@olundot/ui 0.20.0-next.6 → 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
@@ -969,6 +969,7 @@ FileUploadZone.displayName = "FileUploadZone";
969
969
 
970
970
  // src/components/ui/alert.tsx
971
971
  import * as React5 from "react";
972
+ import { CircleAlert, CircleCheck, Info, TriangleAlert, X } from "lucide-react";
972
973
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
973
974
  var SEM_FG = {
974
975
  info: "var(--semantic-info-fg)",
@@ -982,29 +983,20 @@ var SEM_BG = {
982
983
  warning: "var(--semantic-warning-bg)",
983
984
  error: "var(--semantic-error-bg)"
984
985
  };
986
+ var MARKER_ICON = {
987
+ info: Info,
988
+ success: CircleCheck,
989
+ warning: TriangleAlert,
990
+ error: CircleAlert
991
+ };
992
+ var TITLE_LINE_HEIGHT = 21;
985
993
  var defaultEmphasis = (v) => v === "error" ? "strong" : "subtle";
986
- function XIcon({ size }) {
987
- return /* @__PURE__ */ jsx5(
988
- "svg",
989
- {
990
- width: size,
991
- height: size,
992
- viewBox: "0 0 24 24",
993
- fill: "none",
994
- stroke: "currentColor",
995
- strokeWidth: 1.75,
996
- strokeLinecap: "round",
997
- strokeLinejoin: "round",
998
- "aria-hidden": "true",
999
- children: /* @__PURE__ */ jsx5("path", { d: "M18 6 6 18M6 6l12 12" })
1000
- }
1001
- );
1002
- }
1003
994
  var Alert = React5.forwardRef(
1004
- ({ variant = "info", emphasis, title, children, onDismiss, style, ...rest }, ref) => {
995
+ ({ variant = "info", emphasis, marker = "icon", title, children, onDismiss, style, ...rest }, ref) => {
1005
996
  const weight = emphasis ?? defaultEmphasis(variant);
1006
997
  const strong = weight === "strong";
1007
998
  const fg = SEM_FG[variant];
999
+ const MarkerIcon = MARKER_ICON[variant];
1008
1000
  return /* @__PURE__ */ jsxs5(
1009
1001
  "div",
1010
1002
  {
@@ -1014,16 +1006,16 @@ var Alert = React5.forwardRef(
1014
1006
  "data-slot": "alert",
1015
1007
  "data-variant": variant,
1016
1008
  "data-emphasis": weight,
1009
+ "data-marker": marker,
1017
1010
  style: {
1018
1011
  display: "flex",
1019
1012
  alignItems: "flex-start",
1020
- gap: 11,
1021
- borderRadius: 10,
1013
+ gap: "var(--space-2)",
1014
+ borderRadius: "var(--radius-md)",
1022
1015
  border: "1px solid " + (strong ? "color-mix(in srgb, " + fg + " 26%, transparent)" : "var(--border)"),
1023
1016
  background: strong ? SEM_BG[variant] : "var(--bg-surface)",
1024
1017
  color: "var(--text-primary)",
1025
- padding: "12px 14px",
1026
- paddingInlineEnd: onDismiss ? 10 : 14,
1018
+ padding: "var(--space-2) 10px",
1027
1019
  ...style
1028
1020
  },
1029
1021
  ...rest,
@@ -1032,42 +1024,49 @@ var Alert = React5.forwardRef(
1032
1024
  "span",
1033
1025
  {
1034
1026
  "aria-hidden": "true",
1035
- "data-slot": "alert-dot",
1027
+ "data-slot": "alert-marker",
1036
1028
  style: {
1037
- marginTop: title ? 5 : 4,
1038
- width: 7,
1039
- height: 7,
1029
+ display: "inline-flex",
1030
+ height: TITLE_LINE_HEIGHT,
1040
1031
  flexShrink: 0,
1041
- borderRadius: 9999,
1042
- background: fg
1043
- }
1032
+ alignItems: "center",
1033
+ justifyContent: "center",
1034
+ color: fg
1035
+ },
1036
+ children: marker === "dot" ? /* @__PURE__ */ jsx5(
1037
+ "span",
1038
+ {
1039
+ "data-slot": "alert-dot",
1040
+ style: { width: 7, height: 7, borderRadius: 9999, background: "currentColor" }
1041
+ }
1042
+ ) : /* @__PURE__ */ jsx5(MarkerIcon, { "data-slot": "alert-icon", size: 16, strokeWidth: 2.25 })
1044
1043
  }
1045
1044
  ),
1046
1045
  /* @__PURE__ */ jsxs5("div", { "data-slot": "alert-content", style: { flex: 1, minWidth: 0 }, children: [
1047
- title ? /* @__PURE__ */ jsx5(
1046
+ /* @__PURE__ */ jsx5(
1048
1047
  "div",
1049
1048
  {
1050
1049
  "data-slot": "alert-title",
1051
1050
  style: {
1052
1051
  fontFamily: "var(--font-sans)",
1053
- fontSize: 13,
1054
- fontWeight: 600,
1055
- lineHeight: 1.35,
1052
+ fontSize: 14,
1053
+ fontWeight: "var(--fw-medium)",
1054
+ lineHeight: TITLE_LINE_HEIGHT + "px",
1056
1055
  color: strong ? fg : "var(--text-primary)"
1057
1056
  },
1058
1057
  children: title
1059
1058
  }
1060
- ) : null,
1059
+ ),
1061
1060
  /* @__PURE__ */ jsx5(
1062
1061
  "div",
1063
1062
  {
1064
1063
  "data-slot": "alert-body",
1065
1064
  style: {
1066
- marginTop: title ? 2 : 0,
1065
+ marginTop: 2,
1067
1066
  fontFamily: "var(--font-sans)",
1068
- fontSize: 12.5,
1069
- lineHeight: 1.45,
1070
- color: strong ? "color-mix(in srgb, " + fg + " 88%, var(--text-primary))" : "var(--text-tertiary)"
1067
+ fontSize: "var(--fs-sm)",
1068
+ lineHeight: "var(--lh-normal)",
1069
+ color: strong ? "color-mix(in srgb, " + fg + " 88%, var(--text-primary))" : "var(--text-secondary)"
1071
1070
  },
1072
1071
  children
1073
1072
  }
@@ -1101,21 +1100,20 @@ function DismissButton({
1101
1100
  style: {
1102
1101
  flexShrink: 0,
1103
1102
  display: "inline-flex",
1104
- width: 24,
1105
- height: 24,
1106
- marginTop: -1,
1103
+ width: 28,
1104
+ height: 28,
1107
1105
  alignItems: "center",
1108
1106
  justifyContent: "center",
1109
1107
  borderRadius: "var(--radius-md)",
1110
- border: 0,
1111
- background: hover ? "var(--action-hover)" : "transparent",
1112
- color: hover ? strong ? fg : "var(--text-primary)" : strong ? "color-mix(in srgb, " + fg + " 70%, transparent)" : "var(--text-tertiary)",
1108
+ border: "1px solid var(--border)",
1109
+ background: hover ? "var(--action-hover)" : "var(--bg-surface)",
1110
+ color: hover ? strong ? fg : "var(--text-primary)" : strong ? "color-mix(in srgb, " + fg + " 70%, transparent)" : "var(--text-secondary)",
1113
1111
  cursor: "pointer",
1114
1112
  outline: "none",
1115
1113
  boxShadow: focus ? "0 0 0 2px var(--focus-ring)" : "none",
1116
1114
  transition: "background var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard)"
1117
1115
  },
1118
- children: /* @__PURE__ */ jsx5(XIcon, { size: 15 })
1116
+ children: /* @__PURE__ */ jsx5(X, { "aria-hidden": "true", size: 15 })
1119
1117
  }
1120
1118
  );
1121
1119
  }
@@ -1527,13 +1525,14 @@ var Select = React7.forwardRef(
1527
1525
  surface = "surface",
1528
1526
  id,
1529
1527
  label,
1528
+ labelPlacement = "top",
1530
1529
  description,
1531
1530
  message,
1532
1531
  invalid,
1533
1532
  state = "default",
1534
1533
  options,
1535
1534
  placeholder = "\uC120\uD0DD\uD558\uC138\uC694",
1536
- clearable = true,
1535
+ clearable = labelPlacement !== "inline",
1537
1536
  clearLabel,
1538
1537
  disabled,
1539
1538
  required,
@@ -1550,6 +1549,9 @@ var Select = React7.forwardRef(
1550
1549
  const resolvedAppearance = appearance ?? (selectVariant === "inline" ? "inline" : "field");
1551
1550
  const generatedId = React7.useId();
1552
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;
1553
1555
  const triggerId = label || message || description ? selectId : id;
1554
1556
  const resolvedState = invalid || state === "error" ? "error" : state;
1555
1557
  const showDescription = resolvedState === "default" && Boolean(description);
@@ -1646,13 +1648,26 @@ var Select = React7.forwardRef(
1646
1648
  id: triggerId,
1647
1649
  "data-slot": "select-trigger",
1648
1650
  "aria-label": ariaLabel,
1651
+ "aria-labelledby": inlineLabel ? `${inlineLabelId} ${inlineValueId}` : void 0,
1649
1652
  "aria-describedby": describedBy,
1650
1653
  "aria-invalid": resolvedInvalid,
1651
- 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),
1652
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,
1653
1667
  /* @__PURE__ */ jsx7(
1654
1668
  "span",
1655
1669
  {
1670
+ id: inlineValueId,
1656
1671
  "data-slot": "select-value",
1657
1672
  "data-placeholder": hasSelection ? void 0 : "",
1658
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",
@@ -1682,7 +1697,7 @@ var Select = React7.forwardRef(
1682
1697
  ]
1683
1698
  }
1684
1699
  );
1685
- if (!label && !message && !description) {
1700
+ if ((!label || inlineLabel) && !message && !description) {
1686
1701
  return select;
1687
1702
  }
1688
1703
  const MessageIcon = resolvedState === "success" ? CheckCircle23 : AlertCircle3;
@@ -1691,9 +1706,9 @@ var Select = React7.forwardRef(
1691
1706
  {
1692
1707
  "data-slot": "select-field",
1693
1708
  "data-state": resolvedState,
1694
- 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"),
1695
1710
  children: [
1696
- label ? /* @__PURE__ */ jsxs7(
1711
+ label && !inlineLabel ? /* @__PURE__ */ jsxs7(
1697
1712
  "label",
1698
1713
  {
1699
1714
  "data-slot": "select-label",
@@ -2624,7 +2639,11 @@ var DataLayout = React15.forwardRef(
2624
2639
  className: cn("flex min-w-0 flex-col gap-[var(--space-8)]", className),
2625
2640
  ...props,
2626
2641
  children: [
2627
- /* @__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,
2628
2647
  /* @__PURE__ */ jsxs15(
2629
2648
  "div",
2630
2649
  {
@@ -2639,7 +2658,7 @@ var DataLayout = React15.forwardRef(
2639
2658
  {
2640
2659
  "data-slot": "data-layout-bulkbar",
2641
2660
  className: "pointer-events-none sticky bottom-[var(--space-4)] z-20 mt-[var(--space-2)] flex justify-center",
2642
- 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 })
2643
2662
  }
2644
2663
  ) : null
2645
2664
  ]
@@ -3908,7 +3927,7 @@ function OverlayGrabber({
3908
3927
  }
3909
3928
 
3910
3929
  // src/components/ui/overlay-close-button.tsx
3911
- import { X } from "lucide-react";
3930
+ import { X as X2 } from "lucide-react";
3912
3931
  import { Dialog as DialogPrimitive } from "radix-ui";
3913
3932
 
3914
3933
  // src/components/ui/icon-button.tsx
@@ -4106,7 +4125,7 @@ function OverlayCloseButton({
4106
4125
  label = "\uB2EB\uAE30",
4107
4126
  className
4108
4127
  }) {
4109
- return /* @__PURE__ */ jsx23(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx23(IconButton, { appearance: "ghost", size: "md", icon: X, "aria-label": label, className }) });
4128
+ return /* @__PURE__ */ jsx23(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx23(IconButton, { appearance: "ghost", size: "md", icon: X2, "aria-label": label, className }) });
4110
4129
  }
4111
4130
 
4112
4131
  // src/components/ui/overlay-anatomy.tsx
@@ -4233,7 +4252,7 @@ function focusBodyInput(event) {
4233
4252
  }
4234
4253
  }
4235
4254
  var headingClassName = {
4236
- title: "text-[18px] font-bold leading-snug text-foreground",
4255
+ title: "text-base font-semibold leading-normal text-foreground",
4237
4256
  menu: "text-[15px] font-semibold leading-snug text-foreground"
4238
4257
  };
4239
4258
  var descriptionClassName = {
@@ -4665,7 +4684,7 @@ function SheetTitle({
4665
4684
  SheetPrimitive.Title,
4666
4685
  {
4667
4686
  "data-slot": "sheet-title",
4668
- className: cn("font-semibold text-foreground", className),
4687
+ className: cn("text-base font-semibold leading-normal text-foreground", className),
4669
4688
  ...props
4670
4689
  }
4671
4690
  );
@@ -4912,7 +4931,7 @@ var DialogTitle = React26.forwardRef(({ className, ...props }, ref) => /* @__PUR
4912
4931
  {
4913
4932
  ref,
4914
4933
  className: cn(
4915
- "text-xl font-bold leading-tight tracking-tight text-foreground",
4934
+ "text-base font-semibold leading-normal text-foreground",
4916
4935
  className
4917
4936
  ),
4918
4937
  ...props
@@ -5120,7 +5139,7 @@ import { SlidersHorizontal } from "lucide-react";
5120
5139
  // src/components/ui/chip.tsx
5121
5140
  import * as React27 from "react";
5122
5141
  import { cva as cva11 } from "class-variance-authority";
5123
- import { X as X2 } from "lucide-react";
5142
+ import { X as X3 } from "lucide-react";
5124
5143
  import { Slot as Slot2 } from "radix-ui";
5125
5144
  import { jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
5126
5145
  var chipVariants = cva11(
@@ -5271,7 +5290,7 @@ var Chip = React27.forwardRef(
5271
5290
  disabled,
5272
5291
  onClick,
5273
5292
  className: "inline-flex size-[var(--space-4)] items-center justify-center rounded-[var(--radius-full)] text-text-tertiary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)]",
5274
- children: /* @__PURE__ */ jsx30(X2, { "aria-hidden": "true", size: 14, strokeWidth: 2.25 })
5293
+ children: /* @__PURE__ */ jsx30(X3, { "aria-hidden": "true", size: 14, strokeWidth: 2.25 })
5275
5294
  }
5276
5295
  )
5277
5296
  ]
@@ -5635,513 +5654,184 @@ FilterToolbar.displayName = "FilterToolbar";
5635
5654
 
5636
5655
  // src/components/ui/data-table.tsx
5637
5656
  import * as React33 from "react";
5638
- 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";
5639
5658
  import { cva as cva13 } from "class-variance-authority";
5640
5659
 
5641
- // src/components/ui/checkbox.tsx
5660
+ // src/components/ui/action-menu.tsx
5642
5661
  import * as React30 from "react";
5643
- import { cva as cva12 } from "class-variance-authority";
5644
- import { Check as Check3, Minus } from "lucide-react";
5645
- 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";
5646
5667
  import { jsx as jsx33, jsxs as jsxs29 } from "react/jsx-runtime";
5647
- var checkboxFieldVariants = cva12(
5648
- "flex flex-col gap-[var(--space-1)]",
5649
- {
5650
- variants: {
5651
- fullWidth: {
5652
- true: "w-full",
5653
- false: "w-fit"
5654
- }
5655
- },
5656
- defaultVariants: {
5657
- 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
5658
5686
  }
5659
- }
5660
- );
5661
- var checkboxVariants = checkboxFieldVariants;
5662
- var checkboxRootVariants = cva12(
5663
- [
5664
- "group shrink-0 cursor-pointer rounded-[var(--radius-xs)]",
5665
- "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)]",
5666
- "disabled:cursor-not-allowed"
5667
- ].join(" ")
5668
- );
5669
- var checkboxBoxVariants = cva12(
5670
- [
5671
- "flex shrink-0 items-center justify-center rounded-[var(--radius-xs)] border",
5672
- "border-[var(--border-strong)] bg-[var(--bg-surface)] text-transparent",
5673
- "transition-colors motion-reduce:transition-none",
5674
- "group-hover:bg-[var(--action-hover)]",
5675
- "group-disabled:border-[var(--border-subtle)] group-disabled:bg-[var(--action-disabled-bg)]",
5676
- "group-data-[state=checked]:border-[var(--primary)] group-data-[state=checked]:bg-[var(--primary)] group-data-[state=checked]:text-[var(--primary-fg)]",
5677
- "group-data-[state=indeterminate]:border-[var(--primary)] group-data-[state=indeterminate]:bg-[var(--primary)] group-data-[state=indeterminate]:text-[var(--primary-fg)]",
5678
- "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",
5679
- "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"
5680
- ].join(" "),
5681
- {
5682
- variants: {
5683
- size: {
5684
- sm: "size-[calc(var(--space-4)+var(--space-1))]",
5685
- md: "size-[calc(var(--space-4)+var(--space-1))]"
5686
- }
5687
- },
5688
- defaultVariants: {
5689
- 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
5690
5711
  }
5691
- }
5692
- );
5693
- var checkboxGroupItemVariants = cva12(
5694
- [
5695
- "group w-full cursor-pointer text-left transition-colors motion-reduce:transition-none",
5696
- "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)]",
5697
- "disabled:cursor-not-allowed disabled:text-text-disabled"
5698
- ].join(" "),
5699
- {
5700
- variants: {
5701
- appearance: {
5702
- plain: "inline-flex items-start gap-[var(--space-3)] rounded-[var(--radius-md)] px-[var(--space-3)] py-[var(--space-2)]",
5703
- card: [
5704
- "flex min-h-[calc(var(--space-12)+var(--space-2))] items-start gap-[var(--space-3)]",
5705
- "rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--bg-surface)]",
5706
- "hover:bg-[var(--action-hover)]",
5707
- "data-[state=checked]:border-[var(--border-strong)] data-[state=checked]:bg-[var(--action-selected)]",
5708
- "disabled:border-[var(--border-subtle)] disabled:bg-[var(--action-disabled-bg)]",
5709
- "disabled:data-[state=checked]:border-[var(--border-subtle)] disabled:data-[state=checked]:bg-[var(--action-disabled-bg)]"
5710
- ].join(" ")
5711
- },
5712
- density: {
5713
- comfortable: "",
5714
- compact: ""
5715
- }
5716
- },
5717
- compoundVariants: [
5718
- {
5719
- appearance: "card",
5720
- density: "comfortable",
5721
- className: "px-[var(--space-4)] py-[var(--space-4)]"
5722
- },
5723
- {
5724
- appearance: "card",
5725
- density: "compact",
5726
- className: "px-[var(--space-3)] py-[var(--space-3)]"
5727
- }
5728
- ],
5729
- defaultVariants: {
5730
- appearance: "plain",
5731
- 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
5732
5743
  }
5733
- }
5734
- );
5735
- var checkboxGroupBoxVariants = cva12(
5736
- "mt-[2px]",
5737
- {
5738
- variants: {
5739
- appearance: {
5740
- plain: "",
5741
- card: "mt-[var(--space-1)]"
5742
- }
5743
- },
5744
- defaultVariants: {
5745
- 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
+ ]
5746
5771
  }
5747
- }
5748
- );
5749
- var CheckboxGroupContext = React30.createContext(null);
5750
- function getLabel(children, label) {
5751
- return children ?? label;
5772
+ );
5752
5773
  }
5753
- var Checkbox = React30.forwardRef(
5754
- ({
5755
- className,
5756
- size = "md",
5757
- fullWidth = false,
5758
- children,
5759
- label,
5760
- description,
5761
- required,
5762
- error,
5763
- id,
5764
- value,
5765
- name,
5766
- checked,
5767
- disabled,
5768
- onCheckedChange,
5769
- ...props
5770
- }, ref) => {
5771
- const group = React30.useContext(CheckboxGroupContext);
5772
- const generatedId = React30.useId();
5773
- const checkboxId = id ?? generatedId;
5774
- const labelContent = getLabel(children, label);
5775
- const isGrouped = Boolean(group && value != null);
5776
- const valueString = value == null ? void 0 : String(value);
5777
- const resolvedChecked = isGrouped && valueString ? group?.selectedValues.has(valueString) : checked;
5778
- const resolvedDisabled = disabled || group?.disabled;
5779
- const resolvedName = name ?? group?.name;
5780
- const labelId = `${checkboxId}-label`;
5781
- const descriptionId = description && !error ? `${checkboxId}-description` : void 0;
5782
- const errorId = error ? `${checkboxId}-error` : void 0;
5783
- const describedBy = errorId ?? descriptionId;
5784
- const handleCheckedChange = (nextChecked) => {
5785
- onCheckedChange?.(nextChecked);
5786
- if (isGrouped && valueString) {
5787
- group?.toggleValue(valueString, nextChecked === true);
5788
- }
5789
- };
5790
- if (isGrouped) {
5791
- const appearance = group?.appearance ?? "plain";
5792
- const density = group?.density ?? "comfortable";
5793
- return /* @__PURE__ */ jsxs29(
5794
- CheckboxPrimitive.Root,
5795
- {
5796
- ref,
5797
- id: checkboxId,
5798
- "data-slot": "checkbox",
5799
- "aria-labelledby": labelId,
5800
- "aria-describedby": describedBy,
5801
- "aria-required": required || void 0,
5802
- "aria-invalid": error ? true : void 0,
5803
- name: resolvedName,
5804
- value: valueString,
5805
- checked: resolvedChecked,
5806
- disabled: resolvedDisabled,
5807
- className: cn(
5808
- checkboxGroupItemVariants({ appearance, density }),
5809
- className
5810
- ),
5811
- onCheckedChange: handleCheckedChange,
5812
- ...props,
5813
- children: [
5814
- /* @__PURE__ */ jsx33(
5815
- "span",
5816
- {
5817
- "aria-hidden": "true",
5818
- "data-slot": "checkbox-box",
5819
- className: cn(
5820
- checkboxBoxVariants({ size }),
5821
- checkboxGroupBoxVariants({ appearance })
5822
- ),
5823
- children: /* @__PURE__ */ jsx33(
5824
- CheckboxPrimitive.Indicator,
5825
- {
5826
- "data-slot": "checkbox-indicator",
5827
- className: "flex items-center justify-center",
5828
- 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 })
5829
- }
5830
- )
5831
- }
5832
- ),
5833
- /* @__PURE__ */ jsxs29("span", { className: "flex min-w-0 flex-col gap-[var(--space-1)]", children: [
5834
- /* @__PURE__ */ jsxs29(
5835
- "span",
5836
- {
5837
- id: labelId,
5838
- "data-slot": "checkbox-label",
5839
- className: "text-sm font-medium leading-snug text-foreground group-disabled:text-text-disabled",
5840
- children: [
5841
- labelContent,
5842
- required ? /* @__PURE__ */ jsx33(
5843
- "span",
5844
- {
5845
- "aria-hidden": "true",
5846
- "data-slot": "checkbox-required-marker",
5847
- className: "ml-[var(--space-1)] font-bold text-[var(--semantic-error,var(--error))]",
5848
- children: "*"
5849
- }
5850
- ) : null
5851
- ]
5852
- }
5853
- ),
5854
- error ? /* @__PURE__ */ jsx33(
5855
- "span",
5856
- {
5857
- id: errorId,
5858
- role: "alert",
5859
- "data-slot": "checkbox-error",
5860
- className: "text-xs font-medium leading-normal text-[var(--error)]",
5861
- children: error
5862
- }
5863
- ) : description ? /* @__PURE__ */ jsx33(
5864
- "span",
5865
- {
5866
- id: descriptionId,
5867
- "data-slot": "checkbox-description",
5868
- className: "text-xs font-normal leading-normal text-text-tertiary group-disabled:text-text-disabled",
5869
- children: description
5870
- }
5871
- ) : null
5872
- ] })
5873
- ]
5874
- }
5875
- );
5876
- }
5877
- const labelClassName = cn(
5878
- "cursor-pointer select-none text-left font-medium text-foreground",
5879
- size === "sm" ? "text-xs" : "text-sm",
5880
- resolvedDisabled && "cursor-not-allowed text-text-disabled"
5881
- );
5882
- return /* @__PURE__ */ jsxs29(
5883
- "div",
5884
- {
5885
- "data-slot": "checkbox-field",
5886
- "data-disabled": resolvedDisabled ? "" : void 0,
5887
- className: checkboxFieldVariants({ fullWidth }),
5888
- children: [
5889
- /* @__PURE__ */ jsxs29("div", { className: "inline-flex items-center gap-[var(--space-3)]", children: [
5890
- /* @__PURE__ */ jsx33(
5891
- CheckboxPrimitive.Root,
5892
- {
5893
- ref,
5894
- id: checkboxId,
5895
- "data-slot": "checkbox",
5896
- "aria-describedby": describedBy,
5897
- "aria-required": required || void 0,
5898
- "aria-invalid": error ? true : void 0,
5899
- name: resolvedName,
5900
- value: valueString,
5901
- checked: resolvedChecked,
5902
- disabled: resolvedDisabled,
5903
- className: cn(checkboxRootVariants(), className),
5904
- onCheckedChange: handleCheckedChange,
5905
- ...props,
5906
- children: /* @__PURE__ */ jsx33(
5907
- "span",
5908
- {
5909
- "aria-hidden": "true",
5910
- "data-slot": "checkbox-box",
5911
- className: checkboxBoxVariants({ size }),
5912
- children: /* @__PURE__ */ jsx33(
5913
- CheckboxPrimitive.Indicator,
5914
- {
5915
- "data-slot": "checkbox-indicator",
5916
- className: "flex items-center justify-center",
5917
- 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 })
5918
- }
5919
- )
5920
- }
5921
- )
5922
- }
5923
- ),
5924
- labelContent ? /* @__PURE__ */ jsxs29(
5925
- "label",
5926
- {
5927
- id: labelId,
5928
- htmlFor: checkboxId,
5929
- "data-slot": "checkbox-label",
5930
- className: labelClassName,
5931
- children: [
5932
- labelContent,
5933
- required ? /* @__PURE__ */ jsx33(
5934
- "span",
5935
- {
5936
- "aria-hidden": "true",
5937
- "data-slot": "checkbox-required-marker",
5938
- className: "ml-[var(--space-1)] font-bold text-[var(--semantic-error,var(--error))]",
5939
- children: "*"
5940
- }
5941
- ) : null
5942
- ]
5943
- }
5944
- ) : null
5945
- ] }),
5946
- error ? /* @__PURE__ */ jsx33(
5947
- "p",
5948
- {
5949
- id: errorId,
5950
- role: "alert",
5951
- "data-slot": "checkbox-error",
5952
- className: "ml-[32px] text-xs font-medium leading-normal text-[var(--error)]",
5953
- children: error
5954
- }
5955
- ) : description ? /* @__PURE__ */ jsx33(
5956
- "p",
5957
- {
5958
- id: descriptionId,
5959
- "data-slot": "checkbox-description",
5960
- className: cn(
5961
- "ml-[32px] text-xs font-normal leading-normal text-text-tertiary",
5962
- resolvedDisabled && "text-text-disabled"
5963
- ),
5964
- children: description
5965
- }
5966
- ) : null
5967
- ]
5968
- }
5969
- );
5970
- }
5971
- );
5972
- Checkbox.displayName = "Checkbox";
5973
-
5974
- // src/components/ui/dropdown-menu.tsx
5975
- import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
5976
- import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
5977
- import { jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
5978
- function DropdownMenu({
5979
- ...props
5980
- }) {
5981
- return /* @__PURE__ */ jsx34(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
5982
- }
5983
- function DropdownMenuPortal({
5984
- ...props
5985
- }) {
5986
- return /* @__PURE__ */ jsx34(DropdownMenuPrimitive.Portal, { "data-slot": "dropdown-menu-portal", ...props });
5987
- }
5988
- function DropdownMenuTrigger({
5774
+ function DropdownMenuRadioGroup({
5989
5775
  ...props
5990
5776
  }) {
5991
- return /* @__PURE__ */ jsx34(
5992
- DropdownMenuPrimitive.Trigger,
5777
+ return /* @__PURE__ */ jsx33(
5778
+ DropdownMenuPrimitive.RadioGroup,
5993
5779
  {
5994
- "data-slot": "dropdown-menu-trigger",
5780
+ "data-slot": "dropdown-menu-radio-group",
5995
5781
  ...props
5996
5782
  }
5997
5783
  );
5998
5784
  }
5999
- function DropdownMenuContent({
5785
+ function DropdownMenuRadioItem({
6000
5786
  className,
6001
- sideOffset = 4,
5787
+ children,
6002
5788
  ...props
6003
5789
  }) {
6004
- return /* @__PURE__ */ jsx34(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx34(
6005
- DropdownMenuPrimitive.Content,
5790
+ return /* @__PURE__ */ jsxs29(
5791
+ DropdownMenuPrimitive.RadioItem,
6006
5792
  {
6007
- "data-slot": "dropdown-menu-content",
6008
- sideOffset,
5793
+ "data-slot": "dropdown-menu-radio-item",
6009
5794
  className: cn(
6010
- "z-[var(--z-popover)] max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem]",
6011
- "origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto",
6012
- "rounded-[var(--radius-lg)] border border-[var(--border)] bg-[var(--bg-surface)] p-[var(--space-1)] text-text-primary shadow-[var(--shadow-16)]",
6013
- "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
6014
- "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
6015
- "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
6016
- "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
6017
- "motion-reduce:transition-none",
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",
6018
5801
  className
6019
5802
  ),
6020
- ...props
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
+ ]
6021
5808
  }
6022
- ) });
6023
- }
6024
- function DropdownMenuGroup({
6025
- ...props
6026
- }) {
6027
- return /* @__PURE__ */ jsx34(DropdownMenuPrimitive.Group, { "data-slot": "dropdown-menu-group", ...props });
5809
+ );
6028
5810
  }
6029
- function DropdownMenuItem({
5811
+ function DropdownMenuLabel({
6030
5812
  className,
6031
5813
  inset,
6032
- variant = "default",
6033
5814
  ...props
6034
5815
  }) {
6035
- return /* @__PURE__ */ jsx34(
6036
- DropdownMenuPrimitive.Item,
5816
+ return /* @__PURE__ */ jsx33(
5817
+ DropdownMenuPrimitive.Label,
6037
5818
  {
6038
- "data-slot": "dropdown-menu-item",
5819
+ "data-slot": "dropdown-menu-label",
6039
5820
  "data-inset": inset,
6040
- "data-variant": variant,
6041
5821
  className: cn(
6042
- "relative flex min-h-[32px] cursor-pointer items-center gap-[var(--space-2)]",
6043
- "rounded-sm px-[var(--space-3)] py-[var(--space-1)] text-body-sm leading-compact text-text-primary outline-none select-none",
6044
- "data-[inset]:pl-8",
6045
- "data-[highlighted]:bg-action-hover data-[highlighted]:text-text-primary",
6046
- "data-[state=open]:bg-action-selected",
6047
- "data-[disabled]:pointer-events-none data-[disabled]:bg-action-disabled-bg data-[disabled]:text-text-disabled",
6048
- "data-[variant=destructive]:text-[var(--semantic-error,var(--error))]",
6049
- "[&_svg]:pointer-events-none [&_svg]:shrink-0",
5822
+ "px-[var(--space-2)] py-[var(--space-1)] text-xs font-semibold leading-compact text-text-tertiary data-[inset]:pl-8",
6050
5823
  className
6051
5824
  ),
6052
5825
  ...props
6053
5826
  }
6054
5827
  );
6055
5828
  }
6056
- function DropdownMenuCheckboxItem({
5829
+ function DropdownMenuSeparator({
6057
5830
  className,
6058
- children,
6059
- checked,
6060
5831
  ...props
6061
5832
  }) {
6062
- return /* @__PURE__ */ jsxs30(
6063
- DropdownMenuPrimitive.CheckboxItem,
6064
- {
6065
- "data-slot": "dropdown-menu-checkbox-item",
6066
- className: cn(
6067
- "relative flex min-h-[32px] cursor-pointer items-center gap-[var(--space-2)]",
6068
- "rounded-sm py-[var(--space-1)] pr-[var(--space-3)] pl-8 text-body-sm leading-compact text-text-primary outline-none select-none",
6069
- "data-[highlighted]:bg-action-hover data-[highlighted]:text-text-primary",
6070
- "data-[state=open]:bg-action-selected",
6071
- "data-[disabled]:pointer-events-none data-[disabled]:bg-action-disabled-bg data-[disabled]:text-text-disabled",
6072
- "[&_svg]:pointer-events-none [&_svg]:shrink-0",
6073
- className
6074
- ),
6075
- checked,
6076
- ...props,
6077
- children: [
6078
- /* @__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 }) }) }),
6079
- children
6080
- ]
6081
- }
6082
- );
6083
- }
6084
- function DropdownMenuRadioGroup({
6085
- ...props
6086
- }) {
6087
- return /* @__PURE__ */ jsx34(
6088
- DropdownMenuPrimitive.RadioGroup,
6089
- {
6090
- "data-slot": "dropdown-menu-radio-group",
6091
- ...props
6092
- }
6093
- );
6094
- }
6095
- function DropdownMenuRadioItem({
6096
- className,
6097
- children,
6098
- ...props
6099
- }) {
6100
- return /* @__PURE__ */ jsxs30(
6101
- DropdownMenuPrimitive.RadioItem,
6102
- {
6103
- "data-slot": "dropdown-menu-radio-item",
6104
- className: cn(
6105
- "relative flex min-h-[32px] cursor-pointer items-center gap-[var(--space-2)]",
6106
- "rounded-sm py-[var(--space-1)] pr-[var(--space-3)] pl-8 text-body-sm leading-compact text-text-primary outline-none select-none",
6107
- "data-[highlighted]:bg-action-hover data-[highlighted]:text-text-primary",
6108
- "data-[state=open]:bg-action-selected",
6109
- "data-[disabled]:pointer-events-none data-[disabled]:bg-action-disabled-bg data-[disabled]:text-text-disabled",
6110
- "[&_svg]:pointer-events-none [&_svg]:shrink-0",
6111
- className
6112
- ),
6113
- ...props,
6114
- children: [
6115
- /* @__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" }) }) }),
6116
- children
6117
- ]
6118
- }
6119
- );
6120
- }
6121
- function DropdownMenuLabel({
6122
- className,
6123
- inset,
6124
- ...props
6125
- }) {
6126
- return /* @__PURE__ */ jsx34(
6127
- DropdownMenuPrimitive.Label,
6128
- {
6129
- "data-slot": "dropdown-menu-label",
6130
- "data-inset": inset,
6131
- className: cn(
6132
- "px-[var(--space-2)] py-[var(--space-1)] text-xs font-semibold leading-compact text-text-tertiary data-[inset]:pl-8",
6133
- className
6134
- ),
6135
- ...props
6136
- }
6137
- );
6138
- }
6139
- function DropdownMenuSeparator({
6140
- className,
6141
- ...props
6142
- }) {
6143
- return /* @__PURE__ */ jsx34(
6144
- DropdownMenuPrimitive.Separator,
5833
+ return /* @__PURE__ */ jsx33(
5834
+ DropdownMenuPrimitive.Separator,
6145
5835
  {
6146
5836
  "data-slot": "dropdown-menu-separator",
6147
5837
  className: cn("-mx-1 my-1 h-0 border-t border-border-subtle", className),
@@ -6153,7 +5843,7 @@ function DropdownMenuShortcut({
6153
5843
  className,
6154
5844
  ...props
6155
5845
  }) {
6156
- return /* @__PURE__ */ jsx34(
5846
+ return /* @__PURE__ */ jsx33(
6157
5847
  "span",
6158
5848
  {
6159
5849
  "data-slot": "dropdown-menu-shortcut",
@@ -6168,7 +5858,7 @@ function DropdownMenuShortcut({
6168
5858
  function DropdownMenuSub({
6169
5859
  ...props
6170
5860
  }) {
6171
- return /* @__PURE__ */ jsx34(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
5861
+ return /* @__PURE__ */ jsx33(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
6172
5862
  }
6173
5863
  function DropdownMenuSubTrigger({
6174
5864
  className,
@@ -6176,7 +5866,7 @@ function DropdownMenuSubTrigger({
6176
5866
  children,
6177
5867
  ...props
6178
5868
  }) {
6179
- return /* @__PURE__ */ jsxs30(
5869
+ return /* @__PURE__ */ jsxs29(
6180
5870
  DropdownMenuPrimitive.SubTrigger,
6181
5871
  {
6182
5872
  "data-slot": "dropdown-menu-sub-trigger",
@@ -6193,7 +5883,7 @@ function DropdownMenuSubTrigger({
6193
5883
  ...props,
6194
5884
  children: [
6195
5885
  children,
6196
- /* @__PURE__ */ jsx34(ChevronRightIcon, { className: "ml-auto", size: 16 })
5886
+ /* @__PURE__ */ jsx33(ChevronRightIcon, { className: "ml-auto", size: 16 })
6197
5887
  ]
6198
5888
  }
6199
5889
  );
@@ -6202,7 +5892,7 @@ function DropdownMenuSubContent({
6202
5892
  className,
6203
5893
  ...props
6204
5894
  }) {
6205
- return /* @__PURE__ */ jsx34(
5895
+ return /* @__PURE__ */ jsx33(
6206
5896
  DropdownMenuPrimitive.SubContent,
6207
5897
  {
6208
5898
  "data-slot": "dropdown-menu-sub-content",
@@ -6221,14 +5911,8 @@ function DropdownMenuSubContent({
6221
5911
  );
6222
5912
  }
6223
5913
 
6224
- // src/components/ui/list-card.tsx
6225
- import * as React32 from "react";
6226
- import { ChevronRight as ChevronRight2, MoreVertical } from "lucide-react";
6227
-
6228
5914
  // src/components/ui/action-menu.tsx
6229
- import * as React31 from "react";
6230
- import { Dialog as DialogPrimitive4, Slot as Slot3 } from "radix-ui";
6231
- 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";
6232
5916
  var sheetRowClassName = cn(
6233
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",
6234
5918
  "border-t border-[var(--border-subtle)] text-[13px] font-medium leading-normal text-text-primary",
@@ -6250,9 +5934,9 @@ function ActionMenuSheet({
6250
5934
  onOpenAutoFocus,
6251
5935
  onCloseAutoFocus
6252
5936
  }) {
6253
- const pendingRef = React31.useRef(null);
6254
- const surfaceRef = React31.useRef(null);
6255
- const labelId = React31.useId();
5937
+ const pendingRef = React30.useRef(null);
5938
+ const surfaceRef = React30.useRef(null);
5939
+ const labelId = React30.useId();
6256
5940
  const handleOpenChange = (nextOpen) => {
6257
5941
  pendingRef.current = null;
6258
5942
  onOpenChange(nextOpen);
@@ -6280,9 +5964,9 @@ function ActionMenuSheet({
6280
5964
  pendingRef.current = null;
6281
5965
  item?.onSelect();
6282
5966
  };
6283
- return /* @__PURE__ */ jsx35(DialogPrimitive4.Root, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs31(DialogPrimitive4.Portal, { children: [
6284
- /* @__PURE__ */ jsx35(OverlayScrimLayer, { kind: "menu" }),
6285
- /* @__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(
6286
5970
  DialogPrimitive4.Content,
6287
5971
  {
6288
5972
  ref: surfaceRef,
@@ -6292,8 +5976,8 @@ function ActionMenuSheet({
6292
5976
  onCloseAutoFocus: handleCloseAutoFocus,
6293
5977
  ...description ? {} : { "aria-describedby": void 0 },
6294
5978
  children: [
6295
- /* @__PURE__ */ jsx35(OverlayGrabber, { always: true, ...swipe.handleProps }),
6296
- /* @__PURE__ */ jsx35(
5979
+ /* @__PURE__ */ jsx34(OverlayGrabber, { always: true, ...swipe.handleProps }),
5980
+ /* @__PURE__ */ jsx34(
6297
5981
  OverlayHeader,
6298
5982
  {
6299
5983
  kind: "menu",
@@ -6303,13 +5987,13 @@ function ActionMenuSheet({
6303
5987
  dragHandleProps: swipe.handleProps
6304
5988
  }
6305
5989
  ),
6306
- /* @__PURE__ */ jsx35(OverlayBody, { kind: "menu", children: groups.map((group, index) => /* @__PURE__ */ jsxs31(React31.Fragment, { children: [
6307
- index > 0 ? /* @__PURE__ */ jsx35("div", { role: "separator", className: sheetGroupSeparatorClassName }) : null,
6308
- /* @__PURE__ */ jsxs31("div", { role: "group", "aria-labelledby": group.label ? `${labelId}-${index}` : void 0, children: [
6309
- 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,
6310
5994
  group.items.map((item) => {
6311
5995
  const Icon = item.icon;
6312
- return /* @__PURE__ */ jsxs31(
5996
+ return /* @__PURE__ */ jsxs30(
6313
5997
  "button",
6314
5998
  {
6315
5999
  type: "button",
@@ -6319,10 +6003,10 @@ function ActionMenuSheet({
6319
6003
  disabled: item.disabled,
6320
6004
  onClick: () => handleSelect(item),
6321
6005
  children: [
6322
- Icon ? /* @__PURE__ */ jsx35(Icon, { "aria-hidden": true, size: 17, strokeWidth: 1.75, className: "shrink-0" }) : null,
6323
- /* @__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: [
6324
6008
  item.label,
6325
- item.description ? /* @__PURE__ */ jsx35("span", { className: sheetRowDescriptionClassName, children: item.description }) : null
6009
+ item.description ? /* @__PURE__ */ jsx34("span", { className: sheetRowDescriptionClassName, children: item.description }) : null
6326
6010
  ] })
6327
6011
  ]
6328
6012
  },
@@ -6338,7 +6022,7 @@ function ActionMenuSheet({
6338
6022
  }
6339
6023
  var readPresentation = () => window.matchMedia?.(OVERLAY_DESKTOP_QUERY).matches ?? true ? "dropdown" : "sheet";
6340
6024
  var subscribeNothing = () => () => void 0;
6341
- var useHydrated = () => React31.useSyncExternalStore(
6025
+ var useHydrated = () => React30.useSyncExternalStore(
6342
6026
  subscribeNothing,
6343
6027
  () => true,
6344
6028
  () => false
@@ -6353,10 +6037,10 @@ function ActionMenu({
6353
6037
  items,
6354
6038
  groups
6355
6039
  }) {
6356
- const [uncontrolledOpen, setUncontrolledOpen] = React31.useState(false);
6040
+ const [uncontrolledOpen, setUncontrolledOpen] = React30.useState(false);
6357
6041
  const hydrated = useHydrated();
6358
6042
  const open = (openProp ?? uncontrolledOpen) && hydrated;
6359
- const [shown, setShown] = React31.useState({
6043
+ const [shown, setShown] = React30.useState({
6360
6044
  open: false,
6361
6045
  presentation: "dropdown"
6362
6046
  });
@@ -6365,72 +6049,438 @@ function ActionMenu({
6365
6049
  if (open) presentation = readPresentation();
6366
6050
  setShown({ open, presentation });
6367
6051
  }
6368
- const triggerRef = React31.useRef(null);
6369
- const pendingRef = React31.useRef(null);
6370
- const setOpen = (nextOpen) => {
6371
- if (nextOpen) pendingRef.current = null;
6372
- if (openProp === void 0) setUncontrolledOpen(nextOpen);
6373
- onOpenChange?.(nextOpen);
6374
- };
6375
- const menuGroups = groups ?? [{ id: "items", items: items ?? [] }];
6376
- const handleDropdownCloseAutoFocus = (event) => {
6377
- const item = pendingRef.current;
6378
- pendingRef.current = null;
6379
- if (!item) return;
6380
- event.preventDefault();
6381
- triggerRef.current?.focus();
6382
- item.onSelect();
6383
- };
6384
- const handleSheetCloseAutoFocus = (event) => {
6385
- event.preventDefault();
6386
- triggerRef.current?.focus();
6387
- };
6388
- const triggerLabel = trigger.props["aria-label"];
6389
- return /* @__PURE__ */ jsxs31(Fragment13, { children: [
6390
- /* @__PURE__ */ jsxs31(DropdownMenu, { open: open && presentation === "dropdown", onOpenChange: setOpen, children: [
6391
- /* @__PURE__ */ jsx35(DropdownMenuTrigger, { asChild: true, "aria-expanded": open, children: /* @__PURE__ */ jsx35(Slot3.Root, { ref: triggerRef, children: trigger }) }),
6392
- /* @__PURE__ */ jsx35(DropdownMenuContent, { align: "end", onCloseAutoFocus: handleDropdownCloseAutoFocus, children: menuGroups.map((group, index) => /* @__PURE__ */ jsxs31(React31.Fragment, { children: [
6393
- index > 0 ? /* @__PURE__ */ jsx35(DropdownMenuSeparator, {}) : null,
6394
- /* @__PURE__ */ jsxs31(DropdownMenuGroup, { children: [
6395
- group.label ? /* @__PURE__ */ jsx35(DropdownMenuLabel, { children: group.label }) : null,
6396
- group.items.map((item) => {
6397
- const Icon = item.icon;
6398
- return /* @__PURE__ */ jsxs31(
6399
- DropdownMenuItem,
6400
- {
6401
- variant: item.destructive ? "destructive" : "default",
6402
- disabled: item.disabled,
6403
- onSelect: () => {
6404
- pendingRef.current = item;
6405
- },
6406
- children: [
6407
- Icon ? /* @__PURE__ */ jsx35(Icon, { "aria-hidden": true, size: 16, strokeWidth: 1.75 }) : null,
6408
- item.label
6409
- ]
6410
- },
6411
- item.id
6412
- );
6413
- })
6414
- ] })
6415
- ] }, group.id)) })
6416
- ] }),
6417
- /* @__PURE__ */ jsx35(
6418
- 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",
6419
6464
  {
6420
- open: open && presentation === "sheet",
6421
- onOpenChange: setOpen,
6422
- title: title ?? /* @__PURE__ */ jsx35("span", { className: "sr-only", children: triggerLabel }),
6423
- description,
6424
- closeLabel,
6425
- groups: menuGroups,
6426
- 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
+ }
6427
6474
  }
6428
- )
6475
+ ) }),
6476
+ /* @__PURE__ */ jsx36(DropdownMenuContent, { ...contentProps, children })
6429
6477
  ] });
6430
6478
  }
6431
6479
 
6432
6480
  // src/components/ui/list-card.tsx
6433
- 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";
6434
6484
  function lineTokens(value) {
6435
6485
  return React32.Children.toArray(value).filter((token) => token !== "");
6436
6486
  }
@@ -6440,7 +6490,7 @@ function MetaLine({
6440
6490
  first,
6441
6491
  last
6442
6492
  }) {
6443
- return /* @__PURE__ */ jsx36(
6493
+ return /* @__PURE__ */ jsx37(
6444
6494
  "span",
6445
6495
  {
6446
6496
  "data-slot": slot,
@@ -6448,14 +6498,14 @@ function MetaLine({
6448
6498
  "flex flex-wrap gap-x-[var(--space-3)] gap-y-[2px] text-[12px] leading-[16px] text-text-secondary",
6449
6499
  first ? "mt-[var(--space-1)]" : "mt-[2px]"
6450
6500
  ),
6451
- children: tokens.map((token, index) => /* @__PURE__ */ jsxs32(
6501
+ children: tokens.map((token, index) => /* @__PURE__ */ jsxs33(
6452
6502
  "span",
6453
6503
  {
6454
6504
  className: "max-w-full truncate whitespace-nowrap",
6455
6505
  title: typeof token === "string" || typeof token === "number" ? String(token) : void 0,
6456
6506
  children: [
6457
6507
  token,
6458
- 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
6459
6509
  ]
6460
6510
  },
6461
6511
  index
@@ -6466,7 +6516,7 @@ function MetaLine({
6466
6516
  var titleClassName = "line-clamp-2 text-[13px] font-medium leading-[18px] text-text-primary [overflow-wrap:anywhere] [word-break:keep-all]";
6467
6517
  var overlayClassName = cn(
6468
6518
  "text-inherit no-underline outline-none after:absolute after:inset-0 after:content-['']",
6469
- "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)]"
6470
6520
  );
6471
6521
  function ListCard({
6472
6522
  title,
@@ -6488,19 +6538,19 @@ function ListCard({
6488
6538
  const meta2 = lineTokens(meta?.[1]);
6489
6539
  const hasValue = value != null;
6490
6540
  const overlay = actions != null && (href != null || onClick != null);
6491
- const trailingNode = trailing === "chevron" ? /* @__PURE__ */ jsx36(
6541
+ const trailingNode = trailing === "chevron" ? /* @__PURE__ */ jsx37(
6492
6542
  ChevronRight2,
6493
6543
  {
6494
6544
  "data-slot": `${slot}-suffix`,
6495
6545
  "aria-hidden": true,
6496
6546
  className: "size-[var(--space-4)] shrink-0 text-text-tertiary"
6497
6547
  }
6498
- ) : 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 });
6499
6549
  const bottomIcon = actions != null && trailingNode != null;
6500
6550
  const hasEnd = hasValue || actions != null || trailingNode != null;
6501
6551
  const rootClassName = cn(
6502
6552
  "relative grid w-full min-w-0 items-start gap-x-[var(--space-2)] whitespace-normal text-left outline-none",
6503
- "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)]",
6504
6554
  // An empty end keeps the 16px chevron track.
6505
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]",
6506
6556
  // 84 = the ⋮ hit area (2 above the top to 42 below) meets the chevron's (42 above the bottom to 2 below).
@@ -6508,7 +6558,7 @@ function ListCard({
6508
6558
  href && !overlay && "after:absolute after:inset-0 after:content-['']",
6509
6559
  className
6510
6560
  );
6511
- const titleNode = /* @__PURE__ */ jsx36(
6561
+ const titleNode = /* @__PURE__ */ jsx37(
6512
6562
  "span",
6513
6563
  {
6514
6564
  "data-slot": `${slot}-title`,
@@ -6517,18 +6567,18 @@ function ListCard({
6517
6567
  children: overlay && href != null ? React32.createElement(linkComponent ?? "a", { ...linkProps, href, className: overlayClassName }, title) : title
6518
6568
  }
6519
6569
  );
6520
- const content = /* @__PURE__ */ jsxs32(Fragment14, { children: [
6521
- leading != null ? /* @__PURE__ */ jsx36("span", { className: "flex min-h-[18px] items-center", children: leading }) : null,
6522
- /* @__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: [
6523
6573
  overlay && href == null ? (
6524
6574
  // A block button keeps the title's two-line clamp inside it.
6525
- /* @__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 })
6526
6576
  ) : titleNode,
6527
- meta1.length > 0 ? /* @__PURE__ */ jsx36(MetaLine, { tokens: meta1, slot: `${slot}-meta1`, first: true, last: meta2.length === 0 }) : null,
6528
- meta2.length > 0 ? /* @__PURE__ */ jsx36(MetaLine, { tokens: meta2, slot: `${slot}-meta2`, first: meta1.length === 0, last: true }) : null,
6529
- 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: [
6530
- status != null ? /* @__PURE__ */ jsx36("span", { "data-slot": `${slot}-badge`, className: "flex items-center", children: status }) : null,
6531
- 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(
6532
6582
  "span",
6533
6583
  {
6534
6584
  "data-slot": `${slot}-caption`,
@@ -6538,8 +6588,8 @@ function ListCard({
6538
6588
  ) : null
6539
6589
  ] }) : null
6540
6590
  ] }),
6541
- hasEnd ? /* @__PURE__ */ jsxs32("span", { "data-slot": `${slot}-trailing`, className: "flex flex-col items-end justify-between self-stretch", children: [
6542
- /* @__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(
6543
6593
  "span",
6544
6594
  {
6545
6595
  className: cn(
@@ -6547,13 +6597,13 @@ function ListCard({
6547
6597
  actions != null ? "-mr-[var(--space-2)] gap-[var(--space-1)]" : "gap-[var(--space-2)]"
6548
6598
  ),
6549
6599
  children: [
6550
- hasValue ? /* @__PURE__ */ jsx36("span", { "data-slot": `${slot}-value`, className: "text-[13px] leading-[20px] text-text-secondary tabular-nums", children: value }) : null,
6551
- 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(
6552
6602
  ActionMenu,
6553
6603
  {
6554
6604
  title: typeof title === "string" ? title : void 0,
6555
6605
  items: [...actions.items],
6556
- trigger: /* @__PURE__ */ jsx36(
6606
+ trigger: /* @__PURE__ */ jsx37(
6557
6607
  IconButton,
6558
6608
  {
6559
6609
  icon: MoreVertical,
@@ -6573,16 +6623,16 @@ function ListCard({
6573
6623
  ] });
6574
6624
  if (href && !overlay) {
6575
6625
  const LinkComponent = linkComponent ?? "a";
6576
- return /* @__PURE__ */ jsx36(LinkComponent, { ...linkProps, href, className: rootClassName, children: content });
6626
+ return /* @__PURE__ */ jsx37(LinkComponent, { ...linkProps, href, className: rootClassName, children: content });
6577
6627
  }
6578
6628
  if (onClick && !overlay) {
6579
- return /* @__PURE__ */ jsx36("button", { type: "button", onClick, className: rootClassName, children: content });
6629
+ return /* @__PURE__ */ jsx37("button", { type: "button", onClick, className: rootClassName, children: content });
6580
6630
  }
6581
- return /* @__PURE__ */ jsx36("div", { className: rootClassName, children: content });
6631
+ return /* @__PURE__ */ jsx37("div", { className: rootClassName, children: content });
6582
6632
  }
6583
6633
 
6584
6634
  // src/components/ui/data-table.tsx
6585
- 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";
6586
6636
  var dataTableVariants = cva13(
6587
6637
  [
6588
6638
  "relative overflow-hidden rounded-[var(--radius-md)] border border-[var(--border-subtle)]",
@@ -6611,7 +6661,9 @@ var dataTableRowVariants = cva13(
6611
6661
  {
6612
6662
  variants: {
6613
6663
  interactive: {
6614
- 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)]",
6615
6667
  false: ""
6616
6668
  },
6617
6669
  selected: {
@@ -6633,9 +6685,159 @@ var alignmentClass = {
6633
6685
  function getRowId(row, keyField) {
6634
6686
  return String(row[keyField]);
6635
6687
  }
6636
- function getGridTemplate(columns, selectable, expandable) {
6688
+ function getGridTemplate(columns, selectable, expandable, hasRowActions) {
6637
6689
  const columnWidths = columns.map((column) => column.width ?? "1fr");
6638
- 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
+ );
6639
6841
  }
6640
6842
  function getRenderedCell(row, column) {
6641
6843
  if (column.render) {
@@ -6665,7 +6867,7 @@ function isInteractiveTarget(target) {
6665
6867
  function SortIcon({ sort, columnKey }) {
6666
6868
  const isActive = sort?.key === columnKey;
6667
6869
  if (!isActive) {
6668
- return /* @__PURE__ */ jsx37(
6870
+ return /* @__PURE__ */ jsx38(
6669
6871
  ChevronsUpDown,
6670
6872
  {
6671
6873
  "aria-hidden": "true",
@@ -6677,7 +6879,7 @@ function SortIcon({ sort, columnKey }) {
6677
6879
  );
6678
6880
  }
6679
6881
  const Icon = sort.dir === "asc" ? ChevronUp2 : ChevronDown5;
6680
- return /* @__PURE__ */ jsx37(
6882
+ return /* @__PURE__ */ jsx38(
6681
6883
  Icon,
6682
6884
  {
6683
6885
  "aria-hidden": "true",
@@ -6695,8 +6897,8 @@ function MobileSortMenu({
6695
6897
  onSortChange
6696
6898
  }) {
6697
6899
  const active = sortBy ? columns.find((column) => column.key === sortBy.key) : void 0;
6698
- return /* @__PURE__ */ jsxs33(DropdownMenu, { children: [
6699
- /* @__PURE__ */ jsx37(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs33(
6900
+ return /* @__PURE__ */ jsxs34(DropdownMenu, { children: [
6901
+ /* @__PURE__ */ jsx38(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs34(
6700
6902
  Button,
6701
6903
  {
6702
6904
  "data-slot": "data-table-mobile-sort-button",
@@ -6705,26 +6907,26 @@ function MobileSortMenu({
6705
6907
  size: "sm",
6706
6908
  className: "ml-auto min-w-0",
6707
6909
  children: [
6708
- active && sortBy ? /* @__PURE__ */ jsxs33(Fragment15, { children: [
6709
- /* @__PURE__ */ jsx37("span", { className: "sr-only", children: "\uC815\uB82C " }),
6710
- /* @__PURE__ */ jsx37("span", { className: "truncate", children: active.header }),
6711
- /* @__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: [
6712
6914
  ", ",
6713
6915
  sortBy.dir === "asc" ? "\uC624\uB984\uCC28\uC21C" : "\uB0B4\uB9BC\uCC28\uC21C"
6714
6916
  ] })
6715
6917
  ] }) : "\uC815\uB82C",
6716
- /* @__PURE__ */ jsx37(SortIcon, { sort: sortBy, columnKey: active?.key ?? "" })
6918
+ /* @__PURE__ */ jsx38(SortIcon, { sort: sortBy, columnKey: active?.key ?? "" })
6717
6919
  ]
6718
6920
  }
6719
6921
  ) }),
6720
- /* @__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(
6721
6923
  DropdownMenuRadioItem,
6722
6924
  {
6723
6925
  value: column.key,
6724
6926
  onSelect: () => onSortChange?.(column.key, getNextSort(sortBy, column.key)),
6725
6927
  children: [
6726
- /* @__PURE__ */ jsx37("span", { className: "truncate", children: column.header }),
6727
- 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
6728
6930
  ]
6729
6931
  },
6730
6932
  column.key
@@ -6737,35 +6939,38 @@ function MobileToolbar({
6737
6939
  onSortChange,
6738
6940
  selectable,
6739
6941
  selectAllChecked,
6942
+ selectAllDisabled,
6740
6943
  onToggleAll
6741
6944
  }) {
6742
6945
  const sortableColumns = columns.filter((column) => column.sortable);
6743
6946
  if (!selectable && sortableColumns.length === 0) {
6744
6947
  return null;
6745
6948
  }
6746
- return /* @__PURE__ */ jsxs33(
6949
+ return /* @__PURE__ */ jsxs34(
6747
6950
  "div",
6748
6951
  {
6749
6952
  "data-slot": "data-table-mobile-toolbar",
6750
6953
  className: "flex min-w-0 items-center gap-[var(--space-2)] px-[var(--space-4)] py-[var(--space-2)]",
6751
6954
  children: [
6752
- selectable ? /* @__PURE__ */ jsx37(SelectAllCheckbox, { checked: selectAllChecked, onToggleAll }) : null,
6753
- 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
6754
6957
  ]
6755
6958
  }
6756
6959
  );
6757
6960
  }
6758
6961
  function SelectAllCheckbox({
6759
6962
  checked,
6963
+ disabled,
6760
6964
  onToggleAll
6761
6965
  }) {
6762
- return /* @__PURE__ */ jsx37(
6966
+ return /* @__PURE__ */ jsx38(
6763
6967
  Checkbox,
6764
6968
  {
6765
6969
  "aria-label": "\uC804\uCCB4 \uD589 \uC120\uD0DD",
6766
6970
  checked,
6971
+ disabled,
6767
6972
  onCheckedChange: (nextChecked) => onToggleAll(nextChecked === true),
6768
- 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" })
6769
6974
  }
6770
6975
  );
6771
6976
  }
@@ -6774,15 +6979,17 @@ function RowCheckbox({
6774
6979
  rowId,
6775
6980
  columns,
6776
6981
  selected,
6982
+ selectionBlocked,
6777
6983
  onToggle
6778
6984
  }) {
6779
- return /* @__PURE__ */ jsx37(
6985
+ return /* @__PURE__ */ jsx38(
6780
6986
  Checkbox,
6781
6987
  {
6782
6988
  "aria-label": `${String(row[columns[0]?.key] ?? rowId)} \uD589 \uC120\uD0DD`,
6783
6989
  checked: selected,
6990
+ disabled: selectionBlocked,
6784
6991
  onCheckedChange: (nextChecked) => onToggle(rowId, nextChecked === true),
6785
- children: /* @__PURE__ */ jsxs33("span", { className: "sr-only", children: [
6992
+ children: /* @__PURE__ */ jsxs34("span", { className: "sr-only", children: [
6786
6993
  rowId,
6787
6994
  " \uD589 \uC120\uD0DD"
6788
6995
  ] })
@@ -6799,17 +7006,17 @@ function SkeletonRows({
6799
7006
  // role="table"의 허용 자식은 row/rowgroup뿐이라 컨테이너는 rowgroup이어야 한다.
6800
7007
  // 로딩 알림은 그 안의 row/cell 안에 둔다 — 종전에는 컨테이너가 role="status"라
6801
7008
  // aria-required-children(Critical)이 났다.
6802
- /* @__PURE__ */ jsxs33("div", { role: "rowgroup", children: [
6803
- /* @__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" }) }) }),
6804
- 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(
6805
7012
  "div",
6806
7013
  {
6807
7014
  "data-slot": "data-table-skeleton-row",
6808
7015
  className: "grid min-h-[48px] items-center border-t border-[var(--border-subtle)]",
6809
7016
  style: { gridTemplateColumns },
6810
7017
  children: [
6811
- selectable ? /* @__PURE__ */ jsx37("div", { "aria-hidden": "true", className: "px-[var(--space-4)]" }) : null,
6812
- 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(
6813
7020
  "div",
6814
7021
  {
6815
7022
  className: cn(
@@ -6826,24 +7033,25 @@ function SkeletonRows({
6826
7033
  );
6827
7034
  }
6828
7035
  function MobileSkeletonCards({ count }) {
6829
- 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(
6830
7037
  "div",
6831
7038
  {
6832
7039
  "data-slot": "data-table-mobile-skeleton-card",
6833
7040
  className: "flex flex-col gap-[var(--space-2)] border-t border-[var(--border-subtle)] px-[var(--space-4)] py-[var(--space-4)]",
6834
7041
  children: [
6835
- /* @__PURE__ */ jsx37("div", { className: "h-[14px] w-[72%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" }),
6836
- /* @__PURE__ */ jsx37("div", { className: "h-[12px] w-[56%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" }),
6837
- /* @__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)]" })
6838
7045
  ]
6839
7046
  },
6840
7047
  rowIndex
6841
7048
  )) });
6842
7049
  }
6843
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)]";
6844
7052
  var rowLinkClass = cn(
6845
7053
  "text-inherit no-underline outline-none after:absolute after:inset-0 after:content-['']",
6846
- "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)]"
6847
7055
  );
6848
7056
  var expandedPanelClass = cn(
6849
7057
  "grid grid-rows-[0fr] invisible data-[state=open]:grid-rows-[1fr] data-[state=open]:visible",
@@ -6883,6 +7091,7 @@ function DataTableRowView({
6883
7091
  columns,
6884
7092
  selectable,
6885
7093
  selected,
7094
+ selectionBlocked,
6886
7095
  visuallySelected,
6887
7096
  href,
6888
7097
  activatable,
@@ -6891,13 +7100,15 @@ function DataTableRowView({
6891
7100
  onActivate,
6892
7101
  onRowContextMenu,
6893
7102
  expand,
7103
+ rowActions,
7104
+ getRowActionsLabel,
6894
7105
  gridTemplateColumns,
6895
7106
  ariaRowIndex
6896
7107
  }) {
6897
7108
  const linked = Boolean(LinkComponent && href);
6898
7109
  const handlers = useActivationHandlers({ row, href, activatable, onActivate });
6899
7110
  const opened = useOpenedOnce(expand?.expanded ?? false);
6900
- const dataRow = /* @__PURE__ */ jsxs33(
7111
+ const dataRow = /* @__PURE__ */ jsxs34(
6901
7112
  "div",
6902
7113
  {
6903
7114
  "data-slot": "data-table-row",
@@ -6917,26 +7128,26 @@ function DataTableRowView({
6917
7128
  } : handlers.onClick,
6918
7129
  onKeyDown: handlers.onKeyDown,
6919
7130
  children: [
6920
- 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,
6921
7132
  columns.map((column, columnIndex) => {
6922
7133
  const align = column.align ?? "left";
6923
7134
  const content = getRenderedCell(row, column);
6924
- return /* @__PURE__ */ jsx37(
7135
+ return /* @__PURE__ */ jsx38(
6925
7136
  "div",
6926
7137
  {
6927
7138
  "data-slot": "data-table-cell",
6928
7139
  role: "cell",
6929
7140
  className: cn(
6930
- "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)]",
6931
7142
  alignmentClass[align],
6932
7143
  column.tabular ? "font-[family-name:var(--font-display)] tabular-nums" : null
6933
7144
  ),
6934
- 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 })
6935
7146
  },
6936
7147
  column.key
6937
7148
  );
6938
7149
  }),
6939
- 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(
6940
7151
  IconButton,
6941
7152
  {
6942
7153
  icon: ChevronRight3,
@@ -6952,16 +7163,17 @@ function DataTableRowView({
6952
7163
  ),
6953
7164
  onClick: () => expand.onToggle(rowId)
6954
7165
  }
6955
- ) }) : null
7166
+ ) }) : null,
7167
+ rowActions && getRowActionsLabel ? /* @__PURE__ */ jsx38(RowActionsCell, { row, rowId, rowActions, getRowActionsLabel }) : null
6956
7168
  ]
6957
7169
  }
6958
7170
  );
6959
7171
  if (!expand) {
6960
7172
  return dataRow;
6961
7173
  }
6962
- return /* @__PURE__ */ jsxs33(Fragment15, { children: [
7174
+ return /* @__PURE__ */ jsxs34(Fragment16, { children: [
6963
7175
  dataRow,
6964
- /* @__PURE__ */ jsx37(
7176
+ /* @__PURE__ */ jsx38(
6965
7177
  "div",
6966
7178
  {
6967
7179
  role: "row",
@@ -6969,12 +7181,12 @@ function DataTableRowView({
6969
7181
  "data-row-id": rowId,
6970
7182
  "data-state": expand.expanded ? "open" : "closed",
6971
7183
  className: expandedPanelClass,
6972
- children: /* @__PURE__ */ jsx37(
7184
+ children: /* @__PURE__ */ jsx38(
6973
7185
  "div",
6974
7186
  {
6975
7187
  role: "cell",
6976
7188
  id: expand.panelId,
6977
- "aria-colspan": columns.length + (selectable ? 2 : 1),
7189
+ "aria-colspan": columns.length + (selectable ? 2 : 1) + (rowActions ? 1 : 0),
6978
7190
  className: "min-h-0 min-w-0 overflow-hidden",
6979
7191
  children: opened ? expand.render(row) : null
6980
7192
  }
@@ -6989,6 +7201,7 @@ function DataTableMobileCardView({
6989
7201
  columns,
6990
7202
  selectable,
6991
7203
  selected,
7204
+ selectionBlocked,
6992
7205
  visuallySelected,
6993
7206
  href,
6994
7207
  activatable,
@@ -6997,6 +7210,8 @@ function DataTableMobileCardView({
6997
7210
  onActivate,
6998
7211
  onRowContextMenu,
6999
7212
  expand,
7213
+ rowActions,
7214
+ getRowActionsLabel,
7000
7215
  getMobileCardContent,
7001
7216
  ariaPosInSet,
7002
7217
  ariaSetSize,
@@ -7004,15 +7219,21 @@ function DataTableMobileCardView({
7004
7219
  }) {
7005
7220
  const linked = Boolean(LinkComponent && href);
7006
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
+ }
7007
7228
  const navigable = linked || activatable;
7008
7229
  const opened = useOpenedOnce(expand?.expanded ?? false);
7009
- const leading = selectable || content.leading != null ? /* @__PURE__ */ jsxs33("span", { className: "flex items-center gap-[var(--space-2)]", children: [
7010
- 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,
7011
7232
  content.leading
7012
7233
  ] }) : void 0;
7013
7234
  let title = content.title;
7014
7235
  if (expand) {
7015
- title = /* @__PURE__ */ jsx37(
7236
+ title = /* @__PURE__ */ jsx38(
7016
7237
  "button",
7017
7238
  {
7018
7239
  type: "button",
@@ -7022,24 +7243,24 @@ function DataTableMobileCardView({
7022
7243
  "aria-controls": expand.panelId,
7023
7244
  className: cn(rowLinkClass, "block w-full text-left"),
7024
7245
  onClick: () => expand.onToggle(rowId),
7025
- children: /* @__PURE__ */ jsx37("span", { className: "line-clamp-2", children: content.title })
7246
+ children: /* @__PURE__ */ jsx38("span", { className: "line-clamp-2", children: content.title })
7026
7247
  }
7027
7248
  );
7028
7249
  } else if (linked && LinkComponent) {
7029
- 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 });
7030
7251
  } else if (activatable) {
7031
- title = /* @__PURE__ */ jsx37(
7252
+ title = /* @__PURE__ */ jsx38(
7032
7253
  "button",
7033
7254
  {
7034
7255
  type: "button",
7035
7256
  "data-slot": "data-table-row-link",
7036
7257
  className: cn(rowLinkClass, "block w-full text-left"),
7037
7258
  onClick: (event) => onActivate(row, href, event),
7038
- children: /* @__PURE__ */ jsx37("span", { className: "line-clamp-2", children: content.title })
7259
+ children: /* @__PURE__ */ jsx38("span", { className: "line-clamp-2", children: content.title })
7039
7260
  }
7040
7261
  );
7041
7262
  }
7042
- return /* @__PURE__ */ jsxs33(
7263
+ return /* @__PURE__ */ jsxs34(
7043
7264
  "div",
7044
7265
  {
7045
7266
  "data-slot": "data-table-mobile-card",
@@ -7058,7 +7279,7 @@ function DataTableMobileCardView({
7058
7279
  ),
7059
7280
  onContextMenu: (event) => onRowContextMenu?.(rowId, event),
7060
7281
  children: [
7061
- /* @__PURE__ */ jsx37(
7282
+ /* @__PURE__ */ jsx38(
7062
7283
  ListCard,
7063
7284
  {
7064
7285
  className: cn(
@@ -7071,7 +7292,7 @@ function DataTableMobileCardView({
7071
7292
  caption: content.date,
7072
7293
  value: content.value,
7073
7294
  leading,
7074
- trailing: expand ? /* @__PURE__ */ jsx37(
7295
+ trailing: expand ? /* @__PURE__ */ jsx38(
7075
7296
  ChevronRight3,
7076
7297
  {
7077
7298
  "aria-hidden": true,
@@ -7079,17 +7300,17 @@ function DataTableMobileCardView({
7079
7300
  className: cn("block size-[var(--space-4)] shrink-0 text-text-tertiary data-[state=open]:rotate-90", expandChevronClass)
7080
7301
  }
7081
7302
  ) : navigable ? "chevron" : "none",
7082
- actions: content.actions
7303
+ actions
7083
7304
  }
7084
7305
  ),
7085
- expand ? /* @__PURE__ */ jsx37(
7306
+ expand ? /* @__PURE__ */ jsx38(
7086
7307
  "div",
7087
7308
  {
7088
7309
  id: expand.panelId,
7089
7310
  "data-slot": "data-table-expanded",
7090
7311
  "data-state": expand.expanded ? "open" : "closed",
7091
7312
  className: expandedPanelClass,
7092
- 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 })
7093
7314
  }
7094
7315
  ) : null
7095
7316
  ]
@@ -7418,6 +7639,7 @@ function DataTableInner({
7418
7639
  keyField,
7419
7640
  getMobileCardContent,
7420
7641
  selectable = false,
7642
+ isRowSelectable,
7421
7643
  selectedIds,
7422
7644
  onSelectionChange,
7423
7645
  selectionUnit = "\uAC1C",
@@ -7436,12 +7658,18 @@ function DataTableInner({
7436
7658
  getExpandLabel,
7437
7659
  expandedIds,
7438
7660
  onExpandedChange,
7661
+ rowActions,
7662
+ getRowActionsLabel,
7439
7663
  skeletonRowCount = 8,
7664
+ footer,
7440
7665
  "aria-label": ariaLabel = "\uB370\uC774\uD130 \uD14C\uC774\uBE14",
7441
7666
  ...props
7442
7667
  }, ref) {
7443
7668
  const virtualOptions = virtual ? virtual === true ? {} : virtual : null;
7444
7669
  const isVirtual = virtualOptions !== null;
7670
+ if (isVirtual && columns.some((column) => column.wrap)) {
7671
+ warnWrapVirtualOnce();
7672
+ }
7445
7673
  const rootRef = React33.useRef(null);
7446
7674
  const desktopRef = React33.useRef(null);
7447
7675
  const headerRef = React33.useRef(null);
@@ -7478,13 +7706,19 @@ function DataTableInner({
7478
7706
  mobile: () => mobileListRef.current ?? mobileRef.current
7479
7707
  }
7480
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));
7481
7713
  const resolvedSelectedIds = selectedIds ?? /* @__PURE__ */ new Set();
7482
- const selectedCount = rowIds.filter((id) => resolvedSelectedIds.has(id)).length;
7483
- 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;
7484
7716
  const partiallySelected = selectedCount > 0 && !allVisibleRowsSelected;
7485
7717
  const selectAllChecked = partiallySelected ? "indeterminate" : allVisibleRowsSelected;
7718
+ const selectAllDisabled = selectableRowIds.length === 0;
7486
7719
  const expandable = renderExpanded != null;
7487
- const gridTemplateColumns = getGridTemplate(columns, selectable, expandable);
7720
+ const hasRowActions = rowActions != null;
7721
+ const gridTemplateColumns = getGridTemplate(columns, selectable, expandable, hasRowActions);
7488
7722
  const panelIdBase = React33.useId();
7489
7723
  const [ownExpandedIds, setOwnExpandedIds] = React33.useState(() => /* @__PURE__ */ new Set());
7490
7724
  const resolvedExpandedIds = expandedIds ?? ownExpandedIds;
@@ -7501,18 +7735,22 @@ function DataTableInner({
7501
7735
  onExpandedChange?.(nextIds);
7502
7736
  };
7503
7737
  const emitSelection = (nextIds) => {
7738
+ blockedIds.forEach((id) => nextIds.delete(id));
7504
7739
  onSelectionChange?.(nextIds);
7505
7740
  };
7506
7741
  const toggleAllRows = (checked) => {
7507
7742
  const nextIds = new Set(resolvedSelectedIds);
7508
7743
  if (checked) {
7509
- rowIds.forEach((id) => nextIds.add(id));
7744
+ selectableRowIds.forEach((id) => nextIds.add(id));
7510
7745
  } else {
7511
- rowIds.forEach((id) => nextIds.delete(id));
7746
+ selectableRowIds.forEach((id) => nextIds.delete(id));
7512
7747
  }
7513
7748
  emitSelection(nextIds);
7514
7749
  };
7515
7750
  const toggleRow = (id, checked) => {
7751
+ if (blockedIds.has(id)) {
7752
+ return;
7753
+ }
7516
7754
  const nextIds = new Set(resolvedSelectedIds);
7517
7755
  if (checked) {
7518
7756
  nextIds.add(id);
@@ -7528,9 +7766,44 @@ function DataTableInner({
7528
7766
  window.location.assign(href);
7529
7767
  }
7530
7768
  };
7531
- 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 });
7532
7805
  useIsomorphicLayoutEffect(() => {
7533
- latestHandlers.current = { toggleRow, activateRow, onRowContextMenu };
7806
+ latestHandlers.current = { toggleRow, activateRow, onRowContextMenu, handleRowContextMenu };
7534
7807
  });
7535
7808
  const stableToggleRow = React33.useCallback(
7536
7809
  (id, checked) => latestHandlers.current.toggleRow(id, checked),
@@ -7544,9 +7817,14 @@ function DataTableInner({
7544
7817
  (rowId, event) => latestHandlers.current.onRowContextMenu?.(rowId, event),
7545
7818
  []
7546
7819
  );
7820
+ const stableHandleRowContextMenu = React33.useCallback(
7821
+ (rowId, event) => latestHandlers.current.handleRowContextMenu?.(rowId, event),
7822
+ []
7823
+ );
7547
7824
  const getItemProps = (row, layout, index) => {
7548
7825
  const rowId = getRowId(row, keyField);
7549
- const selected = resolvedSelectedIds.has(rowId);
7826
+ const selectionBlocked = blockedIds.has(rowId);
7827
+ const selected = !selectionBlocked && resolvedSelectedIds.has(rowId);
7550
7828
  const href = rowHref?.(row);
7551
7829
  const linked = Boolean(linkComponent && href);
7552
7830
  return {
@@ -7555,13 +7833,16 @@ function DataTableInner({
7555
7833
  columns,
7556
7834
  selectable,
7557
7835
  selected,
7558
- visuallySelected: selected || rowId === activeRowId,
7836
+ selectionBlocked,
7837
+ visuallySelected: selected || rowId === activeRowId || rowId === contextMenu?.rowId,
7559
7838
  href,
7560
7839
  activatable: !linked && Boolean(href || onRowClick),
7561
7840
  LinkComponent: linkComponent,
7562
7841
  onToggle: isVirtual ? stableToggleRow : toggleRow,
7563
7842
  onActivate: isVirtual ? stableActivateRow : activateRow,
7564
- onRowContextMenu: isVirtual ? stableRowContextMenu : onRowContextMenu,
7843
+ onRowContextMenu: layout === "desktop" ? isVirtual ? stableHandleRowContextMenu : handleRowContextMenu : isVirtual ? stableRowContextMenu : onRowContextMenu,
7844
+ rowActions,
7845
+ getRowActionsLabel,
7565
7846
  expand: renderExpanded && getExpandLabel ? {
7566
7847
  expanded: resolvedExpandedIds.has(rowId),
7567
7848
  label: getExpandLabel(row),
@@ -7599,7 +7880,7 @@ function DataTableInner({
7599
7880
  const mobileSlice = sliceFor("mobile");
7600
7881
  const RowComponent = isVirtual ? MemoDataTableRow : DataTableRowView;
7601
7882
  const CardComponent = isVirtual ? MemoDataTableMobileCard : DataTableMobileCardView;
7602
- return /* @__PURE__ */ jsxs33(
7883
+ return /* @__PURE__ */ jsxs34(
7603
7884
  "div",
7604
7885
  {
7605
7886
  ref: setRootRef,
@@ -7613,7 +7894,7 @@ function DataTableInner({
7613
7894
  ),
7614
7895
  ...props,
7615
7896
  children: [
7616
- selectable && announceSelection ? /* @__PURE__ */ jsx37(
7897
+ selectable && announceSelection ? /* @__PURE__ */ jsx38(
7617
7898
  "div",
7618
7899
  {
7619
7900
  "data-slot": "data-table-selection-status",
@@ -7622,30 +7903,30 @@ function DataTableInner({
7622
7903
  children: selectedCount > 0 ? `${selectedCount.toLocaleString("ko-KR")}${selectionUnit} \uC120\uD0DD\uB428` : ""
7623
7904
  }
7624
7905
  ) : null,
7625
- loading && data.length > 0 ? /* @__PURE__ */ jsx37(
7906
+ loading && data.length > 0 ? /* @__PURE__ */ jsx38(
7626
7907
  "div",
7627
7908
  {
7628
7909
  "data-slot": "data-table-progress",
7629
7910
  "aria-hidden": "true",
7630
7911
  className: "absolute left-0 right-0 top-0 z-10 h-[2px] overflow-hidden bg-[var(--action-selected)]",
7631
- 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)]" })
7632
7913
  }
7633
7914
  ) : null,
7634
- /* @__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(
7635
7916
  "div",
7636
7917
  {
7637
7918
  role: "table",
7638
7919
  "aria-label": ariaLabel,
7639
7920
  "aria-rowcount": isVirtual && data.length > 0 ? data.length + 1 : void 0,
7640
7921
  children: [
7641
- /* @__PURE__ */ jsxs33(
7922
+ /* @__PURE__ */ jsxs34(
7642
7923
  "div",
7643
7924
  {
7644
7925
  ref: headerRef,
7645
7926
  "data-slot": "data-table-header",
7646
7927
  role: "row",
7647
7928
  className: cn(
7648
- "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",
7649
7930
  // Virtual lists are long: the header sticks inside the scroll container,
7650
7931
  // below an inline BulkActionBar band (40px, --z-sticky) rendered before
7651
7932
  // the table — band on top, header under it, rows beneath both.
@@ -7653,12 +7934,12 @@ function DataTableInner({
7653
7934
  ),
7654
7935
  style: { gridTemplateColumns },
7655
7936
  children: [
7656
- 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,
7657
7938
  columns.map((column) => {
7658
7939
  const align = column.align ?? "left";
7659
7940
  const nextSort = getNextSort(sortBy, column.key);
7660
7941
  const ariaSort = sortBy?.key === column.key ? sortBy.dir === "asc" ? "ascending" : "descending" : void 0;
7661
- return /* @__PURE__ */ jsx37(
7942
+ return /* @__PURE__ */ jsx38(
7662
7943
  "div",
7663
7944
  {
7664
7945
  role: "columnheader",
@@ -7667,7 +7948,7 @@ function DataTableInner({
7667
7948
  "flex min-w-0 items-center gap-[var(--space-1)] px-[var(--space-4)] py-[var(--space-2)]",
7668
7949
  alignmentClass[align]
7669
7950
  ),
7670
- children: column.sortable ? /* @__PURE__ */ jsxs33(
7951
+ children: column.sortable ? /* @__PURE__ */ jsxs34(
7671
7952
  "button",
7672
7953
  {
7673
7954
  type: "button",
@@ -7678,20 +7959,21 @@ function DataTableInner({
7678
7959
  ),
7679
7960
  onClick: () => onSortChange?.(column.key, nextSort),
7680
7961
  children: [
7681
- /* @__PURE__ */ jsx37("span", { className: "truncate", children: column.header }),
7682
- /* @__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 })
7683
7964
  ]
7684
7965
  }
7685
- ) : /* @__PURE__ */ jsx37("span", { className: "truncate", children: column.header })
7966
+ ) : /* @__PURE__ */ jsx38("span", { className: column.hideHeader ? "sr-only" : "truncate", children: column.header })
7686
7967
  },
7687
7968
  column.key
7688
7969
  );
7689
7970
  }),
7690
- expandable ? /* @__PURE__ */ jsx37("div", { role: "cell" }) : null
7971
+ expandable ? /* @__PURE__ */ jsx38("div", { role: "cell" }) : null,
7972
+ hasRowActions ? /* @__PURE__ */ jsx38("div", { role: "cell" }) : null
7691
7973
  ]
7692
7974
  }
7693
7975
  ),
7694
- loading && data.length === 0 ? /* @__PURE__ */ jsx37(
7976
+ loading && data.length === 0 ? /* @__PURE__ */ jsx38(
7695
7977
  SkeletonRows,
7696
7978
  {
7697
7979
  columns,
@@ -7702,7 +7984,7 @@ function DataTableInner({
7702
7984
  ) : data.length === 0 ? (
7703
7985
  /* role="table" 직계 자식은 row/rowgroup이어야 한다. data-slot과 테두리는
7704
7986
  그대로 유지해 시각 계약을 깨지 않는다(빈 상태에서도 표가 테두리를 그린다). */
7705
- /* @__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(
7706
7988
  "div",
7707
7989
  {
7708
7990
  role: "cell",
@@ -7712,9 +7994,9 @@ function DataTableInner({
7712
7994
  children: emptyState
7713
7995
  }
7714
7996
  ) }) })
7715
- ) : /* @__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) => {
7716
7998
  const itemProps = getItemProps(row, "desktop", desktopSlice.start + index);
7717
- return /* @__PURE__ */ jsx37(
7999
+ return /* @__PURE__ */ jsx38(
7718
8000
  RowComponent,
7719
8001
  {
7720
8002
  ...itemProps,
@@ -7727,8 +8009,8 @@ function DataTableInner({
7727
8009
  ]
7728
8010
  }
7729
8011
  ) }),
7730
- /* @__PURE__ */ jsxs33("div", { ref: mobileRef, "data-slot": "data-table-mobile", className: "lg:hidden", children: [
7731
- /* @__PURE__ */ jsx37(
8012
+ /* @__PURE__ */ jsxs34("div", { ref: mobileRef, "data-slot": "data-table-mobile", className: "lg:hidden", children: [
8013
+ /* @__PURE__ */ jsx38(
7732
8014
  MobileToolbar,
7733
8015
  {
7734
8016
  columns,
@@ -7736,10 +8018,11 @@ function DataTableInner({
7736
8018
  onSortChange,
7737
8019
  selectable,
7738
8020
  selectAllChecked,
8021
+ selectAllDisabled,
7739
8022
  onToggleAll: toggleAllRows
7740
8023
  }
7741
8024
  ),
7742
- 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(
7743
8026
  "div",
7744
8027
  {
7745
8028
  ref: mobileListRef,
@@ -7750,7 +8033,7 @@ function DataTableInner({
7750
8033
  children: mobileSlice.rows.map((row, index) => {
7751
8034
  const rowIndex = mobileSlice.start + index;
7752
8035
  const itemProps = getItemProps(row, "mobile", rowIndex);
7753
- return /* @__PURE__ */ jsx37(
8036
+ return /* @__PURE__ */ jsx38(
7754
8037
  CardComponent,
7755
8038
  {
7756
8039
  ...itemProps,
@@ -7764,7 +8047,17 @@ function DataTableInner({
7764
8047
  })
7765
8048
  }
7766
8049
  )
7767
- ] })
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
7768
8061
  ]
7769
8062
  }
7770
8063
  );
@@ -7772,40 +8065,9 @@ function DataTableInner({
7772
8065
  var DataTable = React33.forwardRef(DataTableInner);
7773
8066
  DataTable.displayName = "DataTable";
7774
8067
 
7775
- // src/components/ui/context-menu.tsx
7776
- import { jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
7777
- function ContextMenu({
7778
- open,
7779
- onOpenChange,
7780
- position,
7781
- children,
7782
- contentProps
7783
- }) {
7784
- if (!position) {
7785
- return null;
7786
- }
7787
- return /* @__PURE__ */ jsxs34(DropdownMenu, { open, onOpenChange, modal: false, children: [
7788
- /* @__PURE__ */ jsx38(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx38(
7789
- "span",
7790
- {
7791
- "aria-hidden": "true",
7792
- "data-slot": "context-menu-anchor",
7793
- style: {
7794
- position: "fixed",
7795
- left: position.x,
7796
- top: position.y,
7797
- width: 0,
7798
- height: 0
7799
- }
7800
- }
7801
- ) }),
7802
- /* @__PURE__ */ jsx38(DropdownMenuContent, { ...contentProps, children })
7803
- ] });
7804
- }
7805
-
7806
8068
  // src/components/ui/bulk-action-bar.tsx
7807
8069
  import * as React34 from "react";
7808
- import { X as X3 } from "lucide-react";
8070
+ import { X as X4 } from "lucide-react";
7809
8071
  import { jsx as jsx39, jsxs as jsxs35 } from "react/jsx-runtime";
7810
8072
  function ActionButton({ action }) {
7811
8073
  const danger = action.variant === "destructive";
@@ -7890,7 +8152,7 @@ function ClearButton({ onClear }) {
7890
8152
  justifyContent: "center",
7891
8153
  borderRadius: "var(--radius-md)"
7892
8154
  },
7893
- children: /* @__PURE__ */ jsx39(X3, { size: 16, strokeWidth: 1.75, "aria-hidden": "true" })
8155
+ children: /* @__PURE__ */ jsx39(X4, { size: 16, strokeWidth: 1.75, "aria-hidden": "true" })
7894
8156
  }
7895
8157
  );
7896
8158
  }
@@ -9445,9 +9707,97 @@ var Pagination = React43.forwardRef(
9445
9707
  );
9446
9708
  Pagination.displayName = "Pagination";
9447
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
+
9448
9798
  // src/components/ui/mode-toggle.tsx
9449
9799
  import { cva as cva19 } from "class-variance-authority";
9450
- import { jsx as jsx55, jsxs as jsxs43 } from "react/jsx-runtime";
9800
+ import { jsx as jsx56, jsxs as jsxs44 } from "react/jsx-runtime";
9451
9801
  var modeToggleVariants = cva19(
9452
9802
  [
9453
9803
  "inline-flex items-center rounded-[var(--radius-md)] border border-[var(--border-subtle)]",
@@ -9478,7 +9828,7 @@ function ModeToggle({
9478
9828
  onChange,
9479
9829
  ...props
9480
9830
  }) {
9481
- return /* @__PURE__ */ jsx55(
9831
+ return /* @__PURE__ */ jsx56(
9482
9832
  "div",
9483
9833
  {
9484
9834
  role: "group",
@@ -9488,7 +9838,7 @@ function ModeToggle({
9488
9838
  children: options.map((option) => {
9489
9839
  const Icon = option.icon;
9490
9840
  const isActive = option.value === value;
9491
- return /* @__PURE__ */ jsxs43(
9841
+ return /* @__PURE__ */ jsxs44(
9492
9842
  "button",
9493
9843
  {
9494
9844
  type: "button",
@@ -9504,8 +9854,8 @@ function ModeToggle({
9504
9854
  }
9505
9855
  },
9506
9856
  children: [
9507
- Icon ? /* @__PURE__ */ jsx55(Icon, { "aria-hidden": "true", "data-slot": "mode-toggle-icon" }) : null,
9508
- /* @__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 })
9509
9859
  ]
9510
9860
  },
9511
9861
  option.value
@@ -9518,7 +9868,7 @@ function ModeToggle({
9518
9868
  // src/components/ui/action-footer.tsx
9519
9869
  import * as React44 from "react";
9520
9870
  import { cva as cva20 } from "class-variance-authority";
9521
- import { jsx as jsx56, jsxs as jsxs44 } from "react/jsx-runtime";
9871
+ import { jsx as jsx57, jsxs as jsxs45 } from "react/jsx-runtime";
9522
9872
  var actionFooterVariants = cva20(
9523
9873
  [
9524
9874
  // Below sm: two fixed rows — destructive actions (start) and status (end) on top, the main
@@ -9602,7 +9952,7 @@ function renderAction(action, className) {
9602
9952
  };
9603
9953
  const style = actionStyle(action);
9604
9954
  if (action.leadingIcon) {
9605
- return /* @__PURE__ */ jsx56(
9955
+ return /* @__PURE__ */ jsx57(
9606
9956
  IconButton,
9607
9957
  {
9608
9958
  ...common,
@@ -9615,7 +9965,7 @@ function renderAction(action, className) {
9615
9965
  key
9616
9966
  );
9617
9967
  }
9618
- 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);
9619
9969
  }
9620
9970
  var ActionFooter = React44.forwardRef(
9621
9971
  ({
@@ -9630,7 +9980,7 @@ var ActionFooter = React44.forwardRef(
9630
9980
  const visibleActions = actions.filter((action) => canRenderAction(action, permissions));
9631
9981
  const destructiveActions = visibleActions.filter(isDestructive);
9632
9982
  const mainActions = sortMainActions(visibleActions.filter((action) => !isDestructive(action)));
9633
- return /* @__PURE__ */ jsxs44(
9983
+ return /* @__PURE__ */ jsxs45(
9634
9984
  "div",
9635
9985
  {
9636
9986
  ref,
@@ -9639,7 +9989,7 @@ var ActionFooter = React44.forwardRef(
9639
9989
  className: cn(actionFooterVariants({ position, surface, className })),
9640
9990
  ...props,
9641
9991
  children: [
9642
- destructiveActions.length > 0 ? /* @__PURE__ */ jsx56(
9992
+ destructiveActions.length > 0 ? /* @__PURE__ */ jsx57(
9643
9993
  "div",
9644
9994
  {
9645
9995
  "data-slot": "action-footer-destructive-actions",
@@ -9647,7 +9997,7 @@ var ActionFooter = React44.forwardRef(
9647
9997
  children: destructiveActions.map((action) => renderAction(action))
9648
9998
  }
9649
9999
  ) : null,
9650
- status ? /* @__PURE__ */ jsxs44(
10000
+ status ? /* @__PURE__ */ jsxs45(
9651
10001
  "div",
9652
10002
  {
9653
10003
  "data-slot": "action-footer-status",
@@ -9655,7 +10005,7 @@ var ActionFooter = React44.forwardRef(
9655
10005
  "aria-live": "polite",
9656
10006
  className: cn(actionFooterStatusVariants({ kind: status.kind })),
9657
10007
  children: [
9658
- /* @__PURE__ */ jsx56(
10008
+ /* @__PURE__ */ jsx57(
9659
10009
  "span",
9660
10010
  {
9661
10011
  "aria-hidden": "true",
@@ -9663,11 +10013,11 @@ var ActionFooter = React44.forwardRef(
9663
10013
  className: "size-[6px] shrink-0 rounded-[var(--radius-full)]"
9664
10014
  }
9665
10015
  ),
9666
- /* @__PURE__ */ jsx56("span", { className: "truncate", children: getStatusLabel(status) })
10016
+ /* @__PURE__ */ jsx57("span", { className: "truncate", children: getStatusLabel(status) })
9667
10017
  ]
9668
10018
  }
9669
10019
  ) : null,
9670
- /* @__PURE__ */ jsx56(
10020
+ /* @__PURE__ */ jsx57(
9671
10021
  "div",
9672
10022
  {
9673
10023
  "data-slot": "action-footer-main-actions",
@@ -9689,7 +10039,7 @@ ActionFooter.displayName = "ActionFooter";
9689
10039
  // src/components/ui/toast.tsx
9690
10040
  import * as React45 from "react";
9691
10041
  import { cva as cva21 } from "class-variance-authority";
9692
- import { jsx as jsx57, jsxs as jsxs45 } from "react/jsx-runtime";
10042
+ import { jsx as jsx58, jsxs as jsxs46 } from "react/jsx-runtime";
9693
10043
  var DOT3 = {
9694
10044
  default: "var(--neutral)",
9695
10045
  success: "var(--success)",
@@ -9836,7 +10186,7 @@ var ToastRoot = React45.forwardRef(
9836
10186
  timerRef.current = null;
9837
10187
  };
9838
10188
  }, [durationMs]);
9839
- return /* @__PURE__ */ jsxs45(
10189
+ return /* @__PURE__ */ jsxs46(
9840
10190
  "div",
9841
10191
  {
9842
10192
  ref,
@@ -9864,7 +10214,7 @@ var ToastRoot = React45.forwardRef(
9864
10214
  },
9865
10215
  ...props,
9866
10216
  children: [
9867
- /* @__PURE__ */ jsx57(
10217
+ /* @__PURE__ */ jsx58(
9868
10218
  "span",
9869
10219
  {
9870
10220
  "aria-hidden": "true",
@@ -9873,8 +10223,8 @@ var ToastRoot = React45.forwardRef(
9873
10223
  style: { background: DOT3[variant] ?? DOT3.default }
9874
10224
  }
9875
10225
  ),
9876
- /* @__PURE__ */ jsxs45("div", { "data-slot": "toast-body", className: "min-w-0 flex-1", children: [
9877
- /* @__PURE__ */ jsx57(
10226
+ /* @__PURE__ */ jsxs46("div", { "data-slot": "toast-body", className: "min-w-0 flex-1", children: [
10227
+ /* @__PURE__ */ jsx58(
9878
10228
  "div",
9879
10229
  {
9880
10230
  "data-slot": "toast-message",
@@ -9882,7 +10232,7 @@ var ToastRoot = React45.forwardRef(
9882
10232
  children: message
9883
10233
  }
9884
10234
  ),
9885
- description ? /* @__PURE__ */ jsx57(
10235
+ description ? /* @__PURE__ */ jsx58(
9886
10236
  "div",
9887
10237
  {
9888
10238
  "data-slot": "toast-description",
@@ -9891,8 +10241,8 @@ var ToastRoot = React45.forwardRef(
9891
10241
  }
9892
10242
  ) : null
9893
10243
  ] }),
9894
- /* @__PURE__ */ jsxs45("div", { "data-slot": "toast-actions", className: "flex shrink-0 items-center gap-[2px]", children: [
9895
- action ? /* @__PURE__ */ jsx57(
10244
+ /* @__PURE__ */ jsxs46("div", { "data-slot": "toast-actions", className: "flex shrink-0 items-center gap-[2px]", children: [
10245
+ action ? /* @__PURE__ */ jsx58(
9896
10246
  Button,
9897
10247
  {
9898
10248
  "data-slot": "toast-action",
@@ -9903,7 +10253,7 @@ var ToastRoot = React45.forwardRef(
9903
10253
  children: action.label
9904
10254
  }
9905
10255
  ) : null,
9906
- /* @__PURE__ */ jsx57(
10256
+ /* @__PURE__ */ jsx58(
9907
10257
  "button",
9908
10258
  {
9909
10259
  type: "button",
@@ -9925,7 +10275,7 @@ var ToastRoot = React45.forwardRef(
9925
10275
  }
9926
10276
  );
9927
10277
  ToastRoot.displayName = "ToastRoot";
9928
- var ToastViewport = React45.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx57(
10278
+ var ToastViewport = React45.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx58(
9929
10279
  "ol",
9930
10280
  {
9931
10281
  ref,
@@ -9943,9 +10293,9 @@ function ToastProvider({ children, maxToasts = 3, className, ...props }) {
9943
10293
  }),
9944
10294
  [maxToasts]
9945
10295
  );
9946
- return /* @__PURE__ */ jsxs45("div", { "data-slot": "toast-provider", className, ...props, children: [
10296
+ return /* @__PURE__ */ jsxs46("div", { "data-slot": "toast-provider", className, ...props, children: [
9947
10297
  children,
9948
- /* @__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)) })
9949
10299
  ] });
9950
10300
  }
9951
10301
 
@@ -9953,7 +10303,7 @@ function ToastProvider({ children, maxToasts = 3, className, ...props }) {
9953
10303
  import * as React46 from "react";
9954
10304
  import { cva as cva22 } from "class-variance-authority";
9955
10305
  import { AlertCircle as AlertCircle4 } from "lucide-react";
9956
- 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";
9957
10307
  var otpFieldVariants = cva22("flex w-full min-w-0 flex-col gap-[var(--space-3)]", {
9958
10308
  variants: {
9959
10309
  size: {
@@ -10138,7 +10488,7 @@ var OTPField = React46.forwardRef(
10138
10488
  },
10139
10489
  [disabled, isControlled, length, onComplete, onValueChange]
10140
10490
  );
10141
- return /* @__PURE__ */ jsxs46(
10491
+ return /* @__PURE__ */ jsxs47(
10142
10492
  "fieldset",
10143
10493
  {
10144
10494
  ref,
@@ -10151,7 +10501,7 @@ var OTPField = React46.forwardRef(
10151
10501
  className: cn(otpFieldVariants({ size, className })),
10152
10502
  ...props,
10153
10503
  children: [
10154
- /* @__PURE__ */ jsxs46(
10504
+ /* @__PURE__ */ jsxs47(
10155
10505
  "legend",
10156
10506
  {
10157
10507
  id: labelId,
@@ -10159,11 +10509,11 @@ var OTPField = React46.forwardRef(
10159
10509
  className: "text-sm font-medium leading-snug text-foreground",
10160
10510
  children: [
10161
10511
  label,
10162
- 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
10163
10513
  ]
10164
10514
  }
10165
10515
  ),
10166
- /* @__PURE__ */ jsx58(
10516
+ /* @__PURE__ */ jsx59(
10167
10517
  "div",
10168
10518
  {
10169
10519
  "data-slot": "otp-field-group",
@@ -10173,7 +10523,7 @@ var OTPField = React46.forwardRef(
10173
10523
  children: Array.from({ length }, (_, index) => {
10174
10524
  const digit = resolvedSlots[index] ?? "";
10175
10525
  const inputId = `${fieldId}-cell-${index + 1}`;
10176
- return /* @__PURE__ */ jsx58(
10526
+ return /* @__PURE__ */ jsx59(
10177
10527
  "input",
10178
10528
  {
10179
10529
  ref: (node) => {
@@ -10268,15 +10618,15 @@ var OTPField = React46.forwardRef(
10268
10618
  })
10269
10619
  }
10270
10620
  ),
10271
- helperText || errorText ? /* @__PURE__ */ jsx58(
10621
+ helperText || errorText ? /* @__PURE__ */ jsx59(
10272
10622
  "p",
10273
10623
  {
10274
10624
  id: errorText ? errorId : helperId,
10275
10625
  "data-slot": "otp-field-message",
10276
10626
  "data-kind": errorText ? "error" : "helper",
10277
10627
  className: otpFieldMessageVariants({ state: resolvedState }),
10278
- children: errorText ? /* @__PURE__ */ jsxs46(Fragment16, { children: [
10279
- /* @__PURE__ */ jsx58(
10628
+ children: errorText ? /* @__PURE__ */ jsxs47(Fragment17, { children: [
10629
+ /* @__PURE__ */ jsx59(
10280
10630
  AlertCircle4,
10281
10631
  {
10282
10632
  "aria-hidden": "true",
@@ -10284,11 +10634,11 @@ var OTPField = React46.forwardRef(
10284
10634
  strokeWidth: 2
10285
10635
  }
10286
10636
  ),
10287
- /* @__PURE__ */ jsx58("span", { children: errorText })
10288
- ] }) : /* @__PURE__ */ jsx58("span", { children: helperText })
10637
+ /* @__PURE__ */ jsx59("span", { children: errorText })
10638
+ ] }) : /* @__PURE__ */ jsx59("span", { children: helperText })
10289
10639
  }
10290
10640
  ) : null,
10291
- name ? /* @__PURE__ */ jsx58(
10641
+ name ? /* @__PURE__ */ jsx59(
10292
10642
  "input",
10293
10643
  {
10294
10644
  "aria-hidden": "true",
@@ -10310,9 +10660,9 @@ OTPField.displayName = "OTPField";
10310
10660
 
10311
10661
  // src/components/ui/search-field.tsx
10312
10662
  import * as React47 from "react";
10313
- import { Search, X as X4 } from "lucide-react";
10663
+ import { Search, X as X5 } from "lucide-react";
10314
10664
  import { cva as cva23 } from "class-variance-authority";
10315
- import { jsx as jsx59, jsxs as jsxs47 } from "react/jsx-runtime";
10665
+ import { jsx as jsx60, jsxs as jsxs48 } from "react/jsx-runtime";
10316
10666
  var searchFieldVariants = cva23("relative flex w-full items-center", {
10317
10667
  variants: {
10318
10668
  size: {
@@ -10411,14 +10761,14 @@ var SearchField = React47.forwardRef(
10411
10761
  }
10412
10762
  onClear?.();
10413
10763
  };
10414
- return /* @__PURE__ */ jsxs47(
10764
+ return /* @__PURE__ */ jsxs48(
10415
10765
  "div",
10416
10766
  {
10417
10767
  "data-slot": "search-field",
10418
10768
  "data-size": resolvedSize,
10419
10769
  className: cn(searchFieldVariants({ size, className })),
10420
10770
  children: [
10421
- /* @__PURE__ */ jsx59(
10771
+ /* @__PURE__ */ jsx60(
10422
10772
  Search,
10423
10773
  {
10424
10774
  "aria-hidden": "true",
@@ -10428,7 +10778,7 @@ var SearchField = React47.forwardRef(
10428
10778
  strokeWidth: resolvedSize === "sm" ? 2 : 1.75
10429
10779
  }
10430
10780
  ),
10431
- /* @__PURE__ */ jsx59(
10781
+ /* @__PURE__ */ jsx60(
10432
10782
  "input",
10433
10783
  {
10434
10784
  ref: inputRef,
@@ -10449,7 +10799,7 @@ var SearchField = React47.forwardRef(
10449
10799
  ...props
10450
10800
  }
10451
10801
  ),
10452
- showClear ? /* @__PURE__ */ jsx59(
10802
+ showClear ? /* @__PURE__ */ jsx60(
10453
10803
  "button",
10454
10804
  {
10455
10805
  type: "button",
@@ -10457,7 +10807,7 @@ var SearchField = React47.forwardRef(
10457
10807
  "data-slot": "search-field-clear",
10458
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)]",
10459
10809
  onClick: clearInput,
10460
- children: /* @__PURE__ */ jsx59(X4, { "aria-hidden": "true", size: 16, strokeWidth: 1.75 })
10810
+ children: /* @__PURE__ */ jsx60(X5, { "aria-hidden": "true", size: 16, strokeWidth: 1.75 })
10461
10811
  }
10462
10812
  ) : null
10463
10813
  ]
@@ -10470,7 +10820,7 @@ SearchField.displayName = "SearchField";
10470
10820
  // src/components/ui/checkbox-group.tsx
10471
10821
  import * as React48 from "react";
10472
10822
  import { cva as cva24 } from "class-variance-authority";
10473
- import { jsx as jsx60 } from "react/jsx-runtime";
10823
+ import { jsx as jsx61 } from "react/jsx-runtime";
10474
10824
  var checkboxGroupVariants = cva24("gap-[var(--space-2)]", {
10475
10825
  variants: {
10476
10826
  appearance: {
@@ -10546,7 +10896,7 @@ var CheckboxGroup = React48.forwardRef(
10546
10896
  }),
10547
10897
  [appearance, density, disabled, name, selectedValues, toggleValue]
10548
10898
  );
10549
- return /* @__PURE__ */ jsx60(CheckboxGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx60(
10899
+ return /* @__PURE__ */ jsx61(CheckboxGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx61(
10550
10900
  "div",
10551
10901
  {
10552
10902
  ref,
@@ -10574,7 +10924,7 @@ import * as React49 from "react";
10574
10924
  import { cva as cva25 } from "class-variance-authority";
10575
10925
  import { Circle } from "lucide-react";
10576
10926
  import { RadioGroup as RadioGroupPrimitive } from "radix-ui";
10577
- import { jsx as jsx61, jsxs as jsxs48 } from "react/jsx-runtime";
10927
+ import { jsx as jsx62, jsxs as jsxs49 } from "react/jsx-runtime";
10578
10928
  var radioGroupVariants = cva25("gap-[var(--space-2)]", {
10579
10929
  variants: {
10580
10930
  appearance: {
@@ -10682,7 +11032,7 @@ var RadioGroup = React49.forwardRef(
10682
11032
  () => ({ appearance, density }),
10683
11033
  [appearance, density]
10684
11034
  );
10685
- return /* @__PURE__ */ jsx61(RadioGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx61(
11035
+ return /* @__PURE__ */ jsx62(RadioGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx62(
10686
11036
  RadioGroupPrimitive.Root,
10687
11037
  {
10688
11038
  ref,
@@ -10711,7 +11061,7 @@ var Radio = React49.forwardRef(({ className, children, description, id, ...props
10711
11061
  const radioId = id ?? generatedId;
10712
11062
  const labelId = `${radioId}-label`;
10713
11063
  const descriptionId = description ? `${radioId}-description` : void 0;
10714
- return /* @__PURE__ */ jsxs48(
11064
+ return /* @__PURE__ */ jsxs49(
10715
11065
  RadioGroupPrimitive.Item,
10716
11066
  {
10717
11067
  ref,
@@ -10722,24 +11072,24 @@ var Radio = React49.forwardRef(({ className, children, description, id, ...props
10722
11072
  className: cn(radioVariants({ appearance, density }), className),
10723
11073
  ...props,
10724
11074
  children: [
10725
- /* @__PURE__ */ jsx61(
11075
+ /* @__PURE__ */ jsx62(
10726
11076
  "span",
10727
11077
  {
10728
11078
  "aria-hidden": "true",
10729
11079
  "data-slot": "radio-control",
10730
11080
  className: radioControlVariants({ appearance }),
10731
- children: /* @__PURE__ */ jsx61(
11081
+ children: /* @__PURE__ */ jsx62(
10732
11082
  RadioGroupPrimitive.Indicator,
10733
11083
  {
10734
11084
  "data-slot": "radio-indicator",
10735
11085
  className: "flex items-center justify-center",
10736
- children: /* @__PURE__ */ jsx61(Circle, { "aria-hidden": "true", size: 8, fill: "currentColor" })
11086
+ children: /* @__PURE__ */ jsx62(Circle, { "aria-hidden": "true", size: 8, fill: "currentColor" })
10737
11087
  }
10738
11088
  )
10739
11089
  }
10740
11090
  ),
10741
- /* @__PURE__ */ jsxs48("span", { className: "flex min-w-0 flex-col gap-[var(--space-1)]", children: [
10742
- /* @__PURE__ */ jsx61(
11091
+ /* @__PURE__ */ jsxs49("span", { className: "flex min-w-0 flex-col gap-[var(--space-1)]", children: [
11092
+ /* @__PURE__ */ jsx62(
10743
11093
  "span",
10744
11094
  {
10745
11095
  id: labelId,
@@ -10751,7 +11101,7 @@ var Radio = React49.forwardRef(({ className, children, description, id, ...props
10751
11101
  children
10752
11102
  }
10753
11103
  ),
10754
- description ? /* @__PURE__ */ jsx61(
11104
+ description ? /* @__PURE__ */ jsx62(
10755
11105
  "span",
10756
11106
  {
10757
11107
  id: descriptionId,
@@ -10769,20 +11119,20 @@ Radio.displayName = "Radio";
10769
11119
 
10770
11120
  // src/components/ui/scroll-area.tsx
10771
11121
  import { ScrollArea as ScrollAreaPrimitive } from "radix-ui";
10772
- import { jsx as jsx62, jsxs as jsxs49 } from "react/jsx-runtime";
11122
+ import { jsx as jsx63, jsxs as jsxs50 } from "react/jsx-runtime";
10773
11123
  function ScrollArea({
10774
11124
  className,
10775
11125
  children,
10776
11126
  ...props
10777
11127
  }) {
10778
- return /* @__PURE__ */ jsxs49(
11128
+ return /* @__PURE__ */ jsxs50(
10779
11129
  ScrollAreaPrimitive.Root,
10780
11130
  {
10781
11131
  "data-slot": "scroll-area",
10782
11132
  className: cn("relative", className),
10783
11133
  ...props,
10784
11134
  children: [
10785
- /* @__PURE__ */ jsx62(
11135
+ /* @__PURE__ */ jsx63(
10786
11136
  ScrollAreaPrimitive.Viewport,
10787
11137
  {
10788
11138
  "data-slot": "scroll-area-viewport",
@@ -10790,8 +11140,8 @@ function ScrollArea({
10790
11140
  children
10791
11141
  }
10792
11142
  ),
10793
- /* @__PURE__ */ jsx62(ScrollBar, {}),
10794
- /* @__PURE__ */ jsx62(ScrollAreaPrimitive.Corner, {})
11143
+ /* @__PURE__ */ jsx63(ScrollBar, {}),
11144
+ /* @__PURE__ */ jsx63(ScrollAreaPrimitive.Corner, {})
10795
11145
  ]
10796
11146
  }
10797
11147
  );
@@ -10801,7 +11151,7 @@ function ScrollBar({
10801
11151
  orientation = "vertical",
10802
11152
  ...props
10803
11153
  }) {
10804
- return /* @__PURE__ */ jsx62(
11154
+ return /* @__PURE__ */ jsx63(
10805
11155
  ScrollAreaPrimitive.ScrollAreaScrollbar,
10806
11156
  {
10807
11157
  "data-slot": "scroll-area-scrollbar",
@@ -10813,7 +11163,7 @@ function ScrollBar({
10813
11163
  className
10814
11164
  ),
10815
11165
  ...props,
10816
- children: /* @__PURE__ */ jsx62(
11166
+ children: /* @__PURE__ */ jsx63(
10817
11167
  ScrollAreaPrimitive.ScrollAreaThumb,
10818
11168
  {
10819
11169
  "data-slot": "scroll-area-thumb",
@@ -10825,7 +11175,7 @@ function ScrollBar({
10825
11175
  }
10826
11176
 
10827
11177
  // src/components/ui/progress.tsx
10828
- import { jsx as jsx63 } from "react/jsx-runtime";
11178
+ import { jsx as jsx64 } from "react/jsx-runtime";
10829
11179
  var progressFillByStatus = {
10830
11180
  active: "bg-[var(--primary)]",
10831
11181
  success: "bg-[var(--success)]",
@@ -10846,7 +11196,7 @@ function Progress({
10846
11196
  const clamped = Math.max(0, Math.min(safeMax, value));
10847
11197
  const percent = clamped / safeMax * 100;
10848
11198
  const w = typeof width === "number" ? `${width}px` : width;
10849
- return /* @__PURE__ */ jsx63(
11199
+ return /* @__PURE__ */ jsx64(
10850
11200
  "div",
10851
11201
  {
10852
11202
  role: "progressbar",
@@ -10860,7 +11210,7 @@ function Progress({
10860
11210
  ),
10861
11211
  style: { width: w, height: `${height}px`, ...style },
10862
11212
  ...props,
10863
- children: /* @__PURE__ */ jsx63(
11213
+ children: /* @__PURE__ */ jsx64(
10864
11214
  "div",
10865
11215
  {
10866
11216
  className: cn(
@@ -10876,9 +11226,9 @@ function Progress({
10876
11226
 
10877
11227
  // src/components/ui/tree-view.tsx
10878
11228
  import * as React50 from "react";
10879
- import { ChevronRight as ChevronRight5 } from "lucide-react";
11229
+ import { ChevronRight as ChevronRight6 } from "lucide-react";
10880
11230
  import { cva as cva26 } from "class-variance-authority";
10881
- import { jsx as jsx64, jsxs as jsxs50 } from "react/jsx-runtime";
11231
+ import { jsx as jsx65, jsxs as jsxs51 } from "react/jsx-runtime";
10882
11232
  var treeViewVariants = cva26(
10883
11233
  "m-0 list-none p-[var(--space-1)] text-body-sm text-foreground"
10884
11234
  );
@@ -10890,7 +11240,7 @@ var treeItemRowVariants = cva26(
10890
11240
  "hover:bg-[var(--action-hover)] hover:text-foreground",
10891
11241
  // Roving focus lives on the treeitem <li> (named group/treeitem); the ring is
10892
11242
  // painted on the visual row so it never wraps the nested child group.
10893
- "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)]"
10894
11244
  ].join(" "),
10895
11245
  {
10896
11246
  variants: {
@@ -11048,7 +11398,7 @@ function TreeView({
11048
11398
  const selected = node.id === selectedId;
11049
11399
  const isActive = node.id === activeId;
11050
11400
  const itemState = { expanded, selected, depth, hasChildren };
11051
- return /* @__PURE__ */ jsxs50(
11401
+ return /* @__PURE__ */ jsxs51(
11052
11402
  "li",
11053
11403
  {
11054
11404
  ref: (element) => {
@@ -11073,7 +11423,7 @@ function TreeView({
11073
11423
  onSelect?.(node.id, node);
11074
11424
  },
11075
11425
  children: [
11076
- /* @__PURE__ */ jsxs50(
11426
+ /* @__PURE__ */ jsxs51(
11077
11427
  "span",
11078
11428
  {
11079
11429
  "data-slot": "treeitem-row",
@@ -11082,7 +11432,7 @@ function TreeView({
11082
11432
  },
11083
11433
  className: treeItemRowVariants({ selected }),
11084
11434
  children: [
11085
- hasChildren ? /* @__PURE__ */ jsx64(
11435
+ hasChildren ? /* @__PURE__ */ jsx65(
11086
11436
  "span",
11087
11437
  {
11088
11438
  "data-slot": "treeitem-toggle",
@@ -11092,8 +11442,8 @@ function TreeView({
11092
11442
  setExpanded(node.id, !expanded);
11093
11443
  },
11094
11444
  className: "flex size-[var(--space-4)] shrink-0 items-center justify-center text-text-tertiary",
11095
- children: /* @__PURE__ */ jsx64(
11096
- ChevronRight5,
11445
+ children: /* @__PURE__ */ jsx65(
11446
+ ChevronRight6,
11097
11447
  {
11098
11448
  "aria-hidden": "true",
11099
11449
  "data-slot": "treeitem-chevron",
@@ -11105,7 +11455,7 @@ function TreeView({
11105
11455
  }
11106
11456
  )
11107
11457
  }
11108
- ) : /* @__PURE__ */ jsx64(
11458
+ ) : /* @__PURE__ */ jsx65(
11109
11459
  "span",
11110
11460
  {
11111
11461
  "data-slot": "treeitem-spacer",
@@ -11113,18 +11463,18 @@ function TreeView({
11113
11463
  className: "size-[var(--space-4)] shrink-0"
11114
11464
  }
11115
11465
  ),
11116
- /* @__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) })
11117
11467
  ]
11118
11468
  }
11119
11469
  ),
11120
- 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
11121
11471
  ]
11122
11472
  },
11123
11473
  node.id
11124
11474
  );
11125
11475
  });
11126
11476
  }
11127
- return /* @__PURE__ */ jsx64(
11477
+ return /* @__PURE__ */ jsx65(
11128
11478
  "ul",
11129
11479
  {
11130
11480
  role: "tree",
@@ -11141,7 +11491,7 @@ function TreeView({
11141
11491
 
11142
11492
  // src/components/branding/olun-logo.tsx
11143
11493
  import { OLUN_MASTER, OLUN_SYMBOL, OLUN_WORDMARK } from "@olundot/tokens/brand";
11144
- 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";
11145
11495
  var ACCENT_FILL = "var(--accent-pop)";
11146
11496
  var INK = { color: "var(--text-primary)" };
11147
11497
  var INK_TIGHT = { ...INK, display: "block", overflow: "visible" };
@@ -11151,8 +11501,8 @@ function symbolGeometry(size) {
11151
11501
  function SymbolCircles({ size }) {
11152
11502
  const { ring } = OLUN_SYMBOL;
11153
11503
  const g = symbolGeometry(size);
11154
- return /* @__PURE__ */ jsxs51(Fragment17, { children: [
11155
- /* @__PURE__ */ jsx65(
11504
+ return /* @__PURE__ */ jsxs52(Fragment18, { children: [
11505
+ /* @__PURE__ */ jsx66(
11156
11506
  "circle",
11157
11507
  {
11158
11508
  className: "olun-logo__ring",
@@ -11164,11 +11514,11 @@ function SymbolCircles({ size }) {
11164
11514
  fill: "none"
11165
11515
  }
11166
11516
  ),
11167
- /* @__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 })
11168
11518
  ] });
11169
11519
  }
11170
11520
  function OlunSymbol({ size = 28, className }) {
11171
- return /* @__PURE__ */ jsx65(
11521
+ return /* @__PURE__ */ jsx66(
11172
11522
  "svg",
11173
11523
  {
11174
11524
  width: size,
@@ -11179,7 +11529,7 @@ function OlunSymbol({ size = 28, className }) {
11179
11529
  className,
11180
11530
  style: INK,
11181
11531
  "aria-hidden": "true",
11182
- children: /* @__PURE__ */ jsx65(SymbolCircles, { size })
11532
+ children: /* @__PURE__ */ jsx66(SymbolCircles, { size })
11183
11533
  }
11184
11534
  );
11185
11535
  }
@@ -11192,7 +11542,7 @@ function OlunLogo({
11192
11542
  if (!showSymbol) {
11193
11543
  const { full } = OLUN_WORDMARK;
11194
11544
  const height2 = fontSize * full.height / OLUN_WORDMARK.unitsPerEm;
11195
- return /* @__PURE__ */ jsxs51(
11545
+ return /* @__PURE__ */ jsxs52(
11196
11546
  "svg",
11197
11547
  {
11198
11548
  width: height2 * full.width / full.height,
@@ -11205,8 +11555,8 @@ function OlunLogo({
11205
11555
  role: "img",
11206
11556
  "aria-label": "OLUN.",
11207
11557
  children: [
11208
- /* @__PURE__ */ jsx65("path", { className: "olun-logo__wordmark", fill: "currentColor", d: full.letters }),
11209
- /* @__PURE__ */ jsx65(
11558
+ /* @__PURE__ */ jsx66("path", { className: "olun-logo__wordmark", fill: "currentColor", d: full.letters }),
11559
+ /* @__PURE__ */ jsx66(
11210
11560
  "circle",
11211
11561
  {
11212
11562
  className: "olun-accent olun-logo__period",
@@ -11222,7 +11572,7 @@ function OlunLogo({
11222
11572
  }
11223
11573
  const layout = symbolSize > OLUN_SYMBOL.smallMax ? OLUN_MASTER.large : OLUN_MASTER.small;
11224
11574
  const height = symbolSize * layout.height / (OLUN_SYMBOL.box * layout.symbol.scale);
11225
- return /* @__PURE__ */ jsxs51(
11575
+ return /* @__PURE__ */ jsxs52(
11226
11576
  "svg",
11227
11577
  {
11228
11578
  width: height * layout.width / layout.height,
@@ -11235,15 +11585,15 @@ function OlunLogo({
11235
11585
  role: "img",
11236
11586
  "aria-label": "OLUN",
11237
11587
  children: [
11238
- /* @__PURE__ */ jsx65(
11588
+ /* @__PURE__ */ jsx66(
11239
11589
  "g",
11240
11590
  {
11241
11591
  className: "olun-logo__symbol",
11242
11592
  transform: `translate(${layout.symbol.x} ${layout.symbol.y}) scale(${layout.symbol.scale})`,
11243
- children: /* @__PURE__ */ jsx65(SymbolCircles, { size: symbolSize })
11593
+ children: /* @__PURE__ */ jsx66(SymbolCircles, { size: symbolSize })
11244
11594
  }
11245
11595
  ),
11246
- /* @__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 })
11247
11597
  ]
11248
11598
  }
11249
11599
  );
@@ -11251,11 +11601,11 @@ function OlunLogo({
11251
11601
 
11252
11602
  // src/components/branding/theme-toggle.tsx
11253
11603
  import { Sun, Moon } from "lucide-react";
11254
- import { jsx as jsx66 } from "react/jsx-runtime";
11604
+ import { jsx as jsx67 } from "react/jsx-runtime";
11255
11605
  function ThemeToggle({ className }) {
11256
11606
  const { resolvedTheme, toggleTheme } = useOlunTheme();
11257
11607
  const Icon = resolvedTheme === "dark" ? Moon : Sun;
11258
- return /* @__PURE__ */ jsx66(
11608
+ return /* @__PURE__ */ jsx67(
11259
11609
  "button",
11260
11610
  {
11261
11611
  onClick: () => toggleTheme(),
@@ -11267,14 +11617,14 @@ function ThemeToggle({ className }) {
11267
11617
  ),
11268
11618
  "aria-label": "\uD14C\uB9C8 \uC804\uD658",
11269
11619
  title: resolvedTheme === "dark" ? "\uB77C\uC774\uD2B8 \uBAA8\uB4DC\uB85C" : "\uB2E4\uD06C \uBAA8\uB4DC\uB85C",
11270
- children: /* @__PURE__ */ jsx66(Icon, { className: "size-[18px]", strokeWidth: 1.75 })
11620
+ children: /* @__PURE__ */ jsx67(Icon, { className: "size-[18px]", strokeWidth: 1.75 })
11271
11621
  }
11272
11622
  );
11273
11623
  }
11274
11624
 
11275
11625
  // src/components/branding/theme-fab.tsx
11276
11626
  import { Sun as Sun2, Moon as Moon2 } from "lucide-react";
11277
- import { jsx as jsx67 } from "react/jsx-runtime";
11627
+ import { jsx as jsx68 } from "react/jsx-runtime";
11278
11628
  function ThemeFab({ variant = "square" } = {}) {
11279
11629
  const { mounted, resolvedTheme, toggleTheme } = useOlunTheme();
11280
11630
  if (!mounted) {
@@ -11314,7 +11664,7 @@ function ThemeFab({ variant = "square" } = {}) {
11314
11664
  WebkitBackdropFilter: "blur(16px)",
11315
11665
  zIndex: 9999
11316
11666
  };
11317
- return /* @__PURE__ */ jsx67(
11667
+ return /* @__PURE__ */ jsx68(
11318
11668
  "button",
11319
11669
  {
11320
11670
  onClick: () => toggleTheme(),
@@ -11339,7 +11689,7 @@ function ThemeFab({ variant = "square" } = {}) {
11339
11689
  e.currentTarget.style.color = "var(--text-secondary)";
11340
11690
  }
11341
11691
  },
11342
- children: /* @__PURE__ */ jsx67(
11692
+ children: /* @__PURE__ */ jsx68(
11343
11693
  Icon,
11344
11694
  {
11345
11695
  size: isCircle ? 22 : 16,
@@ -11351,7 +11701,7 @@ function ThemeFab({ variant = "square" } = {}) {
11351
11701
  }
11352
11702
 
11353
11703
  // src/components/logos/organization-logo.tsx
11354
- import { jsx as jsx68 } from "react/jsx-runtime";
11704
+ import { jsx as jsx69 } from "react/jsx-runtime";
11355
11705
  var organizationLogoRegistry = {
11356
11706
  jbnu: {
11357
11707
  label: "\uC804\uBD81\uB300\uD559\uAD50 \uC5E0\uBE14\uB7FC",
@@ -11380,7 +11730,7 @@ function OrganizationLogo({
11380
11730
  }) {
11381
11731
  const asset = organizationLogoRegistry[organization];
11382
11732
  const isDecorative = ariaHidden === true || ariaHidden === "true";
11383
- return /* @__PURE__ */ jsx68(
11733
+ return /* @__PURE__ */ jsx69(
11384
11734
  "svg",
11385
11735
  {
11386
11736
  viewBox: asset.viewBox,
@@ -11398,7 +11748,7 @@ function OrganizationLogo({
11398
11748
  ...style
11399
11749
  },
11400
11750
  ...props,
11401
- children: asset.paths.map((path) => /* @__PURE__ */ jsx68("path", { d: path }, path))
11751
+ children: asset.paths.map((path) => /* @__PURE__ */ jsx69("path", { d: path }, path))
11402
11752
  }
11403
11753
  );
11404
11754
  }
@@ -11515,6 +11865,8 @@ export {
11515
11865
  StatusBadge,
11516
11866
  StatusDot,
11517
11867
  Switch,
11868
+ TABLE_PAGE_SIZE_OPTIONS,
11869
+ TablePagination,
11518
11870
  Tabs,
11519
11871
  TabsContent,
11520
11872
  Textarea,
@@ -11583,6 +11935,7 @@ export {
11583
11935
  selectMessageVariants,
11584
11936
  selectVariants,
11585
11937
  setOlunTheme,
11938
+ shouldHideTablePagination,
11586
11939
  skeletonVariants,
11587
11940
  spinnerVariants,
11588
11941
  tabsBadgeVariants,