@facter/ds-core 1.11.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +119 -35
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +120 -36
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -898,6 +898,14 @@ interface FormSelectProps<T extends FieldValues = FieldValues> extends BaseField
|
|
|
898
898
|
selectSize?: 'sm' | 'default' | 'lg';
|
|
899
899
|
/** Render as dropdown (default) or visual card grid */
|
|
900
900
|
variant?: 'default' | 'card';
|
|
901
|
+
/** Server-side search callback. If not provided, filters locally */
|
|
902
|
+
onSearch?: (query: string) => void;
|
|
903
|
+
/** Infinite scroll: callback to load more items */
|
|
904
|
+
onLoadMore?: () => void;
|
|
905
|
+
/** Infinite scroll: whether there are more items to load */
|
|
906
|
+
hasMore?: boolean;
|
|
907
|
+
/** Placeholder for the search input */
|
|
908
|
+
searchPlaceholder?: string;
|
|
901
909
|
}
|
|
902
910
|
interface FormTextareaProps<T extends FieldValues = FieldValues> extends BaseFieldProps<T>, Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, 'name'> {
|
|
903
911
|
hideError?: boolean;
|
|
@@ -929,7 +937,7 @@ declare namespace FormInput {
|
|
|
929
937
|
var displayName: string;
|
|
930
938
|
}
|
|
931
939
|
|
|
932
|
-
declare function FormSelect<T extends FieldValues = FieldValues>({ name, label, description, required, disabled, className, options, placeholder, icon, hideError, selectSize, emptyText, loading, variant, }: FormSelectProps<T>): react_jsx_runtime.JSX.Element;
|
|
940
|
+
declare function FormSelect<T extends FieldValues = FieldValues>({ name, label, description, required, disabled, className, options, placeholder, icon, hideError, selectSize, emptyText, loading, variant, searchable, onSearch, onLoadMore, hasMore, searchPlaceholder, }: FormSelectProps<T>): react_jsx_runtime.JSX.Element;
|
|
933
941
|
declare namespace FormSelect {
|
|
934
942
|
var displayName: string;
|
|
935
943
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -898,6 +898,14 @@ interface FormSelectProps<T extends FieldValues = FieldValues> extends BaseField
|
|
|
898
898
|
selectSize?: 'sm' | 'default' | 'lg';
|
|
899
899
|
/** Render as dropdown (default) or visual card grid */
|
|
900
900
|
variant?: 'default' | 'card';
|
|
901
|
+
/** Server-side search callback. If not provided, filters locally */
|
|
902
|
+
onSearch?: (query: string) => void;
|
|
903
|
+
/** Infinite scroll: callback to load more items */
|
|
904
|
+
onLoadMore?: () => void;
|
|
905
|
+
/** Infinite scroll: whether there are more items to load */
|
|
906
|
+
hasMore?: boolean;
|
|
907
|
+
/** Placeholder for the search input */
|
|
908
|
+
searchPlaceholder?: string;
|
|
901
909
|
}
|
|
902
910
|
interface FormTextareaProps<T extends FieldValues = FieldValues> extends BaseFieldProps<T>, Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, 'name'> {
|
|
903
911
|
hideError?: boolean;
|
|
@@ -929,7 +937,7 @@ declare namespace FormInput {
|
|
|
929
937
|
var displayName: string;
|
|
930
938
|
}
|
|
931
939
|
|
|
932
|
-
declare function FormSelect<T extends FieldValues = FieldValues>({ name, label, description, required, disabled, className, options, placeholder, icon, hideError, selectSize, emptyText, loading, variant, }: FormSelectProps<T>): react_jsx_runtime.JSX.Element;
|
|
940
|
+
declare function FormSelect<T extends FieldValues = FieldValues>({ name, label, description, required, disabled, className, options, placeholder, icon, hideError, selectSize, emptyText, loading, variant, searchable, onSearch, onLoadMore, hasMore, searchPlaceholder, }: FormSelectProps<T>): react_jsx_runtime.JSX.Element;
|
|
933
941
|
declare namespace FormSelect {
|
|
934
942
|
var displayName: string;
|
|
935
943
|
}
|
package/dist/index.js
CHANGED
|
@@ -3269,7 +3269,12 @@ function FormSelect({
|
|
|
3269
3269
|
selectSize = "default",
|
|
3270
3270
|
emptyText = "Nenhuma op\xE7\xE3o dispon\xEDvel",
|
|
3271
3271
|
loading = false,
|
|
3272
|
-
variant = "default"
|
|
3272
|
+
variant = "default",
|
|
3273
|
+
searchable = false,
|
|
3274
|
+
onSearch,
|
|
3275
|
+
onLoadMore,
|
|
3276
|
+
hasMore,
|
|
3277
|
+
searchPlaceholder = "Buscar..."
|
|
3273
3278
|
}) {
|
|
3274
3279
|
const form = reactHookForm.useFormContext();
|
|
3275
3280
|
const fieldState = form.getFieldState(name, form.formState);
|
|
@@ -3290,7 +3295,14 @@ function FormSelect({
|
|
|
3290
3295
|
label,
|
|
3291
3296
|
required,
|
|
3292
3297
|
error: !!error,
|
|
3293
|
-
placeholder
|
|
3298
|
+
placeholder,
|
|
3299
|
+
searchable,
|
|
3300
|
+
onSearch,
|
|
3301
|
+
onLoadMore,
|
|
3302
|
+
hasMore,
|
|
3303
|
+
loading,
|
|
3304
|
+
emptyText,
|
|
3305
|
+
searchPlaceholder
|
|
3294
3306
|
}
|
|
3295
3307
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
3296
3308
|
Select,
|
|
@@ -3338,11 +3350,55 @@ function CardSelect({
|
|
|
3338
3350
|
label,
|
|
3339
3351
|
required,
|
|
3340
3352
|
error,
|
|
3341
|
-
placeholder = "Selecione..."
|
|
3353
|
+
placeholder = "Selecione...",
|
|
3354
|
+
searchable,
|
|
3355
|
+
onSearch,
|
|
3356
|
+
onLoadMore,
|
|
3357
|
+
hasMore,
|
|
3358
|
+
loading,
|
|
3359
|
+
emptyText = "Nenhuma op\xE7\xE3o dispon\xEDvel",
|
|
3360
|
+
searchPlaceholder = "Buscar..."
|
|
3342
3361
|
}) {
|
|
3343
3362
|
const [open, setOpen] = React10__namespace.useState(false);
|
|
3363
|
+
const [search, setSearch] = React10__namespace.useState("");
|
|
3344
3364
|
const selected = options.find((o) => o.value === value);
|
|
3345
|
-
|
|
3365
|
+
const listRef = React10__namespace.useRef(null);
|
|
3366
|
+
const searchRef = React10__namespace.useRef(null);
|
|
3367
|
+
const filteredOptions = React10__namespace.useMemo(() => {
|
|
3368
|
+
if (!searchable || onSearch || !search) return options;
|
|
3369
|
+
const q = search.toLowerCase();
|
|
3370
|
+
return options.filter(
|
|
3371
|
+
(o) => o.label.toLowerCase().includes(q) || o.description?.toLowerCase().includes(q)
|
|
3372
|
+
);
|
|
3373
|
+
}, [options, search, searchable, onSearch]);
|
|
3374
|
+
const handleSearch = React10__namespace.useCallback(
|
|
3375
|
+
(value2) => {
|
|
3376
|
+
setSearch(value2);
|
|
3377
|
+
if (onSearch) onSearch(value2);
|
|
3378
|
+
},
|
|
3379
|
+
[onSearch]
|
|
3380
|
+
);
|
|
3381
|
+
React10__namespace.useEffect(() => {
|
|
3382
|
+
if (!open) {
|
|
3383
|
+
setSearch("");
|
|
3384
|
+
if (onSearch) onSearch("");
|
|
3385
|
+
}
|
|
3386
|
+
}, [open, onSearch]);
|
|
3387
|
+
React10__namespace.useEffect(() => {
|
|
3388
|
+
if (open && searchable) {
|
|
3389
|
+
setTimeout(() => searchRef.current?.focus(), 0);
|
|
3390
|
+
}
|
|
3391
|
+
}, [open, searchable]);
|
|
3392
|
+
const handleScroll = React10__namespace.useCallback(() => {
|
|
3393
|
+
if (!onLoadMore || !hasMore || loading) return;
|
|
3394
|
+
const el = listRef.current;
|
|
3395
|
+
if (!el) return;
|
|
3396
|
+
const { scrollTop, scrollHeight, clientHeight } = el;
|
|
3397
|
+
if (scrollHeight - scrollTop - clientHeight < 80) {
|
|
3398
|
+
onLoadMore();
|
|
3399
|
+
}
|
|
3400
|
+
}, [onLoadMore, hasMore, loading]);
|
|
3401
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, modal: false, children: [
|
|
3346
3402
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
3347
3403
|
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, disabled, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3348
3404
|
"button",
|
|
@@ -3379,45 +3435,73 @@ function CardSelect({
|
|
|
3379
3435
|
}
|
|
3380
3436
|
)
|
|
3381
3437
|
] }),
|
|
3382
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3438
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3383
3439
|
PopoverContent,
|
|
3384
3440
|
{
|
|
3385
3441
|
align: "start",
|
|
3386
|
-
className: "p-
|
|
3442
|
+
className: "p-0 overflow-hidden",
|
|
3387
3443
|
style: {
|
|
3388
3444
|
width: "var(--radix-popover-trigger-width)",
|
|
3389
3445
|
maxHeight: "var(--radix-popover-content-available-height)"
|
|
3390
3446
|
},
|
|
3391
|
-
children:
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3447
|
+
children: [
|
|
3448
|
+
searchable && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-3 py-2 border-b border-border", children: [
|
|
3449
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
|
|
3450
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3451
|
+
"input",
|
|
3452
|
+
{
|
|
3453
|
+
ref: searchRef,
|
|
3454
|
+
type: "text",
|
|
3455
|
+
value: search,
|
|
3456
|
+
onChange: (e) => handleSearch(e.target.value),
|
|
3457
|
+
placeholder: searchPlaceholder,
|
|
3458
|
+
className: "flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
|
|
3459
|
+
}
|
|
3460
|
+
)
|
|
3461
|
+
] }),
|
|
3462
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3463
|
+
"div",
|
|
3396
3464
|
{
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3465
|
+
ref: listRef,
|
|
3466
|
+
className: "overflow-y-auto overscroll-contain",
|
|
3467
|
+
style: { maxHeight: searchable ? "calc(var(--radix-popover-content-available-height) - 45px)" : "var(--radix-popover-content-available-height)" },
|
|
3468
|
+
onScroll: handleScroll,
|
|
3469
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-border/50 p-2", children: [
|
|
3470
|
+
filteredOptions.length === 0 && !loading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "py-4 text-center text-sm text-muted-foreground", children: emptyText }) : filteredOptions.map((option) => {
|
|
3471
|
+
const isSelected = value === option.value;
|
|
3472
|
+
const isDisabled = option.disabled || disabled;
|
|
3473
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3474
|
+
"button",
|
|
3475
|
+
{
|
|
3476
|
+
type: "button",
|
|
3477
|
+
disabled: isDisabled,
|
|
3478
|
+
onClick: () => {
|
|
3479
|
+
onChange(option.value);
|
|
3480
|
+
setOpen(false);
|
|
3481
|
+
},
|
|
3482
|
+
className: cn(
|
|
3483
|
+
"flex w-full items-center gap-3 p-3 text-left transition-all",
|
|
3484
|
+
"cursor-pointer hover:bg-accent",
|
|
3485
|
+
isSelected && "bg-primary/5",
|
|
3486
|
+
isDisabled && "cursor-not-allowed opacity-50 hover:bg-transparent"
|
|
3487
|
+
),
|
|
3488
|
+
children: [
|
|
3489
|
+
option.icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsxRuntime.jsx(option.icon, { className: "h-5 w-5 text-primary" }) }),
|
|
3490
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
3491
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium leading-tight", children: option.label }),
|
|
3492
|
+
option.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-xs leading-tight text-muted-foreground", children: option.description })
|
|
3493
|
+
] }),
|
|
3494
|
+
isSelected && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3 w-3" }) })
|
|
3495
|
+
]
|
|
3496
|
+
},
|
|
3497
|
+
option.value
|
|
3498
|
+
);
|
|
3499
|
+
}),
|
|
3500
|
+
loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-3", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin text-muted-foreground" }) })
|
|
3501
|
+
] })
|
|
3502
|
+
}
|
|
3503
|
+
)
|
|
3504
|
+
]
|
|
3421
3505
|
}
|
|
3422
3506
|
)
|
|
3423
3507
|
] });
|