fix label
This commit is contained in:
parent
cdf8c5c837
commit
1dc4da9a68
|
|
@ -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<ControllerRenderProps<FieldValues, string>> = ({
|
||||
value,
|
||||
}) => {
|
||||
export const Dropdown: FC<
|
||||
ControllerRenderProps<FieldValues, string> & {
|
||||
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 (
|
||||
<Popover
|
||||
open={local.open}
|
||||
|
|
@ -24,12 +79,51 @@ export const Dropdown: FC<ControllerRenderProps<FieldValues, string>> = ({
|
|||
content={
|
||||
<div
|
||||
className={cx(
|
||||
"c-px-3 c-py-2",
|
||||
"c-text-sm",
|
||||
css`
|
||||
width: ${local.ref.input?.clientWidth || 100}px;
|
||||
`
|
||||
)}
|
||||
></div>
|
||||
>
|
||||
{local.status === "loading" && (
|
||||
<>
|
||||
<div className="c-flex c-flex-col c-space-y-1 c-px-3 c-py-2">
|
||||
<Skeleton className="c-h-[10px] c-w-[90px]" />
|
||||
<Skeleton className="c-h-[10px] c-w-[60px]" />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{local.status === "ready" && (
|
||||
<>
|
||||
{filtered.map((item, idx) => {
|
||||
return (
|
||||
<div
|
||||
tabIndex={0}
|
||||
key={item.value + "_" + idx}
|
||||
className={cx(
|
||||
"c-px-3 c-py-1 cursor-pointer option-item",
|
||||
item.value === value
|
||||
? "c-bg-blue-600 c-text-white"
|
||||
: "hover:c-bg-blue-50",
|
||||
idx > 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}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div
|
||||
|
|
@ -39,22 +133,41 @@ export const Dropdown: FC<ControllerRenderProps<FieldValues, string>> = ({
|
|||
cursor: pointer !important;
|
||||
`
|
||||
)}
|
||||
tabIndex={0}
|
||||
onFocus={() => {
|
||||
local.open = true;
|
||||
local.input = local.label;
|
||||
local.filter = "";
|
||||
local.render();
|
||||
setTimeout(() => {
|
||||
local.ref.input?.focus();
|
||||
});
|
||||
}}
|
||||
>
|
||||
<div className="c-absolute c-pointer-events-none c-inset-0 c-left-auto c-flex c-items-center c-pr-4">
|
||||
<ChevronDown size={14} />
|
||||
</div>
|
||||
<Input
|
||||
spellCheck={false}
|
||||
onFocus={() => {
|
||||
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 && (
|
||||
<div className="c-absolute c-text-sm c-inset-0 c-px-3 c-flex c-items-center">
|
||||
{local.label}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Popover>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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<SliderOptions>;
|
||||
on_change: (arg: { value: any }) => void | Promise<void>;
|
||||
PassProp: any;
|
||||
|
|
@ -218,7 +219,14 @@ export const Field: FC<{
|
|||
<Textarea {...field} ref={textAreaRef} />
|
||||
)}
|
||||
|
||||
{type === "dropdown" && <Dropdown {...field} />}
|
||||
{type === "dropdown" && (
|
||||
<Dropdown
|
||||
{...field}
|
||||
options={options}
|
||||
form={form}
|
||||
name={name}
|
||||
/>
|
||||
)}
|
||||
|
||||
{type === "date" && (
|
||||
<Date
|
||||
|
|
|
|||
|
|
@ -2,14 +2,12 @@ import { useLocal } from "@/utils/use-local";
|
|||
import { FC, useEffect } from "react";
|
||||
import { Button } from "../../ui/button";
|
||||
import { FormHook, modify } from "../utils/utils";
|
||||
import { FieldOptions } from "../type";
|
||||
|
||||
export const Radio: FC<{
|
||||
name: string;
|
||||
on_select: (val: any) => void;
|
||||
options: (opt: {
|
||||
data: any;
|
||||
current_name: string;
|
||||
}) => Promise<(string | { value: string; label: string })[]>;
|
||||
options: FieldOptions;
|
||||
value: string | string[];
|
||||
PassProp: any;
|
||||
custom: "y" | "n";
|
||||
|
|
@ -40,8 +38,7 @@ export const Radio: FC<{
|
|||
if (!local.option_modified && form) {
|
||||
local.status = "loading";
|
||||
local.render();
|
||||
options({ data: form.hook.getValues(), current_name: name }).then(
|
||||
(result) => {
|
||||
const callback = (result: any[]) => {
|
||||
local.list = result.map((e) => {
|
||||
if (typeof e === "string") {
|
||||
return {
|
||||
|
|
@ -54,8 +51,14 @@ export const Radio: FC<{
|
|||
|
||||
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]);
|
||||
|
||||
|
|
@ -104,8 +107,8 @@ export const Radio: FC<{
|
|||
local.mod(name, { value: item.value });
|
||||
local.render();
|
||||
} else if (selection === "multi") {
|
||||
const val = []
|
||||
val.push()
|
||||
const val = [];
|
||||
val.push();
|
||||
local.mod(name, { value: item.value });
|
||||
local.render();
|
||||
console.log(value, "====multi", name);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
export type FieldOptions = (opt: {
|
||||
data: any;
|
||||
current_name: string;
|
||||
where?: { values: string[] }
|
||||
}) => Promise<(string | FieldListItem)[]>
|
||||
|
||||
export type FieldListItem = { value: string; label: string }
|
||||
Loading…
Reference in New Issue