@olundot/ui 0.20.0-next.8 → 0.20.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
@@ -456,9 +456,30 @@ var CopyButton = React2.forwardRef(
456
456
  CopyButton.displayName = "CopyButton";
457
457
 
458
458
  // src/components/ui/input.tsx
459
- import * as React3 from "react";
459
+ import * as React4 from "react";
460
460
  import { cva as cva2 } from "class-variance-authority";
461
461
  import { AlertCircle, CheckCircle2 } from "lucide-react";
462
+
463
+ // src/components/ui/form-field-context.ts
464
+ import * as React3 from "react";
465
+ var FormFieldControlContext = React3.createContext(null);
466
+ function useFormFieldControl() {
467
+ return React3.useContext(FormFieldControlContext);
468
+ }
469
+ function joinIds(...lists) {
470
+ const ids = /* @__PURE__ */ new Set();
471
+ for (const list of lists) {
472
+ for (const id of list?.split(/\s+/) ?? []) {
473
+ if (id) ids.add(id);
474
+ }
475
+ }
476
+ return ids.size > 0 ? [...ids].join(" ") : void 0;
477
+ }
478
+ function FormFieldBoundary({ children }) {
479
+ return React3.createElement(FormFieldControlContext.Provider, { value: null }, children);
480
+ }
481
+
482
+ // src/components/ui/input.tsx
462
483
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
463
484
  var inputVariants = cva2(
464
485
  [
@@ -525,7 +546,7 @@ function mapInputSizeLegacy(inputSize) {
525
546
  return "lg";
526
547
  }
527
548
  }
528
- var Input = React3.forwardRef(
549
+ var Input = React4.forwardRef(
529
550
  ({
530
551
  className,
531
552
  type,
@@ -548,21 +569,29 @@ var Input = React3.forwardRef(
548
569
  }, ref) => {
549
570
  const resolvedSize = size ?? mapInputSizeLegacy(inputSize) ?? "md";
550
571
  const resolvedFullWidth = fullWidth ?? true;
551
- const generatedId = React3.useId();
552
- const inputId = id ?? generatedId;
572
+ const field = useFormFieldControl();
573
+ const generatedId = React4.useId();
574
+ const inputId = field ? generatedId : id ?? generatedId;
575
+ const controlId = id ?? field?.controlId;
553
576
  const resolvedState = invalid || state === "error" ? "error" : state;
554
577
  const showDescription = resolvedState === "default" && Boolean(description);
555
578
  const showMessage = Boolean(message) && !showDescription;
556
579
  const messageId = showMessage ? `${inputId}-message` : void 0;
557
580
  const descriptionId = showDescription ? `${inputId}-description` : void 0;
558
- const describedBy = [ariaDescribedBy, descriptionId, messageId].filter(Boolean).join(" ") || void 0;
581
+ const describedBy = joinIds(
582
+ ariaDescribedBy,
583
+ descriptionId,
584
+ messageId,
585
+ field?.describedBy
586
+ );
559
587
  const resolvedInvalid = resolvedState === "error" ? true : ariaInvalid ?? void 0;
588
+ const elementId = controlId ?? (label || message || description ? inputId : void 0);
560
589
  const control = /* @__PURE__ */ jsx3(
561
590
  "input",
562
591
  {
563
592
  type,
564
593
  ref,
565
- id: label || message || description ? inputId : id,
594
+ id: elementId,
566
595
  required,
567
596
  disabled,
568
597
  readOnly,
@@ -589,7 +618,7 @@ var Input = React3.forwardRef(
589
618
  {
590
619
  "data-slot": "input-label",
591
620
  "data-required": required ? "true" : void 0,
592
- htmlFor: inputId,
621
+ htmlFor: elementId,
593
622
  className: "pl-1 pb-1 text-sm font-medium leading-snug text-text-secondary",
594
623
  children: [
595
624
  label,
@@ -645,7 +674,7 @@ var Input = React3.forwardRef(
645
674
  Input.displayName = "Input";
646
675
 
647
676
  // src/components/ui/file-upload-zone.tsx
648
- import * as React4 from "react";
677
+ import * as React5 from "react";
649
678
  import { UploadCloud } from "lucide-react";
650
679
  import { cva as cva3 } from "class-variance-authority";
651
680
  import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
@@ -782,7 +811,7 @@ function createFileListFromFiles(files) {
782
811
  files.forEach((file) => transfer.items.add(file));
783
812
  return transfer.files;
784
813
  }
785
- var FileUploadZone = React4.forwardRef(
814
+ var FileUploadZone = React5.forwardRef(
786
815
  ({
787
816
  accept = ".csv,text/csv",
788
817
  className,
@@ -802,13 +831,13 @@ var FileUploadZone = React4.forwardRef(
802
831
  surface = "surface",
803
832
  ...props
804
833
  }, ref) => {
805
- const generatedId = React4.useId();
834
+ const generatedId = React5.useId();
806
835
  const inputId = id ?? generatedId;
807
- const inputRef = React4.useRef(null);
808
- const [isDragging, setIsDragging] = React4.useState(false);
809
- const [selectedFiles, setSelectedFiles] = React4.useState("");
836
+ const inputRef = React5.useRef(null);
837
+ const [isDragging, setIsDragging] = React5.useState(false);
838
+ const [selectedFiles, setSelectedFiles] = React5.useState("");
810
839
  const hasFile = selectedFiles.length > 0;
811
- const pushFiles = React4.useCallback(
840
+ const pushFiles = React5.useCallback(
812
841
  (incomingFiles) => {
813
842
  if (!incomingFiles || incomingFiles.length === 0) {
814
843
  setSelectedFiles("");
@@ -968,7 +997,7 @@ var FileUploadZone = React4.forwardRef(
968
997
  FileUploadZone.displayName = "FileUploadZone";
969
998
 
970
999
  // src/components/ui/alert.tsx
971
- import * as React5 from "react";
1000
+ import * as React6 from "react";
972
1001
  import { CircleAlert, CircleCheck, Info, TriangleAlert, X } from "lucide-react";
973
1002
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
974
1003
  var SEM_FG = {
@@ -990,13 +1019,38 @@ var MARKER_ICON = {
990
1019
  error: CircleAlert
991
1020
  };
992
1021
  var TITLE_LINE_HEIGHT = 21;
993
- var defaultEmphasis = (v) => v === "error" ? "strong" : "subtle";
994
- var Alert = React5.forwardRef(
995
- ({ variant = "info", emphasis, marker = "icon", title, children, onDismiss, style, ...rest }, ref) => {
996
- const weight = emphasis ?? defaultEmphasis(variant);
997
- const strong = weight === "strong";
1022
+ var actionPlacement = {
1023
+ oneLine: "col-start-2 row-start-2 justify-self-start mt-[var(--space-1)] @[344px]:col-start-3 @[344px]:row-start-1 @[344px]:mt-0 @[344px]:ms-[var(--space-2)]",
1024
+ twoLine: "col-start-2 row-start-3 justify-self-start mt-[var(--space-1)] @[344px]:col-start-3 @[344px]:row-[1/span_2] @[344px]:mt-0 @[344px]:ms-[var(--space-2)]"
1025
+ };
1026
+ var textWrap = { wordBreak: "keep-all", overflowWrap: "break-word", minWidth: 0 };
1027
+ var isEmpty = (node) => {
1028
+ if (node == null || typeof node === "boolean" || node === "") return true;
1029
+ if (Array.isArray(node)) return node.every(isEmpty);
1030
+ if (React6.isValidElement(node) && node.type === React6.Fragment) {
1031
+ return isEmpty(node.props.children);
1032
+ }
1033
+ return false;
1034
+ };
1035
+ var Alert = React6.forwardRef(
1036
+ ({
1037
+ variant = "info",
1038
+ emphasis = "subtle",
1039
+ marker = "icon",
1040
+ title,
1041
+ children,
1042
+ action,
1043
+ onDismiss,
1044
+ className,
1045
+ style,
1046
+ ...rest
1047
+ }, ref) => {
1048
+ const strong = emphasis === "strong";
998
1049
  const fg = SEM_FG[variant];
999
1050
  const MarkerIcon = MARKER_ICON[variant];
1051
+ const hasBody = !isEmpty(children);
1052
+ const hasAction = !isEmpty(action);
1053
+ const controlRow = hasBody ? "1 / span 2" : 1;
1000
1054
  return /* @__PURE__ */ jsxs5(
1001
1055
  "div",
1002
1056
  {
@@ -1005,12 +1059,14 @@ var Alert = React5.forwardRef(
1005
1059
  "aria-live": variant === "error" ? "assertive" : "polite",
1006
1060
  "data-slot": "alert",
1007
1061
  "data-variant": variant,
1008
- "data-emphasis": weight,
1062
+ "data-emphasis": emphasis,
1009
1063
  "data-marker": marker,
1064
+ className: cn(hasAction && "@container w-full", className),
1010
1065
  style: {
1011
- display: "flex",
1012
- alignItems: "flex-start",
1013
- gap: "var(--space-2)",
1066
+ display: "grid",
1067
+ gridTemplateColumns: "auto minmax(0, 1fr) auto auto",
1068
+ rowGap: 2,
1069
+ alignItems: hasBody ? "start" : "center",
1014
1070
  borderRadius: "var(--radius-md)",
1015
1071
  border: "1px solid " + (strong ? "color-mix(in srgb, " + fg + " 26%, transparent)" : "var(--border)"),
1016
1072
  background: strong ? SEM_BG[variant] : "var(--bg-surface)",
@@ -1026,9 +1082,11 @@ var Alert = React5.forwardRef(
1026
1082
  "aria-hidden": "true",
1027
1083
  "data-slot": "alert-marker",
1028
1084
  style: {
1085
+ gridColumn: 1,
1086
+ gridRow: 1,
1029
1087
  display: "inline-flex",
1030
1088
  height: TITLE_LINE_HEIGHT,
1031
- flexShrink: 0,
1089
+ marginInlineEnd: "var(--space-2)",
1032
1090
  alignItems: "center",
1033
1091
  justifyContent: "center",
1034
1092
  color: fg
@@ -1042,37 +1100,49 @@ var Alert = React5.forwardRef(
1042
1100
  ) : /* @__PURE__ */ jsx5(MarkerIcon, { "data-slot": "alert-icon", size: 16, strokeWidth: 2.25 })
1043
1101
  }
1044
1102
  ),
1045
- /* @__PURE__ */ jsxs5("div", { "data-slot": "alert-content", style: { flex: 1, minWidth: 0 }, children: [
1046
- /* @__PURE__ */ jsx5(
1047
- "div",
1048
- {
1049
- "data-slot": "alert-title",
1050
- style: {
1051
- fontFamily: "var(--font-sans)",
1052
- fontSize: 14,
1053
- fontWeight: "var(--fw-medium)",
1054
- lineHeight: TITLE_LINE_HEIGHT + "px",
1055
- color: strong ? fg : "var(--text-primary)"
1056
- },
1057
- children: title
1058
- }
1059
- ),
1060
- /* @__PURE__ */ jsx5(
1061
- "div",
1062
- {
1063
- "data-slot": "alert-body",
1064
- style: {
1065
- marginTop: 2,
1066
- fontFamily: "var(--font-sans)",
1067
- fontSize: "var(--fs-sm)",
1068
- lineHeight: "var(--lh-normal)",
1069
- color: strong ? "color-mix(in srgb, " + fg + " 88%, var(--text-primary))" : "var(--text-secondary)"
1070
- },
1071
- children
1072
- }
1073
- )
1074
- ] }),
1075
- onDismiss ? /* @__PURE__ */ jsx5(DismissButton, { onDismiss, strong, fg }) : null
1103
+ /* @__PURE__ */ jsx5(
1104
+ "div",
1105
+ {
1106
+ "data-slot": "alert-title",
1107
+ style: {
1108
+ gridColumn: 2,
1109
+ gridRow: 1,
1110
+ ...textWrap,
1111
+ fontFamily: "var(--font-sans)",
1112
+ fontSize: 14,
1113
+ fontWeight: "var(--fw-medium)",
1114
+ lineHeight: TITLE_LINE_HEIGHT + "px",
1115
+ color: strong ? fg : "var(--text-primary)"
1116
+ },
1117
+ children: title
1118
+ }
1119
+ ),
1120
+ hasBody ? /* @__PURE__ */ jsx5(
1121
+ "div",
1122
+ {
1123
+ "data-slot": "alert-body",
1124
+ style: {
1125
+ gridColumn: 2,
1126
+ gridRow: 2,
1127
+ ...textWrap,
1128
+ fontFamily: "var(--font-sans)",
1129
+ fontSize: "var(--fs-sm)",
1130
+ lineHeight: "var(--lh-normal)",
1131
+ color: strong ? "color-mix(in srgb, " + fg + " 88%, var(--text-primary))" : "var(--text-secondary)"
1132
+ },
1133
+ children
1134
+ }
1135
+ ) : null,
1136
+ hasAction ? /* @__PURE__ */ jsx5(
1137
+ "div",
1138
+ {
1139
+ "data-slot": "alert-action",
1140
+ className: hasBody ? actionPlacement.twoLine : actionPlacement.oneLine,
1141
+ style: { display: "flex", alignItems: "center" },
1142
+ children: action
1143
+ }
1144
+ ) : null,
1145
+ onDismiss ? /* @__PURE__ */ jsx5(DismissButton, { onDismiss, strong, fg, row: controlRow }) : null
1076
1146
  ]
1077
1147
  }
1078
1148
  );
@@ -1082,10 +1152,11 @@ Alert.displayName = "Alert";
1082
1152
  function DismissButton({
1083
1153
  onDismiss,
1084
1154
  strong,
1085
- fg
1155
+ fg,
1156
+ row
1086
1157
  }) {
1087
- const [hover, setHover] = React5.useState(false);
1088
- const [focus, setFocus] = React5.useState(false);
1158
+ const [hover, setHover] = React6.useState(false);
1159
+ const [focus, setFocus] = React6.useState(false);
1089
1160
  return /* @__PURE__ */ jsx5(
1090
1161
  "button",
1091
1162
  {
@@ -1097,8 +1168,11 @@ function DismissButton({
1097
1168
  onMouseLeave: () => setHover(false),
1098
1169
  onFocus: (e) => setFocus(e.currentTarget.matches(":focus-visible")),
1099
1170
  onBlur: () => setFocus(false),
1171
+ className: "relative before:absolute before:-inset-[9px] before:content-['']",
1100
1172
  style: {
1101
- flexShrink: 0,
1173
+ gridColumn: 4,
1174
+ gridRow: row,
1175
+ marginInlineStart: "var(--space-2)",
1102
1176
  display: "inline-flex",
1103
1177
  width: 28,
1104
1178
  height: 28,
@@ -1117,22 +1191,19 @@ function DismissButton({
1117
1191
  }
1118
1192
  );
1119
1193
  }
1120
- var InlineAlert = React5.forwardRef(
1194
+ var INLINE_LINE_HEIGHT = 1.4;
1195
+ var INLINE_ICON_SIZE = 12;
1196
+ var InlineAlert = React6.forwardRef(
1121
1197
  ({
1122
1198
  variant = "info",
1123
- emphasis = "subtle",
1124
- surface = "filled",
1199
+ marker = "icon",
1125
1200
  children,
1126
1201
  style,
1127
1202
  "aria-live": ariaLive,
1128
1203
  ...rest
1129
1204
  }, ref) => {
1130
- const strong = emphasis === "strong";
1131
1205
  const fg = SEM_FG[variant];
1132
- const filled = surface === "filled";
1133
- const bg = strong ? SEM_BG[variant] : filled ? "var(--bg-surface)" : "transparent";
1134
- const border = strong ? "color-mix(in srgb, " + fg + " 26%, transparent)" : filled ? "var(--border-subtle)" : "transparent";
1135
- const textColor = strong ? fg : filled ? "var(--text-primary)" : "var(--text-secondary)";
1206
+ const MarkerIcon = MARKER_ICON[variant];
1136
1207
  return /* @__PURE__ */ jsxs5(
1137
1208
  "div",
1138
1209
  {
@@ -1141,23 +1212,21 @@ var InlineAlert = React5.forwardRef(
1141
1212
  "aria-live": ariaLive ?? (variant === "error" ? "assertive" : "polite"),
1142
1213
  "data-slot": "inline-alert",
1143
1214
  "data-variant": variant,
1144
- "data-emphasis": emphasis,
1145
- "data-surface": surface,
1215
+ "data-marker": marker,
1146
1216
  style: {
1147
1217
  display: "inline-flex",
1148
1218
  width: "fit-content",
1149
1219
  maxWidth: "100%",
1150
- alignItems: "center",
1151
- gap: 7,
1152
- borderRadius: "var(--radius-sm)",
1153
- background: bg,
1154
- border: "1px solid " + border,
1155
- padding: strong || filled ? "6px 10px" : "2px 0",
1220
+ alignItems: "flex-start",
1221
+ gap: "var(--space-2)",
1222
+ background: "transparent",
1223
+ border: "1px solid transparent",
1224
+ padding: "2px 0",
1156
1225
  fontFamily: "var(--font-sans)",
1157
1226
  fontSize: 12,
1158
1227
  fontWeight: 500,
1159
- lineHeight: 1.4,
1160
- color: textColor,
1228
+ lineHeight: INLINE_LINE_HEIGHT,
1229
+ color: "var(--text-secondary)",
1161
1230
  ...style
1162
1231
  },
1163
1232
  ...rest,
@@ -1166,7 +1235,21 @@ var InlineAlert = React5.forwardRef(
1166
1235
  "span",
1167
1236
  {
1168
1237
  "aria-hidden": "true",
1169
- style: { width: 6, height: 6, flexShrink: 0, borderRadius: 9999, background: fg }
1238
+ "data-slot": "inline-alert-marker",
1239
+ style: {
1240
+ display: "inline-flex",
1241
+ height: INLINE_LINE_HEIGHT + "em",
1242
+ flexShrink: 0,
1243
+ alignItems: "center",
1244
+ color: fg
1245
+ },
1246
+ children: marker === "dot" ? /* @__PURE__ */ jsx5(
1247
+ "span",
1248
+ {
1249
+ "data-slot": "inline-alert-dot",
1250
+ style: { width: 6, height: 6, borderRadius: 9999, background: "currentColor" }
1251
+ }
1252
+ ) : /* @__PURE__ */ jsx5(MarkerIcon, { "data-slot": "inline-alert-icon", size: INLINE_ICON_SIZE, strokeWidth: 2.25 })
1170
1253
  }
1171
1254
  ),
1172
1255
  /* @__PURE__ */ jsx5("span", { style: { minWidth: 0 }, children })
@@ -1178,7 +1261,7 @@ var InlineAlert = React5.forwardRef(
1178
1261
  InlineAlert.displayName = "InlineAlert";
1179
1262
 
1180
1263
  // src/components/ui/textarea.tsx
1181
- import * as React6 from "react";
1264
+ import * as React7 from "react";
1182
1265
  import { cva as cva4 } from "class-variance-authority";
1183
1266
  import { AlertCircle as AlertCircle2, CheckCircle2 as CheckCircle22 } from "lucide-react";
1184
1267
  import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
@@ -1247,7 +1330,7 @@ function mapTextareaSizeLegacy(textareaSize) {
1247
1330
  function getTextLength(value) {
1248
1331
  return typeof value === "string" ? value.length : void 0;
1249
1332
  }
1250
- var Textarea = React6.forwardRef(
1333
+ var Textarea = React7.forwardRef(
1251
1334
  ({
1252
1335
  className,
1253
1336
  size,
@@ -1274,8 +1357,10 @@ var Textarea = React6.forwardRef(
1274
1357
  }, ref) => {
1275
1358
  const resolvedSize = size ?? mapTextareaSizeLegacy(textareaSize) ?? "md";
1276
1359
  const resolvedFullWidth = fullWidth ?? true;
1277
- const generatedId = React6.useId();
1278
- const textareaId = id ?? generatedId;
1360
+ const field = useFormFieldControl();
1361
+ const generatedId = React7.useId();
1362
+ const textareaId = field ? generatedId : id ?? generatedId;
1363
+ const controlId = id ?? field?.controlId;
1279
1364
  const hasCounter = maxLength != null;
1280
1365
  const resolvedState = invalid || state === "error" ? "error" : state;
1281
1366
  const showDescription = resolvedState === "default" && Boolean(description);
@@ -1283,9 +1368,16 @@ var Textarea = React6.forwardRef(
1283
1368
  const messageId = showMessage ? `${textareaId}-message` : void 0;
1284
1369
  const descriptionId = showDescription ? `${textareaId}-description` : void 0;
1285
1370
  const counterId = hasCounter ? `${textareaId}-counter` : void 0;
1286
- const describedBy = [ariaDescribedBy, descriptionId, messageId, counterId].filter(Boolean).join(" ") || void 0;
1371
+ const describedBy = joinIds(
1372
+ ariaDescribedBy,
1373
+ descriptionId,
1374
+ messageId,
1375
+ counterId,
1376
+ field?.describedBy
1377
+ );
1378
+ const elementId = controlId ?? (label || message || description || hasCounter ? textareaId : void 0);
1287
1379
  const resolvedInvalid = resolvedState === "error" ? true : ariaInvalid ?? void 0;
1288
- const [uncontrolledLength, setUncontrolledLength] = React6.useState(
1380
+ const [uncontrolledLength, setUncontrolledLength] = React7.useState(
1289
1381
  () => getTextLength(defaultValue) ?? 0
1290
1382
  );
1291
1383
  const resolvedLength = valueLength ?? getTextLength(value) ?? uncontrolledLength;
@@ -1299,7 +1391,7 @@ var Textarea = React6.forwardRef(
1299
1391
  "textarea",
1300
1392
  {
1301
1393
  ref,
1302
- id: label || message || description || hasCounter ? textareaId : id,
1394
+ id: elementId,
1303
1395
  required,
1304
1396
  disabled,
1305
1397
  readOnly,
@@ -1330,7 +1422,7 @@ var Textarea = React6.forwardRef(
1330
1422
  {
1331
1423
  "data-slot": "textarea-label",
1332
1424
  "data-required": required ? "true" : void 0,
1333
- htmlFor: textareaId,
1425
+ htmlFor: elementId,
1334
1426
  className: "pl-1 pb-1 text-sm font-medium leading-snug text-text-secondary",
1335
1427
  children: [
1336
1428
  label,
@@ -1405,7 +1497,7 @@ var Textarea = React6.forwardRef(
1405
1497
  Textarea.displayName = "Textarea";
1406
1498
 
1407
1499
  // src/components/ui/select.tsx
1408
- import * as React7 from "react";
1500
+ import * as React8 from "react";
1409
1501
  import { cva as cva5 } from "class-variance-authority";
1410
1502
  import {
1411
1503
  AlertCircle as AlertCircle3,
@@ -1514,7 +1606,7 @@ function SelectItem({
1514
1606
  );
1515
1607
  }
1516
1608
  SelectItem.displayName = "SelectItem";
1517
- var Select = React7.forwardRef(
1609
+ var Select = React8.forwardRef(
1518
1610
  ({
1519
1611
  className,
1520
1612
  selectVariant,
@@ -1547,38 +1639,44 @@ var Select = React7.forwardRef(
1547
1639
  const resolvedSize = size ?? mapSelectSizeLegacy(selectSize) ?? "md";
1548
1640
  const resolvedFullWidth = fullWidth ?? (selectVariant === "inline" ? false : true);
1549
1641
  const resolvedAppearance = appearance ?? (selectVariant === "inline" ? "inline" : "field");
1550
- const generatedId = React7.useId();
1551
- const selectId = id ?? generatedId;
1642
+ const field = useFormFieldControl();
1643
+ const generatedId = React8.useId();
1644
+ const selectId = field ? generatedId : id ?? generatedId;
1552
1645
  const inlineLabel = labelPlacement === "inline" && Boolean(label);
1553
1646
  const inlineLabelId = inlineLabel ? `${selectId}-label` : void 0;
1554
1647
  const inlineValueId = inlineLabel ? `${selectId}-value` : void 0;
1555
- const triggerId = label || message || description ? selectId : id;
1648
+ const triggerId = id ?? field?.controlId ?? (label || message || description ? selectId : void 0);
1556
1649
  const resolvedState = invalid || state === "error" ? "error" : state;
1557
1650
  const showDescription = resolvedState === "default" && Boolean(description);
1558
1651
  const showMessage = Boolean(message) && !showDescription;
1559
1652
  const messageId = showMessage ? `${selectId}-message` : void 0;
1560
1653
  const descriptionId = showDescription ? `${selectId}-description` : void 0;
1561
1654
  const resolvedInvalid = resolvedState === "error" ? true : ariaInvalid ?? void 0;
1562
- const describedBy = [ariaDescribedBy, descriptionId, messageId].filter(Boolean).join(" ") || void 0;
1655
+ const describedBy = joinIds(
1656
+ ariaDescribedBy,
1657
+ descriptionId,
1658
+ messageId,
1659
+ field?.describedBy
1660
+ );
1563
1661
  const isControlled = value !== void 0;
1564
- const [uncontrolledValue, setUncontrolledValue] = React7.useState(
1662
+ const [uncontrolledValue, setUncontrolledValue] = React8.useState(
1565
1663
  defaultValue ?? ""
1566
1664
  );
1567
1665
  const selectedValue = isControlled ? value : uncontrolledValue;
1568
1666
  const selectedOption = options.find((option) => option.value === selectedValue);
1569
1667
  const hasSelection = selectedValue != null && selectedValue !== "";
1570
- const [portalMounted, setPortalMounted] = React7.useState(false);
1571
- React7.useEffect(() => {
1668
+ const [portalMounted, setPortalMounted] = React8.useState(false);
1669
+ React8.useEffect(() => {
1572
1670
  setPortalMounted(true);
1573
1671
  }, []);
1574
- const effectiveOptions = React7.useMemo(() => {
1672
+ const effectiveOptions = React8.useMemo(() => {
1575
1673
  if (!clearable) return options;
1576
1674
  return [
1577
1675
  { value: SELECT_CLEAR_SENTINEL, label: clearLabel ?? placeholder },
1578
1676
  ...options
1579
1677
  ];
1580
1678
  }, [clearable, clearLabel, placeholder, options]);
1581
- const handleValueChange = React7.useCallback(
1679
+ const handleValueChange = React8.useCallback(
1582
1680
  (nextValue) => {
1583
1681
  const resolved = nextValue === SELECT_CLEAR_SENTINEL ? "" : nextValue;
1584
1682
  if (!isControlled) {
@@ -1693,7 +1791,7 @@ var Select = React7.forwardRef(
1693
1791
  ]
1694
1792
  }
1695
1793
  ),
1696
- portalMounted ? /* @__PURE__ */ jsx7(SelectPrimitive.Portal, { children: content }) : content
1794
+ /* @__PURE__ */ jsx7(FormFieldBoundary, { children: portalMounted ? /* @__PURE__ */ jsx7(SelectPrimitive.Portal, { children: content }) : content })
1697
1795
  ]
1698
1796
  }
1699
1797
  );
@@ -1713,7 +1811,7 @@ var Select = React7.forwardRef(
1713
1811
  {
1714
1812
  "data-slot": "select-label",
1715
1813
  "data-required": required ? "true" : void 0,
1716
- htmlFor: selectId,
1814
+ htmlFor: triggerId,
1717
1815
  className: "pl-1 pb-1 text-sm font-medium leading-snug text-text-secondary",
1718
1816
  children: [
1719
1817
  label,
@@ -1769,6 +1867,7 @@ var Select = React7.forwardRef(
1769
1867
  Select.displayName = "Select";
1770
1868
 
1771
1869
  // src/components/ui/form-field.tsx
1870
+ import * as React9 from "react";
1772
1871
  import { cva as cva6 } from "class-variance-authority";
1773
1872
  import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1774
1873
  var formFieldVariants = cva6("w-full", {
@@ -1787,6 +1886,10 @@ var formFieldRequiredClassName = "ml-[2px] font-bold text-[var(--semantic-error,
1787
1886
  var formFieldDescriptionClassName = "text-[12px] leading-snug text-text-tertiary";
1788
1887
  var formFieldErrorClassName = "text-[12px] leading-snug text-[var(--semantic-error,var(--error))]";
1789
1888
  var formFieldControlStackClassName = "flex min-w-0 flex-col gap-[var(--space-1)]";
1889
+ var nativeLabelableTags = /* @__PURE__ */ new Set(["input", "select", "textarea", "button"]);
1890
+ function isNativeLabelable(node) {
1891
+ return React9.isValidElement(node) && typeof node.type === "string" && nativeLabelableTags.has(node.type);
1892
+ }
1790
1893
  function FormField({
1791
1894
  label,
1792
1895
  required,
@@ -1799,27 +1902,50 @@ function FormField({
1799
1902
  ...props
1800
1903
  }) {
1801
1904
  const isFunctionChildren = typeof children === "function";
1802
- const descriptionId = id && description && !error ? `${id}-description` : void 0;
1803
- const errorId = id && error ? `${id}-error` : void 0;
1804
- const describedBy = !isFunctionChildren ? [descriptionId, errorId].filter(Boolean).join(" ") || void 0 : void 0;
1905
+ const autoId = React9.useId();
1906
+ const controlId = id ?? autoId;
1907
+ const labelId = `${autoId}-label`;
1908
+ const descriptionId = description && !error ? `${controlId}-description` : void 0;
1909
+ const errorId = error ? `${controlId}-error` : void 0;
1910
+ const describedBy = !isFunctionChildren ? joinIds(descriptionId, errorId) : void 0;
1805
1911
  const invalid = Boolean(error);
1806
1912
  const controlDescription = !error ? description : void 0;
1807
1913
  const controlMessage = error;
1808
1914
  const controlState = error ? "error" : "default";
1809
- const resolvedChildren = isFunctionChildren ? children({
1810
- controlProps: {
1811
- id,
1812
- "aria-describedby": describedBy,
1813
- "aria-invalid": invalid ? true : void 0,
1814
- required: required || void 0,
1815
- description: controlDescription,
1816
- message: controlMessage,
1817
- state: controlState
1818
- },
1819
- descriptionId,
1820
- errorId,
1821
- invalid
1822
- }) : children;
1915
+ const nativeControl = !isFunctionChildren && isNativeLabelable(children) ? children : null;
1916
+ const labelTarget = nativeControl?.props.id ?? controlId;
1917
+ let resolvedChildren;
1918
+ if (isFunctionChildren) {
1919
+ resolvedChildren = children({
1920
+ controlProps: {
1921
+ id: controlId,
1922
+ "aria-describedby": describedBy,
1923
+ "aria-invalid": invalid ? true : void 0,
1924
+ required: required || void 0,
1925
+ description: controlDescription,
1926
+ message: controlMessage,
1927
+ state: controlState
1928
+ },
1929
+ descriptionId,
1930
+ errorId,
1931
+ invalid
1932
+ });
1933
+ } else if (nativeControl) {
1934
+ const nativeDescribedBy = joinIds(
1935
+ nativeControl.props["aria-describedby"],
1936
+ describedBy
1937
+ );
1938
+ resolvedChildren = React9.cloneElement(nativeControl, {
1939
+ id: labelTarget,
1940
+ ...nativeDescribedBy ? { "aria-describedby": nativeDescribedBy } : null
1941
+ });
1942
+ } else {
1943
+ resolvedChildren = children;
1944
+ }
1945
+ const controlContext = React9.useMemo(
1946
+ () => isFunctionChildren ? null : { controlId, labelId, describedBy },
1947
+ [isFunctionChildren, controlId, labelId, describedBy]
1948
+ );
1823
1949
  const labelClassName = cn(
1824
1950
  formFieldLabelClassName,
1825
1951
  layout === "horizontal" && "sm:justify-self-end sm:text-right sm:pt-[var(--space-4)]"
@@ -1833,11 +1959,12 @@ function FormField({
1833
1959
  className: cn(formFieldVariants({ layout }), className),
1834
1960
  ...props,
1835
1961
  children: [
1836
- id ? /* @__PURE__ */ jsxs8(
1962
+ /* @__PURE__ */ jsxs8(
1837
1963
  "label",
1838
1964
  {
1965
+ id: labelId,
1839
1966
  "data-slot": "form-field-label",
1840
- htmlFor: id,
1967
+ htmlFor: labelTarget,
1841
1968
  className: labelClassName,
1842
1969
  children: [
1843
1970
  /* @__PURE__ */ jsx8("span", { children: label }),
@@ -1851,17 +1978,7 @@ function FormField({
1851
1978
  ) : null
1852
1979
  ]
1853
1980
  }
1854
- ) : /* @__PURE__ */ jsxs8("span", { "data-slot": "form-field-label", className: labelClassName, children: [
1855
- label,
1856
- required ? /* @__PURE__ */ jsx8(
1857
- "span",
1858
- {
1859
- "aria-hidden": "true",
1860
- className: formFieldRequiredClassName,
1861
- children: "*"
1862
- }
1863
- ) : null
1864
- ] }),
1981
+ ),
1865
1982
  /* @__PURE__ */ jsxs8(
1866
1983
  "div",
1867
1984
  {
@@ -1871,7 +1988,7 @@ function FormField({
1871
1988
  layout === "horizontal" && "sm:col-start-2"
1872
1989
  ),
1873
1990
  children: [
1874
- resolvedChildren,
1991
+ /* @__PURE__ */ jsx8(FormFieldControlContext.Provider, { value: controlContext, children: resolvedChildren }),
1875
1992
  !isFunctionChildren && !error && description ? /* @__PURE__ */ jsx8(
1876
1993
  "p",
1877
1994
  {
@@ -1900,10 +2017,10 @@ function FormField({
1900
2017
  }
1901
2018
 
1902
2019
  // src/components/ui/label.tsx
1903
- import * as React8 from "react";
2020
+ import * as React10 from "react";
1904
2021
  import { Label as LabelPrimitive } from "radix-ui";
1905
2022
  import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1906
- var Label = React8.forwardRef(({ htmlFor, required, children, className, ...props }, ref) => /* @__PURE__ */ jsxs9(
2023
+ var Label = React10.forwardRef(({ htmlFor, required, children, className, ...props }, ref) => /* @__PURE__ */ jsxs9(
1907
2024
  LabelPrimitive.Root,
1908
2025
  {
1909
2026
  ref,
@@ -1931,11 +2048,11 @@ var Label = React8.forwardRef(({ htmlFor, required, children, className, ...prop
1931
2048
  Label.displayName = "Label";
1932
2049
 
1933
2050
  // src/components/ui/switch.tsx
1934
- import * as React9 from "react";
2051
+ import * as React11 from "react";
1935
2052
  import { cva as cva7 } from "class-variance-authority";
1936
2053
  import { Loader2 as Loader22 } from "lucide-react";
1937
2054
  import { Switch as SwitchPrimitive } from "radix-ui";
1938
- import { Fragment, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
2055
+ import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1939
2056
  var switchFieldVariants = cva7("", {
1940
2057
  variants: {
1941
2058
  labelPlacement: {
@@ -1952,7 +2069,7 @@ var switchFieldVariants = cva7("", {
1952
2069
  fullWidth: false
1953
2070
  }
1954
2071
  });
1955
- var Switch = React9.forwardRef(
2072
+ var Switch = React11.forwardRef(
1956
2073
  ({
1957
2074
  className,
1958
2075
  label,
@@ -1963,12 +2080,15 @@ var Switch = React9.forwardRef(
1963
2080
  fullWidth = false,
1964
2081
  disabled,
1965
2082
  id,
2083
+ "aria-describedby": ariaDescribedBy,
1966
2084
  ...props
1967
2085
  }, ref) => {
1968
- const generatedId = React9.useId();
1969
- const switchId = id ?? generatedId;
1970
- const labelId = id ? `${id}-label` : `${generatedId}-label`;
1971
- const descriptionId = description ? id ? `${id}-description` : `${generatedId}-description` : void 0;
2086
+ const field = useFormFieldControl();
2087
+ const generatedId = React11.useId();
2088
+ const switchId = id ?? field?.controlId ?? generatedId;
2089
+ const slotId = field ? generatedId : id ?? generatedId;
2090
+ const labelId = `${slotId}-label`;
2091
+ const descriptionId = description ? `${slotId}-description` : void 0;
1972
2092
  const isDisabled = disabled || loading;
1973
2093
  const isStart = labelPlacement === "start";
1974
2094
  const track = /* @__PURE__ */ jsxs10(
@@ -1980,7 +2100,7 @@ var Switch = React9.forwardRef(
1980
2100
  disabled: isDisabled,
1981
2101
  "aria-required": required || void 0,
1982
2102
  "aria-busy": loading || void 0,
1983
- "aria-describedby": descriptionId,
2103
+ "aria-describedby": joinIds(ariaDescribedBy, descriptionId, field?.describedBy),
1984
2104
  className: cn(
1985
2105
  "group relative inline-flex h-[24px] w-[44px] cursor-pointer items-center rounded-full transition-colors",
1986
2106
  "bg-[var(--border)] data-[state=checked]:bg-[var(--primary)]",
@@ -2057,13 +2177,13 @@ var Switch = React9.forwardRef(
2057
2177
  "data-slot": "switch-field",
2058
2178
  "data-disabled": isDisabled ? "" : void 0,
2059
2179
  className: switchFieldVariants({ labelPlacement, fullWidth }),
2060
- children: isStart ? /* @__PURE__ */ jsxs10(Fragment, { children: [
2180
+ children: isStart ? /* @__PURE__ */ jsxs10(Fragment2, { children: [
2061
2181
  /* @__PURE__ */ jsxs10("div", { className: "flex min-w-0 grow flex-col gap-[var(--space-1)]", children: [
2062
2182
  labelNode,
2063
2183
  descriptionNode
2064
2184
  ] }),
2065
2185
  track
2066
- ] }) : /* @__PURE__ */ jsxs10(Fragment, { children: [
2186
+ ] }) : /* @__PURE__ */ jsxs10(Fragment2, { children: [
2067
2187
  /* @__PURE__ */ jsxs10("div", { className: "inline-flex items-center gap-[var(--space-3)]", children: [
2068
2188
  track,
2069
2189
  labelNode
@@ -2077,13 +2197,13 @@ var Switch = React9.forwardRef(
2077
2197
  Switch.displayName = "Switch";
2078
2198
 
2079
2199
  // src/components/ui/permission-guard.tsx
2080
- import * as React11 from "react";
2200
+ import * as React13 from "react";
2081
2201
 
2082
2202
  // src/components/ui/tooltip.tsx
2083
- import * as React10 from "react";
2203
+ import * as React12 from "react";
2084
2204
  import { Tooltip as TooltipPrimitive } from "radix-ui";
2085
2205
  import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
2086
- var TooltipTouchContext = React10.createContext(null);
2206
+ var TooltipTouchContext = React12.createContext(null);
2087
2207
  function TooltipProvider({
2088
2208
  delayDuration = 0,
2089
2209
  ...props
@@ -2105,17 +2225,17 @@ function Tooltip({
2105
2225
  children,
2106
2226
  ...props
2107
2227
  }) {
2108
- const [uncontrolledOpen, setUncontrolledOpen] = React10.useState(defaultOpen ?? false);
2228
+ const [uncontrolledOpen, setUncontrolledOpen] = React12.useState(defaultOpen ?? false);
2109
2229
  const isControlled = controlledOpen !== void 0;
2110
2230
  const open = isControlled ? controlledOpen : uncontrolledOpen;
2111
- const handleOpenChange = React10.useCallback(
2231
+ const handleOpenChange = React12.useCallback(
2112
2232
  (value) => {
2113
2233
  if (!isControlled) setUncontrolledOpen(value);
2114
2234
  userOnOpenChange?.(value);
2115
2235
  },
2116
2236
  [isControlled, userOnOpenChange]
2117
2237
  );
2118
- const ctx = React10.useMemo(
2238
+ const ctx = React12.useMemo(
2119
2239
  () => ({
2120
2240
  enableTouch: enableTouch && !isControlled,
2121
2241
  toggle: () => handleOpenChange(!open)
@@ -2137,7 +2257,7 @@ function TooltipTrigger({
2137
2257
  onClick: userOnClick,
2138
2258
  ...props
2139
2259
  }) {
2140
- const ctx = React10.useContext(TooltipTouchContext);
2260
+ const ctx = React12.useContext(TooltipTouchContext);
2141
2261
  return /* @__PURE__ */ jsx11(
2142
2262
  TooltipPrimitive.Trigger,
2143
2263
  {
@@ -2156,7 +2276,7 @@ function TooltipContent({
2156
2276
  children,
2157
2277
  ...props
2158
2278
  }) {
2159
- return /* @__PURE__ */ jsx11(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs11(
2279
+ return /* @__PURE__ */ jsx11(FormFieldBoundary, { children: /* @__PURE__ */ jsx11(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs11(
2160
2280
  TooltipPrimitive.Content,
2161
2281
  {
2162
2282
  "data-slot": "tooltip-content",
@@ -2171,13 +2291,13 @@ function TooltipContent({
2171
2291
  /* @__PURE__ */ jsx11(TooltipPrimitive.Arrow, { className: "z-[var(--z-tooltip)] size-[10px] translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" })
2172
2292
  ]
2173
2293
  }
2174
- ) });
2294
+ ) }) });
2175
2295
  }
2176
2296
 
2177
2297
  // src/components/ui/permission-guard.tsx
2178
- import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
2298
+ import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
2179
2299
  var defaultDisabledReason = "\uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4";
2180
- var PermissionContext = React11.createContext(
2300
+ var PermissionContext = React13.createContext(
2181
2301
  void 0
2182
2302
  );
2183
2303
  function PermissionProvider({
@@ -2188,7 +2308,7 @@ function PermissionProvider({
2188
2308
  return /* @__PURE__ */ jsx12(PermissionContext.Provider, { value: value ?? permissions, children });
2189
2309
  }
2190
2310
  function usePermission(permission, scope) {
2191
- const state = React11.useContext(PermissionContext);
2311
+ const state = React13.useContext(PermissionContext);
2192
2312
  return evaluatePermission(permission, state, scope);
2193
2313
  }
2194
2314
  function evaluatePermission(permission, state, scope) {
@@ -2219,10 +2339,10 @@ function PermissionGuard({
2219
2339
  permissions,
2220
2340
  disabledReason = defaultDisabledReason
2221
2341
  }) {
2222
- const state = React11.useContext(PermissionContext);
2342
+ const state = React13.useContext(PermissionContext);
2223
2343
  const allowed = evaluatePermission(permission, permissions ?? state, scope);
2224
2344
  if (allowed) {
2225
- return /* @__PURE__ */ jsx12(Fragment3, { children });
2345
+ return /* @__PURE__ */ jsx12(Fragment4, { children });
2226
2346
  }
2227
2347
  if (fallback === "hide" || fallback == null) {
2228
2348
  return null;
@@ -2230,7 +2350,7 @@ function PermissionGuard({
2230
2350
  if (fallback === "disabled") {
2231
2351
  return renderDisabledFallback(children, disabledReason);
2232
2352
  }
2233
- return /* @__PURE__ */ jsx12(Fragment3, { children: fallback });
2353
+ return /* @__PURE__ */ jsx12(Fragment4, { children: fallback });
2234
2354
  }
2235
2355
  function getPermissionCandidates(permission, scope) {
2236
2356
  const candidates = /* @__PURE__ */ new Set([permission]);
@@ -2253,10 +2373,10 @@ function hasAnyMatch(candidates, values) {
2253
2373
  return candidates.some((candidate) => valueSet.has(candidate));
2254
2374
  }
2255
2375
  function renderDisabledFallback(children, disabledReason) {
2256
- if (!React11.isValidElement(children) || children.type === React11.Fragment) {
2376
+ if (!React13.isValidElement(children) || children.type === React13.Fragment) {
2257
2377
  return null;
2258
2378
  }
2259
- const clonedChild = React11.cloneElement(
2379
+ const clonedChild = React13.cloneElement(
2260
2380
  children,
2261
2381
  {
2262
2382
  disabled: true,
@@ -2282,7 +2402,7 @@ function isPermissionState(value) {
2282
2402
  }
2283
2403
 
2284
2404
  // src/components/ui/card.tsx
2285
- import * as React12 from "react";
2405
+ import * as React14 from "react";
2286
2406
  import { cva as cva8 } from "class-variance-authority";
2287
2407
  import { jsx as jsx13 } from "react/jsx-runtime";
2288
2408
  var cardBaseVariants = cva8(
@@ -2333,7 +2453,7 @@ function cardVariants({ variant, surface, interactive, className } = {}) {
2333
2453
  className
2334
2454
  );
2335
2455
  }
2336
- var Card = React12.forwardRef(
2456
+ var Card = React14.forwardRef(
2337
2457
  ({ className, variant, surface, interactive, selected, disabled, "aria-disabled": ariaDisabled, ...props }, ref) => /* @__PURE__ */ jsx13(
2338
2458
  "div",
2339
2459
  {
@@ -2354,7 +2474,7 @@ var Card = React12.forwardRef(
2354
2474
  )
2355
2475
  );
2356
2476
  Card.displayName = "Card";
2357
- var CardHeader = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
2477
+ var CardHeader = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
2358
2478
  "div",
2359
2479
  {
2360
2480
  ref,
@@ -2364,7 +2484,7 @@ var CardHeader = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE
2364
2484
  }
2365
2485
  ));
2366
2486
  CardHeader.displayName = "CardHeader";
2367
- var CardTitle = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
2487
+ var CardTitle = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
2368
2488
  "h3",
2369
2489
  {
2370
2490
  ref,
@@ -2377,7 +2497,7 @@ var CardTitle = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE_
2377
2497
  }
2378
2498
  ));
2379
2499
  CardTitle.displayName = "CardTitle";
2380
- var CardDescription = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
2500
+ var CardDescription = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
2381
2501
  "p",
2382
2502
  {
2383
2503
  ref,
@@ -2390,7 +2510,7 @@ var CardDescription = React12.forwardRef(({ className, ...props }, ref) => /* @_
2390
2510
  }
2391
2511
  ));
2392
2512
  CardDescription.displayName = "CardDescription";
2393
- var CardContent = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
2513
+ var CardContent = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
2394
2514
  "div",
2395
2515
  {
2396
2516
  ref,
@@ -2400,7 +2520,7 @@ var CardContent = React12.forwardRef(({ className, ...props }, ref) => /* @__PUR
2400
2520
  }
2401
2521
  ));
2402
2522
  CardContent.displayName = "CardContent";
2403
- var CardProse = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
2523
+ var CardProse = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
2404
2524
  "div",
2405
2525
  {
2406
2526
  ref,
@@ -2419,7 +2539,7 @@ var CardProse = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE_
2419
2539
  }
2420
2540
  ));
2421
2541
  CardProse.displayName = "CardProse";
2422
- var CardFooter = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
2542
+ var CardFooter = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
2423
2543
  "div",
2424
2544
  {
2425
2545
  ref,
@@ -2431,9 +2551,9 @@ var CardFooter = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE
2431
2551
  CardFooter.displayName = "CardFooter";
2432
2552
 
2433
2553
  // src/components/ui/page-header.tsx
2434
- import * as React13 from "react";
2554
+ import * as React15 from "react";
2435
2555
  import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
2436
- var PageHeader = React13.forwardRef(
2556
+ var PageHeader = React15.forwardRef(
2437
2557
  ({
2438
2558
  className,
2439
2559
  breadcrumb,
@@ -2518,7 +2638,7 @@ var PageHeader = React13.forwardRef(
2518
2638
  PageHeader.displayName = "PageHeader";
2519
2639
 
2520
2640
  // src/components/ui/breadcrumb.tsx
2521
- import * as React14 from "react";
2641
+ import * as React16 from "react";
2522
2642
  import { ChevronRight } from "lucide-react";
2523
2643
  import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
2524
2644
  function getDisplayItems(items, maxItems) {
@@ -2543,7 +2663,7 @@ var Separator = () => /* @__PURE__ */ jsx15("li", { "aria-hidden": "true", "data
2543
2663
  className: "text-[var(--text-disabled)]"
2544
2664
  }
2545
2665
  ) });
2546
- var Breadcrumb = React14.forwardRef(
2666
+ var Breadcrumb = React16.forwardRef(
2547
2667
  ({
2548
2668
  className,
2549
2669
  items,
@@ -2568,7 +2688,7 @@ var Breadcrumb = React14.forwardRef(
2568
2688
  children: displayItems.map((item, index) => {
2569
2689
  const isLast = index === displayItems.length - 1;
2570
2690
  if (item === "ellipsis") {
2571
- return /* @__PURE__ */ jsxs14(React14.Fragment, { children: [
2691
+ return /* @__PURE__ */ jsxs14(React16.Fragment, { children: [
2572
2692
  /* @__PURE__ */ jsx15(
2573
2693
  "li",
2574
2694
  {
@@ -2581,7 +2701,7 @@ var Breadcrumb = React14.forwardRef(
2581
2701
  /* @__PURE__ */ jsx15(Separator, {})
2582
2702
  ] }, "ellipsis");
2583
2703
  }
2584
- return /* @__PURE__ */ jsxs14(React14.Fragment, { children: [
2704
+ return /* @__PURE__ */ jsxs14(React16.Fragment, { children: [
2585
2705
  /* @__PURE__ */ jsx15("li", { "data-slot": "breadcrumb-item", className: "flex min-w-0 items-center", children: isLast ? /* @__PURE__ */ jsx15(
2586
2706
  "span",
2587
2707
  {
@@ -2627,9 +2747,9 @@ var Breadcrumb = React14.forwardRef(
2627
2747
  Breadcrumb.displayName = "Breadcrumb";
2628
2748
 
2629
2749
  // src/components/ui/data-layout.tsx
2630
- import * as React15 from "react";
2750
+ import * as React17 from "react";
2631
2751
  import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
2632
- var DataLayout = React15.forwardRef(
2752
+ var DataLayout = React17.forwardRef(
2633
2753
  ({ className, header, toolbar, children, footer, bulkBar, ...props }, ref) => {
2634
2754
  return /* @__PURE__ */ jsxs15(
2635
2755
  "div",
@@ -2657,7 +2777,7 @@ var DataLayout = React15.forwardRef(
2657
2777
  "div",
2658
2778
  {
2659
2779
  "data-slot": "data-layout-bulkbar",
2660
- className: "pointer-events-none sticky bottom-[var(--space-4)] z-20 mt-[var(--space-2)] flex justify-center",
2780
+ className: "pointer-events-none sticky bottom-[calc(var(--space-4)+env(safe-area-inset-bottom))] z-20 mt-[var(--space-2)] flex justify-center",
2661
2781
  children: /* @__PURE__ */ jsx16("div", { className: "flex w-full flex-col items-center [&>*:has([data-slot=bulk-action-bar])]:self-stretch [&>*:not(:has([data-slot=bulk-action-bar]))]:pointer-events-auto [&>*]:max-w-full [&_[data-slot=bulk-action-bar]]:pointer-events-auto", children: bulkBar })
2662
2782
  }
2663
2783
  ) : null
@@ -2672,9 +2792,9 @@ var DataLayout = React15.forwardRef(
2672
2792
  DataLayout.displayName = "DataLayout";
2673
2793
 
2674
2794
  // src/components/ui/wizard-layout.tsx
2675
- import * as React16 from "react";
2795
+ import * as React18 from "react";
2676
2796
  import { Check as Check2 } from "lucide-react";
2677
- import { Fragment as Fragment6, jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
2797
+ import { Fragment as Fragment7, jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
2678
2798
  var circleBaseClassName = [
2679
2799
  "flex items-center justify-center rounded-[var(--radius-full)] border text-[12px] font-semibold leading-none",
2680
2800
  "transition-[background-color,border-color,color] motion-reduce:transition-none"
@@ -2739,7 +2859,7 @@ function getConnectorClassName(isActivePath) {
2739
2859
  isActivePath ? "bg-[var(--primary)]" : "bg-[var(--border-subtle)]"
2740
2860
  );
2741
2861
  }
2742
- var WizardLayout = React16.forwardRef(
2862
+ var WizardLayout = React18.forwardRef(
2743
2863
  ({
2744
2864
  className,
2745
2865
  header,
@@ -2752,8 +2872,8 @@ var WizardLayout = React16.forwardRef(
2752
2872
  allowStepNavigation = true,
2753
2873
  ...props
2754
2874
  }, ref) => {
2755
- const stepViewportRef = React16.useRef(null);
2756
- const stepItemRefs = React16.useRef([]);
2875
+ const stepViewportRef = React18.useRef(null);
2876
+ const stepItemRefs = React18.useRef([]);
2757
2877
  const resolvedSteps = steps.map((step, index) => ({
2758
2878
  ...step,
2759
2879
  resolvedState: getStepState(step, index, activeStep)
@@ -2763,7 +2883,7 @@ var WizardLayout = React16.forwardRef(
2763
2883
  const currentStep = resolvedSteps[currentStepIndex];
2764
2884
  const progressStepNumber = stepCount > 0 ? currentStepIndex + 1 : 0;
2765
2885
  const progressValue = stepCount > 0 ? progressStepNumber / stepCount * 100 : 0;
2766
- React16.useLayoutEffect(() => {
2886
+ React18.useLayoutEffect(() => {
2767
2887
  const viewportNode = stepViewportRef.current;
2768
2888
  const activeNode = stepItemRefs.current[currentStepIndex];
2769
2889
  if (!viewportNode || !activeNode) {
@@ -2917,7 +3037,7 @@ var WizardLayout = React16.forwardRef(
2917
3037
  const isClickable = allowStepNavigation && step.resolvedState === "complete" && typeof onStepChange === "function";
2918
3038
  const isCurrent = step.resolvedState === "current";
2919
3039
  const connectorIsActive = index < activeStep;
2920
- return /* @__PURE__ */ jsxs16(React16.Fragment, { children: [
3040
+ return /* @__PURE__ */ jsxs16(React18.Fragment, { children: [
2921
3041
  /* @__PURE__ */ jsx17(
2922
3042
  "li",
2923
3043
  {
@@ -2965,7 +3085,7 @@ var WizardLayout = React16.forwardRef(
2965
3085
  ) : null
2966
3086
  ]
2967
3087
  }
2968
- ) : /* @__PURE__ */ jsxs16(Fragment6, { children: [
3088
+ ) : /* @__PURE__ */ jsxs16(Fragment7, { children: [
2969
3089
  /* @__PURE__ */ jsx17(
2970
3090
  "span",
2971
3091
  {
@@ -3027,14 +3147,14 @@ var WizardLayout = React16.forwardRef(
3027
3147
  WizardLayout.displayName = "WizardLayout";
3028
3148
 
3029
3149
  // src/components/ui/detail-layout.tsx
3030
- import * as React18 from "react";
3150
+ import * as React20 from "react";
3031
3151
 
3032
3152
  // src/components/ui/tabs.tsx
3033
- import * as React17 from "react";
3153
+ import * as React19 from "react";
3034
3154
  import { Tabs as TabsPrimitive } from "radix-ui";
3035
3155
  import { cva as cva9 } from "class-variance-authority";
3036
3156
  import { Lock } from "lucide-react";
3037
- import { Fragment as Fragment7, jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
3157
+ import { Fragment as Fragment8, jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
3038
3158
  var tabsRootVariants = cva9("w-full", {
3039
3159
  variants: {
3040
3160
  orientation: {
@@ -3179,9 +3299,9 @@ var tabsBadgeVariants = cva9(
3179
3299
  ].join(" ")
3180
3300
  );
3181
3301
  function useTabsIndicator(enabled, activeKey, tabsKey, listRef, indicatorRef) {
3182
- const placedRef = React17.useRef(null);
3183
- const previousKeyRef = React17.useRef(null);
3184
- const place = React17.useCallback(
3302
+ const placedRef = React19.useRef(null);
3303
+ const previousKeyRef = React19.useRef(null);
3304
+ const place = React19.useCallback(
3185
3305
  (animate) => {
3186
3306
  const list = listRef.current;
3187
3307
  const indicator = indicatorRef.current;
@@ -3206,7 +3326,7 @@ function useTabsIndicator(enabled, activeKey, tabsKey, listRef, indicatorRef) {
3206
3326
  },
3207
3327
  [listRef, indicatorRef]
3208
3328
  );
3209
- React17.useLayoutEffect(() => {
3329
+ React19.useLayoutEffect(() => {
3210
3330
  if (!enabled) {
3211
3331
  placedRef.current = null;
3212
3332
  previousKeyRef.current = null;
@@ -3216,7 +3336,7 @@ function useTabsIndicator(enabled, activeKey, tabsKey, listRef, indicatorRef) {
3216
3336
  previousKeyRef.current = activeKey;
3217
3337
  place(previousKey !== null && previousKey !== activeKey);
3218
3338
  }, [enabled, activeKey, tabsKey, place]);
3219
- React17.useEffect(() => {
3339
+ React19.useEffect(() => {
3220
3340
  const list = listRef.current;
3221
3341
  if (!enabled || !list) return;
3222
3342
  let cancelled = false;
@@ -3251,7 +3371,7 @@ function getTabId(baseId, key) {
3251
3371
  function getPanelId(baseId, key) {
3252
3372
  return baseId ? `${baseId}-panel-${key}` : `panel-${key}`;
3253
3373
  }
3254
- var Tabs = React17.forwardRef(
3374
+ var Tabs = React19.forwardRef(
3255
3375
  ({
3256
3376
  className,
3257
3377
  listClassName,
@@ -3265,8 +3385,8 @@ var Tabs = React17.forwardRef(
3265
3385
  variant = "line",
3266
3386
  ...props
3267
3387
  }, ref) => {
3268
- const listRef = React17.useRef(null);
3269
- const indicatorRef = React17.useRef(null);
3388
+ const listRef = React19.useRef(null);
3389
+ const indicatorRef = React19.useRef(null);
3270
3390
  const isLine = variant === "line";
3271
3391
  const tabsKey = tabs.map((tab) => tab.key).join("\0");
3272
3392
  useTabsIndicator(isLine, activeKey, tabsKey, listRef, indicatorRef);
@@ -3301,7 +3421,7 @@ var Tabs = React17.forwardRef(
3301
3421
  className: cn("group", tabsTriggerVariants({ variant, orientation }), triggerClassName),
3302
3422
  children: [
3303
3423
  isLine ? /* @__PURE__ */ jsx18("span", { "data-label": tab.label, className: tabsLabelReserveClassName, children: tab.label }) : /* @__PURE__ */ jsx18("span", { children: tab.label }),
3304
- isShownTabBadge(tab.badge) ? /* @__PURE__ */ jsxs17(Fragment7, { children: [
3424
+ isShownTabBadge(tab.badge) ? /* @__PURE__ */ jsxs17(Fragment8, { children: [
3305
3425
  /* @__PURE__ */ jsx18("span", { "aria-hidden": "true", "data-slot": "tabs-badge", className: tabsBadgeVariants(), children: formatTabBadge(tab.badge) }),
3306
3426
  /* @__PURE__ */ jsx18("span", { className: "sr-only", children: ` ${tab.badge}` })
3307
3427
  ] }) : null,
@@ -3340,7 +3460,7 @@ var Tabs = React17.forwardRef(
3340
3460
  }
3341
3461
  );
3342
3462
  Tabs.displayName = "Tabs";
3343
- var TabsContent = React17.forwardRef(({ className, tabKey, baseId, ...props }, ref) => /* @__PURE__ */ jsx18(
3463
+ var TabsContent = React19.forwardRef(({ className, tabKey, baseId, ...props }, ref) => /* @__PURE__ */ jsx18(
3344
3464
  TabsPrimitive.Content,
3345
3465
  {
3346
3466
  ref,
@@ -3360,7 +3480,7 @@ var TabsContent = React17.forwardRef(({ className, tabKey, baseId, ...props }, r
3360
3480
  TabsContent.displayName = TabsPrimitive.Content.displayName;
3361
3481
 
3362
3482
  // src/components/ui/detail-layout.tsx
3363
- import { Fragment as Fragment8, jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
3483
+ import { Fragment as Fragment9, jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
3364
3484
  function DetailLayoutBody({
3365
3485
  children,
3366
3486
  aside,
@@ -3398,29 +3518,29 @@ function DetailLayoutBody({
3398
3518
  );
3399
3519
  }
3400
3520
  function isTabsContentChild(child) {
3401
- return React18.isValidElement(child) && child.type === TabsContent;
3521
+ return React20.isValidElement(child) && child.type === TabsContent;
3402
3522
  }
3403
3523
  function containsTabsContent(children) {
3404
- return React18.Children.toArray(children).some((child) => {
3524
+ return React20.Children.toArray(children).some((child) => {
3405
3525
  if (isTabsContentChild(child)) return true;
3406
- return React18.isValidElement(child) && containsTabsContent(child.props.children);
3526
+ return React20.isValidElement(child) && containsTabsContent(child.props.children);
3407
3527
  });
3408
3528
  }
3409
3529
  function appendFooterToActiveTabsContent(children, activeTab, footer) {
3410
- return React18.Children.map(children, (child) => {
3530
+ return React20.Children.map(children, (child) => {
3411
3531
  if (isTabsContentChild(child)) {
3412
3532
  if (child.props.tabKey !== activeTab || !footer) return child;
3413
- return React18.cloneElement(
3533
+ return React20.cloneElement(
3414
3534
  child,
3415
3535
  void 0,
3416
- /* @__PURE__ */ jsxs18(Fragment8, { children: [
3536
+ /* @__PURE__ */ jsxs18(Fragment9, { children: [
3417
3537
  child.props.children,
3418
3538
  /* @__PURE__ */ jsx19("div", { "data-slot": "detail-layout-footer", className: "min-w-0", children: footer })
3419
3539
  ] })
3420
3540
  );
3421
3541
  }
3422
- if (React18.isValidElement(child)) {
3423
- return React18.cloneElement(
3542
+ if (React20.isValidElement(child)) {
3543
+ return React20.cloneElement(
3424
3544
  child,
3425
3545
  void 0,
3426
3546
  appendFooterToActiveTabsContent(child.props.children, activeTab, footer)
@@ -3429,7 +3549,7 @@ function appendFooterToActiveTabsContent(children, activeTab, footer) {
3429
3549
  return child;
3430
3550
  });
3431
3551
  }
3432
- var DetailLayout = React18.forwardRef(
3552
+ var DetailLayout = React20.forwardRef(
3433
3553
  ({
3434
3554
  className,
3435
3555
  header,
@@ -3495,7 +3615,7 @@ var DetailLayout = React18.forwardRef(
3495
3615
  baseId,
3496
3616
  forceMount: true,
3497
3617
  hidden: tab.key !== activeTab,
3498
- children: tab.key === activeTab ? /* @__PURE__ */ jsxs18(Fragment8, { children: [
3618
+ children: tab.key === activeTab ? /* @__PURE__ */ jsxs18(Fragment9, { children: [
3499
3619
  body,
3500
3620
  footer ? /* @__PURE__ */ jsx19("div", { "data-slot": "detail-layout-footer", className: "min-w-0", children: footer }) : null
3501
3621
  ] }) : null
@@ -3503,7 +3623,7 @@ var DetailLayout = React18.forwardRef(
3503
3623
  tab.key
3504
3624
  ))
3505
3625
  }
3506
- ) : /* @__PURE__ */ jsxs18(Fragment8, { children: [
3626
+ ) : /* @__PURE__ */ jsxs18(Fragment9, { children: [
3507
3627
  body,
3508
3628
  footer ? /* @__PURE__ */ jsx19("div", { "data-slot": "detail-layout-footer", className: "min-w-0", children: footer }) : null
3509
3629
  ] })
@@ -3515,7 +3635,7 @@ var DetailLayout = React18.forwardRef(
3515
3635
  DetailLayout.displayName = "DetailLayout";
3516
3636
 
3517
3637
  // src/components/ui/form-layout.tsx
3518
- import * as React19 from "react";
3638
+ import * as React21 from "react";
3519
3639
  import { ChevronDown as ChevronDown3 } from "lucide-react";
3520
3640
  import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
3521
3641
  function FormLayoutSectionBlock({
@@ -3528,7 +3648,7 @@ function FormLayoutSectionBlock({
3528
3648
  const isEditorSection = section.id === editorSectionId;
3529
3649
  const resolvedColumns = isEditorSection ? 1 : section.columns ?? 1;
3530
3650
  const isCollapsible = Boolean(section.collapsible);
3531
- const [isOpen, setIsOpen] = React19.useState(section.defaultOpen ?? true);
3651
+ const [isOpen, setIsOpen] = React21.useState(section.defaultOpen ?? true);
3532
3652
  const contentId = `${section.id}-content`;
3533
3653
  const titleId = `${section.id}-title`;
3534
3654
  const sectionHeader = /* @__PURE__ */ jsxs19("div", { className: "flex min-w-0 flex-col gap-[var(--space-2)] sm:flex-row sm:items-start sm:justify-between", children: [
@@ -3615,7 +3735,7 @@ function FormLayoutSectionBlock({
3615
3735
  }
3616
3736
  );
3617
3737
  }
3618
- var FormLayout = React19.forwardRef(
3738
+ var FormLayout = React21.forwardRef(
3619
3739
  ({
3620
3740
  className,
3621
3741
  header,
@@ -3674,11 +3794,11 @@ var FormLayout = React19.forwardRef(
3674
3794
  FormLayout.displayName = "FormLayout";
3675
3795
 
3676
3796
  // src/components/ui/dialog.tsx
3677
- import * as React26 from "react";
3797
+ import * as React28 from "react";
3678
3798
  import { Dialog as DialogPrimitive3 } from "radix-ui";
3679
3799
 
3680
3800
  // src/lib/use-overlay-action.ts
3681
- import * as React20 from "react";
3801
+ import * as React22 from "react";
3682
3802
  function useOverlayAction({
3683
3803
  action,
3684
3804
  onOpenChange,
@@ -3686,10 +3806,10 @@ function useOverlayAction({
3686
3806
  disabled = false,
3687
3807
  onError
3688
3808
  }) {
3689
- const [pending, setPending] = React20.useState(false);
3690
- const busyRef = React20.useRef(false);
3809
+ const [pending, setPending] = React22.useState(false);
3810
+ const busyRef = React22.useRef(false);
3691
3811
  const isBusy = loading || pending;
3692
- const guardOpenChange = React20.useCallback(
3812
+ const guardOpenChange = React22.useCallback(
3693
3813
  (nextOpen) => {
3694
3814
  if (!nextOpen && isBusy) {
3695
3815
  return;
@@ -3698,7 +3818,7 @@ function useOverlayAction({
3698
3818
  },
3699
3819
  [isBusy, onOpenChange]
3700
3820
  );
3701
- const run = React20.useCallback(async () => {
3821
+ const run = React22.useCallback(async () => {
3702
3822
  if (busyRef.current || loading || disabled) {
3703
3823
  return;
3704
3824
  }
@@ -3719,11 +3839,11 @@ function useOverlayAction({
3719
3839
  }
3720
3840
 
3721
3841
  // src/lib/use-return-focus.ts
3722
- import * as React21 from "react";
3842
+ import * as React23 from "react";
3723
3843
  var closingOverlay = '[role="dialog"][data-state="closed"], [role="alertdialog"][data-state="closed"]';
3724
3844
  function useReturnFocus() {
3725
- const returnTo = React21.useRef(null);
3726
- const onOpenAutoFocus = React21.useCallback((event) => {
3845
+ const returnTo = React23.useRef(null);
3846
+ const onOpenAutoFocus = React23.useCallback((event) => {
3727
3847
  const active = document.activeElement;
3728
3848
  const content = event?.target instanceof HTMLElement ? event.target : null;
3729
3849
  const hasTrigger = !!content?.id && Array.from(document.querySelectorAll("[aria-controls]")).some(
@@ -3731,7 +3851,7 @@ function useReturnFocus() {
3731
3851
  );
3732
3852
  returnTo.current = !hasTrigger && active instanceof HTMLElement && active !== document.body ? active : null;
3733
3853
  }, []);
3734
- const onCloseAutoFocus = React21.useCallback((event) => {
3854
+ const onCloseAutoFocus = React23.useCallback((event) => {
3735
3855
  const target = returnTo.current;
3736
3856
  returnTo.current = null;
3737
3857
  if (!target?.isConnected) return;
@@ -3746,11 +3866,11 @@ function useReturnFocus() {
3746
3866
  }
3747
3867
 
3748
3868
  // src/components/ui/overlay-anatomy.tsx
3749
- import * as React24 from "react";
3869
+ import * as React26 from "react";
3750
3870
  import { AlertDialog as AlertDialogPrimitive, Dialog as DialogPrimitive2 } from "radix-ui";
3751
3871
 
3752
3872
  // src/components/ui/overlay-bottom-sheet.tsx
3753
- import * as React22 from "react";
3873
+ import * as React24 from "react";
3754
3874
 
3755
3875
  // src/components/ui/overlay-policy.ts
3756
3876
  var OVERLAY_DESKTOP_QUERY = "(min-width: 1024px)";
@@ -3824,11 +3944,11 @@ function clearOffset(surface) {
3824
3944
  surface?.style.removeProperty("transform");
3825
3945
  }
3826
3946
  function useSwipeDismiss({ enabled, onDismiss, surfaceRef, always = false }) {
3827
- const [dragging, setDragging] = React22.useState(false);
3828
- const drag = React22.useRef(null);
3829
- const dismiss = React22.useRef(onDismiss);
3947
+ const [dragging, setDragging] = React24.useState(false);
3948
+ const drag = React24.useRef(null);
3949
+ const dismiss = React24.useRef(onDismiss);
3830
3950
  dismiss.current = onDismiss;
3831
- const handleProps = React22.useMemo(() => {
3951
+ const handleProps = React24.useMemo(() => {
3832
3952
  if (!enabled) return {};
3833
3953
  const end = (event, release) => {
3834
3954
  const current = drag.current;
@@ -3931,7 +4051,7 @@ import { X as X2 } from "lucide-react";
3931
4051
  import { Dialog as DialogPrimitive } from "radix-ui";
3932
4052
 
3933
4053
  // src/components/ui/icon-button.tsx
3934
- import * as React23 from "react";
4054
+ import * as React25 from "react";
3935
4055
  import { cva as cva10 } from "class-variance-authority";
3936
4056
  import { ChevronDown as ChevronDown4, Loader2 as Loader23 } from "lucide-react";
3937
4057
  import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
@@ -4011,7 +4131,7 @@ var iconButtonBadgeVariants = cva10(
4011
4131
  }
4012
4132
  }
4013
4133
  );
4014
- var IconButton = React23.forwardRef(
4134
+ var IconButton = React25.forwardRef(
4015
4135
  ({
4016
4136
  className,
4017
4137
  appearance,
@@ -4173,7 +4293,8 @@ var overlaySize = {
4173
4293
  dialog: {
4174
4294
  sm: "max-w-[420px]",
4175
4295
  md: "max-w-[560px]",
4176
- lg: "max-w-[720px]"
4296
+ lg: "max-w-[720px]",
4297
+ xl: "max-w-[960px]"
4177
4298
  },
4178
4299
  sheet: {
4179
4300
  md: "lg:w-[480px] lg:max-w-[480px]",
@@ -4221,7 +4342,7 @@ var scrimMotionOf = {
4221
4342
  sheet: scrimMotion.responsive,
4222
4343
  menu: scrimMotion.sheet
4223
4344
  };
4224
- var OverlayScrimLayer = React24.forwardRef(
4345
+ var OverlayScrimLayer = React26.forwardRef(
4225
4346
  ({ scrim, kind, still, className, ...props }, ref) => {
4226
4347
  const Overlay = kind === "alert" ? AlertDialogPrimitive.Overlay : DialogPrimitive2.Overlay;
4227
4348
  return /* @__PURE__ */ jsx24(
@@ -4405,7 +4526,7 @@ var bottomSheet = {
4405
4526
  };
4406
4527
 
4407
4528
  // src/components/ui/sheet.tsx
4408
- import * as React25 from "react";
4529
+ import * as React27 from "react";
4409
4530
  import { Dialog as SheetPrimitive } from "radix-ui";
4410
4531
  import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
4411
4532
  var defaultSheetMotionConfig = {
@@ -4475,10 +4596,10 @@ function StructuredSheet({
4475
4596
  }) {
4476
4597
  const policy = OVERLAY_POLICY.sheet;
4477
4598
  const motionConfig = resolveSheetMotionConfig(motion);
4478
- const surfaceRef = React25.useRef(null);
4599
+ const surfaceRef = React27.useRef(null);
4479
4600
  const swipe = useSwipeDismiss({ enabled: policy.swipe, onDismiss: () => onOpenChange(false), surfaceRef });
4480
4601
  const returnFocus = useReturnFocus();
4481
- return /* @__PURE__ */ jsx25(SheetPrimitive.Root, { open, onOpenChange, children: /* @__PURE__ */ jsxs22(SheetPrimitive.Portal, { children: [
4602
+ return /* @__PURE__ */ jsx25(SheetPrimitive.Root, { open, onOpenChange, children: /* @__PURE__ */ jsx25(FormFieldBoundary, { children: /* @__PURE__ */ jsxs22(SheetPrimitive.Portal, { children: [
4482
4603
  /* @__PURE__ */ jsx25(OverlayScrimLayer, { kind: "sheet", scrim, still: motionConfig === false }),
4483
4604
  /* @__PURE__ */ jsxs22(
4484
4605
  SheetPrimitive.Content,
@@ -4519,7 +4640,7 @@ function StructuredSheet({
4519
4640
  ]
4520
4641
  }
4521
4642
  )
4522
- ] }) });
4643
+ ] }) }) });
4523
4644
  }
4524
4645
  function SheetTrigger({
4525
4646
  ...props
@@ -4534,7 +4655,7 @@ function SheetClose({
4534
4655
  function SheetPortal({
4535
4656
  ...props
4536
4657
  }) {
4537
- return /* @__PURE__ */ jsx25(SheetPrimitive.Portal, { "data-slot": "sheet-portal", ...props });
4658
+ return /* @__PURE__ */ jsx25(FormFieldBoundary, { children: /* @__PURE__ */ jsx25(SheetPrimitive.Portal, { "data-slot": "sheet-portal", ...props }) });
4538
4659
  }
4539
4660
  function SheetOverlay({
4540
4661
  className,
@@ -4704,11 +4825,11 @@ function SheetDescription({
4704
4825
  }
4705
4826
 
4706
4827
  // src/components/ui/dialog.tsx
4707
- import { Fragment as Fragment9, jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
4828
+ import { Fragment as Fragment10, jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
4708
4829
  function dialogMobileSheetStyle(style) {
4709
4830
  return getDefaultSheetMotionStyle(style);
4710
4831
  }
4711
- var DialogModalContext = React26.createContext(true);
4832
+ var DialogModalContext = React28.createContext(true);
4712
4833
  function Dialog(props) {
4713
4834
  if (props.title !== void 0) return /* @__PURE__ */ jsx26(StructuredDialog, { ...props });
4714
4835
  return /* @__PURE__ */ jsx26(DialogRoot, { ...props });
@@ -4740,7 +4861,7 @@ function StructuredDialog({
4740
4861
  onError
4741
4862
  });
4742
4863
  const returnFocus = useReturnFocus();
4743
- const surfaceRef = React26.useRef(null);
4864
+ const surfaceRef = React28.useRef(null);
4744
4865
  const swipe = useSwipeDismiss({ enabled: policy.swipe, onDismiss: () => guardOpenChange(false), surfaceRef });
4745
4866
  const body = /* @__PURE__ */ jsx26(OverlayBody, { kind: "dialog", className, children });
4746
4867
  const footerRow = formMode ? /* @__PURE__ */ jsxs23(OverlayFooter, { kind: "dialog", children: [
@@ -4758,7 +4879,7 @@ function StructuredDialog({
4758
4879
  ),
4759
4880
  /* @__PURE__ */ jsx26(Button, { type: "submit", appearance: "filled", tone: "primary", size: "lg", className: footerButtonHitAreaClassName, loading: isBusy, children: submitLabel })
4760
4881
  ] }) : footer != null ? /* @__PURE__ */ jsx26(OverlayFooter, { kind: "dialog", children: footer }) : null;
4761
- return /* @__PURE__ */ jsx26(DialogPrimitive3.Root, { open, onOpenChange: guardOpenChange, children: /* @__PURE__ */ jsxs23(DialogPrimitive3.Portal, { children: [
4882
+ return /* @__PURE__ */ jsx26(DialogPrimitive3.Root, { open, onOpenChange: guardOpenChange, children: /* @__PURE__ */ jsx26(FormFieldBoundary, { children: /* @__PURE__ */ jsxs23(DialogPrimitive3.Portal, { children: [
4762
4883
  /* @__PURE__ */ jsx26(OverlayScrimLayer, { kind: "dialog", scrim }),
4763
4884
  /* @__PURE__ */ jsxs23(
4764
4885
  DialogPrimitive3.Content,
@@ -4798,22 +4919,24 @@ function StructuredDialog({
4798
4919
  footerRow
4799
4920
  ]
4800
4921
  }
4801
- ) : /* @__PURE__ */ jsxs23(Fragment9, { children: [
4922
+ ) : /* @__PURE__ */ jsxs23(Fragment10, { children: [
4802
4923
  body,
4803
4924
  footerRow
4804
4925
  ] })
4805
4926
  ]
4806
4927
  }
4807
4928
  )
4808
- ] }) });
4929
+ ] }) }) });
4809
4930
  }
4810
4931
  function DialogRoot({ modal = true, ...props }) {
4811
4932
  return /* @__PURE__ */ jsx26(DialogModalContext.Provider, { value: modal, children: /* @__PURE__ */ jsx26(DialogPrimitive3.Root, { modal, ...props }) });
4812
4933
  }
4813
4934
  var DialogTrigger = DialogPrimitive3.Trigger;
4814
- var DialogPortal = DialogPrimitive3.Portal;
4935
+ function DialogPortal(props) {
4936
+ return /* @__PURE__ */ jsx26(FormFieldBoundary, { children: /* @__PURE__ */ jsx26(DialogPrimitive3.Portal, { ...props }) });
4937
+ }
4815
4938
  var DialogClose = DialogPrimitive3.Close;
4816
- var DialogOverlay = React26.forwardRef(({ className, ...props }, ref) => (
4939
+ var DialogOverlay = React28.forwardRef(({ className, ...props }, ref) => (
4817
4940
  // Position and scrim color come from the shared scrim (overlay-anatomy).
4818
4941
  /* @__PURE__ */ jsx26(
4819
4942
  OverlayScrimLayer,
@@ -4830,7 +4953,7 @@ var DialogOverlay = React26.forwardRef(({ className, ...props }, ref) => (
4830
4953
  )
4831
4954
  ));
4832
4955
  DialogOverlay.displayName = DialogPrimitive3.Overlay.displayName;
4833
- var DialogContent = React26.forwardRef(
4956
+ var DialogContent = React28.forwardRef(
4834
4957
  ({
4835
4958
  className,
4836
4959
  children,
@@ -4841,7 +4964,7 @@ var DialogContent = React26.forwardRef(
4841
4964
  onCloseAutoFocus,
4842
4965
  ...props
4843
4966
  }, ref) => {
4844
- const modal = React26.useContext(DialogModalContext);
4967
+ const modal = React28.useContext(DialogModalContext);
4845
4968
  const returnFocus = useReturnFocus();
4846
4969
  const handleOpenAutoFocus = (event) => {
4847
4970
  if (modal) returnFocus.onOpenAutoFocus(event);
@@ -4926,7 +5049,7 @@ var DialogFooter = ({
4926
5049
  }
4927
5050
  );
4928
5051
  DialogFooter.displayName = "DialogFooter";
4929
- var DialogTitle = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
5052
+ var DialogTitle = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
4930
5053
  DialogPrimitive3.Title,
4931
5054
  {
4932
5055
  ref,
@@ -4938,7 +5061,7 @@ var DialogTitle = React26.forwardRef(({ className, ...props }, ref) => /* @__PUR
4938
5061
  }
4939
5062
  ));
4940
5063
  DialogTitle.displayName = DialogPrimitive3.Title.displayName;
4941
- var DialogDescription = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
5064
+ var DialogDescription = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
4942
5065
  DialogPrimitive3.Description,
4943
5066
  {
4944
5067
  ref,
@@ -4947,7 +5070,7 @@ var DialogDescription = React26.forwardRef(({ className, ...props }, ref) => /*
4947
5070
  }
4948
5071
  ));
4949
5072
  DialogDescription.displayName = DialogPrimitive3.Description.displayName;
4950
- var DialogEyebrow = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
5073
+ var DialogEyebrow = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
4951
5074
  "p",
4952
5075
  {
4953
5076
  ref,
@@ -4959,7 +5082,8 @@ var DialogEyebrow = React26.forwardRef(({ className, ...props }, ref) => /* @__P
4959
5082
  }
4960
5083
  ));
4961
5084
  DialogEyebrow.displayName = "DialogEyebrow";
4962
- var DialogRawContent = DialogPrimitive3.Content;
5085
+ var DialogRawContent = React28.forwardRef((props, ref) => /* @__PURE__ */ jsx26(FormFieldBoundary, { children: /* @__PURE__ */ jsx26(DialogPrimitive3.Content, { ref, ...props }) }));
5086
+ DialogRawContent.displayName = DialogPrimitive3.Content.displayName;
4963
5087
 
4964
5088
  // src/components/ui/form-modal.tsx
4965
5089
  import { jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
@@ -4999,7 +5123,7 @@ function FormModal({
4999
5123
 
5000
5124
  // src/components/ui/alert-dialog.tsx
5001
5125
  import { AlertDialog as AlertDialogPrimitive2 } from "radix-ui";
5002
- import { Fragment as Fragment10, jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
5126
+ import { Fragment as Fragment11, jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
5003
5127
  function AlertDialogFrame({
5004
5128
  open,
5005
5129
  onOpenChange,
@@ -5023,7 +5147,7 @@ function AlertDialogFrame({
5023
5147
  control.focus();
5024
5148
  }
5025
5149
  };
5026
- return /* @__PURE__ */ jsx28(AlertDialogPrimitive2.Root, { open, onOpenChange, children: /* @__PURE__ */ jsxs25(AlertDialogPrimitive2.Portal, { children: [
5150
+ return /* @__PURE__ */ jsx28(AlertDialogPrimitive2.Root, { open, onOpenChange, children: /* @__PURE__ */ jsx28(FormFieldBoundary, { children: /* @__PURE__ */ jsxs25(AlertDialogPrimitive2.Portal, { children: [
5027
5151
  /* @__PURE__ */ jsx28(OverlayScrimLayer, { kind: "alert", scrim }),
5028
5152
  /* @__PURE__ */ jsxs25(
5029
5153
  AlertDialogPrimitive2.Content,
@@ -5038,7 +5162,7 @@ function AlertDialogFrame({
5038
5162
  ]
5039
5163
  }
5040
5164
  )
5041
- ] }) });
5165
+ ] }) }) });
5042
5166
  }
5043
5167
  function AlertDialog({
5044
5168
  open,
@@ -5063,7 +5187,7 @@ function AlertDialog({
5063
5187
  disabled: confirmDisabled,
5064
5188
  onError
5065
5189
  });
5066
- const footer = confirmLabel != null ? /* @__PURE__ */ jsxs25(Fragment10, { children: [
5190
+ const footer = confirmLabel != null ? /* @__PURE__ */ jsxs25(Fragment11, { children: [
5067
5191
  /* @__PURE__ */ jsx28(AlertDialogPrimitive2.Cancel, { asChild: true, children: /* @__PURE__ */ jsx28(Button, { appearance: "outline", tone: "neutral", size: "lg", className: footerButtonHitAreaClassName, disabled: isBusy, children: cancelLabel }) }),
5068
5192
  /* @__PURE__ */ jsx28(
5069
5193
  Button,
@@ -5133,15 +5257,15 @@ function InfoModal({
5133
5257
  }
5134
5258
 
5135
5259
  // src/components/ui/filter-toolbar.tsx
5136
- import * as React29 from "react";
5260
+ import * as React31 from "react";
5137
5261
  import { SlidersHorizontal } from "lucide-react";
5138
5262
 
5139
5263
  // src/components/ui/chip.tsx
5140
- import * as React27 from "react";
5264
+ import * as React29 from "react";
5141
5265
  import { cva as cva11 } from "class-variance-authority";
5142
5266
  import { X as X3 } from "lucide-react";
5143
5267
  import { Slot as Slot2 } from "radix-ui";
5144
- import { jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
5268
+ import { Fragment as Fragment12, jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
5145
5269
  var chipVariants = cva11(
5146
5270
  [
5147
5271
  "inline-flex w-fit shrink-0 items-center justify-center whitespace-nowrap",
@@ -5158,7 +5282,7 @@ var chipVariants = cva11(
5158
5282
  filter: "cursor-pointer",
5159
5283
  choice: "cursor-pointer",
5160
5284
  removable: "cursor-pointer",
5161
- // status-filter — 정적 표시 chip (display only, 클릭 affordance 없음).
5285
+ // status-filter — 정적 표시 chip (display only, 클릭 affordance 없음). onClick·pressed 없으면 span.
5162
5286
  /** @deprecated A read-only label is a Badge: neutral·muted → `neutral`, accent → `brand`, success → `success`, warning → `warning`, danger → `error`. */
5163
5287
  "status-filter": "cursor-default"
5164
5288
  },
@@ -5235,19 +5359,42 @@ var chipCountVariants = cva11(
5235
5359
  }
5236
5360
  }
5237
5361
  );
5238
- var Chip = React27.forwardRef(
5362
+ function ChipCount({
5363
+ count,
5364
+ tone,
5365
+ size
5366
+ }) {
5367
+ return /* @__PURE__ */ jsxs26(Fragment12, { children: [
5368
+ /* @__PURE__ */ jsx30(
5369
+ "span",
5370
+ {
5371
+ "aria-hidden": "true",
5372
+ "data-slot": "chip-count",
5373
+ "data-count-tone": tone,
5374
+ className: chipCountVariants({ tone, size }),
5375
+ children: count
5376
+ }
5377
+ ),
5378
+ /* @__PURE__ */ jsxs26("span", { className: "sr-only", children: [
5379
+ " ",
5380
+ count
5381
+ ] })
5382
+ ] });
5383
+ }
5384
+ var Chip = React29.forwardRef(
5239
5385
  ({
5240
5386
  className,
5241
5387
  variant = "filter",
5242
5388
  tone = "neutral",
5243
5389
  size = "md",
5244
- pressed = false,
5390
+ pressed: pressedProp,
5245
5391
  count,
5246
- removeLabel = "Remove",
5392
+ removeLabel = "\uC81C\uAC70",
5247
5393
  asChild = false,
5248
5394
  children,
5249
5395
  ...props
5250
5396
  }, ref) => {
5397
+ const pressed = pressedProp ?? false;
5251
5398
  const removable = variant === "removable";
5252
5399
  if (removable) {
5253
5400
  const {
@@ -5270,16 +5417,7 @@ var Chip = React27.forwardRef(
5270
5417
  ...spanProps,
5271
5418
  children: [
5272
5419
  /* @__PURE__ */ jsx30("span", { children }),
5273
- count !== void 0 ? /* @__PURE__ */ jsx30(
5274
- "span",
5275
- {
5276
- "aria-hidden": "true",
5277
- "data-slot": "chip-count",
5278
- "data-count-tone": tone,
5279
- className: chipCountVariants({ tone, size }),
5280
- children: count
5281
- }
5282
- ) : null,
5420
+ count !== void 0 ? /* @__PURE__ */ jsx30(ChipCount, { count, tone, size }) : null,
5283
5421
  /* @__PURE__ */ jsx30(
5284
5422
  "button",
5285
5423
  {
@@ -5297,6 +5435,32 @@ var Chip = React27.forwardRef(
5297
5435
  }
5298
5436
  );
5299
5437
  }
5438
+ if (variant === "status-filter" && !asChild && props.onClick === void 0 && pressedProp === void 0) {
5439
+ const {
5440
+ disabled: _disabled,
5441
+ type: _type,
5442
+ autoFocus: _af,
5443
+ form: _form,
5444
+ name: _name,
5445
+ value: _value,
5446
+ ...spanProps
5447
+ } = props;
5448
+ return /* @__PURE__ */ jsxs26(
5449
+ "span",
5450
+ {
5451
+ ref,
5452
+ "data-slot": "chip",
5453
+ "data-variant": variant,
5454
+ "data-tone": tone,
5455
+ className: cn(chipVariants({ variant, tone, size, pressed, className })),
5456
+ ...spanProps,
5457
+ children: [
5458
+ children,
5459
+ count !== void 0 ? /* @__PURE__ */ jsx30(ChipCount, { count, tone, size }) : null
5460
+ ]
5461
+ }
5462
+ );
5463
+ }
5300
5464
  const Comp = asChild ? Slot2.Root : "button";
5301
5465
  return /* @__PURE__ */ jsxs26(
5302
5466
  Comp,
@@ -5313,16 +5477,7 @@ var Chip = React27.forwardRef(
5313
5477
  ...props,
5314
5478
  children: [
5315
5479
  children,
5316
- count !== void 0 ? /* @__PURE__ */ jsx30(
5317
- "span",
5318
- {
5319
- "aria-hidden": "true",
5320
- "data-slot": "chip-count",
5321
- "data-count-tone": tone,
5322
- className: chipCountVariants({ tone, size }),
5323
- children: count
5324
- }
5325
- ) : null
5480
+ count !== void 0 ? /* @__PURE__ */ jsx30(ChipCount, { count, tone, size }) : null
5326
5481
  ]
5327
5482
  }
5328
5483
  );
@@ -5331,7 +5486,7 @@ var Chip = React27.forwardRef(
5331
5486
  Chip.displayName = "Chip";
5332
5487
 
5333
5488
  // src/components/ui/popover.tsx
5334
- import * as React28 from "react";
5489
+ import * as React30 from "react";
5335
5490
  import { Popover as PopoverPrimitive } from "radix-ui";
5336
5491
  import { jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
5337
5492
  function Popover({ modal = false, ...props }) {
@@ -5341,7 +5496,7 @@ var popoverArrowClassName = "fill-[var(--bg-surface)] stroke-[var(--border)] [&>
5341
5496
  var PopoverTrigger = PopoverPrimitive.Trigger;
5342
5497
  var PopoverAnchor = PopoverPrimitive.Anchor;
5343
5498
  var PopoverClose = PopoverPrimitive.Close;
5344
- var PopoverContent = React28.forwardRef(({ className, align = "center", sideOffset = 8, collisionPadding = 8, showArrow = false, children, ...props }, ref) => /* @__PURE__ */ jsx31(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsxs27(
5499
+ var PopoverContent = React30.forwardRef(({ className, align = "center", sideOffset = 8, collisionPadding = 8, showArrow = false, children, ...props }, ref) => /* @__PURE__ */ jsx31(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsxs27(
5345
5500
  PopoverPrimitive.Content,
5346
5501
  {
5347
5502
  ref,
@@ -5364,7 +5519,7 @@ var PopoverContent = React28.forwardRef(({ className, align = "center", sideOffs
5364
5519
  ),
5365
5520
  ...props,
5366
5521
  children: [
5367
- children,
5522
+ /* @__PURE__ */ jsx31(FormFieldBoundary, { children }),
5368
5523
  showArrow ? /* @__PURE__ */ jsx31(
5369
5524
  PopoverPrimitive.Arrow,
5370
5525
  {
@@ -5378,7 +5533,7 @@ var PopoverContent = React28.forwardRef(({ className, align = "center", sideOffs
5378
5533
  }
5379
5534
  ) }));
5380
5535
  PopoverContent.displayName = PopoverPrimitive.Content.displayName;
5381
- var PopoverArrow = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx31(
5536
+ var PopoverArrow = React30.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx31(
5382
5537
  PopoverPrimitive.Arrow,
5383
5538
  {
5384
5539
  ref,
@@ -5392,7 +5547,7 @@ var PopoverArrow = React28.forwardRef(({ className, ...props }, ref) => /* @__PU
5392
5547
  PopoverArrow.displayName = PopoverPrimitive.Arrow.displayName;
5393
5548
 
5394
5549
  // src/components/ui/filter-toolbar.tsx
5395
- import { Fragment as Fragment11, jsx as jsx32, jsxs as jsxs28 } from "react/jsx-runtime";
5550
+ import { Fragment as Fragment14, jsx as jsx32, jsxs as jsxs28 } from "react/jsx-runtime";
5396
5551
  var collapsibleClassNames = {
5397
5552
  sm: {
5398
5553
  inline: "hidden @[640px]:flex",
@@ -5411,30 +5566,71 @@ var collapsibleClassNames = {
5411
5566
  trigger: "hidden"
5412
5567
  }
5413
5568
  };
5414
- var FilterToolbar = React29.forwardRef(
5569
+ var gridCollapsibleClassNames = {
5570
+ sm: { inline: "hidden", trigger: "" },
5571
+ md: { inline: "hidden", trigger: "" },
5572
+ lg: { inline: "hidden", trigger: "" },
5573
+ never: { inline: "flex @[640px]:hidden", trigger: "hidden @[640px]:inline" }
5574
+ };
5575
+ var gridSearchClassName = "order-1 min-w-[min(160px,100%)] max-w-full flex-[1_1_0%] @[640px]:min-w-0 @[640px]:flex-[3_1_0%]";
5576
+ var gridFiltersClassName = "order-3 flex min-w-0 flex-[1_0_100%] flex-wrap items-center gap-[var(--space-2)] @[640px]:contents";
5577
+ var gridCellClassName = cn(
5578
+ "contents @[640px]:block @[640px]:order-3 @[640px]:min-w-0 @[640px]:flex-[3_1_0%]",
5579
+ "@[640px]:[&:has([data-slot=select-trigger])]:flex-[2_1_0%]",
5580
+ "@[640px]:[&:has(>[data-slot=chip])]:flex-none",
5581
+ // A Chip group is named: a role="group" child that holds the Chips. A control that shows its
5582
+ // values as Chips keeps the default share.
5583
+ "@[640px]:[&:has(>[role=group]>[data-slot=chip])]:flex-none",
5584
+ // The control fills its cell, through a width the consumer put on a wrapper.
5585
+ "@[640px]:[&>:not([data-slot=chip])]:w-full @[640px]:[&_[data-slot=select-trigger]]:w-full"
5586
+ );
5587
+ var MAX_GRID_FILTERS = 3;
5588
+ var focusableSelector = "input, button, [tabindex]:not([tabindex='-1'])";
5589
+ function canTakeFocus(element) {
5590
+ return Boolean(element && element.getClientRects().length > 0 && !element.matches(":disabled"));
5591
+ }
5592
+ function filterCells(node, prefix = "") {
5593
+ return React31.Children.toArray(node).flatMap((child, index) => {
5594
+ const key = `${prefix}${React31.isValidElement(child) ? child.key : index}`;
5595
+ return React31.isValidElement(child) && child.type === React31.Fragment ? filterCells(child.props.children, `${key}/`) : [{ key, cell: child }];
5596
+ });
5597
+ }
5598
+ function warnGridFilters(count) {
5599
+ if (typeof process === "undefined" || process.env.NODE_ENV === "production") return;
5600
+ console.warn(
5601
+ `FilterToolbar: layout="grid" fits ${MAX_GRID_FILTERS} filters on the line, got ${count}. Move the rest to \`collapsible\`.`
5602
+ );
5603
+ }
5604
+ var FilterToolbar = React31.forwardRef(
5415
5605
  ({
5416
5606
  className,
5417
5607
  search,
5418
5608
  filters,
5419
5609
  collapsible,
5420
5610
  collapseBelow = "lg",
5421
- activeFilterCount = 0,
5611
+ activeFilterCount: activeFilterCountProp,
5422
5612
  onClearFilters,
5423
5613
  collapsedLabel = "\uD544\uD130",
5424
5614
  resultSummary,
5425
5615
  clearAction,
5426
5616
  actions,
5617
+ layout = "flow",
5618
+ appliedFilters,
5427
5619
  ...props
5428
5620
  }, ref) => {
5429
- const [rootElement, setRootElement] = React29.useState(
5621
+ const [rootElement, setRootElement] = React31.useState(
5430
5622
  null
5431
5623
  );
5432
- const [containerWidth, setContainerWidth] = React29.useState(
5624
+ const [containerWidth, setContainerWidth] = React31.useState(
5433
5625
  null
5434
5626
  );
5435
- const [overlayOpen, setOverlayOpen] = React29.useState(false);
5436
- const triggerRef = React29.useRef(null);
5437
- const setRootRefs = React29.useCallback(
5627
+ const [overlayOpen, setOverlayOpen] = React31.useState(false);
5628
+ const triggerRef = React31.useRef(null);
5629
+ const rowRef = React31.useRef(null);
5630
+ const chipsRef = React31.useRef(null);
5631
+ const chipRemoveRefs = React31.useRef(/* @__PURE__ */ new Map());
5632
+ const pendingFocusRef = React31.useRef(null);
5633
+ const setRootRefs = React31.useCallback(
5438
5634
  (element) => {
5439
5635
  setRootElement(element);
5440
5636
  if (typeof ref === "function") ref(element);
@@ -5442,7 +5638,7 @@ var FilterToolbar = React29.forwardRef(
5442
5638
  },
5443
5639
  [ref]
5444
5640
  );
5445
- React29.useEffect(() => {
5641
+ React31.useEffect(() => {
5446
5642
  if (!rootElement) return;
5447
5643
  const updateWidth = () => {
5448
5644
  setContainerWidth(rootElement.getBoundingClientRect().width);
@@ -5453,15 +5649,53 @@ var FilterToolbar = React29.forwardRef(
5453
5649
  observer.observe(rootElement);
5454
5650
  return () => observer.disconnect();
5455
5651
  }, [rootElement]);
5456
- const handleOverlayOpenChange = React29.useCallback((open) => {
5652
+ const handleOverlayOpenChange = React31.useCallback((open) => {
5457
5653
  setOverlayOpen(open);
5458
5654
  if (!open) queueMicrotask(() => triggerRef.current?.focus());
5459
5655
  }, []);
5460
- const hasMeta = Boolean(resultSummary || clearAction || actions);
5656
+ const isGrid = layout === "grid";
5657
+ const gridCells = isGrid ? filterCells(filters) : [];
5658
+ const filterCellCount = gridCells.length;
5659
+ React31.useEffect(() => {
5660
+ if (filterCellCount > MAX_GRID_FILTERS) warnGridFilters(filterCellCount);
5661
+ }, [filterCellCount]);
5662
+ React31.useEffect(() => {
5663
+ const ownerDocument = rootElement?.ownerDocument;
5664
+ if (!ownerDocument) return;
5665
+ const dropOutside = (event) => {
5666
+ if (!chipsRef.current?.contains(event.target)) pendingFocusRef.current = null;
5667
+ };
5668
+ ownerDocument.addEventListener("focusin", dropOutside);
5669
+ ownerDocument.addEventListener("pointerdown", dropOutside, true);
5670
+ return () => {
5671
+ ownerDocument.removeEventListener("focusin", dropOutside);
5672
+ ownerDocument.removeEventListener("pointerdown", dropOutside, true);
5673
+ };
5674
+ }, [rootElement]);
5675
+ React31.useEffect(() => {
5676
+ const request = pendingFocusRef.current;
5677
+ if (!request) return;
5678
+ const present = new Set(appliedFilters?.map((filter) => filter.key));
5679
+ if (request.removed.some((key) => present.has(key))) return;
5680
+ pendingFocusRef.current = null;
5681
+ const active = rootElement?.ownerDocument.activeElement;
5682
+ if (active && active !== rootElement.ownerDocument.body) return;
5683
+ const candidates = [
5684
+ ...request.next.map((key) => chipRemoveRefs.current.get(key)),
5685
+ triggerRef.current,
5686
+ ...rowRef.current?.querySelectorAll(focusableSelector) ?? []
5687
+ ];
5688
+ candidates.find(canTakeFocus)?.focus();
5689
+ }, [appliedFilters, rootElement]);
5461
5690
  const hasControls = Boolean(search || filters || collapsible);
5691
+ const hasMeta = Boolean(
5692
+ resultSummary || clearAction || actions && !hasControls
5693
+ );
5694
+ const activeFilterCount = activeFilterCountProp ?? appliedFilters?.length ?? 0;
5462
5695
  const hasAppliedFilters = activeFilterCount > 0;
5696
+ const hasAppliedChips = Boolean(appliedFilters && appliedFilters.length > 0);
5463
5697
  const usesSheet = containerWidth !== null && containerWidth < 640;
5464
- const collapseClasses = collapsibleClassNames[collapseBelow];
5698
+ const collapseClasses = (isGrid ? gridCollapsibleClassNames : collapsibleClassNames)[collapseBelow];
5465
5699
  const collapseTriggerLabel = hasAppliedFilters ? `${collapsedLabel}, ${activeFilterCount}\uAC1C \uC801\uC6A9` : collapsedLabel;
5466
5700
  const clearFiltersButton = onClearFilters ? /* @__PURE__ */ jsx32(
5467
5701
  "button",
@@ -5521,6 +5755,7 @@ var FilterToolbar = React29.forwardRef(
5521
5755
  "div",
5522
5756
  {
5523
5757
  ref: setRootRefs,
5758
+ role: "group",
5524
5759
  "data-slot": "filter-toolbar",
5525
5760
  className: cn(
5526
5761
  "@container flex w-full flex-col gap-[var(--space-2)] text-foreground",
@@ -5531,14 +5766,18 @@ var FilterToolbar = React29.forwardRef(
5531
5766
  hasControls ? /* @__PURE__ */ jsxs28(
5532
5767
  "div",
5533
5768
  {
5769
+ ref: rowRef,
5534
5770
  "data-slot": "filter-toolbar-row",
5535
- className: "flex min-h-[32px] w-full flex-wrap items-center justify-start gap-x-[var(--space-2)] gap-y-[var(--space-2)]",
5771
+ className: cn(
5772
+ "flex min-h-[32px] w-full flex-wrap items-center justify-start gap-x-[var(--space-2)] gap-y-[var(--space-2)]",
5773
+ isGrid && "@[640px]:flex-nowrap"
5774
+ ),
5536
5775
  children: [
5537
5776
  search ? /* @__PURE__ */ jsx32(
5538
5777
  "div",
5539
5778
  {
5540
5779
  "data-slot": "filter-toolbar-search",
5541
- className: "order-1 min-w-0 max-w-full flex-[1_1_auto] @[640px]:flex-[1_1_280px]",
5780
+ className: isGrid ? gridSearchClassName : "order-1 min-w-[min(160px,100%)] max-w-full flex-[1_1_0%] @[640px]:min-w-0 @[640px]:flex-[1_1_280px]",
5542
5781
  children: search
5543
5782
  }
5544
5783
  ) : null,
@@ -5565,8 +5804,16 @@ var FilterToolbar = React29.forwardRef(
5565
5804
  "div",
5566
5805
  {
5567
5806
  "data-slot": "filter-toolbar-filters",
5568
- className: "order-3 flex min-w-0 flex-[1_0_100%] flex-wrap items-center gap-[var(--space-2)] @[640px]:flex-[2_1_auto]",
5569
- children: filters
5807
+ className: isGrid ? gridFiltersClassName : "order-3 flex min-w-0 flex-[1_0_100%] flex-wrap items-center gap-[var(--space-2)] @[640px]:flex-[2_1_auto]",
5808
+ children: isGrid ? gridCells.map(({ key, cell }) => /* @__PURE__ */ jsx32(
5809
+ "div",
5810
+ {
5811
+ "data-slot": "filter-toolbar-cell",
5812
+ className: gridCellClassName,
5813
+ children: cell
5814
+ },
5815
+ key
5816
+ )) : filters
5570
5817
  }
5571
5818
  ) : null,
5572
5819
  collapsible && !overlayOpen ? /* @__PURE__ */ jsx32(
@@ -5579,6 +5826,14 @@ var FilterToolbar = React29.forwardRef(
5579
5826
  ),
5580
5827
  children: collapsible
5581
5828
  }
5829
+ ) : null,
5830
+ actions ? /* @__PURE__ */ jsx32(
5831
+ "div",
5832
+ {
5833
+ "data-slot": "filter-toolbar-actions",
5834
+ className: "order-6 ml-auto flex shrink-0 flex-wrap items-center gap-[var(--space-2)]",
5835
+ children: actions
5836
+ }
5582
5837
  ) : null
5583
5838
  ]
5584
5839
  }
@@ -5593,18 +5848,72 @@ var FilterToolbar = React29.forwardRef(
5593
5848
  children: collapsedContent
5594
5849
  }
5595
5850
  ) : null,
5851
+ hasAppliedChips ? /* @__PURE__ */ jsxs28(
5852
+ "div",
5853
+ {
5854
+ ref: chipsRef,
5855
+ role: "group",
5856
+ "aria-label": collapsedLabel,
5857
+ "data-slot": "filter-toolbar-applied-chips",
5858
+ className: "hidden flex-wrap items-center gap-[var(--space-2)] @[640px]:flex",
5859
+ children: [
5860
+ appliedFilters.map((filter, index) => /* @__PURE__ */ jsx32(
5861
+ Chip,
5862
+ {
5863
+ ref: (button) => {
5864
+ if (button) chipRemoveRefs.current.set(filter.key, button);
5865
+ else chipRemoveRefs.current.delete(filter.key);
5866
+ },
5867
+ variant: "removable",
5868
+ size: "md",
5869
+ removeLabel: `${filter.label} \uC81C\uAC70`,
5870
+ onClick: () => {
5871
+ pendingFocusRef.current = {
5872
+ removed: [filter.key],
5873
+ next: [appliedFilters[index + 1]?.key, appliedFilters[index - 1]?.key].filter(
5874
+ (key) => key !== void 0
5875
+ )
5876
+ };
5877
+ filter.onRemove();
5878
+ },
5879
+ children: filter.label
5880
+ },
5881
+ filter.key
5882
+ )),
5883
+ onClearFilters ? /* @__PURE__ */ jsx32(
5884
+ "button",
5885
+ {
5886
+ type: "button",
5887
+ "data-slot": "filter-toolbar-clear-filters",
5888
+ className: "cursor-pointer border-0 bg-transparent p-0 text-body-sm font-medium text-text-secondary no-underline",
5889
+ onClick: () => {
5890
+ pendingFocusRef.current = {
5891
+ removed: appliedFilters.map((filter) => filter.key),
5892
+ next: []
5893
+ };
5894
+ onClearFilters();
5895
+ },
5896
+ children: "\uD574\uC81C"
5897
+ }
5898
+ ) : null
5899
+ ]
5900
+ }
5901
+ ) : null,
5596
5902
  hasAppliedFilters ? /* @__PURE__ */ jsxs28(
5597
5903
  "div",
5598
5904
  {
5599
5905
  "data-slot": "filter-toolbar-applied",
5600
- className: "flex items-center gap-[var(--space-1)] text-[11px] text-text-tertiary",
5906
+ className: cn(
5907
+ "flex items-center gap-[var(--space-1)] text-[11px] text-text-tertiary",
5908
+ hasAppliedChips && "@[640px]:hidden"
5909
+ ),
5601
5910
  children: [
5602
5911
  /* @__PURE__ */ jsxs28("span", { children: [
5603
5912
  "\uD544\uD130 ",
5604
5913
  activeFilterCount,
5605
5914
  "\uAC1C \uC801\uC6A9"
5606
5915
  ] }),
5607
- onClearFilters ? /* @__PURE__ */ jsxs28(Fragment11, { children: [
5916
+ onClearFilters ? /* @__PURE__ */ jsxs28(Fragment14, { children: [
5608
5917
  /* @__PURE__ */ jsx32("span", { "aria-hidden": "true", children: " \xB7 " }),
5609
5918
  /* @__PURE__ */ jsx32(
5610
5919
  "button",
@@ -5634,7 +5943,7 @@ var FilterToolbar = React29.forwardRef(
5634
5943
  }
5635
5944
  ) : null,
5636
5945
  clearAction ? /* @__PURE__ */ jsx32("div", { "data-slot": "filter-toolbar-clear", className: "shrink-0", children: clearAction }) : null,
5637
- actions ? /* @__PURE__ */ jsx32(
5946
+ actions && !hasControls ? /* @__PURE__ */ jsx32(
5638
5947
  "div",
5639
5948
  {
5640
5949
  "data-slot": "filter-toolbar-actions",
@@ -5653,12 +5962,12 @@ var FilterToolbar = React29.forwardRef(
5653
5962
  FilterToolbar.displayName = "FilterToolbar";
5654
5963
 
5655
5964
  // src/components/ui/data-table.tsx
5656
- import * as React33 from "react";
5965
+ import * as React35 from "react";
5657
5966
  import { ChevronDown as ChevronDown5, ChevronRight as ChevronRight3, ChevronUp as ChevronUp2, ChevronsUpDown, EllipsisVertical } from "lucide-react";
5658
5967
  import { cva as cva13 } from "class-variance-authority";
5659
5968
 
5660
5969
  // src/components/ui/action-menu.tsx
5661
- import * as React30 from "react";
5970
+ import * as React32 from "react";
5662
5971
  import { Dialog as DialogPrimitive4, Slot as Slot3 } from "radix-ui";
5663
5972
 
5664
5973
  // src/components/ui/dropdown-menu.tsx
@@ -5673,7 +5982,7 @@ function DropdownMenu({
5673
5982
  function DropdownMenuPortal({
5674
5983
  ...props
5675
5984
  }) {
5676
- return /* @__PURE__ */ jsx33(DropdownMenuPrimitive.Portal, { "data-slot": "dropdown-menu-portal", ...props });
5985
+ return /* @__PURE__ */ jsx33(FormFieldBoundary, { children: /* @__PURE__ */ jsx33(DropdownMenuPrimitive.Portal, { "data-slot": "dropdown-menu-portal", ...props }) });
5677
5986
  }
5678
5987
  function DropdownMenuTrigger({
5679
5988
  ...props
@@ -5691,7 +6000,7 @@ function DropdownMenuContent({
5691
6000
  sideOffset = 4,
5692
6001
  ...props
5693
6002
  }) {
5694
- return /* @__PURE__ */ jsx33(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx33(
6003
+ return /* @__PURE__ */ jsx33(FormFieldBoundary, { children: /* @__PURE__ */ jsx33(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx33(
5695
6004
  DropdownMenuPrimitive.Content,
5696
6005
  {
5697
6006
  "data-slot": "dropdown-menu-content",
@@ -5709,7 +6018,7 @@ function DropdownMenuContent({
5709
6018
  ),
5710
6019
  ...props
5711
6020
  }
5712
- ) });
6021
+ ) }) });
5713
6022
  }
5714
6023
  function DropdownMenuGroup({
5715
6024
  ...props
@@ -5892,7 +6201,7 @@ function DropdownMenuSubContent({
5892
6201
  className,
5893
6202
  ...props
5894
6203
  }) {
5895
- return /* @__PURE__ */ jsx33(
6204
+ return /* @__PURE__ */ jsx33(FormFieldBoundary, { children: /* @__PURE__ */ jsx33(
5896
6205
  DropdownMenuPrimitive.SubContent,
5897
6206
  {
5898
6207
  "data-slot": "dropdown-menu-sub-content",
@@ -5908,20 +6217,23 @@ function DropdownMenuSubContent({
5908
6217
  ),
5909
6218
  ...props
5910
6219
  }
5911
- );
6220
+ ) });
5912
6221
  }
5913
6222
 
5914
6223
  // src/components/ui/action-menu.tsx
5915
- import { Fragment as Fragment13, jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
6224
+ import { Fragment as Fragment16, jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
5916
6225
  var sheetRowClassName = cn(
5917
6226
  "group flex min-h-12 w-full cursor-pointer items-center gap-[var(--space-3)] px-[var(--space-4)] py-[var(--space-2)] text-left",
5918
6227
  "border-t border-[var(--border-subtle)] text-[13px] font-medium leading-normal text-text-primary",
5919
6228
  "transition-colors motion-reduce:transition-none hover:bg-[var(--action-hover)]",
5920
6229
  "focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[var(--focus-ring)]",
5921
6230
  "enabled:data-[destructive]:text-[var(--semantic-error-fg)]",
5922
- "disabled:cursor-not-allowed disabled:bg-[var(--action-disabled-bg)] disabled:text-text-disabled"
6231
+ "disabled:cursor-not-allowed disabled:bg-[var(--action-disabled-bg)] disabled:text-text-disabled",
6232
+ "aria-disabled:cursor-not-allowed"
5923
6233
  );
5924
6234
  var sheetRowDescriptionClassName = "block text-[12px] font-normal text-text-secondary group-disabled:text-text-disabled";
6235
+ var unavailableClassName = "text-text-disabled";
6236
+ var reasonClassName = "block text-[12px] font-normal leading-normal text-text-tertiary";
5925
6237
  var sheetGroupLabelClassName = "px-[var(--space-4)] pt-[var(--space-3)] pb-[var(--space-2)] text-[12px] font-semibold leading-normal text-text-tertiary";
5926
6238
  var sheetGroupSeparatorClassName = "h-[var(--space-2)] bg-[var(--bg-inset)]";
5927
6239
  function ActionMenuSheet({
@@ -5934,9 +6246,9 @@ function ActionMenuSheet({
5934
6246
  onOpenAutoFocus,
5935
6247
  onCloseAutoFocus
5936
6248
  }) {
5937
- const pendingRef = React30.useRef(null);
5938
- const surfaceRef = React30.useRef(null);
5939
- const labelId = React30.useId();
6249
+ const pendingRef = React32.useRef(null);
6250
+ const surfaceRef = React32.useRef(null);
6251
+ const labelId = React32.useId();
5940
6252
  const handleOpenChange = (nextOpen) => {
5941
6253
  pendingRef.current = null;
5942
6254
  onOpenChange(nextOpen);
@@ -5964,7 +6276,7 @@ function ActionMenuSheet({
5964
6276
  pendingRef.current = null;
5965
6277
  item?.onSelect();
5966
6278
  };
5967
- return /* @__PURE__ */ jsx34(DialogPrimitive4.Root, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs30(DialogPrimitive4.Portal, { children: [
6279
+ return /* @__PURE__ */ jsx34(DialogPrimitive4.Root, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsx34(FormFieldBoundary, { children: /* @__PURE__ */ jsxs30(DialogPrimitive4.Portal, { children: [
5968
6280
  /* @__PURE__ */ jsx34(OverlayScrimLayer, { kind: "menu" }),
5969
6281
  /* @__PURE__ */ jsxs30(
5970
6282
  DialogPrimitive4.Content,
@@ -5987,27 +6299,38 @@ function ActionMenuSheet({
5987
6299
  dragHandleProps: swipe.handleProps
5988
6300
  }
5989
6301
  ),
5990
- /* @__PURE__ */ jsx34(OverlayBody, { kind: "menu", children: groups.map((group, index) => /* @__PURE__ */ jsxs30(React30.Fragment, { children: [
6302
+ /* @__PURE__ */ jsx34(OverlayBody, { kind: "menu", children: groups.map((group, index) => /* @__PURE__ */ jsxs30(React32.Fragment, { children: [
5991
6303
  index > 0 ? /* @__PURE__ */ jsx34("div", { role: "separator", className: sheetGroupSeparatorClassName }) : null,
5992
6304
  /* @__PURE__ */ jsxs30("div", { role: "group", "aria-labelledby": group.label ? `${labelId}-${index}` : void 0, children: [
5993
6305
  group.label ? /* @__PURE__ */ jsx34("div", { id: `${labelId}-${index}`, className: sheetGroupLabelClassName, children: group.label }) : null,
5994
- group.items.map((item) => {
6306
+ group.items.map((item, itemIndex) => {
5995
6307
  const Icon = item.icon;
6308
+ const reason = item.disabledReason || void 0;
6309
+ const reasonId = `${labelId}-${index}-${itemIndex}-reason`;
6310
+ const itemLabelId = `${labelId}-${index}-${itemIndex}-label`;
5996
6311
  return /* @__PURE__ */ jsxs30(
5997
6312
  "button",
5998
6313
  {
5999
6314
  type: "button",
6000
6315
  "data-slot": "action-menu-item",
6001
- "data-destructive": item.destructive ? "" : void 0,
6316
+ "data-destructive": item.destructive && !reason ? "" : void 0,
6002
6317
  className: sheetRowClassName,
6003
- disabled: item.disabled,
6004
- onClick: () => handleSelect(item),
6318
+ disabled: item.disabled && !reason,
6319
+ "aria-disabled": reason ? true : void 0,
6320
+ "aria-labelledby": reason ? itemLabelId : void 0,
6321
+ "aria-describedby": reason ? reasonId : void 0,
6322
+ onClick: () => {
6323
+ if (!reason) handleSelect(item);
6324
+ },
6005
6325
  children: [
6006
- Icon ? /* @__PURE__ */ jsx34(Icon, { "aria-hidden": true, size: 17, strokeWidth: 1.75, className: "shrink-0" }) : null,
6007
- /* @__PURE__ */ jsxs30("span", { className: "min-w-0 flex-1 break-keep", children: [
6326
+ Icon ? /* @__PURE__ */ jsx34(Icon, { "aria-hidden": true, size: 17, strokeWidth: 1.75, className: cn("shrink-0", reason && unavailableClassName) }) : null,
6327
+ /* @__PURE__ */ jsx34("span", { className: "min-w-0 flex-1 break-keep", children: reason ? /* @__PURE__ */ jsxs30(Fragment16, { children: [
6328
+ /* @__PURE__ */ jsx34("span", { id: itemLabelId, className: unavailableClassName, children: item.label }),
6329
+ /* @__PURE__ */ jsx34("span", { id: reasonId, className: reasonClassName, children: reason })
6330
+ ] }) : /* @__PURE__ */ jsxs30(Fragment16, { children: [
6008
6331
  item.label,
6009
6332
  item.description ? /* @__PURE__ */ jsx34("span", { className: sheetRowDescriptionClassName, children: item.description }) : null
6010
- ] })
6333
+ ] }) })
6011
6334
  ]
6012
6335
  },
6013
6336
  item.id
@@ -6018,11 +6341,53 @@ function ActionMenuSheet({
6018
6341
  ]
6019
6342
  }
6020
6343
  )
6021
- ] }) });
6344
+ ] }) }) });
6345
+ }
6346
+ function ActionMenuDropdownItem({
6347
+ item,
6348
+ onPick
6349
+ }) {
6350
+ const id = React32.useId();
6351
+ const labelId = `${id}-label`;
6352
+ const reasonId = `${id}-reason`;
6353
+ const Icon = item.icon;
6354
+ const reason = item.disabledReason || void 0;
6355
+ if (!reason) {
6356
+ return /* @__PURE__ */ jsxs30(
6357
+ DropdownMenuItem,
6358
+ {
6359
+ variant: item.destructive ? "destructive" : "default",
6360
+ disabled: item.disabled,
6361
+ onSelect: () => onPick(item),
6362
+ children: [
6363
+ Icon ? /* @__PURE__ */ jsx34(Icon, { "aria-hidden": true, size: 16, strokeWidth: 1.75 }) : null,
6364
+ item.label
6365
+ ]
6366
+ }
6367
+ );
6368
+ }
6369
+ return /* @__PURE__ */ jsxs30(
6370
+ DropdownMenuItem,
6371
+ {
6372
+ "aria-disabled": true,
6373
+ "aria-labelledby": labelId,
6374
+ "aria-describedby": reasonId,
6375
+ textValue: item.label,
6376
+ className: "aria-disabled:cursor-not-allowed",
6377
+ onSelect: (event) => event.preventDefault(),
6378
+ children: [
6379
+ Icon ? /* @__PURE__ */ jsx34(Icon, { "aria-hidden": true, size: 16, strokeWidth: 1.75, className: unavailableClassName }) : null,
6380
+ /* @__PURE__ */ jsxs30("span", { className: "min-w-0 flex-1 break-keep", children: [
6381
+ /* @__PURE__ */ jsx34("span", { id: labelId, className: unavailableClassName, children: item.label }),
6382
+ /* @__PURE__ */ jsx34("span", { id: reasonId, className: cn(reasonClassName, "max-w-64"), children: reason })
6383
+ ] })
6384
+ ]
6385
+ }
6386
+ );
6022
6387
  }
6023
6388
  var readPresentation = () => window.matchMedia?.(OVERLAY_DESKTOP_QUERY).matches ?? true ? "dropdown" : "sheet";
6024
6389
  var subscribeNothing = () => () => void 0;
6025
- var useHydrated = () => React30.useSyncExternalStore(
6390
+ var useHydrated = () => React32.useSyncExternalStore(
6026
6391
  subscribeNothing,
6027
6392
  () => true,
6028
6393
  () => false
@@ -6037,10 +6402,10 @@ function ActionMenu({
6037
6402
  items,
6038
6403
  groups
6039
6404
  }) {
6040
- const [uncontrolledOpen, setUncontrolledOpen] = React30.useState(false);
6405
+ const [uncontrolledOpen, setUncontrolledOpen] = React32.useState(false);
6041
6406
  const hydrated = useHydrated();
6042
6407
  const open = (openProp ?? uncontrolledOpen) && hydrated;
6043
- const [shown, setShown] = React30.useState({
6408
+ const [shown, setShown] = React32.useState({
6044
6409
  open: false,
6045
6410
  presentation: "dropdown"
6046
6411
  });
@@ -6049,8 +6414,8 @@ function ActionMenu({
6049
6414
  if (open) presentation = readPresentation();
6050
6415
  setShown({ open, presentation });
6051
6416
  }
6052
- const triggerRef = React30.useRef(null);
6053
- const pendingRef = React30.useRef(null);
6417
+ const triggerRef = React32.useRef(null);
6418
+ const pendingRef = React32.useRef(null);
6054
6419
  const setOpen = (nextOpen) => {
6055
6420
  if (nextOpen) pendingRef.current = null;
6056
6421
  if (openProp === void 0) setUncontrolledOpen(nextOpen);
@@ -6070,31 +6435,23 @@ function ActionMenu({
6070
6435
  triggerRef.current?.focus();
6071
6436
  };
6072
6437
  const triggerLabel = trigger.props["aria-label"];
6073
- return /* @__PURE__ */ jsxs30(Fragment13, { children: [
6438
+ return /* @__PURE__ */ jsxs30(Fragment16, { children: [
6074
6439
  /* @__PURE__ */ jsxs30(DropdownMenu, { open: open && presentation === "dropdown", onOpenChange: setOpen, children: [
6075
6440
  /* @__PURE__ */ jsx34(DropdownMenuTrigger, { asChild: true, "aria-expanded": open, children: /* @__PURE__ */ jsx34(Slot3.Root, { ref: triggerRef, children: trigger }) }),
6076
- /* @__PURE__ */ jsx34(DropdownMenuContent, { align: "end", onCloseAutoFocus: handleDropdownCloseAutoFocus, children: menuGroups.map((group, index) => /* @__PURE__ */ jsxs30(React30.Fragment, { children: [
6441
+ /* @__PURE__ */ jsx34(DropdownMenuContent, { align: "end", onCloseAutoFocus: handleDropdownCloseAutoFocus, children: menuGroups.map((group, index) => /* @__PURE__ */ jsxs30(React32.Fragment, { children: [
6077
6442
  index > 0 ? /* @__PURE__ */ jsx34(DropdownMenuSeparator, {}) : null,
6078
6443
  /* @__PURE__ */ jsxs30(DropdownMenuGroup, { children: [
6079
6444
  group.label ? /* @__PURE__ */ jsx34(DropdownMenuLabel, { children: group.label }) : null,
6080
- group.items.map((item) => {
6081
- const Icon = item.icon;
6082
- return /* @__PURE__ */ jsxs30(
6083
- DropdownMenuItem,
6084
- {
6085
- variant: item.destructive ? "destructive" : "default",
6086
- disabled: item.disabled,
6087
- onSelect: () => {
6088
- pendingRef.current = item;
6089
- },
6090
- children: [
6091
- Icon ? /* @__PURE__ */ jsx34(Icon, { "aria-hidden": true, size: 16, strokeWidth: 1.75 }) : null,
6092
- item.label
6093
- ]
6094
- },
6095
- item.id
6096
- );
6097
- })
6445
+ group.items.map((item) => /* @__PURE__ */ jsx34(
6446
+ ActionMenuDropdownItem,
6447
+ {
6448
+ item,
6449
+ onPick: (picked) => {
6450
+ pendingRef.current = picked;
6451
+ }
6452
+ },
6453
+ item.id
6454
+ ))
6098
6455
  ] })
6099
6456
  ] }, group.id)) })
6100
6457
  ] }),
@@ -6114,7 +6471,7 @@ function ActionMenu({
6114
6471
  }
6115
6472
 
6116
6473
  // src/components/ui/checkbox.tsx
6117
- import * as React31 from "react";
6474
+ import * as React33 from "react";
6118
6475
  import { cva as cva12 } from "class-variance-authority";
6119
6476
  import { Check as Check3, Minus } from "lucide-react";
6120
6477
  import { Checkbox as CheckboxPrimitive } from "radix-ui";
@@ -6221,11 +6578,11 @@ var checkboxGroupBoxVariants = cva12(
6221
6578
  }
6222
6579
  }
6223
6580
  );
6224
- var CheckboxGroupContext = React31.createContext(null);
6581
+ var CheckboxGroupContext = React33.createContext(null);
6225
6582
  function getLabel(children, label) {
6226
6583
  return children ?? label;
6227
6584
  }
6228
- var Checkbox = React31.forwardRef(
6585
+ var Checkbox = React33.forwardRef(
6229
6586
  ({
6230
6587
  className,
6231
6588
  size = "md",
@@ -6241,21 +6598,29 @@ var Checkbox = React31.forwardRef(
6241
6598
  checked,
6242
6599
  disabled,
6243
6600
  onCheckedChange,
6601
+ "aria-describedby": ariaDescribedBy,
6244
6602
  ...props
6245
6603
  }, ref) => {
6246
- const group = React31.useContext(CheckboxGroupContext);
6247
- const generatedId = React31.useId();
6248
- const checkboxId = id ?? generatedId;
6604
+ const group = React33.useContext(CheckboxGroupContext);
6605
+ const field = useFormFieldControl();
6606
+ const generatedId = React33.useId();
6249
6607
  const labelContent = getLabel(children, label);
6250
6608
  const isGrouped = Boolean(group && value != null);
6251
6609
  const valueString = value == null ? void 0 : String(value);
6252
6610
  const resolvedChecked = isGrouped && valueString ? group?.selectedValues.has(valueString) : checked;
6253
6611
  const resolvedDisabled = disabled || group?.disabled;
6254
6612
  const resolvedName = name ?? group?.name;
6613
+ const fieldControl = isGrouped ? null : field;
6614
+ const checkboxId = fieldControl ? generatedId : id ?? generatedId;
6255
6615
  const labelId = `${checkboxId}-label`;
6256
6616
  const descriptionId = description && !error ? `${checkboxId}-description` : void 0;
6257
6617
  const errorId = error ? `${checkboxId}-error` : void 0;
6258
- const describedBy = errorId ?? descriptionId;
6618
+ const elementId = id ?? fieldControl?.controlId ?? generatedId;
6619
+ const describedBy = joinIds(
6620
+ ariaDescribedBy,
6621
+ errorId ?? descriptionId,
6622
+ fieldControl?.describedBy
6623
+ );
6259
6624
  const handleCheckedChange = (nextChecked) => {
6260
6625
  onCheckedChange?.(nextChecked);
6261
6626
  if (isGrouped && valueString) {
@@ -6269,7 +6634,7 @@ var Checkbox = React31.forwardRef(
6269
6634
  CheckboxPrimitive.Root,
6270
6635
  {
6271
6636
  ref,
6272
- id: checkboxId,
6637
+ id: elementId,
6273
6638
  "data-slot": "checkbox",
6274
6639
  "aria-labelledby": labelId,
6275
6640
  "aria-describedby": describedBy,
@@ -6281,6 +6646,8 @@ var Checkbox = React31.forwardRef(
6281
6646
  disabled: resolvedDisabled,
6282
6647
  className: cn(
6283
6648
  checkboxGroupItemVariants({ appearance, density }),
6649
+ // plain rows sit side by side only at content width; w-full would wrap each one.
6650
+ appearance === "plain" && group?.orientation === "horizontal" && "w-auto",
6284
6651
  className
6285
6652
  ),
6286
6653
  onCheckedChange: handleCheckedChange,
@@ -6366,7 +6733,7 @@ var Checkbox = React31.forwardRef(
6366
6733
  CheckboxPrimitive.Root,
6367
6734
  {
6368
6735
  ref,
6369
- id: checkboxId,
6736
+ id: elementId,
6370
6737
  "data-slot": "checkbox",
6371
6738
  "aria-describedby": describedBy,
6372
6739
  "aria-required": required || void 0,
@@ -6400,7 +6767,7 @@ var Checkbox = React31.forwardRef(
6400
6767
  "label",
6401
6768
  {
6402
6769
  id: labelId,
6403
- htmlFor: checkboxId,
6770
+ htmlFor: elementId,
6404
6771
  "data-slot": "checkbox-label",
6405
6772
  className: labelClassName,
6406
6773
  children: [
@@ -6478,11 +6845,11 @@ function ContextMenu({
6478
6845
  }
6479
6846
 
6480
6847
  // src/components/ui/list-card.tsx
6481
- import * as React32 from "react";
6848
+ import * as React34 from "react";
6482
6849
  import { ChevronRight as ChevronRight2, MoreVertical } from "lucide-react";
6483
- import { Fragment as Fragment14, jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
6850
+ import { Fragment as Fragment17, jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
6484
6851
  function lineTokens(value) {
6485
- return React32.Children.toArray(value).filter((token) => token !== "");
6852
+ return React34.Children.toArray(value).filter((token) => token !== "");
6486
6853
  }
6487
6854
  function MetaLine({
6488
6855
  tokens,
@@ -6564,10 +6931,10 @@ function ListCard({
6564
6931
  "data-slot": `${slot}-title`,
6565
6932
  className: titleClassName,
6566
6933
  title: typeof title === "string" || typeof title === "number" ? String(title) : void 0,
6567
- children: overlay && href != null ? React32.createElement(linkComponent ?? "a", { ...linkProps, href, className: overlayClassName }, title) : title
6934
+ children: overlay && href != null ? React34.createElement(linkComponent ?? "a", { ...linkProps, href, className: overlayClassName }, title) : title
6568
6935
  }
6569
6936
  );
6570
- const content = /* @__PURE__ */ jsxs33(Fragment14, { children: [
6937
+ const content = /* @__PURE__ */ jsxs33(Fragment17, { children: [
6571
6938
  leading != null ? /* @__PURE__ */ jsx37("span", { className: "flex min-h-[18px] items-center", children: leading }) : null,
6572
6939
  /* @__PURE__ */ jsxs33("span", { className: "min-w-0", children: [
6573
6940
  overlay && href == null ? (
@@ -6598,7 +6965,7 @@ function ListCard({
6598
6965
  ),
6599
6966
  children: [
6600
6967
  hasValue ? /* @__PURE__ */ jsx37("span", { "data-slot": `${slot}-value`, className: "text-[13px] leading-[20px] text-text-secondary tabular-nums", children: value }) : null,
6601
- actions != null ? /* @__PURE__ */ jsx37("span", { className: "relative z-[1] flex", children: /* @__PURE__ */ jsx37(
6968
+ actions != null ? /* @__PURE__ */ jsx37("span", { "data-slot": `${slot}-actions`, className: "relative z-[1] flex", children: /* @__PURE__ */ jsx37(
6602
6969
  ActionMenu,
6603
6970
  {
6604
6971
  title: typeof title === "string" ? title : void 0,
@@ -6632,7 +6999,7 @@ function ListCard({
6632
6999
  }
6633
7000
 
6634
7001
  // src/components/ui/data-table.tsx
6635
- import { Fragment as Fragment16, jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
7002
+ import { Fragment as Fragment19, jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
6636
7003
  var dataTableVariants = cva13(
6637
7004
  [
6638
7005
  "relative overflow-hidden rounded-[var(--radius-md)] border border-[var(--border-subtle)]",
@@ -6755,25 +7122,24 @@ function RowActionsCell({
6755
7122
  );
6756
7123
  }
6757
7124
  function RowContextMenu({
6758
- openKey,
7125
+ menuKey,
6759
7126
  position,
6760
7127
  groups,
7128
+ cards,
6761
7129
  onClose
6762
7130
  }) {
6763
- const [open, setOpen] = React33.useState(false);
6764
- const pendingRef = React33.useRef(null);
6765
- const outsideRef = React33.useRef(false);
6766
- const shownGroups = React33.useRef([]);
7131
+ const [open, setOpen] = React35.useState(true);
7132
+ const closeRef = React35.useRef(null);
7133
+ const pressedOutside = React35.useRef(false);
7134
+ const close = (reason) => {
7135
+ closeRef.current ??= reason;
7136
+ setOpen(false);
7137
+ };
7138
+ const shownGroups = React35.useRef([]);
6767
7139
  if (groups) shownGroups.current = groups;
6768
- const gone = openKey !== null && groups === null;
6769
- const contentRef = React33.useRef(null);
6770
- const focusInsideRef = React33.useRef(false);
6771
- React33.useEffect(() => {
6772
- pendingRef.current = null;
6773
- outsideRef.current = false;
6774
- focusInsideRef.current = false;
6775
- setOpen(openKey !== null);
6776
- }, [openKey]);
7140
+ const gone = groups === null;
7141
+ const contentRef = React35.useRef(null);
7142
+ const focusInsideRef = React35.useRef(false);
6777
7143
  useIsomorphicLayoutEffect(() => {
6778
7144
  const content = contentRef.current;
6779
7145
  if (!open || !focusInsideRef.current || !content?.isConnected) return;
@@ -6782,14 +7148,21 @@ function RowContextMenu({
6782
7148
  const next = content.querySelector('[role="menuitem"]:not([data-disabled])') ?? content;
6783
7149
  next.focus();
6784
7150
  });
6785
- React33.useEffect(() => {
6786
- if (gone) setOpen(false);
7151
+ React35.useEffect(() => {
7152
+ if (gone) close({ by: "dismiss", outside: false });
6787
7153
  }, [gone]);
7154
+ useIsomorphicLayoutEffect(() => {
7155
+ if (!cards || !open || closeRef.current) return;
7156
+ const active = document.activeElement;
7157
+ close({ by: "layout", focusInside: Boolean(active && contentRef.current?.contains(active)) });
7158
+ }, [cards, open]);
6788
7159
  return /* @__PURE__ */ jsx38(
6789
7160
  ContextMenu,
6790
7161
  {
6791
7162
  open: open && !gone,
6792
- onOpenChange: setOpen,
7163
+ onOpenChange: (next) => {
7164
+ if (!next) close({ by: "dismiss", outside: false });
7165
+ },
6793
7166
  position,
6794
7167
  contentProps: {
6795
7168
  align: "start",
@@ -6803,37 +7176,31 @@ function RowContextMenu({
6803
7176
  }
6804
7177
  },
6805
7178
  onInteractOutside: () => {
6806
- outsideRef.current = true;
7179
+ pressedOutside.current = true;
7180
+ close({ by: "dismiss", outside: true });
6807
7181
  },
6808
7182
  onCloseAutoFocus: (event) => {
6809
7183
  event.preventDefault();
6810
- const item = pendingRef.current;
6811
- pendingRef.current = null;
6812
- onClose(item, outsideRef.current);
7184
+ let reason = closeRef.current ?? { by: "dismiss", outside: false };
7185
+ if (pressedOutside.current && reason.by === "dismiss") reason = { by: "dismiss", outside: true };
7186
+ if (pressedOutside.current && reason.by === "layout") reason = { by: "layout", focusInside: false };
7187
+ onClose(menuKey, reason);
6813
7188
  }
6814
7189
  },
6815
- children: shownGroups.current.map((group, index) => /* @__PURE__ */ jsxs34(React33.Fragment, { children: [
7190
+ children: shownGroups.current.map((group, index) => /* @__PURE__ */ jsxs34(React35.Fragment, { children: [
6816
7191
  index > 0 ? /* @__PURE__ */ jsx38(DropdownMenuSeparator, {}) : null,
6817
7192
  /* @__PURE__ */ jsxs34(DropdownMenuGroup, { children: [
6818
7193
  group.label ? /* @__PURE__ */ jsx38(DropdownMenuLabel, { children: group.label }) : null,
6819
- group.items.map((item) => {
6820
- const Icon = item.icon;
6821
- return /* @__PURE__ */ jsxs34(
6822
- DropdownMenuItem,
6823
- {
6824
- variant: item.destructive ? "destructive" : "default",
6825
- disabled: item.disabled,
6826
- onSelect: () => {
6827
- pendingRef.current = item;
6828
- },
6829
- children: [
6830
- Icon ? /* @__PURE__ */ jsx38(Icon, { "aria-hidden": true, size: 16, strokeWidth: 1.75 }) : null,
6831
- item.label
6832
- ]
6833
- },
6834
- item.id
6835
- );
6836
- })
7194
+ group.items.map((item) => /* @__PURE__ */ jsx38(
7195
+ ActionMenuDropdownItem,
7196
+ {
7197
+ item,
7198
+ onPick: (picked) => {
7199
+ closeRef.current ??= { by: "item", item: picked };
7200
+ }
7201
+ },
7202
+ item.id
7203
+ ))
6837
7204
  ] })
6838
7205
  ] }, group.id))
6839
7206
  }
@@ -6847,12 +7214,18 @@ function getRenderedCell(row, column) {
6847
7214
  if (value === null || value === void 0) {
6848
7215
  return null;
6849
7216
  }
6850
- if (React33.isValidElement(value)) {
7217
+ if (React35.isValidElement(value)) {
6851
7218
  return value;
6852
7219
  }
6853
7220
  return String(value);
6854
7221
  }
6855
- function getNextSort(current, key) {
7222
+ function getNextSort(current, key, defaultSort) {
7223
+ if (defaultSort?.key === key) {
7224
+ if (current?.key === key && current.dir === defaultSort.dir) {
7225
+ return defaultSort.dir === "asc" ? "desc" : "asc";
7226
+ }
7227
+ return defaultSort.dir;
7228
+ }
6856
7229
  if (current?.key !== key) {
6857
7230
  return "asc";
6858
7231
  }
@@ -6894,6 +7267,7 @@ function SortIcon({ sort, columnKey }) {
6894
7267
  function MobileSortMenu({
6895
7268
  columns,
6896
7269
  sortBy,
7270
+ defaultSort,
6897
7271
  onSortChange
6898
7272
  }) {
6899
7273
  const active = sortBy ? columns.find((column) => column.key === sortBy.key) : void 0;
@@ -6907,7 +7281,7 @@ function MobileSortMenu({
6907
7281
  size: "sm",
6908
7282
  className: "ml-auto min-w-0",
6909
7283
  children: [
6910
- active && sortBy ? /* @__PURE__ */ jsxs34(Fragment16, { children: [
7284
+ active && sortBy ? /* @__PURE__ */ jsxs34(Fragment19, { children: [
6911
7285
  /* @__PURE__ */ jsx38("span", { className: "sr-only", children: "\uC815\uB82C " }),
6912
7286
  /* @__PURE__ */ jsx38("span", { className: "truncate", children: active.header }),
6913
7287
  /* @__PURE__ */ jsxs34("span", { className: "sr-only", children: [
@@ -6923,7 +7297,7 @@ function MobileSortMenu({
6923
7297
  DropdownMenuRadioItem,
6924
7298
  {
6925
7299
  value: column.key,
6926
- onSelect: () => onSortChange?.(column.key, getNextSort(sortBy, column.key)),
7300
+ onSelect: () => onSortChange?.(column.key, getNextSort(sortBy, column.key, defaultSort)),
6927
7301
  children: [
6928
7302
  /* @__PURE__ */ jsx38("span", { className: "truncate", children: column.header }),
6929
7303
  column.key === active?.key ? /* @__PURE__ */ jsx38("span", { className: "ml-auto pl-[var(--space-4)]", children: /* @__PURE__ */ jsx38(SortIcon, { sort: sortBy, columnKey: column.key }) }) : null
@@ -6936,6 +7310,7 @@ function MobileSortMenu({
6936
7310
  function MobileToolbar({
6937
7311
  columns,
6938
7312
  sortBy,
7313
+ defaultSort,
6939
7314
  onSortChange,
6940
7315
  selectable,
6941
7316
  selectAllChecked,
@@ -6953,7 +7328,15 @@ function MobileToolbar({
6953
7328
  className: "flex min-w-0 items-center gap-[var(--space-2)] px-[var(--space-4)] py-[var(--space-2)]",
6954
7329
  children: [
6955
7330
  selectable ? /* @__PURE__ */ jsx38(SelectAllCheckbox, { checked: selectAllChecked, disabled: selectAllDisabled, onToggleAll }) : null,
6956
- sortableColumns.length > 0 ? /* @__PURE__ */ jsx38(MobileSortMenu, { columns: sortableColumns, sortBy, onSortChange }) : null
7331
+ sortableColumns.length > 0 ? /* @__PURE__ */ jsx38(
7332
+ MobileSortMenu,
7333
+ {
7334
+ columns: sortableColumns,
7335
+ sortBy,
7336
+ defaultSort,
7337
+ onSortChange
7338
+ }
7339
+ ) : null
6957
7340
  ]
6958
7341
  }
6959
7342
  );
@@ -7060,7 +7443,7 @@ var expandedPanelClass = cn(
7060
7443
  );
7061
7444
  var expandChevronClass = "motion-safe:transition-transform motion-safe:duration-[var(--dur-base)] motion-safe:ease-[var(--ease-standard)]";
7062
7445
  function useOpenedOnce(expanded) {
7063
- const [opened, setOpened] = React33.useState(expanded);
7446
+ const [opened, setOpened] = React35.useState(expanded);
7064
7447
  if (expanded && !opened) {
7065
7448
  setOpened(true);
7066
7449
  }
@@ -7171,7 +7554,7 @@ function DataTableRowView({
7171
7554
  if (!expand) {
7172
7555
  return dataRow;
7173
7556
  }
7174
- return /* @__PURE__ */ jsxs34(Fragment16, { children: [
7557
+ return /* @__PURE__ */ jsxs34(Fragment19, { children: [
7175
7558
  dataRow,
7176
7559
  /* @__PURE__ */ jsx38(
7177
7560
  "div",
@@ -7317,9 +7700,9 @@ function DataTableMobileCardView({
7317
7700
  }
7318
7701
  );
7319
7702
  }
7320
- var MemoDataTableRow = React33.memo(DataTableRowView);
7321
- var MemoDataTableMobileCard = React33.memo(DataTableMobileCardView);
7322
- var useIsomorphicLayoutEffect = typeof window === "undefined" ? React33.useEffect : React33.useLayoutEffect;
7703
+ var MemoDataTableRow = React35.memo(DataTableRowView);
7704
+ var MemoDataTableMobileCard = React35.memo(DataTableMobileCardView);
7705
+ var useIsomorphicLayoutEffect = typeof window === "undefined" ? React35.useEffect : React35.useLayoutEffect;
7323
7706
  var VIRTUAL_DEFAULT_OVERSCAN = 8;
7324
7707
  var VIRTUAL_INITIAL_ROWS = 24;
7325
7708
  var VIRTUAL_FALLBACK_SIZE = { desktop: 48, mobile: 120 };
@@ -7399,7 +7782,7 @@ function useVirtualWindow({
7399
7782
  mobileListRef
7400
7783
  }) {
7401
7784
  const count = rowIds.length;
7402
- const [win, setWin] = React33.useState({
7785
+ const [win, setWin] = React35.useState({
7403
7786
  layout: null,
7404
7787
  start: 0,
7405
7788
  end: VIRTUAL_INITIAL_ROWS,
@@ -7407,12 +7790,12 @@ function useVirtualWindow({
7407
7790
  padTop: 0,
7408
7791
  padBottom: 0
7409
7792
  });
7410
- const desktopSize = React33.useRef(0);
7411
- const cardHeights = React33.useRef(null);
7793
+ const desktopSize = React35.useRef(0);
7794
+ const cardHeights = React35.useRef(null);
7412
7795
  cardHeights.current ??= new CardHeights();
7413
- const update = React33.useRef(() => void 0);
7414
- const reported = React33.useRef("");
7415
- const latest = React33.useRef({
7796
+ const update = React35.useRef(() => void 0);
7797
+ const reported = React35.useRef("");
7798
+ const latest = React35.useRef({
7416
7799
  count,
7417
7800
  layout: "desktop",
7418
7801
  extent: uniformExtent(VIRTUAL_FALLBACK_SIZE.desktop)
@@ -7475,7 +7858,7 @@ function useVirtualWindow({
7475
7858
  useIsomorphicLayoutEffect(() => {
7476
7859
  update.current();
7477
7860
  });
7478
- React33.useEffect(() => {
7861
+ React35.useEffect(() => {
7479
7862
  if (!enabled) {
7480
7863
  return;
7481
7864
  }
@@ -7497,7 +7880,7 @@ function useVirtualWindow({
7497
7880
  window.cancelAnimationFrame(frame);
7498
7881
  };
7499
7882
  }, [enabled]);
7500
- const scrollToIndex = React33.useCallback(
7883
+ const scrollToIndex = React35.useCallback(
7501
7884
  (index) => {
7502
7885
  const { count: rowCount, layout, extent } = latest.current;
7503
7886
  const list = (layout === "desktop" ? desktopListRef : mobileListRef).current;
@@ -7530,7 +7913,7 @@ function useVisibleLayout({
7530
7913
  desktopRef,
7531
7914
  mobileRef
7532
7915
  }) {
7533
- const [layout, setLayout] = React33.useState(null);
7916
+ const [layout, setLayout] = React35.useState(null);
7534
7917
  useIsomorphicLayoutEffect(() => {
7535
7918
  if (!enabled) {
7536
7919
  return;
@@ -7567,9 +7950,9 @@ function useLayoutFocusHandoff({
7567
7950
  layout,
7568
7951
  containers
7569
7952
  }) {
7570
- const lastFocus = React33.useRef(null);
7571
- const previousLayout = React33.useRef(layout);
7572
- React33.useEffect(() => {
7953
+ const lastFocus = React35.useRef(null);
7954
+ const previousLayout = React35.useRef(layout);
7955
+ React35.useEffect(() => {
7573
7956
  const root = rootRef.current;
7574
7957
  if (!root) {
7575
7958
  return;
@@ -7646,7 +8029,8 @@ function DataTableInner({
7646
8029
  announceSelection = true,
7647
8030
  activeRowId,
7648
8031
  onRowContextMenu,
7649
- sortBy,
8032
+ sortBy: sortByProp,
8033
+ defaultSort,
7650
8034
  onSortChange,
7651
8035
  loading = false,
7652
8036
  emptyState,
@@ -7665,18 +8049,19 @@ function DataTableInner({
7665
8049
  "aria-label": ariaLabel = "\uB370\uC774\uD130 \uD14C\uC774\uBE14",
7666
8050
  ...props
7667
8051
  }, ref) {
8052
+ const sortBy = sortByProp ?? defaultSort;
7668
8053
  const virtualOptions = virtual ? virtual === true ? {} : virtual : null;
7669
8054
  const isVirtual = virtualOptions !== null;
7670
8055
  if (isVirtual && columns.some((column) => column.wrap)) {
7671
8056
  warnWrapVirtualOnce();
7672
8057
  }
7673
- const rootRef = React33.useRef(null);
7674
- const desktopRef = React33.useRef(null);
7675
- const headerRef = React33.useRef(null);
7676
- const desktopListRef = React33.useRef(null);
7677
- const mobileRef = React33.useRef(null);
7678
- const mobileListRef = React33.useRef(null);
7679
- const setRootRef = React33.useCallback(
8058
+ const rootRef = React35.useRef(null);
8059
+ const desktopRef = React35.useRef(null);
8060
+ const headerRef = React35.useRef(null);
8061
+ const desktopListRef = React35.useRef(null);
8062
+ const mobileRef = React35.useRef(null);
8063
+ const mobileListRef = React35.useRef(null);
8064
+ const setRootRef = React35.useCallback(
7680
8065
  (node) => {
7681
8066
  rootRef.current = node;
7682
8067
  if (typeof ref === "function") ref(node);
@@ -7695,7 +8080,7 @@ function DataTableInner({
7695
8080
  desktopListRef,
7696
8081
  mobileListRef
7697
8082
  });
7698
- React33.useImperativeHandle(virtualOptions?.handleRef, () => ({ scrollToIndex }), [scrollToIndex]);
8083
+ React35.useImperativeHandle(virtualOptions?.handleRef, () => ({ scrollToIndex }), [scrollToIndex]);
7699
8084
  const visibleLayout = useVisibleLayout({ enabled: !isVirtual, desktopRef, mobileRef });
7700
8085
  const activeLayout = isVirtual ? virtualWindow.layout : visibleLayout;
7701
8086
  useLayoutFocusHandoff({
@@ -7719,8 +8104,8 @@ function DataTableInner({
7719
8104
  const expandable = renderExpanded != null;
7720
8105
  const hasRowActions = rowActions != null;
7721
8106
  const gridTemplateColumns = getGridTemplate(columns, selectable, expandable, hasRowActions);
7722
- const panelIdBase = React33.useId();
7723
- const [ownExpandedIds, setOwnExpandedIds] = React33.useState(() => /* @__PURE__ */ new Set());
8107
+ const panelIdBase = React35.useId();
8108
+ const [ownExpandedIds, setOwnExpandedIds] = React35.useState(() => /* @__PURE__ */ new Set());
7724
8109
  const resolvedExpandedIds = expandedIds ?? ownExpandedIds;
7725
8110
  const toggleExpanded = (id) => {
7726
8111
  const nextIds = new Set(resolvedExpandedIds);
@@ -7766,8 +8151,8 @@ function DataTableInner({
7766
8151
  window.location.assign(href);
7767
8152
  }
7768
8153
  };
7769
- const [contextMenu, setContextMenu] = React33.useState(null);
7770
- const contextMenuKey = React33.useRef(0);
8154
+ const [contextMenu, setContextMenu] = React35.useState(null);
8155
+ const contextMenuKey = React35.useRef(0);
7771
8156
  const contextRow = contextMenu ? data.find((item) => getRowId(item, keyField) === contextMenu.rowId) : void 0;
7772
8157
  const contextActions = contextRow && rowActions ? rowActions(contextRow) : [];
7773
8158
  const contextGroups = countActions(contextActions) > 0 ? toActionGroups(contextActions) : null;
@@ -7781,15 +8166,22 @@ function DataTableInner({
7781
8166
  contextMenuKey.current += 1;
7782
8167
  setContextMenu({ rowId, position: { x: event.clientX, y: event.clientY }, key: contextMenuKey.current });
7783
8168
  };
7784
- const closeRowContextMenu = (item, outside) => {
8169
+ const closeRowContextMenu = (key, close) => {
8170
+ if (key !== contextMenuKey.current) {
8171
+ return;
8172
+ }
7785
8173
  const rowId = contextMenu?.rowId;
7786
- if (rowId !== void 0 && (item || !outside)) {
7787
- const list = desktopListRef.current;
7788
- const row = Array.from(list?.querySelectorAll('[data-slot="data-table-row"]') ?? []).find(
7789
- (node) => node.getAttribute("data-row-id") === rowId
8174
+ const refocus = close.by === "item" || (close.by === "dismiss" ? !close.outside : close.focusInside);
8175
+ if (rowId !== void 0 && refocus) {
8176
+ const cards = readLayout(desktopRef.current) === "mobile";
8177
+ const list = cards ? mobileListRef.current : desktopListRef.current;
8178
+ const row = Array.from(
8179
+ list?.querySelectorAll(cards ? '[data-slot="data-table-mobile-card"]' : '[data-slot="data-table-row"]') ?? []
8180
+ ).find((node) => node.getAttribute("data-row-id") === rowId);
8181
+ const trigger = row?.querySelector(
8182
+ cards ? '[data-slot="list-card-actions"] button' : '[data-slot="data-table-row-actions"] button'
7790
8183
  );
7791
- const trigger = row?.querySelector('[data-slot="data-table-row-actions"] button');
7792
- const target = trigger ?? (row?.hasAttribute("tabindex") ? row : null) ?? list ?? desktopRef.current;
8184
+ const target = trigger ?? (row && (cards || row.hasAttribute("tabindex")) ? row : null) ?? list ?? (cards ? mobileRef : desktopRef).current;
7793
8185
  if (target) {
7794
8186
  if (!target.hasAttribute("tabindex") && !target.matches("a[href],button,input")) {
7795
8187
  target.tabIndex = -1;
@@ -7798,26 +8190,26 @@ function DataTableInner({
7798
8190
  }
7799
8191
  }
7800
8192
  setContextMenu(null);
7801
- item?.onSelect();
8193
+ if (close.by === "item") close.item.onSelect();
7802
8194
  };
7803
8195
  const handleRowContextMenu = rowActions ? openRowContextMenu : onRowContextMenu;
7804
- const latestHandlers = React33.useRef({ toggleRow, activateRow, onRowContextMenu, handleRowContextMenu });
8196
+ const latestHandlers = React35.useRef({ toggleRow, activateRow, onRowContextMenu, handleRowContextMenu });
7805
8197
  useIsomorphicLayoutEffect(() => {
7806
8198
  latestHandlers.current = { toggleRow, activateRow, onRowContextMenu, handleRowContextMenu };
7807
8199
  });
7808
- const stableToggleRow = React33.useCallback(
8200
+ const stableToggleRow = React35.useCallback(
7809
8201
  (id, checked) => latestHandlers.current.toggleRow(id, checked),
7810
8202
  []
7811
8203
  );
7812
- const stableActivateRow = React33.useCallback(
8204
+ const stableActivateRow = React35.useCallback(
7813
8205
  (row, href, event) => latestHandlers.current.activateRow(row, href, event),
7814
8206
  []
7815
8207
  );
7816
- const stableRowContextMenu = React33.useCallback(
8208
+ const stableRowContextMenu = React35.useCallback(
7817
8209
  (rowId, event) => latestHandlers.current.onRowContextMenu?.(rowId, event),
7818
8210
  []
7819
8211
  );
7820
- const stableHandleRowContextMenu = React33.useCallback(
8212
+ const stableHandleRowContextMenu = React35.useCallback(
7821
8213
  (rowId, event) => latestHandlers.current.handleRowContextMenu?.(rowId, event),
7822
8214
  []
7823
8215
  );
@@ -7937,7 +8329,7 @@ function DataTableInner({
7937
8329
  selectable ? /* @__PURE__ */ jsx38("div", { role: "columnheader", className: "px-[var(--space-4)]", children: /* @__PURE__ */ jsx38(SelectAllCheckbox, { checked: selectAllChecked, disabled: selectAllDisabled, onToggleAll: toggleAllRows }) }) : null,
7938
8330
  columns.map((column) => {
7939
8331
  const align = column.align ?? "left";
7940
- const nextSort = getNextSort(sortBy, column.key);
8332
+ const nextSort = getNextSort(sortBy, column.key, defaultSort);
7941
8333
  const ariaSort = sortBy?.key === column.key ? sortBy.dir === "asc" ? "ascending" : "descending" : void 0;
7942
8334
  return /* @__PURE__ */ jsx38(
7943
8335
  "div",
@@ -8015,6 +8407,7 @@ function DataTableInner({
8015
8407
  {
8016
8408
  columns,
8017
8409
  sortBy,
8410
+ defaultSort,
8018
8411
  onSortChange,
8019
8412
  selectable,
8020
8413
  selectAllChecked,
@@ -8049,24 +8442,26 @@ function DataTableInner({
8049
8442
  )
8050
8443
  ] }),
8051
8444
  footer != null ? /* @__PURE__ */ jsx38("div", { "data-slot": "data-table-footer", className: "border-t border-[var(--border-subtle)] empty:hidden", children: footer }) : null,
8052
- hasRowActions ? /* @__PURE__ */ jsx38(
8445
+ hasRowActions && contextMenu ? /* @__PURE__ */ jsx38(
8053
8446
  RowContextMenu,
8054
8447
  {
8055
- openKey: contextMenu?.key ?? null,
8056
- position: contextMenu?.position ?? null,
8448
+ menuKey: contextMenu.key,
8449
+ position: contextMenu.position,
8057
8450
  groups: contextGroups,
8451
+ cards: activeLayout === "mobile",
8058
8452
  onClose: closeRowContextMenu
8059
- }
8453
+ },
8454
+ contextMenu.key
8060
8455
  ) : null
8061
8456
  ]
8062
8457
  }
8063
8458
  );
8064
8459
  }
8065
- var DataTable = React33.forwardRef(DataTableInner);
8460
+ var DataTable = React35.forwardRef(DataTableInner);
8066
8461
  DataTable.displayName = "DataTable";
8067
8462
 
8068
8463
  // src/components/ui/bulk-action-bar.tsx
8069
- import * as React34 from "react";
8464
+ import * as React36 from "react";
8070
8465
  import { X as X4 } from "lucide-react";
8071
8466
  import { jsx as jsx39, jsxs as jsxs35 } from "react/jsx-runtime";
8072
8467
  function ActionButton({ action }) {
@@ -8114,6 +8509,35 @@ function ActionButton({ action }) {
8114
8509
  }
8115
8510
  );
8116
8511
  }
8512
+ function CardActionButton({ action }) {
8513
+ const Icon = action.icon;
8514
+ return /* @__PURE__ */ jsxs35(
8515
+ Button,
8516
+ {
8517
+ appearance: "outline",
8518
+ tone: action.variant === "destructive" ? "danger" : "neutral",
8519
+ size: "sm",
8520
+ className: "before:-inset-y-[5px]",
8521
+ "data-slot": "bulk-action-bar-action",
8522
+ "data-variant": action.variant ?? "default",
8523
+ disabled: action.disabled,
8524
+ title: action.title,
8525
+ onClick: action.onClick,
8526
+ children: [
8527
+ Icon ? /* @__PURE__ */ jsx39(
8528
+ Icon,
8529
+ {
8530
+ "aria-hidden": "true",
8531
+ "data-slot": "bulk-action-bar-action-icon",
8532
+ size: 16,
8533
+ strokeWidth: 1.75
8534
+ }
8535
+ ) : null,
8536
+ action.label
8537
+ ]
8538
+ }
8539
+ );
8540
+ }
8117
8541
  function Divider() {
8118
8542
  return /* @__PURE__ */ jsx39(
8119
8543
  "span",
@@ -8156,24 +8580,24 @@ function ClearButton({ onClear }) {
8156
8580
  }
8157
8581
  );
8158
8582
  }
8583
+ var CLEAR_CLEARANCE = 32;
8159
8584
  var INLINE_HEIGHT = 40;
8160
8585
  var HIT_AREA = 44;
8161
8586
  var HIT_INSET = 8;
8587
+ var FLOATING_BOTTOM = "calc(var(--space-4) + env(safe-area-inset-bottom))";
8162
8588
  var floatingStyle = {
8163
8589
  position: "sticky",
8164
- bottom: "calc(var(--space-4) + env(safe-area-inset-bottom))",
8590
+ bottom: FLOATING_BOTTOM,
8165
8591
  zIndex: 1100,
8166
8592
  margin: "0 auto",
8167
8593
  display: "flex",
8168
- minHeight: 32,
8169
- width: "fit-content",
8170
- maxWidth: "calc(100% - var(--space-8))",
8171
- alignItems: "center",
8172
- gap: "var(--space-2)",
8173
- borderRadius: 9999,
8594
+ boxSizing: "border-box",
8595
+ width: "min(360px, calc(100% - var(--space-8)))",
8596
+ flexDirection: "column",
8597
+ borderRadius: "var(--radius-xl)",
8174
8598
  border: "1px solid var(--border)",
8175
8599
  background: "var(--bg-raised)",
8176
- padding: "var(--space-1) var(--space-2)",
8600
+ padding: "var(--space-2) var(--space-4) var(--space-3)",
8177
8601
  boxShadow: "var(--shadow-8)"
8178
8602
  };
8179
8603
  var inlineStyle = {
@@ -8207,10 +8631,128 @@ var idleLineStyle = {
8207
8631
  fontVariantNumeric: "tabular-nums",
8208
8632
  color: "var(--text-secondary)"
8209
8633
  };
8210
- var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React34.useEffect : React34.useLayoutEffect;
8634
+ var warnedInline = false;
8635
+ function warnInlineOnce() {
8636
+ if (warnedInline || typeof process === "undefined" || process.env.NODE_ENV === "production") {
8637
+ return;
8638
+ }
8639
+ warnedInline = true;
8640
+ console.warn('BulkActionBar: placement="inline" is deprecated and removed in the next minor. Use "floating".');
8641
+ }
8642
+ var warnedTrailing = false;
8643
+ function warnTrailingOnce() {
8644
+ if (warnedTrailing || typeof process === "undefined" || process.env.NODE_ENV === "production") {
8645
+ return;
8646
+ }
8647
+ warnedTrailing = true;
8648
+ console.warn("BulkActionBar: the floating card ignores `trailing`. Put edit-mode controls at the right end of the toolbar.");
8649
+ }
8650
+ var OFFSET_PROPERTY = "--olun-bulk-bar-offset";
8651
+ var LIFT_ZONE = 204;
8652
+ var cardOffsets = /* @__PURE__ */ new Map();
8653
+ function writeOffset() {
8654
+ const root = document.documentElement;
8655
+ const offset = Math.max(0, ...cardOffsets.values());
8656
+ const value = offset > 0 ? `${offset}px` : "";
8657
+ if (root.style.getPropertyValue(OFFSET_PROPERTY) === value) return;
8658
+ if (value) root.style.setProperty(OFFSET_PROPERTY, value);
8659
+ else root.style.removeProperty(OFFSET_PROPERTY);
8660
+ }
8661
+ function reportOffset(key, card) {
8662
+ let offset = 0;
8663
+ if (card.offsetHeight > 0) {
8664
+ const { top, bottom } = card.getBoundingClientRect();
8665
+ if (window.innerHeight - bottom <= LIFT_ZONE) offset = Math.max(0, Math.round(window.innerHeight - top));
8666
+ }
8667
+ if (offset === (cardOffsets.get(key) ?? 0)) return;
8668
+ if (offset > 0) cardOffsets.set(key, offset);
8669
+ else cardOffsets.delete(key);
8670
+ writeOffset();
8671
+ }
8672
+ var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React36.useEffect : React36.useLayoutEffect;
8673
+ function useBottomOffset(card) {
8674
+ const [key] = React36.useState(() => ({}));
8675
+ React36.useEffect(() => {
8676
+ if (!card) return;
8677
+ let frame = 0;
8678
+ let stopped = false;
8679
+ let listening = false;
8680
+ const schedule = () => {
8681
+ if (frame || stopped) return;
8682
+ frame = requestAnimationFrame(measure);
8683
+ };
8684
+ const listen = (on) => {
8685
+ if (on === listening) return;
8686
+ listening = on;
8687
+ if (on) {
8688
+ window.addEventListener("resize", schedule);
8689
+ window.addEventListener("scroll", schedule, { capture: true, passive: true });
8690
+ } else {
8691
+ window.removeEventListener("resize", schedule);
8692
+ window.removeEventListener("scroll", schedule, { capture: true });
8693
+ }
8694
+ };
8695
+ let watcher = null;
8696
+ let watched = "";
8697
+ const arm = (margin, threshold) => {
8698
+ let first = true;
8699
+ watcher = new IntersectionObserver(
8700
+ ([entry]) => {
8701
+ if (stopped) return;
8702
+ if (first) {
8703
+ first = false;
8704
+ if (entry.intersectionRatio === threshold) return;
8705
+ watcher?.disconnect();
8706
+ arm(margin, entry.intersectionRatio);
8707
+ }
8708
+ schedule();
8709
+ },
8710
+ { root: document, rootMargin: margin, threshold }
8711
+ );
8712
+ watcher.observe(card);
8713
+ };
8714
+ const watch = (on) => {
8715
+ let margin = "";
8716
+ if (on && typeof IntersectionObserver !== "undefined") {
8717
+ const { top, right, bottom, left } = card.getBoundingClientRect();
8718
+ const { clientWidth, clientHeight } = document.documentElement;
8719
+ margin = [top, clientWidth - right, clientHeight - bottom, left].map((inset) => `${-Math.floor(inset)}px`).join(" ");
8720
+ }
8721
+ if (margin === watched) return;
8722
+ watched = margin;
8723
+ watcher?.disconnect();
8724
+ watcher = null;
8725
+ if (margin) arm(margin, 1);
8726
+ };
8727
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => schedule());
8728
+ const measure = () => {
8729
+ frame = 0;
8730
+ reportOffset(key, card);
8731
+ const shown = card.offsetHeight > 0;
8732
+ listen(shown || !observer);
8733
+ watch(shown);
8734
+ };
8735
+ measure();
8736
+ observer?.observe(card);
8737
+ card.addEventListener("animationend", schedule);
8738
+ return () => {
8739
+ stopped = true;
8740
+ cancelAnimationFrame(frame);
8741
+ listen(false);
8742
+ watcher?.disconnect();
8743
+ observer?.disconnect();
8744
+ card.removeEventListener("animationend", schedule);
8745
+ cardOffsets.delete(key);
8746
+ writeOffset();
8747
+ };
8748
+ }, [key, card]);
8749
+ useIsomorphicLayoutEffect2(() => {
8750
+ if (card && typeof ResizeObserver === "undefined") reportOffset(key, card);
8751
+ });
8752
+ }
8211
8753
  function useCompactSummary(slot, enabled) {
8212
- const [fullWidth, setFullWidth] = React34.useState(null);
8213
- const measure = React34.useCallback(() => {
8754
+ const [fullWidth, setFullWidth] = React36.useState(null);
8755
+ const measure = React36.useCallback(() => {
8214
8756
  if (!slot) return;
8215
8757
  setFullWidth((prev) => {
8216
8758
  if (prev === null) return slot.scrollWidth > slot.clientWidth ? slot.scrollWidth : null;
@@ -8220,7 +8762,7 @@ function useCompactSummary(slot, enabled) {
8220
8762
  useIsomorphicLayoutEffect2(() => {
8221
8763
  if (enabled) measure();
8222
8764
  });
8223
- React34.useEffect(() => {
8765
+ React36.useEffect(() => {
8224
8766
  if (!enabled || !slot || typeof ResizeObserver === "undefined") return;
8225
8767
  const observer = new ResizeObserver(measure);
8226
8768
  observer.observe(slot);
@@ -8244,7 +8786,10 @@ function BulkActionBar({
8244
8786
  ...props
8245
8787
  }) {
8246
8788
  const inline = placement === "inline";
8247
- const trailingSlot = trailing !== void 0 && trailing !== null ? /* @__PURE__ */ jsx39(
8789
+ if (inline) warnInlineOnce();
8790
+ const hasTrailing = trailing !== void 0 && trailing !== null;
8791
+ if (!inline && hasTrailing) warnTrailingOnce();
8792
+ const trailingSlot = inline && hasTrailing ? /* @__PURE__ */ jsx39(
8248
8793
  "div",
8249
8794
  {
8250
8795
  "data-slot": "bulk-action-bar-trailing",
@@ -8257,11 +8802,13 @@ function BulkActionBar({
8257
8802
  children: trailing
8258
8803
  }
8259
8804
  ) : null;
8260
- const [summaryElement, setSummaryElement] = React34.useState(null);
8805
+ const [summaryElement, setSummaryElement] = React36.useState(null);
8261
8806
  const compact = useCompactSummary(
8262
8807
  summaryElement,
8263
8808
  inline && compactSummary !== void 0 && compactSummary !== null
8264
8809
  );
8810
+ const [card, setCard] = React36.useState(null);
8811
+ useBottomOffset(card);
8265
8812
  if (count === 0 && idleContent !== void 0 && trailingSlot) {
8266
8813
  return /* @__PURE__ */ jsxs35(
8267
8814
  "div",
@@ -8316,16 +8863,31 @@ function BulkActionBar({
8316
8863
  "span",
8317
8864
  {
8318
8865
  "data-slot": "bulk-action-bar-count",
8319
- style: {
8320
- paddingLeft: inline ? void 0 : "var(--space-2)",
8866
+ style: inline ? {
8321
8867
  paddingRight: "var(--space-1)",
8322
8868
  fontFamily: "var(--font-sans)",
8323
8869
  fontSize: 13,
8324
- fontWeight: inline ? 600 : 500,
8870
+ fontWeight: 600,
8325
8871
  fontVariantNumeric: "tabular-nums",
8326
8872
  color: "var(--text-primary)",
8327
8873
  whiteSpace: "nowrap"
8328
- },
8874
+ } : (
8875
+ // First row, 32px like the ✕ beside it; the right padding keeps text clear of it,
8876
+ // and a long unbroken unit or hint breaks instead of running under it.
8877
+ {
8878
+ display: "flex",
8879
+ minHeight: 32,
8880
+ alignItems: "center",
8881
+ paddingRight: CLEAR_CLEARANCE,
8882
+ fontFamily: "var(--font-sans)",
8883
+ fontSize: 13,
8884
+ fontWeight: 500,
8885
+ fontVariantNumeric: "tabular-nums",
8886
+ color: "var(--text-primary)",
8887
+ wordBreak: "keep-all",
8888
+ overflowWrap: "anywhere"
8889
+ }
8890
+ ),
8329
8891
  children: count > 0 ? `${count.toLocaleString("ko-KR")}${unit} \uC120\uD0DD\uB428` : emptyHint
8330
8892
  }
8331
8893
  );
@@ -8335,7 +8897,7 @@ function BulkActionBar({
8335
8897
  ref: setSummaryElement,
8336
8898
  "data-slot": "bulk-action-bar-summary",
8337
8899
  style: {
8338
- display: inline ? "flex" : "inline-flex",
8900
+ display: "flex",
8339
8901
  minWidth: 0,
8340
8902
  alignItems: "center",
8341
8903
  columnGap: "var(--space-3)",
@@ -8358,27 +8920,30 @@ function BulkActionBar({
8358
8920
  whiteSpace: "nowrap",
8359
8921
  contain: "inline-size"
8360
8922
  }
8361
- ) : { flexWrap: "wrap", wordBreak: "keep-all" }
8923
+ ) : (
8924
+ // Its own row at the card's full inner width; wraps, never clips.
8925
+ { flexWrap: "wrap", lineHeight: 1.5, wordBreak: "keep-all", overflowWrap: "anywhere" }
8926
+ )
8362
8927
  },
8363
8928
  children: compact ? compactSummary : summary
8364
8929
  }
8365
8930
  ) : null;
8366
- const actionGroup = /* @__PURE__ */ jsx39(
8367
- "div",
8368
- {
8369
- "data-slot": "bulk-action-bar-actions",
8370
- style: {
8371
- display: "flex",
8372
- minWidth: 0,
8373
- flexWrap: inline ? "nowrap" : "wrap",
8374
- alignItems: "center",
8375
- justifyContent: "flex-end",
8376
- gap: 2
8377
- },
8378
- children: actions.map((action) => /* @__PURE__ */ jsx39(ActionButton, { action }, action.key))
8379
- }
8380
- );
8381
8931
  if (inline) {
8932
+ const actionGroup = /* @__PURE__ */ jsx39(
8933
+ "div",
8934
+ {
8935
+ "data-slot": "bulk-action-bar-actions",
8936
+ style: {
8937
+ display: "flex",
8938
+ minWidth: 0,
8939
+ flexWrap: "nowrap",
8940
+ alignItems: "center",
8941
+ justifyContent: "flex-end",
8942
+ gap: 2
8943
+ },
8944
+ children: actions.map((action) => /* @__PURE__ */ jsx39(ActionButton, { action }, action.key))
8945
+ }
8946
+ );
8382
8947
  return /* @__PURE__ */ jsxs35(
8383
8948
  "div",
8384
8949
  {
@@ -8443,6 +9008,7 @@ function BulkActionBar({
8443
9008
  "animate-[olun-bulk-action-bar-in_var(--dur-fast)_var(--ease-out)_both] motion-reduce:animate-none",
8444
9009
  className
8445
9010
  ),
9011
+ ref: setCard,
8446
9012
  style: { ...floatingStyle, ...style },
8447
9013
  ...props,
8448
9014
  children: [
@@ -8454,8 +9020,8 @@ function BulkActionBar({
8454
9020
  style: {
8455
9021
  display: "flex",
8456
9022
  minWidth: 0,
8457
- alignItems: "center",
8458
- gap: "var(--space-2)"
9023
+ flexDirection: "column",
9024
+ rowGap: "var(--space-2)"
8459
9025
  },
8460
9026
  children: [
8461
9027
  countLabel,
@@ -8463,11 +9029,29 @@ function BulkActionBar({
8463
9029
  ]
8464
9030
  }
8465
9031
  ),
8466
- count > 0 && actions.length > 0 ? /* @__PURE__ */ jsx39(Divider, {}) : null,
8467
- actionGroup,
8468
- /* @__PURE__ */ jsx39(Divider, {}),
8469
- /* @__PURE__ */ jsx39(ClearButton, { onClear }),
8470
- trailingSlot
9032
+ actions.length > 0 ? /* @__PURE__ */ jsx39(
9033
+ "div",
9034
+ {
9035
+ "data-slot": "bulk-action-bar-actions",
9036
+ style: {
9037
+ display: "flex",
9038
+ flexWrap: "wrap",
9039
+ justifyContent: "flex-end",
9040
+ gap: "var(--space-2)",
9041
+ marginTop: "var(--space-3)"
9042
+ },
9043
+ children: actions.map((action) => /* @__PURE__ */ jsx39(CardActionButton, { action }, action.key))
9044
+ }
9045
+ ) : null,
9046
+ /* @__PURE__ */ jsx39(
9047
+ IconButton,
9048
+ {
9049
+ icon: X4,
9050
+ "aria-label": "\uC120\uD0DD \uD574\uC81C",
9051
+ onClick: onClear,
9052
+ style: { position: "absolute", top: "var(--space-2)", right: "var(--space-2)" }
9053
+ }
9054
+ )
8471
9055
  ]
8472
9056
  }
8473
9057
  );
@@ -8717,7 +9301,7 @@ function ActionSheet({
8717
9301
  }
8718
9302
 
8719
9303
  // src/components/ui/badge.tsx
8720
- import * as React35 from "react";
9304
+ import * as React37 from "react";
8721
9305
  import { jsx as jsx45 } from "react/jsx-runtime";
8722
9306
  var TONE = {
8723
9307
  neutral: "bg-[var(--fill-on-bg,var(--semantic-neutral-bg))] text-[var(--semantic-neutral-fg)]",
@@ -8727,7 +9311,7 @@ var TONE = {
8727
9311
  error: "bg-[var(--semantic-error-bg)] text-[var(--semantic-error-fg)]",
8728
9312
  brand: "bg-[var(--accent-bg-strong)] text-[var(--accent)]"
8729
9313
  };
8730
- var Badge = React35.forwardRef(
9314
+ var Badge = React37.forwardRef(
8731
9315
  ({ tone = "neutral", className, children, ...props }, ref) => /* @__PURE__ */ jsx45(
8732
9316
  "span",
8733
9317
  {
@@ -8748,7 +9332,7 @@ var Badge = React35.forwardRef(
8748
9332
  Badge.displayName = "Badge";
8749
9333
 
8750
9334
  // src/components/ui/two-tier-badge.tsx
8751
- import * as React36 from "react";
9335
+ import * as React38 from "react";
8752
9336
  import { jsx as jsx46, jsxs as jsxs37 } from "react/jsx-runtime";
8753
9337
  var FG = {
8754
9338
  neutral: "var(--text-secondary)",
@@ -8771,7 +9355,7 @@ var SEGMENT = {
8771
9355
  md: "gap-[7px] py-[var(--space-1)] px-[var(--space-3)] text-[14px]"
8772
9356
  };
8773
9357
  var DOT = { xs: 5, sm: 6, md: 7 };
8774
- var TwoTierBadge = React36.forwardRef(
9358
+ var TwoTierBadge = React38.forwardRef(
8775
9359
  ({ primary, secondary, tone = "neutral", emphasis = "subtle", size = "sm", showDot = false, className, style, ...props }, ref) => {
8776
9360
  const strong = emphasis === "strong";
8777
9361
  const fg = FG[tone];
@@ -8841,7 +9425,7 @@ var TwoTierBadge = React36.forwardRef(
8841
9425
  TwoTierBadge.displayName = "TwoTierBadge";
8842
9426
 
8843
9427
  // src/components/ui/status-badge.tsx
8844
- import * as React37 from "react";
9428
+ import * as React39 from "react";
8845
9429
  import { jsx as jsx47 } from "react/jsx-runtime";
8846
9430
  var ROLE = {
8847
9431
  error: "error",
@@ -8852,13 +9436,13 @@ var ROLE = {
8852
9436
  success: "success",
8853
9437
  archived: "neutral"
8854
9438
  };
8855
- var StatusBadge = React37.forwardRef(
9439
+ var StatusBadge = React39.forwardRef(
8856
9440
  ({ status = "active", emphasis: _emphasis, size: _size, showDot: _showDot, pulse: _pulse, ...props }, ref) => /* @__PURE__ */ jsx47(Badge, { ref, tone: ROLE[status], ...props })
8857
9441
  );
8858
9442
  StatusBadge.displayName = "StatusBadge";
8859
9443
 
8860
9444
  // src/components/ui/status-dot.tsx
8861
- import * as React38 from "react";
9445
+ import * as React40 from "react";
8862
9446
  import { jsx as jsx48, jsxs as jsxs38 } from "react/jsx-runtime";
8863
9447
  var DOT2 = {
8864
9448
  neutral: "bg-[var(--semantic-neutral-fg)]",
@@ -8867,7 +9451,7 @@ var DOT2 = {
8867
9451
  warning: "bg-[var(--semantic-warning-fg)]",
8868
9452
  error: "bg-[var(--semantic-error-fg)]"
8869
9453
  };
8870
- var StatusDot = React38.forwardRef(
9454
+ var StatusDot = React40.forwardRef(
8871
9455
  ({ tone, label, pulse = false, className, ...props }, ref) => /* @__PURE__ */ jsxs38(
8872
9456
  "span",
8873
9457
  {
@@ -8901,9 +9485,9 @@ var StatusDot = React38.forwardRef(
8901
9485
  StatusDot.displayName = "StatusDot";
8902
9486
 
8903
9487
  // src/components/ui/notification-badge.tsx
8904
- import * as React39 from "react";
9488
+ import * as React41 from "react";
8905
9489
  import { cva as cva14 } from "class-variance-authority";
8906
- import { jsx as jsx49 } from "react/jsx-runtime";
9490
+ import { jsx as jsx49, jsxs as jsxs39 } from "react/jsx-runtime";
8907
9491
  var notificationBadgeVariants = cva14(
8908
9492
  [
8909
9493
  "inline-flex shrink-0 items-center justify-center rounded-[var(--radius-full)]",
@@ -8934,7 +9518,7 @@ function formatNotificationCount(count, max) {
8934
9518
  }
8935
9519
  return String(count);
8936
9520
  }
8937
- var NotificationBadge = React39.forwardRef(
9521
+ var NotificationBadge = React41.forwardRef(
8938
9522
  ({
8939
9523
  className,
8940
9524
  count,
@@ -8949,17 +9533,19 @@ var NotificationBadge = React39.forwardRef(
8949
9533
  }
8950
9534
  const normalizedMax = Math.max(1, Math.floor(max));
8951
9535
  const label = ariaLabel ?? (count > normalizedMax ? `\uC77D\uC9C0 \uC54A\uC740 \uC54C\uB9BC ${normalizedMax}\uAC1C \uC774\uC0C1` : `\uC77D\uC9C0 \uC54A\uC740 \uC54C\uB9BC ${count}\uAC1C`);
8952
- return /* @__PURE__ */ jsx49(
9536
+ return /* @__PURE__ */ jsxs39(
8953
9537
  "span",
8954
9538
  {
8955
9539
  ref,
8956
9540
  "data-slot": "notification-badge",
8957
9541
  "data-size": size,
8958
9542
  "data-placement": placement,
8959
- "aria-label": label,
8960
9543
  className: cn(notificationBadgeVariants({ size, placement, className })),
8961
9544
  ...props,
8962
- children: formatNotificationCount(count, normalizedMax)
9545
+ children: [
9546
+ /* @__PURE__ */ jsx49("span", { "aria-hidden": "true", children: formatNotificationCount(count, normalizedMax) }),
9547
+ /* @__PURE__ */ jsx49("span", { className: "sr-only", children: label })
9548
+ ]
8963
9549
  }
8964
9550
  );
8965
9551
  }
@@ -8967,9 +9553,9 @@ var NotificationBadge = React39.forwardRef(
8967
9553
  NotificationBadge.displayName = "NotificationBadge";
8968
9554
 
8969
9555
  // src/components/ui/empty-state.tsx
8970
- import * as React40 from "react";
9556
+ import * as React42 from "react";
8971
9557
  import { cva as cva15 } from "class-variance-authority";
8972
- import { jsx as jsx50, jsxs as jsxs39 } from "react/jsx-runtime";
9558
+ import { jsx as jsx50, jsxs as jsxs40 } from "react/jsx-runtime";
8973
9559
  var emptyStateBaseVariants = cva15(
8974
9560
  [
8975
9561
  "flex flex-col items-center justify-center text-center",
@@ -8995,7 +9581,7 @@ var emptyStateBaseVariants = cva15(
8995
9581
  }
8996
9582
  );
8997
9583
  var PAGE_FILL_QUERY = "(min-width: 768px)";
8998
- var useIsomorphicLayoutEffect3 = typeof window === "undefined" ? React40.useEffect : React40.useLayoutEffect;
9584
+ var useIsomorphicLayoutEffect3 = typeof window === "undefined" ? React42.useEffect : React42.useLayoutEffect;
8999
9585
  function findScrollParent(node) {
9000
9586
  for (let el = node.parentElement; el && el !== document.body && el !== document.documentElement; el = el.parentElement) {
9001
9587
  const { overflowY } = getComputedStyle(el);
@@ -9107,7 +9693,7 @@ var iconSize2 = {
9107
9693
  md: 20,
9108
9694
  lg: 24
9109
9695
  };
9110
- var EmptyState = React40.forwardRef(
9696
+ var EmptyState = React42.forwardRef(
9111
9697
  ({
9112
9698
  className,
9113
9699
  size = "md",
@@ -9123,9 +9709,9 @@ var EmptyState = React40.forwardRef(
9123
9709
  ...props
9124
9710
  }, ref) => {
9125
9711
  const resolvedSize = size ?? "md";
9126
- const pageRef = React40.useRef(null);
9712
+ const pageRef = React42.useRef(null);
9127
9713
  usePageFill(pageRef, layout === "page");
9128
- const box = /* @__PURE__ */ jsxs39(
9714
+ const box = /* @__PURE__ */ jsxs40(
9129
9715
  "div",
9130
9716
  {
9131
9717
  ref,
@@ -9143,7 +9729,7 @@ var EmptyState = React40.forwardRef(
9143
9729
  children: /* @__PURE__ */ jsx50(Icon, { size: iconSize2[resolvedSize], strokeWidth: 1.75 })
9144
9730
  }
9145
9731
  ) : null,
9146
- /* @__PURE__ */ jsxs39("div", { className: "flex max-w-[420px] flex-col items-center gap-[var(--space-2)]", children: [
9732
+ /* @__PURE__ */ jsxs40("div", { className: "flex max-w-[420px] flex-col items-center gap-[var(--space-2)]", children: [
9147
9733
  /* @__PURE__ */ jsx50(
9148
9734
  "h2",
9149
9735
  {
@@ -9189,10 +9775,10 @@ var EmptyState = React40.forwardRef(
9189
9775
  EmptyState.displayName = "EmptyState";
9190
9776
 
9191
9777
  // src/components/ui/error-state.tsx
9192
- import * as React41 from "react";
9778
+ import * as React43 from "react";
9193
9779
  import { AlertTriangle } from "lucide-react";
9194
9780
  import { cva as cva16 } from "class-variance-authority";
9195
- import { jsx as jsx51, jsxs as jsxs40 } from "react/jsx-runtime";
9781
+ import { jsx as jsx51, jsxs as jsxs41 } from "react/jsx-runtime";
9196
9782
  var errorStateVariants = cva16(
9197
9783
  [
9198
9784
  "flex flex-col items-center justify-center text-center",
@@ -9214,7 +9800,7 @@ var errorStateVariants = cva16(
9214
9800
  }
9215
9801
  }
9216
9802
  );
9217
- var ErrorState = React41.forwardRef(
9803
+ var ErrorState = React43.forwardRef(
9218
9804
  ({
9219
9805
  className,
9220
9806
  size = "md",
@@ -9225,7 +9811,7 @@ var ErrorState = React41.forwardRef(
9225
9811
  onRetry,
9226
9812
  retryLabel = "\uB2E4\uC2DC \uC2DC\uB3C4",
9227
9813
  ...props
9228
- }, ref) => /* @__PURE__ */ jsxs40(
9814
+ }, ref) => /* @__PURE__ */ jsxs41(
9229
9815
  "div",
9230
9816
  {
9231
9817
  ref,
@@ -9243,7 +9829,7 @@ var ErrorState = React41.forwardRef(
9243
9829
  children: /* @__PURE__ */ jsx51(AlertTriangle, { size: 24, strokeWidth: 1.75 })
9244
9830
  }
9245
9831
  ),
9246
- /* @__PURE__ */ jsxs40("div", { className: "flex max-w-[420px] flex-col items-center gap-[var(--space-2)]", children: [
9832
+ /* @__PURE__ */ jsxs41("div", { className: "flex max-w-[420px] flex-col items-center gap-[var(--space-2)]", children: [
9247
9833
  /* @__PURE__ */ jsx51(
9248
9834
  "h2",
9249
9835
  {
@@ -9277,7 +9863,7 @@ var ErrorState = React41.forwardRef(
9277
9863
  ErrorState.displayName = "ErrorState";
9278
9864
 
9279
9865
  // src/components/ui/skeleton.tsx
9280
- import * as React42 from "react";
9866
+ import * as React44 from "react";
9281
9867
  import { cva as cva17 } from "class-variance-authority";
9282
9868
  import { jsx as jsx52 } from "react/jsx-runtime";
9283
9869
  var skeletonVariants = cva17(
@@ -9323,7 +9909,7 @@ var spinnerVariants = cva17(
9323
9909
  }
9324
9910
  }
9325
9911
  );
9326
- var Skeleton = React42.forwardRef(
9912
+ var Skeleton = React44.forwardRef(
9327
9913
  ({ className, shape, style, ...props }, ref) => /* @__PURE__ */ jsx52(
9328
9914
  "div",
9329
9915
  {
@@ -9337,7 +9923,7 @@ var Skeleton = React42.forwardRef(
9337
9923
  );
9338
9924
  Skeleton.displayName = "Skeleton";
9339
9925
  var defaultTextWidths = ["92%", "84%", "68%", "76%"];
9340
- var SkeletonText = React42.forwardRef(
9926
+ var SkeletonText = React44.forwardRef(
9341
9927
  ({ className, lines = 3, widths = defaultTextWidths, ...props }, ref) => /* @__PURE__ */ jsx52(
9342
9928
  "div",
9343
9929
  {
@@ -9357,7 +9943,7 @@ var SkeletonText = React42.forwardRef(
9357
9943
  )
9358
9944
  );
9359
9945
  SkeletonText.displayName = "SkeletonText";
9360
- var SkeletonRow = React42.forwardRef(
9946
+ var SkeletonRow = React44.forwardRef(
9361
9947
  ({
9362
9948
  className,
9363
9949
  columns,
@@ -9414,7 +10000,7 @@ var SkeletonRow = React42.forwardRef(
9414
10000
  }
9415
10001
  );
9416
10002
  SkeletonRow.displayName = "SkeletonRow";
9417
- var Spinner = React42.forwardRef(
10003
+ var Spinner = React44.forwardRef(
9418
10004
  ({ className, size, label = "\uB85C\uB529 \uC911", ...props }, ref) => /* @__PURE__ */ jsx52(
9419
10005
  "span",
9420
10006
  {
@@ -9430,12 +10016,12 @@ var Spinner = React42.forwardRef(
9430
10016
  Spinner.displayName = "Spinner";
9431
10017
 
9432
10018
  // src/components/ui/pagination.tsx
9433
- import * as React43 from "react";
10019
+ import * as React45 from "react";
9434
10020
  import { ChevronsLeft, ChevronLeft, ChevronRight as ChevronRight4, ChevronsRight } from "lucide-react";
9435
10021
  import { cva as cva18 } from "class-variance-authority";
9436
10022
 
9437
10023
  // src/components/ui/page-size-select.tsx
9438
- import { jsx as jsx53, jsxs as jsxs41 } from "react/jsx-runtime";
10024
+ import { jsx as jsx53, jsxs as jsxs42 } from "react/jsx-runtime";
9439
10025
  var DEFAULT_OPTIONS = [10, 20, 50, 100];
9440
10026
  function PageSizeSelect({
9441
10027
  value,
@@ -9454,7 +10040,7 @@ function PageSizeSelect({
9454
10040
  label: `${opt}${unit}`
9455
10041
  }));
9456
10042
  const selectSize = size === "compact" ? "sm" : "md";
9457
- return /* @__PURE__ */ jsxs41(
10043
+ return /* @__PURE__ */ jsxs42(
9458
10044
  "div",
9459
10045
  {
9460
10046
  "data-slot": "page-size-select",
@@ -9486,7 +10072,7 @@ function PageSizeSelect({
9486
10072
  }
9487
10073
 
9488
10074
  // src/components/ui/pagination.tsx
9489
- import { jsx as jsx54, jsxs as jsxs42 } from "react/jsx-runtime";
10075
+ import { jsx as jsx54, jsxs as jsxs43 } from "react/jsx-runtime";
9490
10076
  var paginationVariants = cva18(
9491
10077
  [
9492
10078
  "flex w-full flex-col gap-[var(--space-3)]",
@@ -9571,7 +10157,7 @@ function NavigationButton({
9571
10157
  }
9572
10158
  );
9573
10159
  }
9574
- var Pagination = React43.forwardRef(
10160
+ var Pagination = React45.forwardRef(
9575
10161
  ({
9576
10162
  className,
9577
10163
  size = "standard",
@@ -9596,7 +10182,7 @@ var Pagination = React43.forwardRef(
9596
10182
  const items = getPaginationItems(currentPage, pageCount);
9597
10183
  const isFirstPage = currentPage === 1;
9598
10184
  const isLastPage = currentPage === pageCount;
9599
- return /* @__PURE__ */ jsxs42(
10185
+ return /* @__PURE__ */ jsxs43(
9600
10186
  "nav",
9601
10187
  {
9602
10188
  ref,
@@ -9606,7 +10192,7 @@ var Pagination = React43.forwardRef(
9606
10192
  className: cn(paginationVariants({ size: resolvedSize, className })),
9607
10193
  ...props,
9608
10194
  children: [
9609
- /* @__PURE__ */ jsxs42("div", { className: "flex flex-wrap items-center gap-[var(--space-3)]", children: [
10195
+ /* @__PURE__ */ jsxs43("div", { className: "flex flex-wrap items-center gap-[var(--space-3)]", children: [
9610
10196
  /* @__PURE__ */ jsx54("span", { "data-slot": "pagination-total", className: "font-medium text-text-secondary", children: totalLabel(total) }),
9611
10197
  showPageSize ? /* @__PURE__ */ jsx54("div", { "data-slot": "pagination-size", children: /* @__PURE__ */ jsx54(
9612
10198
  PageSizeSelect,
@@ -9620,7 +10206,7 @@ var Pagination = React43.forwardRef(
9620
10206
  }
9621
10207
  ) }) : null
9622
10208
  ] }),
9623
- /* @__PURE__ */ jsxs42(
10209
+ /* @__PURE__ */ jsxs43(
9624
10210
  "div",
9625
10211
  {
9626
10212
  "data-slot": "pagination-list",
@@ -9709,7 +10295,7 @@ Pagination.displayName = "Pagination";
9709
10295
 
9710
10296
  // src/components/ui/table-pagination.tsx
9711
10297
  import { ChevronLeft as ChevronLeft2, ChevronRight as ChevronRight5 } from "lucide-react";
9712
- import { jsx as jsx55, jsxs as jsxs43 } from "react/jsx-runtime";
10298
+ import { jsx as jsx55, jsxs as jsxs44 } from "react/jsx-runtime";
9713
10299
  var TABLE_PAGE_SIZE_OPTIONS = [20, 50, 100];
9714
10300
  function shouldHideTablePagination({
9715
10301
  rangeEnd,
@@ -9739,7 +10325,7 @@ function TablePagination({
9739
10325
  "aria-label": ariaLabel = "\uD398\uC774\uC9C0\uB124\uC774\uC158"
9740
10326
  }) {
9741
10327
  if (shouldHideTablePagination({ rangeEnd, total, hasPrev, hasNext, pageSizeOptions })) return null;
9742
- return /* @__PURE__ */ jsxs43(
10328
+ return /* @__PURE__ */ jsxs44(
9743
10329
  "nav",
9744
10330
  {
9745
10331
  "data-slot": "table-pagination",
@@ -9756,16 +10342,16 @@ function TablePagination({
9756
10342
  className: "shrink-0 max-lg:[&>span:first-child]:hidden"
9757
10343
  }
9758
10344
  ),
9759
- /* @__PURE__ */ jsxs43("div", { className: "flex min-w-0 items-center gap-[var(--space-2)]", children: [
9760
- /* @__PURE__ */ jsxs43("span", { "data-slot": "table-pagination-range", className: "whitespace-nowrap tabular-nums", children: [
9761
- /* @__PURE__ */ jsxs43("span", { className: "font-medium text-text-primary", children: [
10345
+ /* @__PURE__ */ jsxs44("div", { className: "flex min-w-0 items-center gap-[var(--space-2)]", children: [
10346
+ /* @__PURE__ */ jsxs44("span", { "data-slot": "table-pagination-range", className: "whitespace-nowrap tabular-nums", children: [
10347
+ /* @__PURE__ */ jsxs44("span", { className: "font-medium text-text-primary", children: [
9762
10348
  formatCount(rangeStart),
9763
10349
  "\u2013",
9764
10350
  formatCount(rangeEnd)
9765
10351
  ] }),
9766
10352
  total !== void 0 ? /* @__PURE__ */ jsx55("span", { "data-slot": "table-pagination-total", className: "text-text-tertiary @max-[400px]:hidden", children: ` / \uCD1D ${formatCount(total)}${unit}` }) : null
9767
10353
  ] }),
9768
- /* @__PURE__ */ jsxs43("div", { className: "flex shrink-0 items-center gap-[var(--space-1)]", children: [
10354
+ /* @__PURE__ */ jsxs44("div", { className: "flex shrink-0 items-center gap-[var(--space-1)]", children: [
9769
10355
  /* @__PURE__ */ jsx55(
9770
10356
  IconButton,
9771
10357
  {
@@ -9797,7 +10383,7 @@ function TablePagination({
9797
10383
 
9798
10384
  // src/components/ui/mode-toggle.tsx
9799
10385
  import { cva as cva19 } from "class-variance-authority";
9800
- import { jsx as jsx56, jsxs as jsxs44 } from "react/jsx-runtime";
10386
+ import { Fragment as Fragment20, jsx as jsx56, jsxs as jsxs45 } from "react/jsx-runtime";
9801
10387
  var modeToggleVariants = cva19(
9802
10388
  [
9803
10389
  "inline-flex items-center rounded-[var(--radius-md)] border border-[var(--border-subtle)]",
@@ -9820,25 +10406,41 @@ var modeToggleItemVariants = cva19(
9820
10406
  "[&_svg]:pointer-events-none [&_svg]:size-[14px] [&_svg]:shrink-0 [&_svg]:stroke-[1.75]"
9821
10407
  ].join(" ")
9822
10408
  );
10409
+ function formatModeToggleCount(value) {
10410
+ return value > 99 ? "99+" : String(value);
10411
+ }
10412
+ function isShownModeToggleCount(value) {
10413
+ if (value === void 0) return false;
10414
+ if (Number.isInteger(value) && value >= 0) return true;
10415
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
10416
+ console.warn(`ModeToggle: count must be an integer 0 or greater (got ${value}). The count is not shown.`);
10417
+ }
10418
+ return false;
10419
+ }
9823
10420
  function ModeToggle({
9824
10421
  className,
9825
10422
  itemClassName,
9826
10423
  options,
9827
10424
  value,
9828
10425
  onChange,
10426
+ "aria-labelledby": ariaLabelledBy,
10427
+ "aria-describedby": ariaDescribedBy,
9829
10428
  ...props
9830
10429
  }) {
10430
+ const field = useFormFieldControl();
9831
10431
  return /* @__PURE__ */ jsx56(
9832
10432
  "div",
9833
10433
  {
9834
10434
  role: "group",
10435
+ "aria-labelledby": ariaLabelledBy ?? (props["aria-label"] ? void 0 : field?.labelId),
10436
+ "aria-describedby": joinIds(ariaDescribedBy, field?.describedBy),
9835
10437
  "data-slot": "mode-toggle",
9836
10438
  className: cn(modeToggleVariants(), className),
9837
10439
  ...props,
9838
- children: options.map((option) => {
10440
+ children: /* @__PURE__ */ jsx56(FormFieldBoundary, { children: options.map((option) => {
9839
10441
  const Icon = option.icon;
9840
10442
  const isActive = option.value === value;
9841
- return /* @__PURE__ */ jsxs44(
10443
+ return /* @__PURE__ */ jsxs45(
9842
10444
  "button",
9843
10445
  {
9844
10446
  type: "button",
@@ -9855,20 +10457,24 @@ function ModeToggle({
9855
10457
  },
9856
10458
  children: [
9857
10459
  Icon ? /* @__PURE__ */ jsx56(Icon, { "aria-hidden": "true", "data-slot": "mode-toggle-icon" }) : null,
9858
- /* @__PURE__ */ jsx56("span", { children: option.label })
10460
+ /* @__PURE__ */ jsx56("span", { children: option.label }),
10461
+ isShownModeToggleCount(option.count) ? /* @__PURE__ */ jsxs45(Fragment20, { children: [
10462
+ /* @__PURE__ */ jsx56("span", { "aria-hidden": "true", "data-slot": "mode-toggle-count", className: tabsBadgeVariants(), children: formatModeToggleCount(option.count) }),
10463
+ /* @__PURE__ */ jsx56("span", { className: "sr-only", children: ` ${option.count}` })
10464
+ ] }) : null
9859
10465
  ]
9860
10466
  },
9861
10467
  option.value
9862
10468
  );
9863
- })
10469
+ }) })
9864
10470
  }
9865
10471
  );
9866
10472
  }
9867
10473
 
9868
10474
  // src/components/ui/action-footer.tsx
9869
- import * as React44 from "react";
10475
+ import * as React46 from "react";
9870
10476
  import { cva as cva20 } from "class-variance-authority";
9871
- import { jsx as jsx57, jsxs as jsxs45 } from "react/jsx-runtime";
10477
+ import { jsx as jsx57, jsxs as jsxs46 } from "react/jsx-runtime";
9872
10478
  var actionFooterVariants = cva20(
9873
10479
  [
9874
10480
  // Below sm: two fixed rows — destructive actions (start) and status (end) on top, the main
@@ -9967,7 +10573,7 @@ function renderAction(action, className) {
9967
10573
  }
9968
10574
  return /* @__PURE__ */ jsx57(Button, { ...common, ...style, size: "lg", loading: action.loading, children: action.label }, key);
9969
10575
  }
9970
- var ActionFooter = React44.forwardRef(
10576
+ var ActionFooter = React46.forwardRef(
9971
10577
  ({
9972
10578
  className,
9973
10579
  status,
@@ -9980,7 +10586,7 @@ var ActionFooter = React44.forwardRef(
9980
10586
  const visibleActions = actions.filter((action) => canRenderAction(action, permissions));
9981
10587
  const destructiveActions = visibleActions.filter(isDestructive);
9982
10588
  const mainActions = sortMainActions(visibleActions.filter((action) => !isDestructive(action)));
9983
- return /* @__PURE__ */ jsxs45(
10589
+ return /* @__PURE__ */ jsxs46(
9984
10590
  "div",
9985
10591
  {
9986
10592
  ref,
@@ -9997,7 +10603,7 @@ var ActionFooter = React44.forwardRef(
9997
10603
  children: destructiveActions.map((action) => renderAction(action))
9998
10604
  }
9999
10605
  ) : null,
10000
- status ? /* @__PURE__ */ jsxs45(
10606
+ status ? /* @__PURE__ */ jsxs46(
10001
10607
  "div",
10002
10608
  {
10003
10609
  "data-slot": "action-footer-status",
@@ -10037,9 +10643,9 @@ var ActionFooter = React44.forwardRef(
10037
10643
  ActionFooter.displayName = "ActionFooter";
10038
10644
 
10039
10645
  // src/components/ui/toast.tsx
10040
- import * as React45 from "react";
10646
+ import * as React47 from "react";
10041
10647
  import { cva as cva21 } from "class-variance-authority";
10042
- import { jsx as jsx58, jsxs as jsxs46 } from "react/jsx-runtime";
10648
+ import { jsx as jsx58, jsxs as jsxs47 } from "react/jsx-runtime";
10043
10649
  var DOT3 = {
10044
10650
  default: "var(--neutral)",
10045
10651
  success: "var(--success)",
@@ -10071,7 +10677,8 @@ var toastVariants = cva21(
10071
10677
  );
10072
10678
  var toastViewportVariants = cva21(
10073
10679
  [
10074
- "fixed bottom-[var(--space-6)] right-[var(--space-6)] z-[var(--z-toast,50)]",
10680
+ // A floating BulkActionBar publishes --olun-bulk-bar-offset while it is up; sit 8px above it.
10681
+ "fixed bottom-[max(var(--space-6),calc(var(--olun-bulk-bar-offset,0px)+var(--space-2)))] right-[var(--space-6)] z-[var(--z-toast,50)]",
10075
10682
  "flex w-[min(420px,calc(100vw-var(--space-12)))] list-none flex-col gap-[var(--space-2)]",
10076
10683
  "pointer-events-none outline-none"
10077
10684
  ].join(" ")
@@ -10157,7 +10764,7 @@ var toast = {
10157
10764
  }
10158
10765
  };
10159
10766
  var Toast = toast;
10160
- var ToastRoot = React45.forwardRef(
10767
+ var ToastRoot = React47.forwardRef(
10161
10768
  ({
10162
10769
  className,
10163
10770
  id,
@@ -10174,10 +10781,10 @@ var ToastRoot = React45.forwardRef(
10174
10781
  ...props
10175
10782
  }, ref) => {
10176
10783
  const durationMs = getToastDuration({ message, variant, duration });
10177
- const onCloseRef = React45.useRef(onClose);
10784
+ const onCloseRef = React47.useRef(onClose);
10178
10785
  onCloseRef.current = onClose;
10179
- const timerRef = React45.useRef(null);
10180
- React45.useEffect(() => {
10786
+ const timerRef = React47.useRef(null);
10787
+ React47.useEffect(() => {
10181
10788
  if (!onCloseRef.current) return void 0;
10182
10789
  const timer = createToastTimer(durationMs, () => onCloseRef.current?.());
10183
10790
  timerRef.current = timer;
@@ -10186,7 +10793,7 @@ var ToastRoot = React45.forwardRef(
10186
10793
  timerRef.current = null;
10187
10794
  };
10188
10795
  }, [durationMs]);
10189
- return /* @__PURE__ */ jsxs46(
10796
+ return /* @__PURE__ */ jsxs47(
10190
10797
  "div",
10191
10798
  {
10192
10799
  ref,
@@ -10223,7 +10830,7 @@ var ToastRoot = React45.forwardRef(
10223
10830
  style: { background: DOT3[variant] ?? DOT3.default }
10224
10831
  }
10225
10832
  ),
10226
- /* @__PURE__ */ jsxs46("div", { "data-slot": "toast-body", className: "min-w-0 flex-1", children: [
10833
+ /* @__PURE__ */ jsxs47("div", { "data-slot": "toast-body", className: "min-w-0 flex-1", children: [
10227
10834
  /* @__PURE__ */ jsx58(
10228
10835
  "div",
10229
10836
  {
@@ -10241,7 +10848,7 @@ var ToastRoot = React45.forwardRef(
10241
10848
  }
10242
10849
  ) : null
10243
10850
  ] }),
10244
- /* @__PURE__ */ jsxs46("div", { "data-slot": "toast-actions", className: "flex shrink-0 items-center gap-[2px]", children: [
10851
+ /* @__PURE__ */ jsxs47("div", { "data-slot": "toast-actions", className: "flex shrink-0 items-center gap-[2px]", children: [
10245
10852
  action ? /* @__PURE__ */ jsx58(
10246
10853
  Button,
10247
10854
  {
@@ -10275,7 +10882,7 @@ var ToastRoot = React45.forwardRef(
10275
10882
  }
10276
10883
  );
10277
10884
  ToastRoot.displayName = "ToastRoot";
10278
- var ToastViewport = React45.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx58(
10885
+ var ToastViewport = React47.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx58(
10279
10886
  "ol",
10280
10887
  {
10281
10888
  ref,
@@ -10286,24 +10893,24 @@ var ToastViewport = React45.forwardRef(({ className, ...props }, ref) => /* @__P
10286
10893
  ));
10287
10894
  ToastViewport.displayName = "ToastViewport";
10288
10895
  function ToastProvider({ children, maxToasts = 3, className, ...props }) {
10289
- const [items, setItems] = React45.useState([]);
10290
- React45.useEffect(
10896
+ const [items, setItems] = React47.useState([]);
10897
+ React47.useEffect(
10291
10898
  () => toast.subscribe((nextItems) => {
10292
10899
  setItems(limitToasts(nextItems, maxToasts));
10293
10900
  }),
10294
10901
  [maxToasts]
10295
10902
  );
10296
- return /* @__PURE__ */ jsxs46("div", { "data-slot": "toast-provider", className, ...props, children: [
10903
+ return /* @__PURE__ */ jsxs47("div", { "data-slot": "toast-provider", className, ...props, children: [
10297
10904
  children,
10298
10905
  /* @__PURE__ */ jsx58(ToastViewport, { children: items.map((item) => /* @__PURE__ */ jsx58("li", { children: /* @__PURE__ */ jsx58(ToastRoot, { ...item, onClose: () => toast.dismiss(item.id) }) }, item.id)) })
10299
10906
  ] });
10300
10907
  }
10301
10908
 
10302
10909
  // src/components/ui/otp-field.tsx
10303
- import * as React46 from "react";
10910
+ import * as React48 from "react";
10304
10911
  import { cva as cva22 } from "class-variance-authority";
10305
10912
  import { AlertCircle as AlertCircle4 } from "lucide-react";
10306
- import { Fragment as Fragment17, jsx as jsx59, jsxs as jsxs47 } from "react/jsx-runtime";
10913
+ import { Fragment as Fragment21, jsx as jsx59, jsxs as jsxs48 } from "react/jsx-runtime";
10307
10914
  var otpFieldVariants = cva22("flex w-full min-w-0 flex-col gap-[var(--space-3)]", {
10308
10915
  variants: {
10309
10916
  size: {
@@ -10430,7 +11037,7 @@ function fillDigitsFromIndex(slots, index, inserted, length) {
10430
11037
  focusIndex: Math.min(cursor, length - 1)
10431
11038
  };
10432
11039
  }
10433
- var OTPField = React46.forwardRef(
11040
+ var OTPField = React48.forwardRef(
10434
11041
  ({
10435
11042
  className,
10436
11043
  defaultValue,
@@ -10450,26 +11057,34 @@ var OTPField = React46.forwardRef(
10450
11057
  surface = "surface",
10451
11058
  value,
10452
11059
  required,
11060
+ "aria-describedby": ariaDescribedBy,
10453
11061
  ...props
10454
11062
  }, ref) => {
10455
- const generatedId = React46.useId();
11063
+ const formField = useFormFieldControl();
11064
+ const generatedId = React48.useId();
10456
11065
  const fieldId = id ?? generatedId;
10457
- const labelId = `${fieldId}-label`;
10458
- const helperId = helperText ? `${fieldId}-helper` : void 0;
10459
- const errorId = errorText ? `${fieldId}-error` : void 0;
11066
+ const slotId = formField ? generatedId : fieldId;
11067
+ const labelId = `${slotId}-label`;
11068
+ const helperId = helperText ? `${slotId}-helper` : void 0;
11069
+ const errorId = errorText ? `${slotId}-error` : void 0;
10460
11070
  const resolvedState = invalid || errorText ? "error" : "default";
10461
11071
  const isControlled = value !== void 0;
10462
- const [uncontrolledSlots, setUncontrolledSlots] = React46.useState(
11072
+ const [uncontrolledSlots, setUncontrolledSlots] = React48.useState(
10463
11073
  () => toDigitsArray(onlyDigits(defaultValue, length), length)
10464
11074
  );
10465
- const resolvedSlots = React46.useMemo(
11075
+ const resolvedSlots = React48.useMemo(
10466
11076
  () => isControlled ? toDigitsArray(onlyDigits(value, length), length) : uncontrolledSlots,
10467
11077
  [isControlled, length, uncontrolledSlots, value]
10468
11078
  );
10469
11079
  const resolvedValue = joinDigits(resolvedSlots).slice(0, length);
10470
- const cellsRef = React46.useRef([]);
10471
- const groupDescribedBy = [helperId, errorId].filter(Boolean).join(" ") || void 0;
10472
- const setResolvedValue = React46.useCallback(
11080
+ const cellsRef = React48.useRef([]);
11081
+ const groupDescribedBy = joinIds(
11082
+ ariaDescribedBy,
11083
+ helperId,
11084
+ errorId,
11085
+ formField?.describedBy
11086
+ );
11087
+ const setResolvedValue = React48.useCallback(
10473
11088
  (nextSlots, focusIndex) => {
10474
11089
  const normalizedSlots = nextSlots.slice(0, length);
10475
11090
  const normalizedValue = joinDigits(normalizedSlots).slice(0, length);
@@ -10488,7 +11103,7 @@ var OTPField = React46.forwardRef(
10488
11103
  },
10489
11104
  [disabled, isControlled, length, onComplete, onValueChange]
10490
11105
  );
10491
- return /* @__PURE__ */ jsxs47(
11106
+ return /* @__PURE__ */ jsxs48(
10492
11107
  "fieldset",
10493
11108
  {
10494
11109
  ref,
@@ -10501,7 +11116,7 @@ var OTPField = React46.forwardRef(
10501
11116
  className: cn(otpFieldVariants({ size, className })),
10502
11117
  ...props,
10503
11118
  children: [
10504
- /* @__PURE__ */ jsxs47(
11119
+ /* @__PURE__ */ jsxs48(
10505
11120
  "legend",
10506
11121
  {
10507
11122
  id: labelId,
@@ -10625,7 +11240,7 @@ var OTPField = React46.forwardRef(
10625
11240
  "data-slot": "otp-field-message",
10626
11241
  "data-kind": errorText ? "error" : "helper",
10627
11242
  className: otpFieldMessageVariants({ state: resolvedState }),
10628
- children: errorText ? /* @__PURE__ */ jsxs47(Fragment17, { children: [
11243
+ children: errorText ? /* @__PURE__ */ jsxs48(Fragment21, { children: [
10629
11244
  /* @__PURE__ */ jsx59(
10630
11245
  AlertCircle4,
10631
11246
  {
@@ -10659,10 +11274,10 @@ var OTPField = React46.forwardRef(
10659
11274
  OTPField.displayName = "OTPField";
10660
11275
 
10661
11276
  // src/components/ui/search-field.tsx
10662
- import * as React47 from "react";
11277
+ import * as React49 from "react";
10663
11278
  import { Search, X as X5 } from "lucide-react";
10664
11279
  import { cva as cva23 } from "class-variance-authority";
10665
- import { jsx as jsx60, jsxs as jsxs48 } from "react/jsx-runtime";
11280
+ import { jsx as jsx60, jsxs as jsxs49 } from "react/jsx-runtime";
10666
11281
  var searchFieldVariants = cva23("relative flex w-full items-center", {
10667
11282
  variants: {
10668
11283
  size: {
@@ -10727,7 +11342,7 @@ var iconSize3 = {
10727
11342
  function hasVisibleValue(value) {
10728
11343
  return typeof value === "string" ? value.length > 0 : value !== void 0;
10729
11344
  }
10730
- var SearchField = React47.forwardRef(
11345
+ var SearchField = React49.forwardRef(
10731
11346
  ({
10732
11347
  className,
10733
11348
  inputMode = "search",
@@ -10740,15 +11355,18 @@ var SearchField = React47.forwardRef(
10740
11355
  value,
10741
11356
  defaultValue,
10742
11357
  disabled,
11358
+ id,
11359
+ "aria-describedby": ariaDescribedBy,
10743
11360
  ...props
10744
11361
  }, ref) => {
11362
+ const field = useFormFieldControl();
10745
11363
  const resolvedSize = size ?? "md";
10746
- const inputRef = React47.useRef(null);
10747
- const [hasText, setHasText] = React47.useState(
11364
+ const inputRef = React49.useRef(null);
11365
+ const [hasText, setHasText] = React49.useState(
10748
11366
  () => hasVisibleValue(value ?? defaultValue)
10749
11367
  );
10750
- React47.useImperativeHandle(ref, () => inputRef.current);
10751
- React47.useEffect(() => {
11368
+ React49.useImperativeHandle(ref, () => inputRef.current);
11369
+ React49.useEffect(() => {
10752
11370
  if (value !== void 0) {
10753
11371
  setHasText(hasVisibleValue(value));
10754
11372
  }
@@ -10761,7 +11379,7 @@ var SearchField = React47.forwardRef(
10761
11379
  }
10762
11380
  onClear?.();
10763
11381
  };
10764
- return /* @__PURE__ */ jsxs48(
11382
+ return /* @__PURE__ */ jsxs49(
10765
11383
  "div",
10766
11384
  {
10767
11385
  "data-slot": "search-field",
@@ -10783,6 +11401,8 @@ var SearchField = React47.forwardRef(
10783
11401
  {
10784
11402
  ref: inputRef,
10785
11403
  type: "search",
11404
+ id: id ?? field?.controlId,
11405
+ "aria-describedby": joinIds(ariaDescribedBy, field?.describedBy),
10786
11406
  inputMode,
10787
11407
  value,
10788
11408
  defaultValue,
@@ -10818,7 +11438,7 @@ var SearchField = React47.forwardRef(
10818
11438
  SearchField.displayName = "SearchField";
10819
11439
 
10820
11440
  // src/components/ui/checkbox-group.tsx
10821
- import * as React48 from "react";
11441
+ import * as React50 from "react";
10822
11442
  import { cva as cva24 } from "class-variance-authority";
10823
11443
  import { jsx as jsx61 } from "react/jsx-runtime";
10824
11444
  var checkboxGroupVariants = cva24("gap-[var(--space-2)]", {
@@ -10846,7 +11466,7 @@ var checkboxGroupVariants = cva24("gap-[var(--space-2)]", {
10846
11466
  function toSelectionSet(value) {
10847
11467
  return new Set(value ?? []);
10848
11468
  }
10849
- var CheckboxGroup = React48.forwardRef(
11469
+ var CheckboxGroup = React50.forwardRef(
10850
11470
  ({
10851
11471
  className,
10852
11472
  children,
@@ -10859,17 +11479,20 @@ var CheckboxGroup = React48.forwardRef(
10859
11479
  columns = "one",
10860
11480
  density = "comfortable",
10861
11481
  disabled,
11482
+ "aria-labelledby": ariaLabelledBy,
11483
+ "aria-describedby": ariaDescribedBy,
10862
11484
  ...props
10863
11485
  }, ref) => {
11486
+ const field = useFormFieldControl();
10864
11487
  const isControlled = value != null;
10865
- const [uncontrolledValue, setUncontrolledValue] = React48.useState(
11488
+ const [uncontrolledValue, setUncontrolledValue] = React50.useState(
10866
11489
  () => toSelectionSet(defaultValue)
10867
11490
  );
10868
- const selectedValues = React48.useMemo(
11491
+ const selectedValues = React50.useMemo(
10869
11492
  () => isControlled ? toSelectionSet(value) : uncontrolledValue,
10870
11493
  [isControlled, uncontrolledValue, value]
10871
11494
  );
10872
- const toggleValue = React48.useCallback(
11495
+ const toggleValue = React50.useCallback(
10873
11496
  (itemValue, checked) => {
10874
11497
  const nextValues = new Set(selectedValues);
10875
11498
  if (checked) {
@@ -10885,16 +11508,17 @@ var CheckboxGroup = React48.forwardRef(
10885
11508
  },
10886
11509
  [isControlled, onValueChange, selectedValues]
10887
11510
  );
10888
- const contextValue = React48.useMemo(
11511
+ const contextValue = React50.useMemo(
10889
11512
  () => ({
10890
11513
  appearance,
10891
11514
  density,
11515
+ orientation,
10892
11516
  disabled,
10893
11517
  name,
10894
11518
  selectedValues,
10895
11519
  toggleValue
10896
11520
  }),
10897
- [appearance, density, disabled, name, selectedValues, toggleValue]
11521
+ [appearance, density, orientation, disabled, name, selectedValues, toggleValue]
10898
11522
  );
10899
11523
  return /* @__PURE__ */ jsx61(CheckboxGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx61(
10900
11524
  "div",
@@ -10903,6 +11527,8 @@ var CheckboxGroup = React48.forwardRef(
10903
11527
  "data-slot": "checkbox-group",
10904
11528
  "data-appearance": appearance,
10905
11529
  role: "group",
11530
+ "aria-labelledby": ariaLabelledBy ?? (props["aria-label"] ? void 0 : field?.labelId),
11531
+ "aria-describedby": joinIds(ariaDescribedBy, field?.describedBy),
10906
11532
  className: cn(
10907
11533
  checkboxGroupVariants({
10908
11534
  appearance,
@@ -10912,7 +11538,7 @@ var CheckboxGroup = React48.forwardRef(
10912
11538
  className
10913
11539
  ),
10914
11540
  ...props,
10915
- children
11541
+ children: /* @__PURE__ */ jsx61(FormFieldControlContext.Provider, { value: null, children })
10916
11542
  }
10917
11543
  ) });
10918
11544
  }
@@ -10920,11 +11546,11 @@ var CheckboxGroup = React48.forwardRef(
10920
11546
  CheckboxGroup.displayName = "CheckboxGroup";
10921
11547
 
10922
11548
  // src/components/ui/radio-group.tsx
10923
- import * as React49 from "react";
11549
+ import * as React51 from "react";
10924
11550
  import { cva as cva25 } from "class-variance-authority";
10925
11551
  import { Circle } from "lucide-react";
10926
11552
  import { RadioGroup as RadioGroupPrimitive } from "radix-ui";
10927
- import { jsx as jsx62, jsxs as jsxs49 } from "react/jsx-runtime";
11553
+ import { jsx as jsx62, jsxs as jsxs50 } from "react/jsx-runtime";
10928
11554
  var radioGroupVariants = cva25("gap-[var(--space-2)]", {
10929
11555
  variants: {
10930
11556
  appearance: {
@@ -11013,11 +11639,12 @@ var radioControlVariants = cva25(
11013
11639
  }
11014
11640
  }
11015
11641
  );
11016
- var RadioGroupContext = React49.createContext({
11642
+ var RadioGroupContext = React51.createContext({
11017
11643
  appearance: "plain",
11018
- density: "comfortable"
11644
+ density: "comfortable",
11645
+ orientation: "vertical"
11019
11646
  });
11020
- var RadioGroup = React49.forwardRef(
11647
+ var RadioGroup = React51.forwardRef(
11021
11648
  ({
11022
11649
  className,
11023
11650
  children,
@@ -11026,11 +11653,14 @@ var RadioGroup = React49.forwardRef(
11026
11653
  columns = "one",
11027
11654
  density = "comfortable",
11028
11655
  required,
11656
+ "aria-labelledby": ariaLabelledBy,
11657
+ "aria-describedby": ariaDescribedBy,
11029
11658
  ...props
11030
11659
  }, ref) => {
11031
- const contextValue = React49.useMemo(
11032
- () => ({ appearance, density }),
11033
- [appearance, density]
11660
+ const field = useFormFieldControl();
11661
+ const contextValue = React51.useMemo(
11662
+ () => ({ appearance, density, orientation }),
11663
+ [appearance, density, orientation]
11034
11664
  );
11035
11665
  return /* @__PURE__ */ jsx62(RadioGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx62(
11036
11666
  RadioGroupPrimitive.Root,
@@ -11039,6 +11669,8 @@ var RadioGroup = React49.forwardRef(
11039
11669
  "data-slot": "radio-group",
11040
11670
  "data-appearance": appearance,
11041
11671
  "aria-required": required || void 0,
11672
+ "aria-labelledby": ariaLabelledBy ?? (props["aria-label"] ? void 0 : field?.labelId),
11673
+ "aria-describedby": joinIds(ariaDescribedBy, field?.describedBy),
11042
11674
  orientation,
11043
11675
  className: cn(
11044
11676
  radioGroupVariants({
@@ -11049,19 +11681,19 @@ var RadioGroup = React49.forwardRef(
11049
11681
  className
11050
11682
  ),
11051
11683
  ...props,
11052
- children
11684
+ children: /* @__PURE__ */ jsx62(FormFieldControlContext.Provider, { value: null, children })
11053
11685
  }
11054
11686
  ) });
11055
11687
  }
11056
11688
  );
11057
11689
  RadioGroup.displayName = "RadioGroup";
11058
- var Radio = React49.forwardRef(({ className, children, description, id, ...props }, ref) => {
11059
- const { appearance, density } = React49.useContext(RadioGroupContext);
11060
- const generatedId = React49.useId();
11690
+ var Radio = React51.forwardRef(({ className, children, description, id, ...props }, ref) => {
11691
+ const { appearance, density, orientation } = React51.useContext(RadioGroupContext);
11692
+ const generatedId = React51.useId();
11061
11693
  const radioId = id ?? generatedId;
11062
11694
  const labelId = `${radioId}-label`;
11063
11695
  const descriptionId = description ? `${radioId}-description` : void 0;
11064
- return /* @__PURE__ */ jsxs49(
11696
+ return /* @__PURE__ */ jsxs50(
11065
11697
  RadioGroupPrimitive.Item,
11066
11698
  {
11067
11699
  ref,
@@ -11069,7 +11701,12 @@ var Radio = React49.forwardRef(({ className, children, description, id, ...props
11069
11701
  "data-slot": "radio",
11070
11702
  "aria-labelledby": labelId,
11071
11703
  "aria-describedby": descriptionId,
11072
- className: cn(radioVariants({ appearance, density }), className),
11704
+ className: cn(
11705
+ radioVariants({ appearance, density }),
11706
+ // plain rows sit side by side only at content width; w-full would wrap each one.
11707
+ appearance === "plain" && orientation === "horizontal" && "w-auto",
11708
+ className
11709
+ ),
11073
11710
  ...props,
11074
11711
  children: [
11075
11712
  /* @__PURE__ */ jsx62(
@@ -11088,7 +11725,7 @@ var Radio = React49.forwardRef(({ className, children, description, id, ...props
11088
11725
  )
11089
11726
  }
11090
11727
  ),
11091
- /* @__PURE__ */ jsxs49("span", { className: "flex min-w-0 flex-col gap-[var(--space-1)]", children: [
11728
+ /* @__PURE__ */ jsxs50("span", { className: "flex min-w-0 flex-col gap-[var(--space-1)]", children: [
11092
11729
  /* @__PURE__ */ jsx62(
11093
11730
  "span",
11094
11731
  {
@@ -11119,13 +11756,13 @@ Radio.displayName = "Radio";
11119
11756
 
11120
11757
  // src/components/ui/scroll-area.tsx
11121
11758
  import { ScrollArea as ScrollAreaPrimitive } from "radix-ui";
11122
- import { jsx as jsx63, jsxs as jsxs50 } from "react/jsx-runtime";
11759
+ import { jsx as jsx63, jsxs as jsxs51 } from "react/jsx-runtime";
11123
11760
  function ScrollArea({
11124
11761
  className,
11125
11762
  children,
11126
11763
  ...props
11127
11764
  }) {
11128
- return /* @__PURE__ */ jsxs50(
11765
+ return /* @__PURE__ */ jsxs51(
11129
11766
  ScrollAreaPrimitive.Root,
11130
11767
  {
11131
11768
  "data-slot": "scroll-area",
@@ -11225,10 +11862,10 @@ function Progress({
11225
11862
  }
11226
11863
 
11227
11864
  // src/components/ui/tree-view.tsx
11228
- import * as React50 from "react";
11865
+ import * as React52 from "react";
11229
11866
  import { ChevronRight as ChevronRight6 } from "lucide-react";
11230
11867
  import { cva as cva26 } from "class-variance-authority";
11231
- import { jsx as jsx65, jsxs as jsxs51 } from "react/jsx-runtime";
11868
+ import { jsx as jsx65, jsxs as jsxs52 } from "react/jsx-runtime";
11232
11869
  var treeViewVariants = cva26(
11233
11870
  "m-0 list-none p-[var(--space-1)] text-body-sm text-foreground"
11234
11871
  );
@@ -11331,27 +11968,27 @@ function TreeView({
11331
11968
  ...rest
11332
11969
  }) {
11333
11970
  const isExpandedControlled = expandedIds !== void 0;
11334
- const [internalExpanded, setInternalExpanded] = React50.useState(
11971
+ const [internalExpanded, setInternalExpanded] = React52.useState(
11335
11972
  () => defaultExpandedIds ?? []
11336
11973
  );
11337
11974
  const expandedList = isExpandedControlled ? expandedIds : internalExpanded;
11338
- const expandedSet = React50.useMemo(() => new Set(expandedList), [expandedList]);
11339
- const items = React50.useMemo(
11975
+ const expandedSet = React52.useMemo(() => new Set(expandedList), [expandedList]);
11976
+ const items = React52.useMemo(
11340
11977
  () => flattenVisibleNodes(nodes, getChildren, expandedSet),
11341
11978
  [nodes, getChildren, expandedSet]
11342
11979
  );
11343
- const [focusedId, setFocusedId] = React50.useState(null);
11980
+ const [focusedId, setFocusedId] = React52.useState(null);
11344
11981
  const visibleIds = items.map((item) => item.id);
11345
11982
  const activeId = focusedId && visibleIds.includes(focusedId) ? focusedId : selectedId && visibleIds.includes(selectedId) ? selectedId : visibleIds[0] ?? null;
11346
- const itemRefs = React50.useRef(/* @__PURE__ */ new Map());
11347
- const commitExpanded = React50.useCallback(
11983
+ const itemRefs = React52.useRef(/* @__PURE__ */ new Map());
11984
+ const commitExpanded = React52.useCallback(
11348
11985
  (next) => {
11349
11986
  if (!isExpandedControlled) setInternalExpanded(next);
11350
11987
  onExpandedChange?.(next);
11351
11988
  },
11352
11989
  [isExpandedControlled, onExpandedChange]
11353
11990
  );
11354
- const setExpanded = React50.useCallback(
11991
+ const setExpanded = React52.useCallback(
11355
11992
  (id, expand) => {
11356
11993
  const has = expandedSet.has(id);
11357
11994
  if (expand && !has) {
@@ -11362,7 +11999,7 @@ function TreeView({
11362
11999
  },
11363
12000
  [commitExpanded, expandedList, expandedSet]
11364
12001
  );
11365
- const focusItem = React50.useCallback((id) => {
12002
+ const focusItem = React52.useCallback((id) => {
11366
12003
  setFocusedId(id);
11367
12004
  itemRefs.current.get(id)?.focus();
11368
12005
  }, []);
@@ -11398,7 +12035,7 @@ function TreeView({
11398
12035
  const selected = node.id === selectedId;
11399
12036
  const isActive = node.id === activeId;
11400
12037
  const itemState = { expanded, selected, depth, hasChildren };
11401
- return /* @__PURE__ */ jsxs51(
12038
+ return /* @__PURE__ */ jsxs52(
11402
12039
  "li",
11403
12040
  {
11404
12041
  ref: (element) => {
@@ -11423,7 +12060,7 @@ function TreeView({
11423
12060
  onSelect?.(node.id, node);
11424
12061
  },
11425
12062
  children: [
11426
- /* @__PURE__ */ jsxs51(
12063
+ /* @__PURE__ */ jsxs52(
11427
12064
  "span",
11428
12065
  {
11429
12066
  "data-slot": "treeitem-row",
@@ -11491,7 +12128,7 @@ function TreeView({
11491
12128
 
11492
12129
  // src/components/branding/olun-logo.tsx
11493
12130
  import { OLUN_MASTER, OLUN_SYMBOL, OLUN_WORDMARK } from "@olundot/tokens/brand";
11494
- import { Fragment as Fragment18, jsx as jsx66, jsxs as jsxs52 } from "react/jsx-runtime";
12131
+ import { Fragment as Fragment22, jsx as jsx66, jsxs as jsxs53 } from "react/jsx-runtime";
11495
12132
  var ACCENT_FILL = "var(--accent-pop)";
11496
12133
  var INK = { color: "var(--text-primary)" };
11497
12134
  var INK_TIGHT = { ...INK, display: "block", overflow: "visible" };
@@ -11501,7 +12138,7 @@ function symbolGeometry(size) {
11501
12138
  function SymbolCircles({ size }) {
11502
12139
  const { ring } = OLUN_SYMBOL;
11503
12140
  const g = symbolGeometry(size);
11504
- return /* @__PURE__ */ jsxs52(Fragment18, { children: [
12141
+ return /* @__PURE__ */ jsxs53(Fragment22, { children: [
11505
12142
  /* @__PURE__ */ jsx66(
11506
12143
  "circle",
11507
12144
  {
@@ -11542,7 +12179,7 @@ function OlunLogo({
11542
12179
  if (!showSymbol) {
11543
12180
  const { full } = OLUN_WORDMARK;
11544
12181
  const height2 = fontSize * full.height / OLUN_WORDMARK.unitsPerEm;
11545
- return /* @__PURE__ */ jsxs52(
12182
+ return /* @__PURE__ */ jsxs53(
11546
12183
  "svg",
11547
12184
  {
11548
12185
  width: height2 * full.width / full.height,
@@ -11572,7 +12209,7 @@ function OlunLogo({
11572
12209
  }
11573
12210
  const layout = symbolSize > OLUN_SYMBOL.smallMax ? OLUN_MASTER.large : OLUN_MASTER.small;
11574
12211
  const height = symbolSize * layout.height / (OLUN_SYMBOL.box * layout.symbol.scale);
11575
- return /* @__PURE__ */ jsxs52(
12212
+ return /* @__PURE__ */ jsxs53(
11576
12213
  "svg",
11577
12214
  {
11578
12215
  width: height * layout.width / layout.height,