@flytedan/flytebot-design-system 0.16.0 → 0.17.1

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
@@ -212,6 +212,7 @@ __export(index_exports, {
212
212
  useChatEngine: () => useChatEngine,
213
213
  useFeatureStatus: () => useFeatureStatus,
214
214
  usePopoverPosition: () => usePopoverPosition,
215
+ useResponsiveRail: () => useResponsiveRail,
215
216
  useRuntimeMode: () => useRuntimeMode,
216
217
  useServerTable: () => useServerTable,
217
218
  useSessionContext: () => useSessionContext,
@@ -1107,37 +1108,48 @@ function Spinner({ size = "md", label = "Loading", className = "", style, ...res
1107
1108
  }
1108
1109
 
1109
1110
  // src/components/navigation/SidebarNav.tsx
1111
+ var React6 = __toESM(require("react"), 1);
1110
1112
  var import_jsx_runtime13 = require("react/jsx-runtime");
1111
1113
  function Tip({ label, children }) {
1112
1114
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { title: label, style: { display: "inline-flex", flex: "none" }, children });
1113
1115
  }
1114
- function SidebarNav({ brand, groups = [], current: current2, onNavigate, footer, open = false, className = "", ...rest }) {
1115
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("nav", { className: ["fd-side", className].filter(Boolean).join(" "), "data-open": open ? "true" : "false", ...rest, children: [
1116
- brand ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { height: "var(--topbar-h)", display: "flex", alignItems: "center", padding: "0 18px", borderBottom: "1px solid var(--border)", flex: "none", overflow: "hidden" }, children: brand }) : null,
1117
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { flex: 1, overflow: "auto", padding: "4px 10px 18px" }, children: groups.map((g, gi) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
1118
- g.label ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "fd-side-group", children: g.label }) : null,
1119
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "fd-stack", style: { gap: 2 }, children: g.items.map((it) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1120
- "button",
1121
- {
1122
- type: "button",
1123
- className: "fd-side-item",
1124
- "aria-current": current2 === it.value ? "page" : void 0,
1125
- onClick: onNavigate ? () => onNavigate(it.value) : void 0,
1126
- children: [
1127
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "fd-side-item-icon", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) }),
1128
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, title: truncationTitle(it.label), children: it.label }),
1129
- it.preview ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Tip, { label: "Designed, backend not wired yet", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("i", { className: "ph ph-traffic-cone", style: { fontSize: 13, color: "var(--warn-solid)", flex: "none" } }) }) : null,
1130
- it.locked ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Tip, { label: "You do not have permission for this", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 13, color: "var(--text-muted)", flex: "none" } }) }) : null,
1131
- it.count !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "fd-side-item-count", children: it.count }) : null,
1132
- it.loading ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "fd-skel fd-skel-text", style: { width: 22, height: 11, marginLeft: "auto" } }) : null
1133
- ]
1134
- },
1135
- it.value
1136
- )) })
1137
- ] }, gi)) }),
1138
- footer ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { borderTop: "1px solid var(--border)", padding: 14, flex: "none" }, children: footer }) : null
1139
- ] });
1140
- }
1116
+ var SidebarNav = React6.forwardRef(function SidebarNav2({ brand, groups = [], current: current2, onNavigate, footer, open = false, className = "", ...rest }, ref) {
1117
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1118
+ "nav",
1119
+ {
1120
+ ref,
1121
+ tabIndex: -1,
1122
+ className: ["fd-side", className].filter(Boolean).join(" "),
1123
+ "data-open": open ? "true" : "false",
1124
+ ...rest,
1125
+ children: [
1126
+ brand ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { height: "var(--topbar-h)", display: "flex", alignItems: "center", padding: "0 18px", borderBottom: "1px solid var(--border)", flex: "none", overflow: "hidden" }, children: brand }) : null,
1127
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { flex: 1, overflow: "auto", padding: "4px 10px 18px" }, children: groups.map((g, gi) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
1128
+ g.label ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "fd-side-group", children: g.label }) : null,
1129
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "fd-stack", style: { gap: 2 }, children: g.items.map((it) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1130
+ "button",
1131
+ {
1132
+ type: "button",
1133
+ className: "fd-side-item",
1134
+ "aria-current": current2 === it.value ? "page" : void 0,
1135
+ onClick: onNavigate ? () => onNavigate(it.value) : void 0,
1136
+ children: [
1137
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "fd-side-item-icon", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) }),
1138
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, title: truncationTitle(it.label), children: it.label }),
1139
+ it.preview ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Tip, { label: "Designed, backend not wired yet", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("i", { className: "ph ph-traffic-cone", style: { fontSize: 13, color: "var(--warn-solid)", flex: "none" } }) }) : null,
1140
+ it.locked ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Tip, { label: "You do not have permission for this", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 13, color: "var(--text-muted)", flex: "none" } }) }) : null,
1141
+ it.count !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "fd-side-item-count", children: it.count }) : null,
1142
+ it.loading ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "fd-skel fd-skel-text", style: { width: 22, height: 11, marginLeft: "auto" } }) : null
1143
+ ]
1144
+ },
1145
+ it.value
1146
+ )) })
1147
+ ] }, gi)) }),
1148
+ footer ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { borderTop: "1px solid var(--border)", padding: 14, flex: "none" }, children: footer }) : null
1149
+ ]
1150
+ }
1151
+ );
1152
+ });
1141
1153
 
1142
1154
  // src/components/navigation/FlytedeskBrand.tsx
1143
1155
  var import_jsx_runtime14 = require("react/jsx-runtime");
@@ -1178,13 +1190,13 @@ function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
1178
1190
  }
1179
1191
 
1180
1192
  // src/components/navigation/Topbar.tsx
1181
- var React6 = __toESM(require("react"), 1);
1193
+ var React7 = __toESM(require("react"), 1);
1182
1194
  var import_jsx_runtime16 = require("react/jsx-runtime");
1183
1195
  function useIsNarrow(breakpoint) {
1184
- const [narrow, setNarrow] = React6.useState(
1196
+ const [narrow, setNarrow] = React7.useState(
1185
1197
  () => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
1186
1198
  );
1187
- React6.useEffect(() => {
1199
+ React7.useEffect(() => {
1188
1200
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
1189
1201
  const mq = window.matchMedia(`(max-width: ${breakpoint}px)`);
1190
1202
  const apply = () => setNarrow(mq.matches);
@@ -1205,11 +1217,11 @@ function Topbar({
1205
1217
  ...rest
1206
1218
  }) {
1207
1219
  const narrow = useIsNarrow(overflowBreakpoint);
1208
- const [moreOpen, setMoreOpen] = React6.useState(false);
1209
- const moreRef = React6.useRef(null);
1220
+ const [moreOpen, setMoreOpen] = React7.useState(false);
1221
+ const moreRef = React7.useRef(null);
1210
1222
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("header", { className: ["fd-topbar", narrow ? "is-narrow" : "", className].filter(Boolean).join(" "), ...rest, children: [
1211
1223
  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,
1212
- /* @__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: [
1224
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(React7.Fragment, { children: [
1213
1225
  i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("i", { className: "ph ph-caret-right", style: { fontSize: 11, opacity: 0.6 }, "aria-hidden": "true" }) : null,
1214
1226
  i === crumbs.length - 1 ? (
1215
1227
  // MP-141: the current crumb mixes a static route label with (usually) a
@@ -1418,18 +1430,18 @@ function Toast({ title, children, tone = "success", onUndo, onDismiss, className
1418
1430
  }
1419
1431
 
1420
1432
  // src/components/feedback/Tooltip.tsx
1421
- var React7 = __toESM(require("react"), 1);
1433
+ var React8 = __toESM(require("react"), 1);
1422
1434
  var import_jsx_runtime24 = require("react/jsx-runtime");
1423
1435
  var CLOSE_DELAY_MS = 120;
1424
1436
  function Tooltip({ label, placement = "top", children, className = "" }) {
1425
- const anchorRef = React7.useRef(null);
1426
- const bubbleRef = React7.useRef(null);
1427
- const [reason, setReason] = React7.useState(null);
1428
- const closeTimer = React7.useRef(null);
1429
- const id = React7.useId();
1437
+ const anchorRef = React8.useRef(null);
1438
+ const bubbleRef = React8.useRef(null);
1439
+ const [reason, setReason] = React8.useState(null);
1440
+ const closeTimer = React8.useRef(null);
1441
+ const id = React8.useId();
1430
1442
  const descId = id + "-desc";
1431
1443
  const open = reason != null;
1432
- const cancelClose = React7.useCallback(() => {
1444
+ const cancelClose = React8.useCallback(() => {
1433
1445
  if (closeTimer.current) {
1434
1446
  clearTimeout(closeTimer.current);
1435
1447
  closeTimer.current = null;
@@ -1439,7 +1451,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
1439
1451
  cancelClose();
1440
1452
  setReason(why);
1441
1453
  };
1442
- const hide = React7.useCallback(() => {
1454
+ const hide = React8.useCallback(() => {
1443
1455
  cancelClose();
1444
1456
  setReason(null);
1445
1457
  }, [cancelClose]);
@@ -1454,7 +1466,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
1454
1466
  setReason((r) => r === "hover" ? null : r);
1455
1467
  }, CLOSE_DELAY_MS);
1456
1468
  };
1457
- React7.useEffect(() => cancelClose, [cancelClose]);
1469
+ React8.useEffect(() => cancelClose, [cancelClose]);
1458
1470
  const pos = usePopoverPosition(open, anchorRef, {
1459
1471
  placement: placement === "bottom" ? "bottom-center" : "top-center",
1460
1472
  offset: 8,
@@ -1464,7 +1476,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
1464
1476
  onDetach: hide
1465
1477
  });
1466
1478
  const zIndex = useOverlayLayer(open);
1467
- React7.useEffect(() => {
1479
+ React8.useEffect(() => {
1468
1480
  if (!open) return;
1469
1481
  const key = (e) => {
1470
1482
  if (e.key === "Escape") hide();
@@ -1492,7 +1504,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
1492
1504
  }
1493
1505
  if (keyboard) show("focus");
1494
1506
  };
1495
- const described = React7.isValidElement(children) ? React7.cloneElement(children, {
1507
+ const described = React8.isValidElement(children) ? React8.cloneElement(children, {
1496
1508
  "aria-describedby": [children.props["aria-describedby"], descId].filter(Boolean).join(" ")
1497
1509
  }) : children;
1498
1510
  return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
@@ -1500,7 +1512,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
1500
1512
  {
1501
1513
  ref: anchorRef,
1502
1514
  className: "fd-tooltip-anchor",
1503
- "aria-describedby": React7.isValidElement(children) ? void 0 : descId,
1515
+ "aria-describedby": React8.isValidElement(children) ? void 0 : descId,
1504
1516
  onPointerEnter: (e) => {
1505
1517
  if (isMouse(e)) hover();
1506
1518
  },
@@ -1544,7 +1556,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
1544
1556
  }
1545
1557
 
1546
1558
  // src/components/data/Clamp.tsx
1547
- var React8 = __toESM(require("react"), 1);
1559
+ var React9 = __toESM(require("react"), 1);
1548
1560
  var import_jsx_runtime25 = require("react/jsx-runtime");
1549
1561
  function Clamp({
1550
1562
  children,
@@ -1556,16 +1568,16 @@ function Clamp({
1556
1568
  onToggle,
1557
1569
  className = ""
1558
1570
  }) {
1559
- const [open, setOpen] = React8.useState(false);
1560
- const [overflows, setOverflows] = React8.useState(false);
1561
- const bodyRef = React8.useRef(null);
1562
- const charClamped = React8.useMemo(() => {
1571
+ const [open, setOpen] = React9.useState(false);
1572
+ const [overflows, setOverflows] = React9.useState(false);
1573
+ const bodyRef = React9.useRef(null);
1574
+ const charClamped = React9.useMemo(() => {
1563
1575
  if (open || !maxChars || typeof text !== "string" || text.length <= maxChars) return null;
1564
1576
  const cut = text.slice(0, maxChars);
1565
1577
  const at = cut.lastIndexOf(" ");
1566
1578
  return (at > maxChars * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
1567
1579
  }, [text, maxChars, open]);
1568
- React8.useLayoutEffect(() => {
1580
+ React9.useLayoutEffect(() => {
1569
1581
  const node = bodyRef.current;
1570
1582
  if (maxChars || !node || !maxHeight) return;
1571
1583
  const measure = () => {
@@ -1704,18 +1716,18 @@ function DataTable({
1704
1716
  }
1705
1717
 
1706
1718
  // src/components/data/FilterBar.tsx
1707
- var React9 = __toESM(require("react"), 1);
1719
+ var React10 = __toESM(require("react"), 1);
1708
1720
  var import_jsx_runtime28 = require("react/jsx-runtime");
1709
1721
  var isSet = (v) => !(v == null || v === "" || v === false);
1710
1722
  function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align = "left", className = "", ...rest }) {
1711
- const [panel, setPanel] = React9.useState(null);
1723
+ const [panel, setPanel] = React10.useState(null);
1712
1724
  const zIndex = useOverlayLayer(!!panel);
1713
- const rootRef = React9.useRef(null);
1714
- const textInputRef = React9.useRef(null);
1715
- const optionsRef = React9.useRef(null);
1725
+ const rootRef = React10.useRef(null);
1726
+ const textInputRef = React10.useRef(null);
1727
+ const optionsRef = React10.useRef(null);
1716
1728
  const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
1717
1729
  const dismissible = !!panel && (panel.kind === "add" || panel.kind === "edit" && editingField?.type === "select");
1718
- React9.useEffect(() => {
1730
+ React10.useEffect(() => {
1719
1731
  if (!dismissible) return;
1720
1732
  const away = (e) => {
1721
1733
  if (rootRef.current && !rootRef.current.contains(e.target)) setPanel(null);
@@ -1730,7 +1742,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
1730
1742
  document.removeEventListener("keydown", esc);
1731
1743
  };
1732
1744
  }, [dismissible]);
1733
- React9.useEffect(() => {
1745
+ React10.useEffect(() => {
1734
1746
  if (!panel || panel.kind !== "edit") return;
1735
1747
  if (editingField?.type === "text") {
1736
1748
  textInputRef.current?.focus();
@@ -1896,7 +1908,7 @@ function StatTile({ label, value, sub, delta, loading = false, compact: compact3
1896
1908
  }
1897
1909
 
1898
1910
  // src/components/data/CodeBlock.tsx
1899
- var React10 = __toESM(require("react"), 1);
1911
+ var React11 = __toESM(require("react"), 1);
1900
1912
  var import_jsx_runtime30 = require("react/jsx-runtime");
1901
1913
  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)$/;
1902
1914
  var RULES = {
@@ -2052,13 +2064,13 @@ function tokenize(src, lang) {
2052
2064
  return out;
2053
2065
  }
2054
2066
  function Highlighted({ code, lang }) {
2055
- const toks = React10.useMemo(() => tokenize(code, lang), [code, lang]);
2067
+ const toks = React11.useMemo(() => tokenize(code, lang), [code, lang]);
2056
2068
  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) });
2057
2069
  }
2058
2070
  function useCopy() {
2059
- const [done, setDone] = React10.useState(false);
2060
- const timer = React10.useRef(null);
2061
- React10.useEffect(() => () => {
2071
+ const [done, setDone] = React11.useState(false);
2072
+ const timer = React11.useRef(null);
2073
+ React11.useEffect(() => () => {
2062
2074
  if (timer.current) clearTimeout(timer.current);
2063
2075
  }, []);
2064
2076
  const copy = (text) => {
@@ -2094,8 +2106,8 @@ function CodeBlock({
2094
2106
  actions,
2095
2107
  className = ""
2096
2108
  }) {
2097
- const [wrap, setWrap] = React10.useState(!!wrapDefault);
2098
- const [open, setOpen] = React10.useState(false);
2109
+ const [wrap, setWrap] = React11.useState(!!wrapDefault);
2110
+ const [open, setOpen] = React11.useState(false);
2099
2111
  const [copied, copy] = useCopy();
2100
2112
  const body = String(code).replace(/\n$/, "");
2101
2113
  const lines = body.split("\n");
@@ -2124,7 +2136,7 @@ function CodeBlock({
2124
2136
  ] });
2125
2137
  }
2126
2138
  function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
2127
- const [open, setOpen] = React10.useState(false);
2139
+ const [open, setOpen] = React11.useState(false);
2128
2140
  const [copied, copy] = useCopy();
2129
2141
  const raw = String(diff).replace(/\n$/, "");
2130
2142
  const all = raw.split("\n").map((line) => {
@@ -2170,7 +2182,7 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
2170
2182
  }
2171
2183
 
2172
2184
  // src/components/data/Markdown.tsx
2173
- var React11 = __toESM(require("react"), 1);
2185
+ var React12 = __toESM(require("react"), 1);
2174
2186
  var import_jsx_runtime31 = require("react/jsx-runtime");
2175
2187
  var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
2176
2188
  var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
@@ -2209,7 +2221,7 @@ function inlineNodes(src, ctx, keyBase) {
2209
2221
  const href = safeHref(g(2));
2210
2222
  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()));
2211
2223
  } else if (kind === "cite") {
2212
- 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()));
2224
+ out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(React12.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("sup", { className: "fd-md-cite", children: g(1) }, key()));
2213
2225
  } 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()));
2214
2226
  else if (kind === "strong") out.push(/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
2215
2227
  else if (kind === "em") out.push(/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
@@ -2374,7 +2386,7 @@ function Markdown({
2374
2386
  onLinkClick
2375
2387
  }) {
2376
2388
  const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
2377
- const blocks = React11.useMemo(() => parseBlocks(source), [source]);
2389
+ const blocks = React12.useMemo(() => parseBlocks(source), [source]);
2378
2390
  return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: ["fd-md", className].filter(Boolean).join(" "), children: renderBlocks(blocks, ctx, "b") });
2379
2391
  }
2380
2392
  function MarkdownInline({ source = "", className = "", onLinkClick }) {
@@ -2488,7 +2500,7 @@ function Pagination({
2488
2500
  }
2489
2501
 
2490
2502
  // src/components/data/RelativeTime.tsx
2491
- var React12 = __toESM(require("react"), 1);
2503
+ var React13 = __toESM(require("react"), 1);
2492
2504
  var import_jsx_runtime34 = require("react/jsx-runtime");
2493
2505
  var MIN = 6e4;
2494
2506
  var HOUR = 36e5;
@@ -2540,9 +2552,9 @@ function formatDuration(ms) {
2540
2552
  return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
2541
2553
  }
2542
2554
  function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
2543
- const [, force] = React12.useState(0);
2555
+ const [, force] = React13.useState(0);
2544
2556
  const t = value instanceof Date ? value.getTime() : Date.parse(value);
2545
- React12.useEffect(() => {
2557
+ React13.useEffect(() => {
2546
2558
  if (!refresh2 || !t || isNaN(t)) return;
2547
2559
  const abs = Math.abs(t - Date.now());
2548
2560
  if (abs > DAY) return;
@@ -2558,10 +2570,10 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
2558
2570
  }
2559
2571
 
2560
2572
  // src/components/data/ScoreMeter.tsx
2561
- var React14 = __toESM(require("react"), 1);
2573
+ var React15 = __toESM(require("react"), 1);
2562
2574
 
2563
2575
  // src/components/data/SegmentedMeter.tsx
2564
- var React13 = __toESM(require("react"), 1);
2576
+ var React14 = __toESM(require("react"), 1);
2565
2577
 
2566
2578
  // src/kits/files.ts
2567
2579
  function formatBytes(n) {
@@ -2766,7 +2778,7 @@ function SegmentedMeter({
2766
2778
  const pct = safeTotal ? Math.min(100, Math.round(used / safeTotal * 100)) : 0;
2767
2779
  const w = (v) => safeTotal ? Math.max(0, Math.min(100, Number(v) / safeTotal * 100)) : 0;
2768
2780
  const fill = (s, i) => s.color || (s.variant ? VARIANT_FILL[s.variant] : void 0) || CHART[i % CHART.length];
2769
- const generatedId = React13.useId();
2781
+ const generatedId = React14.useId();
2770
2782
  const uid2 = id || generatedId;
2771
2783
  return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: ["fd-segmeter", className].filter(Boolean).join(" "), onClick, children: [
2772
2784
  label || showTotal ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "fd-segmeter-head", children: [
@@ -2850,10 +2862,10 @@ function ScoreMeter({
2850
2862
  breakdownWidth = 280,
2851
2863
  className = ""
2852
2864
  }) {
2853
- const [open, setOpen] = React14.useState(false);
2854
- const ref = React14.useRef(null);
2865
+ const [open, setOpen] = React15.useState(false);
2866
+ const ref = React15.useRef(null);
2855
2867
  const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
2856
- const body = /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(React14.Fragment, { children: [
2868
+ const body = /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(React15.Fragment, { children: [
2857
2869
  /* @__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 }) }),
2858
2870
  showScore ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
2859
2871
  ] });
@@ -2872,7 +2884,7 @@ function ScoreMeter({
2872
2884
  }
2873
2885
  );
2874
2886
  }
2875
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(React14.Fragment, { children: [
2887
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(React15.Fragment, { children: [
2876
2888
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
2877
2889
  "button",
2878
2890
  {
@@ -2903,13 +2915,13 @@ function ScoreMeter({
2903
2915
  }
2904
2916
 
2905
2917
  // src/components/data/SortMenu.tsx
2906
- var React15 = __toESM(require("react"), 1);
2918
+ var React16 = __toESM(require("react"), 1);
2907
2919
  var import_jsx_runtime37 = require("react/jsx-runtime");
2908
2920
  function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", className = "", ...rest }) {
2909
- const [open, setOpen] = React15.useState(false);
2921
+ const [open, setOpen] = React16.useState(false);
2910
2922
  const zIndex = useOverlayLayer(open);
2911
- const ref = React15.useRef(null);
2912
- React15.useEffect(() => {
2923
+ const ref = React16.useRef(null);
2924
+ React16.useEffect(() => {
2913
2925
  if (!open) return;
2914
2926
  const away = (e) => {
2915
2927
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -2971,7 +2983,7 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
2971
2983
  }
2972
2984
 
2973
2985
  // src/components/data/StepList.tsx
2974
- var React16 = __toESM(require("react"), 1);
2986
+ var React17 = __toESM(require("react"), 1);
2975
2987
  var import_jsx_runtime38 = require("react/jsx-runtime");
2976
2988
  var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
2977
2989
  function StepList({
@@ -2984,9 +2996,9 @@ function StepList({
2984
2996
  dense = false,
2985
2997
  className = ""
2986
2998
  }) {
2987
- const [openState, setOpenState] = React16.useState(defaultOpen);
2999
+ const [openState, setOpenState] = React17.useState(defaultOpen);
2988
3000
  const open = openProp == null ? openState : openProp;
2989
- const [expanded, setExpanded] = React16.useState({});
3001
+ const [expanded, setExpanded] = React17.useState({});
2990
3002
  if (!steps.length) return null;
2991
3003
  const running = steps.some((s) => s.status === "running");
2992
3004
  const failed = steps.filter((s) => s.status === "error").length;
@@ -3044,7 +3056,7 @@ function StepList({
3044
3056
  }
3045
3057
 
3046
3058
  // src/components/data/VirtualList.tsx
3047
- var React17 = __toESM(require("react"), 1);
3059
+ var React18 = __toESM(require("react"), 1);
3048
3060
  var import_jsx_runtime39 = require("react/jsx-runtime");
3049
3061
  var VIRTUAL_LIST_BUFFER_ROWS = 20;
3050
3062
  var VIRTUAL_LIST_ROW_GAP = 6;
@@ -3096,35 +3108,35 @@ function VirtualList({
3096
3108
  className = "",
3097
3109
  style
3098
3110
  }) {
3099
- const [scrollTop, setScrollTop] = React17.useState(0);
3100
- const loaded = React17.useMemo(
3111
+ const [scrollTop, setScrollTop] = React18.useState(0);
3112
+ const loaded = React18.useMemo(
3101
3113
  () => ({ firstItemIndex, count: items.length }),
3102
3114
  [firstItemIndex, items.length]
3103
3115
  );
3104
3116
  const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
3105
3117
  const bandKey = firstItemIndex + ":" + items.length;
3106
- const win = React17.useMemo(
3118
+ const win = React18.useMemo(
3107
3119
  () => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
3108
3120
  [scrollTop, height, itemHeight, total, loaded]
3109
3121
  );
3110
- const need = React17.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
3122
+ const need = React18.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
3111
3123
  const wantStart = need.start && hasMore?.start !== false;
3112
3124
  const wantEnd = need.end && hasMore?.end !== false;
3113
3125
  const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
3114
3126
  const askKey = bandKey + "@" + bucket2;
3115
- const asked = React17.useRef({ start: null, end: null });
3116
- React17.useEffect(() => {
3127
+ const asked = React18.useRef({ start: null, end: null });
3128
+ React18.useEffect(() => {
3117
3129
  if (loading || !wantStart || asked.current.start === askKey) return;
3118
3130
  asked.current.start = askKey;
3119
3131
  onNeedMore("start", win);
3120
3132
  }, [wantStart, loading, askKey, onNeedMore, win]);
3121
- React17.useEffect(() => {
3133
+ React18.useEffect(() => {
3122
3134
  if (loading || !wantEnd || asked.current.end === askKey) return;
3123
3135
  asked.current.end = askKey;
3124
3136
  onNeedMore("end", win);
3125
3137
  }, [wantEnd, loading, askKey, onNeedMore, win]);
3126
- const lastKeysRef = React17.useRef(null);
3127
- const newKeys = React17.useMemo(() => {
3138
+ const lastKeysRef = React18.useRef(null);
3139
+ const newKeys = React18.useMemo(() => {
3128
3140
  const prev = lastKeysRef.current;
3129
3141
  if (!prev) return /* @__PURE__ */ new Set();
3130
3142
  const fresh = /* @__PURE__ */ new Set();
@@ -3134,7 +3146,7 @@ function VirtualList({
3134
3146
  }
3135
3147
  return fresh;
3136
3148
  }, [items]);
3137
- React17.useEffect(() => {
3149
+ React18.useEffect(() => {
3138
3150
  lastKeysRef.current = new Set(items.map(keyOf));
3139
3151
  }, [items]);
3140
3152
  const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
@@ -3179,7 +3191,7 @@ function VirtualList({
3179
3191
  }
3180
3192
 
3181
3193
  // src/components/data/EntityRow.tsx
3182
- var React18 = __toESM(require("react"), 1);
3194
+ var React19 = __toESM(require("react"), 1);
3183
3195
  var import_jsx_runtime40 = require("react/jsx-runtime");
3184
3196
  var ENTITY_ROW_METRIC_WIDTH = 74;
3185
3197
  var METRIC_TONE_COLOR = {
@@ -3192,7 +3204,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
3192
3204
  const key = m.id || m.label || i;
3193
3205
  const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
3194
3206
  const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
3195
- const content = /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(React18.Fragment, { children: [
3207
+ const content = /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(React19.Fragment, { children: [
3196
3208
  m.icon ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
3197
3209
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
3198
3210
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-sr", children: " " + m.label })
@@ -3284,14 +3296,14 @@ function EntityRow({
3284
3296
  }
3285
3297
 
3286
3298
  // src/components/data/TransferList.tsx
3287
- var React20 = __toESM(require("react"), 1);
3299
+ var React21 = __toESM(require("react"), 1);
3288
3300
  var import_react_dom4 = require("react-dom");
3289
3301
 
3290
3302
  // src/components/forms/field.tsx
3291
- var React19 = __toESM(require("react"), 1);
3303
+ var React20 = __toESM(require("react"), 1);
3292
3304
  var import_jsx_runtime41 = require("react/jsx-runtime");
3293
3305
  function useFieldId(id) {
3294
- const generated = React19.useId();
3306
+ const generated = React20.useId();
3295
3307
  return id || generated;
3296
3308
  }
3297
3309
  function FieldLabel({ htmlFor, id, required = false, onClick, children }) {
@@ -3409,12 +3421,12 @@ function TransferList({
3409
3421
  listHeight = 440,
3410
3422
  className = ""
3411
3423
  }) {
3412
- const [drag, setDrag] = React20.useState(null);
3413
- const [dragOverSide, setDragOverSide] = React20.useState(null);
3414
- const dragRef = React20.useRef(null);
3415
- const armedRef = React20.useRef(null);
3416
- const sideRefs = React20.useRef({ left: null, right: null });
3417
- const hitTestSide = React20.useCallback((x, y) => {
3424
+ const [drag, setDrag] = React21.useState(null);
3425
+ const [dragOverSide, setDragOverSide] = React21.useState(null);
3426
+ const dragRef = React21.useRef(null);
3427
+ const armedRef = React21.useRef(null);
3428
+ const sideRefs = React21.useRef({ left: null, right: null });
3429
+ const hitTestSide = React21.useCallback((x, y) => {
3418
3430
  for (const side of ["left", "right"]) {
3419
3431
  const el = sideRefs.current[side];
3420
3432
  if (!el) continue;
@@ -3423,7 +3435,7 @@ function TransferList({
3423
3435
  }
3424
3436
  return null;
3425
3437
  }, []);
3426
- const findItem = React20.useCallback(
3438
+ const findItem = React21.useCallback(
3427
3439
  (side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
3428
3440
  [left.items, right.items, keyOf]
3429
3441
  );
@@ -3445,7 +3457,7 @@ function TransferList({
3445
3457
  height: rect.height
3446
3458
  };
3447
3459
  };
3448
- React20.useEffect(() => {
3460
+ React21.useEffect(() => {
3449
3461
  const onMovePointer = (e) => {
3450
3462
  const armed = armedRef.current;
3451
3463
  if (!armed || e.pointerId !== armed.pointerId) return;
@@ -3498,7 +3510,7 @@ function TransferList({
3498
3510
  window.removeEventListener("pointercancel", endDrag);
3499
3511
  };
3500
3512
  }, [hitTestSide, findItem, onMove]);
3501
- React20.useEffect(() => {
3513
+ React21.useEffect(() => {
3502
3514
  if (!drag || typeof document === "undefined") return;
3503
3515
  const prev = document.body.style.userSelect;
3504
3516
  document.body.style.userSelect = "none";
@@ -3606,11 +3618,11 @@ function TransferList({
3606
3618
  }
3607
3619
 
3608
3620
  // src/components/forms/Checkbox.tsx
3609
- var React21 = __toESM(require("react"), 1);
3621
+ var React22 = __toESM(require("react"), 1);
3610
3622
  var import_jsx_runtime45 = require("react/jsx-runtime");
3611
3623
  function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
3612
- const ref = React21.useRef(null);
3613
- React21.useEffect(() => {
3624
+ const ref = React22.useRef(null);
3625
+ React22.useEffect(() => {
3614
3626
  if (ref.current) ref.current.indeterminate = indeterminate;
3615
3627
  }, [indeterminate]);
3616
3628
  return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
@@ -3669,7 +3681,7 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
3669
3681
  }
3670
3682
 
3671
3683
  // src/components/forms/NumberInput.tsx
3672
- var React22 = __toESM(require("react"), 1);
3684
+ var React23 = __toESM(require("react"), 1);
3673
3685
  var import_jsx_runtime49 = require("react/jsx-runtime");
3674
3686
  function NumberInput({
3675
3687
  label,
@@ -3697,10 +3709,10 @@ function NumberInput({
3697
3709
  const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
3698
3710
  return isNaN(n) ? null : n;
3699
3711
  };
3700
- const [text, setText] = React22.useState(value == null || value === "" ? "" : String(value));
3701
- const [editing, setEditing] = React22.useState(false);
3702
- const timer = React22.useRef(null);
3703
- React22.useEffect(() => {
3712
+ const [text, setText] = React23.useState(value == null || value === "" ? "" : String(value));
3713
+ const [editing, setEditing] = React23.useState(false);
3714
+ const timer = React23.useRef(null);
3715
+ React23.useEffect(() => {
3704
3716
  if (!editing) setText(value == null || value === "" ? "" : String(value));
3705
3717
  }, [value, editing]);
3706
3718
  const clamp = (n) => Math.min(max, Math.max(min, n));
@@ -3724,7 +3736,7 @@ function NumberInput({
3724
3736
  const release = () => {
3725
3737
  if (timer.current) clearTimeout(timer.current);
3726
3738
  };
3727
- React22.useEffect(() => () => {
3739
+ React23.useEffect(() => () => {
3728
3740
  if (timer.current) clearTimeout(timer.current);
3729
3741
  }, []);
3730
3742
  const shown = editing ? text : (() => {
@@ -3811,7 +3823,7 @@ function NumberInput({
3811
3823
  }
3812
3824
 
3813
3825
  // src/components/forms/Select.tsx
3814
- var React23 = __toESM(require("react"), 1);
3826
+ var React24 = __toESM(require("react"), 1);
3815
3827
  var import_jsx_runtime50 = require("react/jsx-runtime");
3816
3828
  var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
3817
3829
  function Select({
@@ -3838,13 +3850,13 @@ function Select({
3838
3850
  const isOn = (v) => multiple ? vals.includes(v) : v === value;
3839
3851
  const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
3840
3852
  const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
3841
- const [open, setOpen] = React23.useState(false);
3842
- const [q, setQ] = React23.useState("");
3843
- const [active, setActive] = React23.useState(-1);
3844
- const rootRef = React23.useRef(null);
3845
- const boxRef = React23.useRef(null);
3846
- const listRef = React23.useRef(null);
3847
- const typeBuf = React23.useRef({ s: "", t: 0 });
3853
+ const [open, setOpen] = React24.useState(false);
3854
+ const [q, setQ] = React24.useState("");
3855
+ const [active, setActive] = React24.useState(-1);
3856
+ const rootRef = React24.useRef(null);
3857
+ const boxRef = React24.useRef(null);
3858
+ const listRef = React24.useRef(null);
3859
+ const typeBuf = React24.useRef({ s: "", t: 0 });
3848
3860
  const selected = multiple ? null : opts.find((o) => o.value === value);
3849
3861
  const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
3850
3862
  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;
@@ -3869,7 +3881,7 @@ function Select({
3869
3881
  }
3870
3882
  setOpen(!open);
3871
3883
  };
3872
- React23.useEffect(() => {
3884
+ React24.useEffect(() => {
3873
3885
  if (!open || active < 0 || !listRef.current) return;
3874
3886
  const el = listRef.current.querySelector('[data-i="' + active + '"]');
3875
3887
  if (el) {
@@ -3990,7 +4002,7 @@ function Select({
3990
4002
  ),
3991
4003
  q ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
3992
4004
  ] }) : void 0,
3993
- footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(React23.Fragment, { children: [
4005
+ footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(React24.Fragment, { children: [
3994
4006
  /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3995
4007
  "button",
3996
4008
  {
@@ -4021,7 +4033,7 @@ function Select({
4021
4033
  'Nothing matches "',
4022
4034
  q,
4023
4035
  '".'
4024
- ] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(React23.Fragment, { children: [
4036
+ ] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(React24.Fragment, { children: [
4025
4037
  grp.g ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
4026
4038
  grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
4027
4039
  "button",
@@ -4058,7 +4070,7 @@ function Select({
4058
4070
  }
4059
4071
 
4060
4072
  // src/components/forms/DatePicker.tsx
4061
- var React24 = __toESM(require("react"), 1);
4073
+ var React25 = __toESM(require("react"), 1);
4062
4074
  var import_jsx_runtime51 = require("react/jsx-runtime");
4063
4075
  var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
4064
4076
  var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
@@ -4076,10 +4088,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
4076
4088
  const today = /* @__PURE__ */ new Date();
4077
4089
  const sel = range ? value || {} : { start: value, end: value };
4078
4090
  const anchor = parse(sel.start) || parse(initialMonth) || today;
4079
- const [vy, setVy] = React24.useState(anchor.getFullYear());
4080
- const [vm, setVm] = React24.useState(anchor.getMonth());
4081
- const [mode2, setMode] = React24.useState("days");
4082
- const [hover, setHover] = React24.useState(null);
4091
+ const [vy, setVy] = React25.useState(anchor.getFullYear());
4092
+ const [vm, setVm] = React25.useState(anchor.getMonth());
4093
+ const [mode2, setMode] = React25.useState("days");
4094
+ const [hover, setHover] = React25.useState(null);
4083
4095
  const s = parse(sel.start), e = parse(sel.end);
4084
4096
  const hoverEnd = range && s && !e && hover ? parse(hover) : null;
4085
4097
  const inRange = (d) => {
@@ -4195,9 +4207,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
4195
4207
  }
4196
4208
  function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, ...rest }) {
4197
4209
  const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
4198
- const [open, setOpen] = React24.useState(false);
4199
- const rootRef = React24.useRef(null);
4200
- const boxRef = React24.useRef(null);
4210
+ const [open, setOpen] = React25.useState(false);
4211
+ const rootRef = React25.useRef(null);
4212
+ const boxRef = React25.useRef(null);
4201
4213
  const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
4202
4214
  const toggle = () => {
4203
4215
  if (!disabled) setOpen(!open);
@@ -4260,7 +4272,7 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
4260
4272
  }
4261
4273
 
4262
4274
  // src/components/forms/TimePicker.tsx
4263
- var React25 = __toESM(require("react"), 1);
4275
+ var React26 = __toESM(require("react"), 1);
4264
4276
  var import_jsx_runtime52 = require("react/jsx-runtime");
4265
4277
  var pad = (n) => String(n).padStart(2, "0");
4266
4278
  function ClockFace({ value = "09:00", onChange }) {
@@ -4269,9 +4281,9 @@ function ClockFace({ value = "09:00", onChange }) {
4269
4281
  if (isNaN(m)) m = 0;
4270
4282
  const pm = h24 >= 12;
4271
4283
  const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
4272
- const [mode2, setMode] = React25.useState("h");
4273
- const faceRef = React25.useRef(null);
4274
- const dragging = React25.useRef(false);
4284
+ const [mode2, setMode] = React26.useState("h");
4285
+ const faceRef = React26.useRef(null);
4286
+ const dragging = React26.useRef(false);
4275
4287
  const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
4276
4288
  const R = 108, NR = 80;
4277
4289
  const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
@@ -4344,9 +4356,9 @@ function ClockFace({ value = "09:00", onChange }) {
4344
4356
  }
4345
4357
  function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
4346
4358
  const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
4347
- const [open, setOpen] = React25.useState(false);
4348
- const rootRef = React25.useRef(null);
4349
- const boxRef = React25.useRef(null);
4359
+ const [open, setOpen] = React26.useState(false);
4360
+ const rootRef = React26.useRef(null);
4361
+ const boxRef = React26.useRef(null);
4350
4362
  const disp = () => {
4351
4363
  if (!value) return "";
4352
4364
  const [h, m] = value.split(":").map(Number);
@@ -4389,7 +4401,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
4389
4401
  offset: 6,
4390
4402
  width: 262,
4391
4403
  role: "presentation",
4392
- footer: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React25.Fragment, { children: [
4404
+ footer: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React26.Fragment, { children: [
4393
4405
  /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
4394
4406
  "button",
4395
4407
  {
@@ -4417,7 +4429,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
4417
4429
  }
4418
4430
 
4419
4431
  // src/components/forms/Slider.tsx
4420
- var React26 = __toESM(require("react"), 1);
4432
+ var React27 = __toESM(require("react"), 1);
4421
4433
  var import_jsx_runtime53 = require("react/jsx-runtime");
4422
4434
  function Slider({
4423
4435
  label,
@@ -4435,7 +4447,7 @@ function Slider({
4435
4447
  ...rest
4436
4448
  }) {
4437
4449
  const fieldId = useFieldId(id);
4438
- const [dragging, setDragging] = React26.useState(false);
4450
+ const [dragging, setDragging] = React27.useState(false);
4439
4451
  const v = value === void 0 ? min : Number(value);
4440
4452
  const pct = max === min ? 0 : (v - min) / (max - min) * 100;
4441
4453
  return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
@@ -4469,7 +4481,7 @@ function Slider({
4469
4481
  }
4470
4482
 
4471
4483
  // src/components/forms/RangeSlider.tsx
4472
- var React27 = __toESM(require("react"), 1);
4484
+ var React28 = __toESM(require("react"), 1);
4473
4485
  var import_jsx_runtime54 = require("react/jsx-runtime");
4474
4486
  function RangeSlider({
4475
4487
  label,
@@ -4489,9 +4501,9 @@ function RangeSlider({
4489
4501
  }) {
4490
4502
  const fmt2 = format || ((v) => String(v));
4491
4503
  const [a, b] = value || [min, max];
4492
- const [drag, setDrag] = React27.useState(null);
4493
- const [focus, setFocus] = React27.useState(null);
4494
- const railRef = React27.useRef(null);
4504
+ const [drag, setDrag] = React28.useState(null);
4505
+ const [focus, setFocus] = React28.useState(null);
4506
+ const railRef = React28.useRef(null);
4495
4507
  const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
4496
4508
  const clampPair = (i, v) => {
4497
4509
  v = Math.min(max, Math.max(min, Math.round(v / step) * step));
@@ -4506,7 +4518,7 @@ function RangeSlider({
4506
4518
  const r = railRef.current.getBoundingClientRect();
4507
4519
  return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
4508
4520
  };
4509
- React27.useEffect(() => {
4521
+ React28.useEffect(() => {
4510
4522
  if (drag === null) return;
4511
4523
  const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
4512
4524
  const upH = () => setDrag(null);
@@ -4587,7 +4599,7 @@ function RangeSlider({
4587
4599
  /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
4588
4600
  /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-rail", ref: railRef }),
4589
4601
  /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
4590
- marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(React27.Fragment, { children: [
4602
+ marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(React28.Fragment, { children: [
4591
4603
  /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
4592
4604
  m.label ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
4593
4605
  ] }, m.value)),
@@ -4616,7 +4628,7 @@ function RangeSlider({
4616
4628
  }
4617
4629
 
4618
4630
  // src/components/forms/Dropzone.tsx
4619
- var React28 = __toESM(require("react"), 1);
4631
+ var React29 = __toESM(require("react"), 1);
4620
4632
  var import_jsx_runtime55 = require("react/jsx-runtime");
4621
4633
  function Dropzone({
4622
4634
  onFiles,
@@ -4631,8 +4643,8 @@ function Dropzone({
4631
4643
  className = "",
4632
4644
  style
4633
4645
  }) {
4634
- const [over, setOver] = React28.useState(false);
4635
- const depth = React28.useRef(0);
4646
+ const [over, setOver] = React29.useState(false);
4647
+ const depth = React29.useRef(0);
4636
4648
  const has = (e) => {
4637
4649
  const dt = e.dataTransfer;
4638
4650
  if (!dt) return false;
@@ -4694,8 +4706,8 @@ function FilePickButton({
4694
4706
  className = "",
4695
4707
  children
4696
4708
  }) {
4697
- const ref = React28.useRef(null);
4698
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(React28.Fragment, { children: [
4709
+ const ref = React29.useRef(null);
4710
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(React29.Fragment, { children: [
4699
4711
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
4700
4712
  "button",
4701
4713
  {
@@ -4728,10 +4740,10 @@ function FilePickButton({
4728
4740
  }
4729
4741
  function useStagedFiles(upload, opts) {
4730
4742
  const o = opts || {};
4731
- const [items, setItems] = React28.useState([]);
4732
- const controllers = React28.useRef({});
4743
+ const [items, setItems] = React29.useState([]);
4744
+ const controllers = React29.useRef({});
4733
4745
  const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
4734
- const run = React28.useCallback((att) => {
4746
+ const run = React29.useCallback((att) => {
4735
4747
  if (!upload) return;
4736
4748
  const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
4737
4749
  controllers.current[att.id] = ac;
@@ -4748,14 +4760,14 @@ function useStagedFiles(upload, opts) {
4748
4760
  delete controllers.current[att.id];
4749
4761
  });
4750
4762
  }, [upload]);
4751
- const add = React28.useCallback((files) => {
4763
+ const add = React29.useCallback((files) => {
4752
4764
  if (!upload) return [];
4753
4765
  const atts = Array.from(files).map((f) => toAttachment(f));
4754
4766
  setItems((list) => list.concat(atts));
4755
4767
  atts.forEach(run);
4756
4768
  return atts;
4757
4769
  }, [upload, run]);
4758
- const remove = React28.useCallback((att) => {
4770
+ const remove = React29.useCallback((att) => {
4759
4771
  const ac = controllers.current[att.id];
4760
4772
  if (ac) {
4761
4773
  try {
@@ -4766,10 +4778,10 @@ function useStagedFiles(upload, opts) {
4766
4778
  }
4767
4779
  setItems((list) => list.filter((f) => f.id !== att.id));
4768
4780
  }, []);
4769
- const retry = React28.useCallback((att) => {
4781
+ const retry = React29.useCallback((att) => {
4770
4782
  run(att);
4771
4783
  }, [run]);
4772
- const clear = React28.useCallback(() => {
4784
+ const clear = React29.useCallback(() => {
4773
4785
  Object.values(controllers.current).forEach((ac) => {
4774
4786
  try {
4775
4787
  ac && ac.abort();
@@ -4893,7 +4905,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
4893
4905
  }
4894
4906
 
4895
4907
  // src/components/forms/MarkdownEditor.tsx
4896
- var React29 = __toESM(require("react"), 1);
4908
+ var React30 = __toESM(require("react"), 1);
4897
4909
  var import_jsx_runtime57 = require("react/jsx-runtime");
4898
4910
  var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
4899
4911
  var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
@@ -5107,7 +5119,7 @@ function syncDom(root, value) {
5107
5119
  while (root.children.length > lines.length) root.removeChild(root.lastChild);
5108
5120
  }
5109
5121
  var LIST_CONT = RE_LI;
5110
- var MarkdownEditor = React29.forwardRef(function MarkdownEditor2({
5122
+ var MarkdownEditor = React30.forwardRef(function MarkdownEditor2({
5111
5123
  value = "",
5112
5124
  onChange,
5113
5125
  onSubmit,
@@ -5126,10 +5138,10 @@ var MarkdownEditor = React29.forwardRef(function MarkdownEditor2({
5126
5138
  className = "",
5127
5139
  id
5128
5140
  }, ref) {
5129
- const boxRef = React29.useRef(null);
5130
- const composing = React29.useRef(false);
5131
- const pendingCaret = React29.useRef(null);
5132
- React29.useLayoutEffect(() => {
5141
+ const boxRef = React30.useRef(null);
5142
+ const composing = React30.useRef(false);
5143
+ const pendingCaret = React30.useRef(null);
5144
+ React30.useLayoutEffect(() => {
5133
5145
  const root = boxRef.current;
5134
5146
  if (!root || composing.current) return;
5135
5147
  const active = document.activeElement === root || root.contains(document.activeElement);
@@ -5138,7 +5150,7 @@ var MarkdownEditor = React29.forwardRef(function MarkdownEditor2({
5138
5150
  pendingCaret.current = null;
5139
5151
  if (active && caret != null) placeCaret(root, caret);
5140
5152
  }, [value]);
5141
- React29.useEffect(() => {
5153
+ React30.useEffect(() => {
5142
5154
  if (autoFocus && boxRef.current) boxRef.current.focus();
5143
5155
  }, [autoFocus]);
5144
5156
  const caretNow = () => {
@@ -5205,7 +5217,7 @@ var MarkdownEditor = React29.forwardRef(function MarkdownEditor2({
5205
5217
  api.replaceRange(from, to, next, from + next.length);
5206
5218
  }
5207
5219
  };
5208
- React29.useImperativeHandle(ref, () => api);
5220
+ React30.useImperativeHandle(ref, () => api);
5209
5221
  function detect(text, caret) {
5210
5222
  if (!onTrigger) return;
5211
5223
  const upto = text.slice(0, caret);
@@ -5357,16 +5369,16 @@ var MarkdownEditor = React29.forwardRef(function MarkdownEditor2({
5357
5369
  });
5358
5370
 
5359
5371
  // src/components/platform/AccountMenu.tsx
5360
- var React31 = __toESM(require("react"), 1);
5372
+ var React32 = __toESM(require("react"), 1);
5361
5373
 
5362
5374
  // src/kits/sessionContext.tsx
5363
- var React30 = __toESM(require("react"), 1);
5364
- var SessionContext = React30.createContext(null);
5375
+ var React31 = __toESM(require("react"), 1);
5376
+ var SessionContext = React31.createContext(null);
5365
5377
  function SessionProvider({ value, children }) {
5366
- return React30.createElement(SessionContext.Provider, { value }, children);
5378
+ return React31.createElement(SessionContext.Provider, { value }, children);
5367
5379
  }
5368
5380
  function useSessionContext() {
5369
- const ctx = React30.useContext(SessionContext);
5381
+ const ctx = React31.useContext(SessionContext);
5370
5382
  if (!ctx) {
5371
5383
  throw new Error(
5372
5384
  "useSessionContext() was called outside a <SessionProvider>. Wrap your app root in <SessionProvider value={...}> with your real session, or \u2014 in the docs site or a demo \u2014 in <DemoSessionProvider>, before rendering AccountMenu, Gate, ProfilePage or AppSwitcher."
@@ -5377,20 +5389,8 @@ function useSessionContext() {
5377
5389
 
5378
5390
  // src/components/platform/AccountMenu.tsx
5379
5391
  var import_jsx_runtime58 = require("react/jsx-runtime");
5380
- var DEFAULT_LINKS = [
5381
- { id: "profile", label: "Your profile", icon: "user-circle", href: "../admin/index.html#profile" },
5382
- { id: "preferences", label: "Preferences", icon: "sliders-horizontal", href: "../admin/index.html#preferences" }
5383
- ];
5384
- var DEFAULT_GROUPS = [
5385
- {
5386
- label: "Administration",
5387
- links: [
5388
- { id: "users", label: "Users", icon: "users-three", href: "../admin/index.html#users", perm: "users.view" },
5389
- { id: "roles", label: "Roles & permissions", icon: "shield-check", href: "../admin/index.html#roles", perm: "roles.manage" },
5390
- { id: "flags", label: "Feature flags", icon: "toggle-right", href: "../admin/index.html#flags", perm: "flags.manage" }
5391
- ]
5392
- }
5393
- ];
5392
+ var DEFAULT_LINKS = [];
5393
+ var DEFAULT_GROUPS = [];
5394
5394
  function Item({ item, onPick }) {
5395
5395
  return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
5396
5396
  "button",
@@ -5418,10 +5418,10 @@ function AccountMenu({
5418
5418
  ...rest
5419
5419
  }) {
5420
5420
  const { user, roles, can: can2, signOut: ctxSignOut, demo } = useSessionContext();
5421
- const [open, setOpen] = React31.useState(false);
5422
- const [switching, setSwitching] = React31.useState(false);
5423
- const [signingOut, setSigningOut] = React31.useState(false);
5424
- const ref = React31.useRef(null);
5421
+ const [open, setOpen] = React32.useState(false);
5422
+ const [switching, setSwitching] = React32.useState(false);
5423
+ const [signingOut, setSigningOut] = React32.useState(false);
5424
+ const ref = React32.useRef(null);
5425
5425
  const visibleLinks = links.filter((l) => !l.perm || can2(l.perm));
5426
5426
  const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || can2(l.perm)) })).filter((g) => g.links.length);
5427
5427
  const pick = (item) => {
@@ -5524,13 +5524,13 @@ function AccountMenu({
5524
5524
  }
5525
5525
 
5526
5526
  // src/components/platform/AppSwitcher.tsx
5527
- var React32 = __toESM(require("react"), 1);
5527
+ var React33 = __toESM(require("react"), 1);
5528
5528
  var import_jsx_runtime59 = require("react/jsx-runtime");
5529
5529
  function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
5530
5530
  const { apps: contextApps } = useSessionContext();
5531
5531
  const apps = appsProp ?? contextApps ?? [];
5532
- const [open, setOpen] = React32.useState(false);
5533
- const anchorRef = React32.useRef(null);
5532
+ const [open, setOpen] = React33.useState(false);
5533
+ const anchorRef = React33.useRef(null);
5534
5534
  if (!apps.length) return null;
5535
5535
  const items = apps.map((app) => ({
5536
5536
  id: app.key,
@@ -5544,7 +5544,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
5544
5544
  window.location.href = app.url;
5545
5545
  }
5546
5546
  }));
5547
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React32.Fragment, { children: [
5547
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React33.Fragment, { children: [
5548
5548
  /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
5549
5549
  IconButton,
5550
5550
  {
@@ -5573,10 +5573,10 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
5573
5573
  }
5574
5574
 
5575
5575
  // src/components/platform/AppearanceMenu.tsx
5576
- var React34 = __toESM(require("react"), 1);
5576
+ var React35 = __toESM(require("react"), 1);
5577
5577
 
5578
5578
  // src/kits/appearance.ts
5579
- var React33 = __toESM(require("react"), 1);
5579
+ var React34 = __toESM(require("react"), 1);
5580
5580
  var DEFAULT_STORAGE_KEY = "fd-appearance";
5581
5581
  var DEFAULT_PREFS = {
5582
5582
  theme: "system",
@@ -5671,11 +5671,11 @@ function applyPrefs(prefs, root = document.documentElement) {
5671
5671
  else root.removeAttribute("data-motion");
5672
5672
  }
5673
5673
  function useAppearancePrefs(store) {
5674
- const prefs = React33.useSyncExternalStore(store.subscribe, store.getSnapshot);
5675
- React33.useEffect(() => {
5674
+ const prefs = React34.useSyncExternalStore(store.subscribe, store.getSnapshot);
5675
+ React34.useEffect(() => {
5676
5676
  applyPrefs(prefs);
5677
5677
  }, [prefs]);
5678
- React33.useEffect(() => {
5678
+ React34.useEffect(() => {
5679
5679
  if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
5680
5680
  return;
5681
5681
  }
@@ -5684,7 +5684,7 @@ function useAppearancePrefs(store) {
5684
5684
  mq.addEventListener("change", onChange);
5685
5685
  return () => mq.removeEventListener("change", onChange);
5686
5686
  }, [prefs]);
5687
- const update = React33.useCallback(
5687
+ const update = React34.useCallback(
5688
5688
  (patch) => {
5689
5689
  store.write({ ...store.getSnapshot(), ...patch });
5690
5690
  },
@@ -5707,15 +5707,15 @@ var TEXT_SCALE_OPTIONS = [
5707
5707
  { value: "xl", label: "XL" }
5708
5708
  ];
5709
5709
  function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
5710
- const store = React34.useMemo(
5710
+ const store = React35.useMemo(
5711
5711
  () => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
5712
5712
  [storeProp, storageKey, storage, defaults]
5713
5713
  );
5714
5714
  const [prefs, update] = useAppearancePrefs(store);
5715
- const [open, setOpen] = React34.useState(false);
5716
- const anchorRef = React34.useRef(null);
5715
+ const [open, setOpen] = React35.useState(false);
5716
+ const anchorRef = React35.useRef(null);
5717
5717
  const patch = (p) => update(p);
5718
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(React34.Fragment, { children: [
5718
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(React35.Fragment, { children: [
5719
5719
  /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
5720
5720
  IconButton,
5721
5721
  {
@@ -5784,14 +5784,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
5784
5784
  }
5785
5785
 
5786
5786
  // src/components/platform/ApiSpecBrowser.tsx
5787
- var React35 = __toESM(require("react"), 1);
5787
+ var React36 = __toESM(require("react"), 1);
5788
5788
  var import_jsx_runtime61 = require("react/jsx-runtime");
5789
5789
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
5790
5790
  function Json({ obj }) {
5791
5791
  return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
5792
5792
  }
5793
5793
  function Endpoint({ s, onRequest }) {
5794
- const [tried, setTried] = React35.useState(null);
5794
+ const [tried, setTried] = React36.useState(null);
5795
5795
  const run = async () => {
5796
5796
  setTried("busy");
5797
5797
  const t0 = (window.performance || Date).now();
@@ -5864,10 +5864,10 @@ function ApiSpecBrowser({
5864
5864
  className = "",
5865
5865
  ...rest
5866
5866
  }) {
5867
- const [q, setQ] = React35.useState("");
5868
- const [method, setMethod] = React35.useState(null);
5869
- const [mod, setMod] = React35.useState(null);
5870
- const [listOnly, setListOnly] = React35.useState(false);
5867
+ const [q, setQ] = React36.useState("");
5868
+ const [method, setMethod] = React36.useState(null);
5869
+ const [mod, setMod] = React36.useState(null);
5870
+ const [listOnly, setListOnly] = React36.useState(false);
5871
5871
  const activeModule = modules && modules.find((m) => m.id === mod);
5872
5872
  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())));
5873
5873
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
@@ -5946,7 +5946,7 @@ function ApiSpecBrowser({
5946
5946
  }
5947
5947
 
5948
5948
  // src/components/platform/ProfilePage.tsx
5949
- var React36 = __toESM(require("react"), 1);
5949
+ var React37 = __toESM(require("react"), 1);
5950
5950
  var import_jsx_runtime62 = require("react/jsx-runtime");
5951
5951
  function fieldInitialValue(field, user) {
5952
5952
  if (field.value) return field.value(user);
@@ -5982,21 +5982,21 @@ function ProfilePage({
5982
5982
  }) {
5983
5983
  const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
5984
5984
  const user = userProp || sessionUser;
5985
- const initialFieldValues = React36.useMemo(() => {
5985
+ const initialFieldValues = React37.useMemo(() => {
5986
5986
  const values2 = {};
5987
5987
  for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
5988
5988
  return values2;
5989
5989
  }, [user.id, fields]);
5990
- const initialNotify = React36.useMemo(() => {
5990
+ const initialNotify = React37.useMemo(() => {
5991
5991
  const values2 = {};
5992
5992
  for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
5993
5993
  return values2;
5994
5994
  }, [user.id, notifications]);
5995
- const [values, setValues] = React36.useState(initialFieldValues);
5996
- const [notify, setNotify] = React36.useState(initialNotify);
5997
- const [saving, setSaving] = React36.useState(false);
5998
- const [saved, setSaved] = React36.useState(false);
5999
- const [prevUserId, setPrevUserId] = React36.useState(user.id);
5995
+ const [values, setValues] = React37.useState(initialFieldValues);
5996
+ const [notify, setNotify] = React37.useState(initialNotify);
5997
+ const [saving, setSaving] = React37.useState(false);
5998
+ const [saved, setSaved] = React37.useState(false);
5999
+ const [prevUserId, setPrevUserId] = React37.useState(user.id);
6000
6000
  if (user.id !== prevUserId) {
6001
6001
  setPrevUserId(user.id);
6002
6002
  setValues(initialFieldValues);
@@ -6184,10 +6184,10 @@ function ProfilePage({
6184
6184
  }
6185
6185
 
6186
6186
  // src/components/platform/RoadmapTimeline.tsx
6187
- var React39 = __toESM(require("react"), 1);
6187
+ var React40 = __toESM(require("react"), 1);
6188
6188
 
6189
6189
  // src/kits/session.ts
6190
- var React37 = __toESM(require("react"), 1);
6190
+ var React38 = __toESM(require("react"), 1);
6191
6191
  var PERMISSION_CATALOG = [
6192
6192
  { group: "Plans", items: [
6193
6193
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -7754,8 +7754,8 @@ function roadmap(overrides) {
7754
7754
  };
7755
7755
  }
7756
7756
  function useSession() {
7757
- const [s, setS] = React37.useState(getSession);
7758
- React37.useEffect(() => subscribe(setS), []);
7757
+ const [s, setS] = React38.useState(getSession);
7758
+ React38.useEffect(() => subscribe(setS), []);
7759
7759
  return s;
7760
7760
  }
7761
7761
  var SessionKit = {
@@ -7788,7 +7788,7 @@ var SessionKit = {
7788
7788
  };
7789
7789
  function DemoSessionProvider({ children }) {
7790
7790
  const session = useSession();
7791
- const value = React37.useMemo(
7791
+ const value = React38.useMemo(
7792
7792
  () => ({
7793
7793
  user: session.user,
7794
7794
  roles: session.roles,
@@ -7804,11 +7804,11 @@ function DemoSessionProvider({ children }) {
7804
7804
  }),
7805
7805
  [session]
7806
7806
  );
7807
- return React37.createElement(SessionProvider, { value }, children);
7807
+ return React38.createElement(SessionProvider, { value }, children);
7808
7808
  }
7809
7809
 
7810
7810
  // src/kits/runtime.ts
7811
- var React38 = __toESM(require("react"), 1);
7811
+ var React39 = __toESM(require("react"), 1);
7812
7812
  var WIRED_ENDPOINTS = [
7813
7813
  // Nothing yet. Every id below would come from a real service:
7814
7814
  // "plan.get", "placements.list", …
@@ -7979,8 +7979,8 @@ var RuntimeKit = {
7979
7979
  };
7980
7980
  RuntimeKit.declare(FEATURE_NEEDS);
7981
7981
  function useRuntimeMode() {
7982
- const [m, setM] = React38.useState(RuntimeKit.getMode());
7983
- React38.useEffect(() => RuntimeKit.subscribe(setM), []);
7982
+ const [m, setM] = React39.useState(RuntimeKit.getMode());
7983
+ React39.useEffect(() => RuntimeKit.subscribe(setM), []);
7984
7984
  return m;
7985
7985
  }
7986
7986
  function useFeatureStatus(key) {
@@ -8063,12 +8063,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
8063
8063
  }
8064
8064
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
8065
8065
  const session = SessionKit.useSession();
8066
- const [project, setProject] = React39.useState("");
8067
- const [q, setQ] = React39.useState("");
8068
- const scrollRef = React39.useRef(null);
8069
- const nowRef = React39.useRef(null);
8070
- const rm = React39.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
8071
- const byKey = React39.useMemo(() => {
8066
+ const [project, setProject] = React40.useState("");
8067
+ const [q, setQ] = React40.useState("");
8068
+ const scrollRef = React40.useRef(null);
8069
+ const nowRef = React40.useRef(null);
8070
+ const rm = React40.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
8071
+ const byKey = React40.useMemo(() => {
8072
8072
  const m = {};
8073
8073
  rm.items.forEach((i) => {
8074
8074
  m[i.key] = i;
@@ -8077,7 +8077,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
8077
8077
  }, [rm]);
8078
8078
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
8079
8079
  const projects = [...new Set(rm.items.map((i) => i.project))];
8080
- React39.useEffect(() => {
8080
+ React40.useEffect(() => {
8081
8081
  let raf1 = 0, raf2 = 0;
8082
8082
  const place = () => {
8083
8083
  const box = scrollRef.current, mark = nowRef.current;
@@ -8151,7 +8151,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
8151
8151
  lastPhase = item.phase;
8152
8152
  const inPhase = items.filter((i) => i.phase === item.phase).length;
8153
8153
  const isBoundary = n === firstPending;
8154
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(React39.Fragment, { children: [
8154
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(React40.Fragment, { children: [
8155
8155
  showPhase ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "fd-rm-era", children: [
8156
8156
  /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
8157
8157
  /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
@@ -8195,7 +8195,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
8195
8195
  }
8196
8196
 
8197
8197
  // src/components/platform/ComingSoon.tsx
8198
- var React40 = __toESM(require("react"), 1);
8198
+ var React41 = __toESM(require("react"), 1);
8199
8199
  var import_react_dom5 = require("react-dom");
8200
8200
  var import_jsx_runtime64 = require("react/jsx-runtime");
8201
8201
  var BYPASS_STORE = "fd.soon.bypass.v1";
@@ -8213,8 +8213,8 @@ function writeBypassed(list) {
8213
8213
  }
8214
8214
  }
8215
8215
  function useBypass(key) {
8216
- const [on, setOn] = React40.useState(() => !!key && readBypassed().indexOf(key) >= 0);
8217
- React40.useEffect(() => {
8216
+ const [on, setOn] = React41.useState(() => !!key && readBypassed().indexOf(key) >= 0);
8217
+ React41.useEffect(() => {
8218
8218
  setOn(!!key && readBypassed().indexOf(key) >= 0);
8219
8219
  }, [key]);
8220
8220
  const set = (next) => {
@@ -8261,9 +8261,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
8261
8261
  ] });
8262
8262
  }
8263
8263
  function useHoverCard(open) {
8264
- const anchor = React40.useRef(null);
8265
- const [pos, setPos] = React40.useState(null);
8266
- React40.useLayoutEffect(() => {
8264
+ const anchor = React41.useRef(null);
8265
+ const [pos, setPos] = React41.useState(null);
8266
+ React41.useLayoutEffect(() => {
8267
8267
  if (!open || !anchor.current) {
8268
8268
  setPos(null);
8269
8269
  return;
@@ -8390,10 +8390,10 @@ function ComingSoon({
8390
8390
  ] });
8391
8391
  }
8392
8392
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
8393
- const [open, setOpen] = React40.useState(false);
8393
+ const [open, setOpen] = React41.useState(false);
8394
8394
  const [anchor, pos] = useHoverCard(open);
8395
8395
  const zIndex = useOverlayLayer(open);
8396
- const close = React40.useRef(null);
8396
+ const close = React41.useRef(null);
8397
8397
  const show = () => {
8398
8398
  if (close.current) {
8399
8399
  clearTimeout(close.current);
@@ -8409,7 +8409,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
8409
8409
  setOpen(false);
8410
8410
  }, 140);
8411
8411
  };
8412
- React40.useEffect(() => () => {
8412
+ React41.useEffect(() => () => {
8413
8413
  if (close.current) clearTimeout(close.current);
8414
8414
  }, []);
8415
8415
  return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
@@ -8580,14 +8580,14 @@ function PermissionHint({ perm, children }) {
8580
8580
  }
8581
8581
 
8582
8582
  // src/components/platform/ModeSwitch.tsx
8583
- var React41 = __toESM(require("react"), 1);
8583
+ var React42 = __toESM(require("react"), 1);
8584
8584
  var import_jsx_runtime66 = require("react/jsx-runtime");
8585
8585
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
8586
8586
  const mode2 = useRuntimeMode();
8587
- const [open, setOpen] = React41.useState(false);
8587
+ const [open, setOpen] = React42.useState(false);
8588
8588
  const zIndex = useOverlayLayer(open);
8589
- const ref = React41.useRef(null);
8590
- React41.useEffect(() => {
8589
+ const ref = React42.useRef(null);
8590
+ React42.useEffect(() => {
8591
8591
  if (!open) return;
8592
8592
  const away = (e) => {
8593
8593
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -8843,7 +8843,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
8843
8843
  }
8844
8844
 
8845
8845
  // src/components/planner/MixGap.tsx
8846
- var React42 = __toESM(require("react"), 1);
8846
+ var React43 = __toESM(require("react"), 1);
8847
8847
  var import_jsx_runtime69 = require("react/jsx-runtime");
8848
8848
  var MIX_GAP_LAYOUT = {
8849
8849
  trackHeight: 30,
@@ -8858,7 +8858,7 @@ function mixGapOffset(value, max) {
8858
8858
  }
8859
8859
  function MixGap({ rows = [], loading = false, className = "" }) {
8860
8860
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
8861
- const [hover, setHover] = React42.useState(null);
8861
+ const [hover, setHover] = React43.useState(null);
8862
8862
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
8863
8863
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
8864
8864
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
@@ -9001,7 +9001,7 @@ function ChannelContribution({
9001
9001
  }
9002
9002
 
9003
9003
  // src/components/planner/BudgetReallocator.tsx
9004
- var React43 = __toESM(require("react"), 1);
9004
+ var React44 = __toESM(require("react"), 1);
9005
9005
  var import_jsx_runtime71 = require("react/jsx-runtime");
9006
9006
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
9007
9007
  function BudgetReallocator({
@@ -9017,8 +9017,8 @@ function BudgetReallocator({
9017
9017
  onCancel,
9018
9018
  className = ""
9019
9019
  }) {
9020
- const [draft, setDraft] = React43.useState(spend);
9021
- React43.useEffect(() => setDraft(spend), [spend]);
9020
+ const [draft, setDraft] = React44.useState(spend);
9021
+ React44.useEffect(() => setDraft(spend), [spend]);
9022
9022
  const dirty = draft !== spend;
9023
9023
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
9024
9024
  const nextBand = bandFor(nextCrp);
@@ -9033,10 +9033,10 @@ function BudgetReallocator({
9033
9033
  setDraft(spend);
9034
9034
  if (onCancel) onCancel();
9035
9035
  };
9036
- const trackRef = React43.useRef(null);
9037
- const chipRef = React43.useRef(null);
9038
- const [chipLeft, setChipLeft] = React43.useState(null);
9039
- React43.useLayoutEffect(() => {
9036
+ const trackRef = React44.useRef(null);
9037
+ const chipRef = React44.useRef(null);
9038
+ const [chipLeft, setChipLeft] = React44.useState(null);
9039
+ React44.useLayoutEffect(() => {
9040
9040
  const track = trackRef.current;
9041
9041
  if (!dirty || !track) {
9042
9042
  setChipLeft(null);
@@ -9223,7 +9223,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "" })
9223
9223
  }
9224
9224
 
9225
9225
  // src/components/planner/PreferenceMeter.tsx
9226
- var React44 = __toESM(require("react"), 1);
9226
+ var React45 = __toESM(require("react"), 1);
9227
9227
  var import_jsx_runtime74 = require("react/jsx-runtime");
9228
9228
  function preferenceScore(criteria) {
9229
9229
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
@@ -9253,7 +9253,7 @@ function PreferenceMeter({
9253
9253
  className = ""
9254
9254
  }) {
9255
9255
  const value = score == null ? preferenceScore(criteria) : score;
9256
- const segments = React44.useMemo(() => preferenceSegments(criteria), [criteria]);
9256
+ const segments = React45.useMemo(() => preferenceSegments(criteria), [criteria]);
9257
9257
  return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
9258
9258
  ScoreMeter,
9259
9259
  {
@@ -9292,10 +9292,10 @@ function PreferenceMeter({
9292
9292
  }
9293
9293
 
9294
9294
  // src/components/chat/AgentChatPanel.tsx
9295
- var React50 = __toESM(require("react"), 1);
9295
+ var React51 = __toESM(require("react"), 1);
9296
9296
 
9297
9297
  // src/components/chat/chatEngine.ts
9298
- var React45 = __toESM(require("react"), 1);
9298
+ var React46 = __toESM(require("react"), 1);
9299
9299
  var CHAT_UNAVAILABLE = "chat_unavailable";
9300
9300
  var JOB_PENDING = ["queued", "running"];
9301
9301
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -9349,22 +9349,22 @@ function useChatEngine(opts) {
9349
9349
  onClear,
9350
9350
  onFeedback
9351
9351
  } = opts || {};
9352
- const [status, setStatus] = React45.useState("idle");
9353
- const [threadId, setThreadId] = React45.useState(null);
9354
- const [messages, setMessages] = React45.useState([]);
9355
- const [queue, setQueue] = React45.useState([]);
9356
- const [fatal, setFatal] = React45.useState(null);
9357
- const [busy, setBusy] = React45.useState(false);
9358
- const [turnStartedAt, setTurnStartedAt] = React45.useState(null);
9359
- const listRef = React45.useRef([]);
9360
- const queueRef = React45.useRef([]);
9361
- const busyRef = React45.useRef(false);
9362
- const stoppedRef = React45.useRef(false);
9363
- const abortRef = React45.useRef(null);
9364
- const serverCount = React45.useRef(0);
9365
- const threadRef = React45.useRef(null);
9366
- const mounted = React45.useRef(true);
9367
- React45.useEffect(() => {
9352
+ const [status, setStatus] = React46.useState("idle");
9353
+ const [threadId, setThreadId] = React46.useState(null);
9354
+ const [messages, setMessages] = React46.useState([]);
9355
+ const [queue, setQueue] = React46.useState([]);
9356
+ const [fatal, setFatal] = React46.useState(null);
9357
+ const [busy, setBusy] = React46.useState(false);
9358
+ const [turnStartedAt, setTurnStartedAt] = React46.useState(null);
9359
+ const listRef = React46.useRef([]);
9360
+ const queueRef = React46.useRef([]);
9361
+ const busyRef = React46.useRef(false);
9362
+ const stoppedRef = React46.useRef(false);
9363
+ const abortRef = React46.useRef(null);
9364
+ const serverCount = React46.useRef(0);
9365
+ const threadRef = React46.useRef(null);
9366
+ const mounted = React46.useRef(true);
9367
+ React46.useEffect(() => {
9368
9368
  mounted.current = true;
9369
9369
  return () => {
9370
9370
  mounted.current = false;
@@ -9386,14 +9386,14 @@ function useChatEngine(opts) {
9386
9386
  }
9387
9387
  return false;
9388
9388
  };
9389
- const loadThread = React45.useCallback(async (id) => {
9389
+ const loadThread = React46.useCallback(async (id) => {
9390
9390
  const data = await apiAdapter.getThread(id);
9391
9391
  const list = [...data && data.messages || []];
9392
9392
  serverCount.current = list.length;
9393
9393
  commit(list);
9394
9394
  return list;
9395
9395
  }, [apiAdapter]);
9396
- React45.useEffect(() => {
9396
+ React46.useEffect(() => {
9397
9397
  if (!apiAdapter) {
9398
9398
  setStatus("idle");
9399
9399
  setFatal(null);
@@ -9606,7 +9606,7 @@ function useChatEngine(opts) {
9606
9606
  await dispatchTurn(turn);
9607
9607
  }
9608
9608
  }
9609
- const send = React45.useCallback((text, attachments) => {
9609
+ const send = React46.useCallback((text, attachments) => {
9610
9610
  const body = (text || "").trim();
9611
9611
  if (!body && !(attachments && attachments.length)) return;
9612
9612
  if (status === "disconnected") return;
@@ -9616,7 +9616,7 @@ function useChatEngine(opts) {
9616
9616
  stoppedRef.current = false;
9617
9617
  drain();
9618
9618
  }, [status]);
9619
- const stop = React45.useCallback(() => {
9619
+ const stop = React46.useCallback(() => {
9620
9620
  stoppedRef.current = true;
9621
9621
  const ac = abortRef.current;
9622
9622
  if (ac) {
@@ -9635,11 +9635,11 @@ function useChatEngine(opts) {
9635
9635
  store.del(STORAGE_PREFIX + threadRef.current);
9636
9636
  }
9637
9637
  }, [apiAdapter]);
9638
- const removeQueued = React45.useCallback((id) => {
9638
+ const removeQueued = React46.useCallback((id) => {
9639
9639
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
9640
9640
  setQueue(queueRef.current.slice());
9641
9641
  }, []);
9642
- const retry = React45.useCallback(() => {
9642
+ const retry = React46.useCallback(() => {
9643
9643
  const list = listRef.current;
9644
9644
  let at = -1;
9645
9645
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -9655,19 +9655,19 @@ function useChatEngine(opts) {
9655
9655
  setQueue(queueRef.current.slice());
9656
9656
  drain();
9657
9657
  }, []);
9658
- const clear = React45.useCallback(() => {
9658
+ const clear = React46.useCallback(() => {
9659
9659
  commit([]);
9660
9660
  serverCount.current = 0;
9661
9661
  queueRef.current = [];
9662
9662
  setQueue([]);
9663
9663
  onClear && onClear();
9664
9664
  }, [onClear]);
9665
- const setFeedback = React45.useCallback((id, value) => {
9665
+ const setFeedback = React46.useCallback((id, value) => {
9666
9666
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
9667
9667
  const msg = listRef.current.find((m) => m.id === id);
9668
9668
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
9669
9669
  }, [onFeedback]);
9670
- const reload = React45.useCallback(async () => {
9670
+ const reload = React46.useCallback(async () => {
9671
9671
  if (!threadRef.current) return;
9672
9672
  setStatus("loading");
9673
9673
  try {
@@ -9705,10 +9705,10 @@ var ChatKit = {
9705
9705
  };
9706
9706
 
9707
9707
  // src/components/chat/ChatTranscript.tsx
9708
- var React47 = __toESM(require("react"), 1);
9708
+ var React48 = __toESM(require("react"), 1);
9709
9709
 
9710
9710
  // src/components/chat/ChatTurn.tsx
9711
- var React46 = __toESM(require("react"), 1);
9711
+ var React47 = __toESM(require("react"), 1);
9712
9712
  var import_jsx_runtime75 = require("react/jsx-runtime");
9713
9713
  function JsonView({ value }) {
9714
9714
  let text;
@@ -9745,7 +9745,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
9745
9745
  ] });
9746
9746
  }
9747
9747
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
9748
- const [open, setOpen] = React46.useState(defaultOpen);
9748
+ const [open, setOpen] = React47.useState(defaultOpen);
9749
9749
  if (!text) return null;
9750
9750
  return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
9751
9751
  /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
@@ -9762,7 +9762,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
9762
9762
  ] });
9763
9763
  }
9764
9764
  function Citations({ items = [], onOpen }) {
9765
- const [open, setOpen] = React46.useState(false);
9765
+ const [open, setOpen] = React47.useState(false);
9766
9766
  if (!items.length) return null;
9767
9767
  return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "fdc-cites", children: [
9768
9768
  /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
@@ -9788,7 +9788,7 @@ function clampText(text, max) {
9788
9788
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
9789
9789
  }
9790
9790
  function MessageBody({ message: m, ctx }) {
9791
- const [expanded, setExpanded] = React46.useState(false);
9791
+ const [expanded, setExpanded] = React47.useState(false);
9792
9792
  const isUser = m.role === "user";
9793
9793
  const raw = m.text || "";
9794
9794
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
@@ -9855,9 +9855,9 @@ function MessageBody({ message: m, ctx }) {
9855
9855
  ] });
9856
9856
  }
9857
9857
  function useCopyRun() {
9858
- const [done, setDone] = React46.useState(false);
9859
- const t = React46.useRef(null);
9860
- React46.useEffect(() => () => {
9858
+ const [done, setDone] = React47.useState(false);
9859
+ const t = React47.useRef(null);
9860
+ React47.useEffect(() => () => {
9861
9861
  if (t.current) clearTimeout(t.current);
9862
9862
  }, []);
9863
9863
  return [done, (text) => {
@@ -9884,7 +9884,7 @@ function RunActions({ group, ctx }) {
9884
9884
  ] }),
9885
9885
  isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
9886
9886
  group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
9887
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(React46.Fragment, { children: [
9887
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(React47.Fragment, { children: [
9888
9888
  /* @__PURE__ */ (0, import_jsx_runtime75.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_runtime75.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
9889
9889
  /* @__PURE__ */ (0, import_jsx_runtime75.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_runtime75.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
9890
9890
  ] }) : null,
@@ -9979,10 +9979,10 @@ function ChatTranscript({
9979
9979
  renderEmpty,
9980
9980
  className = ""
9981
9981
  }) {
9982
- const scroller = React47.useRef(null);
9983
- const stick = React47.useRef(true);
9984
- const [pill, setPill] = React47.useState(0);
9985
- const seen = React47.useRef(0);
9982
+ const scroller = React48.useRef(null);
9983
+ const stick = React48.useRef(true);
9984
+ const [pill, setPill] = React48.useState(0);
9985
+ const seen = React48.useRef(0);
9986
9986
  const toBottom = (smooth) => {
9987
9987
  const el = scroller.current;
9988
9988
  if (!el) return;
@@ -10001,7 +10001,7 @@ function ChatTranscript({
10001
10001
  seen.current = messages.length;
10002
10002
  }
10003
10003
  };
10004
- React47.useLayoutEffect(() => {
10004
+ React48.useLayoutEffect(() => {
10005
10005
  const el = scroller.current;
10006
10006
  if (!el) return;
10007
10007
  if (stick.current) {
@@ -10009,7 +10009,7 @@ function ChatTranscript({
10009
10009
  seen.current = messages.length;
10010
10010
  } else setPill(Math.max(0, messages.length - seen.current));
10011
10011
  }, [messages]);
10012
- React47.useEffect(() => {
10012
+ React48.useEffect(() => {
10013
10013
  const el = scroller.current;
10014
10014
  const inner = el && el.firstChild;
10015
10015
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -10019,7 +10019,7 @@ function ChatTranscript({
10019
10019
  ro.observe(inner);
10020
10020
  return () => ro.disconnect();
10021
10021
  }, []);
10022
- const groups = React47.useMemo(() => groupMessages(messages), [messages]);
10022
+ const groups = React48.useMemo(() => groupMessages(messages), [messages]);
10023
10023
  const empty = !messages.length && status === "ready";
10024
10024
  return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
10025
10025
  /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
@@ -10043,7 +10043,7 @@ function ChatTranscript({
10043
10043
  const prev = groups[i - 1];
10044
10044
  const k = dayKey(g.messages[0].timestamp);
10045
10045
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
10046
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React47.Fragment, { children: [
10046
+ return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React48.Fragment, { children: [
10047
10047
  showDay ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { children: dayLabel(k) }) }) : null,
10048
10048
  /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(ChatTurn, { group: g, ctx })
10049
10049
  ] }, g.key || i);
@@ -10060,7 +10060,7 @@ function ChatTranscript({
10060
10060
  var TranscriptKit = { groupMessages };
10061
10061
 
10062
10062
  // src/components/chat/ChatComposer.tsx
10063
- var React48 = __toESM(require("react"), 1);
10063
+ var React49 = __toESM(require("react"), 1);
10064
10064
  var import_jsx_runtime77 = require("react/jsx-runtime");
10065
10065
  function ChatComposer({
10066
10066
  onSubmit,
@@ -10088,17 +10088,17 @@ function ChatComposer({
10088
10088
  onReject,
10089
10089
  onOpenAttachment
10090
10090
  }) {
10091
- const [text, setText] = React48.useState(draft || "");
10092
- const [trigger, setTrigger] = React48.useState(null);
10093
- const [mentionItems, setMentionItems] = React48.useState([]);
10094
- const [listening, setListening] = React48.useState(false);
10095
- const [notice, setNotice] = React48.useState(null);
10096
- const editor = React48.useRef(null);
10097
- const wrap = React48.useRef(null);
10098
- const stopVoice = React48.useRef(null);
10091
+ const [text, setText] = React49.useState(draft || "");
10092
+ const [trigger, setTrigger] = React49.useState(null);
10093
+ const [mentionItems, setMentionItems] = React49.useState([]);
10094
+ const [listening, setListening] = React49.useState(false);
10095
+ const [notice, setNotice] = React49.useState(null);
10096
+ const editor = React49.useRef(null);
10097
+ const wrap = React49.useRef(null);
10098
+ const stopVoice = React49.useRef(null);
10099
10099
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
10100
10100
  } });
10101
- React48.useEffect(() => {
10101
+ React49.useEffect(() => {
10102
10102
  if (draft != null && draft !== text) setText(draft);
10103
10103
  }, [draft]);
10104
10104
  const change = (v) => {
@@ -10134,7 +10134,7 @@ function ChatComposer({
10134
10134
  e.preventDefault();
10135
10135
  staged.add(found.files);
10136
10136
  };
10137
- React48.useEffect(() => {
10137
+ React49.useEffect(() => {
10138
10138
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
10139
10139
  setMentionItems([]);
10140
10140
  return;
@@ -10152,7 +10152,7 @@ function ChatComposer({
10152
10152
  const q = (trigger.query || "").toLowerCase();
10153
10153
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
10154
10154
  }, [trigger, mentionSources]);
10155
- const slashItems = React48.useMemo(() => {
10155
+ const slashItems = React49.useMemo(() => {
10156
10156
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
10157
10157
  const q = (trigger.query || "").toLowerCase();
10158
10158
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -10326,12 +10326,12 @@ function ChatComposer({
10326
10326
  }
10327
10327
 
10328
10328
  // src/components/chat/ChatSessionBar.tsx
10329
- var React49 = __toESM(require("react"), 1);
10329
+ var React50 = __toESM(require("react"), 1);
10330
10330
  var import_jsx_runtime78 = require("react/jsx-runtime");
10331
10331
  var compact2 = meterFormats.compact;
10332
10332
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
10333
- const [open, setOpen] = React49.useState(false);
10334
- const anchor = React49.useRef(null);
10333
+ const [open, setOpen] = React50.useState(false);
10334
+ const anchor = React50.useRef(null);
10335
10335
  const stats = sessionStats || null;
10336
10336
  const cu = contextUsage || null;
10337
10337
  const limits = usageLimits || null;
@@ -10346,7 +10346,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
10346
10346
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
10347
10347
  if (cu) bits.push(pct + "% context");
10348
10348
  const expandable = !!(cu || limits);
10349
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(React49.Fragment, { children: [
10349
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(React50.Fragment, { children: [
10350
10350
  /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fdc-bar", children: [
10351
10351
  /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
10352
10352
  "button",
@@ -10487,7 +10487,7 @@ function ModelControls({
10487
10487
  ] })
10488
10488
  });
10489
10489
  }
10490
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(React49.Fragment, { children: [
10490
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(React50.Fragment, { children: [
10491
10491
  /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
10492
10492
  MenuButton,
10493
10493
  {
@@ -10604,11 +10604,11 @@ function AgentChatPanel({
10604
10604
  onFeedback,
10605
10605
  onEditMessage
10606
10606
  }) {
10607
- const [panelWidth, setPanelWidth] = React50.useState(width);
10608
- const [applied, setApplied] = React50.useState({});
10609
- const [draft, setDraft] = React50.useState("");
10610
- const dragging = React50.useRef(null);
10611
- React50.useEffect(() => setPanelWidth(width), [width]);
10607
+ const [panelWidth, setPanelWidth] = React51.useState(width);
10608
+ const [applied, setApplied] = React51.useState({});
10609
+ const [draft, setDraft] = React51.useState("");
10610
+ const dragging = React51.useRef(null);
10611
+ React51.useEffect(() => setPanelWidth(width), [width]);
10612
10612
  const engine = useChatEngine({
10613
10613
  contextType,
10614
10614
  contextId,
@@ -10812,7 +10812,7 @@ function AgentChatPanel({
10812
10812
  }
10813
10813
 
10814
10814
  // src/components/files/FileViewer.tsx
10815
- var React51 = __toESM(require("react"), 1);
10815
+ var React52 = __toESM(require("react"), 1);
10816
10816
  var import_jsx_runtime80 = require("react/jsx-runtime");
10817
10817
  function previewKindOf(file) {
10818
10818
  const mime = (file.mime || "").toLowerCase();
@@ -10869,13 +10869,13 @@ function parseDelimited(text, delimiter) {
10869
10869
  return rows;
10870
10870
  }
10871
10871
  function usePreview(file, kind, resolveUrl) {
10872
- const [state, setState] = React51.useState({ status: "loading" });
10873
- const [attempt, setAttempt] = React51.useState(0);
10874
- const resolveRef = React51.useRef(resolveUrl);
10875
- React51.useEffect(() => {
10872
+ const [state, setState] = React52.useState({ status: "loading" });
10873
+ const [attempt, setAttempt] = React52.useState(0);
10874
+ const resolveRef = React52.useRef(resolveUrl);
10875
+ React52.useEffect(() => {
10876
10876
  resolveRef.current = resolveUrl;
10877
10877
  }, [resolveUrl]);
10878
- React51.useEffect(() => {
10878
+ React52.useEffect(() => {
10879
10879
  if (kind === "none") {
10880
10880
  setState({ status: "ready" });
10881
10881
  return;
@@ -10905,7 +10905,7 @@ function usePreview(file, kind, resolveUrl) {
10905
10905
  if (ac) ac.abort();
10906
10906
  };
10907
10907
  }, [file.id, kind, attempt]);
10908
- return { ...state, retry: React51.useCallback(() => setAttempt((a) => a + 1), []) };
10908
+ return { ...state, retry: React52.useCallback(() => setAttempt((a) => a + 1), []) };
10909
10909
  }
10910
10910
  function PreviewBody({ file, kind, state }) {
10911
10911
  if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
@@ -10950,13 +10950,13 @@ function PreviewBody({ file, kind, state }) {
10950
10950
  ] });
10951
10951
  }
10952
10952
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
10953
- const kind = React51.useMemo(() => previewKindOf(file), [file]);
10953
+ const kind = React52.useMemo(() => previewKindOf(file), [file]);
10954
10954
  const preview = usePreview(file, kind, resolveUrl);
10955
- const [tab, setTab] = React51.useState("preview");
10956
- const [downloading, setDownloading] = React51.useState(false);
10957
- const [downloadError, setDownloadError] = React51.useState(null);
10955
+ const [tab, setTab] = React52.useState("preview");
10956
+ const [downloading, setDownloading] = React52.useState(false);
10957
+ const [downloadError, setDownloadError] = React52.useState(null);
10958
10958
  const hasSide = sidePanel != null;
10959
- React51.useEffect(() => {
10959
+ React52.useEffect(() => {
10960
10960
  setTab("preview");
10961
10961
  }, [file.id]);
10962
10962
  const download = () => {
@@ -11023,7 +11023,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
11023
11023
  }
11024
11024
 
11025
11025
  // src/components/files/FileBrowser.tsx
11026
- var React52 = __toESM(require("react"), 1);
11026
+ var React53 = __toESM(require("react"), 1);
11027
11027
  var import_jsx_runtime81 = require("react/jsx-runtime");
11028
11028
  function childrenOf(folders, parentId) {
11029
11029
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
@@ -11094,10 +11094,10 @@ function FolderPickerMenu({
11094
11094
  destinations,
11095
11095
  onPick
11096
11096
  }) {
11097
- const [open, setOpen] = React52.useState(false);
11097
+ const [open, setOpen] = React53.useState(false);
11098
11098
  const zIndex = useOverlayLayer(open);
11099
- const ref = React52.useRef(null);
11100
- React52.useEffect(() => {
11099
+ const ref = React53.useRef(null);
11100
+ React53.useEffect(() => {
11101
11101
  if (!open) return;
11102
11102
  const away = (e) => {
11103
11103
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -11149,8 +11149,8 @@ function FolderPickerMenu({
11149
11149
  ] });
11150
11150
  }
11151
11151
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
11152
- const [over, setOver] = React52.useState(false);
11153
- const dragCounter = React52.useRef(0);
11152
+ const [over, setOver] = React53.useState(false);
11153
+ const dragCounter = React53.useRef(0);
11154
11154
  const dropHandlers = isDropTarget ? {
11155
11155
  onDragEnter: (e) => {
11156
11156
  if (!hasInternalPayload(e)) return;
@@ -11198,8 +11198,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
11198
11198
  }
11199
11199
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
11200
11200
  const kids = childrenOf(folders, folder.id);
11201
- const [expanded, setExpanded] = React52.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
11202
- React52.useEffect(() => {
11201
+ const [expanded, setExpanded] = React53.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
11202
+ React53.useEffect(() => {
11203
11203
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
11204
11204
  }, [currentFolderId, folder.id, folders]);
11205
11205
  const isCurrent = folder.id === currentFolderId;
@@ -11265,15 +11265,15 @@ function FileBrowser({
11265
11265
  const canUpload = perm.canUpload !== false && !!onUpload;
11266
11266
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
11267
11267
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
11268
- const [createOpen, setCreateOpen] = React52.useState(false);
11269
- const [createName, setCreateName] = React52.useState("");
11270
- const [renameTarget, setRenameTarget] = React52.useState(null);
11271
- const [renameValue, setRenameValue] = React52.useState("");
11272
- const [deleteTarget, setDeleteTarget] = React52.useState(null);
11273
- const uploadInputRef = React52.useRef(null);
11274
- const crumbFolders = React52.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
11275
- const subfolders = React52.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
11276
- const currentFiles = React52.useMemo(
11268
+ const [createOpen, setCreateOpen] = React53.useState(false);
11269
+ const [createName, setCreateName] = React53.useState("");
11270
+ const [renameTarget, setRenameTarget] = React53.useState(null);
11271
+ const [renameValue, setRenameValue] = React53.useState("");
11272
+ const [deleteTarget, setDeleteTarget] = React53.useState(null);
11273
+ const uploadInputRef = React53.useRef(null);
11274
+ const crumbFolders = React53.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
11275
+ const subfolders = React53.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
11276
+ const currentFiles = React53.useMemo(
11277
11277
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
11278
11278
  [files, currentFolderId]
11279
11279
  );
@@ -11505,8 +11505,8 @@ function BreadcrumbCrumb({
11505
11505
  isDropTarget,
11506
11506
  onDropPayload
11507
11507
  }) {
11508
- const [over, setOver] = React52.useState(false);
11509
- const dragCounter = React52.useRef(0);
11508
+ const [over, setOver] = React53.useState(false);
11509
+ const dragCounter = React53.useRef(0);
11510
11510
  const dropHandlers = isDropTarget ? {
11511
11511
  onDragEnter: (e) => {
11512
11512
  if (!hasInternalPayload(e)) return;
@@ -11535,7 +11535,7 @@ function BreadcrumbCrumb({
11535
11535
  }
11536
11536
 
11537
11537
  // src/kits/query.ts
11538
- var React53 = __toESM(require("react"), 1);
11538
+ var React54 = __toESM(require("react"), 1);
11539
11539
  function eqFilter(get2) {
11540
11540
  return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
11541
11541
  }
@@ -11567,22 +11567,22 @@ function compare(a, b, dir) {
11567
11567
  var API = null;
11568
11568
  var PREFS = null;
11569
11569
  function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
11570
- const [query, setQuery] = React53.useState(() => {
11570
+ const [query, setQuery] = React54.useState(() => {
11571
11571
  const store = PREFS || window.PlannerPrefs;
11572
11572
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
11573
11573
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
11574
11574
  });
11575
- const savePref = React53.useCallback((patch2) => {
11575
+ const savePref = React54.useCallback((patch2) => {
11576
11576
  const store = PREFS || window.PlannerPrefs;
11577
11577
  if (prefsKey && store) store.setTable(prefsKey, patch2);
11578
11578
  }, [prefsKey]);
11579
- const [res, setRes] = React53.useState(null);
11580
- const [loading, setLoading] = React53.useState(true);
11581
- const seq2 = React53.useRef(0);
11579
+ const [res, setRes] = React54.useState(null);
11580
+ const [loading, setLoading] = React54.useState(true);
11581
+ const seq2 = React54.useRef(0);
11582
11582
  const depKey = (deps || []).join("|");
11583
11583
  const paramKey = JSON.stringify(params || {});
11584
11584
  const queryKey = JSON.stringify(query);
11585
- React53.useEffect(() => {
11585
+ React54.useEffect(() => {
11586
11586
  const id = ++seq2.current;
11587
11587
  setLoading(true);
11588
11588
  const t = setTimeout(() => {
@@ -11879,6 +11879,95 @@ function createVersionStore(initialState, options) {
11879
11879
  }
11880
11880
  };
11881
11881
  }
11882
+
11883
+ // src/kits/useResponsiveRail.ts
11884
+ var React55 = __toESM(require("react"), 1);
11885
+ function matchesBreakpoint(breakpoint) {
11886
+ return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches;
11887
+ }
11888
+ var FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
11889
+ function getFocusable(container) {
11890
+ return Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR));
11891
+ }
11892
+ function useFocusTrap(navRef, active) {
11893
+ React55.useEffect(() => {
11894
+ if (!active) return;
11895
+ const container = navRef.current;
11896
+ if (!container) return;
11897
+ const previouslyFocused = document.activeElement;
11898
+ const focusable = getFocusable(container);
11899
+ (focusable[0] ?? container).focus();
11900
+ const handler = (e) => {
11901
+ if (e.key !== "Tab") return;
11902
+ const items = getFocusable(container);
11903
+ if (items.length === 0) {
11904
+ e.preventDefault();
11905
+ return;
11906
+ }
11907
+ const first = items[0];
11908
+ const last = items[items.length - 1];
11909
+ const activeElement = document.activeElement;
11910
+ const outside = !(activeElement instanceof Node) || !container.contains(activeElement);
11911
+ if (e.shiftKey) {
11912
+ if (outside || activeElement === first) {
11913
+ e.preventDefault();
11914
+ last.focus();
11915
+ }
11916
+ } else if (outside || activeElement === last) {
11917
+ e.preventDefault();
11918
+ first.focus();
11919
+ }
11920
+ };
11921
+ document.addEventListener("keydown", handler);
11922
+ return () => {
11923
+ document.removeEventListener("keydown", handler);
11924
+ previouslyFocused?.focus?.();
11925
+ };
11926
+ }, [active, navRef]);
11927
+ }
11928
+ function useResponsiveRail(options = {}) {
11929
+ const { breakpoint = 1024, initialOpen = true, onPersist } = options;
11930
+ const navRef = React55.useRef(null);
11931
+ const [overlay, setOverlay] = React55.useState(() => matchesBreakpoint(breakpoint));
11932
+ const [open, setOpenRaw] = React55.useState(() => matchesBreakpoint(breakpoint) ? false : initialOpen);
11933
+ const setOpen = React55.useCallback(
11934
+ (value) => {
11935
+ setOpenRaw(value);
11936
+ if (!matchesBreakpoint(breakpoint)) onPersist?.(value);
11937
+ },
11938
+ [breakpoint, onPersist]
11939
+ );
11940
+ const toggle = React55.useCallback(() => setOpen(!open), [open, setOpen]);
11941
+ const close = React55.useCallback(() => setOpenRaw(false), []);
11942
+ React55.useEffect(() => {
11943
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
11944
+ const mq = window.matchMedia(`(max-width: ${breakpoint}px)`);
11945
+ const handler = (e) => {
11946
+ setOverlay(e.matches);
11947
+ setOpenRaw(!e.matches);
11948
+ };
11949
+ mq.addEventListener("change", handler);
11950
+ return () => mq.removeEventListener("change", handler);
11951
+ }, [breakpoint]);
11952
+ React55.useEffect(() => {
11953
+ if (!overlay || !open) return;
11954
+ const handler = (e) => {
11955
+ if (e.key === "Escape") close();
11956
+ };
11957
+ document.addEventListener("keydown", handler);
11958
+ return () => document.removeEventListener("keydown", handler);
11959
+ }, [overlay, open, close]);
11960
+ React55.useEffect(() => {
11961
+ if (!overlay || !open) return;
11962
+ const previousOverflow = document.body.style.overflow;
11963
+ document.body.style.overflow = "hidden";
11964
+ return () => {
11965
+ document.body.style.overflow = previousOverflow;
11966
+ };
11967
+ }, [overlay, open]);
11968
+ useFocusTrap(navRef, overlay && open);
11969
+ return { open, overlay, navRef, toggle, close, setOpen };
11970
+ }
11882
11971
  // Annotate the CommonJS export names for ESM import in node:
11883
11972
  0 && (module.exports = {
11884
11973
  AccountMenu,
@@ -12063,6 +12152,7 @@ function createVersionStore(initialState, options) {
12063
12152
  useChatEngine,
12064
12153
  useFeatureStatus,
12065
12154
  usePopoverPosition,
12155
+ useResponsiveRail,
12066
12156
  useRuntimeMode,
12067
12157
  useServerTable,
12068
12158
  useSessionContext,