@flytedan/flytebot-design-system 0.12.4 → 0.12.6

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.cjs CHANGED
@@ -253,6 +253,11 @@ function Button({
253
253
  );
254
254
  }
255
255
 
256
+ // src/components/actions/overflowRowContext.ts
257
+ var React = __toESM(require("react"), 1);
258
+ var OverflowRowContext = React.createContext(false);
259
+ var useOverflowRow = () => React.useContext(OverflowRowContext);
260
+
256
261
  // src/components/actions/IconButton.tsx
257
262
  var import_jsx_runtime2 = require("react/jsx-runtime");
258
263
  function IconButton({
@@ -266,19 +271,24 @@ function IconButton({
266
271
  className = "",
267
272
  ...rest
268
273
  }) {
274
+ const overflowRow = useOverflowRow();
269
275
  const cls = [
270
276
  "fd-btn-icon",
271
277
  variant === "outline" ? "fd-btn-icon-outline" : variant === "solid" ? "fd-btn-icon-solid" : "",
272
278
  tone !== "neutral" ? "is-" + tone : "",
273
279
  size === "sm" ? "fd-btn-icon-sm" : size === "lg" ? "fd-btn-icon-lg" : "",
274
280
  round ? "fd-btn-icon-round" : "",
281
+ overflowRow ? "fd-btn-icon-row" : "",
275
282
  className
276
283
  ].filter(Boolean).join(" ");
277
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: cls, "aria-label": label, title: label, disabled, ...rest, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", { className: "ph ph-" + icon, "aria-hidden": "true" }) });
284
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { type: "button", className: cls, "aria-label": label, title: label, disabled, ...rest, children: [
285
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", { className: "ph ph-" + icon, "aria-hidden": "true" }),
286
+ overflowRow ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "fd-btn-icon-row-label", children: label }) : null
287
+ ] });
278
288
  }
279
289
 
280
290
  // src/components/actions/Popover.tsx
281
- var React = __toESM(require("react"), 1);
291
+ var React2 = __toESM(require("react"), 1);
282
292
  var import_react_dom = require("react-dom");
283
293
  var import_jsx_runtime3 = require("react/jsx-runtime");
284
294
  var MARGIN = 8;
@@ -310,12 +320,12 @@ function measureLayer(el) {
310
320
  function usePopoverPosition(open, anchorRef, opts) {
311
321
  const o = opts || {};
312
322
  const { side: wantSide, align } = parsePlacement(o.placement);
313
- const [pos, setPos] = React.useState(null);
314
- const posRef = React.useRef(null);
315
- const detachRef = React.useRef(o.onDetach);
323
+ const [pos, setPos] = React2.useState(null);
324
+ const posRef = React2.useRef(null);
325
+ const detachRef = React2.useRef(o.onDetach);
316
326
  detachRef.current = o.onDetach;
317
327
  const layerRef = o.layerRef;
318
- React.useLayoutEffect(() => {
328
+ React2.useLayoutEffect(() => {
319
329
  if (!open || !anchorRef || !anchorRef.current) {
320
330
  posRef.current = null;
321
331
  setPos(null);
@@ -390,8 +400,8 @@ var portal = (node) => {
390
400
  };
391
401
  var ROOT_LAYER = 0;
392
402
  var LAYER_STEP = 10;
393
- var LayerContext = React.createContext(ROOT_LAYER);
394
- var useLayer = () => React.useContext(LayerContext);
403
+ var LayerContext = React2.createContext(ROOT_LAYER);
404
+ var useLayer = () => React2.useContext(LayerContext);
395
405
  var useOverlayLayer = (base) => {
396
406
  const parent = useLayer();
397
407
  return parent === ROOT_LAYER ? base : parent + LAYER_STEP;
@@ -421,7 +431,7 @@ function Popover({
421
431
  footer,
422
432
  children
423
433
  }) {
424
- const ref = React.useRef(null);
434
+ const ref = React2.useRef(null);
425
435
  const pos = usePopoverPosition(!!open, anchorRef, {
426
436
  placement,
427
437
  offset,
@@ -433,9 +443,9 @@ function Popover({
433
443
  onDetach: onClose,
434
444
  layerRef: ref
435
445
  });
436
- const restore = React.useRef(null);
446
+ const restore = React2.useRef(null);
437
447
  const zIndex = useOverlayLayer(POPOVER_BASE);
438
- React.useEffect(() => {
448
+ React2.useEffect(() => {
439
449
  if (!open) return;
440
450
  restore.current = typeof document !== "undefined" ? document.activeElement : null;
441
451
  return () => {
@@ -447,7 +457,7 @@ function Popover({
447
457
  }
448
458
  };
449
459
  }, [open, returnFocus]);
450
- React.useEffect(() => {
460
+ React2.useEffect(() => {
451
461
  if (!open) return;
452
462
  const away = (e) => {
453
463
  if (!closeOnOutside) return;
@@ -521,12 +531,12 @@ function Popover({
521
531
  }
522
532
  var isItem = (it) => !!it && it.kind !== "separator" && it.kind !== "section" && it.kind !== "custom" && !it.disabled;
523
533
  function Menu({ items = [], onSelect, onClose, autoFocus = true, className = "", footer, header }) {
524
- const listRef = React.useRef(null);
525
- const [active, setActive] = React.useState(() => items.findIndex(isItem));
526
- const [openSub, setOpenSub] = React.useState(null);
527
- const subAnchor = React.useRef(null);
528
- const typed = React.useRef({ s: "", t: 0 });
529
- React.useEffect(() => {
534
+ const listRef = React2.useRef(null);
535
+ const [active, setActive] = React2.useState(() => items.findIndex(isItem));
536
+ const [openSub, setOpenSub] = React2.useState(null);
537
+ const subAnchor = React2.useRef(null);
538
+ const typed = React2.useRef({ s: "", t: 0 });
539
+ React2.useEffect(() => {
530
540
  if (autoFocus && listRef.current) listRef.current.focus({ preventScroll: true });
531
541
  }, [autoFocus]);
532
542
  const move = (dir) => {
@@ -588,7 +598,7 @@ function Menu({ items = [], onSelect, onClose, autoFocus = true, className = "",
588
598
  }
589
599
  };
590
600
  const sub = openSub != null ? items[openSub] : null;
591
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(React.Fragment, { children: [
601
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(React2.Fragment, { children: [
592
602
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "fd-menu-frame", children: [
593
603
  header != null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "fd-menu-header", children: header }) : null,
594
604
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
@@ -702,9 +712,9 @@ function MenuButton({
702
712
  header,
703
713
  footer
704
714
  }) {
705
- const [open, setOpen] = React.useState(false);
706
- const ref = React.useRef(null);
707
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(React.Fragment, { children: [
715
+ const [open, setOpen] = React2.useState(false);
716
+ const ref = React2.useRef(null);
717
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(React2.Fragment, { children: [
708
718
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
709
719
  "button",
710
720
  {
@@ -797,7 +807,7 @@ function CardRow({ label, children, className = "" }) {
797
807
  }
798
808
 
799
809
  // src/components/surfaces/Collapsible.tsx
800
- var React2 = __toESM(require("react"), 1);
810
+ var React3 = __toESM(require("react"), 1);
801
811
  var import_jsx_runtime6 = require("react/jsx-runtime");
802
812
  function Collapsible({
803
813
  title,
@@ -811,7 +821,7 @@ function Collapsible({
811
821
  className = "",
812
822
  ...rest
813
823
  }) {
814
- const [internal, setInternal] = React2.useState(defaultOpen);
824
+ const [internal, setInternal] = React3.useState(defaultOpen);
815
825
  const isOpen = open === void 0 ? internal : open;
816
826
  const toggle = () => {
817
827
  if (open === void 0) setInternal(!isOpen);
@@ -832,19 +842,19 @@ function Collapsible({
832
842
  }
833
843
 
834
844
  // src/components/surfaces/Drawer.tsx
835
- var React3 = __toESM(require("react"), 1);
845
+ var React4 = __toESM(require("react"), 1);
836
846
  var import_react_dom2 = require("react-dom");
837
847
  var import_jsx_runtime7 = require("react/jsx-runtime");
838
848
  var DRAWER_BASE = 90;
839
849
  function Drawer({ open = true, title, onClose, footer, children, className = "", ...rest }) {
840
850
  const zIndex = useOverlayLayer(DRAWER_BASE);
841
- const [closing, setClosing] = React3.useState(false);
842
- const close = React3.useCallback(() => {
851
+ const [closing, setClosing] = React4.useState(false);
852
+ const close = React4.useCallback(() => {
843
853
  if (!onClose) return;
844
854
  setClosing(true);
845
855
  setTimeout(onClose, 210);
846
856
  }, [onClose]);
847
- React3.useEffect(() => {
857
+ React4.useEffect(() => {
848
858
  if (!open || !onClose) return;
849
859
  const h = (e) => {
850
860
  if (e.key === "Escape") close();
@@ -870,17 +880,17 @@ function Drawer({ open = true, title, onClose, footer, children, className = "",
870
880
  }
871
881
 
872
882
  // src/components/surfaces/Modal.tsx
873
- var React4 = __toESM(require("react"), 1);
883
+ var React5 = __toESM(require("react"), 1);
874
884
  var import_react_dom3 = require("react-dom");
875
885
  var import_jsx_runtime8 = require("react/jsx-runtime");
876
886
  function Modal({ open = true, title, description, onClose, footer, wide = false, children, className = "", ...rest }) {
877
- const [closing, setClosing] = React4.useState(false);
878
- const close = React4.useCallback(() => {
887
+ const [closing, setClosing] = React5.useState(false);
888
+ const close = React5.useCallback(() => {
879
889
  if (!onClose) return;
880
890
  setClosing(true);
881
891
  setTimeout(onClose, 190);
882
892
  }, [onClose]);
883
- React4.useEffect(() => {
893
+ React5.useEffect(() => {
884
894
  if (!open || !onClose) return;
885
895
  const h = (e) => {
886
896
  if (e.key === "Escape") close();
@@ -1107,13 +1117,13 @@ function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
1107
1117
  }
1108
1118
 
1109
1119
  // src/components/navigation/Topbar.tsx
1110
- var React5 = __toESM(require("react"), 1);
1120
+ var React6 = __toESM(require("react"), 1);
1111
1121
  var import_jsx_runtime16 = require("react/jsx-runtime");
1112
1122
  function useIsNarrow(breakpoint) {
1113
- const [narrow, setNarrow] = React5.useState(
1123
+ const [narrow, setNarrow] = React6.useState(
1114
1124
  () => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
1115
1125
  );
1116
- React5.useEffect(() => {
1126
+ React6.useEffect(() => {
1117
1127
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
1118
1128
  const mq = window.matchMedia(`(max-width: ${breakpoint}px)`);
1119
1129
  const apply = () => setNarrow(mq.matches);
@@ -1134,11 +1144,11 @@ function Topbar({
1134
1144
  ...rest
1135
1145
  }) {
1136
1146
  const narrow = useIsNarrow(overflowBreakpoint);
1137
- const [moreOpen, setMoreOpen] = React5.useState(false);
1138
- const moreRef = React5.useRef(null);
1147
+ const [moreOpen, setMoreOpen] = React6.useState(false);
1148
+ const moreRef = React6.useRef(null);
1139
1149
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("header", { className: ["fd-topbar", narrow ? "is-narrow" : "", className].filter(Boolean).join(" "), ...rest, children: [
1140
1150
  onMenu ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Menu", onClick: onMenu, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("i", { className: "ph ph-list" }) }) : null,
1141
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(React5.Fragment, { children: [
1151
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(React6.Fragment, { children: [
1142
1152
  i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("i", { className: "ph ph-caret-right", style: { fontSize: 11, opacity: 0.6 }, "aria-hidden": "true" }) : null,
1143
1153
  i === crumbs.length - 1 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fd-crumb-current", children: c.label }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1144
1154
  "a",
@@ -1177,7 +1187,7 @@ function Topbar({
1177
1187
  padded: true,
1178
1188
  label: "More actions",
1179
1189
  className: "fd-topbar-overflow",
1180
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "fd-stack fd-topbar-overflow-list", children: overflowActions })
1190
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "fd-stack fd-topbar-overflow-list", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(OverflowRowContext.Provider, { value: true, children: overflowActions }) })
1181
1191
  }
1182
1192
  )
1183
1193
  ] }) : overflowActions : null,
@@ -1343,19 +1353,19 @@ function Toast({ title, children, tone = "success", onUndo, onDismiss, className
1343
1353
  }
1344
1354
 
1345
1355
  // src/components/feedback/Tooltip.tsx
1346
- var React6 = __toESM(require("react"), 1);
1356
+ var React7 = __toESM(require("react"), 1);
1347
1357
  var import_jsx_runtime24 = require("react/jsx-runtime");
1348
1358
  var TOOLTIP_BASE = 150;
1349
1359
  var CLOSE_DELAY_MS = 120;
1350
1360
  function Tooltip({ label, placement = "top", children, className = "" }) {
1351
- const anchorRef = React6.useRef(null);
1352
- const bubbleRef = React6.useRef(null);
1353
- const [reason, setReason] = React6.useState(null);
1354
- const closeTimer = React6.useRef(null);
1355
- const id = React6.useId();
1361
+ const anchorRef = React7.useRef(null);
1362
+ const bubbleRef = React7.useRef(null);
1363
+ const [reason, setReason] = React7.useState(null);
1364
+ const closeTimer = React7.useRef(null);
1365
+ const id = React7.useId();
1356
1366
  const descId = id + "-desc";
1357
1367
  const open = reason != null;
1358
- const cancelClose = React6.useCallback(() => {
1368
+ const cancelClose = React7.useCallback(() => {
1359
1369
  if (closeTimer.current) {
1360
1370
  clearTimeout(closeTimer.current);
1361
1371
  closeTimer.current = null;
@@ -1365,7 +1375,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
1365
1375
  cancelClose();
1366
1376
  setReason(why);
1367
1377
  };
1368
- const hide = React6.useCallback(() => {
1378
+ const hide = React7.useCallback(() => {
1369
1379
  cancelClose();
1370
1380
  setReason(null);
1371
1381
  }, [cancelClose]);
@@ -1380,7 +1390,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
1380
1390
  setReason((r) => r === "hover" ? null : r);
1381
1391
  }, CLOSE_DELAY_MS);
1382
1392
  };
1383
- React6.useEffect(() => cancelClose, [cancelClose]);
1393
+ React7.useEffect(() => cancelClose, [cancelClose]);
1384
1394
  const pos = usePopoverPosition(open, anchorRef, {
1385
1395
  placement: placement === "bottom" ? "bottom-center" : "top-center",
1386
1396
  offset: 8,
@@ -1390,7 +1400,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
1390
1400
  onDetach: hide
1391
1401
  });
1392
1402
  const zIndex = useOverlayLayer(TOOLTIP_BASE);
1393
- React6.useEffect(() => {
1403
+ React7.useEffect(() => {
1394
1404
  if (!open) return;
1395
1405
  const key = (e) => {
1396
1406
  if (e.key === "Escape") hide();
@@ -1418,7 +1428,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
1418
1428
  }
1419
1429
  if (keyboard) show("focus");
1420
1430
  };
1421
- const described = React6.isValidElement(children) ? React6.cloneElement(children, {
1431
+ const described = React7.isValidElement(children) ? React7.cloneElement(children, {
1422
1432
  "aria-describedby": [children.props["aria-describedby"], descId].filter(Boolean).join(" ")
1423
1433
  }) : children;
1424
1434
  return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
@@ -1426,7 +1436,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
1426
1436
  {
1427
1437
  ref: anchorRef,
1428
1438
  className: "fd-tooltip-anchor",
1429
- "aria-describedby": React6.isValidElement(children) ? void 0 : descId,
1439
+ "aria-describedby": React7.isValidElement(children) ? void 0 : descId,
1430
1440
  onPointerEnter: (e) => {
1431
1441
  if (isMouse(e)) hover();
1432
1442
  },
@@ -1470,7 +1480,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
1470
1480
  }
1471
1481
 
1472
1482
  // src/components/data/Clamp.tsx
1473
- var React7 = __toESM(require("react"), 1);
1483
+ var React8 = __toESM(require("react"), 1);
1474
1484
  var import_jsx_runtime25 = require("react/jsx-runtime");
1475
1485
  function Clamp({
1476
1486
  children,
@@ -1482,16 +1492,16 @@ function Clamp({
1482
1492
  onToggle,
1483
1493
  className = ""
1484
1494
  }) {
1485
- const [open, setOpen] = React7.useState(false);
1486
- const [overflows, setOverflows] = React7.useState(false);
1487
- const bodyRef = React7.useRef(null);
1488
- const charClamped = React7.useMemo(() => {
1495
+ const [open, setOpen] = React8.useState(false);
1496
+ const [overflows, setOverflows] = React8.useState(false);
1497
+ const bodyRef = React8.useRef(null);
1498
+ const charClamped = React8.useMemo(() => {
1489
1499
  if (open || !maxChars || typeof text !== "string" || text.length <= maxChars) return null;
1490
1500
  const cut = text.slice(0, maxChars);
1491
1501
  const at = cut.lastIndexOf(" ");
1492
1502
  return (at > maxChars * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
1493
1503
  }, [text, maxChars, open]);
1494
- React7.useLayoutEffect(() => {
1504
+ React8.useLayoutEffect(() => {
1495
1505
  const node = bodyRef.current;
1496
1506
  if (maxChars || !node || !maxHeight) return;
1497
1507
  const measure = () => {
@@ -1630,17 +1640,19 @@ function DataTable({
1630
1640
  }
1631
1641
 
1632
1642
  // src/components/data/FilterBar.tsx
1633
- var React8 = __toESM(require("react"), 1);
1643
+ var React9 = __toESM(require("react"), 1);
1634
1644
  var import_jsx_runtime28 = require("react/jsx-runtime");
1645
+ var FILTER_BAR_BASE = 120;
1635
1646
  var isSet = (v) => !(v == null || v === "" || v === false);
1636
1647
  function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align = "left", className = "", ...rest }) {
1637
- const [panel, setPanel] = React8.useState(null);
1638
- const rootRef = React8.useRef(null);
1639
- const textInputRef = React8.useRef(null);
1640
- const optionsRef = React8.useRef(null);
1648
+ const [panel, setPanel] = React9.useState(null);
1649
+ const zIndex = useOverlayLayer(FILTER_BAR_BASE);
1650
+ const rootRef = React9.useRef(null);
1651
+ const textInputRef = React9.useRef(null);
1652
+ const optionsRef = React9.useRef(null);
1641
1653
  const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
1642
1654
  const dismissible = !!panel && (panel.kind === "add" || panel.kind === "edit" && editingField?.type === "select");
1643
- React8.useEffect(() => {
1655
+ React9.useEffect(() => {
1644
1656
  if (!dismissible) return;
1645
1657
  const away = (e) => {
1646
1658
  if (rootRef.current && !rootRef.current.contains(e.target)) setPanel(null);
@@ -1655,7 +1667,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
1655
1667
  document.removeEventListener("keydown", esc);
1656
1668
  };
1657
1669
  }, [dismissible]);
1658
- React8.useEffect(() => {
1670
+ React9.useEffect(() => {
1659
1671
  if (!panel || panel.kind !== "edit") return;
1660
1672
  if (editingField?.type === "text") {
1661
1673
  textInputRef.current?.focus();
@@ -1725,11 +1737,11 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
1725
1737
  field.label,
1726
1738
  chosen ? ": " + chosen.label : ""
1727
1739
  ] }),
1728
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1740
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1729
1741
  "span",
1730
1742
  {
1731
1743
  className: "fd-view-enter",
1732
- style: { position: "absolute", top: "calc(100% + 6px)", left: 0, zIndex: 120, minWidth: 200, maxWidth: "calc(100vw - 32px)", display: "block", background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 10, boxShadow: "0 16px 44px rgba(11,13,17,.18)", padding: 8 },
1744
+ style: { position: "absolute", top: "calc(100% + 6px)", left: 0, zIndex, minWidth: 200, maxWidth: "calc(100vw - 32px)", display: "block", background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 10, boxShadow: "0 16px 44px rgba(11,13,17,.18)", padding: 8 },
1733
1745
  children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "fd-stack", role: "listbox", "aria-label": field.label, ref: optionsRef, style: { gap: 2 }, children: field.options.map((o) => {
1734
1746
  const on = o.value === value;
1735
1747
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
@@ -1750,7 +1762,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
1750
1762
  );
1751
1763
  }) })
1752
1764
  }
1753
- )
1765
+ ) })
1754
1766
  ] }, field.key);
1755
1767
  }
1756
1768
  if (isSet(value)) {
@@ -1777,11 +1789,11 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
1777
1789
  children: "Filter"
1778
1790
  }
1779
1791
  ),
1780
- panel?.kind === "add" ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1792
+ panel?.kind === "add" ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1781
1793
  "span",
1782
1794
  {
1783
1795
  className: "fd-view-enter",
1784
- style: { position: "absolute", top: "calc(100% + 6px)", [align]: 0, zIndex: 120, width: 220, maxWidth: "calc(100vw - 32px)", display: "block", background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 10, boxShadow: "0 16px 44px rgba(11,13,17,.18)", padding: 8 },
1796
+ style: { position: "absolute", top: "calc(100% + 6px)", [align]: 0, zIndex, width: 220, maxWidth: "calc(100vw - 32px)", display: "block", background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 10, boxShadow: "0 16px 44px rgba(11,13,17,.18)", padding: 8 },
1785
1797
  children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "fd-stack", role: "menu", "aria-label": "Add filter", style: { gap: 2 }, children: [
1786
1798
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "4px 8px 6px" }, children: "Add filter" }),
1787
1799
  addableFields.map((f) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
@@ -1798,7 +1810,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
1798
1810
  ))
1799
1811
  ] })
1800
1812
  }
1801
- ) : null
1813
+ ) }) : null
1802
1814
  ] }) : null
1803
1815
  ] });
1804
1816
  }
@@ -1821,7 +1833,7 @@ function StatTile({ label, value, sub, delta, loading = false, compact: compact3
1821
1833
  }
1822
1834
 
1823
1835
  // src/components/data/CodeBlock.tsx
1824
- var React9 = __toESM(require("react"), 1);
1836
+ var React10 = __toESM(require("react"), 1);
1825
1837
  var import_jsx_runtime30 = require("react/jsx-runtime");
1826
1838
  var JS_KW = /^(?:const|let|var|function|return|if|else|for|while|do|new|class|extends|import|from|export|default|await|async|try|catch|finally|throw|typeof|instanceof|of|in|switch|case|break|continue|delete|void|yield|static|get|set|this|super|interface|type|enum|implements|public|private|protected|readonly|abstract|as|satisfies|declare|namespace)$/;
1827
1839
  var RULES = {
@@ -1977,13 +1989,13 @@ function tokenize(src, lang) {
1977
1989
  return out;
1978
1990
  }
1979
1991
  function Highlighted({ code, lang }) {
1980
- const toks = React9.useMemo(() => tokenize(code, lang), [code, lang]);
1992
+ const toks = React10.useMemo(() => tokenize(code, lang), [code, lang]);
1981
1993
  return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_jsx_runtime30.Fragment, { children: toks.map((tk, i) => tk.c ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "tok-" + tk.c, children: tk.t }, i) : tk.t) });
1982
1994
  }
1983
1995
  function useCopy() {
1984
- const [done, setDone] = React9.useState(false);
1985
- const timer = React9.useRef(null);
1986
- React9.useEffect(() => () => {
1996
+ const [done, setDone] = React10.useState(false);
1997
+ const timer = React10.useRef(null);
1998
+ React10.useEffect(() => () => {
1987
1999
  if (timer.current) clearTimeout(timer.current);
1988
2000
  }, []);
1989
2001
  const copy = (text) => {
@@ -2019,8 +2031,8 @@ function CodeBlock({
2019
2031
  actions,
2020
2032
  className = ""
2021
2033
  }) {
2022
- const [wrap, setWrap] = React9.useState(!!wrapDefault);
2023
- const [open, setOpen] = React9.useState(false);
2034
+ const [wrap, setWrap] = React10.useState(!!wrapDefault);
2035
+ const [open, setOpen] = React10.useState(false);
2024
2036
  const [copied, copy] = useCopy();
2025
2037
  const body = String(code).replace(/\n$/, "");
2026
2038
  const lines = body.split("\n");
@@ -2049,7 +2061,7 @@ function CodeBlock({
2049
2061
  ] });
2050
2062
  }
2051
2063
  function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
2052
- const [open, setOpen] = React9.useState(false);
2064
+ const [open, setOpen] = React10.useState(false);
2053
2065
  const [copied, copy] = useCopy();
2054
2066
  const raw = String(diff).replace(/\n$/, "");
2055
2067
  const all = raw.split("\n").map((line) => {
@@ -2095,7 +2107,7 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
2095
2107
  }
2096
2108
 
2097
2109
  // src/components/data/Markdown.tsx
2098
- var React10 = __toESM(require("react"), 1);
2110
+ var React11 = __toESM(require("react"), 1);
2099
2111
  var import_jsx_runtime31 = require("react/jsx-runtime");
2100
2112
  var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
2101
2113
  var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
@@ -2134,7 +2146,7 @@ function inlineNodes(src, ctx, keyBase) {
2134
2146
  const href = safeHref(g(2));
2135
2147
  out.push(href ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("a", { href, title: g(3) || void 0, target: /^https?:/i.test(href) ? "_blank" : void 0, rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: inlineNodes(g(1), ctx, key()) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { children: g(1) }, key()));
2136
2148
  } else if (kind === "cite") {
2137
- out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(React10.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("sup", { className: "fd-md-cite", children: g(1) }, key()));
2149
+ out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(React11.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("sup", { className: "fd-md-cite", children: g(1) }, key()));
2138
2150
  } else if (kind === "strongem") out.push(/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("strong", { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("em", { children: inlineNodes(g(1), ctx, key()) }) }, key()));
2139
2151
  else if (kind === "strong") out.push(/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
2140
2152
  else if (kind === "em") out.push(/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
@@ -2299,7 +2311,7 @@ function Markdown({
2299
2311
  onLinkClick
2300
2312
  }) {
2301
2313
  const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
2302
- const blocks = React10.useMemo(() => parseBlocks(source), [source]);
2314
+ const blocks = React11.useMemo(() => parseBlocks(source), [source]);
2303
2315
  return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: ["fd-md", className].filter(Boolean).join(" "), children: renderBlocks(blocks, ctx, "b") });
2304
2316
  }
2305
2317
  function MarkdownInline({ source = "", className = "", onLinkClick }) {
@@ -2407,7 +2419,7 @@ function Pagination({
2407
2419
  }
2408
2420
 
2409
2421
  // src/components/data/RelativeTime.tsx
2410
- var React11 = __toESM(require("react"), 1);
2422
+ var React12 = __toESM(require("react"), 1);
2411
2423
  var import_jsx_runtime34 = require("react/jsx-runtime");
2412
2424
  var MIN = 6e4;
2413
2425
  var HOUR = 36e5;
@@ -2459,9 +2471,9 @@ function formatDuration(ms) {
2459
2471
  return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
2460
2472
  }
2461
2473
  function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
2462
- const [, force] = React11.useState(0);
2474
+ const [, force] = React12.useState(0);
2463
2475
  const t = value instanceof Date ? value.getTime() : Date.parse(value);
2464
- React11.useEffect(() => {
2476
+ React12.useEffect(() => {
2465
2477
  if (!refresh2 || !t || isNaN(t)) return;
2466
2478
  const abs = Math.abs(t - Date.now());
2467
2479
  if (abs > DAY) return;
@@ -2477,10 +2489,10 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
2477
2489
  }
2478
2490
 
2479
2491
  // src/components/data/ScoreMeter.tsx
2480
- var React13 = __toESM(require("react"), 1);
2492
+ var React14 = __toESM(require("react"), 1);
2481
2493
 
2482
2494
  // src/components/data/SegmentedMeter.tsx
2483
- var React12 = __toESM(require("react"), 1);
2495
+ var React13 = __toESM(require("react"), 1);
2484
2496
 
2485
2497
  // src/kits/files.ts
2486
2498
  function formatBytes(n) {
@@ -2685,7 +2697,7 @@ function SegmentedMeter({
2685
2697
  const pct = safeTotal ? Math.min(100, Math.round(used / safeTotal * 100)) : 0;
2686
2698
  const w = (v) => safeTotal ? Math.max(0, Math.min(100, Number(v) / safeTotal * 100)) : 0;
2687
2699
  const fill = (s, i) => s.color || (s.variant ? VARIANT_FILL[s.variant] : void 0) || CHART[i % CHART.length];
2688
- const generatedId = React12.useId();
2700
+ const generatedId = React13.useId();
2689
2701
  const uid2 = id || generatedId;
2690
2702
  return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: ["fd-segmeter", className].filter(Boolean).join(" "), onClick, children: [
2691
2703
  label || showTotal ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "fd-segmeter-head", children: [
@@ -2769,10 +2781,10 @@ function ScoreMeter({
2769
2781
  breakdownWidth = 280,
2770
2782
  className = ""
2771
2783
  }) {
2772
- const [open, setOpen] = React13.useState(false);
2773
- const ref = React13.useRef(null);
2784
+ const [open, setOpen] = React14.useState(false);
2785
+ const ref = React14.useRef(null);
2774
2786
  const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
2775
- const body = /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(React13.Fragment, { children: [
2787
+ const body = /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(React14.Fragment, { children: [
2776
2788
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "fd-scoremeter-rail", style: { width }, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(SegmentedMeter, { total: 100, segments, height, showTotal: false, showPercent: false, legend: false }) }),
2777
2789
  showScore ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
2778
2790
  ] });
@@ -2791,7 +2803,7 @@ function ScoreMeter({
2791
2803
  }
2792
2804
  );
2793
2805
  }
2794
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(React13.Fragment, { children: [
2806
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(React14.Fragment, { children: [
2795
2807
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
2796
2808
  "button",
2797
2809
  {
@@ -2822,12 +2834,14 @@ function ScoreMeter({
2822
2834
  }
2823
2835
 
2824
2836
  // src/components/data/SortMenu.tsx
2825
- var React14 = __toESM(require("react"), 1);
2837
+ var React15 = __toESM(require("react"), 1);
2826
2838
  var import_jsx_runtime37 = require("react/jsx-runtime");
2839
+ var SORT_MENU_BASE = 120;
2827
2840
  function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", className = "", ...rest }) {
2828
- const [open, setOpen] = React14.useState(false);
2829
- const ref = React14.useRef(null);
2830
- React14.useEffect(() => {
2841
+ const [open, setOpen] = React15.useState(false);
2842
+ const zIndex = useOverlayLayer(SORT_MENU_BASE);
2843
+ const ref = React15.useRef(null);
2844
+ React15.useEffect(() => {
2831
2845
  if (!open) return;
2832
2846
  const away = (e) => {
2833
2847
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -2874,7 +2888,7 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
2874
2888
  cur ? cur.label : "Unsorted",
2875
2889
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("i", { className: "ph ph-" + (dir === "asc" ? "arrow-up" : "arrow-down"), style: { fontSize: 12, marginLeft: 6, opacity: 0.75 } })
2876
2890
  ] }),
2877
- open ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "fd-view-enter", style: { position: "absolute", top: "calc(100% + 6px)", [align]: 0, zIndex: 120, width: 280, maxWidth: "calc(100vw - 32px)", display: "block", background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 10, boxShadow: "0 16px 44px rgba(11,13,17,.18)", padding: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
2891
+ open ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "fd-view-enter", style: { position: "absolute", top: "calc(100% + 6px)", [align]: 0, zIndex, width: 280, maxWidth: "calc(100vw - 32px)", display: "block", background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 10, boxShadow: "0 16px 44px rgba(11,13,17,.18)", padding: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
2878
2892
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "4px 8px 6px" }, children: "Sort by" }),
2879
2893
  fields.map((f) => {
2880
2894
  const active = cur && cur.key === f.key;
@@ -2884,12 +2898,12 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
2884
2898
  arrow(f, "desc")
2885
2899
  ] }, f.key);
2886
2900
  })
2887
- ] }) }) : null
2901
+ ] }) }) }) : null
2888
2902
  ] });
2889
2903
  }
2890
2904
 
2891
2905
  // src/components/data/StepList.tsx
2892
- var React15 = __toESM(require("react"), 1);
2906
+ var React16 = __toESM(require("react"), 1);
2893
2907
  var import_jsx_runtime38 = require("react/jsx-runtime");
2894
2908
  var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
2895
2909
  function StepList({
@@ -2902,9 +2916,9 @@ function StepList({
2902
2916
  dense = false,
2903
2917
  className = ""
2904
2918
  }) {
2905
- const [openState, setOpenState] = React15.useState(defaultOpen);
2919
+ const [openState, setOpenState] = React16.useState(defaultOpen);
2906
2920
  const open = openProp == null ? openState : openProp;
2907
- const [expanded, setExpanded] = React15.useState({});
2921
+ const [expanded, setExpanded] = React16.useState({});
2908
2922
  if (!steps.length) return null;
2909
2923
  const running = steps.some((s) => s.status === "running");
2910
2924
  const failed = steps.filter((s) => s.status === "error").length;
@@ -2962,7 +2976,7 @@ function StepList({
2962
2976
  }
2963
2977
 
2964
2978
  // src/components/data/VirtualList.tsx
2965
- var React16 = __toESM(require("react"), 1);
2979
+ var React17 = __toESM(require("react"), 1);
2966
2980
  var import_jsx_runtime39 = require("react/jsx-runtime");
2967
2981
  var VIRTUAL_LIST_BUFFER_ROWS = 20;
2968
2982
  var VIRTUAL_LIST_ROW_GAP = 6;
@@ -3014,35 +3028,35 @@ function VirtualList({
3014
3028
  className = "",
3015
3029
  style
3016
3030
  }) {
3017
- const [scrollTop, setScrollTop] = React16.useState(0);
3018
- const loaded = React16.useMemo(
3031
+ const [scrollTop, setScrollTop] = React17.useState(0);
3032
+ const loaded = React17.useMemo(
3019
3033
  () => ({ firstItemIndex, count: items.length }),
3020
3034
  [firstItemIndex, items.length]
3021
3035
  );
3022
3036
  const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
3023
3037
  const bandKey = firstItemIndex + ":" + items.length;
3024
- const win = React16.useMemo(
3038
+ const win = React17.useMemo(
3025
3039
  () => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
3026
3040
  [scrollTop, height, itemHeight, total, loaded]
3027
3041
  );
3028
- const need = React16.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
3042
+ const need = React17.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
3029
3043
  const wantStart = need.start && hasMore?.start !== false;
3030
3044
  const wantEnd = need.end && hasMore?.end !== false;
3031
3045
  const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
3032
3046
  const askKey = bandKey + "@" + bucket2;
3033
- const asked = React16.useRef({ start: null, end: null });
3034
- React16.useEffect(() => {
3047
+ const asked = React17.useRef({ start: null, end: null });
3048
+ React17.useEffect(() => {
3035
3049
  if (loading || !wantStart || asked.current.start === askKey) return;
3036
3050
  asked.current.start = askKey;
3037
3051
  onNeedMore("start", win);
3038
3052
  }, [wantStart, loading, askKey, onNeedMore, win]);
3039
- React16.useEffect(() => {
3053
+ React17.useEffect(() => {
3040
3054
  if (loading || !wantEnd || asked.current.end === askKey) return;
3041
3055
  asked.current.end = askKey;
3042
3056
  onNeedMore("end", win);
3043
3057
  }, [wantEnd, loading, askKey, onNeedMore, win]);
3044
- const lastKeysRef = React16.useRef(null);
3045
- const newKeys = React16.useMemo(() => {
3058
+ const lastKeysRef = React17.useRef(null);
3059
+ const newKeys = React17.useMemo(() => {
3046
3060
  const prev = lastKeysRef.current;
3047
3061
  if (!prev) return /* @__PURE__ */ new Set();
3048
3062
  const fresh = /* @__PURE__ */ new Set();
@@ -3052,7 +3066,7 @@ function VirtualList({
3052
3066
  }
3053
3067
  return fresh;
3054
3068
  }, [items]);
3055
- React16.useEffect(() => {
3069
+ React17.useEffect(() => {
3056
3070
  lastKeysRef.current = new Set(items.map(keyOf));
3057
3071
  }, [items]);
3058
3072
  const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
@@ -3097,7 +3111,7 @@ function VirtualList({
3097
3111
  }
3098
3112
 
3099
3113
  // src/components/data/EntityRow.tsx
3100
- var React17 = __toESM(require("react"), 1);
3114
+ var React18 = __toESM(require("react"), 1);
3101
3115
  var import_jsx_runtime40 = require("react/jsx-runtime");
3102
3116
  var ENTITY_ROW_METRIC_WIDTH = 74;
3103
3117
  var METRIC_TONE_COLOR = {
@@ -3110,7 +3124,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
3110
3124
  const key = m.id || m.label || i;
3111
3125
  const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
3112
3126
  const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
3113
- const content = /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(React17.Fragment, { children: [
3127
+ const content = /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(React18.Fragment, { children: [
3114
3128
  m.icon ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
3115
3129
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
3116
3130
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-sr", children: " " + m.label })
@@ -3178,14 +3192,14 @@ function EntityRow({
3178
3192
  }
3179
3193
 
3180
3194
  // src/components/data/TransferList.tsx
3181
- var React19 = __toESM(require("react"), 1);
3195
+ var React20 = __toESM(require("react"), 1);
3182
3196
  var import_react_dom4 = require("react-dom");
3183
3197
 
3184
3198
  // src/components/forms/field.tsx
3185
- var React18 = __toESM(require("react"), 1);
3199
+ var React19 = __toESM(require("react"), 1);
3186
3200
  var import_jsx_runtime41 = require("react/jsx-runtime");
3187
3201
  function useFieldId(id) {
3188
- const generated = React18.useId();
3202
+ const generated = React19.useId();
3189
3203
  return id || generated;
3190
3204
  }
3191
3205
  function FieldLabel({ htmlFor, id, required = false, onClick, children }) {
@@ -3303,12 +3317,12 @@ function TransferList({
3303
3317
  listHeight = 440,
3304
3318
  className = ""
3305
3319
  }) {
3306
- const [drag, setDrag] = React19.useState(null);
3307
- const [dragOverSide, setDragOverSide] = React19.useState(null);
3308
- const dragRef = React19.useRef(null);
3309
- const armedRef = React19.useRef(null);
3310
- const sideRefs = React19.useRef({ left: null, right: null });
3311
- const hitTestSide = React19.useCallback((x, y) => {
3320
+ const [drag, setDrag] = React20.useState(null);
3321
+ const [dragOverSide, setDragOverSide] = React20.useState(null);
3322
+ const dragRef = React20.useRef(null);
3323
+ const armedRef = React20.useRef(null);
3324
+ const sideRefs = React20.useRef({ left: null, right: null });
3325
+ const hitTestSide = React20.useCallback((x, y) => {
3312
3326
  for (const side of ["left", "right"]) {
3313
3327
  const el = sideRefs.current[side];
3314
3328
  if (!el) continue;
@@ -3317,7 +3331,7 @@ function TransferList({
3317
3331
  }
3318
3332
  return null;
3319
3333
  }, []);
3320
- const findItem = React19.useCallback(
3334
+ const findItem = React20.useCallback(
3321
3335
  (side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
3322
3336
  [left.items, right.items, keyOf]
3323
3337
  );
@@ -3339,7 +3353,7 @@ function TransferList({
3339
3353
  height: rect.height
3340
3354
  };
3341
3355
  };
3342
- React19.useEffect(() => {
3356
+ React20.useEffect(() => {
3343
3357
  const onMovePointer = (e) => {
3344
3358
  const armed = armedRef.current;
3345
3359
  if (!armed || e.pointerId !== armed.pointerId) return;
@@ -3392,7 +3406,7 @@ function TransferList({
3392
3406
  window.removeEventListener("pointercancel", endDrag);
3393
3407
  };
3394
3408
  }, [hitTestSide, findItem, onMove]);
3395
- React19.useEffect(() => {
3409
+ React20.useEffect(() => {
3396
3410
  if (!drag || typeof document === "undefined") return;
3397
3411
  const prev = document.body.style.userSelect;
3398
3412
  document.body.style.userSelect = "none";
@@ -3500,11 +3514,11 @@ function TransferList({
3500
3514
  }
3501
3515
 
3502
3516
  // src/components/forms/Checkbox.tsx
3503
- var React20 = __toESM(require("react"), 1);
3517
+ var React21 = __toESM(require("react"), 1);
3504
3518
  var import_jsx_runtime45 = require("react/jsx-runtime");
3505
3519
  function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
3506
- const ref = React20.useRef(null);
3507
- React20.useEffect(() => {
3520
+ const ref = React21.useRef(null);
3521
+ React21.useEffect(() => {
3508
3522
  if (ref.current) ref.current.indeterminate = indeterminate;
3509
3523
  }, [indeterminate]);
3510
3524
  return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
@@ -3563,7 +3577,7 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
3563
3577
  }
3564
3578
 
3565
3579
  // src/components/forms/NumberInput.tsx
3566
- var React21 = __toESM(require("react"), 1);
3580
+ var React22 = __toESM(require("react"), 1);
3567
3581
  var import_jsx_runtime49 = require("react/jsx-runtime");
3568
3582
  function NumberInput({
3569
3583
  label,
@@ -3591,10 +3605,10 @@ function NumberInput({
3591
3605
  const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
3592
3606
  return isNaN(n) ? null : n;
3593
3607
  };
3594
- const [text, setText] = React21.useState(value == null || value === "" ? "" : String(value));
3595
- const [editing, setEditing] = React21.useState(false);
3596
- const timer = React21.useRef(null);
3597
- React21.useEffect(() => {
3608
+ const [text, setText] = React22.useState(value == null || value === "" ? "" : String(value));
3609
+ const [editing, setEditing] = React22.useState(false);
3610
+ const timer = React22.useRef(null);
3611
+ React22.useEffect(() => {
3598
3612
  if (!editing) setText(value == null || value === "" ? "" : String(value));
3599
3613
  }, [value, editing]);
3600
3614
  const clamp = (n) => Math.min(max, Math.max(min, n));
@@ -3618,7 +3632,7 @@ function NumberInput({
3618
3632
  const release = () => {
3619
3633
  if (timer.current) clearTimeout(timer.current);
3620
3634
  };
3621
- React21.useEffect(() => () => {
3635
+ React22.useEffect(() => () => {
3622
3636
  if (timer.current) clearTimeout(timer.current);
3623
3637
  }, []);
3624
3638
  const shown = editing ? text : (() => {
@@ -3705,7 +3719,7 @@ function NumberInput({
3705
3719
  }
3706
3720
 
3707
3721
  // src/components/forms/Select.tsx
3708
- var React22 = __toESM(require("react"), 1);
3722
+ var React23 = __toESM(require("react"), 1);
3709
3723
  var import_jsx_runtime50 = require("react/jsx-runtime");
3710
3724
  var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
3711
3725
  function Select({
@@ -3732,13 +3746,13 @@ function Select({
3732
3746
  const isOn = (v) => multiple ? vals.includes(v) : v === value;
3733
3747
  const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
3734
3748
  const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
3735
- const [open, setOpen] = React22.useState(false);
3736
- const [q, setQ] = React22.useState("");
3737
- const [active, setActive] = React22.useState(-1);
3738
- const rootRef = React22.useRef(null);
3739
- const boxRef = React22.useRef(null);
3740
- const listRef = React22.useRef(null);
3741
- const typeBuf = React22.useRef({ s: "", t: 0 });
3749
+ const [open, setOpen] = React23.useState(false);
3750
+ const [q, setQ] = React23.useState("");
3751
+ const [active, setActive] = React23.useState(-1);
3752
+ const rootRef = React23.useRef(null);
3753
+ const boxRef = React23.useRef(null);
3754
+ const listRef = React23.useRef(null);
3755
+ const typeBuf = React23.useRef({ s: "", t: 0 });
3742
3756
  const selected = multiple ? null : opts.find((o) => o.value === value);
3743
3757
  const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
3744
3758
  const boxText = multiple ? chosen.length === 0 ? placeholder : chosen.length === 1 ? chosen[0].label : summary ? summary(chosen.map((o) => o.value)) : chosen.length + " selected" : selected ? selected.label : placeholder;
@@ -3763,7 +3777,7 @@ function Select({
3763
3777
  }
3764
3778
  setOpen(!open);
3765
3779
  };
3766
- React22.useEffect(() => {
3780
+ React23.useEffect(() => {
3767
3781
  if (!open || active < 0 || !listRef.current) return;
3768
3782
  const el = listRef.current.querySelector('[data-i="' + active + '"]');
3769
3783
  if (el) {
@@ -3884,7 +3898,7 @@ function Select({
3884
3898
  ),
3885
3899
  q ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
3886
3900
  ] }) : void 0,
3887
- footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(React22.Fragment, { children: [
3901
+ footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(React23.Fragment, { children: [
3888
3902
  /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3889
3903
  "button",
3890
3904
  {
@@ -3915,7 +3929,7 @@ function Select({
3915
3929
  'Nothing matches "',
3916
3930
  q,
3917
3931
  '".'
3918
- ] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(React22.Fragment, { children: [
3932
+ ] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(React23.Fragment, { children: [
3919
3933
  grp.g ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
3920
3934
  grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
3921
3935
  "button",
@@ -3952,7 +3966,7 @@ function Select({
3952
3966
  }
3953
3967
 
3954
3968
  // src/components/forms/DatePicker.tsx
3955
- var React23 = __toESM(require("react"), 1);
3969
+ var React24 = __toESM(require("react"), 1);
3956
3970
  var import_jsx_runtime51 = require("react/jsx-runtime");
3957
3971
  var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
3958
3972
  var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
@@ -3970,10 +3984,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3970
3984
  const today = /* @__PURE__ */ new Date();
3971
3985
  const sel = range ? value || {} : { start: value, end: value };
3972
3986
  const anchor = parse(sel.start) || parse(initialMonth) || today;
3973
- const [vy, setVy] = React23.useState(anchor.getFullYear());
3974
- const [vm, setVm] = React23.useState(anchor.getMonth());
3975
- const [mode2, setMode] = React23.useState("days");
3976
- const [hover, setHover] = React23.useState(null);
3987
+ const [vy, setVy] = React24.useState(anchor.getFullYear());
3988
+ const [vm, setVm] = React24.useState(anchor.getMonth());
3989
+ const [mode2, setMode] = React24.useState("days");
3990
+ const [hover, setHover] = React24.useState(null);
3977
3991
  const s = parse(sel.start), e = parse(sel.end);
3978
3992
  const hoverEnd = range && s && !e && hover ? parse(hover) : null;
3979
3993
  const inRange = (d) => {
@@ -4089,9 +4103,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
4089
4103
  }
4090
4104
  function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, ...rest }) {
4091
4105
  const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
4092
- const [open, setOpen] = React23.useState(false);
4093
- const rootRef = React23.useRef(null);
4094
- const boxRef = React23.useRef(null);
4106
+ const [open, setOpen] = React24.useState(false);
4107
+ const rootRef = React24.useRef(null);
4108
+ const boxRef = React24.useRef(null);
4095
4109
  const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
4096
4110
  const toggle = () => {
4097
4111
  if (!disabled) setOpen(!open);
@@ -4153,7 +4167,7 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
4153
4167
  }
4154
4168
 
4155
4169
  // src/components/forms/TimePicker.tsx
4156
- var React24 = __toESM(require("react"), 1);
4170
+ var React25 = __toESM(require("react"), 1);
4157
4171
  var import_jsx_runtime52 = require("react/jsx-runtime");
4158
4172
  var pad = (n) => String(n).padStart(2, "0");
4159
4173
  function ClockFace({ value = "09:00", onChange }) {
@@ -4162,9 +4176,9 @@ function ClockFace({ value = "09:00", onChange }) {
4162
4176
  if (isNaN(m)) m = 0;
4163
4177
  const pm = h24 >= 12;
4164
4178
  const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
4165
- const [mode2, setMode] = React24.useState("h");
4166
- const faceRef = React24.useRef(null);
4167
- const dragging = React24.useRef(false);
4179
+ const [mode2, setMode] = React25.useState("h");
4180
+ const faceRef = React25.useRef(null);
4181
+ const dragging = React25.useRef(false);
4168
4182
  const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
4169
4183
  const R = 108, NR = 80;
4170
4184
  const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
@@ -4237,9 +4251,9 @@ function ClockFace({ value = "09:00", onChange }) {
4237
4251
  }
4238
4252
  function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
4239
4253
  const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
4240
- const [open, setOpen] = React24.useState(false);
4241
- const rootRef = React24.useRef(null);
4242
- const boxRef = React24.useRef(null);
4254
+ const [open, setOpen] = React25.useState(false);
4255
+ const rootRef = React25.useRef(null);
4256
+ const boxRef = React25.useRef(null);
4243
4257
  const disp = () => {
4244
4258
  if (!value) return "";
4245
4259
  const [h, m] = value.split(":").map(Number);
@@ -4282,7 +4296,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
4282
4296
  offset: 6,
4283
4297
  width: 262,
4284
4298
  role: "presentation",
4285
- footer: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React24.Fragment, { children: [
4299
+ footer: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React25.Fragment, { children: [
4286
4300
  /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
4287
4301
  "button",
4288
4302
  {
@@ -4310,7 +4324,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
4310
4324
  }
4311
4325
 
4312
4326
  // src/components/forms/Slider.tsx
4313
- var React25 = __toESM(require("react"), 1);
4327
+ var React26 = __toESM(require("react"), 1);
4314
4328
  var import_jsx_runtime53 = require("react/jsx-runtime");
4315
4329
  function Slider({
4316
4330
  label,
@@ -4328,7 +4342,7 @@ function Slider({
4328
4342
  ...rest
4329
4343
  }) {
4330
4344
  const fieldId = useFieldId(id);
4331
- const [dragging, setDragging] = React25.useState(false);
4345
+ const [dragging, setDragging] = React26.useState(false);
4332
4346
  const v = value === void 0 ? min : Number(value);
4333
4347
  const pct = max === min ? 0 : (v - min) / (max - min) * 100;
4334
4348
  return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
@@ -4362,7 +4376,7 @@ function Slider({
4362
4376
  }
4363
4377
 
4364
4378
  // src/components/forms/RangeSlider.tsx
4365
- var React26 = __toESM(require("react"), 1);
4379
+ var React27 = __toESM(require("react"), 1);
4366
4380
  var import_jsx_runtime54 = require("react/jsx-runtime");
4367
4381
  function RangeSlider({
4368
4382
  label,
@@ -4382,9 +4396,9 @@ function RangeSlider({
4382
4396
  }) {
4383
4397
  const fmt2 = format || ((v) => String(v));
4384
4398
  const [a, b] = value || [min, max];
4385
- const [drag, setDrag] = React26.useState(null);
4386
- const [focus, setFocus] = React26.useState(null);
4387
- const railRef = React26.useRef(null);
4399
+ const [drag, setDrag] = React27.useState(null);
4400
+ const [focus, setFocus] = React27.useState(null);
4401
+ const railRef = React27.useRef(null);
4388
4402
  const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
4389
4403
  const clampPair = (i, v) => {
4390
4404
  v = Math.min(max, Math.max(min, Math.round(v / step) * step));
@@ -4399,7 +4413,7 @@ function RangeSlider({
4399
4413
  const r = railRef.current.getBoundingClientRect();
4400
4414
  return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
4401
4415
  };
4402
- React26.useEffect(() => {
4416
+ React27.useEffect(() => {
4403
4417
  if (drag === null) return;
4404
4418
  const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
4405
4419
  const upH = () => setDrag(null);
@@ -4480,7 +4494,7 @@ function RangeSlider({
4480
4494
  /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
4481
4495
  /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-rail", ref: railRef }),
4482
4496
  /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
4483
- marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(React26.Fragment, { children: [
4497
+ marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(React27.Fragment, { children: [
4484
4498
  /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
4485
4499
  m.label ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
4486
4500
  ] }, m.value)),
@@ -4509,7 +4523,7 @@ function RangeSlider({
4509
4523
  }
4510
4524
 
4511
4525
  // src/components/forms/Dropzone.tsx
4512
- var React27 = __toESM(require("react"), 1);
4526
+ var React28 = __toESM(require("react"), 1);
4513
4527
  var import_jsx_runtime55 = require("react/jsx-runtime");
4514
4528
  function Dropzone({
4515
4529
  onFiles,
@@ -4524,8 +4538,8 @@ function Dropzone({
4524
4538
  className = "",
4525
4539
  style
4526
4540
  }) {
4527
- const [over, setOver] = React27.useState(false);
4528
- const depth = React27.useRef(0);
4541
+ const [over, setOver] = React28.useState(false);
4542
+ const depth = React28.useRef(0);
4529
4543
  const has = (e) => {
4530
4544
  const dt = e.dataTransfer;
4531
4545
  if (!dt) return false;
@@ -4587,8 +4601,8 @@ function FilePickButton({
4587
4601
  className = "",
4588
4602
  children
4589
4603
  }) {
4590
- const ref = React27.useRef(null);
4591
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(React27.Fragment, { children: [
4604
+ const ref = React28.useRef(null);
4605
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(React28.Fragment, { children: [
4592
4606
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
4593
4607
  "button",
4594
4608
  {
@@ -4621,10 +4635,10 @@ function FilePickButton({
4621
4635
  }
4622
4636
  function useStagedFiles(upload, opts) {
4623
4637
  const o = opts || {};
4624
- const [items, setItems] = React27.useState([]);
4625
- const controllers = React27.useRef({});
4638
+ const [items, setItems] = React28.useState([]);
4639
+ const controllers = React28.useRef({});
4626
4640
  const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
4627
- const run = React27.useCallback((att) => {
4641
+ const run = React28.useCallback((att) => {
4628
4642
  if (!upload) return;
4629
4643
  const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
4630
4644
  controllers.current[att.id] = ac;
@@ -4641,14 +4655,14 @@ function useStagedFiles(upload, opts) {
4641
4655
  delete controllers.current[att.id];
4642
4656
  });
4643
4657
  }, [upload]);
4644
- const add = React27.useCallback((files) => {
4658
+ const add = React28.useCallback((files) => {
4645
4659
  if (!upload) return [];
4646
4660
  const atts = Array.from(files).map((f) => toAttachment(f));
4647
4661
  setItems((list) => list.concat(atts));
4648
4662
  atts.forEach(run);
4649
4663
  return atts;
4650
4664
  }, [upload, run]);
4651
- const remove = React27.useCallback((att) => {
4665
+ const remove = React28.useCallback((att) => {
4652
4666
  const ac = controllers.current[att.id];
4653
4667
  if (ac) {
4654
4668
  try {
@@ -4659,10 +4673,10 @@ function useStagedFiles(upload, opts) {
4659
4673
  }
4660
4674
  setItems((list) => list.filter((f) => f.id !== att.id));
4661
4675
  }, []);
4662
- const retry = React27.useCallback((att) => {
4676
+ const retry = React28.useCallback((att) => {
4663
4677
  run(att);
4664
4678
  }, [run]);
4665
- const clear = React27.useCallback(() => {
4679
+ const clear = React28.useCallback(() => {
4666
4680
  Object.values(controllers.current).forEach((ac) => {
4667
4681
  try {
4668
4682
  ac && ac.abort();
@@ -4786,7 +4800,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
4786
4800
  }
4787
4801
 
4788
4802
  // src/components/forms/MarkdownEditor.tsx
4789
- var React28 = __toESM(require("react"), 1);
4803
+ var React29 = __toESM(require("react"), 1);
4790
4804
  var import_jsx_runtime57 = require("react/jsx-runtime");
4791
4805
  var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
4792
4806
  var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
@@ -5000,7 +5014,7 @@ function syncDom(root, value) {
5000
5014
  while (root.children.length > lines.length) root.removeChild(root.lastChild);
5001
5015
  }
5002
5016
  var LIST_CONT = RE_LI;
5003
- var MarkdownEditor = React28.forwardRef(function MarkdownEditor2({
5017
+ var MarkdownEditor = React29.forwardRef(function MarkdownEditor2({
5004
5018
  value = "",
5005
5019
  onChange,
5006
5020
  onSubmit,
@@ -5019,10 +5033,10 @@ var MarkdownEditor = React28.forwardRef(function MarkdownEditor2({
5019
5033
  className = "",
5020
5034
  id
5021
5035
  }, ref) {
5022
- const boxRef = React28.useRef(null);
5023
- const composing = React28.useRef(false);
5024
- const pendingCaret = React28.useRef(null);
5025
- React28.useLayoutEffect(() => {
5036
+ const boxRef = React29.useRef(null);
5037
+ const composing = React29.useRef(false);
5038
+ const pendingCaret = React29.useRef(null);
5039
+ React29.useLayoutEffect(() => {
5026
5040
  const root = boxRef.current;
5027
5041
  if (!root || composing.current) return;
5028
5042
  const active = document.activeElement === root || root.contains(document.activeElement);
@@ -5031,7 +5045,7 @@ var MarkdownEditor = React28.forwardRef(function MarkdownEditor2({
5031
5045
  pendingCaret.current = null;
5032
5046
  if (active && caret != null) placeCaret(root, caret);
5033
5047
  }, [value]);
5034
- React28.useEffect(() => {
5048
+ React29.useEffect(() => {
5035
5049
  if (autoFocus && boxRef.current) boxRef.current.focus();
5036
5050
  }, [autoFocus]);
5037
5051
  const caretNow = () => {
@@ -5098,7 +5112,7 @@ var MarkdownEditor = React28.forwardRef(function MarkdownEditor2({
5098
5112
  api.replaceRange(from, to, next, from + next.length);
5099
5113
  }
5100
5114
  };
5101
- React28.useImperativeHandle(ref, () => api);
5115
+ React29.useImperativeHandle(ref, () => api);
5102
5116
  function detect(text, caret) {
5103
5117
  if (!onTrigger) return;
5104
5118
  const upto = text.slice(0, caret);
@@ -5250,10 +5264,10 @@ var MarkdownEditor = React28.forwardRef(function MarkdownEditor2({
5250
5264
  });
5251
5265
 
5252
5266
  // src/components/platform/AccountMenu.tsx
5253
- var React30 = __toESM(require("react"), 1);
5267
+ var React31 = __toESM(require("react"), 1);
5254
5268
 
5255
5269
  // src/kits/session.ts
5256
- var React29 = __toESM(require("react"), 1);
5270
+ var React30 = __toESM(require("react"), 1);
5257
5271
  var PERMISSION_CATALOG = [
5258
5272
  { group: "Plans", items: [
5259
5273
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -6820,8 +6834,8 @@ function roadmap(overrides) {
6820
6834
  };
6821
6835
  }
6822
6836
  function useSession() {
6823
- const [s, setS] = React29.useState(getSession);
6824
- React29.useEffect(() => subscribe(setS), []);
6837
+ const [s, setS] = React30.useState(getSession);
6838
+ React30.useEffect(() => subscribe(setS), []);
6825
6839
  return s;
6826
6840
  }
6827
6841
  var SessionKit = {
@@ -6891,9 +6905,9 @@ function AccountMenu({
6891
6905
  ...rest
6892
6906
  }) {
6893
6907
  const session = SessionKit.useSession();
6894
- const [open, setOpen] = React30.useState(false);
6895
- const [switching, setSwitching] = React30.useState(false);
6896
- const ref = React30.useRef(null);
6908
+ const [open, setOpen] = React31.useState(false);
6909
+ const [switching, setSwitching] = React31.useState(false);
6910
+ const ref = React31.useRef(null);
6897
6911
  const user = session.user;
6898
6912
  const visibleAdmin = adminLinks.filter((l) => !l.perm || SessionKit.can(l.perm));
6899
6913
  const pick = (item) => {
@@ -6977,14 +6991,14 @@ function AccountMenu({
6977
6991
  }
6978
6992
 
6979
6993
  // src/components/platform/ApiSpecBrowser.tsx
6980
- var React31 = __toESM(require("react"), 1);
6994
+ var React32 = __toESM(require("react"), 1);
6981
6995
  var import_jsx_runtime59 = require("react/jsx-runtime");
6982
6996
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
6983
6997
  function Json({ obj }) {
6984
6998
  return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
6985
6999
  }
6986
7000
  function Endpoint({ s, onRequest }) {
6987
- const [tried, setTried] = React31.useState(null);
7001
+ const [tried, setTried] = React32.useState(null);
6988
7002
  const run = async () => {
6989
7003
  setTried("busy");
6990
7004
  const t0 = (window.performance || Date).now();
@@ -7057,10 +7071,10 @@ function ApiSpecBrowser({
7057
7071
  className = "",
7058
7072
  ...rest
7059
7073
  }) {
7060
- const [q, setQ] = React31.useState("");
7061
- const [method, setMethod] = React31.useState(null);
7062
- const [mod, setMod] = React31.useState(null);
7063
- const [listOnly, setListOnly] = React31.useState(false);
7074
+ const [q, setQ] = React32.useState("");
7075
+ const [method, setMethod] = React32.useState(null);
7076
+ const [mod, setMod] = React32.useState(null);
7077
+ const [listOnly, setListOnly] = React32.useState(false);
7064
7078
  const activeModule = modules && modules.find((m) => m.id === mod);
7065
7079
  const hits = spec.filter((s) => (!method || s.method === method) && (!listOnly || s.isList) && (!activeModule || activeModule.endpoints.indexOf(s.id) >= 0) && (!q || (s.path + " " + s.title + " " + s.purpose + " " + (s.usedBy || []).join(" ")).toLowerCase().includes(q.toLowerCase())));
7066
7080
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
@@ -7139,7 +7153,7 @@ function ApiSpecBrowser({
7139
7153
  }
7140
7154
 
7141
7155
  // src/components/platform/ProfilePage.tsx
7142
- var React32 = __toESM(require("react"), 1);
7156
+ var React33 = __toESM(require("react"), 1);
7143
7157
  var import_jsx_runtime60 = require("react/jsx-runtime");
7144
7158
  var TIMEZONES = ["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles", "America/Anchorage", "Pacific/Honolulu", "Europe/London", "Europe/Berlin"];
7145
7159
  var NOTIFY = [
@@ -7152,7 +7166,7 @@ var NOTIFY = [
7152
7166
  function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSessions = true, className = "", ...rest }) {
7153
7167
  const session = SessionKit.useSession();
7154
7168
  const user = userProp || session.user;
7155
- const [draft, setDraft] = React32.useState(() => ({
7169
+ const [draft, setDraft] = React33.useState(() => ({
7156
7170
  name: user.name || "",
7157
7171
  title: user.title || "",
7158
7172
  email: user.email || "",
@@ -7161,8 +7175,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
7161
7175
  bio: user.bio || "",
7162
7176
  notify: user.notify || { planShared: true, planChanged: true, goalMissed: true, flagChanged: false, weekly: true }
7163
7177
  }));
7164
- const [saving, setSaving] = React32.useState(false);
7165
- const [saved, setSaved] = React32.useState(false);
7178
+ const [saving, setSaving] = React33.useState(false);
7179
+ const [saved, setSaved] = React33.useState(false);
7166
7180
  const set = (k, v) => {
7167
7181
  setDraft((d) => Object.assign({}, d, { [k]: v }));
7168
7182
  setSaved(false);
@@ -7352,10 +7366,10 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
7352
7366
  }
7353
7367
 
7354
7368
  // src/components/platform/RoadmapTimeline.tsx
7355
- var React34 = __toESM(require("react"), 1);
7369
+ var React35 = __toESM(require("react"), 1);
7356
7370
 
7357
7371
  // src/kits/runtime.ts
7358
- var React33 = __toESM(require("react"), 1);
7372
+ var React34 = __toESM(require("react"), 1);
7359
7373
  var WIRED_ENDPOINTS = [
7360
7374
  // Nothing yet. Every id below would come from a real service:
7361
7375
  // "plan.get", "placements.list", …
@@ -7526,8 +7540,8 @@ var RuntimeKit = {
7526
7540
  };
7527
7541
  RuntimeKit.declare(FEATURE_NEEDS);
7528
7542
  function useRuntimeMode() {
7529
- const [m, setM] = React33.useState(RuntimeKit.getMode());
7530
- React33.useEffect(() => RuntimeKit.subscribe(setM), []);
7543
+ const [m, setM] = React34.useState(RuntimeKit.getMode());
7544
+ React34.useEffect(() => RuntimeKit.subscribe(setM), []);
7531
7545
  return m;
7532
7546
  }
7533
7547
  function useFeatureStatus(key) {
@@ -7610,12 +7624,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
7610
7624
  }
7611
7625
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
7612
7626
  const session = SessionKit.useSession();
7613
- const [project, setProject] = React34.useState("");
7614
- const [q, setQ] = React34.useState("");
7615
- const scrollRef = React34.useRef(null);
7616
- const nowRef = React34.useRef(null);
7617
- const rm = React34.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
7618
- const byKey = React34.useMemo(() => {
7627
+ const [project, setProject] = React35.useState("");
7628
+ const [q, setQ] = React35.useState("");
7629
+ const scrollRef = React35.useRef(null);
7630
+ const nowRef = React35.useRef(null);
7631
+ const rm = React35.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
7632
+ const byKey = React35.useMemo(() => {
7619
7633
  const m = {};
7620
7634
  rm.items.forEach((i) => {
7621
7635
  m[i.key] = i;
@@ -7624,7 +7638,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
7624
7638
  }, [rm]);
7625
7639
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
7626
7640
  const projects = [...new Set(rm.items.map((i) => i.project))];
7627
- React34.useEffect(() => {
7641
+ React35.useEffect(() => {
7628
7642
  let raf1 = 0, raf2 = 0;
7629
7643
  const place = () => {
7630
7644
  const box = scrollRef.current, mark = nowRef.current;
@@ -7698,7 +7712,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
7698
7712
  lastPhase = item.phase;
7699
7713
  const inPhase = items.filter((i) => i.phase === item.phase).length;
7700
7714
  const isBoundary = n === firstPending;
7701
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(React34.Fragment, { children: [
7715
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(React35.Fragment, { children: [
7702
7716
  showPhase ? /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "fd-rm-era", children: [
7703
7717
  /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
7704
7718
  /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
@@ -7742,9 +7756,10 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
7742
7756
  }
7743
7757
 
7744
7758
  // src/components/platform/ComingSoon.tsx
7745
- var React35 = __toESM(require("react"), 1);
7759
+ var React36 = __toESM(require("react"), 1);
7746
7760
  var import_react_dom5 = require("react-dom");
7747
7761
  var import_jsx_runtime62 = require("react/jsx-runtime");
7762
+ var SOON_HOVERCARD_BASE = 220;
7748
7763
  var BYPASS_STORE = "fd.soon.bypass.v1";
7749
7764
  function readBypassed() {
7750
7765
  try {
@@ -7760,8 +7775,8 @@ function writeBypassed(list) {
7760
7775
  }
7761
7776
  }
7762
7777
  function useBypass(key) {
7763
- const [on, setOn] = React35.useState(() => !!key && readBypassed().indexOf(key) >= 0);
7764
- React35.useEffect(() => {
7778
+ const [on, setOn] = React36.useState(() => !!key && readBypassed().indexOf(key) >= 0);
7779
+ React36.useEffect(() => {
7765
7780
  setOn(!!key && readBypassed().indexOf(key) >= 0);
7766
7781
  }, [key]);
7767
7782
  const set = (next) => {
@@ -7808,9 +7823,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
7808
7823
  ] });
7809
7824
  }
7810
7825
  function useHoverCard(open) {
7811
- const anchor = React35.useRef(null);
7812
- const [pos, setPos] = React35.useState(null);
7813
- React35.useLayoutEffect(() => {
7826
+ const anchor = React36.useRef(null);
7827
+ const [pos, setPos] = React36.useState(null);
7828
+ React36.useLayoutEffect(() => {
7814
7829
  if (!open || !anchor.current) {
7815
7830
  setPos(null);
7816
7831
  return;
@@ -7937,9 +7952,10 @@ function ComingSoon({
7937
7952
  ] });
7938
7953
  }
7939
7954
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
7940
- const [open, setOpen] = React35.useState(false);
7955
+ const [open, setOpen] = React36.useState(false);
7941
7956
  const [anchor, pos] = useHoverCard(open);
7942
- const close = React35.useRef(null);
7957
+ const zIndex = useOverlayLayer(SOON_HOVERCARD_BASE);
7958
+ const close = React36.useRef(null);
7943
7959
  const show = () => {
7944
7960
  if (close.current) {
7945
7961
  clearTimeout(close.current);
@@ -7955,7 +7971,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7955
7971
  setOpen(false);
7956
7972
  }, 140);
7957
7973
  };
7958
- React35.useEffect(() => () => {
7974
+ React36.useEffect(() => () => {
7959
7975
  if (close.current) clearTimeout(close.current);
7960
7976
  }, []);
7961
7977
  return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
@@ -7985,12 +8001,12 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7985
8001
  }
7986
8002
  ),
7987
8003
  open && pos ? (0, import_react_dom5.createPortal)(
7988
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
8004
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
7989
8005
  "div",
7990
8006
  {
7991
8007
  className: "fd-soon-note fd-soon-hovercard",
7992
8008
  role: "tooltip",
7993
- style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width },
8009
+ style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
7994
8010
  onMouseEnter: show,
7995
8011
  onMouseLeave: hide,
7996
8012
  children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
@@ -8007,7 +8023,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
8007
8023
  }
8008
8024
  )
8009
8025
  }
8010
- ),
8026
+ ) }),
8011
8027
  document.body
8012
8028
  ) : null
8013
8029
  ]
@@ -8124,13 +8140,15 @@ function PermissionHint({ perm, children }) {
8124
8140
  }
8125
8141
 
8126
8142
  // src/components/platform/ModeSwitch.tsx
8127
- var React36 = __toESM(require("react"), 1);
8143
+ var React37 = __toESM(require("react"), 1);
8128
8144
  var import_jsx_runtime64 = require("react/jsx-runtime");
8145
+ var MODE_SWITCH_BASE = 140;
8129
8146
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
8130
8147
  const mode2 = useRuntimeMode();
8131
- const [open, setOpen] = React36.useState(false);
8132
- const ref = React36.useRef(null);
8133
- React36.useEffect(() => {
8148
+ const [open, setOpen] = React37.useState(false);
8149
+ const zIndex = useOverlayLayer(MODE_SWITCH_BASE);
8150
+ const ref = React37.useRef(null);
8151
+ React37.useEffect(() => {
8134
8152
  if (!open) return;
8135
8153
  const away = (e) => {
8136
8154
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -8168,7 +8186,7 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
8168
8186
  ]
8169
8187
  }
8170
8188
  ),
8171
- open ? /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-view-enter fd-mode-pop", children: [
8189
+ open ? /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-view-enter fd-mode-pop", style: { zIndex }, children: [
8172
8190
  /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
8173
8191
  /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
8174
8192
  /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
@@ -8226,7 +8244,7 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
8226
8244
  ] })
8227
8245
  ] }),
8228
8246
  test && renderLog ? /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
8229
- ] }) : null
8247
+ ] }) }) : null
8230
8248
  ] });
8231
8249
  }
8232
8250
  function TestModeBar({ onExit }) {
@@ -8379,7 +8397,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
8379
8397
  }
8380
8398
 
8381
8399
  // src/components/planner/MixGap.tsx
8382
- var React37 = __toESM(require("react"), 1);
8400
+ var React38 = __toESM(require("react"), 1);
8383
8401
  var import_jsx_runtime67 = require("react/jsx-runtime");
8384
8402
  var MIX_GAP_LAYOUT = {
8385
8403
  trackHeight: 30,
@@ -8394,7 +8412,7 @@ function mixGapOffset(value, max) {
8394
8412
  }
8395
8413
  function MixGap({ rows = [], loading = false, className = "" }) {
8396
8414
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
8397
- const [hover, setHover] = React37.useState(null);
8415
+ const [hover, setHover] = React38.useState(null);
8398
8416
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
8399
8417
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
8400
8418
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
@@ -8537,7 +8555,7 @@ function ChannelContribution({
8537
8555
  }
8538
8556
 
8539
8557
  // src/components/planner/BudgetReallocator.tsx
8540
- var React38 = __toESM(require("react"), 1);
8558
+ var React39 = __toESM(require("react"), 1);
8541
8559
  var import_jsx_runtime69 = require("react/jsx-runtime");
8542
8560
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
8543
8561
  function BudgetReallocator({
@@ -8553,8 +8571,8 @@ function BudgetReallocator({
8553
8571
  onCancel,
8554
8572
  className = ""
8555
8573
  }) {
8556
- const [draft, setDraft] = React38.useState(spend);
8557
- React38.useEffect(() => setDraft(spend), [spend]);
8574
+ const [draft, setDraft] = React39.useState(spend);
8575
+ React39.useEffect(() => setDraft(spend), [spend]);
8558
8576
  const dirty = draft !== spend;
8559
8577
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
8560
8578
  const nextBand = bandFor(nextCrp);
@@ -8724,7 +8742,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "" })
8724
8742
  }
8725
8743
 
8726
8744
  // src/components/planner/PreferenceMeter.tsx
8727
- var React39 = __toESM(require("react"), 1);
8745
+ var React40 = __toESM(require("react"), 1);
8728
8746
  var import_jsx_runtime72 = require("react/jsx-runtime");
8729
8747
  function preferenceScore(criteria) {
8730
8748
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
@@ -8754,7 +8772,7 @@ function PreferenceMeter({
8754
8772
  className = ""
8755
8773
  }) {
8756
8774
  const value = score == null ? preferenceScore(criteria) : score;
8757
- const segments = React39.useMemo(() => preferenceSegments(criteria), [criteria]);
8775
+ const segments = React40.useMemo(() => preferenceSegments(criteria), [criteria]);
8758
8776
  return /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
8759
8777
  ScoreMeter,
8760
8778
  {
@@ -8793,10 +8811,10 @@ function PreferenceMeter({
8793
8811
  }
8794
8812
 
8795
8813
  // src/components/chat/AgentChatPanel.tsx
8796
- var React45 = __toESM(require("react"), 1);
8814
+ var React46 = __toESM(require("react"), 1);
8797
8815
 
8798
8816
  // src/components/chat/chatEngine.ts
8799
- var React40 = __toESM(require("react"), 1);
8817
+ var React41 = __toESM(require("react"), 1);
8800
8818
  var CHAT_UNAVAILABLE = "chat_unavailable";
8801
8819
  var JOB_PENDING = ["queued", "running"];
8802
8820
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -8850,22 +8868,22 @@ function useChatEngine(opts) {
8850
8868
  onClear,
8851
8869
  onFeedback
8852
8870
  } = opts || {};
8853
- const [status, setStatus] = React40.useState("idle");
8854
- const [threadId, setThreadId] = React40.useState(null);
8855
- const [messages, setMessages] = React40.useState([]);
8856
- const [queue, setQueue] = React40.useState([]);
8857
- const [fatal, setFatal] = React40.useState(null);
8858
- const [busy, setBusy] = React40.useState(false);
8859
- const [turnStartedAt, setTurnStartedAt] = React40.useState(null);
8860
- const listRef = React40.useRef([]);
8861
- const queueRef = React40.useRef([]);
8862
- const busyRef = React40.useRef(false);
8863
- const stoppedRef = React40.useRef(false);
8864
- const abortRef = React40.useRef(null);
8865
- const serverCount = React40.useRef(0);
8866
- const threadRef = React40.useRef(null);
8867
- const mounted = React40.useRef(true);
8868
- React40.useEffect(() => {
8871
+ const [status, setStatus] = React41.useState("idle");
8872
+ const [threadId, setThreadId] = React41.useState(null);
8873
+ const [messages, setMessages] = React41.useState([]);
8874
+ const [queue, setQueue] = React41.useState([]);
8875
+ const [fatal, setFatal] = React41.useState(null);
8876
+ const [busy, setBusy] = React41.useState(false);
8877
+ const [turnStartedAt, setTurnStartedAt] = React41.useState(null);
8878
+ const listRef = React41.useRef([]);
8879
+ const queueRef = React41.useRef([]);
8880
+ const busyRef = React41.useRef(false);
8881
+ const stoppedRef = React41.useRef(false);
8882
+ const abortRef = React41.useRef(null);
8883
+ const serverCount = React41.useRef(0);
8884
+ const threadRef = React41.useRef(null);
8885
+ const mounted = React41.useRef(true);
8886
+ React41.useEffect(() => {
8869
8887
  mounted.current = true;
8870
8888
  return () => {
8871
8889
  mounted.current = false;
@@ -8887,14 +8905,14 @@ function useChatEngine(opts) {
8887
8905
  }
8888
8906
  return false;
8889
8907
  };
8890
- const loadThread = React40.useCallback(async (id) => {
8908
+ const loadThread = React41.useCallback(async (id) => {
8891
8909
  const data = await apiAdapter.getThread(id);
8892
8910
  const list = [...data && data.messages || []];
8893
8911
  serverCount.current = list.length;
8894
8912
  commit(list);
8895
8913
  return list;
8896
8914
  }, [apiAdapter]);
8897
- React40.useEffect(() => {
8915
+ React41.useEffect(() => {
8898
8916
  if (!apiAdapter) {
8899
8917
  setStatus("idle");
8900
8918
  setFatal(null);
@@ -9107,7 +9125,7 @@ function useChatEngine(opts) {
9107
9125
  await dispatchTurn(turn);
9108
9126
  }
9109
9127
  }
9110
- const send = React40.useCallback((text, attachments) => {
9128
+ const send = React41.useCallback((text, attachments) => {
9111
9129
  const body = (text || "").trim();
9112
9130
  if (!body && !(attachments && attachments.length)) return;
9113
9131
  if (status === "disconnected") return;
@@ -9117,7 +9135,7 @@ function useChatEngine(opts) {
9117
9135
  stoppedRef.current = false;
9118
9136
  drain();
9119
9137
  }, [status]);
9120
- const stop = React40.useCallback(() => {
9138
+ const stop = React41.useCallback(() => {
9121
9139
  stoppedRef.current = true;
9122
9140
  const ac = abortRef.current;
9123
9141
  if (ac) {
@@ -9136,11 +9154,11 @@ function useChatEngine(opts) {
9136
9154
  store.del(STORAGE_PREFIX + threadRef.current);
9137
9155
  }
9138
9156
  }, [apiAdapter]);
9139
- const removeQueued = React40.useCallback((id) => {
9157
+ const removeQueued = React41.useCallback((id) => {
9140
9158
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
9141
9159
  setQueue(queueRef.current.slice());
9142
9160
  }, []);
9143
- const retry = React40.useCallback(() => {
9161
+ const retry = React41.useCallback(() => {
9144
9162
  const list = listRef.current;
9145
9163
  let at = -1;
9146
9164
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -9156,19 +9174,19 @@ function useChatEngine(opts) {
9156
9174
  setQueue(queueRef.current.slice());
9157
9175
  drain();
9158
9176
  }, []);
9159
- const clear = React40.useCallback(() => {
9177
+ const clear = React41.useCallback(() => {
9160
9178
  commit([]);
9161
9179
  serverCount.current = 0;
9162
9180
  queueRef.current = [];
9163
9181
  setQueue([]);
9164
9182
  onClear && onClear();
9165
9183
  }, [onClear]);
9166
- const setFeedback = React40.useCallback((id, value) => {
9184
+ const setFeedback = React41.useCallback((id, value) => {
9167
9185
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
9168
9186
  const msg = listRef.current.find((m) => m.id === id);
9169
9187
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
9170
9188
  }, [onFeedback]);
9171
- const reload = React40.useCallback(async () => {
9189
+ const reload = React41.useCallback(async () => {
9172
9190
  if (!threadRef.current) return;
9173
9191
  setStatus("loading");
9174
9192
  try {
@@ -9206,10 +9224,10 @@ var ChatKit = {
9206
9224
  };
9207
9225
 
9208
9226
  // src/components/chat/ChatTranscript.tsx
9209
- var React42 = __toESM(require("react"), 1);
9227
+ var React43 = __toESM(require("react"), 1);
9210
9228
 
9211
9229
  // src/components/chat/ChatTurn.tsx
9212
- var React41 = __toESM(require("react"), 1);
9230
+ var React42 = __toESM(require("react"), 1);
9213
9231
  var import_jsx_runtime73 = require("react/jsx-runtime");
9214
9232
  function JsonView({ value }) {
9215
9233
  let text;
@@ -9246,7 +9264,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
9246
9264
  ] });
9247
9265
  }
9248
9266
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
9249
- const [open, setOpen] = React41.useState(defaultOpen);
9267
+ const [open, setOpen] = React42.useState(defaultOpen);
9250
9268
  if (!text) return null;
9251
9269
  return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
9252
9270
  /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
@@ -9263,7 +9281,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
9263
9281
  ] });
9264
9282
  }
9265
9283
  function Citations({ items = [], onOpen }) {
9266
- const [open, setOpen] = React41.useState(false);
9284
+ const [open, setOpen] = React42.useState(false);
9267
9285
  if (!items.length) return null;
9268
9286
  return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fdc-cites", children: [
9269
9287
  /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
@@ -9289,7 +9307,7 @@ function clampText(text, max) {
9289
9307
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
9290
9308
  }
9291
9309
  function MessageBody({ message: m, ctx }) {
9292
- const [expanded, setExpanded] = React41.useState(false);
9310
+ const [expanded, setExpanded] = React42.useState(false);
9293
9311
  const isUser = m.role === "user";
9294
9312
  const raw = m.text || "";
9295
9313
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
@@ -9356,9 +9374,9 @@ function MessageBody({ message: m, ctx }) {
9356
9374
  ] });
9357
9375
  }
9358
9376
  function useCopyRun() {
9359
- const [done, setDone] = React41.useState(false);
9360
- const t = React41.useRef(null);
9361
- React41.useEffect(() => () => {
9377
+ const [done, setDone] = React42.useState(false);
9378
+ const t = React42.useRef(null);
9379
+ React42.useEffect(() => () => {
9362
9380
  if (t.current) clearTimeout(t.current);
9363
9381
  }, []);
9364
9382
  return [done, (text) => {
@@ -9385,7 +9403,7 @@ function RunActions({ group, ctx }) {
9385
9403
  ] }),
9386
9404
  isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
9387
9405
  group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
9388
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(React41.Fragment, { children: [
9406
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(React42.Fragment, { children: [
9389
9407
  /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
9390
9408
  /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
9391
9409
  ] }) : null,
@@ -9480,10 +9498,10 @@ function ChatTranscript({
9480
9498
  renderEmpty,
9481
9499
  className = ""
9482
9500
  }) {
9483
- const scroller = React42.useRef(null);
9484
- const stick = React42.useRef(true);
9485
- const [pill, setPill] = React42.useState(0);
9486
- const seen = React42.useRef(0);
9501
+ const scroller = React43.useRef(null);
9502
+ const stick = React43.useRef(true);
9503
+ const [pill, setPill] = React43.useState(0);
9504
+ const seen = React43.useRef(0);
9487
9505
  const toBottom = (smooth) => {
9488
9506
  const el = scroller.current;
9489
9507
  if (!el) return;
@@ -9502,7 +9520,7 @@ function ChatTranscript({
9502
9520
  seen.current = messages.length;
9503
9521
  }
9504
9522
  };
9505
- React42.useLayoutEffect(() => {
9523
+ React43.useLayoutEffect(() => {
9506
9524
  const el = scroller.current;
9507
9525
  if (!el) return;
9508
9526
  if (stick.current) {
@@ -9510,7 +9528,7 @@ function ChatTranscript({
9510
9528
  seen.current = messages.length;
9511
9529
  } else setPill(Math.max(0, messages.length - seen.current));
9512
9530
  }, [messages]);
9513
- React42.useEffect(() => {
9531
+ React43.useEffect(() => {
9514
9532
  const el = scroller.current;
9515
9533
  const inner = el && el.firstChild;
9516
9534
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -9520,7 +9538,7 @@ function ChatTranscript({
9520
9538
  ro.observe(inner);
9521
9539
  return () => ro.disconnect();
9522
9540
  }, []);
9523
- const groups = React42.useMemo(() => groupMessages(messages), [messages]);
9541
+ const groups = React43.useMemo(() => groupMessages(messages), [messages]);
9524
9542
  const empty = !messages.length && status === "ready";
9525
9543
  return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
9526
9544
  /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
@@ -9544,7 +9562,7 @@ function ChatTranscript({
9544
9562
  const prev = groups[i - 1];
9545
9563
  const k = dayKey(g.messages[0].timestamp);
9546
9564
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
9547
- return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(React42.Fragment, { children: [
9565
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(React43.Fragment, { children: [
9548
9566
  showDay ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { children: dayLabel(k) }) }) : null,
9549
9567
  /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(ChatTurn, { group: g, ctx })
9550
9568
  ] }, g.key || i);
@@ -9561,7 +9579,7 @@ function ChatTranscript({
9561
9579
  var TranscriptKit = { groupMessages };
9562
9580
 
9563
9581
  // src/components/chat/ChatComposer.tsx
9564
- var React43 = __toESM(require("react"), 1);
9582
+ var React44 = __toESM(require("react"), 1);
9565
9583
  var import_jsx_runtime75 = require("react/jsx-runtime");
9566
9584
  function ChatComposer({
9567
9585
  onSubmit,
@@ -9589,17 +9607,17 @@ function ChatComposer({
9589
9607
  onReject,
9590
9608
  onOpenAttachment
9591
9609
  }) {
9592
- const [text, setText] = React43.useState(draft || "");
9593
- const [trigger, setTrigger] = React43.useState(null);
9594
- const [mentionItems, setMentionItems] = React43.useState([]);
9595
- const [listening, setListening] = React43.useState(false);
9596
- const [notice, setNotice] = React43.useState(null);
9597
- const editor = React43.useRef(null);
9598
- const wrap = React43.useRef(null);
9599
- const stopVoice = React43.useRef(null);
9610
+ const [text, setText] = React44.useState(draft || "");
9611
+ const [trigger, setTrigger] = React44.useState(null);
9612
+ const [mentionItems, setMentionItems] = React44.useState([]);
9613
+ const [listening, setListening] = React44.useState(false);
9614
+ const [notice, setNotice] = React44.useState(null);
9615
+ const editor = React44.useRef(null);
9616
+ const wrap = React44.useRef(null);
9617
+ const stopVoice = React44.useRef(null);
9600
9618
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
9601
9619
  } });
9602
- React43.useEffect(() => {
9620
+ React44.useEffect(() => {
9603
9621
  if (draft != null && draft !== text) setText(draft);
9604
9622
  }, [draft]);
9605
9623
  const change = (v) => {
@@ -9633,7 +9651,7 @@ function ChatComposer({
9633
9651
  e.preventDefault();
9634
9652
  staged.add(found.files);
9635
9653
  };
9636
- React43.useEffect(() => {
9654
+ React44.useEffect(() => {
9637
9655
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
9638
9656
  setMentionItems([]);
9639
9657
  return;
@@ -9651,7 +9669,7 @@ function ChatComposer({
9651
9669
  const q = (trigger.query || "").toLowerCase();
9652
9670
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
9653
9671
  }, [trigger, mentionSources]);
9654
- const slashItems = React43.useMemo(() => {
9672
+ const slashItems = React44.useMemo(() => {
9655
9673
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
9656
9674
  const q = (trigger.query || "").toLowerCase();
9657
9675
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -9825,12 +9843,12 @@ function ChatComposer({
9825
9843
  }
9826
9844
 
9827
9845
  // src/components/chat/ChatSessionBar.tsx
9828
- var React44 = __toESM(require("react"), 1);
9846
+ var React45 = __toESM(require("react"), 1);
9829
9847
  var import_jsx_runtime76 = require("react/jsx-runtime");
9830
9848
  var compact2 = meterFormats.compact;
9831
9849
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
9832
- const [open, setOpen] = React44.useState(false);
9833
- const anchor = React44.useRef(null);
9850
+ const [open, setOpen] = React45.useState(false);
9851
+ const anchor = React45.useRef(null);
9834
9852
  const stats = sessionStats || null;
9835
9853
  const cu = contextUsage || null;
9836
9854
  const limits = usageLimits || null;
@@ -9845,7 +9863,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
9845
9863
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
9846
9864
  if (cu) bits.push(pct + "% context");
9847
9865
  const expandable = !!(cu || limits);
9848
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React44.Fragment, { children: [
9866
+ return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React45.Fragment, { children: [
9849
9867
  /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fdc-bar", children: [
9850
9868
  /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
9851
9869
  "button",
@@ -9986,7 +10004,7 @@ function ModelControls({
9986
10004
  ] })
9987
10005
  });
9988
10006
  }
9989
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React44.Fragment, { children: [
10007
+ return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React45.Fragment, { children: [
9990
10008
  /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
9991
10009
  MenuButton,
9992
10010
  {
@@ -10103,11 +10121,11 @@ function AgentChatPanel({
10103
10121
  onFeedback,
10104
10122
  onEditMessage
10105
10123
  }) {
10106
- const [panelWidth, setPanelWidth] = React45.useState(width);
10107
- const [applied, setApplied] = React45.useState({});
10108
- const [draft, setDraft] = React45.useState("");
10109
- const dragging = React45.useRef(null);
10110
- React45.useEffect(() => setPanelWidth(width), [width]);
10124
+ const [panelWidth, setPanelWidth] = React46.useState(width);
10125
+ const [applied, setApplied] = React46.useState({});
10126
+ const [draft, setDraft] = React46.useState("");
10127
+ const dragging = React46.useRef(null);
10128
+ React46.useEffect(() => setPanelWidth(width), [width]);
10111
10129
  const engine = useChatEngine({
10112
10130
  contextType,
10113
10131
  contextId,
@@ -10311,7 +10329,7 @@ function AgentChatPanel({
10311
10329
  }
10312
10330
 
10313
10331
  // src/kits/query.ts
10314
- var React46 = __toESM(require("react"), 1);
10332
+ var React47 = __toESM(require("react"), 1);
10315
10333
  function eqFilter(get2) {
10316
10334
  return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
10317
10335
  }
@@ -10343,22 +10361,22 @@ function compare(a, b, dir) {
10343
10361
  var API = null;
10344
10362
  var PREFS = null;
10345
10363
  function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
10346
- const [query, setQuery] = React46.useState(() => {
10364
+ const [query, setQuery] = React47.useState(() => {
10347
10365
  const store = PREFS || window.PlannerPrefs;
10348
10366
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
10349
10367
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
10350
10368
  });
10351
- const savePref = React46.useCallback((patch2) => {
10369
+ const savePref = React47.useCallback((patch2) => {
10352
10370
  const store = PREFS || window.PlannerPrefs;
10353
10371
  if (prefsKey && store) store.setTable(prefsKey, patch2);
10354
10372
  }, [prefsKey]);
10355
- const [res, setRes] = React46.useState(null);
10356
- const [loading, setLoading] = React46.useState(true);
10357
- const seq2 = React46.useRef(0);
10373
+ const [res, setRes] = React47.useState(null);
10374
+ const [loading, setLoading] = React47.useState(true);
10375
+ const seq2 = React47.useRef(0);
10358
10376
  const depKey = (deps || []).join("|");
10359
10377
  const paramKey = JSON.stringify(params || {});
10360
10378
  const queryKey = JSON.stringify(query);
10361
- React46.useEffect(() => {
10379
+ React47.useEffect(() => {
10362
10380
  const id = ++seq2.current;
10363
10381
  setLoading(true);
10364
10382
  const t = setTimeout(() => {