From 1dc4da9a68a82452693c31ed1f7728847e8aaecb Mon Sep 17 00:00:00 2001 From: rizrmd Date: Sat, 23 Mar 2024 06:48:08 -0700 Subject: [PATCH] fix label --- comps/form/Dropdown/index.tsx | 131 +++++++++++++++++++++++++++++++--- comps/form/Field.tsx | 12 +++- comps/form/Radio/index.tsx | 45 ++++++------ comps/form/type.ts | 7 ++ 4 files changed, 163 insertions(+), 32 deletions(-) create mode 100755 comps/form/type.ts diff --git a/comps/form/Dropdown/index.tsx b/comps/form/Dropdown/index.tsx index b36f2cc..84f093b 100755 --- a/comps/form/Dropdown/index.tsx +++ b/comps/form/Dropdown/index.tsx @@ -2,16 +2,71 @@ import { Popover } from "@/comps/custom/Popover"; import { Input } from "@/comps/ui/input"; import { useLocal } from "@/utils/use-local"; import { ChevronDown } from "lucide-react"; -import { FC } from "react"; +import { FC, useEffect } from "react"; import type { ControllerRenderProps, FieldValues } from "react-hook-form"; +import { FieldListItem, FieldOptions } from "../type"; +import { FormHook } from "../utils/utils"; +import { Skeleton } from "@/comps/ui/skeleton"; -export const Dropdown: FC> = ({ - value, -}) => { +export const Dropdown: FC< + ControllerRenderProps & { + options: FieldOptions; + form?: FormHook; + name: string; + } +> = ({ value, options, form, name }) => { const local = useLocal({ + status: "loading" as "loading" | "ready", open: false, ref: { input: null as null | HTMLInputElement }, + list: [] as FieldListItem[], + input: "", + label: "", + filter: "", }); + + useEffect(() => { + if (form) { + local.status = "loading"; + local.render(); + const callback = (result: any[]) => { + local.list = result.map((e) => { + if (typeof e === "string") { + return { + value: e, + label: e, + }; + } + return e; + }); + + const found = local.list.find((e) => e.value === value); + if (found) { + local.label = found.label; + } + + local.status = "ready"; + local.render(); + }; + + const res = options({ data: form.hook.getValues(), current_name: name }); + if (res instanceof Promise) { + res.then(callback); + } else { + callback(res); + } + } + }, [options]); + + let filtered = local.list; + + if (local.filter) { + filtered = local.list.filter((e) => { + if (e.value.toLowerCase().includes(local.filter)) return true; + return false; + }); + } + return ( > = ({ content={
+ > + {local.status === "loading" && ( + <> +
+ + +
+ + )} + {local.status === "ready" && ( + <> + {filtered.map((item, idx) => { + return ( +
0 && "c-border-t", + idx === 0 && "c-rounded-t-sm", + idx === local.list.length - 1 && "c-rounded-b-sm" + )} + onClick={() => { + if (form) { + local.open = false; + form.hook.setValue(name, item.value); + form.render(); + } + }} + > + {item.label} +
+ ); + })} + + )} + } >
> = ({ cursor: pointer !important; ` )} + tabIndex={0} + onFocus={() => { + local.open = true; + local.input = local.label; + local.filter = ""; + local.render(); + setTimeout(() => { + local.ref.input?.focus(); + }); + }} >
{ - local.open = true; + value={local.open ? local.input : ""} + className={cx( + local.open ? "c-cursor-pointer" : "c-pointer-events-none" + )} + onChange={(e) => { + local.input = e.currentTarget.value; + local.filter = local.input.toLowerCase(); local.render(); }} - className="cursor-pointer" ref={(el) => { local.ref.input = el; }} type="text" /> + {!local.open && ( +
+ {local.label} +
+ )}
); diff --git a/comps/form/Field.tsx b/comps/form/Field.tsx index c9c197d..677230a 100755 --- a/comps/form/Field.tsx +++ b/comps/form/Field.tsx @@ -18,6 +18,7 @@ import { Radio } from "./Radio"; import { SliderOptions } from "./Slider/types"; import { FormHook, modify } from "./utils/utils"; import { Dropdown } from "./Dropdown"; +import { FieldOptions } from "./type"; export const Field: FC<{ name: string; @@ -37,7 +38,7 @@ export const Field: FC<{ | "slider" | "master-link"; required: "y" | "n"; - options: () => Promise<{ value: string; label: string }[]>; + options: FieldOptions; slider: () => Promise; on_change: (arg: { value: any }) => void | Promise; PassProp: any; @@ -218,7 +219,14 @@ export const Field: FC<{