@facter/ds-core 1.13.0 → 1.15.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.js CHANGED
@@ -16,10 +16,10 @@ var DialogPrimitive = require('@radix-ui/react-dialog');
16
16
  var sonner = require('sonner');
17
17
  var SwitchPrimitives = require('@radix-ui/react-switch');
18
18
  var reactHookForm = require('react-hook-form');
19
- var PopoverPrimitive = require('@radix-ui/react-popover');
20
19
  var RadioGroupPrimitive = require('@radix-ui/react-radio-group');
21
20
  var AvatarPrimitive = require('@radix-ui/react-avatar');
22
21
  var DropdownMenuPrimitive = require('@radix-ui/react-dropdown-menu');
22
+ var PopoverPrimitive = require('@radix-ui/react-popover');
23
23
  var TooltipPrimitive = require('@radix-ui/react-tooltip');
24
24
  var ScrollAreaPrimitive = require('@radix-ui/react-scroll-area');
25
25
  var SeparatorPrimitive = require('@radix-ui/react-separator');
@@ -50,10 +50,10 @@ var TabsPrimitive__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitive);
50
50
  var CheckboxPrimitive__namespace = /*#__PURE__*/_interopNamespace(CheckboxPrimitive);
51
51
  var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
52
52
  var SwitchPrimitives__namespace = /*#__PURE__*/_interopNamespace(SwitchPrimitives);
53
- var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitive);
54
53
  var RadioGroupPrimitive__namespace = /*#__PURE__*/_interopNamespace(RadioGroupPrimitive);
55
54
  var AvatarPrimitive__namespace = /*#__PURE__*/_interopNamespace(AvatarPrimitive);
56
55
  var DropdownMenuPrimitive__namespace = /*#__PURE__*/_interopNamespace(DropdownMenuPrimitive);
56
+ var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitive);
57
57
  var TooltipPrimitive__namespace = /*#__PURE__*/_interopNamespace(TooltipPrimitive);
58
58
  var ScrollAreaPrimitive__namespace = /*#__PURE__*/_interopNamespace(ScrollAreaPrimitive);
59
59
  var SeparatorPrimitive__namespace = /*#__PURE__*/_interopNamespace(SeparatorPrimitive);
@@ -3239,22 +3239,6 @@ function FormInput({
3239
3239
  ) });
3240
3240
  }
3241
3241
  FormInput.displayName = "Form.Input";
3242
- var Popover = PopoverPrimitive__namespace.Root;
3243
- var PopoverTrigger = PopoverPrimitive__namespace.Trigger;
3244
- var PopoverContent = React10__namespace.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
3245
- PopoverPrimitive__namespace.Content,
3246
- {
3247
- ref,
3248
- align,
3249
- sideOffset,
3250
- className: cn(
3251
- "z-50 w-auto rounded-md border bg-popover p-4 text-popover-foreground shadow-lg outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
3252
- className
3253
- ),
3254
- ...props
3255
- }
3256
- ) }));
3257
- PopoverContent.displayName = PopoverPrimitive__namespace.Content.displayName;
3258
3242
  function FormSelect({
3259
3243
  name,
3260
3244
  label,
@@ -3362,6 +3346,7 @@ function CardSelect({
3362
3346
  const [open, setOpen] = React10__namespace.useState(false);
3363
3347
  const [search, setSearch] = React10__namespace.useState("");
3364
3348
  const selected = options.find((o) => o.value === value);
3349
+ const containerRef = React10__namespace.useRef(null);
3365
3350
  const listRef = React10__namespace.useRef(null);
3366
3351
  const searchRef = React10__namespace.useRef(null);
3367
3352
  const filteredOptions = React10__namespace.useMemo(() => {
@@ -3378,6 +3363,24 @@ function CardSelect({
3378
3363
  },
3379
3364
  [onSearch]
3380
3365
  );
3366
+ React10__namespace.useEffect(() => {
3367
+ if (!open) return;
3368
+ const handleClickOutside = (e) => {
3369
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
3370
+ setOpen(false);
3371
+ }
3372
+ };
3373
+ document.addEventListener("mousedown", handleClickOutside);
3374
+ return () => document.removeEventListener("mousedown", handleClickOutside);
3375
+ }, [open]);
3376
+ React10__namespace.useEffect(() => {
3377
+ if (!open) return;
3378
+ const handleEscape = (e) => {
3379
+ if (e.key === "Escape") setOpen(false);
3380
+ };
3381
+ document.addEventListener("keydown", handleEscape);
3382
+ return () => document.removeEventListener("keydown", handleEscape);
3383
+ }, [open]);
3381
3384
  React10__namespace.useEffect(() => {
3382
3385
  if (!open) {
3383
3386
  setSearch("");
@@ -3389,12 +3392,23 @@ function CardSelect({
3389
3392
  setTimeout(() => searchRef.current?.focus(), 0);
3390
3393
  }
3391
3394
  }, [open, searchable]);
3392
- const handleWheel = React10__namespace.useCallback((e) => {
3393
- e.stopPropagation();
3395
+ React10__namespace.useEffect(() => {
3394
3396
  const el = listRef.current;
3395
- if (!el) return;
3396
- el.scrollTop += e.deltaY;
3397
- }, []);
3397
+ if (!el || !open) return;
3398
+ const handleWheel = (e) => {
3399
+ const { scrollTop, scrollHeight, clientHeight } = el;
3400
+ const isScrollable = scrollHeight > clientHeight;
3401
+ if (!isScrollable) return;
3402
+ e.preventDefault();
3403
+ e.stopPropagation();
3404
+ el.scrollTop = Math.max(
3405
+ 0,
3406
+ Math.min(scrollTop + e.deltaY, scrollHeight - clientHeight)
3407
+ );
3408
+ };
3409
+ el.addEventListener("wheel", handleWheel, { passive: false, capture: true });
3410
+ return () => el.removeEventListener("wheel", handleWheel, { capture: true });
3411
+ }, [open, filteredOptions]);
3398
3412
  const handleScroll = React10__namespace.useCallback(() => {
3399
3413
  if (!onLoadMore || !hasMore || loading) return;
3400
3414
  const el = listRef.current;
@@ -3404,111 +3418,100 @@ function CardSelect({
3404
3418
  onLoadMore();
3405
3419
  }
3406
3420
  }, [onLoadMore, hasMore, loading]);
3407
- return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, modal: false, children: [
3408
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
3409
- /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, disabled, children: /* @__PURE__ */ jsxRuntime.jsxs(
3410
- "button",
3411
- {
3412
- type: "button",
3413
- className: cn(
3414
- "flex w-full items-center justify-between rounded-md border-2 bg-background px-3 text-sm transition-colors",
3415
- "focus:outline-none focus:border-primary",
3416
- "disabled:cursor-not-allowed disabled:opacity-50",
3417
- label ? "h-12 pt-4 pb-2" : "h-9 py-2",
3418
- error ? "border-red-500" : "border-border",
3419
- open && !error && "border-primary"
3420
- ),
3421
- children: [
3422
- selected ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 truncate", children: [
3423
- selected.icon && /* @__PURE__ */ jsxRuntime.jsx(selected.icon, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
3424
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: selected.label })
3425
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: placeholder }),
3426
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-4 w-4 shrink-0 opacity-50" })
3427
- ]
3428
- }
3429
- ) }),
3430
- label && /* @__PURE__ */ jsxRuntime.jsxs(
3431
- "label",
3432
- {
3433
- className: cn(
3434
- "absolute left-3 top-[-6px] text-xs font-medium bg-background px-1 pointer-events-none",
3435
- error ? "text-red-500" : "text-foreground"
3436
- ),
3437
- children: [
3438
- label,
3439
- required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 ml-0.5", children: "*" })
3440
- ]
3441
- }
3442
- )
3443
- ] }),
3421
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "relative", children: [
3444
3422
  /* @__PURE__ */ jsxRuntime.jsxs(
3445
- PopoverContent,
3423
+ "button",
3446
3424
  {
3447
- align: "start",
3448
- className: "p-0 overflow-hidden",
3449
- style: {
3450
- width: "var(--radix-popover-trigger-width)"
3451
- },
3425
+ type: "button",
3426
+ disabled,
3427
+ onClick: () => setOpen((prev) => !prev),
3428
+ className: cn(
3429
+ "flex w-full items-center justify-between rounded-md border-2 bg-background px-3 text-sm transition-colors",
3430
+ "focus:outline-none focus:border-primary",
3431
+ "disabled:cursor-not-allowed disabled:opacity-50",
3432
+ label ? "h-12 pt-4 pb-2" : "h-9 py-2",
3433
+ error ? "border-red-500" : "border-border",
3434
+ open && !error && "border-primary"
3435
+ ),
3452
3436
  children: [
3453
- searchable && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-3 py-2 border-b border-border", children: [
3454
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
3455
- /* @__PURE__ */ jsxRuntime.jsx(
3456
- "input",
3457
- {
3458
- ref: searchRef,
3459
- type: "text",
3460
- value: search,
3461
- onChange: (e) => handleSearch(e.target.value),
3462
- placeholder: searchPlaceholder,
3463
- className: "flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
3464
- }
3465
- )
3466
- ] }),
3467
- /* @__PURE__ */ jsxRuntime.jsx(
3468
- "div",
3469
- {
3470
- ref: listRef,
3471
- className: "overflow-y-auto overscroll-contain max-h-[300px]",
3472
- onScroll: handleScroll,
3473
- onWheel: handleWheel,
3474
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-border/50 p-2", children: [
3475
- filteredOptions.length === 0 && !loading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "py-4 text-center text-sm text-muted-foreground", children: emptyText }) : filteredOptions.map((option) => {
3476
- const isSelected = value === option.value;
3477
- const isDisabled = option.disabled || disabled;
3478
- return /* @__PURE__ */ jsxRuntime.jsxs(
3479
- "button",
3480
- {
3481
- type: "button",
3482
- disabled: isDisabled,
3483
- onClick: () => {
3484
- onChange(option.value);
3485
- setOpen(false);
3486
- },
3487
- className: cn(
3488
- "flex w-full items-center gap-3 p-3 text-left transition-all",
3489
- "cursor-pointer hover:bg-accent",
3490
- isSelected && "bg-primary/5",
3491
- isDisabled && "cursor-not-allowed opacity-50 hover:bg-transparent"
3492
- ),
3493
- children: [
3494
- 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" }) }),
3495
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
3496
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium leading-tight", children: option.label }),
3497
- option.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-xs leading-tight text-muted-foreground", children: option.description })
3498
- ] }),
3499
- 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" }) })
3500
- ]
3501
- },
3502
- option.value
3503
- );
3504
- }),
3505
- 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" }) })
3506
- ] })
3507
- }
3508
- )
3437
+ selected ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 truncate", children: [
3438
+ selected.icon && /* @__PURE__ */ jsxRuntime.jsx(selected.icon, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
3439
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: selected.label })
3440
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: placeholder }),
3441
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: cn("h-4 w-4 shrink-0 opacity-50 transition-transform", open && "rotate-180") })
3509
3442
  ]
3510
3443
  }
3511
- )
3444
+ ),
3445
+ label && /* @__PURE__ */ jsxRuntime.jsxs(
3446
+ "label",
3447
+ {
3448
+ className: cn(
3449
+ "absolute left-3 top-[-6px] text-xs font-medium bg-background px-1 pointer-events-none",
3450
+ error ? "text-red-500" : "text-foreground"
3451
+ ),
3452
+ children: [
3453
+ label,
3454
+ required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 ml-0.5", children: "*" })
3455
+ ]
3456
+ }
3457
+ ),
3458
+ open && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute left-0 top-full z-50 mt-1 w-full rounded-md border border-border bg-popover shadow-md overflow-hidden animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-150", children: [
3459
+ searchable && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-3 py-2 border-b border-border", children: [
3460
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
3461
+ /* @__PURE__ */ jsxRuntime.jsx(
3462
+ "input",
3463
+ {
3464
+ ref: searchRef,
3465
+ type: "text",
3466
+ value: search,
3467
+ onChange: (e) => handleSearch(e.target.value),
3468
+ placeholder: searchPlaceholder,
3469
+ className: "flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
3470
+ }
3471
+ )
3472
+ ] }),
3473
+ /* @__PURE__ */ jsxRuntime.jsx(
3474
+ "div",
3475
+ {
3476
+ ref: listRef,
3477
+ className: "overflow-y-auto overscroll-contain max-h-[300px]",
3478
+ onScroll: handleScroll,
3479
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-border/50 p-2", children: [
3480
+ filteredOptions.length === 0 && !loading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "py-4 text-center text-sm text-muted-foreground", children: emptyText }) : filteredOptions.map((option) => {
3481
+ const isSelected = value === option.value;
3482
+ const isDisabled = option.disabled || disabled;
3483
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3484
+ "button",
3485
+ {
3486
+ type: "button",
3487
+ disabled: isDisabled,
3488
+ onClick: () => {
3489
+ onChange(option.value);
3490
+ setOpen(false);
3491
+ },
3492
+ className: cn(
3493
+ "flex w-full items-center gap-3 p-3 text-left transition-all",
3494
+ "cursor-pointer hover:bg-accent",
3495
+ isSelected && "bg-primary/5",
3496
+ isDisabled && "cursor-not-allowed opacity-50 hover:bg-transparent"
3497
+ ),
3498
+ children: [
3499
+ 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" }) }),
3500
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
3501
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium leading-tight", children: option.label }),
3502
+ option.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-xs leading-tight text-muted-foreground", children: option.description })
3503
+ ] }),
3504
+ 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" }) })
3505
+ ]
3506
+ },
3507
+ option.value
3508
+ );
3509
+ }),
3510
+ 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" }) })
3511
+ ] })
3512
+ }
3513
+ )
3514
+ ] })
3512
3515
  ] });
3513
3516
  }
3514
3517
  function FormTextarea({
@@ -4072,6 +4075,22 @@ var DropdownMenuShortcut = ({
4072
4075
  );
4073
4076
  };
4074
4077
  DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
4078
+ var Popover = PopoverPrimitive__namespace.Root;
4079
+ var PopoverTrigger = PopoverPrimitive__namespace.Trigger;
4080
+ var PopoverContent = React10__namespace.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
4081
+ PopoverPrimitive__namespace.Content,
4082
+ {
4083
+ ref,
4084
+ align,
4085
+ sideOffset,
4086
+ className: cn(
4087
+ "z-50 w-auto rounded-md border bg-popover p-4 text-popover-foreground shadow-lg outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
4088
+ className
4089
+ ),
4090
+ ...props
4091
+ }
4092
+ ) }));
4093
+ PopoverContent.displayName = PopoverPrimitive__namespace.Content.displayName;
4075
4094
  var TooltipProvider = TooltipPrimitive__namespace.Provider;
4076
4095
  var TooltipRoot = TooltipPrimitive__namespace.Root;
4077
4096
  var TooltipTrigger = TooltipPrimitive__namespace.Trigger;