mirror of
https://github.com/khairul169/code-share.git
synced 2025-04-29 00:59:37 +07:00
89 lines
2.3 KiB
TypeScript
89 lines
2.3 KiB
TypeScript
import React, { forwardRef, useId } from "react";
|
|
import FormField, { FormFieldProps } from "./form-field";
|
|
import { cn } from "~/lib/utils";
|
|
import { Controller, FieldValues, Path } from "react-hook-form";
|
|
import { useFormReturn } from "~/hooks/useForm";
|
|
|
|
export type SelectItem = {
|
|
label: string;
|
|
value: string;
|
|
};
|
|
|
|
type BaseSelectProps = React.ComponentPropsWithoutRef<"select"> &
|
|
FormFieldProps & {
|
|
inputClassName?: string;
|
|
items?: SelectItem[] | null;
|
|
};
|
|
|
|
const BaseSelect = forwardRef<HTMLSelectElement, BaseSelectProps>(
|
|
(props, ref) => {
|
|
const { className, label, error, inputClassName, items, ...restProps } =
|
|
props;
|
|
const id = useId();
|
|
|
|
const input = (
|
|
<select
|
|
ref={ref}
|
|
className={cn(
|
|
"h-10 w-full rounded-md border border-slate-200 px-3 py-2 text-sm ring-offset-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-950 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-white/40 bg-transparent dark:ring-offset-slate-950 dark:placeholder:text-slate-400 dark:focus-visible:ring-slate-300",
|
|
inputClassName
|
|
)}
|
|
{...restProps}
|
|
>
|
|
{items?.map((item) => (
|
|
<option key={item.value} value={item.value} className="text-gray-900">
|
|
{item.label}
|
|
</option>
|
|
))}
|
|
</select>
|
|
);
|
|
|
|
if (label || error) {
|
|
return (
|
|
<FormField
|
|
id={id}
|
|
label={label}
|
|
error={error}
|
|
className={className}
|
|
children={input}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return input;
|
|
}
|
|
);
|
|
|
|
type SelectProps<T extends FieldValues> = Omit<
|
|
BaseSelectProps,
|
|
"form" | "name"
|
|
> & {
|
|
form?: useFormReturn<T>;
|
|
name?: Path<T>;
|
|
};
|
|
|
|
const Select = <T extends FieldValues>(props: SelectProps<T>) => {
|
|
const { form, ...restProps } = props;
|
|
|
|
if (form && props.name) {
|
|
return (
|
|
<Controller
|
|
control={form.control}
|
|
name={props.name}
|
|
render={({ field, fieldState }) => (
|
|
<BaseSelect
|
|
{...restProps}
|
|
{...field}
|
|
value={field.value || ""}
|
|
error={fieldState.error?.message}
|
|
/>
|
|
)}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return <BaseSelect {...restProps} />;
|
|
};
|
|
|
|
export default Select;
|