@facter/ds-core 1.33.9 → 1.33.11

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,11 @@ 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');
19
+ var reactDom = require('react-dom');
20
20
  var RadioGroupPrimitive = require('@radix-ui/react-radio-group');
21
21
  var AvatarPrimitive = require('@radix-ui/react-avatar');
22
22
  var DropdownMenuPrimitive = require('@radix-ui/react-dropdown-menu');
23
+ var PopoverPrimitive = require('@radix-ui/react-popover');
23
24
  var TooltipPrimitive = require('@radix-ui/react-tooltip');
24
25
  var ScrollAreaPrimitive = require('@radix-ui/react-scroll-area');
25
26
  var SeparatorPrimitive = require('@radix-ui/react-separator');
@@ -50,10 +51,10 @@ var TabsPrimitive__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitive);
50
51
  var CheckboxPrimitive__namespace = /*#__PURE__*/_interopNamespace(CheckboxPrimitive);
51
52
  var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
52
53
  var SwitchPrimitives__namespace = /*#__PURE__*/_interopNamespace(SwitchPrimitives);
53
- var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitive);
54
54
  var RadioGroupPrimitive__namespace = /*#__PURE__*/_interopNamespace(RadioGroupPrimitive);
55
55
  var AvatarPrimitive__namespace = /*#__PURE__*/_interopNamespace(AvatarPrimitive);
56
56
  var DropdownMenuPrimitive__namespace = /*#__PURE__*/_interopNamespace(DropdownMenuPrimitive);
57
+ var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitive);
57
58
  var TooltipPrimitive__namespace = /*#__PURE__*/_interopNamespace(TooltipPrimitive);
58
59
  var ScrollAreaPrimitive__namespace = /*#__PURE__*/_interopNamespace(ScrollAreaPrimitive);
59
60
  var SeparatorPrimitive__namespace = /*#__PURE__*/_interopNamespace(SeparatorPrimitive);
@@ -3410,22 +3411,6 @@ function FormInput({
3410
3411
  ) });
3411
3412
  }
3412
3413
  FormInput.displayName = "Form.Input";
3413
- var Popover = PopoverPrimitive__namespace.Root;
3414
- var PopoverTrigger = PopoverPrimitive__namespace.Trigger;
3415
- var PopoverContent = React10__namespace.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
3416
- PopoverPrimitive__namespace.Content,
3417
- {
3418
- ref,
3419
- align,
3420
- sideOffset,
3421
- className: cn(
3422
- "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",
3423
- className
3424
- ),
3425
- ...props
3426
- }
3427
- ) }));
3428
- PopoverContent.displayName = PopoverPrimitive__namespace.Content.displayName;
3429
3414
  function FormSelect({
3430
3415
  name,
3431
3416
  label,
@@ -3494,7 +3479,13 @@ function FormSelect({
3494
3479
  {
3495
3480
  value: option.value,
3496
3481
  disabled: option.disabled,
3497
- children: option.label
3482
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
3483
+ option.icon && /* @__PURE__ */ jsxRuntime.jsx(option.icon, { className: "h-4 w-4 text-muted-foreground" }),
3484
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3485
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: option.label }),
3486
+ option.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground ml-2", children: option.description })
3487
+ ] })
3488
+ ] })
3498
3489
  },
3499
3490
  option.value
3500
3491
  ))
@@ -3527,8 +3518,11 @@ function CardSelect({
3527
3518
  const [open, setOpen] = React10__namespace.useState(false);
3528
3519
  const [search, setSearch] = React10__namespace.useState("");
3529
3520
  const selected = options.find((o) => o.value === value);
3521
+ const containerRef = React10__namespace.useRef(null);
3522
+ const dropdownRef = React10__namespace.useRef(null);
3530
3523
  const listRef = React10__namespace.useRef(null);
3531
3524
  const searchRef = React10__namespace.useRef(null);
3525
+ const [dropdownPos, setDropdownPos] = React10__namespace.useState({});
3532
3526
  const filteredOptions = React10__namespace.useMemo(() => {
3533
3527
  if (!searchable || onSearch || !search) return options;
3534
3528
  const q = search.toLowerCase();
@@ -3543,25 +3537,72 @@ function CardSelect({
3543
3537
  },
3544
3538
  [onSearch]
3545
3539
  );
3546
- const handleOpenChange = React10__namespace.useCallback(
3547
- (nextOpen) => {
3548
- setOpen(nextOpen);
3549
- if (!nextOpen) {
3550
- setSearch("");
3551
- if (onSearch) onSearch("");
3540
+ React10__namespace.useEffect(() => {
3541
+ if (!open || !containerRef.current) return;
3542
+ const updatePosition = () => {
3543
+ const rect = containerRef.current.getBoundingClientRect();
3544
+ const spaceBelow = window.innerHeight - rect.bottom;
3545
+ const estimatedHeight = 340;
3546
+ const showAbove = spaceBelow < estimatedHeight && rect.top > spaceBelow;
3547
+ setDropdownPos({
3548
+ position: "fixed",
3549
+ left: rect.left,
3550
+ width: rect.width,
3551
+ zIndex: 9999,
3552
+ ...showAbove ? { bottom: window.innerHeight - rect.top + 4 } : { top: rect.bottom + 4 }
3553
+ });
3554
+ };
3555
+ updatePosition();
3556
+ window.addEventListener("scroll", updatePosition, true);
3557
+ window.addEventListener("resize", updatePosition);
3558
+ return () => {
3559
+ window.removeEventListener("scroll", updatePosition, true);
3560
+ window.removeEventListener("resize", updatePosition);
3561
+ };
3562
+ }, [open]);
3563
+ React10__namespace.useEffect(() => {
3564
+ if (!open) return;
3565
+ const handleClickOutside = (e) => {
3566
+ const target = e.target;
3567
+ if (containerRef.current && !containerRef.current.contains(target) && (!dropdownRef.current || !dropdownRef.current.contains(target))) {
3568
+ setOpen(false);
3552
3569
  }
3553
- },
3554
- [onSearch]
3555
- );
3570
+ };
3571
+ document.addEventListener("mousedown", handleClickOutside);
3572
+ return () => document.removeEventListener("mousedown", handleClickOutside);
3573
+ }, [open]);
3574
+ React10__namespace.useEffect(() => {
3575
+ if (!open) return;
3576
+ const handleEscape = (e) => {
3577
+ if (e.key === "Escape") setOpen(false);
3578
+ };
3579
+ document.addEventListener("keydown", handleEscape);
3580
+ return () => document.removeEventListener("keydown", handleEscape);
3581
+ }, [open]);
3582
+ React10__namespace.useEffect(() => {
3583
+ if (!open) {
3584
+ setSearch("");
3585
+ if (onSearch) onSearch("");
3586
+ }
3587
+ }, [open, onSearch]);
3588
+ React10__namespace.useEffect(() => {
3589
+ if (open && searchable) {
3590
+ setTimeout(() => searchRef.current?.focus(), 0);
3591
+ }
3592
+ }, [open, searchable]);
3556
3593
  React10__namespace.useEffect(() => {
3557
3594
  const el = listRef.current;
3558
3595
  if (!el || !open) return;
3559
3596
  const handleWheel = (e) => {
3560
3597
  const { scrollTop, scrollHeight, clientHeight } = el;
3561
- if (scrollHeight <= clientHeight) return;
3598
+ const isScrollable = scrollHeight > clientHeight;
3599
+ if (!isScrollable) return;
3562
3600
  e.preventDefault();
3563
3601
  e.stopPropagation();
3564
- el.scrollTop = Math.max(0, Math.min(scrollTop + e.deltaY, scrollHeight - clientHeight));
3602
+ el.scrollTop = Math.max(
3603
+ 0,
3604
+ Math.min(scrollTop + e.deltaY, scrollHeight - clientHeight)
3605
+ );
3565
3606
  };
3566
3607
  el.addEventListener("wheel", handleWheel, { passive: false, capture: true });
3567
3608
  return () => el.removeEventListener("wheel", handleWheel, { capture: true });
@@ -3575,116 +3616,110 @@ function CardSelect({
3575
3616
  onLoadMore();
3576
3617
  }
3577
3618
  }, [onLoadMore, hasMore, loading]);
3578
- return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: handleOpenChange, children: [
3579
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
3580
- /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
3581
- "button",
3582
- {
3583
- type: "button",
3584
- disabled,
3585
- className: cn(
3586
- "flex w-full items-center justify-between rounded-md border-2 bg-background px-3 text-sm transition-colors",
3587
- "focus:outline-none focus:border-primary",
3588
- "disabled:cursor-not-allowed disabled:opacity-50",
3589
- label ? "h-12 pt-4 pb-2" : "h-9 py-2",
3590
- error ? "border-red-500" : "border-border",
3591
- open && !error && "border-primary"
3592
- ),
3593
- children: [
3594
- selected ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 truncate", children: [
3595
- selected.icon && /* @__PURE__ */ jsxRuntime.jsx(selected.icon, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
3596
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: selected.label })
3597
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: placeholder }),
3598
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: cn("h-4 w-4 shrink-0 opacity-50 transition-transform", open && "rotate-180") })
3599
- ]
3600
- }
3601
- ) }),
3602
- label && /* @__PURE__ */ jsxRuntime.jsxs(
3603
- "label",
3604
- {
3605
- className: cn(
3606
- "absolute left-3 top-[-6px] text-xs font-medium bg-background px-1 pointer-events-none",
3607
- error ? "text-red-500" : "text-foreground"
3608
- ),
3609
- children: [
3610
- label,
3611
- required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 ml-0.5", children: "*" })
3612
- ]
3613
- }
3614
- )
3615
- ] }),
3619
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "relative", children: [
3616
3620
  /* @__PURE__ */ jsxRuntime.jsxs(
3617
- PopoverContent,
3621
+ "button",
3618
3622
  {
3619
- align: "start",
3620
- sideOffset: 4,
3621
- className: "p-0 overflow-hidden",
3622
- style: { width: "var(--radix-popover-trigger-width)" },
3623
- onOpenAutoFocus: (e) => {
3624
- e.preventDefault();
3625
- if (searchable) {
3626
- searchRef.current?.focus();
3627
- }
3628
- },
3623
+ type: "button",
3624
+ disabled,
3625
+ onClick: () => setOpen((prev) => !prev),
3626
+ className: cn(
3627
+ "flex w-full items-center justify-between rounded-md border-2 bg-background px-3 text-sm transition-colors",
3628
+ "focus:outline-none focus:border-primary",
3629
+ "disabled:cursor-not-allowed disabled:opacity-50",
3630
+ label ? "h-12 pt-4 pb-2" : "h-9 py-2",
3631
+ error ? "border-red-500" : "border-border",
3632
+ open && !error && "border-primary"
3633
+ ),
3629
3634
  children: [
3630
- searchable && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-3 py-2 border-b border-border", children: [
3631
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
3635
+ selected ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 truncate", children: [
3636
+ selected.icon && /* @__PURE__ */ jsxRuntime.jsx(selected.icon, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
3637
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: selected.label })
3638
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: placeholder }),
3639
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: cn("h-4 w-4 shrink-0 opacity-50 transition-transform", open && "rotate-180") })
3640
+ ]
3641
+ }
3642
+ ),
3643
+ label && /* @__PURE__ */ jsxRuntime.jsxs(
3644
+ "label",
3645
+ {
3646
+ className: cn(
3647
+ "absolute left-3 top-[-6px] text-xs font-medium bg-background px-1 pointer-events-none",
3648
+ error ? "text-red-500" : "text-foreground"
3649
+ ),
3650
+ children: [
3651
+ label,
3652
+ required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 ml-0.5", children: "*" })
3653
+ ]
3654
+ }
3655
+ ),
3656
+ open && reactDom.createPortal(
3657
+ /* @__PURE__ */ jsxRuntime.jsxs(
3658
+ "div",
3659
+ {
3660
+ ref: dropdownRef,
3661
+ style: dropdownPos,
3662
+ className: "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",
3663
+ children: [
3664
+ searchable && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-3 py-2 border-b border-border", children: [
3665
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
3666
+ /* @__PURE__ */ jsxRuntime.jsx(
3667
+ "input",
3668
+ {
3669
+ ref: searchRef,
3670
+ type: "text",
3671
+ value: search,
3672
+ onChange: (e) => handleSearch(e.target.value),
3673
+ placeholder: searchPlaceholder,
3674
+ className: "flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
3675
+ }
3676
+ )
3677
+ ] }),
3632
3678
  /* @__PURE__ */ jsxRuntime.jsx(
3633
- "input",
3679
+ "div",
3634
3680
  {
3635
- ref: searchRef,
3636
- type: "text",
3637
- value: search,
3638
- onChange: (e) => handleSearch(e.target.value),
3639
- placeholder: searchPlaceholder,
3640
- className: "flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
3681
+ ref: listRef,
3682
+ className: "overflow-y-auto overscroll-contain max-h-[300px]",
3683
+ onScroll: handleScroll,
3684
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-border/50 p-2", children: [
3685
+ filteredOptions.length === 0 && !loading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "py-4 text-center text-sm text-muted-foreground", children: emptyText }) : filteredOptions.map((option) => {
3686
+ const isSelected = value === option.value;
3687
+ const isDisabled = option.disabled || disabled;
3688
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3689
+ "button",
3690
+ {
3691
+ type: "button",
3692
+ disabled: isDisabled,
3693
+ onClick: () => {
3694
+ onChange(option.value);
3695
+ setOpen(false);
3696
+ },
3697
+ className: cn(
3698
+ "flex w-full items-center gap-3 p-3 text-left transition-all",
3699
+ "cursor-pointer hover:bg-accent",
3700
+ isSelected && "bg-primary/5",
3701
+ isDisabled && "cursor-not-allowed opacity-50 hover:bg-transparent"
3702
+ ),
3703
+ children: [
3704
+ option.icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsxRuntime.jsx(option.icon, { className: "h-3.5 w-3.5 text-primary" }) }),
3705
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
3706
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium leading-tight", children: option.label }),
3707
+ option.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-xs leading-tight text-muted-foreground", children: option.description })
3708
+ ] }),
3709
+ 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" }) })
3710
+ ]
3711
+ },
3712
+ option.value
3713
+ );
3714
+ }),
3715
+ 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" }) })
3716
+ ] })
3641
3717
  }
3642
3718
  )
3643
- ] }),
3644
- /* @__PURE__ */ jsxRuntime.jsx(
3645
- "div",
3646
- {
3647
- ref: listRef,
3648
- className: "overflow-y-auto overscroll-contain",
3649
- style: { maxHeight: "min(300px, var(--radix-popover-content-available-height, 300px))" },
3650
- onScroll: handleScroll,
3651
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-border/50 p-2", children: [
3652
- filteredOptions.length === 0 && !loading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "py-4 text-center text-sm text-muted-foreground", children: emptyText }) : filteredOptions.map((option) => {
3653
- const isSelected = value === option.value;
3654
- const isDisabled = option.disabled || disabled;
3655
- return /* @__PURE__ */ jsxRuntime.jsxs(
3656
- "button",
3657
- {
3658
- type: "button",
3659
- disabled: isDisabled,
3660
- onClick: () => {
3661
- onChange(option.value);
3662
- handleOpenChange(false);
3663
- },
3664
- className: cn(
3665
- "flex w-full items-center gap-3 p-3 text-left transition-all",
3666
- "cursor-pointer hover:bg-accent",
3667
- isSelected && "bg-primary/5",
3668
- isDisabled && "cursor-not-allowed opacity-50 hover:bg-transparent"
3669
- ),
3670
- children: [
3671
- option.icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsxRuntime.jsx(option.icon, { className: "h-3.5 w-3.5 text-primary" }) }),
3672
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
3673
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium leading-tight", children: option.label }),
3674
- option.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-xs leading-tight text-muted-foreground", children: option.description })
3675
- ] }),
3676
- 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" }) })
3677
- ]
3678
- },
3679
- option.value
3680
- );
3681
- }),
3682
- 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" }) })
3683
- ] })
3684
- }
3685
- )
3686
- ]
3687
- }
3719
+ ]
3720
+ }
3721
+ ),
3722
+ document.body
3688
3723
  )
3689
3724
  ] });
3690
3725
  }
@@ -4249,6 +4284,22 @@ var DropdownMenuShortcut = ({
4249
4284
  );
4250
4285
  };
4251
4286
  DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
4287
+ var Popover = PopoverPrimitive__namespace.Root;
4288
+ var PopoverTrigger = PopoverPrimitive__namespace.Trigger;
4289
+ var PopoverContent = React10__namespace.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
4290
+ PopoverPrimitive__namespace.Content,
4291
+ {
4292
+ ref,
4293
+ align,
4294
+ sideOffset,
4295
+ className: cn(
4296
+ "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",
4297
+ className
4298
+ ),
4299
+ ...props
4300
+ }
4301
+ ) }));
4302
+ PopoverContent.displayName = PopoverPrimitive__namespace.Content.displayName;
4252
4303
  var TooltipProvider = TooltipPrimitive__namespace.Provider;
4253
4304
  var TooltipRoot = TooltipPrimitive__namespace.Root;
4254
4305
  var TooltipTrigger = TooltipPrimitive__namespace.Trigger;