@olundot/ui 0.21.1 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -829,10 +829,14 @@ var FileUploadZone = React5.forwardRef(
829
829
  onKeyDown,
830
830
  size = "default",
831
831
  surface = "surface",
832
+ "aria-describedby": ariaDescribedBy,
832
833
  ...props
833
834
  }, ref) => {
835
+ const field = useFormFieldControl();
834
836
  const generatedId = React5.useId();
835
- const inputId = id ?? generatedId;
837
+ const inputId = id ?? field?.controlId ?? generatedId;
838
+ const errorId = field && error ? `${generatedId}-error` : void 0;
839
+ const fieldDescribedBy = field ? joinIds(ariaDescribedBy, errorId, field.describedBy) : void 0;
836
840
  const inputRef = React5.useRef(null);
837
841
  const [isDragging, setIsDragging] = React5.useState(false);
838
842
  const [selectedFiles, setSelectedFiles] = React5.useState("");
@@ -919,6 +923,7 @@ var FileUploadZone = React5.forwardRef(
919
923
  "aria-disabled": disabled || void 0,
920
924
  tabIndex: disabled ? -1 : 0,
921
925
  htmlFor: inputId,
926
+ "aria-describedby": field ? fieldDescribedBy : ariaDescribedBy,
922
927
  className: cn(fileUploadZoneVariants({ size, surface, className })),
923
928
  onDragEnter: handleDragEnter,
924
929
  onDragLeave: handleDragLeave,
@@ -932,6 +937,8 @@ var FileUploadZone = React5.forwardRef(
932
937
  {
933
938
  ref: inputRef,
934
939
  id: inputId,
940
+ "aria-describedby": fieldDescribedBy,
941
+ "aria-invalid": errorId ? true : void 0,
935
942
  "data-slot": "file-upload-zone-input",
936
943
  className: "sr-only",
937
944
  type: "file",
@@ -983,6 +990,7 @@ var FileUploadZone = React5.forwardRef(
983
990
  error ? /* @__PURE__ */ jsx4(
984
991
  "span",
985
992
  {
993
+ id: errorId,
986
994
  role: "alert",
987
995
  "data-slot": "file-upload-zone-error",
988
996
  className: "mt-[var(--space-1)] text-xs leading-normal text-[var(--error)]",
@@ -3794,7 +3802,7 @@ var FormLayout = React21.forwardRef(
3794
3802
  FormLayout.displayName = "FormLayout";
3795
3803
 
3796
3804
  // src/components/ui/dialog.tsx
3797
- import * as React28 from "react";
3805
+ import * as React29 from "react";
3798
3806
  import { Dialog as DialogPrimitive3 } from "radix-ui";
3799
3807
 
3800
3808
  // src/lib/use-overlay-action.ts
@@ -3877,7 +3885,7 @@ function useReturnFocus() {
3877
3885
  }
3878
3886
 
3879
3887
  // src/components/ui/overlay-anatomy.tsx
3880
- import * as React26 from "react";
3888
+ import * as React27 from "react";
3881
3889
  import { AlertDialog as AlertDialogPrimitive, Dialog as DialogPrimitive2 } from "radix-ui";
3882
3890
 
3883
3891
  // src/components/ui/overlay-bottom-sheet.tsx
@@ -4062,9 +4070,33 @@ import { X as X2 } from "lucide-react";
4062
4070
  import { Dialog as DialogPrimitive } from "radix-ui";
4063
4071
 
4064
4072
  // src/components/ui/icon-button.tsx
4065
- import * as React25 from "react";
4073
+ import * as React26 from "react";
4066
4074
  import { cva as cva10 } from "class-variance-authority";
4067
4075
  import { Check as Check3, ChevronDown as ChevronDown4, Loader2 as Loader23 } from "lucide-react";
4076
+
4077
+ // src/lib/compose-refs.ts
4078
+ import * as React25 from "react";
4079
+ function setRef(ref, value) {
4080
+ if (typeof ref === "function") return ref(value);
4081
+ if (ref) ref.current = value;
4082
+ }
4083
+ function composeRefs(...refs) {
4084
+ return (node) => {
4085
+ const cleanups = refs.map((ref) => setRef(ref, node));
4086
+ if (!cleanups.some((cleanup) => typeof cleanup === "function")) return;
4087
+ return () => {
4088
+ cleanups.forEach((cleanup, index) => {
4089
+ if (typeof cleanup === "function") cleanup();
4090
+ else setRef(refs[index], null);
4091
+ });
4092
+ };
4093
+ };
4094
+ }
4095
+ function useComposedRefs(...refs) {
4096
+ return React25.useCallback(composeRefs(...refs), refs);
4097
+ }
4098
+
4099
+ // src/components/ui/icon-button.tsx
4068
4100
  import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
4069
4101
  var pressedNeutralClassName = "border-[var(--border-strong)] bg-[var(--action-selected)] text-foreground";
4070
4102
  var doneClassName = "cursor-default text-[var(--success)]";
@@ -4072,7 +4104,7 @@ var doneRestPaint = (classes) => classes.split(" ").filter(
4072
4104
  (name) => !name.startsWith("hover:") && (!name.startsWith("aria-disabled:") || name.startsWith("aria-disabled:active:"))
4073
4105
  ).join(" ");
4074
4106
  var tabbing = false;
4075
- var tabListeners = 0;
4107
+ var tabListeners = /* @__PURE__ */ new WeakMap();
4076
4108
  var markTab = (event) => {
4077
4109
  if (event.key !== "Tab") return;
4078
4110
  tabbing = true;
@@ -4080,14 +4112,46 @@ var markTab = (event) => {
4080
4112
  tabbing = false;
4081
4113
  }, 0);
4082
4114
  };
4083
- function useTabMark(enabled) {
4084
- React25.useEffect(() => {
4085
- if (!enabled) return;
4086
- if (tabListeners++ === 0) document.addEventListener("keydown", markTab, true);
4087
- return () => {
4088
- if (--tabListeners === 0) document.removeEventListener("keydown", markTab, true);
4115
+ function tabDocuments(ownerDocument) {
4116
+ const documents = [];
4117
+ for (let current = ownerDocument; current; ) {
4118
+ documents.push(current);
4119
+ current = current.defaultView?.frameElement?.ownerDocument;
4120
+ }
4121
+ return documents;
4122
+ }
4123
+ function useTabMark(nodeRef, enabled) {
4124
+ React26.useEffect(() => {
4125
+ const ownerDocument = nodeRef.current?.ownerDocument;
4126
+ if (!enabled || !ownerDocument) return;
4127
+ const documents = tabDocuments(ownerDocument);
4128
+ for (const target of documents) {
4129
+ const count = tabListeners.get(target) ?? 0;
4130
+ if (count === 0) target.addEventListener("keydown", markTab, true);
4131
+ tabListeners.set(target, count + 1);
4132
+ }
4133
+ const view = ownerDocument.defaultView;
4134
+ let released = false;
4135
+ const onPageHide = (event) => {
4136
+ if (!event.persisted) release();
4089
4137
  };
4090
- }, [enabled]);
4138
+ const release = () => {
4139
+ if (released) return;
4140
+ released = true;
4141
+ view?.removeEventListener("pagehide", onPageHide);
4142
+ for (const target of documents) {
4143
+ const remaining = (tabListeners.get(target) ?? 1) - 1;
4144
+ if (remaining > 0) {
4145
+ tabListeners.set(target, remaining);
4146
+ continue;
4147
+ }
4148
+ tabListeners.delete(target);
4149
+ target.removeEventListener("keydown", markTab, true);
4150
+ }
4151
+ };
4152
+ view?.addEventListener("pagehide", onPageHide);
4153
+ return release;
4154
+ }, [nodeRef, enabled]);
4091
4155
  }
4092
4156
  var iconButtonCva = cva10(
4093
4157
  [
@@ -4165,7 +4229,7 @@ var iconButtonBadgeVariants = cva10(
4165
4229
  }
4166
4230
  }
4167
4231
  );
4168
- var IconButton = React25.forwardRef(
4232
+ var IconButton = React26.forwardRef(
4169
4233
  ({
4170
4234
  className,
4171
4235
  appearance,
@@ -4203,9 +4267,11 @@ var IconButton = React25.forwardRef(
4203
4267
  const hasText = text !== void 0 && text !== null && text !== false;
4204
4268
  const resolvedBadge = badge === void 0 && isDone ? /* @__PURE__ */ jsx22(Check3, { strokeWidth: 3 }) : badge;
4205
4269
  const resolvedBadgeTone = badge === void 0 && isDone ? "success" : badgeTone;
4206
- const [tooltipOpen, setTooltipOpen] = React25.useState(false);
4207
- useTabMark(tooltip !== void 0);
4208
- React25.useEffect(() => {
4270
+ const [tooltipOpen, setTooltipOpen] = React26.useState(false);
4271
+ const buttonRef = React26.useRef(null);
4272
+ const setButtonRefs = useComposedRefs(buttonRef, ref);
4273
+ useTabMark(buttonRef, tooltip !== void 0);
4274
+ React26.useEffect(() => {
4209
4275
  if (isDisabled) setTooltipOpen(false);
4210
4276
  }, [isDisabled]);
4211
4277
  const style = resolveActionStyle(appearance, tone, "ghost");
@@ -4237,7 +4303,7 @@ var IconButton = React25.forwardRef(
4237
4303
  const button = /* @__PURE__ */ jsxs20(
4238
4304
  "button",
4239
4305
  {
4240
- ref,
4306
+ ref: setButtonRefs,
4241
4307
  ...props,
4242
4308
  "data-slot": "icon-button",
4243
4309
  "data-appearance": style.appearance,
@@ -4419,7 +4485,7 @@ var scrimMotionOf = {
4419
4485
  sheet: scrimMotion.responsive,
4420
4486
  menu: scrimMotion.sheet
4421
4487
  };
4422
- var OverlayScrimLayer = React26.forwardRef(
4488
+ var OverlayScrimLayer = React27.forwardRef(
4423
4489
  ({ scrim, kind, still, className, ...props }, ref) => {
4424
4490
  const Overlay = kind === "alert" ? AlertDialogPrimitive.Overlay : DialogPrimitive2.Overlay;
4425
4491
  return /* @__PURE__ */ jsx24(
@@ -4617,9 +4683,9 @@ var listBoxClassName = {
4617
4683
  };
4618
4684
  var listFloorClassName = "h-[calc(112px+var(--space-3))]";
4619
4685
  function OverlayList({ height = "md", fit = "max", label, children }) {
4620
- const ref = React26.useRef(null);
4621
- const [hasFocusable, setHasFocusable] = React26.useState(true);
4622
- React26.useLayoutEffect(() => {
4686
+ const ref = React27.useRef(null);
4687
+ const [hasFocusable, setHasFocusable] = React27.useState(true);
4688
+ React27.useLayoutEffect(() => {
4623
4689
  const node = ref.current;
4624
4690
  if (!node) return;
4625
4691
  const check = () => setHasFocusable(firstTabbable(node, TABBABLE_CANDIDATE) != null);
@@ -4696,7 +4762,7 @@ var bottomSheet = {
4696
4762
  };
4697
4763
 
4698
4764
  // src/components/ui/sheet.tsx
4699
- import * as React27 from "react";
4765
+ import * as React28 from "react";
4700
4766
  import { Dialog as SheetPrimitive } from "radix-ui";
4701
4767
  import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
4702
4768
  var defaultSheetMotionConfig = {
@@ -4766,7 +4832,7 @@ function StructuredSheet({
4766
4832
  }) {
4767
4833
  const policy = OVERLAY_POLICY.sheet;
4768
4834
  const motionConfig = resolveSheetMotionConfig(motion);
4769
- const surfaceRef = React27.useRef(null);
4835
+ const surfaceRef = React28.useRef(null);
4770
4836
  const swipe = useSwipeDismiss({ enabled: policy.swipe, onDismiss: () => onOpenChange(false), surfaceRef });
4771
4837
  const returnFocus = useReturnFocus();
4772
4838
  return /* @__PURE__ */ jsx25(SheetPrimitive.Root, { open, onOpenChange, children: /* @__PURE__ */ jsx25(FormFieldBoundary, { children: /* @__PURE__ */ jsxs22(SheetPrimitive.Portal, { children: [
@@ -4999,7 +5065,7 @@ import { Fragment as Fragment10, jsx as jsx26, jsxs as jsxs23 } from "react/jsx-
4999
5065
  function dialogMobileSheetStyle(style) {
5000
5066
  return getDefaultSheetMotionStyle(style);
5001
5067
  }
5002
- var DialogModalContext = React28.createContext(true);
5068
+ var DialogModalContext = React29.createContext(true);
5003
5069
  function Dialog(props) {
5004
5070
  if (props.title !== void 0) return /* @__PURE__ */ jsx26(StructuredDialog, { ...props });
5005
5071
  return /* @__PURE__ */ jsx26(DialogRoot, { ...props });
@@ -5037,7 +5103,7 @@ function StructuredDialog({
5037
5103
  onError
5038
5104
  });
5039
5105
  const returnFocus = useReturnFocus();
5040
- const surfaceRef = React28.useRef(null);
5106
+ const surfaceRef = React29.useRef(null);
5041
5107
  const swipe = useSwipeDismiss({ enabled: policy.swipe, onDismiss: () => guardOpenChange(false), surfaceRef });
5042
5108
  const body = list != null ? (
5043
5109
  // Scrolls only on a screen too low for the body's 16 and the list floor; the footer stays.
@@ -5119,7 +5185,7 @@ function DialogPortal(props) {
5119
5185
  return /* @__PURE__ */ jsx26(FormFieldBoundary, { children: /* @__PURE__ */ jsx26(DialogPrimitive3.Portal, { ...props }) });
5120
5186
  }
5121
5187
  var DialogClose = DialogPrimitive3.Close;
5122
- var DialogOverlay = React28.forwardRef(({ className, ...props }, ref) => (
5188
+ var DialogOverlay = React29.forwardRef(({ className, ...props }, ref) => (
5123
5189
  // Position and scrim color come from the shared scrim (overlay-anatomy).
5124
5190
  /* @__PURE__ */ jsx26(
5125
5191
  OverlayScrimLayer,
@@ -5136,7 +5202,7 @@ var DialogOverlay = React28.forwardRef(({ className, ...props }, ref) => (
5136
5202
  )
5137
5203
  ));
5138
5204
  DialogOverlay.displayName = DialogPrimitive3.Overlay.displayName;
5139
- var DialogContent = React28.forwardRef(
5205
+ var DialogContent = React29.forwardRef(
5140
5206
  ({
5141
5207
  className,
5142
5208
  children,
@@ -5147,7 +5213,7 @@ var DialogContent = React28.forwardRef(
5147
5213
  onCloseAutoFocus,
5148
5214
  ...props
5149
5215
  }, ref) => {
5150
- const modal = React28.useContext(DialogModalContext);
5216
+ const modal = React29.useContext(DialogModalContext);
5151
5217
  const returnFocus = useReturnFocus();
5152
5218
  const handleOpenAutoFocus = (event) => {
5153
5219
  if (modal) returnFocus.onOpenAutoFocus(event);
@@ -5232,7 +5298,7 @@ var DialogFooter = ({
5232
5298
  }
5233
5299
  );
5234
5300
  DialogFooter.displayName = "DialogFooter";
5235
- var DialogTitle = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
5301
+ var DialogTitle = React29.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
5236
5302
  DialogPrimitive3.Title,
5237
5303
  {
5238
5304
  ref,
@@ -5244,7 +5310,7 @@ var DialogTitle = React28.forwardRef(({ className, ...props }, ref) => /* @__PUR
5244
5310
  }
5245
5311
  ));
5246
5312
  DialogTitle.displayName = DialogPrimitive3.Title.displayName;
5247
- var DialogDescription = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
5313
+ var DialogDescription = React29.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
5248
5314
  DialogPrimitive3.Description,
5249
5315
  {
5250
5316
  ref,
@@ -5253,7 +5319,7 @@ var DialogDescription = React28.forwardRef(({ className, ...props }, ref) => /*
5253
5319
  }
5254
5320
  ));
5255
5321
  DialogDescription.displayName = DialogPrimitive3.Description.displayName;
5256
- var DialogEyebrow = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
5322
+ var DialogEyebrow = React29.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
5257
5323
  "p",
5258
5324
  {
5259
5325
  ref,
@@ -5265,7 +5331,7 @@ var DialogEyebrow = React28.forwardRef(({ className, ...props }, ref) => /* @__P
5265
5331
  }
5266
5332
  ));
5267
5333
  DialogEyebrow.displayName = "DialogEyebrow";
5268
- var DialogRawContent = React28.forwardRef((props, ref) => /* @__PURE__ */ jsx26(FormFieldBoundary, { children: /* @__PURE__ */ jsx26(DialogPrimitive3.Content, { ref, ...props }) }));
5334
+ var DialogRawContent = React29.forwardRef((props, ref) => /* @__PURE__ */ jsx26(FormFieldBoundary, { children: /* @__PURE__ */ jsx26(DialogPrimitive3.Content, { ref, ...props }) }));
5269
5335
  DialogRawContent.displayName = DialogPrimitive3.Content.displayName;
5270
5336
 
5271
5337
  // src/components/ui/form-modal.tsx
@@ -5442,11 +5508,11 @@ function InfoModal({
5442
5508
  }
5443
5509
 
5444
5510
  // src/components/ui/filter-toolbar.tsx
5445
- import * as React31 from "react";
5511
+ import * as React32 from "react";
5446
5512
  import { SlidersHorizontal } from "lucide-react";
5447
5513
 
5448
5514
  // src/components/ui/chip.tsx
5449
- import * as React29 from "react";
5515
+ import * as React30 from "react";
5450
5516
  import { cva as cva11 } from "class-variance-authority";
5451
5517
  import { X as X3 } from "lucide-react";
5452
5518
  import { Slot as Slot2 } from "radix-ui";
@@ -5566,7 +5632,7 @@ function ChipCount({
5566
5632
  ] })
5567
5633
  ] });
5568
5634
  }
5569
- var Chip = React29.forwardRef(
5635
+ var Chip = React30.forwardRef(
5570
5636
  ({
5571
5637
  className,
5572
5638
  variant = "filter",
@@ -5671,7 +5737,7 @@ var Chip = React29.forwardRef(
5671
5737
  Chip.displayName = "Chip";
5672
5738
 
5673
5739
  // src/components/ui/popover.tsx
5674
- import * as React30 from "react";
5740
+ import * as React31 from "react";
5675
5741
  import { Popover as PopoverPrimitive } from "radix-ui";
5676
5742
  import { jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
5677
5743
  function Popover({ modal = false, ...props }) {
@@ -5681,7 +5747,7 @@ var popoverArrowClassName = "fill-[var(--bg-surface)] stroke-[var(--border)] [&>
5681
5747
  var PopoverTrigger = PopoverPrimitive.Trigger;
5682
5748
  var PopoverAnchor = PopoverPrimitive.Anchor;
5683
5749
  var PopoverClose = PopoverPrimitive.Close;
5684
- var PopoverContent = React30.forwardRef(({ className, align = "center", sideOffset = 8, collisionPadding = 8, showArrow = false, children, ...props }, ref) => /* @__PURE__ */ jsx31(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsxs27(
5750
+ var PopoverContent = React31.forwardRef(({ className, align = "center", sideOffset = 8, collisionPadding = 8, showArrow = false, children, ...props }, ref) => /* @__PURE__ */ jsx31(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsxs27(
5685
5751
  PopoverPrimitive.Content,
5686
5752
  {
5687
5753
  ref,
@@ -5718,7 +5784,7 @@ var PopoverContent = React30.forwardRef(({ className, align = "center", sideOffs
5718
5784
  }
5719
5785
  ) }));
5720
5786
  PopoverContent.displayName = PopoverPrimitive.Content.displayName;
5721
- var PopoverArrow = React30.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx31(
5787
+ var PopoverArrow = React31.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx31(
5722
5788
  PopoverPrimitive.Arrow,
5723
5789
  {
5724
5790
  ref,
@@ -5769,9 +5835,9 @@ function canTakeFocus(element) {
5769
5835
  return Boolean(element && element.getClientRects().length > 0 && !element.matches(":disabled"));
5770
5836
  }
5771
5837
  function filterCells(node, prefix = "") {
5772
- return React31.Children.toArray(node).flatMap((child, index) => {
5773
- const key = `${prefix}${React31.isValidElement(child) ? child.key : index}`;
5774
- return React31.isValidElement(child) && child.type === React31.Fragment ? filterCells(child.props.children, `${key}/`) : [{ key, cell: child }];
5838
+ return React32.Children.toArray(node).flatMap((child, index) => {
5839
+ const key = `${prefix}${React32.isValidElement(child) ? child.key : index}`;
5840
+ return React32.isValidElement(child) && child.type === React32.Fragment ? filterCells(child.props.children, `${key}/`) : [{ key, cell: child }];
5775
5841
  });
5776
5842
  }
5777
5843
  function contentWidth(element) {
@@ -5784,7 +5850,7 @@ function warnGridFilters(count) {
5784
5850
  `FilterToolbar: layout="grid" fits ${MAX_GRID_FILTERS} filters on the line, got ${count}. Move the rest to \`collapsible\`.`
5785
5851
  );
5786
5852
  }
5787
- var FilterToolbar = React31.forwardRef(
5853
+ var FilterToolbar = React32.forwardRef(
5788
5854
  ({
5789
5855
  className,
5790
5856
  search,
@@ -5803,20 +5869,20 @@ var FilterToolbar = React31.forwardRef(
5803
5869
  appliedFilters,
5804
5870
  ...props
5805
5871
  }, ref) => {
5806
- const [rootElement, setRootElement] = React31.useState(
5872
+ const [rootElement, setRootElement] = React32.useState(
5807
5873
  null
5808
5874
  );
5809
- const [containerWidth, setContainerWidth] = React31.useState(
5875
+ const [containerWidth, setContainerWidth] = React32.useState(
5810
5876
  null
5811
5877
  );
5812
- const [overlayOpen, setOverlayOpen] = React31.useState(false);
5813
- const rootRef = React31.useRef(null);
5814
- const triggerRef = React31.useRef(null);
5815
- const rowRef = React31.useRef(null);
5816
- const chipsRef = React31.useRef(null);
5817
- const chipRemoveRefs = React31.useRef(/* @__PURE__ */ new Map());
5818
- const pendingFocusRef = React31.useRef(null);
5819
- const setRootRefs = React31.useCallback(
5878
+ const [overlayOpen, setOverlayOpen] = React32.useState(false);
5879
+ const rootRef = React32.useRef(null);
5880
+ const triggerRef = React32.useRef(null);
5881
+ const rowRef = React32.useRef(null);
5882
+ const chipsRef = React32.useRef(null);
5883
+ const chipRemoveRefs = React32.useRef(/* @__PURE__ */ new Map());
5884
+ const pendingFocusRef = React32.useRef(null);
5885
+ const setRootRefs = React32.useCallback(
5820
5886
  (element) => {
5821
5887
  rootRef.current = element;
5822
5888
  setRootElement(element);
@@ -5826,7 +5892,7 @@ var FilterToolbar = React31.forwardRef(
5826
5892
  [ref]
5827
5893
  );
5828
5894
  const isGrid = layout === "grid";
5829
- React31.useEffect(() => {
5895
+ React32.useEffect(() => {
5830
5896
  if (!rootElement) return;
5831
5897
  const updateWidth = (entry) => {
5832
5898
  setContainerWidth(
@@ -5839,16 +5905,16 @@ var FilterToolbar = React31.forwardRef(
5839
5905
  observer.observe(rootElement);
5840
5906
  return () => observer.disconnect();
5841
5907
  }, [rootElement, isGrid]);
5842
- const handleOverlayOpenChange = React31.useCallback((open) => {
5908
+ const handleOverlayOpenChange = React32.useCallback((open) => {
5843
5909
  setOverlayOpen(open);
5844
5910
  if (!open) queueMicrotask(() => triggerRef.current?.focus());
5845
5911
  }, []);
5846
5912
  const gridCells = isGrid ? filterCells(filters) : [];
5847
5913
  const filterCellCount = gridCells.length;
5848
- React31.useEffect(() => {
5914
+ React32.useEffect(() => {
5849
5915
  if (filterCellCount > MAX_GRID_FILTERS) warnGridFilters(filterCellCount);
5850
5916
  }, [filterCellCount]);
5851
- React31.useEffect(() => {
5917
+ React32.useEffect(() => {
5852
5918
  const ownerDocument = rootElement?.ownerDocument;
5853
5919
  if (!ownerDocument) return;
5854
5920
  const dropOutside = (event) => {
@@ -5861,14 +5927,14 @@ var FilterToolbar = React31.forwardRef(
5861
5927
  ownerDocument.removeEventListener("pointerdown", dropOutside, true);
5862
5928
  };
5863
5929
  }, [rootElement]);
5864
- React31.useEffect(() => {
5930
+ React32.useEffect(() => {
5865
5931
  const request = pendingFocusRef.current;
5866
5932
  if (!request) return;
5867
5933
  const present = new Set(appliedFilters?.map((filter) => filter.key));
5868
5934
  if (request.removed.some((key) => present.has(key))) return;
5869
5935
  pendingFocusRef.current = null;
5870
5936
  const active = rootElement?.ownerDocument.activeElement;
5871
- if (active && active !== rootElement.ownerDocument.body) return;
5937
+ if (active && active !== rootElement.ownerDocument.body && canTakeFocus(active)) return;
5872
5938
  const candidates = [
5873
5939
  ...request.next.map((key) => chipRemoveRefs.current.get(key)),
5874
5940
  triggerRef.current,
@@ -5890,7 +5956,7 @@ var FilterToolbar = React31.forwardRef(
5890
5956
  const narrowFilterCount = activeFilterCount + lineFilterCount;
5891
5957
  const hasCollapsed = Boolean(collapsible) || gridSheet;
5892
5958
  const outgrownSheet = isGrid && !collapsible && containerWidth !== null && containerWidth >= 640 && overlayOpen;
5893
- React31.useEffect(() => {
5959
+ React32.useEffect(() => {
5894
5960
  if (!outgrownSheet) return;
5895
5961
  setOverlayOpen(false);
5896
5962
  const ownerDocument = rootElement?.ownerDocument;
@@ -6005,10 +6071,9 @@ var FilterToolbar = React31.forwardRef(
6005
6071
  children: search
6006
6072
  }
6007
6073
  ) : null,
6008
- hasCollapsed && (usesSheet || !collapsible) ? collapseTrigger : null,
6009
- collapsible && !usesSheet ? /* @__PURE__ */ jsxs28(Popover, { open: overlayOpen, onOpenChange: handleOverlayOpenChange, children: [
6074
+ collapsible ? /* @__PURE__ */ jsxs28(Popover, { open: overlayOpen, onOpenChange: handleOverlayOpenChange, children: [
6010
6075
  /* @__PURE__ */ jsx32(PopoverAnchor, { asChild: true, children: collapseTrigger }),
6011
- overlayOpen ? /* @__PURE__ */ jsxs28(
6076
+ overlayOpen && !usesSheet ? /* @__PURE__ */ jsxs28(
6012
6077
  PopoverContent,
6013
6078
  {
6014
6079
  role: "dialog",
@@ -6023,7 +6088,7 @@ var FilterToolbar = React31.forwardRef(
6023
6088
  ]
6024
6089
  }
6025
6090
  ) : null
6026
- ] }) : null,
6091
+ ] }) : collapseTrigger,
6027
6092
  filters && !linesInSheet ? /* @__PURE__ */ jsx32(
6028
6093
  "div",
6029
6094
  {
@@ -6189,12 +6254,12 @@ var FilterToolbar = React31.forwardRef(
6189
6254
  FilterToolbar.displayName = "FilterToolbar";
6190
6255
 
6191
6256
  // src/components/ui/data-table.tsx
6192
- import * as React35 from "react";
6257
+ import * as React36 from "react";
6193
6258
  import { ChevronDown as ChevronDown5, ChevronRight as ChevronRight3, ChevronUp as ChevronUp2, ChevronsUpDown, EllipsisVertical } from "lucide-react";
6194
6259
  import { cva as cva13 } from "class-variance-authority";
6195
6260
 
6196
6261
  // src/components/ui/action-menu.tsx
6197
- import * as React32 from "react";
6262
+ import * as React33 from "react";
6198
6263
  import { Dialog as DialogPrimitive4, Slot as Slot3 } from "radix-ui";
6199
6264
 
6200
6265
  // src/components/ui/dropdown-menu.tsx
@@ -6473,9 +6538,9 @@ function ActionMenuSheet({
6473
6538
  onOpenAutoFocus,
6474
6539
  onCloseAutoFocus
6475
6540
  }) {
6476
- const pendingRef = React32.useRef(null);
6477
- const surfaceRef = React32.useRef(null);
6478
- const labelId = React32.useId();
6541
+ const pendingRef = React33.useRef(null);
6542
+ const surfaceRef = React33.useRef(null);
6543
+ const labelId = React33.useId();
6479
6544
  const handleOpenChange = (nextOpen) => {
6480
6545
  pendingRef.current = null;
6481
6546
  onOpenChange(nextOpen);
@@ -6526,7 +6591,7 @@ function ActionMenuSheet({
6526
6591
  dragHandleProps: swipe.handleProps
6527
6592
  }
6528
6593
  ),
6529
- /* @__PURE__ */ jsx34(OverlayBody, { kind: "menu", children: groups.map((group, index) => /* @__PURE__ */ jsxs30(React32.Fragment, { children: [
6594
+ /* @__PURE__ */ jsx34(OverlayBody, { kind: "menu", children: groups.map((group, index) => /* @__PURE__ */ jsxs30(React33.Fragment, { children: [
6530
6595
  index > 0 ? /* @__PURE__ */ jsx34("div", { role: "separator", className: sheetGroupSeparatorClassName }) : null,
6531
6596
  /* @__PURE__ */ jsxs30("div", { role: "group", "aria-labelledby": group.label ? `${labelId}-${index}` : void 0, children: [
6532
6597
  group.label ? /* @__PURE__ */ jsx34("div", { id: `${labelId}-${index}`, className: sheetGroupLabelClassName, children: group.label }) : null,
@@ -6574,7 +6639,7 @@ function ActionMenuDropdownItem({
6574
6639
  item,
6575
6640
  onPick
6576
6641
  }) {
6577
- const id = React32.useId();
6642
+ const id = React33.useId();
6578
6643
  const labelId = `${id}-label`;
6579
6644
  const reasonId = `${id}-reason`;
6580
6645
  const Icon = item.icon;
@@ -6585,6 +6650,7 @@ function ActionMenuDropdownItem({
6585
6650
  {
6586
6651
  variant: item.destructive ? "destructive" : "default",
6587
6652
  disabled: item.disabled,
6653
+ title: item.title,
6588
6654
  onSelect: () => onPick(item),
6589
6655
  children: [
6590
6656
  Icon ? /* @__PURE__ */ jsx34(Icon, { "aria-hidden": true, size: 16, strokeWidth: 1.75 }) : null,
@@ -6614,7 +6680,7 @@ function ActionMenuDropdownItem({
6614
6680
  }
6615
6681
  var readPresentation = () => window.matchMedia?.(OVERLAY_DESKTOP_QUERY).matches ?? true ? "dropdown" : "sheet";
6616
6682
  var subscribeNothing = () => () => void 0;
6617
- var useHydrated = () => React32.useSyncExternalStore(
6683
+ var useHydrated = () => React33.useSyncExternalStore(
6618
6684
  subscribeNothing,
6619
6685
  () => true,
6620
6686
  () => false
@@ -6629,10 +6695,10 @@ function ActionMenu({
6629
6695
  items,
6630
6696
  groups
6631
6697
  }) {
6632
- const [uncontrolledOpen, setUncontrolledOpen] = React32.useState(false);
6698
+ const [uncontrolledOpen, setUncontrolledOpen] = React33.useState(false);
6633
6699
  const hydrated = useHydrated();
6634
6700
  const open = (openProp ?? uncontrolledOpen) && hydrated;
6635
- const [shown, setShown] = React32.useState({
6701
+ const [shown, setShown] = React33.useState({
6636
6702
  open: false,
6637
6703
  presentation: "dropdown"
6638
6704
  });
@@ -6641,8 +6707,8 @@ function ActionMenu({
6641
6707
  if (open) presentation = readPresentation();
6642
6708
  setShown({ open, presentation });
6643
6709
  }
6644
- const triggerRef = React32.useRef(null);
6645
- const pendingRef = React32.useRef(null);
6710
+ const triggerRef = React33.useRef(null);
6711
+ const pendingRef = React33.useRef(null);
6646
6712
  const setOpen = (nextOpen) => {
6647
6713
  if (nextOpen) pendingRef.current = null;
6648
6714
  if (openProp === void 0) setUncontrolledOpen(nextOpen);
@@ -6665,7 +6731,7 @@ function ActionMenu({
6665
6731
  return /* @__PURE__ */ jsxs30(Fragment16, { children: [
6666
6732
  /* @__PURE__ */ jsxs30(DropdownMenu, { open: open && presentation === "dropdown", onOpenChange: setOpen, children: [
6667
6733
  /* @__PURE__ */ jsx34(DropdownMenuTrigger, { asChild: true, "aria-expanded": open, children: /* @__PURE__ */ jsx34(Slot3.Root, { ref: triggerRef, children: trigger }) }),
6668
- /* @__PURE__ */ jsx34(DropdownMenuContent, { align: "end", onCloseAutoFocus: handleDropdownCloseAutoFocus, children: menuGroups.map((group, index) => /* @__PURE__ */ jsxs30(React32.Fragment, { children: [
6734
+ /* @__PURE__ */ jsx34(DropdownMenuContent, { align: "end", onCloseAutoFocus: handleDropdownCloseAutoFocus, children: menuGroups.map((group, index) => /* @__PURE__ */ jsxs30(React33.Fragment, { children: [
6669
6735
  index > 0 ? /* @__PURE__ */ jsx34(DropdownMenuSeparator, {}) : null,
6670
6736
  /* @__PURE__ */ jsxs30(DropdownMenuGroup, { children: [
6671
6737
  group.label ? /* @__PURE__ */ jsx34(DropdownMenuLabel, { children: group.label }) : null,
@@ -6698,7 +6764,7 @@ function ActionMenu({
6698
6764
  }
6699
6765
 
6700
6766
  // src/components/ui/checkbox.tsx
6701
- import * as React33 from "react";
6767
+ import * as React34 from "react";
6702
6768
  import { cva as cva12 } from "class-variance-authority";
6703
6769
  import { Check as Check4, Minus } from "lucide-react";
6704
6770
  import { Checkbox as CheckboxPrimitive } from "radix-ui";
@@ -6805,11 +6871,11 @@ var checkboxGroupBoxVariants = cva12(
6805
6871
  }
6806
6872
  }
6807
6873
  );
6808
- var CheckboxGroupContext = React33.createContext(null);
6874
+ var CheckboxGroupContext = React34.createContext(null);
6809
6875
  function getLabel(children, label) {
6810
6876
  return children ?? label;
6811
6877
  }
6812
- var Checkbox = React33.forwardRef(
6878
+ var Checkbox = React34.forwardRef(
6813
6879
  ({
6814
6880
  className,
6815
6881
  size = "md",
@@ -6828,9 +6894,9 @@ var Checkbox = React33.forwardRef(
6828
6894
  "aria-describedby": ariaDescribedBy,
6829
6895
  ...props
6830
6896
  }, ref) => {
6831
- const group = React33.useContext(CheckboxGroupContext);
6897
+ const group = React34.useContext(CheckboxGroupContext);
6832
6898
  const field = useFormFieldControl();
6833
- const generatedId = React33.useId();
6899
+ const generatedId = React34.useId();
6834
6900
  const labelContent = getLabel(children, label);
6835
6901
  const isGrouped = Boolean(group && value != null);
6836
6902
  const valueString = value == null ? void 0 : String(value);
@@ -7072,11 +7138,11 @@ function ContextMenu({
7072
7138
  }
7073
7139
 
7074
7140
  // src/components/ui/list-card.tsx
7075
- import * as React34 from "react";
7141
+ import * as React35 from "react";
7076
7142
  import { ChevronRight as ChevronRight2, MoreVertical } from "lucide-react";
7077
7143
  import { Fragment as Fragment17, jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
7078
7144
  function lineTokens(value) {
7079
- return React34.Children.toArray(value).filter((token) => token !== "");
7145
+ return React35.Children.toArray(value).filter((token) => token !== "");
7080
7146
  }
7081
7147
  function MetaLine({
7082
7148
  tokens,
@@ -7158,7 +7224,7 @@ function ListCard({
7158
7224
  "data-slot": `${slot}-title`,
7159
7225
  className: titleClassName,
7160
7226
  title: typeof title === "string" || typeof title === "number" ? String(title) : void 0,
7161
- children: overlay && href != null ? React34.createElement(linkComponent ?? "a", { ...linkProps, href, className: overlayClassName }, title) : title
7227
+ children: overlay && href != null ? React35.createElement(linkComponent ?? "a", { ...linkProps, href, className: overlayClassName }, title) : title
7162
7228
  }
7163
7229
  );
7164
7230
  const content = /* @__PURE__ */ jsxs33(Fragment17, { children: [
@@ -7355,18 +7421,18 @@ function RowContextMenu({
7355
7421
  cards,
7356
7422
  onClose
7357
7423
  }) {
7358
- const [open, setOpen] = React35.useState(true);
7359
- const closeRef = React35.useRef(null);
7360
- const pressedOutside = React35.useRef(false);
7424
+ const [open, setOpen] = React36.useState(true);
7425
+ const closeRef = React36.useRef(null);
7426
+ const pressedOutside = React36.useRef(false);
7361
7427
  const close = (reason) => {
7362
7428
  closeRef.current ??= reason;
7363
7429
  setOpen(false);
7364
7430
  };
7365
- const shownGroups = React35.useRef([]);
7431
+ const shownGroups = React36.useRef([]);
7366
7432
  if (groups) shownGroups.current = groups;
7367
7433
  const gone = groups === null;
7368
- const contentRef = React35.useRef(null);
7369
- const focusInsideRef = React35.useRef(false);
7434
+ const contentRef = React36.useRef(null);
7435
+ const focusInsideRef = React36.useRef(false);
7370
7436
  useIsomorphicLayoutEffect(() => {
7371
7437
  const content = contentRef.current;
7372
7438
  if (!open || !focusInsideRef.current || !content?.isConnected) return;
@@ -7375,7 +7441,7 @@ function RowContextMenu({
7375
7441
  const next = content.querySelector('[role="menuitem"]:not([data-disabled])') ?? content;
7376
7442
  next.focus();
7377
7443
  });
7378
- React35.useEffect(() => {
7444
+ React36.useEffect(() => {
7379
7445
  if (gone) close({ by: "dismiss", outside: false });
7380
7446
  }, [gone]);
7381
7447
  useIsomorphicLayoutEffect(() => {
@@ -7414,7 +7480,7 @@ function RowContextMenu({
7414
7480
  onClose(menuKey, reason);
7415
7481
  }
7416
7482
  },
7417
- children: shownGroups.current.map((group, index) => /* @__PURE__ */ jsxs34(React35.Fragment, { children: [
7483
+ children: shownGroups.current.map((group, index) => /* @__PURE__ */ jsxs34(React36.Fragment, { children: [
7418
7484
  index > 0 ? /* @__PURE__ */ jsx38(DropdownMenuSeparator, {}) : null,
7419
7485
  /* @__PURE__ */ jsxs34(DropdownMenuGroup, { children: [
7420
7486
  group.label ? /* @__PURE__ */ jsx38(DropdownMenuLabel, { children: group.label }) : null,
@@ -7441,7 +7507,7 @@ function getRenderedCell(row, column) {
7441
7507
  if (value === null || value === void 0) {
7442
7508
  return null;
7443
7509
  }
7444
- if (React35.isValidElement(value)) {
7510
+ if (React36.isValidElement(value)) {
7445
7511
  return value;
7446
7512
  }
7447
7513
  return String(value);
@@ -7670,7 +7736,7 @@ var expandedPanelClass = cn(
7670
7736
  );
7671
7737
  var expandChevronClass = "motion-safe:transition-transform motion-safe:duration-[var(--dur-base)] motion-safe:ease-[var(--ease-standard)]";
7672
7738
  function useOpenedOnce(expanded) {
7673
- const [opened, setOpened] = React35.useState(expanded);
7739
+ const [opened, setOpened] = React36.useState(expanded);
7674
7740
  if (expanded && !opened) {
7675
7741
  setOpened(true);
7676
7742
  }
@@ -7927,9 +7993,9 @@ function DataTableMobileCardView({
7927
7993
  }
7928
7994
  );
7929
7995
  }
7930
- var MemoDataTableRow = React35.memo(DataTableRowView);
7931
- var MemoDataTableMobileCard = React35.memo(DataTableMobileCardView);
7932
- var useIsomorphicLayoutEffect = typeof window === "undefined" ? React35.useEffect : React35.useLayoutEffect;
7996
+ var MemoDataTableRow = React36.memo(DataTableRowView);
7997
+ var MemoDataTableMobileCard = React36.memo(DataTableMobileCardView);
7998
+ var useIsomorphicLayoutEffect = typeof window === "undefined" ? React36.useEffect : React36.useLayoutEffect;
7933
7999
  var VIRTUAL_DEFAULT_OVERSCAN = 8;
7934
8000
  var VIRTUAL_INITIAL_ROWS = 24;
7935
8001
  var VIRTUAL_FALLBACK_SIZE = { desktop: 48, mobile: 120 };
@@ -8009,7 +8075,7 @@ function useVirtualWindow({
8009
8075
  mobileListRef
8010
8076
  }) {
8011
8077
  const count = rowIds.length;
8012
- const [win, setWin] = React35.useState({
8078
+ const [win, setWin] = React36.useState({
8013
8079
  layout: null,
8014
8080
  start: 0,
8015
8081
  end: VIRTUAL_INITIAL_ROWS,
@@ -8017,12 +8083,12 @@ function useVirtualWindow({
8017
8083
  padTop: 0,
8018
8084
  padBottom: 0
8019
8085
  });
8020
- const desktopSize = React35.useRef(0);
8021
- const cardHeights = React35.useRef(null);
8086
+ const desktopSize = React36.useRef(0);
8087
+ const cardHeights = React36.useRef(null);
8022
8088
  cardHeights.current ??= new CardHeights();
8023
- const update = React35.useRef(() => void 0);
8024
- const reported = React35.useRef("");
8025
- const latest = React35.useRef({
8089
+ const update = React36.useRef(() => void 0);
8090
+ const reported = React36.useRef("");
8091
+ const latest = React36.useRef({
8026
8092
  count,
8027
8093
  layout: "desktop",
8028
8094
  extent: uniformExtent(VIRTUAL_FALLBACK_SIZE.desktop)
@@ -8085,7 +8151,7 @@ function useVirtualWindow({
8085
8151
  useIsomorphicLayoutEffect(() => {
8086
8152
  update.current();
8087
8153
  });
8088
- React35.useEffect(() => {
8154
+ React36.useEffect(() => {
8089
8155
  if (!enabled) {
8090
8156
  return;
8091
8157
  }
@@ -8107,7 +8173,7 @@ function useVirtualWindow({
8107
8173
  window.cancelAnimationFrame(frame);
8108
8174
  };
8109
8175
  }, [enabled]);
8110
- const scrollToIndex = React35.useCallback(
8176
+ const scrollToIndex = React36.useCallback(
8111
8177
  (index) => {
8112
8178
  const { count: rowCount, layout, extent } = latest.current;
8113
8179
  const list = (layout === "desktop" ? desktopListRef : mobileListRef).current;
@@ -8140,7 +8206,7 @@ function useVisibleLayout({
8140
8206
  desktopRef,
8141
8207
  mobileRef
8142
8208
  }) {
8143
- const [layout, setLayout] = React35.useState(null);
8209
+ const [layout, setLayout] = React36.useState(null);
8144
8210
  useIsomorphicLayoutEffect(() => {
8145
8211
  if (!enabled) {
8146
8212
  return;
@@ -8177,9 +8243,9 @@ function useLayoutFocusHandoff({
8177
8243
  layout,
8178
8244
  containers
8179
8245
  }) {
8180
- const lastFocus = React35.useRef(null);
8181
- const previousLayout = React35.useRef(layout);
8182
- React35.useEffect(() => {
8246
+ const lastFocus = React36.useRef(null);
8247
+ const previousLayout = React36.useRef(layout);
8248
+ React36.useEffect(() => {
8183
8249
  const root = rootRef.current;
8184
8250
  if (!root) {
8185
8251
  return;
@@ -8282,13 +8348,13 @@ function DataTableInner({
8282
8348
  if (isVirtual && columns.some((column) => column.wrap)) {
8283
8349
  warnWrapVirtualOnce();
8284
8350
  }
8285
- const rootRef = React35.useRef(null);
8286
- const desktopRef = React35.useRef(null);
8287
- const headerRef = React35.useRef(null);
8288
- const desktopListRef = React35.useRef(null);
8289
- const mobileRef = React35.useRef(null);
8290
- const mobileListRef = React35.useRef(null);
8291
- const setRootRef = React35.useCallback(
8351
+ const rootRef = React36.useRef(null);
8352
+ const desktopRef = React36.useRef(null);
8353
+ const headerRef = React36.useRef(null);
8354
+ const desktopListRef = React36.useRef(null);
8355
+ const mobileRef = React36.useRef(null);
8356
+ const mobileListRef = React36.useRef(null);
8357
+ const setRootRef = React36.useCallback(
8292
8358
  (node) => {
8293
8359
  rootRef.current = node;
8294
8360
  if (typeof ref === "function") ref(node);
@@ -8307,7 +8373,7 @@ function DataTableInner({
8307
8373
  desktopListRef,
8308
8374
  mobileListRef
8309
8375
  });
8310
- React35.useImperativeHandle(virtualOptions?.handleRef, () => ({ scrollToIndex }), [scrollToIndex]);
8376
+ React36.useImperativeHandle(virtualOptions?.handleRef, () => ({ scrollToIndex }), [scrollToIndex]);
8311
8377
  const visibleLayout = useVisibleLayout({ enabled: !isVirtual, desktopRef, mobileRef });
8312
8378
  const activeLayout = isVirtual ? virtualWindow.layout : visibleLayout;
8313
8379
  useLayoutFocusHandoff({
@@ -8331,8 +8397,8 @@ function DataTableInner({
8331
8397
  const expandable = renderExpanded != null;
8332
8398
  const hasRowActions = rowActions != null;
8333
8399
  const gridTemplateColumns = getGridTemplate(columns, selectable, expandable, hasRowActions);
8334
- const panelIdBase = React35.useId();
8335
- const [ownExpandedIds, setOwnExpandedIds] = React35.useState(() => /* @__PURE__ */ new Set());
8400
+ const panelIdBase = React36.useId();
8401
+ const [ownExpandedIds, setOwnExpandedIds] = React36.useState(() => /* @__PURE__ */ new Set());
8336
8402
  const resolvedExpandedIds = expandedIds ?? ownExpandedIds;
8337
8403
  const toggleExpanded = (id) => {
8338
8404
  const nextIds = new Set(resolvedExpandedIds);
@@ -8378,8 +8444,8 @@ function DataTableInner({
8378
8444
  window.location.assign(href);
8379
8445
  }
8380
8446
  };
8381
- const [contextMenu, setContextMenu] = React35.useState(null);
8382
- const contextMenuKey = React35.useRef(0);
8447
+ const [contextMenu, setContextMenu] = React36.useState(null);
8448
+ const contextMenuKey = React36.useRef(0);
8383
8449
  const contextRow = contextMenu ? data.find((item) => getRowId(item, keyField) === contextMenu.rowId) : void 0;
8384
8450
  const contextActions = contextRow && rowActions ? rowActions(contextRow) : [];
8385
8451
  const contextGroups = countActions(contextActions) > 0 ? toActionGroups(contextActions) : null;
@@ -8420,23 +8486,23 @@ function DataTableInner({
8420
8486
  if (close.by === "item") close.item.onSelect();
8421
8487
  };
8422
8488
  const handleRowContextMenu = rowActions ? openRowContextMenu : onRowContextMenu;
8423
- const latestHandlers = React35.useRef({ toggleRow, activateRow, onRowContextMenu, handleRowContextMenu });
8489
+ const latestHandlers = React36.useRef({ toggleRow, activateRow, onRowContextMenu, handleRowContextMenu });
8424
8490
  useIsomorphicLayoutEffect(() => {
8425
8491
  latestHandlers.current = { toggleRow, activateRow, onRowContextMenu, handleRowContextMenu };
8426
8492
  });
8427
- const stableToggleRow = React35.useCallback(
8493
+ const stableToggleRow = React36.useCallback(
8428
8494
  (id, checked) => latestHandlers.current.toggleRow(id, checked),
8429
8495
  []
8430
8496
  );
8431
- const stableActivateRow = React35.useCallback(
8497
+ const stableActivateRow = React36.useCallback(
8432
8498
  (row, href, event) => latestHandlers.current.activateRow(row, href, event),
8433
8499
  []
8434
8500
  );
8435
- const stableRowContextMenu = React35.useCallback(
8501
+ const stableRowContextMenu = React36.useCallback(
8436
8502
  (rowId, event) => latestHandlers.current.onRowContextMenu?.(rowId, event),
8437
8503
  []
8438
8504
  );
8439
- const stableHandleRowContextMenu = React35.useCallback(
8505
+ const stableHandleRowContextMenu = React36.useCallback(
8440
8506
  (rowId, event) => latestHandlers.current.handleRowContextMenu?.(rowId, event),
8441
8507
  []
8442
8508
  );
@@ -8682,14 +8748,21 @@ function DataTableInner({
8682
8748
  }
8683
8749
  );
8684
8750
  }
8685
- var DataTable = React35.forwardRef(DataTableInner);
8751
+ var DataTable = React36.forwardRef(DataTableInner);
8686
8752
  DataTable.displayName = "DataTable";
8687
8753
 
8688
8754
  // src/components/ui/bulk-action-bar.tsx
8689
- import * as React36 from "react";
8690
- import { X as X4 } from "lucide-react";
8755
+ import * as React37 from "react";
8756
+ import { Ellipsis, X as X4 } from "lucide-react";
8691
8757
  import { jsx as jsx39, jsxs as jsxs35 } from "react/jsx-runtime";
8692
- function CardActionButton({ action }) {
8758
+ var foldedStyle = {
8759
+ position: "absolute",
8760
+ top: 0,
8761
+ left: 0,
8762
+ visibility: "hidden",
8763
+ pointerEvents: "none"
8764
+ };
8765
+ function CardActionButton({ action, folded }) {
8693
8766
  const Icon = action.icon;
8694
8767
  return /* @__PURE__ */ jsxs35(
8695
8768
  Button,
@@ -8697,9 +8770,13 @@ function CardActionButton({ action }) {
8697
8770
  appearance: "outline",
8698
8771
  tone: action.variant === "destructive" ? "danger" : "neutral",
8699
8772
  size: "sm",
8700
- className: "before:-inset-y-[5px]",
8773
+ className: "shrink-0 before:-inset-y-[5px]",
8701
8774
  "data-slot": "bulk-action-bar-action",
8702
8775
  "data-variant": action.variant ?? "default",
8776
+ "data-folded": folded ? "" : void 0,
8777
+ "aria-hidden": folded || void 0,
8778
+ tabIndex: folded ? -1 : void 0,
8779
+ style: folded ? foldedStyle : void 0,
8703
8780
  disabled: action.disabled,
8704
8781
  title: action.title,
8705
8782
  onClick: action.onClick,
@@ -8718,6 +8795,191 @@ function CardActionButton({ action }) {
8718
8795
  }
8719
8796
  );
8720
8797
  }
8798
+ var BAR_LABEL = "\uC120\uD0DD \uD56D\uBAA9 \uC77C\uAD04 \uC791\uC5C5";
8799
+ var TO_LIST_LABEL = "\uBAA9\uB85D\uC73C\uB85C";
8800
+ var MORE_LABEL = "\uB354\uBCF4\uAE30";
8801
+ var BAR_SELECTOR = '[data-slot="bulk-action-bar"]';
8802
+ var ROW_SELECTOR = "[data-row-id]";
8803
+ var LIST_SELECTOR = '[role="rowgroup"],[role="list"],[role="listbox"],[role="grid"],[role="treegrid"],[role="tree"],[role="table"],table,tbody,ul,ol';
8804
+ var TEXT_ENTRY_SELECTOR = 'textarea,select,[contenteditable]:not([contenteditable="false"]),[role="textbox"],[role="combobox"],[role="searchbox"]';
8805
+ var NON_TEXT_INPUTS = /* @__PURE__ */ new Set(["checkbox", "radio", "button", "submit", "reset", "image", "file", "range", "color"]);
8806
+ function isShortcut(event) {
8807
+ return event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey && event.code === "Period";
8808
+ }
8809
+ function isTextEntry(target) {
8810
+ if (!(target instanceof Element)) return false;
8811
+ if (target instanceof HTMLInputElement) return !NON_TEXT_INPUTS.has(target.type);
8812
+ return target.isContentEditable === true || target.closest(TEXT_ENTRY_SELECTOR) !== null;
8813
+ }
8814
+ function isShown(node) {
8815
+ return typeof node.checkVisibility === "function" ? node.checkVisibility() : true;
8816
+ }
8817
+ function rowsIn(container) {
8818
+ const seen = /* @__PURE__ */ new Set();
8819
+ const rows = [];
8820
+ for (const node of container.querySelectorAll(ROW_SELECTOR)) {
8821
+ const id = node.getAttribute("data-row-id") ?? "";
8822
+ if (seen.has(id) || node.closest(BAR_SELECTOR) || !isShown(node)) continue;
8823
+ seen.add(id);
8824
+ rows.push(node);
8825
+ }
8826
+ return rows;
8827
+ }
8828
+ var listOf = (row) => row.parentElement?.closest(LIST_SELECTOR) ?? row.parentElement;
8829
+ var rowPosition = (row) => row?.getAttribute("aria-rowindex") ?? row?.getAttribute("aria-posinset") ?? null;
8830
+ function markOf(target) {
8831
+ const row = target.closest(ROW_SELECTOR);
8832
+ if (!row || row.closest(BAR_SELECTOR)) return null;
8833
+ const id = row.getAttribute("data-row-id") ?? "";
8834
+ const list = listOf(row);
8835
+ const rows = list ? rowsIn(list) : [];
8836
+ const index = rows.findIndex((node) => node.getAttribute("data-row-id") === id);
8837
+ return {
8838
+ id,
8839
+ checkbox: target.matches('[role="checkbox"],input[type="checkbox"]'),
8840
+ position: rowPosition(rows[index]),
8841
+ index,
8842
+ list
8843
+ };
8844
+ }
8845
+ function listIn(scope) {
8846
+ const row = rowsIn(scope)[0];
8847
+ if (row) return listOf(row);
8848
+ return Array.from(scope.querySelectorAll(LIST_SELECTOR)).find(
8849
+ (node) => !node.closest(BAR_SELECTOR) && isShown(node)
8850
+ ) ?? null;
8851
+ }
8852
+ function returnTarget(scope, mark) {
8853
+ const list = mark?.list && mark.list.isConnected && scope.contains(mark.list) && isShown(mark.list) ? mark.list : listIn(scope);
8854
+ if (mark && list) {
8855
+ const rows = rowsIn(list);
8856
+ const row = rows.find((node) => node.getAttribute("data-row-id") === mark.id) ?? (mark.position !== null ? rows.find((node) => rowPosition(node) === mark.position) : mark.index >= 0 ? rows[mark.index] : void 0);
8857
+ if (row) {
8858
+ return (mark.checkbox ? row.querySelector('[role="checkbox"],input[type="checkbox"]') : row.hasAttribute("tabindex") ? row : row.querySelector('[data-slot="data-table-row-link"],[data-slot="data-table-expand-cell"] button')) ?? row;
8859
+ }
8860
+ }
8861
+ return list ?? scope;
8862
+ }
8863
+ function focusTarget(target) {
8864
+ if (!target.hasAttribute("tabindex") && !target.matches("a[href],button,input,select,textarea")) {
8865
+ target.tabIndex = -1;
8866
+ }
8867
+ target.focus();
8868
+ }
8869
+ var shortcutBars = /* @__PURE__ */ new Set();
8870
+ function scopeOf(card, scopeProp) {
8871
+ return scopeProp?.current ?? card.closest('[data-slot="data-layout-region"]') ?? card.parentElement;
8872
+ }
8873
+ function depth(node) {
8874
+ let n = 0;
8875
+ for (let at = node; at; at = at.parentNode) n += 1;
8876
+ return n;
8877
+ }
8878
+ function ownerOf(target) {
8879
+ let owner = null;
8880
+ let ownerDepth = -1;
8881
+ for (const bar of shortcutBars) {
8882
+ if (bar.card.contains(target)) return bar;
8883
+ const scope = bar.scope();
8884
+ if (scope?.contains(target) && depth(scope) > ownerDepth) {
8885
+ owner = bar;
8886
+ ownerDepth = depth(scope);
8887
+ }
8888
+ }
8889
+ return owner;
8890
+ }
8891
+ var MODAL_SELECTOR = '[role="dialog"],[role="alertdialog"]';
8892
+ function isFocusVisible(node) {
8893
+ try {
8894
+ return node.matches(":focus-visible");
8895
+ } catch {
8896
+ return false;
8897
+ }
8898
+ }
8899
+ var isMac = () => {
8900
+ const nav = navigator;
8901
+ return /mac|iphone|ipad|ipod/i.test(nav.userAgentData?.platform || nav.platform || "");
8902
+ };
8903
+ var keyCapStyle = {
8904
+ display: "inline-flex",
8905
+ boxSizing: "border-box",
8906
+ height: 20,
8907
+ minWidth: 20,
8908
+ alignItems: "center",
8909
+ justifyContent: "center",
8910
+ padding: "0 var(--space-1)",
8911
+ borderRadius: "var(--radius-sm)",
8912
+ background: "var(--semantic-neutral-bg)",
8913
+ fontFamily: "var(--font-sans)",
8914
+ fontSize: 12,
8915
+ fontWeight: 500,
8916
+ lineHeight: 1,
8917
+ color: "var(--text-tertiary)"
8918
+ };
8919
+ var visuallyHiddenStyle = {
8920
+ position: "absolute",
8921
+ width: 1,
8922
+ height: 1,
8923
+ margin: -1,
8924
+ padding: 0,
8925
+ overflow: "hidden",
8926
+ clip: "rect(0 0 0 0)",
8927
+ whiteSpace: "nowrap",
8928
+ border: 0
8929
+ };
8930
+ function MoveButton({
8931
+ mac,
8932
+ shown,
8933
+ onMove
8934
+ }) {
8935
+ return /* @__PURE__ */ jsxs35(
8936
+ Button,
8937
+ {
8938
+ appearance: "outline",
8939
+ size: "sm",
8940
+ className: "mr-auto shrink-0 pr-[var(--space-2)] before:-inset-y-[5px] [@media(hover:none)_and_(pointer:coarse)]:hidden",
8941
+ style: shown ? void 0 : visuallyHiddenStyle,
8942
+ "data-slot": "bulk-action-bar-move",
8943
+ "data-hidden": shown ? void 0 : "",
8944
+ "aria-keyshortcuts": "Control+.",
8945
+ onMouseDown: (event) => event.preventDefault(),
8946
+ onClick: onMove,
8947
+ children: [
8948
+ /* @__PURE__ */ jsx39("span", { "data-slot": "bulk-action-bar-move-label", children: TO_LIST_LABEL }),
8949
+ /* @__PURE__ */ jsxs35("span", { "aria-hidden": "true", "data-slot": "bulk-action-bar-keys", style: { display: "inline-flex", gap: "var(--space-1)" }, children: [
8950
+ /* @__PURE__ */ jsx39("kbd", { style: keyCapStyle, children: mac ? "\u2303" : "Ctrl" }),
8951
+ /* @__PURE__ */ jsx39("kbd", { style: keyCapStyle, children: "." })
8952
+ ] })
8953
+ ]
8954
+ }
8955
+ );
8956
+ }
8957
+ var sameFold = (a, b) => a !== null && a.folded === b.folded && a.texts.join("\n") === b.texts.join("\n");
8958
+ var ROW_GAP = 8;
8959
+ var MORE_WIDTH = 30;
8960
+ var MOVE_EDGES = 2 + 12 + 6 + 8;
8961
+ function measureFold(row, actionCount) {
8962
+ const buttons = Array.from(row.querySelectorAll('[data-slot="bulk-action-bar-action"]'));
8963
+ const texts = buttons.map((node) => node.textContent ?? "");
8964
+ const available = row.clientWidth;
8965
+ if (available === 0) return { folded: 0, texts };
8966
+ const scale = row.getBoundingClientRect().width / available || 1;
8967
+ const width = (node) => (node?.getBoundingClientRect().width ?? 0) / scale;
8968
+ const move = row.querySelector('[data-slot="bulk-action-bar-move"]');
8969
+ const hasMove = move !== null && !move.hasAttribute("data-hidden") && isShown(move);
8970
+ const label = hasMove ? width(row.querySelector('[data-slot="bulk-action-bar-move-label"]')) : 0;
8971
+ const keys = hasMove ? width(row.querySelector('[data-slot="bulk-action-bar-keys"]')) : 0;
8972
+ const actions = buttons.map(width);
8973
+ const need = (folded2) => {
8974
+ const items = actions.slice(0, actionCount - folded2);
8975
+ if (hasMove) items.unshift(keys + label + MOVE_EDGES);
8976
+ if (folded2 > 0) items.push(MORE_WIDTH);
8977
+ return items.reduce((sum, item) => sum + item, 0) + ROW_GAP * Math.max(0, items.length - 1);
8978
+ };
8979
+ let folded = 0;
8980
+ while (folded < actionCount - 1 && need(folded) > available + 0.5) folded += 1;
8981
+ return { folded, texts };
8982
+ }
8721
8983
  var CLEAR_CLEARANCE = 32;
8722
8984
  var IDLE_HEIGHT = 40;
8723
8985
  var FLOATING_BOTTOM = "calc(var(--space-4) + env(safe-area-inset-bottom))";
@@ -8771,10 +9033,10 @@ function reportOffset(key, card) {
8771
9033
  else cardOffsets.delete(key);
8772
9034
  writeOffset();
8773
9035
  }
8774
- var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React36.useEffect : React36.useLayoutEffect;
9036
+ var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React37.useEffect : React37.useLayoutEffect;
8775
9037
  function useBottomOffset(card) {
8776
- const [key] = React36.useState(() => ({}));
8777
- React36.useEffect(() => {
9038
+ const [key] = React37.useState(() => ({}));
9039
+ React37.useEffect(() => {
8778
9040
  if (!card) return;
8779
9041
  let frame = 0;
8780
9042
  let stopped = false;
@@ -8864,12 +9126,239 @@ function BulkActionBar({
8864
9126
  unit = "\uAC1C",
8865
9127
  summary,
8866
9128
  idleContent,
9129
+ shortcut = true,
9130
+ shortcutScope,
8867
9131
  className,
8868
9132
  style,
9133
+ "aria-label": ariaLabelProp,
8869
9134
  ...props
8870
9135
  }) {
8871
- const [card, setCard] = React36.useState(null);
9136
+ const ariaLabel = ariaLabelProp ?? BAR_LABEL;
9137
+ const [card, setCard] = React37.useState(null);
8872
9138
  useBottomOffset(card);
9139
+ const active = shortcut && count > 0;
9140
+ const cardRef = React37.useRef(null);
9141
+ const activeRef = React37.useRef(false);
9142
+ const scopePropRef = React37.useRef(shortcutScope);
9143
+ const markRef = React37.useRef(null);
9144
+ const moreRef = React37.useRef(null);
9145
+ const foldedFocusRef = React37.useRef(null);
9146
+ const focusedActionRef = React37.useRef(null);
9147
+ const moreLostFocusRef = React37.useRef(false);
9148
+ const [menuOpen, setMenuOpen] = React37.useState(false);
9149
+ const menuOpenRef = React37.useRef(false);
9150
+ const menuKeysRef = React37.useRef([]);
9151
+ const clearRef = React37.useRef(null);
9152
+ const [mac, setMac] = React37.useState(false);
9153
+ const [row, setRow] = React37.useState(null);
9154
+ const [fold, setFold] = React37.useState(null);
9155
+ React37.useEffect(() => setMac(isMac()), []);
9156
+ useIsomorphicLayoutEffect2(() => {
9157
+ activeRef.current = active;
9158
+ scopePropRef.current = shortcutScope;
9159
+ menuOpenRef.current = menuOpen;
9160
+ menuKeysRef.current = actions.slice(actions.length - Math.min(fold?.folded ?? 0, Math.max(0, actions.length - 1))).map((action) => action.key);
9161
+ });
9162
+ const toBar = React37.useCallback(() => {
9163
+ const node = cardRef.current;
9164
+ if (!node) return;
9165
+ const actionButtons = Array.from(node.querySelectorAll('[data-slot="bulk-action-bar-action"]'));
9166
+ const move = node.querySelector('[data-slot="bulk-action-bar-move"]');
9167
+ const target = actionButtons.find((button) => !button.disabled && !button.hasAttribute("data-folded")) ?? (actionButtons.some((button) => !button.disabled) ? moreRef.current : null) ?? (move && isShown(move) ? move : null) ?? clearRef.current;
9168
+ target?.focus();
9169
+ }, []);
9170
+ const toList = React37.useCallback(() => {
9171
+ const scope = cardRef.current && scopeOf(cardRef.current, scopePropRef.current);
9172
+ if (scope) focusTarget(returnTarget(scope, markRef.current));
9173
+ }, []);
9174
+ React37.useEffect(() => {
9175
+ if (!active || !card) return;
9176
+ const resolveScope = () => scopeOf(card, scopePropRef.current);
9177
+ const bar = { card, scope: resolveScope };
9178
+ const note = (target) => {
9179
+ const scope = resolveScope();
9180
+ if (!(target instanceof Element) || !scope?.contains(target) || card.contains(target)) return;
9181
+ const mark = markOf(target);
9182
+ if (mark) markRef.current = mark;
9183
+ };
9184
+ markRef.current = null;
9185
+ note(document.activeElement);
9186
+ const onFocusIn = (event) => note(event.target);
9187
+ const onKeyDown = (event) => {
9188
+ if (!isShortcut(event) || event.isComposing || event.defaultPrevented || isTextEntry(event.target)) return;
9189
+ if (!(event.target instanceof Node) || ownerOf(event.target) !== bar) return;
9190
+ event.preventDefault();
9191
+ if (card.contains(event.target)) toList();
9192
+ else toBar();
9193
+ };
9194
+ shortcutBars.add(bar);
9195
+ window.addEventListener("focusin", onFocusIn);
9196
+ window.addEventListener("keydown", onKeyDown);
9197
+ return () => {
9198
+ shortcutBars.delete(bar);
9199
+ window.removeEventListener("focusin", onFocusIn);
9200
+ window.removeEventListener("keydown", onKeyDown);
9201
+ };
9202
+ }, [active, card, toBar, toList]);
9203
+ const [keyboardIn, setKeyboardIn] = React37.useState(false);
9204
+ React37.useEffect(() => {
9205
+ if (!active || !card) return;
9206
+ let timer = 0;
9207
+ let holder = null;
9208
+ let holderGiveUp = 0;
9209
+ let pressed = false;
9210
+ const read = () => {
9211
+ timer = 0;
9212
+ if (pressed) return;
9213
+ const focused = document.activeElement;
9214
+ if (menuOpenRef.current) return;
9215
+ if (holder) {
9216
+ if (focused && focused !== document.body && holder.contains(focused)) {
9217
+ window.clearTimeout(holderGiveUp);
9218
+ holderGiveUp = 0;
9219
+ return;
9220
+ }
9221
+ if (!focused || focused === document.body) {
9222
+ if (!holderGiveUp) {
9223
+ holderGiveUp = window.setTimeout(() => {
9224
+ holder = null;
9225
+ schedule();
9226
+ }, 1e3);
9227
+ }
9228
+ return;
9229
+ }
9230
+ holder = null;
9231
+ }
9232
+ window.clearTimeout(holderGiveUp);
9233
+ holderGiveUp = 0;
9234
+ setKeyboardIn(focused instanceof Element && card.contains(focused) && (focused.matches('[data-slot="bulk-action-bar-move"]') || isFocusVisible(focused)));
9235
+ };
9236
+ const schedule = () => {
9237
+ if (!timer) timer = window.setTimeout(read, 0);
9238
+ };
9239
+ const onFocusIn = (event) => {
9240
+ const target = event.target instanceof Element ? event.target : null;
9241
+ const content = target?.closest('[role="menu"],[data-slot="action-menu-sheet"]');
9242
+ const id = moreRef.current?.getAttribute("aria-controls");
9243
+ const dialog = target?.closest(MODAL_SELECTOR);
9244
+ if (content && menuOpenRef.current && (!id || content.id === id || content.matches('[data-slot="action-menu-sheet"]'))) holder = content;
9245
+ else if (dialog && !card.contains(dialog) && !dialog.contains(card)) holder = dialog;
9246
+ schedule();
9247
+ };
9248
+ const onPointerDown = () => {
9249
+ pressed = true;
9250
+ };
9251
+ const onPointerUp = () => {
9252
+ pressed = false;
9253
+ schedule();
9254
+ };
9255
+ const onVisibility = () => {
9256
+ if (document.visibilityState === "hidden") onPointerUp();
9257
+ };
9258
+ read();
9259
+ window.addEventListener("focusout", schedule, true);
9260
+ window.addEventListener("focusin", onFocusIn, true);
9261
+ window.addEventListener("pointerdown", onPointerDown, true);
9262
+ for (const type of ["pointerup", "pointercancel", "keydown"]) window.addEventListener(type, onPointerUp, true);
9263
+ window.addEventListener("blur", onPointerUp);
9264
+ document.addEventListener("visibilitychange", onVisibility);
9265
+ return () => {
9266
+ window.clearTimeout(timer);
9267
+ window.clearTimeout(holderGiveUp);
9268
+ window.removeEventListener("focusout", schedule, true);
9269
+ window.removeEventListener("focusin", onFocusIn, true);
9270
+ window.removeEventListener("pointerdown", onPointerDown, true);
9271
+ for (const type of ["pointerup", "pointercancel", "keydown"]) window.removeEventListener(type, onPointerUp, true);
9272
+ window.removeEventListener("blur", onPointerUp);
9273
+ document.removeEventListener("visibilitychange", onVisibility);
9274
+ };
9275
+ }, [active, card]);
9276
+ React37.useEffect(() => {
9277
+ if (!card) return;
9278
+ const onFocusIn = (event) => {
9279
+ const target = event.target instanceof HTMLElement ? event.target : null;
9280
+ focusedActionRef.current = target?.matches('[data-slot="bulk-action-bar-action"]') ? target : null;
9281
+ };
9282
+ const onFocusOut = (event) => {
9283
+ const folding = event.relatedTarget === null && event.target instanceof Element && event.target.hasAttribute("data-folded");
9284
+ if (!folding) focusedActionRef.current = null;
9285
+ };
9286
+ card.addEventListener("focusin", onFocusIn);
9287
+ card.addEventListener("focusout", onFocusOut);
9288
+ return () => {
9289
+ card.removeEventListener("focusin", onFocusIn);
9290
+ card.removeEventListener("focusout", onFocusOut);
9291
+ };
9292
+ }, [card]);
9293
+ const handleCard = React37.useCallback((node) => {
9294
+ const previous = cardRef.current;
9295
+ cardRef.current = node;
9296
+ setCard(node);
9297
+ if (node || !previous || !activeRef.current || !previous.contains(document.activeElement)) return;
9298
+ const scope = scopeOf(previous, scopePropRef.current);
9299
+ const mark = markRef.current;
9300
+ queueMicrotask(() => {
9301
+ const now = document.activeElement;
9302
+ if (now && now !== document.body && now.isConnected) return;
9303
+ if (scope?.isConnected) focusTarget(returnTarget(scope, mark));
9304
+ });
9305
+ }, []);
9306
+ const handleMore = React37.useCallback((node) => {
9307
+ const focused = document.activeElement;
9308
+ if (!node && moreRef.current && focused === moreRef.current) moreLostFocusRef.current = true;
9309
+ const menu = !node && menuOpenRef.current ? focused?.closest('[role="menu"],[data-slot="action-menu-sheet"]') : null;
9310
+ if (menu) {
9311
+ const items = Array.from(menu.querySelectorAll('[role="menuitem"],[data-slot="action-menu-item"]'));
9312
+ foldedFocusRef.current = menuKeysRef.current[items.indexOf(focused)] ?? null;
9313
+ moreLostFocusRef.current = true;
9314
+ }
9315
+ moreRef.current = node;
9316
+ }, []);
9317
+ const actionCount = actions.length;
9318
+ useIsomorphicLayoutEffect2(() => {
9319
+ if (!row) return;
9320
+ const buttons = Array.from(row.querySelectorAll('[data-slot="bulk-action-bar-action"]'));
9321
+ const focused = document.activeElement;
9322
+ const lost = focusedActionRef.current;
9323
+ const index = lost ? buttons.findIndex((button) => button === lost) : -1;
9324
+ const blurred = !focused || focused === document.body || focused === lost;
9325
+ if (index >= 0 && buttons[index].hasAttribute("data-folded") && blurred && moreRef.current) {
9326
+ focusedActionRef.current = null;
9327
+ foldedFocusRef.current = actions[index]?.key ?? null;
9328
+ moreRef.current.focus();
9329
+ } else if (moreLostFocusRef.current) {
9330
+ moreLostFocusRef.current = false;
9331
+ if (!focused || focused === document.body) {
9332
+ const shown = (button) => !button.disabled && !button.hasAttribute("data-folded");
9333
+ const back = buttons.find((button, i) => actions[i]?.key === foldedFocusRef.current && shown(button)) ?? buttons.find(shown);
9334
+ back?.focus();
9335
+ }
9336
+ foldedFocusRef.current = null;
9337
+ }
9338
+ if (!moreRef.current) setMenuOpen(false);
9339
+ const next = measureFold(row, actionCount);
9340
+ setFold((current) => sameFold(current, next) ? current : next);
9341
+ });
9342
+ React37.useEffect(() => {
9343
+ if (!row || typeof ResizeObserver === "undefined") return;
9344
+ const update = () => {
9345
+ const next = measureFold(row, actionCount);
9346
+ setFold((current) => sameFold(current, next) ? current : next);
9347
+ };
9348
+ const observer = new ResizeObserver(update);
9349
+ observer.observe(row);
9350
+ for (const node of row.querySelectorAll(
9351
+ '[data-slot="bulk-action-bar-action"],[data-slot="bulk-action-bar-move-label"],[data-slot="bulk-action-bar-keys"]'
9352
+ )) {
9353
+ observer.observe(node);
9354
+ }
9355
+ const texts = new MutationObserver(update);
9356
+ texts.observe(row, { characterData: true, childList: true, subtree: true });
9357
+ return () => {
9358
+ observer.disconnect();
9359
+ texts.disconnect();
9360
+ };
9361
+ }, [row, actionCount, active]);
8873
9362
  if (count === 0 && idleContent !== void 0) {
8874
9363
  return /* @__PURE__ */ jsx39(
8875
9364
  "div",
@@ -8881,6 +9370,7 @@ function BulkActionBar({
8881
9370
  className,
8882
9371
  style: { ...idleLineStyle, ...style },
8883
9372
  ...props,
9373
+ "aria-label": ariaLabelProp,
8884
9374
  children: idleContent
8885
9375
  }
8886
9376
  );
@@ -8929,11 +9419,27 @@ function BulkActionBar({
8929
9419
  children: summary
8930
9420
  }
8931
9421
  ) : null;
8932
- return /* @__PURE__ */ jsxs35(
8933
- "div",
9422
+ const showMove = active;
9423
+ const folded = Math.min(fold?.folded ?? 0, Math.max(0, actions.length - 1));
9424
+ const shownCount = actions.length - folded;
9425
+ const menuItems = actions.slice(shownCount).map((action, i) => ({
9426
+ id: action.key,
9427
+ // The menu takes text (also its typeahead text): a node label goes in as its rendered text.
9428
+ label: typeof action.label === "string" ? action.label : fold?.texts[shownCount + i] || action.key,
9429
+ icon: action.icon,
9430
+ destructive: action.variant === "destructive",
9431
+ disabled: action.disabled,
9432
+ // `title` of an action that cannot run is its reason, under the label; of one that can, the
9433
+ // dropdown item's tooltip and the menu sheet's line under the label.
9434
+ disabledReason: action.disabled ? action.title : void 0,
9435
+ description: action.disabled ? void 0 : action.title,
9436
+ title: action.disabled ? void 0 : action.title,
9437
+ onSelect: action.onClick
9438
+ }));
9439
+ return /* @__PURE__ */ jsx39(
9440
+ "section",
8934
9441
  {
8935
- role: "toolbar",
8936
- "aria-label": "\uC120\uD0DD \uD56D\uBAA9 \uC77C\uAD04 \uC791\uC5C5",
9442
+ "aria-label": ariaLabel,
8937
9443
  "data-slot": "bulk-action-bar",
8938
9444
  className: cn(
8939
9445
  // Subtle entrance when the bar appears (count>0). CSS animation runs once
@@ -8941,51 +9447,90 @@ function BulkActionBar({
8941
9447
  "animate-[olun-bulk-action-bar-in_var(--dur-fast)_var(--ease-out)_both] motion-reduce:animate-none",
8942
9448
  className
8943
9449
  ),
8944
- ref: setCard,
9450
+ ref: handleCard,
8945
9451
  style: { ...floatingStyle, ...style },
8946
9452
  ...props,
8947
- children: [
8948
- /* @__PURE__ */ jsxs35(
8949
- "div",
8950
- {
8951
- role: "status",
8952
- "data-slot": "bulk-action-bar-state",
8953
- style: {
8954
- display: "flex",
8955
- minWidth: 0,
8956
- flexDirection: "column",
8957
- rowGap: "var(--space-2)"
8958
- },
8959
- children: [
8960
- countLabel,
8961
- summarySlot
8962
- ]
8963
- }
8964
- ),
8965
- actions.length > 0 ? /* @__PURE__ */ jsx39(
8966
- "div",
8967
- {
8968
- "data-slot": "bulk-action-bar-actions",
8969
- style: {
8970
- display: "flex",
8971
- flexWrap: "wrap",
8972
- justifyContent: "flex-end",
8973
- gap: "var(--space-2)",
8974
- marginTop: "var(--space-3)"
8975
- },
8976
- children: actions.map((action) => /* @__PURE__ */ jsx39(CardActionButton, { action }, action.key))
8977
- }
8978
- ) : null,
8979
- /* @__PURE__ */ jsx39(
8980
- IconButton,
8981
- {
8982
- icon: X4,
8983
- "aria-label": "\uC120\uD0DD \uD574\uC81C",
8984
- onClick: onClear,
8985
- style: { position: "absolute", top: "var(--space-2)", right: "var(--space-2)" }
8986
- }
8987
- )
8988
- ]
9453
+ children: /* @__PURE__ */ jsxs35(
9454
+ "div",
9455
+ {
9456
+ role: "toolbar",
9457
+ "aria-label": ariaLabel,
9458
+ "data-slot": "bulk-action-bar-toolbar",
9459
+ style: { display: "flex", minWidth: 0, flexDirection: "column" },
9460
+ children: [
9461
+ /* @__PURE__ */ jsxs35(
9462
+ "div",
9463
+ {
9464
+ role: "status",
9465
+ "data-slot": "bulk-action-bar-state",
9466
+ style: {
9467
+ display: "flex",
9468
+ minWidth: 0,
9469
+ flexDirection: "column",
9470
+ rowGap: "var(--space-2)"
9471
+ },
9472
+ children: [
9473
+ countLabel,
9474
+ summarySlot
9475
+ ]
9476
+ }
9477
+ ),
9478
+ actions.length > 0 || showMove ? (
9479
+ // One line: move button at the left, actions at the right, then ⋯ for folded ones.
9480
+ /* @__PURE__ */ jsxs35(
9481
+ "div",
9482
+ {
9483
+ ref: setRow,
9484
+ "data-slot": "bulk-action-bar-actions",
9485
+ style: {
9486
+ position: "relative",
9487
+ display: "flex",
9488
+ minWidth: 0,
9489
+ flexWrap: fold ? "nowrap" : "wrap",
9490
+ alignItems: "center",
9491
+ justifyContent: "flex-end",
9492
+ gap: "var(--space-2)",
9493
+ marginTop: "var(--space-3)"
9494
+ },
9495
+ children: [
9496
+ showMove ? /* @__PURE__ */ jsx39(MoveButton, { mac, shown: keyboardIn, onMove: toList }) : null,
9497
+ actions.map((action, index) => /* @__PURE__ */ jsx39(CardActionButton, { action, folded: index >= shownCount }, action.key)),
9498
+ folded > 0 ? /* @__PURE__ */ jsx39(
9499
+ ActionMenu,
9500
+ {
9501
+ open: menuOpen,
9502
+ onOpenChange: setMenuOpen,
9503
+ items: menuItems,
9504
+ trigger: /* @__PURE__ */ jsx39(
9505
+ IconButton,
9506
+ {
9507
+ ref: handleMore,
9508
+ icon: Ellipsis,
9509
+ "aria-label": MORE_LABEL,
9510
+ appearance: "outline",
9511
+ size: "sm",
9512
+ className: "shrink-0"
9513
+ }
9514
+ )
9515
+ }
9516
+ ) : null
9517
+ ]
9518
+ }
9519
+ )
9520
+ ) : null,
9521
+ /* @__PURE__ */ jsx39(
9522
+ IconButton,
9523
+ {
9524
+ ref: clearRef,
9525
+ icon: X4,
9526
+ "aria-label": "\uC120\uD0DD \uD574\uC81C",
9527
+ onClick: onClear,
9528
+ style: { position: "absolute", top: "var(--space-2)", right: "var(--space-2)" }
9529
+ }
9530
+ )
9531
+ ]
9532
+ }
9533
+ )
8989
9534
  }
8990
9535
  );
8991
9536
  }
@@ -9234,7 +9779,7 @@ function ActionSheet({
9234
9779
  }
9235
9780
 
9236
9781
  // src/components/ui/badge.tsx
9237
- import * as React37 from "react";
9782
+ import * as React38 from "react";
9238
9783
  import { jsx as jsx45 } from "react/jsx-runtime";
9239
9784
  var TONE = {
9240
9785
  neutral: "bg-[var(--fill-on-bg,var(--semantic-neutral-bg))] text-[var(--semantic-neutral-fg)]",
@@ -9244,7 +9789,7 @@ var TONE = {
9244
9789
  error: "bg-[var(--semantic-error-bg)] text-[var(--semantic-error-fg)]",
9245
9790
  brand: "bg-[var(--accent-bg-strong)] text-[var(--accent)]"
9246
9791
  };
9247
- var Badge = React37.forwardRef(
9792
+ var Badge = React38.forwardRef(
9248
9793
  ({ tone = "neutral", className, children, ...props }, ref) => /* @__PURE__ */ jsx45(
9249
9794
  "span",
9250
9795
  {
@@ -9265,7 +9810,7 @@ var Badge = React37.forwardRef(
9265
9810
  Badge.displayName = "Badge";
9266
9811
 
9267
9812
  // src/components/ui/two-tier-badge.tsx
9268
- import * as React38 from "react";
9813
+ import * as React39 from "react";
9269
9814
  import { jsx as jsx46, jsxs as jsxs37 } from "react/jsx-runtime";
9270
9815
  var FG = {
9271
9816
  neutral: "var(--text-secondary)",
@@ -9288,7 +9833,7 @@ var SEGMENT = {
9288
9833
  md: "gap-[7px] py-[var(--space-1)] px-[var(--space-3)] text-[14px]"
9289
9834
  };
9290
9835
  var DOT = { xs: 5, sm: 6, md: 7 };
9291
- var TwoTierBadge = React38.forwardRef(
9836
+ var TwoTierBadge = React39.forwardRef(
9292
9837
  ({ primary, secondary, tone = "neutral", emphasis = "subtle", size = "sm", showDot = false, className, style, ...props }, ref) => {
9293
9838
  const strong = emphasis === "strong";
9294
9839
  const fg = FG[tone];
@@ -9358,7 +9903,7 @@ var TwoTierBadge = React38.forwardRef(
9358
9903
  TwoTierBadge.displayName = "TwoTierBadge";
9359
9904
 
9360
9905
  // src/components/ui/status-badge.tsx
9361
- import * as React39 from "react";
9906
+ import * as React40 from "react";
9362
9907
  import { jsx as jsx47 } from "react/jsx-runtime";
9363
9908
  var ROLE = {
9364
9909
  error: "error",
@@ -9369,13 +9914,13 @@ var ROLE = {
9369
9914
  success: "success",
9370
9915
  archived: "neutral"
9371
9916
  };
9372
- var StatusBadge = React39.forwardRef(
9917
+ var StatusBadge = React40.forwardRef(
9373
9918
  ({ status = "active", emphasis: _emphasis, size: _size, showDot: _showDot, pulse: _pulse, ...props }, ref) => /* @__PURE__ */ jsx47(Badge, { ref, tone: ROLE[status], ...props })
9374
9919
  );
9375
9920
  StatusBadge.displayName = "StatusBadge";
9376
9921
 
9377
9922
  // src/components/ui/status-dot.tsx
9378
- import * as React40 from "react";
9923
+ import * as React41 from "react";
9379
9924
  import { jsx as jsx48, jsxs as jsxs38 } from "react/jsx-runtime";
9380
9925
  var DOT2 = {
9381
9926
  neutral: "bg-[var(--semantic-neutral-fg)]",
@@ -9384,7 +9929,7 @@ var DOT2 = {
9384
9929
  warning: "bg-[var(--semantic-warning-fg)]",
9385
9930
  error: "bg-[var(--semantic-error-fg)]"
9386
9931
  };
9387
- var StatusDot = React40.forwardRef(
9932
+ var StatusDot = React41.forwardRef(
9388
9933
  ({ tone, label, pulse = false, className, ...props }, ref) => /* @__PURE__ */ jsxs38(
9389
9934
  "span",
9390
9935
  {
@@ -9418,7 +9963,7 @@ var StatusDot = React40.forwardRef(
9418
9963
  StatusDot.displayName = "StatusDot";
9419
9964
 
9420
9965
  // src/components/ui/notification-badge.tsx
9421
- import * as React41 from "react";
9966
+ import * as React42 from "react";
9422
9967
  import { cva as cva14 } from "class-variance-authority";
9423
9968
  import { jsx as jsx49, jsxs as jsxs39 } from "react/jsx-runtime";
9424
9969
  var notificationBadgeVariants = cva14(
@@ -9451,7 +9996,7 @@ function formatNotificationCount(count, max) {
9451
9996
  }
9452
9997
  return String(count);
9453
9998
  }
9454
- var NotificationBadge = React41.forwardRef(
9999
+ var NotificationBadge = React42.forwardRef(
9455
10000
  ({
9456
10001
  className,
9457
10002
  count,
@@ -9486,7 +10031,7 @@ var NotificationBadge = React41.forwardRef(
9486
10031
  NotificationBadge.displayName = "NotificationBadge";
9487
10032
 
9488
10033
  // src/components/ui/empty-state.tsx
9489
- import * as React42 from "react";
10034
+ import * as React43 from "react";
9490
10035
  import { cva as cva15 } from "class-variance-authority";
9491
10036
  import { jsx as jsx50, jsxs as jsxs40 } from "react/jsx-runtime";
9492
10037
  var emptyStateBaseVariants = cva15(
@@ -9514,7 +10059,7 @@ var emptyStateBaseVariants = cva15(
9514
10059
  }
9515
10060
  );
9516
10061
  var PAGE_FILL_QUERY = "(min-width: 768px)";
9517
- var useIsomorphicLayoutEffect3 = typeof window === "undefined" ? React42.useEffect : React42.useLayoutEffect;
10062
+ var useIsomorphicLayoutEffect3 = typeof window === "undefined" ? React43.useEffect : React43.useLayoutEffect;
9518
10063
  function findScrollParent(node) {
9519
10064
  for (let el = node.parentElement; el && el !== document.body && el !== document.documentElement; el = el.parentElement) {
9520
10065
  const { overflowY } = getComputedStyle(el);
@@ -9626,7 +10171,7 @@ var iconSize2 = {
9626
10171
  md: 20,
9627
10172
  lg: 24
9628
10173
  };
9629
- var EmptyState = React42.forwardRef(
10174
+ var EmptyState = React43.forwardRef(
9630
10175
  ({
9631
10176
  className,
9632
10177
  size = "md",
@@ -9642,7 +10187,7 @@ var EmptyState = React42.forwardRef(
9642
10187
  ...props
9643
10188
  }, ref) => {
9644
10189
  const resolvedSize = size ?? "md";
9645
- const pageRef = React42.useRef(null);
10190
+ const pageRef = React43.useRef(null);
9646
10191
  usePageFill(pageRef, layout === "page");
9647
10192
  const box = /* @__PURE__ */ jsxs40(
9648
10193
  "div",
@@ -9708,7 +10253,7 @@ var EmptyState = React42.forwardRef(
9708
10253
  EmptyState.displayName = "EmptyState";
9709
10254
 
9710
10255
  // src/components/ui/error-state.tsx
9711
- import * as React43 from "react";
10256
+ import * as React44 from "react";
9712
10257
  import { AlertTriangle } from "lucide-react";
9713
10258
  import { cva as cva16 } from "class-variance-authority";
9714
10259
  import { jsx as jsx51, jsxs as jsxs41 } from "react/jsx-runtime";
@@ -9733,7 +10278,7 @@ var errorStateVariants = cva16(
9733
10278
  }
9734
10279
  }
9735
10280
  );
9736
- var ErrorState = React43.forwardRef(
10281
+ var ErrorState = React44.forwardRef(
9737
10282
  ({
9738
10283
  className,
9739
10284
  size = "md",
@@ -9771,14 +10316,14 @@ var ErrorState = React43.forwardRef(
9771
10316
  children: title
9772
10317
  }
9773
10318
  ),
9774
- /* @__PURE__ */ jsx51(
10319
+ message || message === 0 ? /* @__PURE__ */ jsx51(
9775
10320
  "p",
9776
10321
  {
9777
10322
  "data-slot": "error-state-message",
9778
10323
  className: "break-keep text-sm leading-normal text-text-tertiary",
9779
10324
  children: message
9780
10325
  }
9781
- ),
10326
+ ) : null,
9782
10327
  errorCode ? /* @__PURE__ */ jsx51(
9783
10328
  "p",
9784
10329
  {
@@ -9796,7 +10341,7 @@ var ErrorState = React43.forwardRef(
9796
10341
  ErrorState.displayName = "ErrorState";
9797
10342
 
9798
10343
  // src/components/ui/skeleton.tsx
9799
- import * as React44 from "react";
10344
+ import * as React45 from "react";
9800
10345
  import { cva as cva17 } from "class-variance-authority";
9801
10346
  import { jsx as jsx52 } from "react/jsx-runtime";
9802
10347
  var skeletonVariants = cva17(
@@ -9842,7 +10387,7 @@ var spinnerVariants = cva17(
9842
10387
  }
9843
10388
  }
9844
10389
  );
9845
- var Skeleton = React44.forwardRef(
10390
+ var Skeleton = React45.forwardRef(
9846
10391
  ({ className, shape, style, ...props }, ref) => /* @__PURE__ */ jsx52(
9847
10392
  "div",
9848
10393
  {
@@ -9856,7 +10401,7 @@ var Skeleton = React44.forwardRef(
9856
10401
  );
9857
10402
  Skeleton.displayName = "Skeleton";
9858
10403
  var defaultTextWidths = ["92%", "84%", "68%", "76%"];
9859
- var SkeletonText = React44.forwardRef(
10404
+ var SkeletonText = React45.forwardRef(
9860
10405
  ({ className, lines = 3, widths = defaultTextWidths, ...props }, ref) => /* @__PURE__ */ jsx52(
9861
10406
  "div",
9862
10407
  {
@@ -9876,7 +10421,7 @@ var SkeletonText = React44.forwardRef(
9876
10421
  )
9877
10422
  );
9878
10423
  SkeletonText.displayName = "SkeletonText";
9879
- var SkeletonRow = React44.forwardRef(
10424
+ var SkeletonRow = React45.forwardRef(
9880
10425
  ({
9881
10426
  className,
9882
10427
  columns,
@@ -9933,7 +10478,7 @@ var SkeletonRow = React44.forwardRef(
9933
10478
  }
9934
10479
  );
9935
10480
  SkeletonRow.displayName = "SkeletonRow";
9936
- var Spinner = React44.forwardRef(
10481
+ var Spinner = React45.forwardRef(
9937
10482
  ({ className, size, label = "\uB85C\uB529 \uC911", ...props }, ref) => /* @__PURE__ */ jsx52(
9938
10483
  "span",
9939
10484
  {
@@ -9949,7 +10494,7 @@ var Spinner = React44.forwardRef(
9949
10494
  Spinner.displayName = "Spinner";
9950
10495
 
9951
10496
  // src/components/ui/pagination.tsx
9952
- import * as React45 from "react";
10497
+ import * as React46 from "react";
9953
10498
  import { ChevronsLeft, ChevronLeft, ChevronRight as ChevronRight4, ChevronsRight } from "lucide-react";
9954
10499
  import { cva as cva18 } from "class-variance-authority";
9955
10500
 
@@ -10090,7 +10635,7 @@ function NavigationButton({
10090
10635
  }
10091
10636
  );
10092
10637
  }
10093
- var Pagination = React45.forwardRef(
10638
+ var Pagination = React46.forwardRef(
10094
10639
  ({
10095
10640
  className,
10096
10641
  size = "standard",
@@ -10406,7 +10951,7 @@ function ModeToggle({
10406
10951
  }
10407
10952
 
10408
10953
  // src/components/ui/action-footer.tsx
10409
- import * as React46 from "react";
10954
+ import * as React47 from "react";
10410
10955
  import { cva as cva20 } from "class-variance-authority";
10411
10956
  import { jsx as jsx57, jsxs as jsxs46 } from "react/jsx-runtime";
10412
10957
  var actionFooterVariants = cva20(
@@ -10507,7 +11052,7 @@ function renderAction(action, className) {
10507
11052
  }
10508
11053
  return /* @__PURE__ */ jsx57(Button, { ...common, ...style, size: "lg", loading: action.loading, children: action.label }, key);
10509
11054
  }
10510
- var ActionFooter = React46.forwardRef(
11055
+ var ActionFooter = React47.forwardRef(
10511
11056
  ({
10512
11057
  className,
10513
11058
  status,
@@ -10577,7 +11122,7 @@ var ActionFooter = React46.forwardRef(
10577
11122
  ActionFooter.displayName = "ActionFooter";
10578
11123
 
10579
11124
  // src/components/ui/toast.tsx
10580
- import * as React47 from "react";
11125
+ import * as React48 from "react";
10581
11126
  import { cva as cva21 } from "class-variance-authority";
10582
11127
  import { jsx as jsx58, jsxs as jsxs47 } from "react/jsx-runtime";
10583
11128
  var DOT3 = {
@@ -10698,7 +11243,7 @@ var toast = {
10698
11243
  }
10699
11244
  };
10700
11245
  var Toast = toast;
10701
- var ToastRoot = React47.forwardRef(
11246
+ var ToastRoot = React48.forwardRef(
10702
11247
  ({
10703
11248
  className,
10704
11249
  id,
@@ -10715,10 +11260,10 @@ var ToastRoot = React47.forwardRef(
10715
11260
  ...props
10716
11261
  }, ref) => {
10717
11262
  const durationMs = getToastDuration({ message, variant, duration });
10718
- const onCloseRef = React47.useRef(onClose);
11263
+ const onCloseRef = React48.useRef(onClose);
10719
11264
  onCloseRef.current = onClose;
10720
- const timerRef = React47.useRef(null);
10721
- React47.useEffect(() => {
11265
+ const timerRef = React48.useRef(null);
11266
+ React48.useEffect(() => {
10722
11267
  if (!onCloseRef.current) return void 0;
10723
11268
  const timer = createToastTimer(durationMs, () => onCloseRef.current?.());
10724
11269
  timerRef.current = timer;
@@ -10816,7 +11361,7 @@ var ToastRoot = React47.forwardRef(
10816
11361
  }
10817
11362
  );
10818
11363
  ToastRoot.displayName = "ToastRoot";
10819
- var ToastViewport = React47.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx58(
11364
+ var ToastViewport = React48.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx58(
10820
11365
  "ol",
10821
11366
  {
10822
11367
  ref,
@@ -10827,8 +11372,8 @@ var ToastViewport = React47.forwardRef(({ className, ...props }, ref) => /* @__P
10827
11372
  ));
10828
11373
  ToastViewport.displayName = "ToastViewport";
10829
11374
  function ToastProvider({ children, maxToasts = 3, className, ...props }) {
10830
- const [items, setItems] = React47.useState([]);
10831
- React47.useEffect(
11375
+ const [items, setItems] = React48.useState([]);
11376
+ React48.useEffect(
10832
11377
  () => toast.subscribe((nextItems) => {
10833
11378
  setItems(limitToasts(nextItems, maxToasts));
10834
11379
  }),
@@ -10841,7 +11386,7 @@ function ToastProvider({ children, maxToasts = 3, className, ...props }) {
10841
11386
  }
10842
11387
 
10843
11388
  // src/components/ui/otp-field.tsx
10844
- import * as React48 from "react";
11389
+ import * as React49 from "react";
10845
11390
  import { cva as cva22 } from "class-variance-authority";
10846
11391
  import { AlertCircle as AlertCircle4 } from "lucide-react";
10847
11392
  import { Fragment as Fragment21, jsx as jsx59, jsxs as jsxs48 } from "react/jsx-runtime";
@@ -10971,7 +11516,7 @@ function fillDigitsFromIndex(slots, index, inserted, length) {
10971
11516
  focusIndex: Math.min(cursor, length - 1)
10972
11517
  };
10973
11518
  }
10974
- var OTPField = React48.forwardRef(
11519
+ var OTPField = React49.forwardRef(
10975
11520
  ({
10976
11521
  className,
10977
11522
  defaultValue,
@@ -10995,7 +11540,7 @@ var OTPField = React48.forwardRef(
10995
11540
  ...props
10996
11541
  }, ref) => {
10997
11542
  const formField = useFormFieldControl();
10998
- const generatedId = React48.useId();
11543
+ const generatedId = React49.useId();
10999
11544
  const fieldId = id ?? generatedId;
11000
11545
  const slotId = formField ? generatedId : fieldId;
11001
11546
  const labelId = `${slotId}-label`;
@@ -11003,22 +11548,22 @@ var OTPField = React48.forwardRef(
11003
11548
  const errorId = errorText ? `${slotId}-error` : void 0;
11004
11549
  const resolvedState = invalid || errorText ? "error" : "default";
11005
11550
  const isControlled = value !== void 0;
11006
- const [uncontrolledSlots, setUncontrolledSlots] = React48.useState(
11551
+ const [uncontrolledSlots, setUncontrolledSlots] = React49.useState(
11007
11552
  () => toDigitsArray(onlyDigits(defaultValue, length), length)
11008
11553
  );
11009
- const resolvedSlots = React48.useMemo(
11554
+ const resolvedSlots = React49.useMemo(
11010
11555
  () => isControlled ? toDigitsArray(onlyDigits(value, length), length) : uncontrolledSlots,
11011
11556
  [isControlled, length, uncontrolledSlots, value]
11012
11557
  );
11013
11558
  const resolvedValue = joinDigits(resolvedSlots).slice(0, length);
11014
- const cellsRef = React48.useRef([]);
11559
+ const cellsRef = React49.useRef([]);
11015
11560
  const groupDescribedBy = joinIds(
11016
11561
  ariaDescribedBy,
11017
11562
  helperId,
11018
11563
  errorId,
11019
11564
  formField?.describedBy
11020
11565
  );
11021
- const setResolvedValue = React48.useCallback(
11566
+ const setResolvedValue = React49.useCallback(
11022
11567
  (nextSlots, focusIndex) => {
11023
11568
  const normalizedSlots = nextSlots.slice(0, length);
11024
11569
  const normalizedValue = joinDigits(normalizedSlots).slice(0, length);
@@ -11208,7 +11753,7 @@ var OTPField = React48.forwardRef(
11208
11753
  OTPField.displayName = "OTPField";
11209
11754
 
11210
11755
  // src/components/ui/search-field.tsx
11211
- import * as React49 from "react";
11756
+ import * as React50 from "react";
11212
11757
  import { Search, X as X5 } from "lucide-react";
11213
11758
  import { cva as cva23 } from "class-variance-authority";
11214
11759
  import { jsx as jsx60, jsxs as jsxs49 } from "react/jsx-runtime";
@@ -11276,7 +11821,7 @@ var iconSize3 = {
11276
11821
  function hasVisibleValue(value) {
11277
11822
  return typeof value === "string" ? value.length > 0 : value !== void 0;
11278
11823
  }
11279
- var SearchField = React49.forwardRef(
11824
+ var SearchField = React50.forwardRef(
11280
11825
  ({
11281
11826
  className,
11282
11827
  inputMode = "search",
@@ -11293,14 +11838,20 @@ var SearchField = React49.forwardRef(
11293
11838
  "aria-describedby": ariaDescribedBy,
11294
11839
  ...props
11295
11840
  }, ref) => {
11841
+ const {
11842
+ description: _description,
11843
+ message: _message,
11844
+ state: _state,
11845
+ ...inputProps
11846
+ } = props;
11296
11847
  const field = useFormFieldControl();
11297
11848
  const resolvedSize = size ?? "md";
11298
- const inputRef = React49.useRef(null);
11299
- const [hasText, setHasText] = React49.useState(
11849
+ const inputRef = React50.useRef(null);
11850
+ const [hasText, setHasText] = React50.useState(
11300
11851
  () => hasVisibleValue(value ?? defaultValue)
11301
11852
  );
11302
- React49.useImperativeHandle(ref, () => inputRef.current);
11303
- React49.useEffect(() => {
11853
+ React50.useImperativeHandle(ref, () => inputRef.current);
11854
+ React50.useEffect(() => {
11304
11855
  if (value !== void 0) {
11305
11856
  setHasText(hasVisibleValue(value));
11306
11857
  }
@@ -11350,7 +11901,7 @@ var SearchField = React49.forwardRef(
11350
11901
  className: cn(
11351
11902
  searchFieldInputVariants({ size, hasClear: showClear, surface })
11352
11903
  ),
11353
- ...props
11904
+ ...inputProps
11354
11905
  }
11355
11906
  ),
11356
11907
  showClear ? /* @__PURE__ */ jsx60(
@@ -11372,7 +11923,7 @@ var SearchField = React49.forwardRef(
11372
11923
  SearchField.displayName = "SearchField";
11373
11924
 
11374
11925
  // src/components/ui/checkbox-group.tsx
11375
- import * as React50 from "react";
11926
+ import * as React51 from "react";
11376
11927
  import { cva as cva24 } from "class-variance-authority";
11377
11928
  import { jsx as jsx61 } from "react/jsx-runtime";
11378
11929
  var checkboxGroupVariants = cva24("gap-[var(--space-2)]", {
@@ -11400,7 +11951,7 @@ var checkboxGroupVariants = cva24("gap-[var(--space-2)]", {
11400
11951
  function toSelectionSet(value) {
11401
11952
  return new Set(value ?? []);
11402
11953
  }
11403
- var CheckboxGroup = React50.forwardRef(
11954
+ var CheckboxGroup = React51.forwardRef(
11404
11955
  ({
11405
11956
  className,
11406
11957
  children,
@@ -11419,14 +11970,14 @@ var CheckboxGroup = React50.forwardRef(
11419
11970
  }, ref) => {
11420
11971
  const field = useFormFieldControl();
11421
11972
  const isControlled = value != null;
11422
- const [uncontrolledValue, setUncontrolledValue] = React50.useState(
11973
+ const [uncontrolledValue, setUncontrolledValue] = React51.useState(
11423
11974
  () => toSelectionSet(defaultValue)
11424
11975
  );
11425
- const selectedValues = React50.useMemo(
11976
+ const selectedValues = React51.useMemo(
11426
11977
  () => isControlled ? toSelectionSet(value) : uncontrolledValue,
11427
11978
  [isControlled, uncontrolledValue, value]
11428
11979
  );
11429
- const toggleValue = React50.useCallback(
11980
+ const toggleValue = React51.useCallback(
11430
11981
  (itemValue, checked) => {
11431
11982
  const nextValues = new Set(selectedValues);
11432
11983
  if (checked) {
@@ -11442,7 +11993,7 @@ var CheckboxGroup = React50.forwardRef(
11442
11993
  },
11443
11994
  [isControlled, onValueChange, selectedValues]
11444
11995
  );
11445
- const contextValue = React50.useMemo(
11996
+ const contextValue = React51.useMemo(
11446
11997
  () => ({
11447
11998
  appearance,
11448
11999
  density,
@@ -11480,7 +12031,7 @@ var CheckboxGroup = React50.forwardRef(
11480
12031
  CheckboxGroup.displayName = "CheckboxGroup";
11481
12032
 
11482
12033
  // src/components/ui/radio-group.tsx
11483
- import * as React51 from "react";
12034
+ import * as React52 from "react";
11484
12035
  import { cva as cva25 } from "class-variance-authority";
11485
12036
  import { Circle } from "lucide-react";
11486
12037
  import { RadioGroup as RadioGroupPrimitive } from "radix-ui";
@@ -11573,12 +12124,12 @@ var radioControlVariants = cva25(
11573
12124
  }
11574
12125
  }
11575
12126
  );
11576
- var RadioGroupContext = React51.createContext({
12127
+ var RadioGroupContext = React52.createContext({
11577
12128
  appearance: "plain",
11578
12129
  density: "comfortable",
11579
12130
  orientation: "vertical"
11580
12131
  });
11581
- var RadioGroup = React51.forwardRef(
12132
+ var RadioGroup = React52.forwardRef(
11582
12133
  ({
11583
12134
  className,
11584
12135
  children,
@@ -11592,7 +12143,7 @@ var RadioGroup = React51.forwardRef(
11592
12143
  ...props
11593
12144
  }, ref) => {
11594
12145
  const field = useFormFieldControl();
11595
- const contextValue = React51.useMemo(
12146
+ const contextValue = React52.useMemo(
11596
12147
  () => ({ appearance, density, orientation }),
11597
12148
  [appearance, density, orientation]
11598
12149
  );
@@ -11621,9 +12172,9 @@ var RadioGroup = React51.forwardRef(
11621
12172
  }
11622
12173
  );
11623
12174
  RadioGroup.displayName = "RadioGroup";
11624
- var Radio = React51.forwardRef(({ className, children, description, id, ...props }, ref) => {
11625
- const { appearance, density, orientation } = React51.useContext(RadioGroupContext);
11626
- const generatedId = React51.useId();
12175
+ var Radio = React52.forwardRef(({ className, children, description, id, ...props }, ref) => {
12176
+ const { appearance, density, orientation } = React52.useContext(RadioGroupContext);
12177
+ const generatedId = React52.useId();
11627
12178
  const radioId = id ?? generatedId;
11628
12179
  const labelId = `${radioId}-label`;
11629
12180
  const descriptionId = description ? `${radioId}-description` : void 0;
@@ -11796,7 +12347,7 @@ function Progress({
11796
12347
  }
11797
12348
 
11798
12349
  // src/components/ui/tree-view.tsx
11799
- import * as React52 from "react";
12350
+ import * as React53 from "react";
11800
12351
  import { ChevronRight as ChevronRight6 } from "lucide-react";
11801
12352
  import { cva as cva26 } from "class-variance-authority";
11802
12353
  import { jsx as jsx65, jsxs as jsxs52 } from "react/jsx-runtime";
@@ -11830,14 +12381,14 @@ var treeItemRowVariants = cva26(
11830
12381
  function defaultGetChildren(node) {
11831
12382
  return node.children;
11832
12383
  }
11833
- function flattenVisibleNodes(nodes, getChildren, expandedSet, depth = 1, parentId = null, acc = []) {
12384
+ function flattenVisibleNodes(nodes, getChildren, expandedSet, depth2 = 1, parentId = null, acc = []) {
11834
12385
  for (const node of nodes) {
11835
12386
  const children = getChildren(node);
11836
12387
  const hasChildren = Array.isArray(children) && children.length > 0;
11837
12388
  const expanded = hasChildren && expandedSet.has(node.id);
11838
- acc.push({ node, id: node.id, depth, hasChildren, expanded, parentId });
12389
+ acc.push({ node, id: node.id, depth: depth2, hasChildren, expanded, parentId });
11839
12390
  if (expanded && children) {
11840
- flattenVisibleNodes(children, getChildren, expandedSet, depth + 1, node.id, acc);
12391
+ flattenVisibleNodes(children, getChildren, expandedSet, depth2 + 1, node.id, acc);
11841
12392
  }
11842
12393
  }
11843
12394
  return acc;
@@ -11902,27 +12453,27 @@ function TreeView({
11902
12453
  ...rest
11903
12454
  }) {
11904
12455
  const isExpandedControlled = expandedIds !== void 0;
11905
- const [internalExpanded, setInternalExpanded] = React52.useState(
12456
+ const [internalExpanded, setInternalExpanded] = React53.useState(
11906
12457
  () => defaultExpandedIds ?? []
11907
12458
  );
11908
12459
  const expandedList = isExpandedControlled ? expandedIds : internalExpanded;
11909
- const expandedSet = React52.useMemo(() => new Set(expandedList), [expandedList]);
11910
- const items = React52.useMemo(
12460
+ const expandedSet = React53.useMemo(() => new Set(expandedList), [expandedList]);
12461
+ const items = React53.useMemo(
11911
12462
  () => flattenVisibleNodes(nodes, getChildren, expandedSet),
11912
12463
  [nodes, getChildren, expandedSet]
11913
12464
  );
11914
- const [focusedId, setFocusedId] = React52.useState(null);
12465
+ const [focusedId, setFocusedId] = React53.useState(null);
11915
12466
  const visibleIds = items.map((item) => item.id);
11916
12467
  const activeId = focusedId && visibleIds.includes(focusedId) ? focusedId : selectedId && visibleIds.includes(selectedId) ? selectedId : visibleIds[0] ?? null;
11917
- const itemRefs = React52.useRef(/* @__PURE__ */ new Map());
11918
- const commitExpanded = React52.useCallback(
12468
+ const itemRefs = React53.useRef(/* @__PURE__ */ new Map());
12469
+ const commitExpanded = React53.useCallback(
11919
12470
  (next) => {
11920
12471
  if (!isExpandedControlled) setInternalExpanded(next);
11921
12472
  onExpandedChange?.(next);
11922
12473
  },
11923
12474
  [isExpandedControlled, onExpandedChange]
11924
12475
  );
11925
- const setExpanded = React52.useCallback(
12476
+ const setExpanded = React53.useCallback(
11926
12477
  (id, expand) => {
11927
12478
  const has = expandedSet.has(id);
11928
12479
  if (expand && !has) {
@@ -11933,7 +12484,7 @@ function TreeView({
11933
12484
  },
11934
12485
  [commitExpanded, expandedList, expandedSet]
11935
12486
  );
11936
- const focusItem = React52.useCallback((id) => {
12487
+ const focusItem = React53.useCallback((id) => {
11937
12488
  setFocusedId(id);
11938
12489
  itemRefs.current.get(id)?.focus();
11939
12490
  }, []);
@@ -11961,14 +12512,14 @@ function TreeView({
11961
12512
  }
11962
12513
  }
11963
12514
  };
11964
- function renderLevel(levelNodes, depth) {
12515
+ function renderLevel(levelNodes, depth2) {
11965
12516
  return levelNodes.map((node) => {
11966
12517
  const children = getChildren(node);
11967
12518
  const hasChildren = Array.isArray(children) && children.length > 0;
11968
12519
  const expanded = hasChildren && expandedSet.has(node.id);
11969
12520
  const selected = node.id === selectedId;
11970
12521
  const isActive = node.id === activeId;
11971
- const itemState = { expanded, selected, depth, hasChildren };
12522
+ const itemState = { expanded, selected, depth: depth2, hasChildren };
11972
12523
  return /* @__PURE__ */ jsxs52(
11973
12524
  "li",
11974
12525
  {
@@ -11979,7 +12530,7 @@ function TreeView({
11979
12530
  role: "treeitem",
11980
12531
  "data-slot": "treeitem",
11981
12532
  "data-id": node.id,
11982
- "aria-level": depth,
12533
+ "aria-level": depth2,
11983
12534
  "aria-expanded": hasChildren ? expanded : void 0,
11984
12535
  "aria-selected": selected ? true : void 0,
11985
12536
  "aria-current": selected && selectionAriaCurrent ? selectionAriaCurrent : void 0,
@@ -11999,7 +12550,7 @@ function TreeView({
11999
12550
  {
12000
12551
  "data-slot": "treeitem-row",
12001
12552
  style: {
12002
- paddingInlineStart: `calc(var(--space-2) + var(--space-4) * ${depth - 1})`
12553
+ paddingInlineStart: `calc(var(--space-2) + var(--space-4) * ${depth2 - 1})`
12003
12554
  },
12004
12555
  className: treeItemRowVariants({ selected }),
12005
12556
  children: [
@@ -12038,7 +12589,7 @@ function TreeView({
12038
12589
  ]
12039
12590
  }
12040
12591
  ),
12041
- 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
12592
+ hasChildren && expanded && children ? /* @__PURE__ */ jsx65("ul", { role: "group", "data-slot": "tree-group", className: "m-0 list-none p-0", children: renderLevel(children, depth2 + 1) }) : null
12042
12593
  ]
12043
12594
  },
12044
12595
  node.id