@olundot/ui 0.20.0-next.7 → 0.20.0-next.8

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
@@ -1525,13 +1525,14 @@ var Select = React7.forwardRef(
1525
1525
  surface = "surface",
1526
1526
  id,
1527
1527
  label,
1528
+ labelPlacement = "top",
1528
1529
  description,
1529
1530
  message,
1530
1531
  invalid,
1531
1532
  state = "default",
1532
1533
  options,
1533
1534
  placeholder = "\uC120\uD0DD\uD558\uC138\uC694",
1534
- clearable = true,
1535
+ clearable = labelPlacement !== "inline",
1535
1536
  clearLabel,
1536
1537
  disabled,
1537
1538
  required,
@@ -1548,6 +1549,9 @@ var Select = React7.forwardRef(
1548
1549
  const resolvedAppearance = appearance ?? (selectVariant === "inline" ? "inline" : "field");
1549
1550
  const generatedId = React7.useId();
1550
1551
  const selectId = id ?? generatedId;
1552
+ const inlineLabel = labelPlacement === "inline" && Boolean(label);
1553
+ const inlineLabelId = inlineLabel ? `${selectId}-label` : void 0;
1554
+ const inlineValueId = inlineLabel ? `${selectId}-value` : void 0;
1551
1555
  const triggerId = label || message || description ? selectId : id;
1552
1556
  const resolvedState = invalid || state === "error" ? "error" : state;
1553
1557
  const showDescription = resolvedState === "default" && Boolean(description);
@@ -1644,13 +1648,26 @@ var Select = React7.forwardRef(
1644
1648
  id: triggerId,
1645
1649
  "data-slot": "select-trigger",
1646
1650
  "aria-label": ariaLabel,
1651
+ "aria-labelledby": inlineLabel ? `${inlineLabelId} ${inlineValueId}` : void 0,
1647
1652
  "aria-describedby": describedBy,
1648
1653
  "aria-invalid": resolvedInvalid,
1649
- className: cn(selectVariants({ size: resolvedSize, fullWidth: resolvedFullWidth, appearance: resolvedAppearance, surface, className })),
1654
+ className: cn(selectVariants({ size: resolvedSize, fullWidth: resolvedFullWidth, appearance: resolvedAppearance, surface }), inlineLabel && "max-w-full", className),
1650
1655
  children: [
1656
+ inlineLabel ? /* @__PURE__ */ jsxs7(
1657
+ "span",
1658
+ {
1659
+ "data-slot": "select-inline-label",
1660
+ className: "mr-[var(--space-1)] shrink-0 whitespace-nowrap text-text-tertiary group-disabled:text-text-disabled",
1661
+ children: [
1662
+ /* @__PURE__ */ jsx7("span", { id: inlineLabelId, children: label }),
1663
+ /* @__PURE__ */ jsx7("span", { "aria-hidden": "true", children: ": " })
1664
+ ]
1665
+ }
1666
+ ) : null,
1651
1667
  /* @__PURE__ */ jsx7(
1652
1668
  "span",
1653
1669
  {
1670
+ id: inlineValueId,
1654
1671
  "data-slot": "select-value",
1655
1672
  "data-placeholder": hasSelection ? void 0 : "",
1656
1673
  className: "flex-1 min-w-0 truncate text-left text-foreground data-[placeholder]:text-text-tertiary group-disabled:text-text-disabled group-disabled:data-[placeholder]:text-text-disabled",
@@ -1680,7 +1697,7 @@ var Select = React7.forwardRef(
1680
1697
  ]
1681
1698
  }
1682
1699
  );
1683
- if (!label && !message && !description) {
1700
+ if ((!label || inlineLabel) && !message && !description) {
1684
1701
  return select;
1685
1702
  }
1686
1703
  const MessageIcon = resolvedState === "success" ? CheckCircle23 : AlertCircle3;
@@ -1689,9 +1706,9 @@ var Select = React7.forwardRef(
1689
1706
  {
1690
1707
  "data-slot": "select-field",
1691
1708
  "data-state": resolvedState,
1692
- className: cn("flex flex-col gap-[var(--space-1)]", resolvedFullWidth ? "w-full" : "w-fit"),
1709
+ className: cn("flex flex-col gap-[var(--space-1)]", resolvedFullWidth ? "w-full" : "w-fit", inlineLabel && "min-w-0 max-w-full"),
1693
1710
  children: [
1694
- label ? /* @__PURE__ */ jsxs7(
1711
+ label && !inlineLabel ? /* @__PURE__ */ jsxs7(
1695
1712
  "label",
1696
1713
  {
1697
1714
  "data-slot": "select-label",
@@ -2622,7 +2639,11 @@ var DataLayout = React15.forwardRef(
2622
2639
  className: cn("flex min-w-0 flex-col gap-[var(--space-8)]", className),
2623
2640
  ...props,
2624
2641
  children: [
2625
- /* @__PURE__ */ jsx16("div", { "data-slot": "data-layout-header", className: "min-w-0", children: header }),
2642
+ header ? (
2643
+ // A header that renders nothing (an empty fragment, a shell header that
2644
+ // returns null) leaves the slot empty; hide it so no gap is left above.
2645
+ /* @__PURE__ */ jsx16("div", { "data-slot": "data-layout-header", className: "min-w-0 empty:hidden", children: header })
2646
+ ) : null,
2626
2647
  /* @__PURE__ */ jsxs15(
2627
2648
  "div",
2628
2649
  {
@@ -2637,7 +2658,7 @@ var DataLayout = React15.forwardRef(
2637
2658
  {
2638
2659
  "data-slot": "data-layout-bulkbar",
2639
2660
  className: "pointer-events-none sticky bottom-[var(--space-4)] z-20 mt-[var(--space-2)] flex justify-center",
2640
- children: /* @__PURE__ */ jsx16("div", { className: "pointer-events-auto max-w-full", children: bulkBar })
2661
+ children: /* @__PURE__ */ jsx16("div", { className: "flex w-full flex-col items-center [&>*:has([data-slot=bulk-action-bar])]:self-stretch [&>*:not(:has([data-slot=bulk-action-bar]))]:pointer-events-auto [&>*]:max-w-full [&_[data-slot=bulk-action-bar]]:pointer-events-auto", children: bulkBar })
2641
2662
  }
2642
2663
  ) : null
2643
2664
  ]
@@ -5633,574 +5654,245 @@ FilterToolbar.displayName = "FilterToolbar";
5633
5654
 
5634
5655
  // src/components/ui/data-table.tsx
5635
5656
  import * as React33 from "react";
5636
- import { ChevronDown as ChevronDown5, ChevronRight as ChevronRight3, ChevronUp as ChevronUp2, ChevronsUpDown } from "lucide-react";
5657
+ import { ChevronDown as ChevronDown5, ChevronRight as ChevronRight3, ChevronUp as ChevronUp2, ChevronsUpDown, EllipsisVertical } from "lucide-react";
5637
5658
  import { cva as cva13 } from "class-variance-authority";
5638
5659
 
5639
- // src/components/ui/checkbox.tsx
5660
+ // src/components/ui/action-menu.tsx
5640
5661
  import * as React30 from "react";
5641
- import { cva as cva12 } from "class-variance-authority";
5642
- import { Check as Check3, Minus } from "lucide-react";
5643
- import { Checkbox as CheckboxPrimitive } from "radix-ui";
5662
+ import { Dialog as DialogPrimitive4, Slot as Slot3 } from "radix-ui";
5663
+
5664
+ // src/components/ui/dropdown-menu.tsx
5665
+ import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
5666
+ import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
5644
5667
  import { jsx as jsx33, jsxs as jsxs29 } from "react/jsx-runtime";
5645
- var checkboxFieldVariants = cva12(
5646
- "flex flex-col gap-[var(--space-1)]",
5647
- {
5648
- variants: {
5649
- fullWidth: {
5650
- true: "w-full",
5651
- false: "w-fit"
5652
- }
5653
- },
5654
- defaultVariants: {
5655
- fullWidth: false
5668
+ function DropdownMenu({
5669
+ ...props
5670
+ }) {
5671
+ return /* @__PURE__ */ jsx33(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
5672
+ }
5673
+ function DropdownMenuPortal({
5674
+ ...props
5675
+ }) {
5676
+ return /* @__PURE__ */ jsx33(DropdownMenuPrimitive.Portal, { "data-slot": "dropdown-menu-portal", ...props });
5677
+ }
5678
+ function DropdownMenuTrigger({
5679
+ ...props
5680
+ }) {
5681
+ return /* @__PURE__ */ jsx33(
5682
+ DropdownMenuPrimitive.Trigger,
5683
+ {
5684
+ "data-slot": "dropdown-menu-trigger",
5685
+ ...props
5656
5686
  }
5657
- }
5658
- );
5659
- var checkboxVariants = checkboxFieldVariants;
5660
- var checkboxRootVariants = cva12(
5661
- [
5662
- "group shrink-0 cursor-pointer rounded-[var(--radius-xs)]",
5663
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--bg-base)]",
5664
- "disabled:cursor-not-allowed"
5665
- ].join(" ")
5666
- );
5667
- var checkboxBoxVariants = cva12(
5668
- [
5669
- "flex shrink-0 items-center justify-center rounded-[var(--radius-xs)] border",
5670
- "border-[var(--border-strong)] bg-[var(--bg-surface)] text-transparent",
5671
- "transition-colors motion-reduce:transition-none",
5672
- "group-hover:bg-[var(--action-hover)]",
5673
- "group-disabled:border-[var(--border-subtle)] group-disabled:bg-[var(--action-disabled-bg)]",
5674
- "group-data-[state=checked]:border-[var(--primary)] group-data-[state=checked]:bg-[var(--primary)] group-data-[state=checked]:text-[var(--primary-fg)]",
5675
- "group-data-[state=indeterminate]:border-[var(--primary)] group-data-[state=indeterminate]:bg-[var(--primary)] group-data-[state=indeterminate]:text-[var(--primary-fg)]",
5676
- "group-disabled:group-data-[state=checked]:border-[var(--border-subtle)] group-disabled:group-data-[state=checked]:bg-[var(--action-disabled-bg)] group-disabled:group-data-[state=checked]:text-text-disabled",
5677
- "group-disabled:group-data-[state=indeterminate]:border-[var(--border-subtle)] group-disabled:group-data-[state=indeterminate]:bg-[var(--action-disabled-bg)] group-disabled:group-data-[state=indeterminate]:text-text-disabled"
5678
- ].join(" "),
5679
- {
5680
- variants: {
5681
- size: {
5682
- sm: "size-[calc(var(--space-4)+var(--space-1))]",
5683
- md: "size-[calc(var(--space-4)+var(--space-1))]"
5684
- }
5685
- },
5686
- defaultVariants: {
5687
- size: "md"
5687
+ );
5688
+ }
5689
+ function DropdownMenuContent({
5690
+ className,
5691
+ sideOffset = 4,
5692
+ ...props
5693
+ }) {
5694
+ return /* @__PURE__ */ jsx33(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx33(
5695
+ DropdownMenuPrimitive.Content,
5696
+ {
5697
+ "data-slot": "dropdown-menu-content",
5698
+ sideOffset,
5699
+ className: cn(
5700
+ "z-[var(--z-popover)] max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem]",
5701
+ "origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto",
5702
+ "rounded-[var(--radius-lg)] border border-[var(--border)] bg-[var(--bg-surface)] p-[var(--space-1)] text-text-primary shadow-[var(--shadow-16)]",
5703
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
5704
+ "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
5705
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
5706
+ "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
5707
+ "motion-reduce:transition-none",
5708
+ className
5709
+ ),
5710
+ ...props
5688
5711
  }
5689
- }
5690
- );
5691
- var checkboxGroupItemVariants = cva12(
5692
- [
5693
- "group w-full cursor-pointer text-left transition-colors motion-reduce:transition-none",
5694
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--bg-base)]",
5695
- "disabled:cursor-not-allowed disabled:text-text-disabled"
5696
- ].join(" "),
5697
- {
5698
- variants: {
5699
- appearance: {
5700
- plain: "inline-flex items-start gap-[var(--space-3)] rounded-[var(--radius-md)] px-[var(--space-3)] py-[var(--space-2)]",
5701
- card: [
5702
- "flex min-h-[calc(var(--space-12)+var(--space-2))] items-start gap-[var(--space-3)]",
5703
- "rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--bg-surface)]",
5704
- "hover:bg-[var(--action-hover)]",
5705
- "data-[state=checked]:border-[var(--border-strong)] data-[state=checked]:bg-[var(--action-selected)]",
5706
- "disabled:border-[var(--border-subtle)] disabled:bg-[var(--action-disabled-bg)]",
5707
- "disabled:data-[state=checked]:border-[var(--border-subtle)] disabled:data-[state=checked]:bg-[var(--action-disabled-bg)]"
5708
- ].join(" ")
5709
- },
5710
- density: {
5711
- comfortable: "",
5712
- compact: ""
5713
- }
5714
- },
5715
- compoundVariants: [
5716
- {
5717
- appearance: "card",
5718
- density: "comfortable",
5719
- className: "px-[var(--space-4)] py-[var(--space-4)]"
5720
- },
5721
- {
5722
- appearance: "card",
5723
- density: "compact",
5724
- className: "px-[var(--space-3)] py-[var(--space-3)]"
5725
- }
5726
- ],
5727
- defaultVariants: {
5728
- appearance: "plain",
5729
- density: "comfortable"
5712
+ ) });
5713
+ }
5714
+ function DropdownMenuGroup({
5715
+ ...props
5716
+ }) {
5717
+ return /* @__PURE__ */ jsx33(DropdownMenuPrimitive.Group, { "data-slot": "dropdown-menu-group", ...props });
5718
+ }
5719
+ function DropdownMenuItem({
5720
+ className,
5721
+ inset,
5722
+ variant = "default",
5723
+ ...props
5724
+ }) {
5725
+ return /* @__PURE__ */ jsx33(
5726
+ DropdownMenuPrimitive.Item,
5727
+ {
5728
+ "data-slot": "dropdown-menu-item",
5729
+ "data-inset": inset,
5730
+ "data-variant": variant,
5731
+ className: cn(
5732
+ "relative flex min-h-[32px] cursor-pointer items-center gap-[var(--space-2)]",
5733
+ "rounded-sm px-[var(--space-3)] py-[var(--space-1)] text-body-sm leading-compact text-text-primary outline-none select-none",
5734
+ "data-[inset]:pl-8",
5735
+ "data-[highlighted]:bg-action-hover data-[highlighted]:text-text-primary",
5736
+ "data-[state=open]:bg-action-selected",
5737
+ "data-[disabled]:pointer-events-none data-[disabled]:bg-action-disabled-bg data-[disabled]:text-text-disabled",
5738
+ "data-[variant=destructive]:text-[var(--semantic-error,var(--error))]",
5739
+ "[&_svg]:pointer-events-none [&_svg]:shrink-0",
5740
+ className
5741
+ ),
5742
+ ...props
5730
5743
  }
5731
- }
5732
- );
5733
- var checkboxGroupBoxVariants = cva12(
5734
- "mt-[2px]",
5735
- {
5736
- variants: {
5737
- appearance: {
5738
- plain: "",
5739
- card: "mt-[var(--space-1)]"
5740
- }
5741
- },
5742
- defaultVariants: {
5743
- appearance: "plain"
5744
+ );
5745
+ }
5746
+ function DropdownMenuCheckboxItem({
5747
+ className,
5748
+ children,
5749
+ checked,
5750
+ ...props
5751
+ }) {
5752
+ return /* @__PURE__ */ jsxs29(
5753
+ DropdownMenuPrimitive.CheckboxItem,
5754
+ {
5755
+ "data-slot": "dropdown-menu-checkbox-item",
5756
+ className: cn(
5757
+ "relative flex min-h-[32px] cursor-pointer items-center gap-[var(--space-2)]",
5758
+ "rounded-sm py-[var(--space-1)] pr-[var(--space-3)] pl-8 text-body-sm leading-compact text-text-primary outline-none select-none",
5759
+ "data-[highlighted]:bg-action-hover data-[highlighted]:text-text-primary",
5760
+ "data-[state=open]:bg-action-selected",
5761
+ "data-[disabled]:pointer-events-none data-[disabled]:bg-action-disabled-bg data-[disabled]:text-text-disabled",
5762
+ "[&_svg]:pointer-events-none [&_svg]:shrink-0",
5763
+ className
5764
+ ),
5765
+ checked,
5766
+ ...props,
5767
+ children: [
5768
+ /* @__PURE__ */ jsx33("span", { className: "pointer-events-none absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx33(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx33(CheckIcon, { size: 16 }) }) }),
5769
+ children
5770
+ ]
5744
5771
  }
5745
- }
5746
- );
5747
- var CheckboxGroupContext = React30.createContext(null);
5748
- function getLabel(children, label) {
5749
- return children ?? label;
5772
+ );
5750
5773
  }
5751
- var Checkbox = React30.forwardRef(
5752
- ({
5753
- className,
5754
- size = "md",
5755
- fullWidth = false,
5756
- children,
5757
- label,
5758
- description,
5759
- required,
5760
- error,
5761
- id,
5762
- value,
5763
- name,
5764
- checked,
5765
- disabled,
5766
- onCheckedChange,
5767
- ...props
5768
- }, ref) => {
5769
- const group = React30.useContext(CheckboxGroupContext);
5770
- const generatedId = React30.useId();
5771
- const checkboxId = id ?? generatedId;
5772
- const labelContent = getLabel(children, label);
5773
- const isGrouped = Boolean(group && value != null);
5774
- const valueString = value == null ? void 0 : String(value);
5775
- const resolvedChecked = isGrouped && valueString ? group?.selectedValues.has(valueString) : checked;
5776
- const resolvedDisabled = disabled || group?.disabled;
5777
- const resolvedName = name ?? group?.name;
5778
- const labelId = `${checkboxId}-label`;
5779
- const descriptionId = description && !error ? `${checkboxId}-description` : void 0;
5780
- const errorId = error ? `${checkboxId}-error` : void 0;
5781
- const describedBy = errorId ?? descriptionId;
5782
- const handleCheckedChange = (nextChecked) => {
5783
- onCheckedChange?.(nextChecked);
5784
- if (isGrouped && valueString) {
5785
- group?.toggleValue(valueString, nextChecked === true);
5786
- }
5787
- };
5788
- if (isGrouped) {
5789
- const appearance = group?.appearance ?? "plain";
5790
- const density = group?.density ?? "comfortable";
5791
- return /* @__PURE__ */ jsxs29(
5792
- CheckboxPrimitive.Root,
5793
- {
5794
- ref,
5795
- id: checkboxId,
5796
- "data-slot": "checkbox",
5797
- "aria-labelledby": labelId,
5798
- "aria-describedby": describedBy,
5799
- "aria-required": required || void 0,
5800
- "aria-invalid": error ? true : void 0,
5801
- name: resolvedName,
5802
- value: valueString,
5803
- checked: resolvedChecked,
5804
- disabled: resolvedDisabled,
5805
- className: cn(
5806
- checkboxGroupItemVariants({ appearance, density }),
5807
- className
5808
- ),
5809
- onCheckedChange: handleCheckedChange,
5810
- ...props,
5811
- children: [
5812
- /* @__PURE__ */ jsx33(
5813
- "span",
5814
- {
5815
- "aria-hidden": "true",
5816
- "data-slot": "checkbox-box",
5817
- className: cn(
5818
- checkboxBoxVariants({ size }),
5819
- checkboxGroupBoxVariants({ appearance })
5820
- ),
5821
- children: /* @__PURE__ */ jsx33(
5822
- CheckboxPrimitive.Indicator,
5823
- {
5824
- "data-slot": "checkbox-indicator",
5825
- className: "flex items-center justify-center",
5826
- children: resolvedChecked === "indeterminate" ? /* @__PURE__ */ jsx33(Minus, { "aria-hidden": "true", size: 14, strokeWidth: 2.5 }) : /* @__PURE__ */ jsx33(Check3, { "aria-hidden": "true", size: 14, strokeWidth: 2.5 })
5827
- }
5828
- )
5829
- }
5830
- ),
5831
- /* @__PURE__ */ jsxs29("span", { className: "flex min-w-0 flex-col gap-[var(--space-1)]", children: [
5832
- /* @__PURE__ */ jsxs29(
5833
- "span",
5834
- {
5835
- id: labelId,
5836
- "data-slot": "checkbox-label",
5837
- className: "text-sm font-medium leading-snug text-foreground group-disabled:text-text-disabled",
5838
- children: [
5839
- labelContent,
5840
- required ? /* @__PURE__ */ jsx33(
5841
- "span",
5842
- {
5843
- "aria-hidden": "true",
5844
- "data-slot": "checkbox-required-marker",
5845
- className: "ml-[var(--space-1)] font-bold text-[var(--semantic-error,var(--error))]",
5846
- children: "*"
5847
- }
5848
- ) : null
5849
- ]
5850
- }
5851
- ),
5852
- error ? /* @__PURE__ */ jsx33(
5853
- "span",
5854
- {
5855
- id: errorId,
5856
- role: "alert",
5857
- "data-slot": "checkbox-error",
5858
- className: "text-xs font-medium leading-normal text-[var(--error)]",
5859
- children: error
5860
- }
5861
- ) : description ? /* @__PURE__ */ jsx33(
5862
- "span",
5863
- {
5864
- id: descriptionId,
5865
- "data-slot": "checkbox-description",
5866
- className: "text-xs font-normal leading-normal text-text-tertiary group-disabled:text-text-disabled",
5867
- children: description
5868
- }
5869
- ) : null
5870
- ] })
5871
- ]
5872
- }
5873
- );
5774
+ function DropdownMenuRadioGroup({
5775
+ ...props
5776
+ }) {
5777
+ return /* @__PURE__ */ jsx33(
5778
+ DropdownMenuPrimitive.RadioGroup,
5779
+ {
5780
+ "data-slot": "dropdown-menu-radio-group",
5781
+ ...props
5874
5782
  }
5875
- const labelClassName = cn(
5876
- "cursor-pointer select-none text-left font-medium text-foreground",
5877
- size === "sm" ? "text-xs" : "text-sm",
5878
- resolvedDisabled && "cursor-not-allowed text-text-disabled"
5879
- );
5880
- return /* @__PURE__ */ jsxs29(
5881
- "div",
5882
- {
5883
- "data-slot": "checkbox-field",
5884
- "data-disabled": resolvedDisabled ? "" : void 0,
5885
- className: checkboxFieldVariants({ fullWidth }),
5886
- children: [
5887
- /* @__PURE__ */ jsxs29("div", { className: "inline-flex items-center gap-[var(--space-3)]", children: [
5888
- /* @__PURE__ */ jsx33(
5889
- CheckboxPrimitive.Root,
5890
- {
5891
- ref,
5892
- id: checkboxId,
5893
- "data-slot": "checkbox",
5894
- "aria-describedby": describedBy,
5895
- "aria-required": required || void 0,
5896
- "aria-invalid": error ? true : void 0,
5897
- name: resolvedName,
5898
- value: valueString,
5899
- checked: resolvedChecked,
5900
- disabled: resolvedDisabled,
5901
- className: cn(checkboxRootVariants(), className),
5902
- onCheckedChange: handleCheckedChange,
5903
- ...props,
5904
- children: /* @__PURE__ */ jsx33(
5905
- "span",
5906
- {
5907
- "aria-hidden": "true",
5908
- "data-slot": "checkbox-box",
5909
- className: checkboxBoxVariants({ size }),
5910
- children: /* @__PURE__ */ jsx33(
5911
- CheckboxPrimitive.Indicator,
5912
- {
5913
- "data-slot": "checkbox-indicator",
5914
- className: "flex items-center justify-center",
5915
- children: resolvedChecked === "indeterminate" ? /* @__PURE__ */ jsx33(Minus, { "aria-hidden": "true", size: 14, strokeWidth: 2.5 }) : /* @__PURE__ */ jsx33(Check3, { "aria-hidden": "true", size: 14, strokeWidth: 2.5 })
5916
- }
5917
- )
5918
- }
5919
- )
5920
- }
5921
- ),
5922
- labelContent ? /* @__PURE__ */ jsxs29(
5923
- "label",
5924
- {
5925
- id: labelId,
5926
- htmlFor: checkboxId,
5927
- "data-slot": "checkbox-label",
5928
- className: labelClassName,
5929
- children: [
5930
- labelContent,
5931
- required ? /* @__PURE__ */ jsx33(
5932
- "span",
5933
- {
5934
- "aria-hidden": "true",
5935
- "data-slot": "checkbox-required-marker",
5936
- className: "ml-[var(--space-1)] font-bold text-[var(--semantic-error,var(--error))]",
5937
- children: "*"
5938
- }
5939
- ) : null
5940
- ]
5941
- }
5942
- ) : null
5943
- ] }),
5944
- error ? /* @__PURE__ */ jsx33(
5945
- "p",
5946
- {
5947
- id: errorId,
5948
- role: "alert",
5949
- "data-slot": "checkbox-error",
5950
- className: "ml-[32px] text-xs font-medium leading-normal text-[var(--error)]",
5951
- children: error
5952
- }
5953
- ) : description ? /* @__PURE__ */ jsx33(
5954
- "p",
5955
- {
5956
- id: descriptionId,
5957
- "data-slot": "checkbox-description",
5958
- className: cn(
5959
- "ml-[32px] text-xs font-normal leading-normal text-text-tertiary",
5960
- resolvedDisabled && "text-text-disabled"
5961
- ),
5962
- children: description
5963
- }
5964
- ) : null
5965
- ]
5966
- }
5967
- );
5968
- }
5969
- );
5970
- Checkbox.displayName = "Checkbox";
5971
-
5972
- // src/components/ui/dropdown-menu.tsx
5973
- import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
5974
- import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
5975
- import { jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
5976
- function DropdownMenu({
5783
+ );
5784
+ }
5785
+ function DropdownMenuRadioItem({
5786
+ className,
5787
+ children,
5977
5788
  ...props
5978
5789
  }) {
5979
- return /* @__PURE__ */ jsx34(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
5790
+ return /* @__PURE__ */ jsxs29(
5791
+ DropdownMenuPrimitive.RadioItem,
5792
+ {
5793
+ "data-slot": "dropdown-menu-radio-item",
5794
+ className: cn(
5795
+ "relative flex min-h-[32px] cursor-pointer items-center gap-[var(--space-2)]",
5796
+ "rounded-sm py-[var(--space-1)] pr-[var(--space-3)] pl-8 text-body-sm leading-compact text-text-primary outline-none select-none",
5797
+ "data-[highlighted]:bg-action-hover data-[highlighted]:text-text-primary",
5798
+ "data-[state=open]:bg-action-selected",
5799
+ "data-[disabled]:pointer-events-none data-[disabled]:bg-action-disabled-bg data-[disabled]:text-text-disabled",
5800
+ "[&_svg]:pointer-events-none [&_svg]:shrink-0",
5801
+ className
5802
+ ),
5803
+ ...props,
5804
+ children: [
5805
+ /* @__PURE__ */ jsx33("span", { className: "pointer-events-none absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx33(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx33(CircleIcon, { size: 8, className: "fill-current" }) }) }),
5806
+ children
5807
+ ]
5808
+ }
5809
+ );
5980
5810
  }
5981
- function DropdownMenuPortal({
5811
+ function DropdownMenuLabel({
5812
+ className,
5813
+ inset,
5982
5814
  ...props
5983
5815
  }) {
5984
- return /* @__PURE__ */ jsx34(DropdownMenuPrimitive.Portal, { "data-slot": "dropdown-menu-portal", ...props });
5816
+ return /* @__PURE__ */ jsx33(
5817
+ DropdownMenuPrimitive.Label,
5818
+ {
5819
+ "data-slot": "dropdown-menu-label",
5820
+ "data-inset": inset,
5821
+ className: cn(
5822
+ "px-[var(--space-2)] py-[var(--space-1)] text-xs font-semibold leading-compact text-text-tertiary data-[inset]:pl-8",
5823
+ className
5824
+ ),
5825
+ ...props
5826
+ }
5827
+ );
5985
5828
  }
5986
- function DropdownMenuTrigger({
5829
+ function DropdownMenuSeparator({
5830
+ className,
5987
5831
  ...props
5988
5832
  }) {
5989
- return /* @__PURE__ */ jsx34(
5990
- DropdownMenuPrimitive.Trigger,
5833
+ return /* @__PURE__ */ jsx33(
5834
+ DropdownMenuPrimitive.Separator,
5991
5835
  {
5992
- "data-slot": "dropdown-menu-trigger",
5836
+ "data-slot": "dropdown-menu-separator",
5837
+ className: cn("-mx-1 my-1 h-0 border-t border-border-subtle", className),
5993
5838
  ...props
5994
5839
  }
5995
5840
  );
5996
5841
  }
5997
- function DropdownMenuContent({
5842
+ function DropdownMenuShortcut({
5998
5843
  className,
5999
- sideOffset = 4,
6000
5844
  ...props
6001
5845
  }) {
6002
- return /* @__PURE__ */ jsx34(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx34(
6003
- DropdownMenuPrimitive.Content,
5846
+ return /* @__PURE__ */ jsx33(
5847
+ "span",
6004
5848
  {
6005
- "data-slot": "dropdown-menu-content",
6006
- sideOffset,
5849
+ "data-slot": "dropdown-menu-shortcut",
6007
5850
  className: cn(
6008
- "z-[var(--z-popover)] max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem]",
6009
- "origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto",
6010
- "rounded-[var(--radius-lg)] border border-[var(--border)] bg-[var(--bg-surface)] p-[var(--space-1)] text-text-primary shadow-[var(--shadow-16)]",
6011
- "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
6012
- "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
6013
- "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
6014
- "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
6015
- "motion-reduce:transition-none",
5851
+ "ml-auto text-xs tracking-widest text-text-secondary",
6016
5852
  className
6017
5853
  ),
6018
5854
  ...props
6019
5855
  }
6020
- ) });
5856
+ );
6021
5857
  }
6022
- function DropdownMenuGroup({
5858
+ function DropdownMenuSub({
6023
5859
  ...props
6024
5860
  }) {
6025
- return /* @__PURE__ */ jsx34(DropdownMenuPrimitive.Group, { "data-slot": "dropdown-menu-group", ...props });
5861
+ return /* @__PURE__ */ jsx33(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
6026
5862
  }
6027
- function DropdownMenuItem({
5863
+ function DropdownMenuSubTrigger({
6028
5864
  className,
6029
5865
  inset,
6030
- variant = "default",
5866
+ children,
6031
5867
  ...props
6032
5868
  }) {
6033
- return /* @__PURE__ */ jsx34(
6034
- DropdownMenuPrimitive.Item,
5869
+ return /* @__PURE__ */ jsxs29(
5870
+ DropdownMenuPrimitive.SubTrigger,
6035
5871
  {
6036
- "data-slot": "dropdown-menu-item",
5872
+ "data-slot": "dropdown-menu-sub-trigger",
6037
5873
  "data-inset": inset,
6038
- "data-variant": variant,
6039
5874
  className: cn(
6040
- "relative flex min-h-[32px] cursor-pointer items-center gap-[var(--space-2)]",
5875
+ "flex min-h-[32px] cursor-pointer items-center gap-[var(--space-2)]",
6041
5876
  "rounded-sm px-[var(--space-3)] py-[var(--space-1)] text-body-sm leading-compact text-text-primary outline-none select-none",
6042
5877
  "data-[inset]:pl-8",
6043
5878
  "data-[highlighted]:bg-action-hover data-[highlighted]:text-text-primary",
6044
5879
  "data-[state=open]:bg-action-selected",
6045
- "data-[disabled]:pointer-events-none data-[disabled]:bg-action-disabled-bg data-[disabled]:text-text-disabled",
6046
- "data-[variant=destructive]:text-[var(--semantic-error,var(--error))]",
6047
5880
  "[&_svg]:pointer-events-none [&_svg]:shrink-0",
6048
5881
  className
6049
5882
  ),
6050
- ...props
5883
+ ...props,
5884
+ children: [
5885
+ children,
5886
+ /* @__PURE__ */ jsx33(ChevronRightIcon, { className: "ml-auto", size: 16 })
5887
+ ]
6051
5888
  }
6052
5889
  );
6053
5890
  }
6054
- function DropdownMenuCheckboxItem({
5891
+ function DropdownMenuSubContent({
6055
5892
  className,
6056
- children,
6057
- checked,
6058
5893
  ...props
6059
5894
  }) {
6060
- return /* @__PURE__ */ jsxs30(
6061
- DropdownMenuPrimitive.CheckboxItem,
6062
- {
6063
- "data-slot": "dropdown-menu-checkbox-item",
6064
- className: cn(
6065
- "relative flex min-h-[32px] cursor-pointer items-center gap-[var(--space-2)]",
6066
- "rounded-sm py-[var(--space-1)] pr-[var(--space-3)] pl-8 text-body-sm leading-compact text-text-primary outline-none select-none",
6067
- "data-[highlighted]:bg-action-hover data-[highlighted]:text-text-primary",
6068
- "data-[state=open]:bg-action-selected",
6069
- "data-[disabled]:pointer-events-none data-[disabled]:bg-action-disabled-bg data-[disabled]:text-text-disabled",
6070
- "[&_svg]:pointer-events-none [&_svg]:shrink-0",
6071
- className
6072
- ),
6073
- checked,
6074
- ...props,
6075
- children: [
6076
- /* @__PURE__ */ jsx34("span", { className: "pointer-events-none absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx34(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx34(CheckIcon, { size: 16 }) }) }),
6077
- children
6078
- ]
6079
- }
6080
- );
6081
- }
6082
- function DropdownMenuRadioGroup({
6083
- ...props
6084
- }) {
6085
- return /* @__PURE__ */ jsx34(
6086
- DropdownMenuPrimitive.RadioGroup,
6087
- {
6088
- "data-slot": "dropdown-menu-radio-group",
6089
- ...props
6090
- }
6091
- );
6092
- }
6093
- function DropdownMenuRadioItem({
6094
- className,
6095
- children,
6096
- ...props
6097
- }) {
6098
- return /* @__PURE__ */ jsxs30(
6099
- DropdownMenuPrimitive.RadioItem,
6100
- {
6101
- "data-slot": "dropdown-menu-radio-item",
6102
- className: cn(
6103
- "relative flex min-h-[32px] cursor-pointer items-center gap-[var(--space-2)]",
6104
- "rounded-sm py-[var(--space-1)] pr-[var(--space-3)] pl-8 text-body-sm leading-compact text-text-primary outline-none select-none",
6105
- "data-[highlighted]:bg-action-hover data-[highlighted]:text-text-primary",
6106
- "data-[state=open]:bg-action-selected",
6107
- "data-[disabled]:pointer-events-none data-[disabled]:bg-action-disabled-bg data-[disabled]:text-text-disabled",
6108
- "[&_svg]:pointer-events-none [&_svg]:shrink-0",
6109
- className
6110
- ),
6111
- ...props,
6112
- children: [
6113
- /* @__PURE__ */ jsx34("span", { className: "pointer-events-none absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx34(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx34(CircleIcon, { size: 8, className: "fill-current" }) }) }),
6114
- children
6115
- ]
6116
- }
6117
- );
6118
- }
6119
- function DropdownMenuLabel({
6120
- className,
6121
- inset,
6122
- ...props
6123
- }) {
6124
- return /* @__PURE__ */ jsx34(
6125
- DropdownMenuPrimitive.Label,
6126
- {
6127
- "data-slot": "dropdown-menu-label",
6128
- "data-inset": inset,
6129
- className: cn(
6130
- "px-[var(--space-2)] py-[var(--space-1)] text-xs font-semibold leading-compact text-text-tertiary data-[inset]:pl-8",
6131
- className
6132
- ),
6133
- ...props
6134
- }
6135
- );
6136
- }
6137
- function DropdownMenuSeparator({
6138
- className,
6139
- ...props
6140
- }) {
6141
- return /* @__PURE__ */ jsx34(
6142
- DropdownMenuPrimitive.Separator,
6143
- {
6144
- "data-slot": "dropdown-menu-separator",
6145
- className: cn("-mx-1 my-1 h-0 border-t border-border-subtle", className),
6146
- ...props
6147
- }
6148
- );
6149
- }
6150
- function DropdownMenuShortcut({
6151
- className,
6152
- ...props
6153
- }) {
6154
- return /* @__PURE__ */ jsx34(
6155
- "span",
6156
- {
6157
- "data-slot": "dropdown-menu-shortcut",
6158
- className: cn(
6159
- "ml-auto text-xs tracking-widest text-text-secondary",
6160
- className
6161
- ),
6162
- ...props
6163
- }
6164
- );
6165
- }
6166
- function DropdownMenuSub({
6167
- ...props
6168
- }) {
6169
- return /* @__PURE__ */ jsx34(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
6170
- }
6171
- function DropdownMenuSubTrigger({
6172
- className,
6173
- inset,
6174
- children,
6175
- ...props
6176
- }) {
6177
- return /* @__PURE__ */ jsxs30(
6178
- DropdownMenuPrimitive.SubTrigger,
6179
- {
6180
- "data-slot": "dropdown-menu-sub-trigger",
6181
- "data-inset": inset,
6182
- className: cn(
6183
- "flex min-h-[32px] cursor-pointer items-center gap-[var(--space-2)]",
6184
- "rounded-sm px-[var(--space-3)] py-[var(--space-1)] text-body-sm leading-compact text-text-primary outline-none select-none",
6185
- "data-[inset]:pl-8",
6186
- "data-[highlighted]:bg-action-hover data-[highlighted]:text-text-primary",
6187
- "data-[state=open]:bg-action-selected",
6188
- "[&_svg]:pointer-events-none [&_svg]:shrink-0",
6189
- className
6190
- ),
6191
- ...props,
6192
- children: [
6193
- children,
6194
- /* @__PURE__ */ jsx34(ChevronRightIcon, { className: "ml-auto", size: 16 })
6195
- ]
6196
- }
6197
- );
6198
- }
6199
- function DropdownMenuSubContent({
6200
- className,
6201
- ...props
6202
- }) {
6203
- return /* @__PURE__ */ jsx34(
5895
+ return /* @__PURE__ */ jsx33(
6204
5896
  DropdownMenuPrimitive.SubContent,
6205
5897
  {
6206
5898
  "data-slot": "dropdown-menu-sub-content",
@@ -6219,14 +5911,8 @@ function DropdownMenuSubContent({
6219
5911
  );
6220
5912
  }
6221
5913
 
6222
- // src/components/ui/list-card.tsx
6223
- import * as React32 from "react";
6224
- import { ChevronRight as ChevronRight2, MoreVertical } from "lucide-react";
6225
-
6226
5914
  // src/components/ui/action-menu.tsx
6227
- import * as React31 from "react";
6228
- import { Dialog as DialogPrimitive4, Slot as Slot3 } from "radix-ui";
6229
- import { Fragment as Fragment13, jsx as jsx35, jsxs as jsxs31 } from "react/jsx-runtime";
5915
+ import { Fragment as Fragment13, jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
6230
5916
  var sheetRowClassName = cn(
6231
5917
  "group flex min-h-12 w-full cursor-pointer items-center gap-[var(--space-3)] px-[var(--space-4)] py-[var(--space-2)] text-left",
6232
5918
  "border-t border-[var(--border-subtle)] text-[13px] font-medium leading-normal text-text-primary",
@@ -6248,9 +5934,9 @@ function ActionMenuSheet({
6248
5934
  onOpenAutoFocus,
6249
5935
  onCloseAutoFocus
6250
5936
  }) {
6251
- const pendingRef = React31.useRef(null);
6252
- const surfaceRef = React31.useRef(null);
6253
- const labelId = React31.useId();
5937
+ const pendingRef = React30.useRef(null);
5938
+ const surfaceRef = React30.useRef(null);
5939
+ const labelId = React30.useId();
6254
5940
  const handleOpenChange = (nextOpen) => {
6255
5941
  pendingRef.current = null;
6256
5942
  onOpenChange(nextOpen);
@@ -6278,9 +5964,9 @@ function ActionMenuSheet({
6278
5964
  pendingRef.current = null;
6279
5965
  item?.onSelect();
6280
5966
  };
6281
- return /* @__PURE__ */ jsx35(DialogPrimitive4.Root, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs31(DialogPrimitive4.Portal, { children: [
6282
- /* @__PURE__ */ jsx35(OverlayScrimLayer, { kind: "menu" }),
6283
- /* @__PURE__ */ jsxs31(
5967
+ return /* @__PURE__ */ jsx34(DialogPrimitive4.Root, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs30(DialogPrimitive4.Portal, { children: [
5968
+ /* @__PURE__ */ jsx34(OverlayScrimLayer, { kind: "menu" }),
5969
+ /* @__PURE__ */ jsxs30(
6284
5970
  DialogPrimitive4.Content,
6285
5971
  {
6286
5972
  ref: surfaceRef,
@@ -6290,8 +5976,8 @@ function ActionMenuSheet({
6290
5976
  onCloseAutoFocus: handleCloseAutoFocus,
6291
5977
  ...description ? {} : { "aria-describedby": void 0 },
6292
5978
  children: [
6293
- /* @__PURE__ */ jsx35(OverlayGrabber, { always: true, ...swipe.handleProps }),
6294
- /* @__PURE__ */ jsx35(
5979
+ /* @__PURE__ */ jsx34(OverlayGrabber, { always: true, ...swipe.handleProps }),
5980
+ /* @__PURE__ */ jsx34(
6295
5981
  OverlayHeader,
6296
5982
  {
6297
5983
  kind: "menu",
@@ -6301,13 +5987,13 @@ function ActionMenuSheet({
6301
5987
  dragHandleProps: swipe.handleProps
6302
5988
  }
6303
5989
  ),
6304
- /* @__PURE__ */ jsx35(OverlayBody, { kind: "menu", children: groups.map((group, index) => /* @__PURE__ */ jsxs31(React31.Fragment, { children: [
6305
- index > 0 ? /* @__PURE__ */ jsx35("div", { role: "separator", className: sheetGroupSeparatorClassName }) : null,
6306
- /* @__PURE__ */ jsxs31("div", { role: "group", "aria-labelledby": group.label ? `${labelId}-${index}` : void 0, children: [
6307
- group.label ? /* @__PURE__ */ jsx35("div", { id: `${labelId}-${index}`, className: sheetGroupLabelClassName, children: group.label }) : null,
5990
+ /* @__PURE__ */ jsx34(OverlayBody, { kind: "menu", children: groups.map((group, index) => /* @__PURE__ */ jsxs30(React30.Fragment, { children: [
5991
+ index > 0 ? /* @__PURE__ */ jsx34("div", { role: "separator", className: sheetGroupSeparatorClassName }) : null,
5992
+ /* @__PURE__ */ jsxs30("div", { role: "group", "aria-labelledby": group.label ? `${labelId}-${index}` : void 0, children: [
5993
+ group.label ? /* @__PURE__ */ jsx34("div", { id: `${labelId}-${index}`, className: sheetGroupLabelClassName, children: group.label }) : null,
6308
5994
  group.items.map((item) => {
6309
5995
  const Icon = item.icon;
6310
- return /* @__PURE__ */ jsxs31(
5996
+ return /* @__PURE__ */ jsxs30(
6311
5997
  "button",
6312
5998
  {
6313
5999
  type: "button",
@@ -6317,10 +6003,10 @@ function ActionMenuSheet({
6317
6003
  disabled: item.disabled,
6318
6004
  onClick: () => handleSelect(item),
6319
6005
  children: [
6320
- Icon ? /* @__PURE__ */ jsx35(Icon, { "aria-hidden": true, size: 17, strokeWidth: 1.75, className: "shrink-0" }) : null,
6321
- /* @__PURE__ */ jsxs31("span", { className: "min-w-0 flex-1 break-keep", children: [
6006
+ Icon ? /* @__PURE__ */ jsx34(Icon, { "aria-hidden": true, size: 17, strokeWidth: 1.75, className: "shrink-0" }) : null,
6007
+ /* @__PURE__ */ jsxs30("span", { className: "min-w-0 flex-1 break-keep", children: [
6322
6008
  item.label,
6323
- item.description ? /* @__PURE__ */ jsx35("span", { className: sheetRowDescriptionClassName, children: item.description }) : null
6009
+ item.description ? /* @__PURE__ */ jsx34("span", { className: sheetRowDescriptionClassName, children: item.description }) : null
6324
6010
  ] })
6325
6011
  ]
6326
6012
  },
@@ -6336,7 +6022,7 @@ function ActionMenuSheet({
6336
6022
  }
6337
6023
  var readPresentation = () => window.matchMedia?.(OVERLAY_DESKTOP_QUERY).matches ?? true ? "dropdown" : "sheet";
6338
6024
  var subscribeNothing = () => () => void 0;
6339
- var useHydrated = () => React31.useSyncExternalStore(
6025
+ var useHydrated = () => React30.useSyncExternalStore(
6340
6026
  subscribeNothing,
6341
6027
  () => true,
6342
6028
  () => false
@@ -6351,10 +6037,10 @@ function ActionMenu({
6351
6037
  items,
6352
6038
  groups
6353
6039
  }) {
6354
- const [uncontrolledOpen, setUncontrolledOpen] = React31.useState(false);
6040
+ const [uncontrolledOpen, setUncontrolledOpen] = React30.useState(false);
6355
6041
  const hydrated = useHydrated();
6356
6042
  const open = (openProp ?? uncontrolledOpen) && hydrated;
6357
- const [shown, setShown] = React31.useState({
6043
+ const [shown, setShown] = React30.useState({
6358
6044
  open: false,
6359
6045
  presentation: "dropdown"
6360
6046
  });
@@ -6363,72 +6049,438 @@ function ActionMenu({
6363
6049
  if (open) presentation = readPresentation();
6364
6050
  setShown({ open, presentation });
6365
6051
  }
6366
- const triggerRef = React31.useRef(null);
6367
- const pendingRef = React31.useRef(null);
6368
- const setOpen = (nextOpen) => {
6369
- if (nextOpen) pendingRef.current = null;
6370
- if (openProp === void 0) setUncontrolledOpen(nextOpen);
6371
- onOpenChange?.(nextOpen);
6372
- };
6373
- const menuGroups = groups ?? [{ id: "items", items: items ?? [] }];
6374
- const handleDropdownCloseAutoFocus = (event) => {
6375
- const item = pendingRef.current;
6376
- pendingRef.current = null;
6377
- if (!item) return;
6378
- event.preventDefault();
6379
- triggerRef.current?.focus();
6380
- item.onSelect();
6381
- };
6382
- const handleSheetCloseAutoFocus = (event) => {
6383
- event.preventDefault();
6384
- triggerRef.current?.focus();
6385
- };
6386
- const triggerLabel = trigger.props["aria-label"];
6387
- return /* @__PURE__ */ jsxs31(Fragment13, { children: [
6388
- /* @__PURE__ */ jsxs31(DropdownMenu, { open: open && presentation === "dropdown", onOpenChange: setOpen, children: [
6389
- /* @__PURE__ */ jsx35(DropdownMenuTrigger, { asChild: true, "aria-expanded": open, children: /* @__PURE__ */ jsx35(Slot3.Root, { ref: triggerRef, children: trigger }) }),
6390
- /* @__PURE__ */ jsx35(DropdownMenuContent, { align: "end", onCloseAutoFocus: handleDropdownCloseAutoFocus, children: menuGroups.map((group, index) => /* @__PURE__ */ jsxs31(React31.Fragment, { children: [
6391
- index > 0 ? /* @__PURE__ */ jsx35(DropdownMenuSeparator, {}) : null,
6392
- /* @__PURE__ */ jsxs31(DropdownMenuGroup, { children: [
6393
- group.label ? /* @__PURE__ */ jsx35(DropdownMenuLabel, { children: group.label }) : null,
6394
- group.items.map((item) => {
6395
- const Icon = item.icon;
6396
- return /* @__PURE__ */ jsxs31(
6397
- DropdownMenuItem,
6398
- {
6399
- variant: item.destructive ? "destructive" : "default",
6400
- disabled: item.disabled,
6401
- onSelect: () => {
6402
- pendingRef.current = item;
6403
- },
6404
- children: [
6405
- Icon ? /* @__PURE__ */ jsx35(Icon, { "aria-hidden": true, size: 16, strokeWidth: 1.75 }) : null,
6406
- item.label
6407
- ]
6408
- },
6409
- item.id
6410
- );
6411
- })
6412
- ] })
6413
- ] }, group.id)) })
6414
- ] }),
6415
- /* @__PURE__ */ jsx35(
6416
- ActionMenuSheet,
6052
+ const triggerRef = React30.useRef(null);
6053
+ const pendingRef = React30.useRef(null);
6054
+ const setOpen = (nextOpen) => {
6055
+ if (nextOpen) pendingRef.current = null;
6056
+ if (openProp === void 0) setUncontrolledOpen(nextOpen);
6057
+ onOpenChange?.(nextOpen);
6058
+ };
6059
+ const menuGroups = groups ?? [{ id: "items", items: items ?? [] }];
6060
+ const handleDropdownCloseAutoFocus = (event) => {
6061
+ const item = pendingRef.current;
6062
+ pendingRef.current = null;
6063
+ if (!item) return;
6064
+ event.preventDefault();
6065
+ triggerRef.current?.focus();
6066
+ item.onSelect();
6067
+ };
6068
+ const handleSheetCloseAutoFocus = (event) => {
6069
+ event.preventDefault();
6070
+ triggerRef.current?.focus();
6071
+ };
6072
+ const triggerLabel = trigger.props["aria-label"];
6073
+ return /* @__PURE__ */ jsxs30(Fragment13, { children: [
6074
+ /* @__PURE__ */ jsxs30(DropdownMenu, { open: open && presentation === "dropdown", onOpenChange: setOpen, children: [
6075
+ /* @__PURE__ */ jsx34(DropdownMenuTrigger, { asChild: true, "aria-expanded": open, children: /* @__PURE__ */ jsx34(Slot3.Root, { ref: triggerRef, children: trigger }) }),
6076
+ /* @__PURE__ */ jsx34(DropdownMenuContent, { align: "end", onCloseAutoFocus: handleDropdownCloseAutoFocus, children: menuGroups.map((group, index) => /* @__PURE__ */ jsxs30(React30.Fragment, { children: [
6077
+ index > 0 ? /* @__PURE__ */ jsx34(DropdownMenuSeparator, {}) : null,
6078
+ /* @__PURE__ */ jsxs30(DropdownMenuGroup, { children: [
6079
+ group.label ? /* @__PURE__ */ jsx34(DropdownMenuLabel, { children: group.label }) : null,
6080
+ group.items.map((item) => {
6081
+ const Icon = item.icon;
6082
+ return /* @__PURE__ */ jsxs30(
6083
+ DropdownMenuItem,
6084
+ {
6085
+ variant: item.destructive ? "destructive" : "default",
6086
+ disabled: item.disabled,
6087
+ onSelect: () => {
6088
+ pendingRef.current = item;
6089
+ },
6090
+ children: [
6091
+ Icon ? /* @__PURE__ */ jsx34(Icon, { "aria-hidden": true, size: 16, strokeWidth: 1.75 }) : null,
6092
+ item.label
6093
+ ]
6094
+ },
6095
+ item.id
6096
+ );
6097
+ })
6098
+ ] })
6099
+ ] }, group.id)) })
6100
+ ] }),
6101
+ /* @__PURE__ */ jsx34(
6102
+ ActionMenuSheet,
6103
+ {
6104
+ open: open && presentation === "sheet",
6105
+ onOpenChange: setOpen,
6106
+ title: title ?? /* @__PURE__ */ jsx34("span", { className: "sr-only", children: triggerLabel }),
6107
+ description,
6108
+ closeLabel,
6109
+ groups: menuGroups,
6110
+ onCloseAutoFocus: handleSheetCloseAutoFocus
6111
+ }
6112
+ )
6113
+ ] });
6114
+ }
6115
+
6116
+ // src/components/ui/checkbox.tsx
6117
+ import * as React31 from "react";
6118
+ import { cva as cva12 } from "class-variance-authority";
6119
+ import { Check as Check3, Minus } from "lucide-react";
6120
+ import { Checkbox as CheckboxPrimitive } from "radix-ui";
6121
+ import { jsx as jsx35, jsxs as jsxs31 } from "react/jsx-runtime";
6122
+ var checkboxFieldVariants = cva12(
6123
+ "flex flex-col gap-[var(--space-1)]",
6124
+ {
6125
+ variants: {
6126
+ fullWidth: {
6127
+ true: "w-full",
6128
+ false: "w-fit"
6129
+ }
6130
+ },
6131
+ defaultVariants: {
6132
+ fullWidth: false
6133
+ }
6134
+ }
6135
+ );
6136
+ var checkboxVariants = checkboxFieldVariants;
6137
+ var checkboxRootVariants = cva12(
6138
+ [
6139
+ "group shrink-0 cursor-pointer rounded-[var(--radius-xs)]",
6140
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--bg-base)]",
6141
+ "disabled:cursor-not-allowed"
6142
+ ].join(" ")
6143
+ );
6144
+ var checkboxBoxVariants = cva12(
6145
+ [
6146
+ "flex shrink-0 items-center justify-center rounded-[var(--radius-xs)] border",
6147
+ "border-[var(--border-strong)] bg-[var(--bg-surface)] text-transparent",
6148
+ "transition-colors motion-reduce:transition-none",
6149
+ "group-hover:bg-[var(--action-hover)]",
6150
+ "group-disabled:border-[var(--border-subtle)] group-disabled:bg-[var(--action-disabled-bg)]",
6151
+ "group-data-[state=checked]:border-[var(--primary)] group-data-[state=checked]:bg-[var(--primary)] group-data-[state=checked]:text-[var(--primary-fg)]",
6152
+ "group-data-[state=indeterminate]:border-[var(--primary)] group-data-[state=indeterminate]:bg-[var(--primary)] group-data-[state=indeterminate]:text-[var(--primary-fg)]",
6153
+ "group-disabled:group-data-[state=checked]:border-[var(--border-subtle)] group-disabled:group-data-[state=checked]:bg-[var(--action-disabled-bg)] group-disabled:group-data-[state=checked]:text-text-disabled",
6154
+ "group-disabled:group-data-[state=indeterminate]:border-[var(--border-subtle)] group-disabled:group-data-[state=indeterminate]:bg-[var(--action-disabled-bg)] group-disabled:group-data-[state=indeterminate]:text-text-disabled"
6155
+ ].join(" "),
6156
+ {
6157
+ variants: {
6158
+ size: {
6159
+ sm: "size-[calc(var(--space-4)+var(--space-1))]",
6160
+ md: "size-[calc(var(--space-4)+var(--space-1))]"
6161
+ }
6162
+ },
6163
+ defaultVariants: {
6164
+ size: "md"
6165
+ }
6166
+ }
6167
+ );
6168
+ var checkboxGroupItemVariants = cva12(
6169
+ [
6170
+ "group w-full cursor-pointer text-left transition-colors motion-reduce:transition-none",
6171
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--bg-base)]",
6172
+ "disabled:cursor-not-allowed disabled:text-text-disabled"
6173
+ ].join(" "),
6174
+ {
6175
+ variants: {
6176
+ appearance: {
6177
+ plain: "inline-flex items-start gap-[var(--space-3)] rounded-[var(--radius-md)] px-[var(--space-3)] py-[var(--space-2)]",
6178
+ card: [
6179
+ "flex min-h-[calc(var(--space-12)+var(--space-2))] items-start gap-[var(--space-3)]",
6180
+ "rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--bg-surface)]",
6181
+ "hover:bg-[var(--action-hover)]",
6182
+ "data-[state=checked]:border-[var(--border-strong)] data-[state=checked]:bg-[var(--action-selected)]",
6183
+ "disabled:border-[var(--border-subtle)] disabled:bg-[var(--action-disabled-bg)]",
6184
+ "disabled:data-[state=checked]:border-[var(--border-subtle)] disabled:data-[state=checked]:bg-[var(--action-disabled-bg)]"
6185
+ ].join(" ")
6186
+ },
6187
+ density: {
6188
+ comfortable: "",
6189
+ compact: ""
6190
+ }
6191
+ },
6192
+ compoundVariants: [
6193
+ {
6194
+ appearance: "card",
6195
+ density: "comfortable",
6196
+ className: "px-[var(--space-4)] py-[var(--space-4)]"
6197
+ },
6198
+ {
6199
+ appearance: "card",
6200
+ density: "compact",
6201
+ className: "px-[var(--space-3)] py-[var(--space-3)]"
6202
+ }
6203
+ ],
6204
+ defaultVariants: {
6205
+ appearance: "plain",
6206
+ density: "comfortable"
6207
+ }
6208
+ }
6209
+ );
6210
+ var checkboxGroupBoxVariants = cva12(
6211
+ "mt-[2px]",
6212
+ {
6213
+ variants: {
6214
+ appearance: {
6215
+ plain: "",
6216
+ card: "mt-[var(--space-1)]"
6217
+ }
6218
+ },
6219
+ defaultVariants: {
6220
+ appearance: "plain"
6221
+ }
6222
+ }
6223
+ );
6224
+ var CheckboxGroupContext = React31.createContext(null);
6225
+ function getLabel(children, label) {
6226
+ return children ?? label;
6227
+ }
6228
+ var Checkbox = React31.forwardRef(
6229
+ ({
6230
+ className,
6231
+ size = "md",
6232
+ fullWidth = false,
6233
+ children,
6234
+ label,
6235
+ description,
6236
+ required,
6237
+ error,
6238
+ id,
6239
+ value,
6240
+ name,
6241
+ checked,
6242
+ disabled,
6243
+ onCheckedChange,
6244
+ ...props
6245
+ }, ref) => {
6246
+ const group = React31.useContext(CheckboxGroupContext);
6247
+ const generatedId = React31.useId();
6248
+ const checkboxId = id ?? generatedId;
6249
+ const labelContent = getLabel(children, label);
6250
+ const isGrouped = Boolean(group && value != null);
6251
+ const valueString = value == null ? void 0 : String(value);
6252
+ const resolvedChecked = isGrouped && valueString ? group?.selectedValues.has(valueString) : checked;
6253
+ const resolvedDisabled = disabled || group?.disabled;
6254
+ const resolvedName = name ?? group?.name;
6255
+ const labelId = `${checkboxId}-label`;
6256
+ const descriptionId = description && !error ? `${checkboxId}-description` : void 0;
6257
+ const errorId = error ? `${checkboxId}-error` : void 0;
6258
+ const describedBy = errorId ?? descriptionId;
6259
+ const handleCheckedChange = (nextChecked) => {
6260
+ onCheckedChange?.(nextChecked);
6261
+ if (isGrouped && valueString) {
6262
+ group?.toggleValue(valueString, nextChecked === true);
6263
+ }
6264
+ };
6265
+ if (isGrouped) {
6266
+ const appearance = group?.appearance ?? "plain";
6267
+ const density = group?.density ?? "comfortable";
6268
+ return /* @__PURE__ */ jsxs31(
6269
+ CheckboxPrimitive.Root,
6270
+ {
6271
+ ref,
6272
+ id: checkboxId,
6273
+ "data-slot": "checkbox",
6274
+ "aria-labelledby": labelId,
6275
+ "aria-describedby": describedBy,
6276
+ "aria-required": required || void 0,
6277
+ "aria-invalid": error ? true : void 0,
6278
+ name: resolvedName,
6279
+ value: valueString,
6280
+ checked: resolvedChecked,
6281
+ disabled: resolvedDisabled,
6282
+ className: cn(
6283
+ checkboxGroupItemVariants({ appearance, density }),
6284
+ className
6285
+ ),
6286
+ onCheckedChange: handleCheckedChange,
6287
+ ...props,
6288
+ children: [
6289
+ /* @__PURE__ */ jsx35(
6290
+ "span",
6291
+ {
6292
+ "aria-hidden": "true",
6293
+ "data-slot": "checkbox-box",
6294
+ className: cn(
6295
+ checkboxBoxVariants({ size }),
6296
+ checkboxGroupBoxVariants({ appearance })
6297
+ ),
6298
+ children: /* @__PURE__ */ jsx35(
6299
+ CheckboxPrimitive.Indicator,
6300
+ {
6301
+ "data-slot": "checkbox-indicator",
6302
+ className: "flex items-center justify-center",
6303
+ children: resolvedChecked === "indeterminate" ? /* @__PURE__ */ jsx35(Minus, { "aria-hidden": "true", size: 14, strokeWidth: 2.5 }) : /* @__PURE__ */ jsx35(Check3, { "aria-hidden": "true", size: 14, strokeWidth: 2.5 })
6304
+ }
6305
+ )
6306
+ }
6307
+ ),
6308
+ /* @__PURE__ */ jsxs31("span", { className: "flex min-w-0 flex-col gap-[var(--space-1)]", children: [
6309
+ /* @__PURE__ */ jsxs31(
6310
+ "span",
6311
+ {
6312
+ id: labelId,
6313
+ "data-slot": "checkbox-label",
6314
+ className: "text-sm font-medium leading-snug text-foreground group-disabled:text-text-disabled",
6315
+ children: [
6316
+ labelContent,
6317
+ required ? /* @__PURE__ */ jsx35(
6318
+ "span",
6319
+ {
6320
+ "aria-hidden": "true",
6321
+ "data-slot": "checkbox-required-marker",
6322
+ className: "ml-[var(--space-1)] font-bold text-[var(--semantic-error,var(--error))]",
6323
+ children: "*"
6324
+ }
6325
+ ) : null
6326
+ ]
6327
+ }
6328
+ ),
6329
+ error ? /* @__PURE__ */ jsx35(
6330
+ "span",
6331
+ {
6332
+ id: errorId,
6333
+ role: "alert",
6334
+ "data-slot": "checkbox-error",
6335
+ className: "text-xs font-medium leading-normal text-[var(--error)]",
6336
+ children: error
6337
+ }
6338
+ ) : description ? /* @__PURE__ */ jsx35(
6339
+ "span",
6340
+ {
6341
+ id: descriptionId,
6342
+ "data-slot": "checkbox-description",
6343
+ className: "text-xs font-normal leading-normal text-text-tertiary group-disabled:text-text-disabled",
6344
+ children: description
6345
+ }
6346
+ ) : null
6347
+ ] })
6348
+ ]
6349
+ }
6350
+ );
6351
+ }
6352
+ const labelClassName = cn(
6353
+ "cursor-pointer select-none text-left font-medium text-foreground",
6354
+ size === "sm" ? "text-xs" : "text-sm",
6355
+ resolvedDisabled && "cursor-not-allowed text-text-disabled"
6356
+ );
6357
+ return /* @__PURE__ */ jsxs31(
6358
+ "div",
6359
+ {
6360
+ "data-slot": "checkbox-field",
6361
+ "data-disabled": resolvedDisabled ? "" : void 0,
6362
+ className: checkboxFieldVariants({ fullWidth }),
6363
+ children: [
6364
+ /* @__PURE__ */ jsxs31("div", { className: "inline-flex items-center gap-[var(--space-3)]", children: [
6365
+ /* @__PURE__ */ jsx35(
6366
+ CheckboxPrimitive.Root,
6367
+ {
6368
+ ref,
6369
+ id: checkboxId,
6370
+ "data-slot": "checkbox",
6371
+ "aria-describedby": describedBy,
6372
+ "aria-required": required || void 0,
6373
+ "aria-invalid": error ? true : void 0,
6374
+ name: resolvedName,
6375
+ value: valueString,
6376
+ checked: resolvedChecked,
6377
+ disabled: resolvedDisabled,
6378
+ className: cn(checkboxRootVariants(), className),
6379
+ onCheckedChange: handleCheckedChange,
6380
+ ...props,
6381
+ children: /* @__PURE__ */ jsx35(
6382
+ "span",
6383
+ {
6384
+ "aria-hidden": "true",
6385
+ "data-slot": "checkbox-box",
6386
+ className: checkboxBoxVariants({ size }),
6387
+ children: /* @__PURE__ */ jsx35(
6388
+ CheckboxPrimitive.Indicator,
6389
+ {
6390
+ "data-slot": "checkbox-indicator",
6391
+ className: "flex items-center justify-center",
6392
+ children: resolvedChecked === "indeterminate" ? /* @__PURE__ */ jsx35(Minus, { "aria-hidden": "true", size: 14, strokeWidth: 2.5 }) : /* @__PURE__ */ jsx35(Check3, { "aria-hidden": "true", size: 14, strokeWidth: 2.5 })
6393
+ }
6394
+ )
6395
+ }
6396
+ )
6397
+ }
6398
+ ),
6399
+ labelContent ? /* @__PURE__ */ jsxs31(
6400
+ "label",
6401
+ {
6402
+ id: labelId,
6403
+ htmlFor: checkboxId,
6404
+ "data-slot": "checkbox-label",
6405
+ className: labelClassName,
6406
+ children: [
6407
+ labelContent,
6408
+ required ? /* @__PURE__ */ jsx35(
6409
+ "span",
6410
+ {
6411
+ "aria-hidden": "true",
6412
+ "data-slot": "checkbox-required-marker",
6413
+ className: "ml-[var(--space-1)] font-bold text-[var(--semantic-error,var(--error))]",
6414
+ children: "*"
6415
+ }
6416
+ ) : null
6417
+ ]
6418
+ }
6419
+ ) : null
6420
+ ] }),
6421
+ error ? /* @__PURE__ */ jsx35(
6422
+ "p",
6423
+ {
6424
+ id: errorId,
6425
+ role: "alert",
6426
+ "data-slot": "checkbox-error",
6427
+ className: "ml-[32px] text-xs font-medium leading-normal text-[var(--error)]",
6428
+ children: error
6429
+ }
6430
+ ) : description ? /* @__PURE__ */ jsx35(
6431
+ "p",
6432
+ {
6433
+ id: descriptionId,
6434
+ "data-slot": "checkbox-description",
6435
+ className: cn(
6436
+ "ml-[32px] text-xs font-normal leading-normal text-text-tertiary",
6437
+ resolvedDisabled && "text-text-disabled"
6438
+ ),
6439
+ children: description
6440
+ }
6441
+ ) : null
6442
+ ]
6443
+ }
6444
+ );
6445
+ }
6446
+ );
6447
+ Checkbox.displayName = "Checkbox";
6448
+
6449
+ // src/components/ui/context-menu.tsx
6450
+ import { jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
6451
+ function ContextMenu({
6452
+ open,
6453
+ onOpenChange,
6454
+ position,
6455
+ children,
6456
+ contentProps
6457
+ }) {
6458
+ if (!position) {
6459
+ return null;
6460
+ }
6461
+ return /* @__PURE__ */ jsxs32(DropdownMenu, { open, onOpenChange, modal: false, children: [
6462
+ /* @__PURE__ */ jsx36(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx36(
6463
+ "span",
6417
6464
  {
6418
- open: open && presentation === "sheet",
6419
- onOpenChange: setOpen,
6420
- title: title ?? /* @__PURE__ */ jsx35("span", { className: "sr-only", children: triggerLabel }),
6421
- description,
6422
- closeLabel,
6423
- groups: menuGroups,
6424
- onCloseAutoFocus: handleSheetCloseAutoFocus
6465
+ "aria-hidden": "true",
6466
+ "data-slot": "context-menu-anchor",
6467
+ style: {
6468
+ position: "fixed",
6469
+ left: position.x,
6470
+ top: position.y,
6471
+ width: 0,
6472
+ height: 0
6473
+ }
6425
6474
  }
6426
- )
6475
+ ) }),
6476
+ /* @__PURE__ */ jsx36(DropdownMenuContent, { ...contentProps, children })
6427
6477
  ] });
6428
6478
  }
6429
6479
 
6430
6480
  // src/components/ui/list-card.tsx
6431
- import { Fragment as Fragment14, jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
6481
+ import * as React32 from "react";
6482
+ import { ChevronRight as ChevronRight2, MoreVertical } from "lucide-react";
6483
+ import { Fragment as Fragment14, jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
6432
6484
  function lineTokens(value) {
6433
6485
  return React32.Children.toArray(value).filter((token) => token !== "");
6434
6486
  }
@@ -6438,7 +6490,7 @@ function MetaLine({
6438
6490
  first,
6439
6491
  last
6440
6492
  }) {
6441
- return /* @__PURE__ */ jsx36(
6493
+ return /* @__PURE__ */ jsx37(
6442
6494
  "span",
6443
6495
  {
6444
6496
  "data-slot": slot,
@@ -6446,14 +6498,14 @@ function MetaLine({
6446
6498
  "flex flex-wrap gap-x-[var(--space-3)] gap-y-[2px] text-[12px] leading-[16px] text-text-secondary",
6447
6499
  first ? "mt-[var(--space-1)]" : "mt-[2px]"
6448
6500
  ),
6449
- children: tokens.map((token, index) => /* @__PURE__ */ jsxs32(
6501
+ children: tokens.map((token, index) => /* @__PURE__ */ jsxs33(
6450
6502
  "span",
6451
6503
  {
6452
6504
  className: "max-w-full truncate whitespace-nowrap",
6453
6505
  title: typeof token === "string" || typeof token === "number" ? String(token) : void 0,
6454
6506
  children: [
6455
6507
  token,
6456
- index < tokens.length - 1 || !last ? /* @__PURE__ */ jsx36("span", { className: "sr-only", children: ", " }) : null
6508
+ index < tokens.length - 1 || !last ? /* @__PURE__ */ jsx37("span", { className: "sr-only", children: ", " }) : null
6457
6509
  ]
6458
6510
  },
6459
6511
  index
@@ -6464,7 +6516,7 @@ function MetaLine({
6464
6516
  var titleClassName = "line-clamp-2 text-[13px] font-medium leading-[18px] text-text-primary [overflow-wrap:anywhere] [word-break:keep-all]";
6465
6517
  var overlayClassName = cn(
6466
6518
  "text-inherit no-underline outline-none after:absolute after:inset-0 after:content-['']",
6467
- "focus-visible:after:ring-2 focus-visible:after:ring-inset focus-visible:after:ring-[var(--focus-ring)]"
6519
+ "focus-visible:after:inset-ring-2 focus-visible:after:inset-ring-[var(--focus-ring)]"
6468
6520
  );
6469
6521
  function ListCard({
6470
6522
  title,
@@ -6486,19 +6538,19 @@ function ListCard({
6486
6538
  const meta2 = lineTokens(meta?.[1]);
6487
6539
  const hasValue = value != null;
6488
6540
  const overlay = actions != null && (href != null || onClick != null);
6489
- const trailingNode = trailing === "chevron" ? /* @__PURE__ */ jsx36(
6541
+ const trailingNode = trailing === "chevron" ? /* @__PURE__ */ jsx37(
6490
6542
  ChevronRight2,
6491
6543
  {
6492
6544
  "data-slot": `${slot}-suffix`,
6493
6545
  "aria-hidden": true,
6494
6546
  className: "size-[var(--space-4)] shrink-0 text-text-tertiary"
6495
6547
  }
6496
- ) : trailing === "none" ? null : /* @__PURE__ */ jsx36("span", { "data-slot": `${slot}-suffix`, children: trailing });
6548
+ ) : trailing === "none" ? null : /* @__PURE__ */ jsx37("span", { "data-slot": `${slot}-suffix`, children: trailing });
6497
6549
  const bottomIcon = actions != null && trailingNode != null;
6498
6550
  const hasEnd = hasValue || actions != null || trailingNode != null;
6499
6551
  const rootClassName = cn(
6500
6552
  "relative grid w-full min-w-0 items-start gap-x-[var(--space-2)] whitespace-normal text-left outline-none",
6501
- "focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--focus-ring)]",
6553
+ "focus-visible:inset-ring-2 focus-visible:inset-ring-[var(--focus-ring)]",
6502
6554
  // An empty end keeps the 16px chevron track.
6503
6555
  leading ? hasEnd ? "grid-cols-[auto_minmax(0,1fr)_auto]" : "grid-cols-[auto_minmax(0,1fr)_16px]" : hasEnd ? "grid-cols-[minmax(0,1fr)_auto]" : "grid-cols-[minmax(0,1fr)_16px]",
6504
6556
  // 84 = the ⋮ hit area (2 above the top to 42 below) meets the chevron's (42 above the bottom to 2 below).
@@ -6506,7 +6558,7 @@ function ListCard({
6506
6558
  href && !overlay && "after:absolute after:inset-0 after:content-['']",
6507
6559
  className
6508
6560
  );
6509
- const titleNode = /* @__PURE__ */ jsx36(
6561
+ const titleNode = /* @__PURE__ */ jsx37(
6510
6562
  "span",
6511
6563
  {
6512
6564
  "data-slot": `${slot}-title`,
@@ -6515,18 +6567,18 @@ function ListCard({
6515
6567
  children: overlay && href != null ? React32.createElement(linkComponent ?? "a", { ...linkProps, href, className: overlayClassName }, title) : title
6516
6568
  }
6517
6569
  );
6518
- const content = /* @__PURE__ */ jsxs32(Fragment14, { children: [
6519
- leading != null ? /* @__PURE__ */ jsx36("span", { className: "flex min-h-[18px] items-center", children: leading }) : null,
6520
- /* @__PURE__ */ jsxs32("span", { className: "min-w-0", children: [
6570
+ const content = /* @__PURE__ */ jsxs33(Fragment14, { children: [
6571
+ leading != null ? /* @__PURE__ */ jsx37("span", { className: "flex min-h-[18px] items-center", children: leading }) : null,
6572
+ /* @__PURE__ */ jsxs33("span", { className: "min-w-0", children: [
6521
6573
  overlay && href == null ? (
6522
6574
  // A block button keeps the title's two-line clamp inside it.
6523
- /* @__PURE__ */ jsx36("button", { type: "button", onClick, className: cn(overlayClassName, "block w-full text-left"), children: titleNode })
6575
+ /* @__PURE__ */ jsx37("button", { type: "button", onClick, className: cn(overlayClassName, "block w-full text-left"), children: titleNode })
6524
6576
  ) : titleNode,
6525
- meta1.length > 0 ? /* @__PURE__ */ jsx36(MetaLine, { tokens: meta1, slot: `${slot}-meta1`, first: true, last: meta2.length === 0 }) : null,
6526
- meta2.length > 0 ? /* @__PURE__ */ jsx36(MetaLine, { tokens: meta2, slot: `${slot}-meta2`, first: meta1.length === 0, last: true }) : null,
6527
- status != null || caption != null ? /* @__PURE__ */ jsxs32("span", { "data-slot": `${slot}-bottom`, className: "mt-[var(--space-2)] flex min-h-[18px] items-center gap-[var(--space-2)]", children: [
6528
- status != null ? /* @__PURE__ */ jsx36("span", { "data-slot": `${slot}-badge`, className: "flex items-center", children: status }) : null,
6529
- caption != null ? /* @__PURE__ */ jsx36(
6577
+ meta1.length > 0 ? /* @__PURE__ */ jsx37(MetaLine, { tokens: meta1, slot: `${slot}-meta1`, first: true, last: meta2.length === 0 }) : null,
6578
+ meta2.length > 0 ? /* @__PURE__ */ jsx37(MetaLine, { tokens: meta2, slot: `${slot}-meta2`, first: meta1.length === 0, last: true }) : null,
6579
+ status != null || caption != null ? /* @__PURE__ */ jsxs33("span", { "data-slot": `${slot}-bottom`, className: "mt-[var(--space-2)] flex min-h-[18px] items-center gap-[var(--space-2)]", children: [
6580
+ status != null ? /* @__PURE__ */ jsx37("span", { "data-slot": `${slot}-badge`, className: "flex items-center", children: status }) : null,
6581
+ caption != null ? /* @__PURE__ */ jsx37(
6530
6582
  "span",
6531
6583
  {
6532
6584
  "data-slot": `${slot}-caption`,
@@ -6536,8 +6588,8 @@ function ListCard({
6536
6588
  ) : null
6537
6589
  ] }) : null
6538
6590
  ] }),
6539
- hasEnd ? /* @__PURE__ */ jsxs32("span", { "data-slot": `${slot}-trailing`, className: "flex flex-col items-end justify-between self-stretch", children: [
6540
- /* @__PURE__ */ jsxs32(
6591
+ hasEnd ? /* @__PURE__ */ jsxs33("span", { "data-slot": `${slot}-trailing`, className: "flex flex-col items-end justify-between self-stretch", children: [
6592
+ /* @__PURE__ */ jsxs33(
6541
6593
  "span",
6542
6594
  {
6543
6595
  className: cn(
@@ -6545,13 +6597,13 @@ function ListCard({
6545
6597
  actions != null ? "-mr-[var(--space-2)] gap-[var(--space-1)]" : "gap-[var(--space-2)]"
6546
6598
  ),
6547
6599
  children: [
6548
- hasValue ? /* @__PURE__ */ jsx36("span", { "data-slot": `${slot}-value`, className: "text-[13px] leading-[20px] text-text-secondary tabular-nums", children: value }) : null,
6549
- actions != null ? /* @__PURE__ */ jsx36("span", { className: "relative z-[1] flex", children: /* @__PURE__ */ jsx36(
6600
+ hasValue ? /* @__PURE__ */ jsx37("span", { "data-slot": `${slot}-value`, className: "text-[13px] leading-[20px] text-text-secondary tabular-nums", children: value }) : null,
6601
+ actions != null ? /* @__PURE__ */ jsx37("span", { className: "relative z-[1] flex", children: /* @__PURE__ */ jsx37(
6550
6602
  ActionMenu,
6551
6603
  {
6552
6604
  title: typeof title === "string" ? title : void 0,
6553
6605
  items: [...actions.items],
6554
- trigger: /* @__PURE__ */ jsx36(
6606
+ trigger: /* @__PURE__ */ jsx37(
6555
6607
  IconButton,
6556
6608
  {
6557
6609
  icon: MoreVertical,
@@ -6571,16 +6623,16 @@ function ListCard({
6571
6623
  ] });
6572
6624
  if (href && !overlay) {
6573
6625
  const LinkComponent = linkComponent ?? "a";
6574
- return /* @__PURE__ */ jsx36(LinkComponent, { ...linkProps, href, className: rootClassName, children: content });
6626
+ return /* @__PURE__ */ jsx37(LinkComponent, { ...linkProps, href, className: rootClassName, children: content });
6575
6627
  }
6576
6628
  if (onClick && !overlay) {
6577
- return /* @__PURE__ */ jsx36("button", { type: "button", onClick, className: rootClassName, children: content });
6629
+ return /* @__PURE__ */ jsx37("button", { type: "button", onClick, className: rootClassName, children: content });
6578
6630
  }
6579
- return /* @__PURE__ */ jsx36("div", { className: rootClassName, children: content });
6631
+ return /* @__PURE__ */ jsx37("div", { className: rootClassName, children: content });
6580
6632
  }
6581
6633
 
6582
6634
  // src/components/ui/data-table.tsx
6583
- import { Fragment as Fragment15, jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
6635
+ import { Fragment as Fragment16, jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
6584
6636
  var dataTableVariants = cva13(
6585
6637
  [
6586
6638
  "relative overflow-hidden rounded-[var(--radius-md)] border border-[var(--border-subtle)]",
@@ -6609,7 +6661,9 @@ var dataTableRowVariants = cva13(
6609
6661
  {
6610
6662
  variants: {
6611
6663
  interactive: {
6612
- true: "cursor-pointer hover:bg-[var(--action-hover)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--focus-ring)]",
6664
+ // inset-ring, not ring-inset: the token theme's --color-inset makes `ring-inset` also a
6665
+ // ring color, which paints the ring in the inset background.
6666
+ true: "cursor-pointer hover:bg-[var(--action-hover)] focus-visible:outline-none focus-visible:inset-ring-2 focus-visible:inset-ring-[var(--focus-ring)]",
6613
6667
  false: ""
6614
6668
  },
6615
6669
  selected: {
@@ -6631,9 +6685,159 @@ var alignmentClass = {
6631
6685
  function getRowId(row, keyField) {
6632
6686
  return String(row[keyField]);
6633
6687
  }
6634
- function getGridTemplate(columns, selectable, expandable) {
6688
+ function getGridTemplate(columns, selectable, expandable, hasRowActions) {
6635
6689
  const columnWidths = columns.map((column) => column.width ?? "1fr");
6636
- return [selectable ? "44px" : null, ...columnWidths, expandable ? "40px" : null].filter(Boolean).join(" ");
6690
+ return [selectable ? "44px" : null, ...columnWidths, expandable ? "40px" : null, hasRowActions ? "44px" : null].filter(Boolean).join(" ");
6691
+ }
6692
+ function isActionGroups(actions) {
6693
+ return actions.length > 0 && "items" in actions[0];
6694
+ }
6695
+ function toActionGroups(actions) {
6696
+ return isActionGroups(actions) ? [...actions] : [{ id: "items", items: [...actions] }];
6697
+ }
6698
+ function countActions(actions) {
6699
+ return isActionGroups(actions) ? actions.reduce((total, group) => total + group.items.length, 0) : actions.length;
6700
+ }
6701
+ function toActionItems(actions) {
6702
+ return isActionGroups(actions) ? actions.flatMap((group) => group.items) : [...actions];
6703
+ }
6704
+ var warnedCardActions = false;
6705
+ function warnCardActionsOnce() {
6706
+ if (warnedCardActions || typeof process === "undefined" || process.env.NODE_ENV === "production") {
6707
+ return;
6708
+ }
6709
+ warnedCardActions = true;
6710
+ console.warn("DataTable: getMobileCardContent().actions is ignored when rowActions is given. The card \u22EE shows rowActions.");
6711
+ }
6712
+ var warnedWrapVirtual = false;
6713
+ function warnWrapVirtualOnce() {
6714
+ if (warnedWrapVirtual || typeof process === "undefined" || process.env.NODE_ENV === "production") {
6715
+ return;
6716
+ }
6717
+ warnedWrapVirtual = true;
6718
+ console.warn("DataTable: a `wrap` column is not supported with `virtual`. Virtual rows share the first row's height, so taller wrapped rows break the scroll positions.");
6719
+ }
6720
+ function RowActionsCell({
6721
+ row,
6722
+ rowId,
6723
+ rowActions,
6724
+ getRowActionsLabel
6725
+ }) {
6726
+ const actions = rowActions(row);
6727
+ const stop = (event) => event.stopPropagation();
6728
+ return /* @__PURE__ */ jsx38(
6729
+ "div",
6730
+ {
6731
+ role: "cell",
6732
+ "data-slot": "data-table-row-actions",
6733
+ "data-row-id": rowId,
6734
+ className: "flex items-center justify-center",
6735
+ onClick: stop,
6736
+ onKeyDown: stop,
6737
+ onContextMenu: stop,
6738
+ children: countActions(actions) > 0 ? /* @__PURE__ */ jsx38(
6739
+ ActionMenu,
6740
+ {
6741
+ groups: toActionGroups(actions),
6742
+ trigger: /* @__PURE__ */ jsx38(
6743
+ IconButton,
6744
+ {
6745
+ icon: EllipsisVertical,
6746
+ "aria-label": getRowActionsLabel(row),
6747
+ appearance: "ghost",
6748
+ tone: "neutral",
6749
+ size: "md"
6750
+ }
6751
+ )
6752
+ }
6753
+ ) : null
6754
+ }
6755
+ );
6756
+ }
6757
+ function RowContextMenu({
6758
+ openKey,
6759
+ position,
6760
+ groups,
6761
+ onClose
6762
+ }) {
6763
+ const [open, setOpen] = React33.useState(false);
6764
+ const pendingRef = React33.useRef(null);
6765
+ const outsideRef = React33.useRef(false);
6766
+ const shownGroups = React33.useRef([]);
6767
+ if (groups) shownGroups.current = groups;
6768
+ const gone = openKey !== null && groups === null;
6769
+ const contentRef = React33.useRef(null);
6770
+ const focusInsideRef = React33.useRef(false);
6771
+ React33.useEffect(() => {
6772
+ pendingRef.current = null;
6773
+ outsideRef.current = false;
6774
+ focusInsideRef.current = false;
6775
+ setOpen(openKey !== null);
6776
+ }, [openKey]);
6777
+ useIsomorphicLayoutEffect(() => {
6778
+ const content = contentRef.current;
6779
+ if (!open || !focusInsideRef.current || !content?.isConnected) return;
6780
+ const active = document.activeElement;
6781
+ if (active && active !== document.body && content.contains(active)) return;
6782
+ const next = content.querySelector('[role="menuitem"]:not([data-disabled])') ?? content;
6783
+ next.focus();
6784
+ });
6785
+ React33.useEffect(() => {
6786
+ if (gone) setOpen(false);
6787
+ }, [gone]);
6788
+ return /* @__PURE__ */ jsx38(
6789
+ ContextMenu,
6790
+ {
6791
+ open: open && !gone,
6792
+ onOpenChange: setOpen,
6793
+ position,
6794
+ contentProps: {
6795
+ align: "start",
6796
+ onFocus: (event) => {
6797
+ contentRef.current = event.currentTarget;
6798
+ focusInsideRef.current = true;
6799
+ },
6800
+ onBlur: (event) => {
6801
+ if (event.relatedTarget instanceof Node && !event.currentTarget.contains(event.relatedTarget)) {
6802
+ focusInsideRef.current = false;
6803
+ }
6804
+ },
6805
+ onInteractOutside: () => {
6806
+ outsideRef.current = true;
6807
+ },
6808
+ onCloseAutoFocus: (event) => {
6809
+ event.preventDefault();
6810
+ const item = pendingRef.current;
6811
+ pendingRef.current = null;
6812
+ onClose(item, outsideRef.current);
6813
+ }
6814
+ },
6815
+ children: shownGroups.current.map((group, index) => /* @__PURE__ */ jsxs34(React33.Fragment, { children: [
6816
+ index > 0 ? /* @__PURE__ */ jsx38(DropdownMenuSeparator, {}) : null,
6817
+ /* @__PURE__ */ jsxs34(DropdownMenuGroup, { children: [
6818
+ group.label ? /* @__PURE__ */ jsx38(DropdownMenuLabel, { children: group.label }) : null,
6819
+ group.items.map((item) => {
6820
+ const Icon = item.icon;
6821
+ return /* @__PURE__ */ jsxs34(
6822
+ DropdownMenuItem,
6823
+ {
6824
+ variant: item.destructive ? "destructive" : "default",
6825
+ disabled: item.disabled,
6826
+ onSelect: () => {
6827
+ pendingRef.current = item;
6828
+ },
6829
+ children: [
6830
+ Icon ? /* @__PURE__ */ jsx38(Icon, { "aria-hidden": true, size: 16, strokeWidth: 1.75 }) : null,
6831
+ item.label
6832
+ ]
6833
+ },
6834
+ item.id
6835
+ );
6836
+ })
6837
+ ] })
6838
+ ] }, group.id))
6839
+ }
6840
+ );
6637
6841
  }
6638
6842
  function getRenderedCell(row, column) {
6639
6843
  if (column.render) {
@@ -6663,7 +6867,7 @@ function isInteractiveTarget(target) {
6663
6867
  function SortIcon({ sort, columnKey }) {
6664
6868
  const isActive = sort?.key === columnKey;
6665
6869
  if (!isActive) {
6666
- return /* @__PURE__ */ jsx37(
6870
+ return /* @__PURE__ */ jsx38(
6667
6871
  ChevronsUpDown,
6668
6872
  {
6669
6873
  "aria-hidden": "true",
@@ -6675,7 +6879,7 @@ function SortIcon({ sort, columnKey }) {
6675
6879
  );
6676
6880
  }
6677
6881
  const Icon = sort.dir === "asc" ? ChevronUp2 : ChevronDown5;
6678
- return /* @__PURE__ */ jsx37(
6882
+ return /* @__PURE__ */ jsx38(
6679
6883
  Icon,
6680
6884
  {
6681
6885
  "aria-hidden": "true",
@@ -6693,8 +6897,8 @@ function MobileSortMenu({
6693
6897
  onSortChange
6694
6898
  }) {
6695
6899
  const active = sortBy ? columns.find((column) => column.key === sortBy.key) : void 0;
6696
- return /* @__PURE__ */ jsxs33(DropdownMenu, { children: [
6697
- /* @__PURE__ */ jsx37(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs33(
6900
+ return /* @__PURE__ */ jsxs34(DropdownMenu, { children: [
6901
+ /* @__PURE__ */ jsx38(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs34(
6698
6902
  Button,
6699
6903
  {
6700
6904
  "data-slot": "data-table-mobile-sort-button",
@@ -6703,26 +6907,26 @@ function MobileSortMenu({
6703
6907
  size: "sm",
6704
6908
  className: "ml-auto min-w-0",
6705
6909
  children: [
6706
- active && sortBy ? /* @__PURE__ */ jsxs33(Fragment15, { children: [
6707
- /* @__PURE__ */ jsx37("span", { className: "sr-only", children: "\uC815\uB82C " }),
6708
- /* @__PURE__ */ jsx37("span", { className: "truncate", children: active.header }),
6709
- /* @__PURE__ */ jsxs33("span", { className: "sr-only", children: [
6910
+ active && sortBy ? /* @__PURE__ */ jsxs34(Fragment16, { children: [
6911
+ /* @__PURE__ */ jsx38("span", { className: "sr-only", children: "\uC815\uB82C " }),
6912
+ /* @__PURE__ */ jsx38("span", { className: "truncate", children: active.header }),
6913
+ /* @__PURE__ */ jsxs34("span", { className: "sr-only", children: [
6710
6914
  ", ",
6711
6915
  sortBy.dir === "asc" ? "\uC624\uB984\uCC28\uC21C" : "\uB0B4\uB9BC\uCC28\uC21C"
6712
6916
  ] })
6713
6917
  ] }) : "\uC815\uB82C",
6714
- /* @__PURE__ */ jsx37(SortIcon, { sort: sortBy, columnKey: active?.key ?? "" })
6918
+ /* @__PURE__ */ jsx38(SortIcon, { sort: sortBy, columnKey: active?.key ?? "" })
6715
6919
  ]
6716
6920
  }
6717
6921
  ) }),
6718
- /* @__PURE__ */ jsx37(DropdownMenuContent, { align: "end", children: /* @__PURE__ */ jsx37(DropdownMenuRadioGroup, { value: active?.key ?? "", children: columns.map((column) => /* @__PURE__ */ jsxs33(
6922
+ /* @__PURE__ */ jsx38(DropdownMenuContent, { align: "end", children: /* @__PURE__ */ jsx38(DropdownMenuRadioGroup, { value: active?.key ?? "", children: columns.map((column) => /* @__PURE__ */ jsxs34(
6719
6923
  DropdownMenuRadioItem,
6720
6924
  {
6721
6925
  value: column.key,
6722
6926
  onSelect: () => onSortChange?.(column.key, getNextSort(sortBy, column.key)),
6723
6927
  children: [
6724
- /* @__PURE__ */ jsx37("span", { className: "truncate", children: column.header }),
6725
- column.key === active?.key ? /* @__PURE__ */ jsx37("span", { className: "ml-auto pl-[var(--space-4)]", children: /* @__PURE__ */ jsx37(SortIcon, { sort: sortBy, columnKey: column.key }) }) : null
6928
+ /* @__PURE__ */ jsx38("span", { className: "truncate", children: column.header }),
6929
+ column.key === active?.key ? /* @__PURE__ */ jsx38("span", { className: "ml-auto pl-[var(--space-4)]", children: /* @__PURE__ */ jsx38(SortIcon, { sort: sortBy, columnKey: column.key }) }) : null
6726
6930
  ]
6727
6931
  },
6728
6932
  column.key
@@ -6735,35 +6939,38 @@ function MobileToolbar({
6735
6939
  onSortChange,
6736
6940
  selectable,
6737
6941
  selectAllChecked,
6942
+ selectAllDisabled,
6738
6943
  onToggleAll
6739
6944
  }) {
6740
6945
  const sortableColumns = columns.filter((column) => column.sortable);
6741
6946
  if (!selectable && sortableColumns.length === 0) {
6742
6947
  return null;
6743
6948
  }
6744
- return /* @__PURE__ */ jsxs33(
6949
+ return /* @__PURE__ */ jsxs34(
6745
6950
  "div",
6746
6951
  {
6747
6952
  "data-slot": "data-table-mobile-toolbar",
6748
6953
  className: "flex min-w-0 items-center gap-[var(--space-2)] px-[var(--space-4)] py-[var(--space-2)]",
6749
6954
  children: [
6750
- selectable ? /* @__PURE__ */ jsx37(SelectAllCheckbox, { checked: selectAllChecked, onToggleAll }) : null,
6751
- sortableColumns.length > 0 ? /* @__PURE__ */ jsx37(MobileSortMenu, { columns: sortableColumns, sortBy, onSortChange }) : null
6955
+ selectable ? /* @__PURE__ */ jsx38(SelectAllCheckbox, { checked: selectAllChecked, disabled: selectAllDisabled, onToggleAll }) : null,
6956
+ sortableColumns.length > 0 ? /* @__PURE__ */ jsx38(MobileSortMenu, { columns: sortableColumns, sortBy, onSortChange }) : null
6752
6957
  ]
6753
6958
  }
6754
6959
  );
6755
6960
  }
6756
6961
  function SelectAllCheckbox({
6757
6962
  checked,
6963
+ disabled,
6758
6964
  onToggleAll
6759
6965
  }) {
6760
- return /* @__PURE__ */ jsx37(
6966
+ return /* @__PURE__ */ jsx38(
6761
6967
  Checkbox,
6762
6968
  {
6763
6969
  "aria-label": "\uC804\uCCB4 \uD589 \uC120\uD0DD",
6764
6970
  checked,
6971
+ disabled,
6765
6972
  onCheckedChange: (nextChecked) => onToggleAll(nextChecked === true),
6766
- children: /* @__PURE__ */ jsx37("span", { className: "sr-only", children: "\uC804\uCCB4 \uD589 \uC120\uD0DD" })
6973
+ children: /* @__PURE__ */ jsx38("span", { className: "sr-only", children: "\uC804\uCCB4 \uD589 \uC120\uD0DD" })
6767
6974
  }
6768
6975
  );
6769
6976
  }
@@ -6772,15 +6979,17 @@ function RowCheckbox({
6772
6979
  rowId,
6773
6980
  columns,
6774
6981
  selected,
6982
+ selectionBlocked,
6775
6983
  onToggle
6776
6984
  }) {
6777
- return /* @__PURE__ */ jsx37(
6985
+ return /* @__PURE__ */ jsx38(
6778
6986
  Checkbox,
6779
6987
  {
6780
6988
  "aria-label": `${String(row[columns[0]?.key] ?? rowId)} \uD589 \uC120\uD0DD`,
6781
6989
  checked: selected,
6990
+ disabled: selectionBlocked,
6782
6991
  onCheckedChange: (nextChecked) => onToggle(rowId, nextChecked === true),
6783
- children: /* @__PURE__ */ jsxs33("span", { className: "sr-only", children: [
6992
+ children: /* @__PURE__ */ jsxs34("span", { className: "sr-only", children: [
6784
6993
  rowId,
6785
6994
  " \uD589 \uC120\uD0DD"
6786
6995
  ] })
@@ -6797,17 +7006,17 @@ function SkeletonRows({
6797
7006
  // role="table"의 허용 자식은 row/rowgroup뿐이라 컨테이너는 rowgroup이어야 한다.
6798
7007
  // 로딩 알림은 그 안의 row/cell 안에 둔다 — 종전에는 컨테이너가 role="status"라
6799
7008
  // aria-required-children(Critical)이 났다.
6800
- /* @__PURE__ */ jsxs33("div", { role: "rowgroup", children: [
6801
- /* @__PURE__ */ jsx37("div", { role: "row", children: /* @__PURE__ */ jsx37("div", { role: "cell", "aria-colindex": 1, "aria-label": "\uB370\uC774\uD130 \uB85C\uB4DC \uC911", children: /* @__PURE__ */ jsx37("span", { role: "status", className: "sr-only", children: "\uB370\uC774\uD130 \uB85C\uB4DC \uC911" }) }) }),
6802
- Array.from({ length: count }, (_, rowIndex) => /* @__PURE__ */ jsxs33(
7009
+ /* @__PURE__ */ jsxs34("div", { role: "rowgroup", children: [
7010
+ /* @__PURE__ */ jsx38("div", { role: "row", children: /* @__PURE__ */ jsx38("div", { role: "cell", "aria-colindex": 1, "aria-label": "\uB370\uC774\uD130 \uB85C\uB4DC \uC911", children: /* @__PURE__ */ jsx38("span", { role: "status", className: "sr-only", children: "\uB370\uC774\uD130 \uB85C\uB4DC \uC911" }) }) }),
7011
+ Array.from({ length: count }, (_, rowIndex) => /* @__PURE__ */ jsxs34(
6803
7012
  "div",
6804
7013
  {
6805
7014
  "data-slot": "data-table-skeleton-row",
6806
7015
  className: "grid min-h-[48px] items-center border-t border-[var(--border-subtle)]",
6807
7016
  style: { gridTemplateColumns },
6808
7017
  children: [
6809
- selectable ? /* @__PURE__ */ jsx37("div", { "aria-hidden": "true", className: "px-[var(--space-4)]" }) : null,
6810
- columns.map((column, columnIndex) => /* @__PURE__ */ jsx37("div", { className: "px-[var(--space-4)] py-[var(--space-2)]", children: /* @__PURE__ */ jsx37(
7018
+ selectable ? /* @__PURE__ */ jsx38("div", { "aria-hidden": "true", className: "px-[var(--space-4)]" }) : null,
7019
+ columns.map((column, columnIndex) => /* @__PURE__ */ jsx38("div", { className: "px-[var(--space-4)] py-[var(--space-2)]", children: /* @__PURE__ */ jsx38(
6811
7020
  "div",
6812
7021
  {
6813
7022
  className: cn(
@@ -6824,24 +7033,25 @@ function SkeletonRows({
6824
7033
  );
6825
7034
  }
6826
7035
  function MobileSkeletonCards({ count }) {
6827
- return /* @__PURE__ */ jsx37("div", { "data-slot": "data-table-mobile-skeleton", "aria-label": "\uB370\uC774\uD130 \uB85C\uB4DC \uC911", role: "status", children: Array.from({ length: count }, (_, rowIndex) => /* @__PURE__ */ jsxs33(
7036
+ return /* @__PURE__ */ jsx38("div", { "data-slot": "data-table-mobile-skeleton", "aria-label": "\uB370\uC774\uD130 \uB85C\uB4DC \uC911", role: "status", children: Array.from({ length: count }, (_, rowIndex) => /* @__PURE__ */ jsxs34(
6828
7037
  "div",
6829
7038
  {
6830
7039
  "data-slot": "data-table-mobile-skeleton-card",
6831
7040
  className: "flex flex-col gap-[var(--space-2)] border-t border-[var(--border-subtle)] px-[var(--space-4)] py-[var(--space-4)]",
6832
7041
  children: [
6833
- /* @__PURE__ */ jsx37("div", { className: "h-[14px] w-[72%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" }),
6834
- /* @__PURE__ */ jsx37("div", { className: "h-[12px] w-[56%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" }),
6835
- /* @__PURE__ */ jsx37("div", { className: "h-[12px] w-[64%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" })
7042
+ /* @__PURE__ */ jsx38("div", { className: "h-[14px] w-[72%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" }),
7043
+ /* @__PURE__ */ jsx38("div", { className: "h-[12px] w-[56%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" }),
7044
+ /* @__PURE__ */ jsx38("div", { className: "h-[12px] w-[64%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" })
6836
7045
  ]
6837
7046
  },
6838
7047
  rowIndex
6839
7048
  )) });
6840
7049
  }
6841
7050
  var rowLinkHostClass = "relative [&_:is(a,button,input,select,textarea,label,[role=button],[role=checkbox]):not([data-slot=data-table-row-link])]:relative [&_:is(a,button,input,select,textarea,label,[role=button],[role=checkbox]):not([data-slot=data-table-row-link])]:z-[1]";
7051
+ var fallbackFocusClass = "focus-visible:outline-none focus-visible:inset-ring-2 focus-visible:inset-ring-[var(--focus-ring)]";
6842
7052
  var rowLinkClass = cn(
6843
7053
  "text-inherit no-underline outline-none after:absolute after:inset-0 after:content-['']",
6844
- "focus-visible:after:ring-2 focus-visible:after:ring-inset focus-visible:after:ring-[var(--focus-ring)]"
7054
+ "focus-visible:after:inset-ring-2 focus-visible:after:inset-ring-[var(--focus-ring)]"
6845
7055
  );
6846
7056
  var expandedPanelClass = cn(
6847
7057
  "grid grid-rows-[0fr] invisible data-[state=open]:grid-rows-[1fr] data-[state=open]:visible",
@@ -6881,6 +7091,7 @@ function DataTableRowView({
6881
7091
  columns,
6882
7092
  selectable,
6883
7093
  selected,
7094
+ selectionBlocked,
6884
7095
  visuallySelected,
6885
7096
  href,
6886
7097
  activatable,
@@ -6889,13 +7100,15 @@ function DataTableRowView({
6889
7100
  onActivate,
6890
7101
  onRowContextMenu,
6891
7102
  expand,
7103
+ rowActions,
7104
+ getRowActionsLabel,
6892
7105
  gridTemplateColumns,
6893
7106
  ariaRowIndex
6894
7107
  }) {
6895
7108
  const linked = Boolean(LinkComponent && href);
6896
7109
  const handlers = useActivationHandlers({ row, href, activatable, onActivate });
6897
7110
  const opened = useOpenedOnce(expand?.expanded ?? false);
6898
- const dataRow = /* @__PURE__ */ jsxs33(
7111
+ const dataRow = /* @__PURE__ */ jsxs34(
6899
7112
  "div",
6900
7113
  {
6901
7114
  "data-slot": "data-table-row",
@@ -6915,26 +7128,26 @@ function DataTableRowView({
6915
7128
  } : handlers.onClick,
6916
7129
  onKeyDown: handlers.onKeyDown,
6917
7130
  children: [
6918
- selectable ? /* @__PURE__ */ jsx37("div", { role: "cell", className: "px-[var(--space-4)]", children: /* @__PURE__ */ jsx37(RowCheckbox, { row, rowId, columns, selected, onToggle }) }) : null,
7131
+ selectable ? /* @__PURE__ */ jsx38("div", { role: "cell", className: "px-[var(--space-4)]", children: /* @__PURE__ */ jsx38(RowCheckbox, { row, rowId, columns, selected, selectionBlocked, onToggle }) }) : null,
6919
7132
  columns.map((column, columnIndex) => {
6920
7133
  const align = column.align ?? "left";
6921
7134
  const content = getRenderedCell(row, column);
6922
- return /* @__PURE__ */ jsx37(
7135
+ return /* @__PURE__ */ jsx38(
6923
7136
  "div",
6924
7137
  {
6925
7138
  "data-slot": "data-table-cell",
6926
7139
  role: "cell",
6927
7140
  className: cn(
6928
- "flex min-w-0 items-center px-[var(--space-4)] py-[var(--space-2)]",
7141
+ "flex min-w-0 items-center overflow-clip px-[var(--space-4)] py-[var(--space-2)]",
6929
7142
  alignmentClass[align],
6930
7143
  column.tabular ? "font-[family-name:var(--font-display)] tabular-nums" : null
6931
7144
  ),
6932
- children: /* @__PURE__ */ jsx37("span", { className: "min-w-0 truncate", children: linked && columnIndex === 0 && LinkComponent ? /* @__PURE__ */ jsx37(LinkComponent, { href, "data-slot": "data-table-row-link", className: rowLinkClass, children: content }) : content })
7145
+ children: /* @__PURE__ */ jsx38("span", { className: column.wrap ? "min-w-0 break-keep [overflow-wrap:anywhere]" : "min-w-0 truncate", children: linked && columnIndex === 0 && LinkComponent ? /* @__PURE__ */ jsx38(LinkComponent, { href, "data-slot": "data-table-row-link", className: rowLinkClass, children: content }) : content })
6933
7146
  },
6934
7147
  column.key
6935
7148
  );
6936
7149
  }),
6937
- expand ? /* @__PURE__ */ jsx37("div", { role: "cell", "data-slot": "data-table-expand-cell", className: "flex items-center justify-end pr-[var(--space-2)]", children: /* @__PURE__ */ jsx37(
7150
+ expand ? /* @__PURE__ */ jsx38("div", { role: "cell", "data-slot": "data-table-expand-cell", className: "flex items-center justify-end pr-[var(--space-2)]", children: /* @__PURE__ */ jsx38(
6938
7151
  IconButton,
6939
7152
  {
6940
7153
  icon: ChevronRight3,
@@ -6950,16 +7163,17 @@ function DataTableRowView({
6950
7163
  ),
6951
7164
  onClick: () => expand.onToggle(rowId)
6952
7165
  }
6953
- ) }) : null
7166
+ ) }) : null,
7167
+ rowActions && getRowActionsLabel ? /* @__PURE__ */ jsx38(RowActionsCell, { row, rowId, rowActions, getRowActionsLabel }) : null
6954
7168
  ]
6955
7169
  }
6956
7170
  );
6957
7171
  if (!expand) {
6958
7172
  return dataRow;
6959
7173
  }
6960
- return /* @__PURE__ */ jsxs33(Fragment15, { children: [
7174
+ return /* @__PURE__ */ jsxs34(Fragment16, { children: [
6961
7175
  dataRow,
6962
- /* @__PURE__ */ jsx37(
7176
+ /* @__PURE__ */ jsx38(
6963
7177
  "div",
6964
7178
  {
6965
7179
  role: "row",
@@ -6967,12 +7181,12 @@ function DataTableRowView({
6967
7181
  "data-row-id": rowId,
6968
7182
  "data-state": expand.expanded ? "open" : "closed",
6969
7183
  className: expandedPanelClass,
6970
- children: /* @__PURE__ */ jsx37(
7184
+ children: /* @__PURE__ */ jsx38(
6971
7185
  "div",
6972
7186
  {
6973
7187
  role: "cell",
6974
7188
  id: expand.panelId,
6975
- "aria-colspan": columns.length + (selectable ? 2 : 1),
7189
+ "aria-colspan": columns.length + (selectable ? 2 : 1) + (rowActions ? 1 : 0),
6976
7190
  className: "min-h-0 min-w-0 overflow-hidden",
6977
7191
  children: opened ? expand.render(row) : null
6978
7192
  }
@@ -6987,6 +7201,7 @@ function DataTableMobileCardView({
6987
7201
  columns,
6988
7202
  selectable,
6989
7203
  selected,
7204
+ selectionBlocked,
6990
7205
  visuallySelected,
6991
7206
  href,
6992
7207
  activatable,
@@ -6995,6 +7210,8 @@ function DataTableMobileCardView({
6995
7210
  onActivate,
6996
7211
  onRowContextMenu,
6997
7212
  expand,
7213
+ rowActions,
7214
+ getRowActionsLabel,
6998
7215
  getMobileCardContent,
6999
7216
  ariaPosInSet,
7000
7217
  ariaSetSize,
@@ -7002,15 +7219,21 @@ function DataTableMobileCardView({
7002
7219
  }) {
7003
7220
  const linked = Boolean(LinkComponent && href);
7004
7221
  const content = getMobileCardContent(row);
7222
+ let actions = content.actions;
7223
+ if (rowActions && getRowActionsLabel) {
7224
+ if (content.actions) warnCardActionsOnce();
7225
+ const items = toActionItems(rowActions(row));
7226
+ actions = items.length > 0 ? { items, label: getRowActionsLabel(row) } : void 0;
7227
+ }
7005
7228
  const navigable = linked || activatable;
7006
7229
  const opened = useOpenedOnce(expand?.expanded ?? false);
7007
- const leading = selectable || content.leading != null ? /* @__PURE__ */ jsxs33("span", { className: "flex items-center gap-[var(--space-2)]", children: [
7008
- selectable ? /* @__PURE__ */ jsx37(RowCheckbox, { row, rowId, columns, selected, onToggle }) : null,
7230
+ const leading = selectable || content.leading != null ? /* @__PURE__ */ jsxs34("span", { className: "flex items-center gap-[var(--space-2)]", children: [
7231
+ selectable ? /* @__PURE__ */ jsx38(RowCheckbox, { row, rowId, columns, selected, selectionBlocked, onToggle }) : null,
7009
7232
  content.leading
7010
7233
  ] }) : void 0;
7011
7234
  let title = content.title;
7012
7235
  if (expand) {
7013
- title = /* @__PURE__ */ jsx37(
7236
+ title = /* @__PURE__ */ jsx38(
7014
7237
  "button",
7015
7238
  {
7016
7239
  type: "button",
@@ -7020,24 +7243,24 @@ function DataTableMobileCardView({
7020
7243
  "aria-controls": expand.panelId,
7021
7244
  className: cn(rowLinkClass, "block w-full text-left"),
7022
7245
  onClick: () => expand.onToggle(rowId),
7023
- children: /* @__PURE__ */ jsx37("span", { className: "line-clamp-2", children: content.title })
7246
+ children: /* @__PURE__ */ jsx38("span", { className: "line-clamp-2", children: content.title })
7024
7247
  }
7025
7248
  );
7026
7249
  } else if (linked && LinkComponent) {
7027
- title = /* @__PURE__ */ jsx37(LinkComponent, { href, "data-slot": "data-table-row-link", className: rowLinkClass, children: content.title });
7250
+ title = /* @__PURE__ */ jsx38(LinkComponent, { href, "data-slot": "data-table-row-link", className: rowLinkClass, children: content.title });
7028
7251
  } else if (activatable) {
7029
- title = /* @__PURE__ */ jsx37(
7252
+ title = /* @__PURE__ */ jsx38(
7030
7253
  "button",
7031
7254
  {
7032
7255
  type: "button",
7033
7256
  "data-slot": "data-table-row-link",
7034
7257
  className: cn(rowLinkClass, "block w-full text-left"),
7035
7258
  onClick: (event) => onActivate(row, href, event),
7036
- children: /* @__PURE__ */ jsx37("span", { className: "line-clamp-2", children: content.title })
7259
+ children: /* @__PURE__ */ jsx38("span", { className: "line-clamp-2", children: content.title })
7037
7260
  }
7038
7261
  );
7039
7262
  }
7040
- return /* @__PURE__ */ jsxs33(
7263
+ return /* @__PURE__ */ jsxs34(
7041
7264
  "div",
7042
7265
  {
7043
7266
  "data-slot": "data-table-mobile-card",
@@ -7056,7 +7279,7 @@ function DataTableMobileCardView({
7056
7279
  ),
7057
7280
  onContextMenu: (event) => onRowContextMenu?.(rowId, event),
7058
7281
  children: [
7059
- /* @__PURE__ */ jsx37(
7282
+ /* @__PURE__ */ jsx38(
7060
7283
  ListCard,
7061
7284
  {
7062
7285
  className: cn(
@@ -7069,7 +7292,7 @@ function DataTableMobileCardView({
7069
7292
  caption: content.date,
7070
7293
  value: content.value,
7071
7294
  leading,
7072
- trailing: expand ? /* @__PURE__ */ jsx37(
7295
+ trailing: expand ? /* @__PURE__ */ jsx38(
7073
7296
  ChevronRight3,
7074
7297
  {
7075
7298
  "aria-hidden": true,
@@ -7077,17 +7300,17 @@ function DataTableMobileCardView({
7077
7300
  className: cn("block size-[var(--space-4)] shrink-0 text-text-tertiary data-[state=open]:rotate-90", expandChevronClass)
7078
7301
  }
7079
7302
  ) : navigable ? "chevron" : "none",
7080
- actions: content.actions
7303
+ actions
7081
7304
  }
7082
7305
  ),
7083
- expand ? /* @__PURE__ */ jsx37(
7306
+ expand ? /* @__PURE__ */ jsx38(
7084
7307
  "div",
7085
7308
  {
7086
7309
  id: expand.panelId,
7087
7310
  "data-slot": "data-table-expanded",
7088
7311
  "data-state": expand.expanded ? "open" : "closed",
7089
7312
  className: expandedPanelClass,
7090
- children: /* @__PURE__ */ jsx37("div", { className: "min-h-0 min-w-0 overflow-hidden", children: opened ? expand.render(row) : null })
7313
+ children: /* @__PURE__ */ jsx38("div", { className: "min-h-0 min-w-0 overflow-hidden", children: opened ? expand.render(row) : null })
7091
7314
  }
7092
7315
  ) : null
7093
7316
  ]
@@ -7416,6 +7639,7 @@ function DataTableInner({
7416
7639
  keyField,
7417
7640
  getMobileCardContent,
7418
7641
  selectable = false,
7642
+ isRowSelectable,
7419
7643
  selectedIds,
7420
7644
  onSelectionChange,
7421
7645
  selectionUnit = "\uAC1C",
@@ -7434,12 +7658,18 @@ function DataTableInner({
7434
7658
  getExpandLabel,
7435
7659
  expandedIds,
7436
7660
  onExpandedChange,
7661
+ rowActions,
7662
+ getRowActionsLabel,
7437
7663
  skeletonRowCount = 8,
7664
+ footer,
7438
7665
  "aria-label": ariaLabel = "\uB370\uC774\uD130 \uD14C\uC774\uBE14",
7439
7666
  ...props
7440
7667
  }, ref) {
7441
7668
  const virtualOptions = virtual ? virtual === true ? {} : virtual : null;
7442
7669
  const isVirtual = virtualOptions !== null;
7670
+ if (isVirtual && columns.some((column) => column.wrap)) {
7671
+ warnWrapVirtualOnce();
7672
+ }
7443
7673
  const rootRef = React33.useRef(null);
7444
7674
  const desktopRef = React33.useRef(null);
7445
7675
  const headerRef = React33.useRef(null);
@@ -7476,13 +7706,19 @@ function DataTableInner({
7476
7706
  mobile: () => mobileListRef.current ?? mobileRef.current
7477
7707
  }
7478
7708
  });
7709
+ const blockedIds = new Set(
7710
+ selectable && isRowSelectable ? data.filter((row) => !isRowSelectable(row)).map((row) => getRowId(row, keyField)) : []
7711
+ );
7712
+ const selectableRowIds = rowIds.filter((id) => !blockedIds.has(id));
7479
7713
  const resolvedSelectedIds = selectedIds ?? /* @__PURE__ */ new Set();
7480
- const selectedCount = rowIds.filter((id) => resolvedSelectedIds.has(id)).length;
7481
- const allVisibleRowsSelected = rowIds.length > 0 && selectedCount === rowIds.length;
7714
+ const selectedCount = selectableRowIds.filter((id) => resolvedSelectedIds.has(id)).length;
7715
+ const allVisibleRowsSelected = selectableRowIds.length > 0 && selectedCount === selectableRowIds.length;
7482
7716
  const partiallySelected = selectedCount > 0 && !allVisibleRowsSelected;
7483
7717
  const selectAllChecked = partiallySelected ? "indeterminate" : allVisibleRowsSelected;
7718
+ const selectAllDisabled = selectableRowIds.length === 0;
7484
7719
  const expandable = renderExpanded != null;
7485
- const gridTemplateColumns = getGridTemplate(columns, selectable, expandable);
7720
+ const hasRowActions = rowActions != null;
7721
+ const gridTemplateColumns = getGridTemplate(columns, selectable, expandable, hasRowActions);
7486
7722
  const panelIdBase = React33.useId();
7487
7723
  const [ownExpandedIds, setOwnExpandedIds] = React33.useState(() => /* @__PURE__ */ new Set());
7488
7724
  const resolvedExpandedIds = expandedIds ?? ownExpandedIds;
@@ -7499,18 +7735,22 @@ function DataTableInner({
7499
7735
  onExpandedChange?.(nextIds);
7500
7736
  };
7501
7737
  const emitSelection = (nextIds) => {
7738
+ blockedIds.forEach((id) => nextIds.delete(id));
7502
7739
  onSelectionChange?.(nextIds);
7503
7740
  };
7504
7741
  const toggleAllRows = (checked) => {
7505
7742
  const nextIds = new Set(resolvedSelectedIds);
7506
7743
  if (checked) {
7507
- rowIds.forEach((id) => nextIds.add(id));
7744
+ selectableRowIds.forEach((id) => nextIds.add(id));
7508
7745
  } else {
7509
- rowIds.forEach((id) => nextIds.delete(id));
7746
+ selectableRowIds.forEach((id) => nextIds.delete(id));
7510
7747
  }
7511
7748
  emitSelection(nextIds);
7512
7749
  };
7513
7750
  const toggleRow = (id, checked) => {
7751
+ if (blockedIds.has(id)) {
7752
+ return;
7753
+ }
7514
7754
  const nextIds = new Set(resolvedSelectedIds);
7515
7755
  if (checked) {
7516
7756
  nextIds.add(id);
@@ -7526,9 +7766,44 @@ function DataTableInner({
7526
7766
  window.location.assign(href);
7527
7767
  }
7528
7768
  };
7529
- const latestHandlers = React33.useRef({ toggleRow, activateRow, onRowContextMenu });
7769
+ const [contextMenu, setContextMenu] = React33.useState(null);
7770
+ const contextMenuKey = React33.useRef(0);
7771
+ const contextRow = contextMenu ? data.find((item) => getRowId(item, keyField) === contextMenu.rowId) : void 0;
7772
+ const contextActions = contextRow && rowActions ? rowActions(contextRow) : [];
7773
+ const contextGroups = countActions(contextActions) > 0 ? toActionGroups(contextActions) : null;
7774
+ const openRowContextMenu = (rowId, event) => {
7775
+ const row = data.find((item) => getRowId(item, keyField) === rowId);
7776
+ const actions = row && rowActions ? rowActions(row) : [];
7777
+ if (countActions(actions) === 0) {
7778
+ return;
7779
+ }
7780
+ event.preventDefault();
7781
+ contextMenuKey.current += 1;
7782
+ setContextMenu({ rowId, position: { x: event.clientX, y: event.clientY }, key: contextMenuKey.current });
7783
+ };
7784
+ const closeRowContextMenu = (item, outside) => {
7785
+ const rowId = contextMenu?.rowId;
7786
+ if (rowId !== void 0 && (item || !outside)) {
7787
+ const list = desktopListRef.current;
7788
+ const row = Array.from(list?.querySelectorAll('[data-slot="data-table-row"]') ?? []).find(
7789
+ (node) => node.getAttribute("data-row-id") === rowId
7790
+ );
7791
+ const trigger = row?.querySelector('[data-slot="data-table-row-actions"] button');
7792
+ const target = trigger ?? (row?.hasAttribute("tabindex") ? row : null) ?? list ?? desktopRef.current;
7793
+ if (target) {
7794
+ if (!target.hasAttribute("tabindex") && !target.matches("a[href],button,input")) {
7795
+ target.tabIndex = -1;
7796
+ }
7797
+ target.focus({ preventScroll: true });
7798
+ }
7799
+ }
7800
+ setContextMenu(null);
7801
+ item?.onSelect();
7802
+ };
7803
+ const handleRowContextMenu = rowActions ? openRowContextMenu : onRowContextMenu;
7804
+ const latestHandlers = React33.useRef({ toggleRow, activateRow, onRowContextMenu, handleRowContextMenu });
7530
7805
  useIsomorphicLayoutEffect(() => {
7531
- latestHandlers.current = { toggleRow, activateRow, onRowContextMenu };
7806
+ latestHandlers.current = { toggleRow, activateRow, onRowContextMenu, handleRowContextMenu };
7532
7807
  });
7533
7808
  const stableToggleRow = React33.useCallback(
7534
7809
  (id, checked) => latestHandlers.current.toggleRow(id, checked),
@@ -7542,9 +7817,14 @@ function DataTableInner({
7542
7817
  (rowId, event) => latestHandlers.current.onRowContextMenu?.(rowId, event),
7543
7818
  []
7544
7819
  );
7820
+ const stableHandleRowContextMenu = React33.useCallback(
7821
+ (rowId, event) => latestHandlers.current.handleRowContextMenu?.(rowId, event),
7822
+ []
7823
+ );
7545
7824
  const getItemProps = (row, layout, index) => {
7546
7825
  const rowId = getRowId(row, keyField);
7547
- const selected = resolvedSelectedIds.has(rowId);
7826
+ const selectionBlocked = blockedIds.has(rowId);
7827
+ const selected = !selectionBlocked && resolvedSelectedIds.has(rowId);
7548
7828
  const href = rowHref?.(row);
7549
7829
  const linked = Boolean(linkComponent && href);
7550
7830
  return {
@@ -7553,13 +7833,16 @@ function DataTableInner({
7553
7833
  columns,
7554
7834
  selectable,
7555
7835
  selected,
7556
- visuallySelected: selected || rowId === activeRowId,
7836
+ selectionBlocked,
7837
+ visuallySelected: selected || rowId === activeRowId || rowId === contextMenu?.rowId,
7557
7838
  href,
7558
7839
  activatable: !linked && Boolean(href || onRowClick),
7559
7840
  LinkComponent: linkComponent,
7560
7841
  onToggle: isVirtual ? stableToggleRow : toggleRow,
7561
7842
  onActivate: isVirtual ? stableActivateRow : activateRow,
7562
- onRowContextMenu: isVirtual ? stableRowContextMenu : onRowContextMenu,
7843
+ onRowContextMenu: layout === "desktop" ? isVirtual ? stableHandleRowContextMenu : handleRowContextMenu : isVirtual ? stableRowContextMenu : onRowContextMenu,
7844
+ rowActions,
7845
+ getRowActionsLabel,
7563
7846
  expand: renderExpanded && getExpandLabel ? {
7564
7847
  expanded: resolvedExpandedIds.has(rowId),
7565
7848
  label: getExpandLabel(row),
@@ -7597,7 +7880,7 @@ function DataTableInner({
7597
7880
  const mobileSlice = sliceFor("mobile");
7598
7881
  const RowComponent = isVirtual ? MemoDataTableRow : DataTableRowView;
7599
7882
  const CardComponent = isVirtual ? MemoDataTableMobileCard : DataTableMobileCardView;
7600
- return /* @__PURE__ */ jsxs33(
7883
+ return /* @__PURE__ */ jsxs34(
7601
7884
  "div",
7602
7885
  {
7603
7886
  ref: setRootRef,
@@ -7611,7 +7894,7 @@ function DataTableInner({
7611
7894
  ),
7612
7895
  ...props,
7613
7896
  children: [
7614
- selectable && announceSelection ? /* @__PURE__ */ jsx37(
7897
+ selectable && announceSelection ? /* @__PURE__ */ jsx38(
7615
7898
  "div",
7616
7899
  {
7617
7900
  "data-slot": "data-table-selection-status",
@@ -7620,30 +7903,30 @@ function DataTableInner({
7620
7903
  children: selectedCount > 0 ? `${selectedCount.toLocaleString("ko-KR")}${selectionUnit} \uC120\uD0DD\uB428` : ""
7621
7904
  }
7622
7905
  ) : null,
7623
- loading && data.length > 0 ? /* @__PURE__ */ jsx37(
7906
+ loading && data.length > 0 ? /* @__PURE__ */ jsx38(
7624
7907
  "div",
7625
7908
  {
7626
7909
  "data-slot": "data-table-progress",
7627
7910
  "aria-hidden": "true",
7628
7911
  className: "absolute left-0 right-0 top-0 z-10 h-[2px] overflow-hidden bg-[var(--action-selected)]",
7629
- children: /* @__PURE__ */ jsx37("div", { className: "h-full w-1/3 animate-pulse bg-[var(--primary)]" })
7912
+ children: /* @__PURE__ */ jsx38("div", { className: "h-full w-1/3 animate-pulse bg-[var(--primary)]" })
7630
7913
  }
7631
7914
  ) : null,
7632
- /* @__PURE__ */ jsx37("div", { ref: desktopRef, "data-slot": "data-table-desktop", className: "max-lg:hidden lg:block", children: /* @__PURE__ */ jsxs33(
7915
+ /* @__PURE__ */ jsx38("div", { ref: desktopRef, "data-slot": "data-table-desktop", className: cn("max-lg:hidden lg:block", fallbackFocusClass), children: /* @__PURE__ */ jsxs34(
7633
7916
  "div",
7634
7917
  {
7635
7918
  role: "table",
7636
7919
  "aria-label": ariaLabel,
7637
7920
  "aria-rowcount": isVirtual && data.length > 0 ? data.length + 1 : void 0,
7638
7921
  children: [
7639
- /* @__PURE__ */ jsxs33(
7922
+ /* @__PURE__ */ jsxs34(
7640
7923
  "div",
7641
7924
  {
7642
7925
  ref: headerRef,
7643
7926
  "data-slot": "data-table-header",
7644
7927
  role: "row",
7645
7928
  className: cn(
7646
- "grid min-h-[40px] items-center bg-[var(--bg-raised)] text-[12px] font-semibold uppercase leading-snug text-text-tertiary",
7929
+ "grid min-h-[40px] items-center bg-[var(--bg-raised)] text-[12px] font-semibold leading-snug text-text-tertiary",
7647
7930
  // Virtual lists are long: the header sticks inside the scroll container,
7648
7931
  // below an inline BulkActionBar band (40px, --z-sticky) rendered before
7649
7932
  // the table — band on top, header under it, rows beneath both.
@@ -7651,12 +7934,12 @@ function DataTableInner({
7651
7934
  ),
7652
7935
  style: { gridTemplateColumns },
7653
7936
  children: [
7654
- selectable ? /* @__PURE__ */ jsx37("div", { role: "columnheader", className: "px-[var(--space-4)]", children: /* @__PURE__ */ jsx37(SelectAllCheckbox, { checked: selectAllChecked, onToggleAll: toggleAllRows }) }) : null,
7937
+ selectable ? /* @__PURE__ */ jsx38("div", { role: "columnheader", className: "px-[var(--space-4)]", children: /* @__PURE__ */ jsx38(SelectAllCheckbox, { checked: selectAllChecked, disabled: selectAllDisabled, onToggleAll: toggleAllRows }) }) : null,
7655
7938
  columns.map((column) => {
7656
7939
  const align = column.align ?? "left";
7657
7940
  const nextSort = getNextSort(sortBy, column.key);
7658
7941
  const ariaSort = sortBy?.key === column.key ? sortBy.dir === "asc" ? "ascending" : "descending" : void 0;
7659
- return /* @__PURE__ */ jsx37(
7942
+ return /* @__PURE__ */ jsx38(
7660
7943
  "div",
7661
7944
  {
7662
7945
  role: "columnheader",
@@ -7665,7 +7948,7 @@ function DataTableInner({
7665
7948
  "flex min-w-0 items-center gap-[var(--space-1)] px-[var(--space-4)] py-[var(--space-2)]",
7666
7949
  alignmentClass[align]
7667
7950
  ),
7668
- children: column.sortable ? /* @__PURE__ */ jsxs33(
7951
+ children: column.sortable ? /* @__PURE__ */ jsxs34(
7669
7952
  "button",
7670
7953
  {
7671
7954
  type: "button",
@@ -7676,20 +7959,21 @@ function DataTableInner({
7676
7959
  ),
7677
7960
  onClick: () => onSortChange?.(column.key, nextSort),
7678
7961
  children: [
7679
- /* @__PURE__ */ jsx37("span", { className: "truncate", children: column.header }),
7680
- /* @__PURE__ */ jsx37(SortIcon, { sort: sortBy, columnKey: column.key })
7962
+ /* @__PURE__ */ jsx38("span", { className: column.hideHeader ? "sr-only" : "truncate", children: column.header }),
7963
+ /* @__PURE__ */ jsx38(SortIcon, { sort: sortBy, columnKey: column.key })
7681
7964
  ]
7682
7965
  }
7683
- ) : /* @__PURE__ */ jsx37("span", { className: "truncate", children: column.header })
7966
+ ) : /* @__PURE__ */ jsx38("span", { className: column.hideHeader ? "sr-only" : "truncate", children: column.header })
7684
7967
  },
7685
7968
  column.key
7686
7969
  );
7687
7970
  }),
7688
- expandable ? /* @__PURE__ */ jsx37("div", { role: "cell" }) : null
7971
+ expandable ? /* @__PURE__ */ jsx38("div", { role: "cell" }) : null,
7972
+ hasRowActions ? /* @__PURE__ */ jsx38("div", { role: "cell" }) : null
7689
7973
  ]
7690
7974
  }
7691
7975
  ),
7692
- loading && data.length === 0 ? /* @__PURE__ */ jsx37(
7976
+ loading && data.length === 0 ? /* @__PURE__ */ jsx38(
7693
7977
  SkeletonRows,
7694
7978
  {
7695
7979
  columns,
@@ -7700,7 +7984,7 @@ function DataTableInner({
7700
7984
  ) : data.length === 0 ? (
7701
7985
  /* role="table" 직계 자식은 row/rowgroup이어야 한다. data-slot과 테두리는
7702
7986
  그대로 유지해 시각 계약을 깨지 않는다(빈 상태에서도 표가 테두리를 그린다). */
7703
- /* @__PURE__ */ jsx37("div", { role: "rowgroup", children: /* @__PURE__ */ jsx37("div", { role: "row", children: /* @__PURE__ */ jsx37(
7987
+ /* @__PURE__ */ jsx38("div", { role: "rowgroup", children: /* @__PURE__ */ jsx38("div", { role: "row", children: /* @__PURE__ */ jsx38(
7704
7988
  "div",
7705
7989
  {
7706
7990
  role: "cell",
@@ -7710,9 +7994,9 @@ function DataTableInner({
7710
7994
  children: emptyState
7711
7995
  }
7712
7996
  ) }) })
7713
- ) : /* @__PURE__ */ jsx37("div", { ref: desktopListRef, role: "rowgroup", style: desktopSlice.style, children: desktopSlice.rows.map((row, index) => {
7997
+ ) : /* @__PURE__ */ jsx38("div", { ref: desktopListRef, role: "rowgroup", className: fallbackFocusClass, style: desktopSlice.style, children: desktopSlice.rows.map((row, index) => {
7714
7998
  const itemProps = getItemProps(row, "desktop", desktopSlice.start + index);
7715
- return /* @__PURE__ */ jsx37(
7999
+ return /* @__PURE__ */ jsx38(
7716
8000
  RowComponent,
7717
8001
  {
7718
8002
  ...itemProps,
@@ -7725,8 +8009,8 @@ function DataTableInner({
7725
8009
  ]
7726
8010
  }
7727
8011
  ) }),
7728
- /* @__PURE__ */ jsxs33("div", { ref: mobileRef, "data-slot": "data-table-mobile", className: "lg:hidden", children: [
7729
- /* @__PURE__ */ jsx37(
8012
+ /* @__PURE__ */ jsxs34("div", { ref: mobileRef, "data-slot": "data-table-mobile", className: "lg:hidden", children: [
8013
+ /* @__PURE__ */ jsx38(
7730
8014
  MobileToolbar,
7731
8015
  {
7732
8016
  columns,
@@ -7734,10 +8018,11 @@ function DataTableInner({
7734
8018
  onSortChange,
7735
8019
  selectable,
7736
8020
  selectAllChecked,
8021
+ selectAllDisabled,
7737
8022
  onToggleAll: toggleAllRows
7738
8023
  }
7739
8024
  ),
7740
- loading && data.length === 0 ? /* @__PURE__ */ jsx37(MobileSkeletonCards, { count: skeletonRowCount }) : data.length === 0 ? /* @__PURE__ */ jsx37("div", { "data-slot": "data-table-mobile-empty", className: "border-t border-[var(--border-subtle)] p-[var(--space-4)]", children: emptyState }) : /* @__PURE__ */ jsx37(
8025
+ loading && data.length === 0 ? /* @__PURE__ */ jsx38(MobileSkeletonCards, { count: skeletonRowCount }) : data.length === 0 ? /* @__PURE__ */ jsx38("div", { "data-slot": "data-table-mobile-empty", className: "border-t border-[var(--border-subtle)] p-[var(--space-4)]", children: emptyState }) : /* @__PURE__ */ jsx38(
7741
8026
  "div",
7742
8027
  {
7743
8028
  ref: mobileListRef,
@@ -7748,7 +8033,7 @@ function DataTableInner({
7748
8033
  children: mobileSlice.rows.map((row, index) => {
7749
8034
  const rowIndex = mobileSlice.start + index;
7750
8035
  const itemProps = getItemProps(row, "mobile", rowIndex);
7751
- return /* @__PURE__ */ jsx37(
8036
+ return /* @__PURE__ */ jsx38(
7752
8037
  CardComponent,
7753
8038
  {
7754
8039
  ...itemProps,
@@ -7762,7 +8047,17 @@ function DataTableInner({
7762
8047
  })
7763
8048
  }
7764
8049
  )
7765
- ] })
8050
+ ] }),
8051
+ footer != null ? /* @__PURE__ */ jsx38("div", { "data-slot": "data-table-footer", className: "border-t border-[var(--border-subtle)] empty:hidden", children: footer }) : null,
8052
+ hasRowActions ? /* @__PURE__ */ jsx38(
8053
+ RowContextMenu,
8054
+ {
8055
+ openKey: contextMenu?.key ?? null,
8056
+ position: contextMenu?.position ?? null,
8057
+ groups: contextGroups,
8058
+ onClose: closeRowContextMenu
8059
+ }
8060
+ ) : null
7766
8061
  ]
7767
8062
  }
7768
8063
  );
@@ -7770,37 +8065,6 @@ function DataTableInner({
7770
8065
  var DataTable = React33.forwardRef(DataTableInner);
7771
8066
  DataTable.displayName = "DataTable";
7772
8067
 
7773
- // src/components/ui/context-menu.tsx
7774
- import { jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
7775
- function ContextMenu({
7776
- open,
7777
- onOpenChange,
7778
- position,
7779
- children,
7780
- contentProps
7781
- }) {
7782
- if (!position) {
7783
- return null;
7784
- }
7785
- return /* @__PURE__ */ jsxs34(DropdownMenu, { open, onOpenChange, modal: false, children: [
7786
- /* @__PURE__ */ jsx38(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx38(
7787
- "span",
7788
- {
7789
- "aria-hidden": "true",
7790
- "data-slot": "context-menu-anchor",
7791
- style: {
7792
- position: "fixed",
7793
- left: position.x,
7794
- top: position.y,
7795
- width: 0,
7796
- height: 0
7797
- }
7798
- }
7799
- ) }),
7800
- /* @__PURE__ */ jsx38(DropdownMenuContent, { ...contentProps, children })
7801
- ] });
7802
- }
7803
-
7804
8068
  // src/components/ui/bulk-action-bar.tsx
7805
8069
  import * as React34 from "react";
7806
8070
  import { X as X4 } from "lucide-react";
@@ -9443,9 +9707,97 @@ var Pagination = React43.forwardRef(
9443
9707
  );
9444
9708
  Pagination.displayName = "Pagination";
9445
9709
 
9710
+ // src/components/ui/table-pagination.tsx
9711
+ import { ChevronLeft as ChevronLeft2, ChevronRight as ChevronRight5 } from "lucide-react";
9712
+ import { jsx as jsx55, jsxs as jsxs43 } from "react/jsx-runtime";
9713
+ var TABLE_PAGE_SIZE_OPTIONS = [20, 50, 100];
9714
+ function shouldHideTablePagination({
9715
+ rangeEnd,
9716
+ total,
9717
+ hasPrev,
9718
+ hasNext,
9719
+ pageSizeOptions = TABLE_PAGE_SIZE_OPTIONS
9720
+ }) {
9721
+ const smallest = Math.min(...pageSizeOptions);
9722
+ if (total !== void 0) return total <= smallest;
9723
+ return !hasPrev && !hasNext && rangeEnd <= smallest;
9724
+ }
9725
+ var formatCount = (value) => value.toLocaleString("ko-KR");
9726
+ function TablePagination({
9727
+ pageSize,
9728
+ onPageSizeChange,
9729
+ pageSizeOptions = TABLE_PAGE_SIZE_OPTIONS,
9730
+ rangeStart,
9731
+ rangeEnd,
9732
+ total,
9733
+ unit = "\uAC1C",
9734
+ hasPrev,
9735
+ hasNext,
9736
+ onPrev,
9737
+ onNext,
9738
+ loading = false,
9739
+ "aria-label": ariaLabel = "\uD398\uC774\uC9C0\uB124\uC774\uC158"
9740
+ }) {
9741
+ if (shouldHideTablePagination({ rangeEnd, total, hasPrev, hasNext, pageSizeOptions })) return null;
9742
+ return /* @__PURE__ */ jsxs43(
9743
+ "nav",
9744
+ {
9745
+ "data-slot": "table-pagination",
9746
+ "aria-label": ariaLabel,
9747
+ className: "@container flex min-h-[48px] items-center justify-between gap-[var(--space-3)] px-[var(--space-4)] text-sm text-text-secondary",
9748
+ children: [
9749
+ /* @__PURE__ */ jsx55(
9750
+ PageSizeSelect,
9751
+ {
9752
+ value: pageSize,
9753
+ onChange: onPageSizeChange,
9754
+ options: pageSizeOptions,
9755
+ size: "compact",
9756
+ className: "shrink-0 max-lg:[&>span:first-child]:hidden"
9757
+ }
9758
+ ),
9759
+ /* @__PURE__ */ jsxs43("div", { className: "flex min-w-0 items-center gap-[var(--space-2)]", children: [
9760
+ /* @__PURE__ */ jsxs43("span", { "data-slot": "table-pagination-range", className: "whitespace-nowrap tabular-nums", children: [
9761
+ /* @__PURE__ */ jsxs43("span", { className: "font-medium text-text-primary", children: [
9762
+ formatCount(rangeStart),
9763
+ "\u2013",
9764
+ formatCount(rangeEnd)
9765
+ ] }),
9766
+ total !== void 0 ? /* @__PURE__ */ jsx55("span", { "data-slot": "table-pagination-total", className: "text-text-tertiary @max-[400px]:hidden", children: ` / \uCD1D ${formatCount(total)}${unit}` }) : null
9767
+ ] }),
9768
+ /* @__PURE__ */ jsxs43("div", { className: "flex shrink-0 items-center gap-[var(--space-1)]", children: [
9769
+ /* @__PURE__ */ jsx55(
9770
+ IconButton,
9771
+ {
9772
+ icon: ChevronLeft2,
9773
+ "aria-label": "\uC774\uC804 \uD398\uC774\uC9C0",
9774
+ appearance: "outline",
9775
+ tone: "neutral",
9776
+ disabled: loading || !hasPrev,
9777
+ onClick: onPrev
9778
+ }
9779
+ ),
9780
+ /* @__PURE__ */ jsx55(
9781
+ IconButton,
9782
+ {
9783
+ icon: ChevronRight5,
9784
+ "aria-label": "\uB2E4\uC74C \uD398\uC774\uC9C0",
9785
+ appearance: "outline",
9786
+ tone: "neutral",
9787
+ disabled: loading || !hasNext,
9788
+ onClick: onNext
9789
+ }
9790
+ )
9791
+ ] })
9792
+ ] })
9793
+ ]
9794
+ }
9795
+ );
9796
+ }
9797
+
9446
9798
  // src/components/ui/mode-toggle.tsx
9447
9799
  import { cva as cva19 } from "class-variance-authority";
9448
- import { jsx as jsx55, jsxs as jsxs43 } from "react/jsx-runtime";
9800
+ import { jsx as jsx56, jsxs as jsxs44 } from "react/jsx-runtime";
9449
9801
  var modeToggleVariants = cva19(
9450
9802
  [
9451
9803
  "inline-flex items-center rounded-[var(--radius-md)] border border-[var(--border-subtle)]",
@@ -9476,7 +9828,7 @@ function ModeToggle({
9476
9828
  onChange,
9477
9829
  ...props
9478
9830
  }) {
9479
- return /* @__PURE__ */ jsx55(
9831
+ return /* @__PURE__ */ jsx56(
9480
9832
  "div",
9481
9833
  {
9482
9834
  role: "group",
@@ -9486,7 +9838,7 @@ function ModeToggle({
9486
9838
  children: options.map((option) => {
9487
9839
  const Icon = option.icon;
9488
9840
  const isActive = option.value === value;
9489
- return /* @__PURE__ */ jsxs43(
9841
+ return /* @__PURE__ */ jsxs44(
9490
9842
  "button",
9491
9843
  {
9492
9844
  type: "button",
@@ -9502,8 +9854,8 @@ function ModeToggle({
9502
9854
  }
9503
9855
  },
9504
9856
  children: [
9505
- Icon ? /* @__PURE__ */ jsx55(Icon, { "aria-hidden": "true", "data-slot": "mode-toggle-icon" }) : null,
9506
- /* @__PURE__ */ jsx55("span", { children: option.label })
9857
+ Icon ? /* @__PURE__ */ jsx56(Icon, { "aria-hidden": "true", "data-slot": "mode-toggle-icon" }) : null,
9858
+ /* @__PURE__ */ jsx56("span", { children: option.label })
9507
9859
  ]
9508
9860
  },
9509
9861
  option.value
@@ -9516,7 +9868,7 @@ function ModeToggle({
9516
9868
  // src/components/ui/action-footer.tsx
9517
9869
  import * as React44 from "react";
9518
9870
  import { cva as cva20 } from "class-variance-authority";
9519
- import { jsx as jsx56, jsxs as jsxs44 } from "react/jsx-runtime";
9871
+ import { jsx as jsx57, jsxs as jsxs45 } from "react/jsx-runtime";
9520
9872
  var actionFooterVariants = cva20(
9521
9873
  [
9522
9874
  // Below sm: two fixed rows — destructive actions (start) and status (end) on top, the main
@@ -9600,7 +9952,7 @@ function renderAction(action, className) {
9600
9952
  };
9601
9953
  const style = actionStyle(action);
9602
9954
  if (action.leadingIcon) {
9603
- return /* @__PURE__ */ jsx56(
9955
+ return /* @__PURE__ */ jsx57(
9604
9956
  IconButton,
9605
9957
  {
9606
9958
  ...common,
@@ -9613,7 +9965,7 @@ function renderAction(action, className) {
9613
9965
  key
9614
9966
  );
9615
9967
  }
9616
- return /* @__PURE__ */ jsx56(Button, { ...common, ...style, size: "lg", loading: action.loading, children: action.label }, key);
9968
+ return /* @__PURE__ */ jsx57(Button, { ...common, ...style, size: "lg", loading: action.loading, children: action.label }, key);
9617
9969
  }
9618
9970
  var ActionFooter = React44.forwardRef(
9619
9971
  ({
@@ -9628,7 +9980,7 @@ var ActionFooter = React44.forwardRef(
9628
9980
  const visibleActions = actions.filter((action) => canRenderAction(action, permissions));
9629
9981
  const destructiveActions = visibleActions.filter(isDestructive);
9630
9982
  const mainActions = sortMainActions(visibleActions.filter((action) => !isDestructive(action)));
9631
- return /* @__PURE__ */ jsxs44(
9983
+ return /* @__PURE__ */ jsxs45(
9632
9984
  "div",
9633
9985
  {
9634
9986
  ref,
@@ -9637,7 +9989,7 @@ var ActionFooter = React44.forwardRef(
9637
9989
  className: cn(actionFooterVariants({ position, surface, className })),
9638
9990
  ...props,
9639
9991
  children: [
9640
- destructiveActions.length > 0 ? /* @__PURE__ */ jsx56(
9992
+ destructiveActions.length > 0 ? /* @__PURE__ */ jsx57(
9641
9993
  "div",
9642
9994
  {
9643
9995
  "data-slot": "action-footer-destructive-actions",
@@ -9645,7 +9997,7 @@ var ActionFooter = React44.forwardRef(
9645
9997
  children: destructiveActions.map((action) => renderAction(action))
9646
9998
  }
9647
9999
  ) : null,
9648
- status ? /* @__PURE__ */ jsxs44(
10000
+ status ? /* @__PURE__ */ jsxs45(
9649
10001
  "div",
9650
10002
  {
9651
10003
  "data-slot": "action-footer-status",
@@ -9653,7 +10005,7 @@ var ActionFooter = React44.forwardRef(
9653
10005
  "aria-live": "polite",
9654
10006
  className: cn(actionFooterStatusVariants({ kind: status.kind })),
9655
10007
  children: [
9656
- /* @__PURE__ */ jsx56(
10008
+ /* @__PURE__ */ jsx57(
9657
10009
  "span",
9658
10010
  {
9659
10011
  "aria-hidden": "true",
@@ -9661,11 +10013,11 @@ var ActionFooter = React44.forwardRef(
9661
10013
  className: "size-[6px] shrink-0 rounded-[var(--radius-full)]"
9662
10014
  }
9663
10015
  ),
9664
- /* @__PURE__ */ jsx56("span", { className: "truncate", children: getStatusLabel(status) })
10016
+ /* @__PURE__ */ jsx57("span", { className: "truncate", children: getStatusLabel(status) })
9665
10017
  ]
9666
10018
  }
9667
10019
  ) : null,
9668
- /* @__PURE__ */ jsx56(
10020
+ /* @__PURE__ */ jsx57(
9669
10021
  "div",
9670
10022
  {
9671
10023
  "data-slot": "action-footer-main-actions",
@@ -9687,7 +10039,7 @@ ActionFooter.displayName = "ActionFooter";
9687
10039
  // src/components/ui/toast.tsx
9688
10040
  import * as React45 from "react";
9689
10041
  import { cva as cva21 } from "class-variance-authority";
9690
- import { jsx as jsx57, jsxs as jsxs45 } from "react/jsx-runtime";
10042
+ import { jsx as jsx58, jsxs as jsxs46 } from "react/jsx-runtime";
9691
10043
  var DOT3 = {
9692
10044
  default: "var(--neutral)",
9693
10045
  success: "var(--success)",
@@ -9834,7 +10186,7 @@ var ToastRoot = React45.forwardRef(
9834
10186
  timerRef.current = null;
9835
10187
  };
9836
10188
  }, [durationMs]);
9837
- return /* @__PURE__ */ jsxs45(
10189
+ return /* @__PURE__ */ jsxs46(
9838
10190
  "div",
9839
10191
  {
9840
10192
  ref,
@@ -9862,7 +10214,7 @@ var ToastRoot = React45.forwardRef(
9862
10214
  },
9863
10215
  ...props,
9864
10216
  children: [
9865
- /* @__PURE__ */ jsx57(
10217
+ /* @__PURE__ */ jsx58(
9866
10218
  "span",
9867
10219
  {
9868
10220
  "aria-hidden": "true",
@@ -9871,8 +10223,8 @@ var ToastRoot = React45.forwardRef(
9871
10223
  style: { background: DOT3[variant] ?? DOT3.default }
9872
10224
  }
9873
10225
  ),
9874
- /* @__PURE__ */ jsxs45("div", { "data-slot": "toast-body", className: "min-w-0 flex-1", children: [
9875
- /* @__PURE__ */ jsx57(
10226
+ /* @__PURE__ */ jsxs46("div", { "data-slot": "toast-body", className: "min-w-0 flex-1", children: [
10227
+ /* @__PURE__ */ jsx58(
9876
10228
  "div",
9877
10229
  {
9878
10230
  "data-slot": "toast-message",
@@ -9880,7 +10232,7 @@ var ToastRoot = React45.forwardRef(
9880
10232
  children: message
9881
10233
  }
9882
10234
  ),
9883
- description ? /* @__PURE__ */ jsx57(
10235
+ description ? /* @__PURE__ */ jsx58(
9884
10236
  "div",
9885
10237
  {
9886
10238
  "data-slot": "toast-description",
@@ -9889,8 +10241,8 @@ var ToastRoot = React45.forwardRef(
9889
10241
  }
9890
10242
  ) : null
9891
10243
  ] }),
9892
- /* @__PURE__ */ jsxs45("div", { "data-slot": "toast-actions", className: "flex shrink-0 items-center gap-[2px]", children: [
9893
- action ? /* @__PURE__ */ jsx57(
10244
+ /* @__PURE__ */ jsxs46("div", { "data-slot": "toast-actions", className: "flex shrink-0 items-center gap-[2px]", children: [
10245
+ action ? /* @__PURE__ */ jsx58(
9894
10246
  Button,
9895
10247
  {
9896
10248
  "data-slot": "toast-action",
@@ -9901,7 +10253,7 @@ var ToastRoot = React45.forwardRef(
9901
10253
  children: action.label
9902
10254
  }
9903
10255
  ) : null,
9904
- /* @__PURE__ */ jsx57(
10256
+ /* @__PURE__ */ jsx58(
9905
10257
  "button",
9906
10258
  {
9907
10259
  type: "button",
@@ -9923,7 +10275,7 @@ var ToastRoot = React45.forwardRef(
9923
10275
  }
9924
10276
  );
9925
10277
  ToastRoot.displayName = "ToastRoot";
9926
- var ToastViewport = React45.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx57(
10278
+ var ToastViewport = React45.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx58(
9927
10279
  "ol",
9928
10280
  {
9929
10281
  ref,
@@ -9941,9 +10293,9 @@ function ToastProvider({ children, maxToasts = 3, className, ...props }) {
9941
10293
  }),
9942
10294
  [maxToasts]
9943
10295
  );
9944
- return /* @__PURE__ */ jsxs45("div", { "data-slot": "toast-provider", className, ...props, children: [
10296
+ return /* @__PURE__ */ jsxs46("div", { "data-slot": "toast-provider", className, ...props, children: [
9945
10297
  children,
9946
- /* @__PURE__ */ jsx57(ToastViewport, { children: items.map((item) => /* @__PURE__ */ jsx57("li", { children: /* @__PURE__ */ jsx57(ToastRoot, { ...item, onClose: () => toast.dismiss(item.id) }) }, item.id)) })
10298
+ /* @__PURE__ */ jsx58(ToastViewport, { children: items.map((item) => /* @__PURE__ */ jsx58("li", { children: /* @__PURE__ */ jsx58(ToastRoot, { ...item, onClose: () => toast.dismiss(item.id) }) }, item.id)) })
9947
10299
  ] });
9948
10300
  }
9949
10301
 
@@ -9951,7 +10303,7 @@ function ToastProvider({ children, maxToasts = 3, className, ...props }) {
9951
10303
  import * as React46 from "react";
9952
10304
  import { cva as cva22 } from "class-variance-authority";
9953
10305
  import { AlertCircle as AlertCircle4 } from "lucide-react";
9954
- import { Fragment as Fragment16, jsx as jsx58, jsxs as jsxs46 } from "react/jsx-runtime";
10306
+ import { Fragment as Fragment17, jsx as jsx59, jsxs as jsxs47 } from "react/jsx-runtime";
9955
10307
  var otpFieldVariants = cva22("flex w-full min-w-0 flex-col gap-[var(--space-3)]", {
9956
10308
  variants: {
9957
10309
  size: {
@@ -10136,7 +10488,7 @@ var OTPField = React46.forwardRef(
10136
10488
  },
10137
10489
  [disabled, isControlled, length, onComplete, onValueChange]
10138
10490
  );
10139
- return /* @__PURE__ */ jsxs46(
10491
+ return /* @__PURE__ */ jsxs47(
10140
10492
  "fieldset",
10141
10493
  {
10142
10494
  ref,
@@ -10149,7 +10501,7 @@ var OTPField = React46.forwardRef(
10149
10501
  className: cn(otpFieldVariants({ size, className })),
10150
10502
  ...props,
10151
10503
  children: [
10152
- /* @__PURE__ */ jsxs46(
10504
+ /* @__PURE__ */ jsxs47(
10153
10505
  "legend",
10154
10506
  {
10155
10507
  id: labelId,
@@ -10157,11 +10509,11 @@ var OTPField = React46.forwardRef(
10157
10509
  className: "text-sm font-medium leading-snug text-foreground",
10158
10510
  children: [
10159
10511
  label,
10160
- required ? /* @__PURE__ */ jsx58("span", { "aria-hidden": "true", className: "ml-1 font-bold text-[var(--error)]", children: "*" }) : null
10512
+ required ? /* @__PURE__ */ jsx59("span", { "aria-hidden": "true", className: "ml-1 font-bold text-[var(--error)]", children: "*" }) : null
10161
10513
  ]
10162
10514
  }
10163
10515
  ),
10164
- /* @__PURE__ */ jsx58(
10516
+ /* @__PURE__ */ jsx59(
10165
10517
  "div",
10166
10518
  {
10167
10519
  "data-slot": "otp-field-group",
@@ -10171,7 +10523,7 @@ var OTPField = React46.forwardRef(
10171
10523
  children: Array.from({ length }, (_, index) => {
10172
10524
  const digit = resolvedSlots[index] ?? "";
10173
10525
  const inputId = `${fieldId}-cell-${index + 1}`;
10174
- return /* @__PURE__ */ jsx58(
10526
+ return /* @__PURE__ */ jsx59(
10175
10527
  "input",
10176
10528
  {
10177
10529
  ref: (node) => {
@@ -10266,15 +10618,15 @@ var OTPField = React46.forwardRef(
10266
10618
  })
10267
10619
  }
10268
10620
  ),
10269
- helperText || errorText ? /* @__PURE__ */ jsx58(
10621
+ helperText || errorText ? /* @__PURE__ */ jsx59(
10270
10622
  "p",
10271
10623
  {
10272
10624
  id: errorText ? errorId : helperId,
10273
10625
  "data-slot": "otp-field-message",
10274
10626
  "data-kind": errorText ? "error" : "helper",
10275
10627
  className: otpFieldMessageVariants({ state: resolvedState }),
10276
- children: errorText ? /* @__PURE__ */ jsxs46(Fragment16, { children: [
10277
- /* @__PURE__ */ jsx58(
10628
+ children: errorText ? /* @__PURE__ */ jsxs47(Fragment17, { children: [
10629
+ /* @__PURE__ */ jsx59(
10278
10630
  AlertCircle4,
10279
10631
  {
10280
10632
  "aria-hidden": "true",
@@ -10282,11 +10634,11 @@ var OTPField = React46.forwardRef(
10282
10634
  strokeWidth: 2
10283
10635
  }
10284
10636
  ),
10285
- /* @__PURE__ */ jsx58("span", { children: errorText })
10286
- ] }) : /* @__PURE__ */ jsx58("span", { children: helperText })
10637
+ /* @__PURE__ */ jsx59("span", { children: errorText })
10638
+ ] }) : /* @__PURE__ */ jsx59("span", { children: helperText })
10287
10639
  }
10288
10640
  ) : null,
10289
- name ? /* @__PURE__ */ jsx58(
10641
+ name ? /* @__PURE__ */ jsx59(
10290
10642
  "input",
10291
10643
  {
10292
10644
  "aria-hidden": "true",
@@ -10310,7 +10662,7 @@ OTPField.displayName = "OTPField";
10310
10662
  import * as React47 from "react";
10311
10663
  import { Search, X as X5 } from "lucide-react";
10312
10664
  import { cva as cva23 } from "class-variance-authority";
10313
- import { jsx as jsx59, jsxs as jsxs47 } from "react/jsx-runtime";
10665
+ import { jsx as jsx60, jsxs as jsxs48 } from "react/jsx-runtime";
10314
10666
  var searchFieldVariants = cva23("relative flex w-full items-center", {
10315
10667
  variants: {
10316
10668
  size: {
@@ -10409,14 +10761,14 @@ var SearchField = React47.forwardRef(
10409
10761
  }
10410
10762
  onClear?.();
10411
10763
  };
10412
- return /* @__PURE__ */ jsxs47(
10764
+ return /* @__PURE__ */ jsxs48(
10413
10765
  "div",
10414
10766
  {
10415
10767
  "data-slot": "search-field",
10416
10768
  "data-size": resolvedSize,
10417
10769
  className: cn(searchFieldVariants({ size, className })),
10418
10770
  children: [
10419
- /* @__PURE__ */ jsx59(
10771
+ /* @__PURE__ */ jsx60(
10420
10772
  Search,
10421
10773
  {
10422
10774
  "aria-hidden": "true",
@@ -10426,7 +10778,7 @@ var SearchField = React47.forwardRef(
10426
10778
  strokeWidth: resolvedSize === "sm" ? 2 : 1.75
10427
10779
  }
10428
10780
  ),
10429
- /* @__PURE__ */ jsx59(
10781
+ /* @__PURE__ */ jsx60(
10430
10782
  "input",
10431
10783
  {
10432
10784
  ref: inputRef,
@@ -10447,7 +10799,7 @@ var SearchField = React47.forwardRef(
10447
10799
  ...props
10448
10800
  }
10449
10801
  ),
10450
- showClear ? /* @__PURE__ */ jsx59(
10802
+ showClear ? /* @__PURE__ */ jsx60(
10451
10803
  "button",
10452
10804
  {
10453
10805
  type: "button",
@@ -10455,7 +10807,7 @@ var SearchField = React47.forwardRef(
10455
10807
  "data-slot": "search-field-clear",
10456
10808
  className: "absolute right-[8px] top-1/2 inline-flex size-[var(--space-4)] -translate-y-1/2 cursor-pointer items-center justify-center rounded-[var(--radius-full)] text-text-tertiary transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)]",
10457
10809
  onClick: clearInput,
10458
- children: /* @__PURE__ */ jsx59(X5, { "aria-hidden": "true", size: 16, strokeWidth: 1.75 })
10810
+ children: /* @__PURE__ */ jsx60(X5, { "aria-hidden": "true", size: 16, strokeWidth: 1.75 })
10459
10811
  }
10460
10812
  ) : null
10461
10813
  ]
@@ -10468,7 +10820,7 @@ SearchField.displayName = "SearchField";
10468
10820
  // src/components/ui/checkbox-group.tsx
10469
10821
  import * as React48 from "react";
10470
10822
  import { cva as cva24 } from "class-variance-authority";
10471
- import { jsx as jsx60 } from "react/jsx-runtime";
10823
+ import { jsx as jsx61 } from "react/jsx-runtime";
10472
10824
  var checkboxGroupVariants = cva24("gap-[var(--space-2)]", {
10473
10825
  variants: {
10474
10826
  appearance: {
@@ -10544,7 +10896,7 @@ var CheckboxGroup = React48.forwardRef(
10544
10896
  }),
10545
10897
  [appearance, density, disabled, name, selectedValues, toggleValue]
10546
10898
  );
10547
- return /* @__PURE__ */ jsx60(CheckboxGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx60(
10899
+ return /* @__PURE__ */ jsx61(CheckboxGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx61(
10548
10900
  "div",
10549
10901
  {
10550
10902
  ref,
@@ -10572,7 +10924,7 @@ import * as React49 from "react";
10572
10924
  import { cva as cva25 } from "class-variance-authority";
10573
10925
  import { Circle } from "lucide-react";
10574
10926
  import { RadioGroup as RadioGroupPrimitive } from "radix-ui";
10575
- import { jsx as jsx61, jsxs as jsxs48 } from "react/jsx-runtime";
10927
+ import { jsx as jsx62, jsxs as jsxs49 } from "react/jsx-runtime";
10576
10928
  var radioGroupVariants = cva25("gap-[var(--space-2)]", {
10577
10929
  variants: {
10578
10930
  appearance: {
@@ -10680,7 +11032,7 @@ var RadioGroup = React49.forwardRef(
10680
11032
  () => ({ appearance, density }),
10681
11033
  [appearance, density]
10682
11034
  );
10683
- return /* @__PURE__ */ jsx61(RadioGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx61(
11035
+ return /* @__PURE__ */ jsx62(RadioGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx62(
10684
11036
  RadioGroupPrimitive.Root,
10685
11037
  {
10686
11038
  ref,
@@ -10709,7 +11061,7 @@ var Radio = React49.forwardRef(({ className, children, description, id, ...props
10709
11061
  const radioId = id ?? generatedId;
10710
11062
  const labelId = `${radioId}-label`;
10711
11063
  const descriptionId = description ? `${radioId}-description` : void 0;
10712
- return /* @__PURE__ */ jsxs48(
11064
+ return /* @__PURE__ */ jsxs49(
10713
11065
  RadioGroupPrimitive.Item,
10714
11066
  {
10715
11067
  ref,
@@ -10720,24 +11072,24 @@ var Radio = React49.forwardRef(({ className, children, description, id, ...props
10720
11072
  className: cn(radioVariants({ appearance, density }), className),
10721
11073
  ...props,
10722
11074
  children: [
10723
- /* @__PURE__ */ jsx61(
11075
+ /* @__PURE__ */ jsx62(
10724
11076
  "span",
10725
11077
  {
10726
11078
  "aria-hidden": "true",
10727
11079
  "data-slot": "radio-control",
10728
11080
  className: radioControlVariants({ appearance }),
10729
- children: /* @__PURE__ */ jsx61(
11081
+ children: /* @__PURE__ */ jsx62(
10730
11082
  RadioGroupPrimitive.Indicator,
10731
11083
  {
10732
11084
  "data-slot": "radio-indicator",
10733
11085
  className: "flex items-center justify-center",
10734
- children: /* @__PURE__ */ jsx61(Circle, { "aria-hidden": "true", size: 8, fill: "currentColor" })
11086
+ children: /* @__PURE__ */ jsx62(Circle, { "aria-hidden": "true", size: 8, fill: "currentColor" })
10735
11087
  }
10736
11088
  )
10737
11089
  }
10738
11090
  ),
10739
- /* @__PURE__ */ jsxs48("span", { className: "flex min-w-0 flex-col gap-[var(--space-1)]", children: [
10740
- /* @__PURE__ */ jsx61(
11091
+ /* @__PURE__ */ jsxs49("span", { className: "flex min-w-0 flex-col gap-[var(--space-1)]", children: [
11092
+ /* @__PURE__ */ jsx62(
10741
11093
  "span",
10742
11094
  {
10743
11095
  id: labelId,
@@ -10749,7 +11101,7 @@ var Radio = React49.forwardRef(({ className, children, description, id, ...props
10749
11101
  children
10750
11102
  }
10751
11103
  ),
10752
- description ? /* @__PURE__ */ jsx61(
11104
+ description ? /* @__PURE__ */ jsx62(
10753
11105
  "span",
10754
11106
  {
10755
11107
  id: descriptionId,
@@ -10767,20 +11119,20 @@ Radio.displayName = "Radio";
10767
11119
 
10768
11120
  // src/components/ui/scroll-area.tsx
10769
11121
  import { ScrollArea as ScrollAreaPrimitive } from "radix-ui";
10770
- import { jsx as jsx62, jsxs as jsxs49 } from "react/jsx-runtime";
11122
+ import { jsx as jsx63, jsxs as jsxs50 } from "react/jsx-runtime";
10771
11123
  function ScrollArea({
10772
11124
  className,
10773
11125
  children,
10774
11126
  ...props
10775
11127
  }) {
10776
- return /* @__PURE__ */ jsxs49(
11128
+ return /* @__PURE__ */ jsxs50(
10777
11129
  ScrollAreaPrimitive.Root,
10778
11130
  {
10779
11131
  "data-slot": "scroll-area",
10780
11132
  className: cn("relative", className),
10781
11133
  ...props,
10782
11134
  children: [
10783
- /* @__PURE__ */ jsx62(
11135
+ /* @__PURE__ */ jsx63(
10784
11136
  ScrollAreaPrimitive.Viewport,
10785
11137
  {
10786
11138
  "data-slot": "scroll-area-viewport",
@@ -10788,8 +11140,8 @@ function ScrollArea({
10788
11140
  children
10789
11141
  }
10790
11142
  ),
10791
- /* @__PURE__ */ jsx62(ScrollBar, {}),
10792
- /* @__PURE__ */ jsx62(ScrollAreaPrimitive.Corner, {})
11143
+ /* @__PURE__ */ jsx63(ScrollBar, {}),
11144
+ /* @__PURE__ */ jsx63(ScrollAreaPrimitive.Corner, {})
10793
11145
  ]
10794
11146
  }
10795
11147
  );
@@ -10799,7 +11151,7 @@ function ScrollBar({
10799
11151
  orientation = "vertical",
10800
11152
  ...props
10801
11153
  }) {
10802
- return /* @__PURE__ */ jsx62(
11154
+ return /* @__PURE__ */ jsx63(
10803
11155
  ScrollAreaPrimitive.ScrollAreaScrollbar,
10804
11156
  {
10805
11157
  "data-slot": "scroll-area-scrollbar",
@@ -10811,7 +11163,7 @@ function ScrollBar({
10811
11163
  className
10812
11164
  ),
10813
11165
  ...props,
10814
- children: /* @__PURE__ */ jsx62(
11166
+ children: /* @__PURE__ */ jsx63(
10815
11167
  ScrollAreaPrimitive.ScrollAreaThumb,
10816
11168
  {
10817
11169
  "data-slot": "scroll-area-thumb",
@@ -10823,7 +11175,7 @@ function ScrollBar({
10823
11175
  }
10824
11176
 
10825
11177
  // src/components/ui/progress.tsx
10826
- import { jsx as jsx63 } from "react/jsx-runtime";
11178
+ import { jsx as jsx64 } from "react/jsx-runtime";
10827
11179
  var progressFillByStatus = {
10828
11180
  active: "bg-[var(--primary)]",
10829
11181
  success: "bg-[var(--success)]",
@@ -10844,7 +11196,7 @@ function Progress({
10844
11196
  const clamped = Math.max(0, Math.min(safeMax, value));
10845
11197
  const percent = clamped / safeMax * 100;
10846
11198
  const w = typeof width === "number" ? `${width}px` : width;
10847
- return /* @__PURE__ */ jsx63(
11199
+ return /* @__PURE__ */ jsx64(
10848
11200
  "div",
10849
11201
  {
10850
11202
  role: "progressbar",
@@ -10858,7 +11210,7 @@ function Progress({
10858
11210
  ),
10859
11211
  style: { width: w, height: `${height}px`, ...style },
10860
11212
  ...props,
10861
- children: /* @__PURE__ */ jsx63(
11213
+ children: /* @__PURE__ */ jsx64(
10862
11214
  "div",
10863
11215
  {
10864
11216
  className: cn(
@@ -10874,9 +11226,9 @@ function Progress({
10874
11226
 
10875
11227
  // src/components/ui/tree-view.tsx
10876
11228
  import * as React50 from "react";
10877
- import { ChevronRight as ChevronRight5 } from "lucide-react";
11229
+ import { ChevronRight as ChevronRight6 } from "lucide-react";
10878
11230
  import { cva as cva26 } from "class-variance-authority";
10879
- import { jsx as jsx64, jsxs as jsxs50 } from "react/jsx-runtime";
11231
+ import { jsx as jsx65, jsxs as jsxs51 } from "react/jsx-runtime";
10880
11232
  var treeViewVariants = cva26(
10881
11233
  "m-0 list-none p-[var(--space-1)] text-body-sm text-foreground"
10882
11234
  );
@@ -10888,7 +11240,7 @@ var treeItemRowVariants = cva26(
10888
11240
  "hover:bg-[var(--action-hover)] hover:text-foreground",
10889
11241
  // Roving focus lives on the treeitem <li> (named group/treeitem); the ring is
10890
11242
  // painted on the visual row so it never wraps the nested child group.
10891
- "group-focus-visible/treeitem:outline-none group-focus-visible/treeitem:ring-2 group-focus-visible/treeitem:ring-inset group-focus-visible/treeitem:ring-[var(--focus-ring)]"
11243
+ "group-focus-visible/treeitem:outline-none group-focus-visible/treeitem:inset-ring-2 group-focus-visible/treeitem:inset-ring-[var(--focus-ring)]"
10892
11244
  ].join(" "),
10893
11245
  {
10894
11246
  variants: {
@@ -11046,7 +11398,7 @@ function TreeView({
11046
11398
  const selected = node.id === selectedId;
11047
11399
  const isActive = node.id === activeId;
11048
11400
  const itemState = { expanded, selected, depth, hasChildren };
11049
- return /* @__PURE__ */ jsxs50(
11401
+ return /* @__PURE__ */ jsxs51(
11050
11402
  "li",
11051
11403
  {
11052
11404
  ref: (element) => {
@@ -11071,7 +11423,7 @@ function TreeView({
11071
11423
  onSelect?.(node.id, node);
11072
11424
  },
11073
11425
  children: [
11074
- /* @__PURE__ */ jsxs50(
11426
+ /* @__PURE__ */ jsxs51(
11075
11427
  "span",
11076
11428
  {
11077
11429
  "data-slot": "treeitem-row",
@@ -11080,7 +11432,7 @@ function TreeView({
11080
11432
  },
11081
11433
  className: treeItemRowVariants({ selected }),
11082
11434
  children: [
11083
- hasChildren ? /* @__PURE__ */ jsx64(
11435
+ hasChildren ? /* @__PURE__ */ jsx65(
11084
11436
  "span",
11085
11437
  {
11086
11438
  "data-slot": "treeitem-toggle",
@@ -11090,8 +11442,8 @@ function TreeView({
11090
11442
  setExpanded(node.id, !expanded);
11091
11443
  },
11092
11444
  className: "flex size-[var(--space-4)] shrink-0 items-center justify-center text-text-tertiary",
11093
- children: /* @__PURE__ */ jsx64(
11094
- ChevronRight5,
11445
+ children: /* @__PURE__ */ jsx65(
11446
+ ChevronRight6,
11095
11447
  {
11096
11448
  "aria-hidden": "true",
11097
11449
  "data-slot": "treeitem-chevron",
@@ -11103,7 +11455,7 @@ function TreeView({
11103
11455
  }
11104
11456
  )
11105
11457
  }
11106
- ) : /* @__PURE__ */ jsx64(
11458
+ ) : /* @__PURE__ */ jsx65(
11107
11459
  "span",
11108
11460
  {
11109
11461
  "data-slot": "treeitem-spacer",
@@ -11111,18 +11463,18 @@ function TreeView({
11111
11463
  className: "size-[var(--space-4)] shrink-0"
11112
11464
  }
11113
11465
  ),
11114
- /* @__PURE__ */ jsx64("span", { className: "flex min-w-0 flex-1 items-center gap-[var(--space-2)]", children: renderItem(node, itemState) })
11466
+ /* @__PURE__ */ jsx65("span", { className: "flex min-w-0 flex-1 items-center gap-[var(--space-2)]", children: renderItem(node, itemState) })
11115
11467
  ]
11116
11468
  }
11117
11469
  ),
11118
- hasChildren && expanded && children ? /* @__PURE__ */ jsx64("ul", { role: "group", "data-slot": "tree-group", className: "m-0 list-none p-0", children: renderLevel(children, depth + 1) }) : null
11470
+ hasChildren && expanded && children ? /* @__PURE__ */ jsx65("ul", { role: "group", "data-slot": "tree-group", className: "m-0 list-none p-0", children: renderLevel(children, depth + 1) }) : null
11119
11471
  ]
11120
11472
  },
11121
11473
  node.id
11122
11474
  );
11123
11475
  });
11124
11476
  }
11125
- return /* @__PURE__ */ jsx64(
11477
+ return /* @__PURE__ */ jsx65(
11126
11478
  "ul",
11127
11479
  {
11128
11480
  role: "tree",
@@ -11139,7 +11491,7 @@ function TreeView({
11139
11491
 
11140
11492
  // src/components/branding/olun-logo.tsx
11141
11493
  import { OLUN_MASTER, OLUN_SYMBOL, OLUN_WORDMARK } from "@olundot/tokens/brand";
11142
- import { Fragment as Fragment17, jsx as jsx65, jsxs as jsxs51 } from "react/jsx-runtime";
11494
+ import { Fragment as Fragment18, jsx as jsx66, jsxs as jsxs52 } from "react/jsx-runtime";
11143
11495
  var ACCENT_FILL = "var(--accent-pop)";
11144
11496
  var INK = { color: "var(--text-primary)" };
11145
11497
  var INK_TIGHT = { ...INK, display: "block", overflow: "visible" };
@@ -11149,8 +11501,8 @@ function symbolGeometry(size) {
11149
11501
  function SymbolCircles({ size }) {
11150
11502
  const { ring } = OLUN_SYMBOL;
11151
11503
  const g = symbolGeometry(size);
11152
- return /* @__PURE__ */ jsxs51(Fragment17, { children: [
11153
- /* @__PURE__ */ jsx65(
11504
+ return /* @__PURE__ */ jsxs52(Fragment18, { children: [
11505
+ /* @__PURE__ */ jsx66(
11154
11506
  "circle",
11155
11507
  {
11156
11508
  className: "olun-logo__ring",
@@ -11162,11 +11514,11 @@ function SymbolCircles({ size }) {
11162
11514
  fill: "none"
11163
11515
  }
11164
11516
  ),
11165
- /* @__PURE__ */ jsx65("circle", { className: "olun-accent olun-logo__dot", cx: g.dot.cx, cy: g.dot.cy, r: g.dot.r, fill: ACCENT_FILL })
11517
+ /* @__PURE__ */ jsx66("circle", { className: "olun-accent olun-logo__dot", cx: g.dot.cx, cy: g.dot.cy, r: g.dot.r, fill: ACCENT_FILL })
11166
11518
  ] });
11167
11519
  }
11168
11520
  function OlunSymbol({ size = 28, className }) {
11169
- return /* @__PURE__ */ jsx65(
11521
+ return /* @__PURE__ */ jsx66(
11170
11522
  "svg",
11171
11523
  {
11172
11524
  width: size,
@@ -11177,7 +11529,7 @@ function OlunSymbol({ size = 28, className }) {
11177
11529
  className,
11178
11530
  style: INK,
11179
11531
  "aria-hidden": "true",
11180
- children: /* @__PURE__ */ jsx65(SymbolCircles, { size })
11532
+ children: /* @__PURE__ */ jsx66(SymbolCircles, { size })
11181
11533
  }
11182
11534
  );
11183
11535
  }
@@ -11190,7 +11542,7 @@ function OlunLogo({
11190
11542
  if (!showSymbol) {
11191
11543
  const { full } = OLUN_WORDMARK;
11192
11544
  const height2 = fontSize * full.height / OLUN_WORDMARK.unitsPerEm;
11193
- return /* @__PURE__ */ jsxs51(
11545
+ return /* @__PURE__ */ jsxs52(
11194
11546
  "svg",
11195
11547
  {
11196
11548
  width: height2 * full.width / full.height,
@@ -11203,8 +11555,8 @@ function OlunLogo({
11203
11555
  role: "img",
11204
11556
  "aria-label": "OLUN.",
11205
11557
  children: [
11206
- /* @__PURE__ */ jsx65("path", { className: "olun-logo__wordmark", fill: "currentColor", d: full.letters }),
11207
- /* @__PURE__ */ jsx65(
11558
+ /* @__PURE__ */ jsx66("path", { className: "olun-logo__wordmark", fill: "currentColor", d: full.letters }),
11559
+ /* @__PURE__ */ jsx66(
11208
11560
  "circle",
11209
11561
  {
11210
11562
  className: "olun-accent olun-logo__period",
@@ -11220,7 +11572,7 @@ function OlunLogo({
11220
11572
  }
11221
11573
  const layout = symbolSize > OLUN_SYMBOL.smallMax ? OLUN_MASTER.large : OLUN_MASTER.small;
11222
11574
  const height = symbolSize * layout.height / (OLUN_SYMBOL.box * layout.symbol.scale);
11223
- return /* @__PURE__ */ jsxs51(
11575
+ return /* @__PURE__ */ jsxs52(
11224
11576
  "svg",
11225
11577
  {
11226
11578
  width: height * layout.width / layout.height,
@@ -11233,15 +11585,15 @@ function OlunLogo({
11233
11585
  role: "img",
11234
11586
  "aria-label": "OLUN",
11235
11587
  children: [
11236
- /* @__PURE__ */ jsx65(
11588
+ /* @__PURE__ */ jsx66(
11237
11589
  "g",
11238
11590
  {
11239
11591
  className: "olun-logo__symbol",
11240
11592
  transform: `translate(${layout.symbol.x} ${layout.symbol.y}) scale(${layout.symbol.scale})`,
11241
- children: /* @__PURE__ */ jsx65(SymbolCircles, { size: symbolSize })
11593
+ children: /* @__PURE__ */ jsx66(SymbolCircles, { size: symbolSize })
11242
11594
  }
11243
11595
  ),
11244
- /* @__PURE__ */ jsx65("path", { className: "olun-logo__wordmark", fill: "currentColor", d: layout.letters })
11596
+ /* @__PURE__ */ jsx66("path", { className: "olun-logo__wordmark", fill: "currentColor", d: layout.letters })
11245
11597
  ]
11246
11598
  }
11247
11599
  );
@@ -11249,11 +11601,11 @@ function OlunLogo({
11249
11601
 
11250
11602
  // src/components/branding/theme-toggle.tsx
11251
11603
  import { Sun, Moon } from "lucide-react";
11252
- import { jsx as jsx66 } from "react/jsx-runtime";
11604
+ import { jsx as jsx67 } from "react/jsx-runtime";
11253
11605
  function ThemeToggle({ className }) {
11254
11606
  const { resolvedTheme, toggleTheme } = useOlunTheme();
11255
11607
  const Icon = resolvedTheme === "dark" ? Moon : Sun;
11256
- return /* @__PURE__ */ jsx66(
11608
+ return /* @__PURE__ */ jsx67(
11257
11609
  "button",
11258
11610
  {
11259
11611
  onClick: () => toggleTheme(),
@@ -11265,14 +11617,14 @@ function ThemeToggle({ className }) {
11265
11617
  ),
11266
11618
  "aria-label": "\uD14C\uB9C8 \uC804\uD658",
11267
11619
  title: resolvedTheme === "dark" ? "\uB77C\uC774\uD2B8 \uBAA8\uB4DC\uB85C" : "\uB2E4\uD06C \uBAA8\uB4DC\uB85C",
11268
- children: /* @__PURE__ */ jsx66(Icon, { className: "size-[18px]", strokeWidth: 1.75 })
11620
+ children: /* @__PURE__ */ jsx67(Icon, { className: "size-[18px]", strokeWidth: 1.75 })
11269
11621
  }
11270
11622
  );
11271
11623
  }
11272
11624
 
11273
11625
  // src/components/branding/theme-fab.tsx
11274
11626
  import { Sun as Sun2, Moon as Moon2 } from "lucide-react";
11275
- import { jsx as jsx67 } from "react/jsx-runtime";
11627
+ import { jsx as jsx68 } from "react/jsx-runtime";
11276
11628
  function ThemeFab({ variant = "square" } = {}) {
11277
11629
  const { mounted, resolvedTheme, toggleTheme } = useOlunTheme();
11278
11630
  if (!mounted) {
@@ -11312,7 +11664,7 @@ function ThemeFab({ variant = "square" } = {}) {
11312
11664
  WebkitBackdropFilter: "blur(16px)",
11313
11665
  zIndex: 9999
11314
11666
  };
11315
- return /* @__PURE__ */ jsx67(
11667
+ return /* @__PURE__ */ jsx68(
11316
11668
  "button",
11317
11669
  {
11318
11670
  onClick: () => toggleTheme(),
@@ -11337,7 +11689,7 @@ function ThemeFab({ variant = "square" } = {}) {
11337
11689
  e.currentTarget.style.color = "var(--text-secondary)";
11338
11690
  }
11339
11691
  },
11340
- children: /* @__PURE__ */ jsx67(
11692
+ children: /* @__PURE__ */ jsx68(
11341
11693
  Icon,
11342
11694
  {
11343
11695
  size: isCircle ? 22 : 16,
@@ -11349,7 +11701,7 @@ function ThemeFab({ variant = "square" } = {}) {
11349
11701
  }
11350
11702
 
11351
11703
  // src/components/logos/organization-logo.tsx
11352
- import { jsx as jsx68 } from "react/jsx-runtime";
11704
+ import { jsx as jsx69 } from "react/jsx-runtime";
11353
11705
  var organizationLogoRegistry = {
11354
11706
  jbnu: {
11355
11707
  label: "\uC804\uBD81\uB300\uD559\uAD50 \uC5E0\uBE14\uB7FC",
@@ -11378,7 +11730,7 @@ function OrganizationLogo({
11378
11730
  }) {
11379
11731
  const asset = organizationLogoRegistry[organization];
11380
11732
  const isDecorative = ariaHidden === true || ariaHidden === "true";
11381
- return /* @__PURE__ */ jsx68(
11733
+ return /* @__PURE__ */ jsx69(
11382
11734
  "svg",
11383
11735
  {
11384
11736
  viewBox: asset.viewBox,
@@ -11396,7 +11748,7 @@ function OrganizationLogo({
11396
11748
  ...style
11397
11749
  },
11398
11750
  ...props,
11399
- children: asset.paths.map((path) => /* @__PURE__ */ jsx68("path", { d: path }, path))
11751
+ children: asset.paths.map((path) => /* @__PURE__ */ jsx69("path", { d: path }, path))
11400
11752
  }
11401
11753
  );
11402
11754
  }
@@ -11513,6 +11865,8 @@ export {
11513
11865
  StatusBadge,
11514
11866
  StatusDot,
11515
11867
  Switch,
11868
+ TABLE_PAGE_SIZE_OPTIONS,
11869
+ TablePagination,
11516
11870
  Tabs,
11517
11871
  TabsContent,
11518
11872
  Textarea,
@@ -11581,6 +11935,7 @@ export {
11581
11935
  selectMessageVariants,
11582
11936
  selectVariants,
11583
11937
  setOlunTheme,
11938
+ shouldHideTablePagination,
11584
11939
  skeletonVariants,
11585
11940
  spinnerVariants,
11586
11941
  tabsBadgeVariants,