Initial commit for new panel

This commit is contained in:
AmirReza Jamali
2025-09-09 11:20:26 +03:30
commit 1d4ccb3575
343 changed files with 20031 additions and 0 deletions
+105
View File
@@ -0,0 +1,105 @@
"use client";
import { ChevronUpIcon } from "@/assets/icons";
import { cn } from "@/lib/utils";
import { useId, useState } from "react";
import {
type FieldErrors,
type FieldValues,
type Path,
type UseFormRegister,
type UseFormRegisterReturn,
} from "react-hook-form";
type PropsType<T extends FieldValues> = {
name: Path<T>;
label: string;
items: { value: string; label: string }[];
prefixIcon?: React.ReactNode;
className?: string;
register?: UseFormRegister<T>;
errors?: FieldErrors<T>;
required?: boolean;
} & (
| { placeholder?: string; defaultValue: string }
| { placeholder: string; defaultValue?: string }
) &
Partial<UseFormRegisterReturn>;
export function Select<T extends FieldValues>({
items,
label,
defaultValue,
placeholder,
prefixIcon,
className,
name,
register,
errors,
required,
onChange,
onBlur,
ref,
...props
}: PropsType<T>) {
const id = useId();
const [isOptionSelected, setIsOptionSelected] = useState(!!defaultValue);
const error = errors && errors[name];
return (
<div className={cn("space-y-3", className)}>
<label
htmlFor={id}
className="block text-body-sm font-medium text-dark dark:text-white"
>
{label}
{required && <span className="text-red ml-1 select-none">*</span>}
</label>
<div className="relative">
{prefixIcon && (
<div className="absolute left-4 top-1/2 -translate-y-1/2">
{prefixIcon}
</div>
)}
<select
id={id}
name={name}
ref={ref}
defaultValue={defaultValue || ""}
onChange={(e) => {
setIsOptionSelected(!!e.target.value);
onChange?.(e);
}}
onBlur={onBlur}
className={cn(
"w-full appearance-none rounded-lg border border-stroke bg-transparent px-5.5 py-3 outline-none transition focus:border-primary active:border-primary dark:border-dark-3 dark:bg-dark-2 dark:focus:border-primary [&>option]:text-dark-5 dark:[&>option]:text-dark-6",
isOptionSelected && "text-dark dark:text-white",
error && "border-red focus:border-red dark:border-red",
prefixIcon && "pl-11.5",
)}
>
{placeholder && (
<option value="" disabled hidden>
{placeholder}
</option>
)}
{items.map((item) => (
<option key={item.value} value={item.value}>
{item.label}
</option>
))}
</select>
<ChevronUpIcon className="pointer-events-none absolute right-4 top-1/2 -translate-y-1/2 rotate-180" />
</div>
{error && (
<p className="text-red mt-1.5 text-sm">{error.message as string}</p>
)}
</div>
);
}