Skip to content

Instantly share code, notes, and snippets.

@stephyswe
Created July 2, 2023 13:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stephyswe/2bcf82033d81d671abfdac6de820b1d9 to your computer and use it in GitHub Desktop.
Save stephyswe/2bcf82033d81d671abfdac6de820b1d9 to your computer and use it in GitHub Desktop.
form n wrapper
/* import * as LabelPrimitive from "@radix-ui/react-label";
import { Slot } from "@radix-ui/react-slot";
import * as React from "react";
import {
Controller,
ControllerProps,
FieldPath,
FieldValues,
FormProvider,
} from "react-hook-form";
import { withFormField, withFormField2 } from "./component-wrapper-copy";
const Form = FormProvider;
const FormFieldContext = React.createContext<{
name: string;
id: string;
}>({
name: "",
id: "",
});
const useFormField = () => {
const context = React.useContext(FormFieldContext);
if (!context) {
throw new Error("useFormField must be used within <FormField>");
}
const { id, name } = context;
return {
id,
name,
};
};
const FormField = <
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
>({
render,
...props
}: ControllerProps<TFieldValues, TName>) => {
if (!props.name) {
throw new Error("Prop 'name' must be provided to 'FormField'");
}
const id = React.useId();
return (
<FormFieldContext.Provider value={{ name: props.name, id }}>
<Controller
{...props}
render={({ field, fieldState, formState }) =>
render({ field, fieldState, formState })
}
/>
</FormFieldContext.Provider>
);
};
const FormItem = withFormField2<"div", React.HTMLAttributes<HTMLDivElement>>(
"div",
"FormItem"
);
const FormLabel = withFormField(LabelPrimitive.Root, "FormLabel");
const FormControl = withFormField(Slot, "FormControl");
const FormDescription = withFormField("p", "FormDescription");
const FormMessage = withFormField("p", "FormMessage");
export {
useFormField,
Form,
FormItem,
FormLabel,
FormControl,
FormDescription,
FormMessage,
FormField,
};
*/
/* import * as React from "react";
import { cn } from "@/lib/utils";
import { useFormField } from "./form";
type ComponentOrElement =
| keyof JSX.IntrinsicElements
| React.JSXElementConstructor<any>;
interface ComponentProps extends React.ComponentProps<any> {
className?: string;
}
type ComponentOrElement2<P> =
| React.JSXElementConstructor<P>
| keyof JSX.IntrinsicElements;
function onComponent<P extends ComponentProps>(
component: ComponentOrElement,
defaultClassName: string,
displayName?: string
) {
const ForwardedComponent = React.forwardRef<unknown, P>(
({ className, ...props }, ref) =>
React.createElement(component as string | React.ComponentType<any>, {
ref,
className: cn(defaultClassName, className),
...props,
})
);
ForwardedComponent.displayName = displayName;
return ForwardedComponent;
}
function withFormField<P>(
Component: ComponentOrElement2<P>,
displayName?: string
) {
const ForwardedComponent = React.forwardRef<any, P>((props, ref) => {
const formFieldProps = useFormField();
return React.createElement(Component, {
ref,
...props,
...formFieldProps,
});
});
if (displayName) {
ForwardedComponent.displayName = displayName;
}
return ForwardedComponent;
}
function withFormField2<
T extends keyof JSX.IntrinsicElements,
P extends JSX.IntrinsicElements[T]
>(Component: T, displayName?: string) {
const ForwardedComponent = React.forwardRef<any, P>((props, ref) => {
const formFieldProps = useFormField();
return React.createElement(Component, {
ref,
...props,
...formFieldProps,
});
});
if (displayName) {
ForwardedComponent.displayName = displayName;
}
return ForwardedComponent;
}
export { onComponent, withFormField, withFormField2 };
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment