@flytedan/flytebot-design-system 0.72.0 → 0.73.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
@@ -1013,6 +1013,7 @@ __export(index_exports, {
1013
1013
  ModeSwitch: () => ModeSwitch,
1014
1014
  ModelControls: () => ModelControls,
1015
1015
  NumberInput: () => NumberInput,
1016
+ OVERLAY_BREAKPOINT: () => OVERLAY_BREAKPOINT,
1016
1017
  OVERLAY_CEILING: () => OVERLAY_CEILING,
1017
1018
  POPOVER_BODY_MIN: () => POPOVER_BODY_MIN,
1018
1019
  PacketCard: () => PacketCard,
@@ -1137,6 +1138,7 @@ __export(index_exports, {
1137
1138
  useDocumentTitle: () => useDocumentTitle,
1138
1139
  useFeatureStatus: () => useFeatureStatus,
1139
1140
  useLayerZIndex: () => useLayerZIndex,
1141
+ useOverlayLayout: () => useOverlayLayout,
1140
1142
  usePopoverPosition: () => usePopoverPosition,
1141
1143
  useResponsiveRail: () => useResponsiveRail,
1142
1144
  useRuntimeMode: () => useRuntimeMode,
@@ -2080,26 +2082,57 @@ function Collapsible({
2080
2082
  }
2081
2083
 
2082
2084
  // src/components/surfaces/Drawer.tsx
2083
- var React6 = __toESM(require("react"), 1);
2085
+ var React7 = __toESM(require("react"), 1);
2084
2086
  var import_react_dom3 = require("react-dom");
2085
- var import_jsx_runtime9 = require("react/jsx-runtime");
2086
- function Drawer({ open: open2 = true, title, onClose, footer, bare = false, children, className = "", ...rest }) {
2087
- const asideRef = React6.useRef(null);
2087
+
2088
+ // src/kits/useClosingAnimation.ts
2089
+ var React6 = __toESM(require("react"), 1);
2090
+ function useClosingAnimation(open2, onClose, durationMs) {
2088
2091
  const [closing, setClosing] = React6.useState(false);
2092
+ const timer = React6.useRef(null);
2093
+ const cancel = React6.useCallback(() => {
2094
+ if (timer.current !== null) clearTimeout(timer.current);
2095
+ timer.current = null;
2096
+ }, []);
2097
+ React6.useEffect(() => {
2098
+ if (!open2) {
2099
+ cancel();
2100
+ setClosing(false);
2101
+ }
2102
+ }, [open2, cancel]);
2103
+ React6.useEffect(() => cancel, [cancel]);
2089
2104
  const close2 = React6.useCallback(() => {
2090
2105
  if (!onClose) return;
2106
+ cancel();
2091
2107
  setClosing(true);
2092
- setTimeout(onClose, 210);
2093
- }, [onClose]);
2108
+ timer.current = setTimeout(() => {
2109
+ timer.current = null;
2110
+ onClose();
2111
+ }, durationMs);
2112
+ }, [onClose, durationMs, cancel]);
2113
+ return { closing, close: close2 };
2114
+ }
2115
+
2116
+ // src/components/surfaces/Drawer.tsx
2117
+ var import_jsx_runtime9 = require("react/jsx-runtime");
2118
+ function Drawer({ open: open2 = true, title, label, onClose, footer, bare = false, children, className = "", ...rest }) {
2119
+ const asideRef = React7.useRef(null);
2120
+ const { closing, close: close2 } = useClosingAnimation(!!open2, onClose, 210);
2094
2121
  const layer = useStackedLayer({ active: !!open2, containerRef: asideRef, trap: true, onEscape: onClose ? close2 : void 0 });
2095
2122
  const zIndex = useLayerZIndex(layer);
2123
+ const titleId = React7.useId();
2124
+ const accessibleName = bare ? label ?? (typeof title === "string" ? title : void 0) : label;
2125
+ const unnamed = !!open2 && bare && !accessibleName;
2126
+ React7.useEffect(() => {
2127
+ if (process.env.NODE_ENV !== "production" && unnamed) console.warn("Drawer: a bare Drawer has no header to name it. Pass `label`, or a string `title`, so the dialog has an accessible name.");
2128
+ }, [unnamed]);
2096
2129
  if (!open2) return null;
2097
2130
  return (0, import_react_dom3.createPortal)(
2098
2131
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(StackedLayerProvider, { layer, children: [
2099
2132
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "fd-scrim" + (closing ? " is-closing" : ""), style: { display: "block", zIndex: zIndex - LAYER_STEP }, onClick: close2 }),
2100
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("aside", { ref: asideRef, className: ["fd-drawer", bare ? "is-bare" : "", closing ? "is-closing" : "", className].filter(Boolean).join(" "), role: "dialog", "aria-modal": "true", "aria-label": bare && typeof title === "string" ? title : void 0, ...rest, style: { zIndex }, children: [
2133
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("aside", { ref: asideRef, className: ["fd-drawer", bare ? "is-bare" : "", closing ? "is-closing" : "", className].filter(Boolean).join(" "), role: "dialog", "aria-modal": "true", "aria-label": accessibleName, "aria-labelledby": bare || label ? void 0 : titleId, ...rest, style: { zIndex }, children: [
2101
2134
  bare ? null : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "fd-card-head", style: { flex: "none" }, children: [
2102
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "fd-card-head-title", title: truncationTitle(title), children: title }),
2135
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { id: titleId, className: "fd-card-head-title", title: truncationTitle(title), children: title }),
2103
2136
  onClose ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Close", onClick: close2, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("i", { className: "ph ph-x" }) }) : null
2104
2137
  ] }),
2105
2138
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: bare ? { flex: "1 1 auto", minHeight: 0, display: "flex", flexDirection: "column" } : { flex: "1 1 auto", minHeight: 0, overflow: "auto", padding: 20 }, children: typeof children === "function" ? children(close2) : children }),
@@ -2111,17 +2144,12 @@ function Drawer({ open: open2 = true, title, onClose, footer, bare = false, chil
2111
2144
  }
2112
2145
 
2113
2146
  // src/components/surfaces/Modal.tsx
2114
- var React7 = __toESM(require("react"), 1);
2147
+ var React8 = __toESM(require("react"), 1);
2115
2148
  var import_react_dom4 = require("react-dom");
2116
2149
  var import_jsx_runtime10 = require("react/jsx-runtime");
2117
2150
  function Modal({ open: open2 = true, title, description, onClose, footer, wide = false, children, className = "", ...rest }) {
2118
- const [closing, setClosing] = React7.useState(false);
2119
- const boxRef = React7.useRef(null);
2120
- const close2 = React7.useCallback(() => {
2121
- if (!onClose) return;
2122
- setClosing(true);
2123
- setTimeout(onClose, 190);
2124
- }, [onClose]);
2151
+ const boxRef = React8.useRef(null);
2152
+ const { closing, close: close2 } = useClosingAnimation(!!open2, onClose, 190);
2125
2153
  const layer = useStackedLayer({ active: !!open2, containerRef: boxRef, trap: true, onEscape: onClose ? close2 : void 0 });
2126
2154
  const zIndex = useLayerZIndex(layer);
2127
2155
  if (!open2) return null;
@@ -2204,13 +2232,13 @@ function ScreenHead({ kicker, title, lede, actions }) {
2204
2232
  }
2205
2233
 
2206
2234
  // src/components/layout/CardGrid.tsx
2207
- var React8 = __toESM(require("react"), 1);
2235
+ var React9 = __toESM(require("react"), 1);
2208
2236
  var import_jsx_runtime12 = require("react/jsx-runtime");
2209
2237
  function flattenFragments(children) {
2210
2238
  const out = [];
2211
- React8.Children.forEach(children, (child) => {
2239
+ React9.Children.forEach(children, (child) => {
2212
2240
  if (child === null || child === void 0 || typeof child === "boolean") return;
2213
- if (React8.isValidElement(child) && child.type === React8.Fragment) {
2241
+ if (React9.isValidElement(child) && child.type === React9.Fragment) {
2214
2242
  const fragmentChildren = child.props.children;
2215
2243
  out.push(...flattenFragments(fragmentChildren));
2216
2244
  return;
@@ -2228,7 +2256,7 @@ function CardGrid({ children, minCardWidth = 280, gap = "lg", className = "", st
2228
2256
  className: ["fd-card-grid", "fd-gap-" + gap, className].filter(Boolean).join(" "),
2229
2257
  style: { ["--card-grid-min"]: minCardWidth + "px", ...style },
2230
2258
  children: items.map((child, i) => {
2231
- if (React8.isValidElement(child)) {
2259
+ if (React9.isValidElement(child)) {
2232
2260
  const existingRole = child.props.role;
2233
2261
  if (existingRole) return child;
2234
2262
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { role: "listitem", children: child }, child.key ?? i);
@@ -2278,10 +2306,10 @@ function LoadingRegion({
2278
2306
  }
2279
2307
 
2280
2308
  // src/components/loading/JobTray.tsx
2281
- var React10 = __toESM(require("react"), 1);
2309
+ var React11 = __toESM(require("react"), 1);
2282
2310
 
2283
2311
  // src/kits/cornerStack.tsx
2284
- var React9 = __toESM(require("react"), 1);
2312
+ var React10 = __toESM(require("react"), 1);
2285
2313
  var import_react_dom5 = require("react-dom");
2286
2314
  var CORNER_STACK_INSET_PROPERTY = "--fd-corner-stack-inset";
2287
2315
  var SLOTS = ["jobs", "toasts"];
@@ -2331,9 +2359,9 @@ function release(slot) {
2331
2359
  slotElements.clear();
2332
2360
  }
2333
2361
  }
2334
- var useSlotEffect = typeof document === "undefined" ? React9.useEffect : React9.useLayoutEffect;
2362
+ var useSlotEffect = typeof document === "undefined" ? React10.useEffect : React10.useLayoutEffect;
2335
2363
  function useCornerStackSlot(slot) {
2336
- const [element, setElement] = React9.useState(null);
2364
+ const [element, setElement] = React10.useState(null);
2337
2365
  useSlotEffect(() => {
2338
2366
  setElement(acquire(slot));
2339
2367
  return () => {
@@ -2390,9 +2418,9 @@ function announcementFor(job) {
2390
2418
  return title + ": in progress";
2391
2419
  }
2392
2420
  function JobTray({ jobs: jobs2, onDismiss, className = "" }) {
2393
- const [announcement, setAnnouncement] = React10.useState("");
2394
- const prevStatuses = React10.useRef({});
2395
- React10.useEffect(() => {
2421
+ const [announcement, setAnnouncement] = React11.useState("");
2422
+ const prevStatuses = React11.useRef({});
2423
+ React11.useEffect(() => {
2396
2424
  let next = "";
2397
2425
  for (const job of jobs2) {
2398
2426
  if (prevStatuses.current[job.id] !== job.status) {
@@ -2443,7 +2471,7 @@ function JobCard({ job, onDismiss }) {
2443
2471
  }
2444
2472
 
2445
2473
  // src/components/loading/PhasedProgress.tsx
2446
- var React11 = __toESM(require("react"), 1);
2474
+ var React12 = __toESM(require("react"), 1);
2447
2475
  var import_jsx_runtime16 = require("react/jsx-runtime");
2448
2476
  var ICON = {
2449
2477
  pending: "ph-circle",
@@ -2456,9 +2484,9 @@ function textOf2(node) {
2456
2484
  return "";
2457
2485
  }
2458
2486
  function PhasedProgress({ phases, summary, className = "" }) {
2459
- const [announcement, setAnnouncement] = React11.useState("");
2460
- const prevStatuses = React11.useRef({});
2461
- React11.useEffect(() => {
2487
+ const [announcement, setAnnouncement] = React12.useState("");
2488
+ const prevStatuses = React12.useRef({});
2489
+ React12.useEffect(() => {
2462
2490
  let next = "";
2463
2491
  for (const phase of phases) {
2464
2492
  if (prevStatuses.current[phase.id] !== phase.status) {
@@ -2538,12 +2566,12 @@ function Spinner({ size = "md", label = "Loading", className = "", style, ...res
2538
2566
  }
2539
2567
 
2540
2568
  // src/components/navigation/SidebarNav.tsx
2541
- var React12 = __toESM(require("react"), 1);
2569
+ var React13 = __toESM(require("react"), 1);
2542
2570
  var import_jsx_runtime20 = require("react/jsx-runtime");
2543
2571
  function Tip({ label, children }) {
2544
2572
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { title: label, style: { display: "inline-flex", flex: "none" }, children });
2545
2573
  }
2546
- var SidebarNav = React12.forwardRef(function SidebarNav2({ brand, groups = [], current: current2, onNavigate, footer, open: open2 = false, className = "", ...rest }, ref) {
2574
+ var SidebarNav = React13.forwardRef(function SidebarNav2({ brand, groups = [], current: current2, onNavigate, footer, open: open2 = false, className = "", ...rest }, ref) {
2547
2575
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
2548
2576
  "nav",
2549
2577
  {
@@ -2582,15 +2610,15 @@ var SidebarNav = React12.forwardRef(function SidebarNav2({ brand, groups = [], c
2582
2610
  });
2583
2611
 
2584
2612
  // src/components/navigation/Topbar.tsx
2585
- var React14 = __toESM(require("react"), 1);
2613
+ var React15 = __toESM(require("react"), 1);
2586
2614
 
2587
2615
  // src/kits/useIsNarrow.ts
2588
- var React13 = __toESM(require("react"), 1);
2616
+ var React14 = __toESM(require("react"), 1);
2589
2617
  function useIsNarrow(breakpoint) {
2590
- const [narrow, setNarrow] = React13.useState(
2618
+ const [narrow, setNarrow] = React14.useState(
2591
2619
  () => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
2592
2620
  );
2593
- React13.useEffect(() => {
2621
+ React14.useEffect(() => {
2594
2622
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
2595
2623
  const mq = window.matchMedia(`(max-width: ${breakpoint}px)`);
2596
2624
  const apply = () => setNarrow(mq.matches);
@@ -2614,11 +2642,11 @@ function Topbar({
2614
2642
  ...rest
2615
2643
  }) {
2616
2644
  const narrow = useIsNarrow(overflowBreakpoint);
2617
- const [moreOpen, setMoreOpen] = React14.useState(false);
2618
- const moreRef = React14.useRef(null);
2645
+ const [moreOpen, setMoreOpen] = React15.useState(false);
2646
+ const moreRef = React15.useRef(null);
2619
2647
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("header", { className: ["fd-topbar", narrow ? "is-narrow" : "", className].filter(Boolean).join(" "), ...rest, children: [
2620
2648
  onMenu ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Menu", onClick: onMenu, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("i", { className: "ph ph-list" }) }) : null,
2621
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(React14.Fragment, { children: [
2649
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(React15.Fragment, { children: [
2622
2650
  i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("i", { className: "ph ph-caret-right", style: { fontSize: 11, opacity: 0.6 }, "aria-hidden": "true" }) : null,
2623
2651
  i === crumbs.length - 1 ? (
2624
2652
  // MP-141: the current crumb mixes a static route label with (usually) a
@@ -2671,29 +2699,37 @@ function Topbar({
2671
2699
  }
2672
2700
 
2673
2701
  // src/kits/useResponsiveRail.ts
2674
- var React15 = __toESM(require("react"), 1);
2702
+ var React16 = __toESM(require("react"), 1);
2703
+
2704
+ // src/kits/overlayLayout.ts
2705
+ var OVERLAY_BREAKPOINT = 1024;
2706
+ function useOverlayLayout() {
2707
+ return useIsNarrow(OVERLAY_BREAKPOINT);
2708
+ }
2709
+
2710
+ // src/kits/useResponsiveRail.ts
2675
2711
  function useResponsiveRail(options = {}) {
2676
- const { breakpoint = 1024, initialOpen = true, onPersist } = options;
2677
- const navRef = React15.useRef(null);
2712
+ const { breakpoint = OVERLAY_BREAKPOINT, initialOpen = true, onPersist } = options;
2713
+ const navRef = React16.useRef(null);
2678
2714
  const overlay = useIsNarrow(breakpoint);
2679
- const [open2, setOpenRaw] = React15.useState(() => overlay ? false : initialOpen);
2680
- const setOpen = React15.useCallback(
2715
+ const [open2, setOpenRaw] = React16.useState(() => overlay ? false : initialOpen);
2716
+ const setOpen = React16.useCallback(
2681
2717
  (value) => {
2682
2718
  setOpenRaw(value);
2683
2719
  if (!overlay) onPersist?.(value);
2684
2720
  },
2685
2721
  [overlay, onPersist]
2686
2722
  );
2687
- const toggle = React15.useCallback(() => setOpen(!open2), [open2, setOpen]);
2688
- const close2 = React15.useCallback(() => setOpenRaw(false), []);
2689
- const lastOverlay = React15.useRef(overlay);
2690
- React15.useEffect(() => {
2723
+ const toggle = React16.useCallback(() => setOpen(!open2), [open2, setOpen]);
2724
+ const close2 = React16.useCallback(() => setOpenRaw(false), []);
2725
+ const lastOverlay = React16.useRef(overlay);
2726
+ React16.useEffect(() => {
2691
2727
  if (lastOverlay.current === overlay) return;
2692
2728
  lastOverlay.current = overlay;
2693
2729
  setOpenRaw(!overlay);
2694
2730
  }, [overlay]);
2695
2731
  const layer = useStackedLayer({ active: overlay && open2, containerRef: navRef, trap: true, onEscape: close2 });
2696
- React15.useEffect(() => {
2732
+ React16.useEffect(() => {
2697
2733
  if (!overlay || !open2) return;
2698
2734
  const previousOverflow = document.body.style.overflow;
2699
2735
  document.body.style.overflow = "hidden";
@@ -2714,7 +2750,7 @@ function AppShell({
2714
2750
  navFooter,
2715
2751
  initialNavOpen = true,
2716
2752
  onNavOpenChange,
2717
- railBreakpoint = 1024,
2753
+ railBreakpoint = OVERLAY_BREAKPOINT,
2718
2754
  crumbs,
2719
2755
  loading,
2720
2756
  actions,
@@ -2820,20 +2856,20 @@ function installFlytedeskFavicon(url) {
2820
2856
  }
2821
2857
 
2822
2858
  // src/components/navigation/Tabs.tsx
2823
- var React16 = __toESM(require("react"), 1);
2859
+ var React17 = __toESM(require("react"), 1);
2824
2860
  var import_jsx_runtime24 = require("react/jsx-runtime");
2825
2861
  var FADE_WIDTH = 32;
2826
2862
  function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
2827
- const strip = React16.useRef(null);
2828
- const [more, setMore] = React16.useState({ start: false, end: false });
2829
- const measure = React16.useCallback(() => {
2863
+ const strip = React17.useRef(null);
2864
+ const [more, setMore] = React17.useState({ start: false, end: false });
2865
+ const measure = React17.useCallback(() => {
2830
2866
  const el = strip.current;
2831
2867
  if (!el) return;
2832
2868
  const start = el.scrollLeft > 1;
2833
2869
  const end = el.scrollLeft + el.clientWidth < el.scrollWidth - 1;
2834
2870
  setMore((m) => m.start === start && m.end === end ? m : { start, end });
2835
2871
  }, []);
2836
- React16.useLayoutEffect(() => {
2872
+ React17.useLayoutEffect(() => {
2837
2873
  const el = strip.current;
2838
2874
  measure();
2839
2875
  if (!el || typeof ResizeObserver === "undefined") return;
@@ -2841,7 +2877,7 @@ function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
2841
2877
  observer.observe(el);
2842
2878
  return () => observer.disconnect();
2843
2879
  }, [measure, tabs]);
2844
- const revealActive = React16.useCallback(() => {
2880
+ const revealActive = React17.useCallback(() => {
2845
2881
  const el = strip.current;
2846
2882
  const active = el?.querySelector('[aria-selected="true"]');
2847
2883
  if (!el || !active || el.scrollWidth <= el.clientWidth) return;
@@ -2851,9 +2887,9 @@ function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
2851
2887
  else if (tab.right > box.right - FADE_WIDTH) el.scrollLeft += tab.right - box.right + FADE_WIDTH;
2852
2888
  measure();
2853
2889
  }, [measure]);
2854
- React16.useLayoutEffect(revealActive, [value, revealActive]);
2890
+ React17.useLayoutEffect(revealActive, [value, revealActive]);
2855
2891
  const tabKeys = tabs.map((t) => typeof t === "string" ? t : t.value).join(",");
2856
- React16.useLayoutEffect(() => {
2892
+ React17.useLayoutEffect(() => {
2857
2893
  const el = strip.current;
2858
2894
  if (!el || typeof ResizeObserver === "undefined") return;
2859
2895
  const observer = new ResizeObserver(revealActive);
@@ -3108,15 +3144,15 @@ function Toast({ title, children, tone = "success", onUndo, onDismiss, className
3108
3144
  }
3109
3145
 
3110
3146
  // src/components/feedback/ToastProvider.tsx
3111
- var React17 = __toESM(require("react"), 1);
3147
+ var React18 = __toESM(require("react"), 1);
3112
3148
  var import_jsx_runtime33 = require("react/jsx-runtime");
3113
3149
  var DEFAULT_TOAST_DURATION_MS = 5e3;
3114
- var ToastContext = React17.createContext(null);
3150
+ var ToastContext = React18.createContext(null);
3115
3151
  function ToastProvider({ children }) {
3116
- const [items, setItems] = React17.useState([]);
3117
- const timers = React17.useRef(/* @__PURE__ */ new Map());
3118
- const nextId = React17.useRef(1);
3119
- const dismiss = React17.useCallback((id) => {
3152
+ const [items, setItems] = React18.useState([]);
3153
+ const timers = React18.useRef(/* @__PURE__ */ new Map());
3154
+ const nextId = React18.useRef(1);
3155
+ const dismiss = React18.useCallback((id) => {
3120
3156
  setItems((current2) => current2.filter((item) => item.id !== id));
3121
3157
  const timer = timers.current.get(id);
3122
3158
  if (timer !== void 0) {
@@ -3124,7 +3160,7 @@ function ToastProvider({ children }) {
3124
3160
  timers.current.delete(id);
3125
3161
  }
3126
3162
  }, []);
3127
- const show = React17.useCallback(
3163
+ const show = React18.useCallback(
3128
3164
  (title, options = {}) => {
3129
3165
  const { tone = "success", duration = DEFAULT_TOAST_DURATION_MS } = options;
3130
3166
  const id = nextId.current++;
@@ -3133,36 +3169,36 @@ function ToastProvider({ children }) {
3133
3169
  },
3134
3170
  [dismiss]
3135
3171
  );
3136
- React17.useEffect(() => {
3172
+ React18.useEffect(() => {
3137
3173
  const pending = timers.current;
3138
3174
  return () => {
3139
3175
  pending.forEach(clearTimeout);
3140
3176
  pending.clear();
3141
3177
  };
3142
3178
  }, []);
3143
- const api = React17.useMemo(() => ({ show }), [show]);
3179
+ const api = React18.useMemo(() => ({ show }), [show]);
3144
3180
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(ToastContext.Provider, { value: api, children: [
3145
3181
  children,
3146
3182
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CornerStackPortal, { slot: "toasts", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "fd-toast-region", "aria-live": "polite", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Toast, { title: item.title, tone: item.tone, onDismiss: () => dismiss(item.id) }, item.id)) }) })
3147
3183
  ] });
3148
3184
  }
3149
3185
  function useToast() {
3150
- const api = React17.useContext(ToastContext);
3186
+ const api = React18.useContext(ToastContext);
3151
3187
  if (!api) throw new Error("useToast must be used inside a <ToastProvider>");
3152
3188
  return api;
3153
3189
  }
3154
3190
 
3155
3191
  // src/components/feedback/Tooltip.tsx
3156
- var React19 = __toESM(require("react"), 1);
3192
+ var React20 = __toESM(require("react"), 1);
3157
3193
 
3158
3194
  // src/components/feedback/useTooltip.tsx
3159
- var React18 = __toESM(require("react"), 1);
3195
+ var React19 = __toESM(require("react"), 1);
3160
3196
  var import_jsx_runtime34 = require("react/jsx-runtime");
3161
3197
  var CLOSE_DELAY_MS = 120;
3162
3198
  var isMouse = (e) => e.pointerType === "mouse";
3163
3199
  function TooltipBubble({ open: open2, labels, placement, className, onHide, onEnter, onLeave }) {
3164
- const anchorRef = React18.useRef(open2.anchor);
3165
- const bubbleRef = React18.useRef(null);
3200
+ const anchorRef = React19.useRef(open2.anchor);
3201
+ const bubbleRef = React19.useRef(null);
3166
3202
  const pos = usePopoverPosition(true, anchorRef, {
3167
3203
  placement: placement === "bottom" ? "bottom-center" : "top-center",
3168
3204
  offset: 8,
@@ -3173,7 +3209,7 @@ function TooltipBubble({ open: open2, labels, placement, className, onHide, onEn
3173
3209
  });
3174
3210
  const layer = useStackedLayer({ active: true, containerRef: bubbleRef, onEscape: onHide, returnFocus: false });
3175
3211
  const zIndex = useLayerZIndex(layer);
3176
- React18.useEffect(() => {
3212
+ React19.useEffect(() => {
3177
3213
  const away = (e) => {
3178
3214
  const t = e.target;
3179
3215
  if (open2.anchor.contains(t)) return;
@@ -3204,16 +3240,16 @@ function TooltipBubble({ open: open2, labels, placement, className, onHide, onEn
3204
3240
  );
3205
3241
  }
3206
3242
  function useTooltip({ placement = "top", className = "" } = {}) {
3207
- const [open2, setOpen] = React18.useState(null);
3208
- const closeTimer = React18.useRef(null);
3209
- const focused = React18.useRef(null);
3210
- const cancelClose = React18.useCallback(() => {
3243
+ const [open2, setOpen] = React19.useState(null);
3244
+ const closeTimer = React19.useRef(null);
3245
+ const focused = React19.useRef(null);
3246
+ const cancelClose = React19.useCallback(() => {
3211
3247
  if (closeTimer.current) {
3212
3248
  clearTimeout(closeTimer.current);
3213
3249
  closeTimer.current = null;
3214
3250
  }
3215
3251
  }, []);
3216
- const hide = React18.useCallback(() => {
3252
+ const hide = React19.useCallback(() => {
3217
3253
  cancelClose();
3218
3254
  focused.current = null;
3219
3255
  setOpen(null);
@@ -3233,7 +3269,7 @@ function useTooltip({ placement = "top", className = "" } = {}) {
3233
3269
  setOpen((o) => o && o.reason === "hover" ? focused.current : o);
3234
3270
  }, CLOSE_DELAY_MS);
3235
3271
  };
3236
- React18.useEffect(() => cancelClose, [cancelClose]);
3272
+ React19.useEffect(() => cancelClose, [cancelClose]);
3237
3273
  const labels = /* @__PURE__ */ new Map();
3238
3274
  const bind = (id, label) => {
3239
3275
  labels.set(id, label);
@@ -3286,17 +3322,17 @@ function useTooltip({ placement = "top", className = "" } = {}) {
3286
3322
  // src/components/feedback/Tooltip.tsx
3287
3323
  var import_jsx_runtime35 = require("react/jsx-runtime");
3288
3324
  function Tooltip({ label, placement = "top", children, className = "" }) {
3289
- const id = React19.useId();
3325
+ const id = React20.useId();
3290
3326
  const descId = id + "-desc";
3291
3327
  const tip = useTooltip({ placement, className });
3292
- const described = React19.isValidElement(children) ? React19.cloneElement(children, {
3328
+ const described = React20.isValidElement(children) ? React20.cloneElement(children, {
3293
3329
  "aria-describedby": [children.props["aria-describedby"], descId].filter(Boolean).join(" ")
3294
3330
  }) : children;
3295
3331
  return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
3296
3332
  "span",
3297
3333
  {
3298
3334
  className: "fd-tooltip-anchor",
3299
- "aria-describedby": React19.isValidElement(children) ? void 0 : descId,
3335
+ "aria-describedby": React20.isValidElement(children) ? void 0 : descId,
3300
3336
  ...tip.bind(id, label),
3301
3337
  children: [
3302
3338
  described,
@@ -3308,16 +3344,16 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
3308
3344
  }
3309
3345
 
3310
3346
  // src/components/data/AnimNum.tsx
3311
- var React20 = __toESM(require("react"), 1);
3347
+ var React21 = __toESM(require("react"), 1);
3312
3348
  var import_jsx_runtime36 = require("react/jsx-runtime");
3313
3349
  function shouldSkipEasing() {
3314
3350
  if (typeof document !== "undefined" && document.hidden) return true;
3315
3351
  return window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false;
3316
3352
  }
3317
3353
  function AnimNum({ value, format, duration = 550 }) {
3318
- const [display, setDisplay] = React20.useState(value);
3319
- const prev = React20.useRef(value);
3320
- React20.useEffect(() => {
3354
+ const [display, setDisplay] = React21.useState(value);
3355
+ const prev = React21.useRef(value);
3356
+ React21.useEffect(() => {
3321
3357
  const from = prev.current;
3322
3358
  const to = value;
3323
3359
  prev.current = to;
@@ -3345,14 +3381,14 @@ function AnimNum({ value, format, duration = 550 }) {
3345
3381
  }
3346
3382
 
3347
3383
  // src/components/data/TrendChart.tsx
3348
- var React23 = __toESM(require("react"), 1);
3384
+ var React24 = __toESM(require("react"), 1);
3349
3385
 
3350
3386
  // src/components/useMeasuredWidth.ts
3351
- var React21 = __toESM(require("react"), 1);
3387
+ var React22 = __toESM(require("react"), 1);
3352
3388
  function useMeasuredWidth(fallback) {
3353
- const [element, setElement] = React21.useState(null);
3354
- const [width, setWidth] = React21.useState(fallback);
3355
- React21.useLayoutEffect(() => {
3389
+ const [element, setElement] = React22.useState(null);
3390
+ const [width, setWidth] = React22.useState(fallback);
3391
+ React22.useLayoutEffect(() => {
3356
3392
  if (!element || typeof ResizeObserver === "undefined") return;
3357
3393
  const measure = () => {
3358
3394
  const measured = Math.round(element.getBoundingClientRect().width);
@@ -3367,7 +3403,7 @@ function useMeasuredWidth(fallback) {
3367
3403
  }
3368
3404
 
3369
3405
  // src/components/data/SegmentedMeter.tsx
3370
- var React22 = __toESM(require("react"), 1);
3406
+ var React23 = __toESM(require("react"), 1);
3371
3407
 
3372
3408
  // src/kits/files.ts
3373
3409
  function formatBytes(n) {
@@ -3572,7 +3608,7 @@ function SegmentedMeter({
3572
3608
  const pct = safeTotal ? Math.min(100, Math.round(used / safeTotal * 100)) : 0;
3573
3609
  const w = (v) => safeTotal ? Math.max(0, Math.min(100, Number(v) / safeTotal * 100)) : 0;
3574
3610
  const fill = (s, i) => s.color || (s.variant ? VARIANT_FILL[s.variant] : void 0) || CHART[i % CHART.length];
3575
- const generatedId = React22.useId();
3611
+ const generatedId = React23.useId();
3576
3612
  const uid2 = id || generatedId;
3577
3613
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: ["fd-segmeter", className].filter(Boolean).join(" "), onClick, children: [
3578
3614
  label || showTotal ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "fd-segmeter-head", children: [
@@ -3723,8 +3759,8 @@ function TrendChart({
3723
3759
  onRetry,
3724
3760
  className = ""
3725
3761
  }) {
3726
- const [activeId, setActiveId] = React23.useState(null);
3727
- const [pointTip, setPointTip] = React23.useState(null);
3762
+ const [activeId, setActiveId] = React24.useState(null);
3763
+ const [pointTip, setPointTip] = React24.useState(null);
3728
3764
  const isEmpty = state === "ready" && (!categories.length || !series.length || series.every((s) => !s.values.length));
3729
3765
  const effectiveState = isEmpty ? "empty" : state;
3730
3766
  const [plotRef, VBW] = useMeasuredWidth(INITIAL_WIDTH);
@@ -3838,7 +3874,7 @@ function TrendChart({
3838
3874
  }
3839
3875
 
3840
3876
  // src/components/data/DonutChart.tsx
3841
- var React24 = __toESM(require("react"), 1);
3877
+ var React25 = __toESM(require("react"), 1);
3842
3878
  var import_jsx_runtime40 = require("react/jsx-runtime");
3843
3879
  function DonutChart({
3844
3880
  segments,
@@ -3853,7 +3889,7 @@ function DonutChart({
3853
3889
  onRetry,
3854
3890
  className = ""
3855
3891
  }) {
3856
- const [activeId, setActiveId] = React24.useState(null);
3892
+ const [activeId, setActiveId] = React25.useState(null);
3857
3893
  const items = segments.filter((s) => Number(s.value) > 0);
3858
3894
  const total = items.reduce((n, s) => n + Number(s.value), 0);
3859
3895
  const isEmpty = state === "ready" && (!items.length || total <= 0);
@@ -3945,7 +3981,7 @@ function DonutChart({
3945
3981
  }
3946
3982
 
3947
3983
  // src/components/data/BarList.tsx
3948
- var React25 = __toESM(require("react"), 1);
3984
+ var React26 = __toESM(require("react"), 1);
3949
3985
  var import_jsx_runtime41 = require("react/jsx-runtime");
3950
3986
  var wholePercent = (share) => formatPercent(Math.round(share * 100));
3951
3987
  function BarList({
@@ -3962,7 +3998,7 @@ function BarList({
3962
3998
  onRetry,
3963
3999
  className = ""
3964
4000
  }) {
3965
- const ordered = React25.useMemo(() => {
4001
+ const ordered = React26.useMemo(() => {
3966
4002
  const list = sort ? [...rows].sort((a, b) => Number(b.value) - Number(a.value)) : rows;
3967
4003
  return maxRows ? list.slice(0, maxRows) : list;
3968
4004
  }, [rows, sort, maxRows]);
@@ -4104,7 +4140,7 @@ function FunnelChart({
4104
4140
  }
4105
4141
 
4106
4142
  // src/components/data/Clamp.tsx
4107
- var React26 = __toESM(require("react"), 1);
4143
+ var React27 = __toESM(require("react"), 1);
4108
4144
  var import_jsx_runtime43 = require("react/jsx-runtime");
4109
4145
  function Clamp({
4110
4146
  children,
@@ -4116,16 +4152,16 @@ function Clamp({
4116
4152
  onToggle,
4117
4153
  className = ""
4118
4154
  }) {
4119
- const [open2, setOpen] = React26.useState(false);
4120
- const [overflows, setOverflows] = React26.useState(false);
4121
- const bodyRef = React26.useRef(null);
4122
- const charClamped = React26.useMemo(() => {
4155
+ const [open2, setOpen] = React27.useState(false);
4156
+ const [overflows, setOverflows] = React27.useState(false);
4157
+ const bodyRef = React27.useRef(null);
4158
+ const charClamped = React27.useMemo(() => {
4123
4159
  if (open2 || !maxChars || typeof text !== "string" || text.length <= maxChars) return null;
4124
4160
  const cut = text.slice(0, maxChars);
4125
4161
  const at = cut.lastIndexOf(" ");
4126
4162
  return (at > maxChars * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
4127
4163
  }, [text, maxChars, open2]);
4128
- React26.useLayoutEffect(() => {
4164
+ React27.useLayoutEffect(() => {
4129
4165
  const node = bodyRef.current;
4130
4166
  if (maxChars || !node || !maxHeight) return;
4131
4167
  const measure = () => {
@@ -4383,16 +4419,16 @@ function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort
4383
4419
  }
4384
4420
 
4385
4421
  // src/components/data/FilterBar.tsx
4386
- var React32 = __toESM(require("react"), 1);
4422
+ var React33 = __toESM(require("react"), 1);
4387
4423
 
4388
4424
  // src/components/forms/NumberInput.tsx
4389
- var React29 = __toESM(require("react"), 1);
4425
+ var React30 = __toESM(require("react"), 1);
4390
4426
 
4391
4427
  // src/components/forms/field.tsx
4392
- var React27 = __toESM(require("react"), 1);
4428
+ var React28 = __toESM(require("react"), 1);
4393
4429
  var import_jsx_runtime46 = require("react/jsx-runtime");
4394
4430
  function useFieldId(id) {
4395
- const generated = React27.useId();
4431
+ const generated = React28.useId();
4396
4432
  return id || generated;
4397
4433
  }
4398
4434
  function FieldLabel({ htmlFor, id, required = false, onClick, children }) {
@@ -4411,10 +4447,10 @@ function HiddenFieldLabel({ id, children }) {
4411
4447
  }
4412
4448
 
4413
4449
  // src/components/useLatest.ts
4414
- var React28 = __toESM(require("react"), 1);
4450
+ var React29 = __toESM(require("react"), 1);
4415
4451
  function useLatest(value) {
4416
- const ref = React28.useRef(value);
4417
- React28.useInsertionEffect(() => {
4452
+ const ref = React29.useRef(value);
4453
+ React29.useInsertionEffect(() => {
4418
4454
  ref.current = value;
4419
4455
  });
4420
4456
  return ref;
@@ -4497,20 +4533,20 @@ function NumberInput({
4497
4533
  const n = typeof v === "number" ? v : parseNumberText(v);
4498
4534
  return n == null || Number.isNaN(n) ? null : n;
4499
4535
  };
4500
- const [text, setText] = React29.useState(() => toText(value));
4501
- const [editing, setEditing] = React29.useState(false);
4536
+ const [text, setText] = React30.useState(() => toText(value));
4537
+ const [editing, setEditing] = React30.useState(false);
4502
4538
  const parsed = parseNumberText(text);
4503
4539
  const invalidMessage = parsed == null ? null : Number.isNaN(parsed) ? "Enter a number" : integer && !Number.isInteger(parsed) ? "Enter a whole number" : parsed < lo ? "Must be \u2265 " + lo : parsed > hi ? "Must be \u2264 " + hi : null;
4504
4540
  const valid = invalidMessage == null;
4505
- const committedRef = React29.useRef(toNumber(value));
4541
+ const committedRef = React30.useRef(toNumber(value));
4506
4542
  const onChangeRef = useLatest(onChange);
4507
4543
  const onValidityChangeRef = useLatest(onValidityChange);
4508
- const focusedRef = React29.useRef(false);
4509
- React29.useEffect(() => {
4544
+ const focusedRef = React30.useRef(false);
4545
+ React30.useEffect(() => {
4510
4546
  committedRef.current = toNumber(value);
4511
4547
  if (!focusedRef.current) setText(toText(value));
4512
4548
  }, [value]);
4513
- React29.useLayoutEffect(() => {
4549
+ React30.useLayoutEffect(() => {
4514
4550
  onValidityChangeRef.current?.(valid);
4515
4551
  }, [valid, onValidityChangeRef]);
4516
4552
  const fire = (n) => {
@@ -4526,7 +4562,7 @@ function NumberInput({
4526
4562
  return true;
4527
4563
  };
4528
4564
  const bumpRef = useLatest(bump);
4529
- const holdTimer = React29.useRef(null);
4565
+ const holdTimer = React30.useRef(null);
4530
4566
  const release2 = () => {
4531
4567
  if (holdTimer.current) clearTimeout(holdTimer.current);
4532
4568
  holdTimer.current = null;
@@ -4545,7 +4581,7 @@ function NumberInput({
4545
4581
  };
4546
4582
  holdTimer.current = setTimeout(tick, HOLD_DELAY_MS);
4547
4583
  };
4548
- React29.useEffect(() => () => {
4584
+ React30.useEffect(() => () => {
4549
4585
  if (holdTimer.current) clearTimeout(holdTimer.current);
4550
4586
  }, []);
4551
4587
  const current2 = committedRef.current;
@@ -4648,7 +4684,7 @@ function NumberInput({
4648
4684
  }
4649
4685
 
4650
4686
  // src/components/forms/DatePicker.tsx
4651
- var React30 = __toESM(require("react"), 1);
4687
+ var React31 = __toESM(require("react"), 1);
4652
4688
  var import_jsx_runtime48 = require("react/jsx-runtime");
4653
4689
  var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
4654
4690
  var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
@@ -4681,10 +4717,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
4681
4717
  const today = /* @__PURE__ */ new Date();
4682
4718
  const sel = range ? value || {} : { start: value, end: value };
4683
4719
  const anchor = parse(sel.start) || parse(initialMonth) || today;
4684
- const [vy, setVy] = React30.useState(anchor.getFullYear());
4685
- const [vm, setVm] = React30.useState(anchor.getMonth());
4686
- const [mode2, setMode] = React30.useState("days");
4687
- const [hover, setHover] = React30.useState(null);
4720
+ const [vy, setVy] = React31.useState(anchor.getFullYear());
4721
+ const [vm, setVm] = React31.useState(anchor.getMonth());
4722
+ const [mode2, setMode] = React31.useState("days");
4723
+ const [hover, setHover] = React31.useState(null);
4688
4724
  const s = parse(sel.start), e = parse(sel.end);
4689
4725
  const hoverEnd = range && s && !e && hover ? parse(hover) : null;
4690
4726
  const inRange = (d) => {
@@ -4695,12 +4731,12 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
4695
4731
  const isEnd = (d) => !!e && iso(d) === iso(e);
4696
4732
  const isEdge = (d) => isStart(d) || isEnd(d);
4697
4733
  const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
4698
- const [activeDate, setActiveDate] = React30.useState(() => {
4734
+ const [activeDate, setActiveDate] = React31.useState(() => {
4699
4735
  if (s) return s;
4700
4736
  if (sameMonth(today, anchor.getFullYear(), anchor.getMonth())) return today;
4701
4737
  return new Date(anchor.getFullYear(), anchor.getMonth(), 1);
4702
4738
  });
4703
- const calRef = React30.useRef(null);
4739
+ const calRef = React31.useRef(null);
4704
4740
  const pageToShow = (y, m) => {
4705
4741
  const idx = y * 12 + m, firstIdx = vy * 12 + vm, secondIdx = firstIdx + 1;
4706
4742
  if (idx === firstIdx || months > 1 && idx === secondIdx) return;
@@ -4717,7 +4753,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
4717
4753
  setActiveDate(next);
4718
4754
  pageToShow(next.getFullYear(), next.getMonth());
4719
4755
  };
4720
- React30.useEffect(() => {
4756
+ React31.useEffect(() => {
4721
4757
  const el = calRef.current?.querySelector('[data-iso="' + iso(activeDate) + '"]');
4722
4758
  if (el) el.focus({ preventScroll: true });
4723
4759
  }, [activeDate, vy, vm]);
@@ -4910,9 +4946,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
4910
4946
  }
4911
4947
  function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, "aria-label": hiddenLabel, ...rest }) {
4912
4948
  const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id, hiddenLabel);
4913
- const [open2, setOpen] = React30.useState(false);
4914
- const rootRef = React30.useRef(null);
4915
- const boxRef = React30.useRef(null);
4949
+ const [open2, setOpen] = React31.useState(false);
4950
+ const rootRef = React31.useRef(null);
4951
+ const boxRef = React31.useRef(null);
4916
4952
  const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
4917
4953
  const toggle = () => {
4918
4954
  if (!disabled) setOpen(!open2);
@@ -5001,9 +5037,9 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
5001
5037
  }
5002
5038
 
5003
5039
  // src/components/forms/listbox.ts
5004
- var React31 = __toESM(require("react"), 1);
5040
+ var React32 = __toESM(require("react"), 1);
5005
5041
  function useListboxNav({ count, onSelect }) {
5006
- const [active, setActive] = React31.useState(-1);
5042
+ const [active, setActive] = React32.useState(-1);
5007
5043
  return {
5008
5044
  active,
5009
5045
  setActive,
@@ -5016,7 +5052,7 @@ function useListboxNav({ count, onSelect }) {
5016
5052
  };
5017
5053
  }
5018
5054
  function useListboxScrollIntoView(active, listRef, enabled) {
5019
- React31.useEffect(() => {
5055
+ React32.useEffect(() => {
5020
5056
  if (!enabled || active < 0 || !listRef.current) return;
5021
5057
  const list = listRef.current;
5022
5058
  const el = list.querySelector('[data-i="' + active + '"]');
@@ -5034,7 +5070,7 @@ var import_jsx_runtime50 = require("react/jsx-runtime");
5034
5070
  var TAIL_CHARS = 12;
5035
5071
  var graphemes = new Intl.Segmenter(void 0, { granularity: "grapheme" });
5036
5072
  function splitForMiddleEllipsis(text) {
5037
- const chars = Array.from(graphemes.segment(text), (part) => part.segment);
5073
+ const chars = Array.from(graphemes.segment(text), (part2) => part2.segment);
5038
5074
  if (chars.length <= TAIL_CHARS) return { head: text, tail: "" };
5039
5075
  return { head: chars.slice(0, -TAIL_CHARS).join(""), tail: chars.slice(-TAIL_CHARS).join("") };
5040
5076
  }
@@ -5237,13 +5273,13 @@ function MultiSelectPanel({
5237
5273
  onClose
5238
5274
  }) {
5239
5275
  const allowedOps = operatorsFor(field);
5240
- const [draftOperator, setDraftOperator] = React32.useState(value?.operator ?? allowedOps[0]);
5276
+ const [draftOperator, setDraftOperator] = React33.useState(value?.operator ?? allowedOps[0]);
5241
5277
  const operator = allowedOps.length === 1 ? allowedOps[0] : value?.operator ?? draftOperator;
5242
5278
  const selected = value?.values ?? [];
5243
5279
  const selectedRef = useLatest(selected);
5244
5280
  const operatorRef = useLatest(operator);
5245
- const mountedRef = React32.useRef(true);
5246
- React32.useEffect(() => {
5281
+ const mountedRef = React33.useRef(true);
5282
+ React33.useEffect(() => {
5247
5283
  mountedRef.current = true;
5248
5284
  return () => {
5249
5285
  mountedRef.current = false;
@@ -5257,20 +5293,20 @@ function MultiSelectPanel({
5257
5293
  if (selectedRef.current.length > 0) commit(selectedRef.current, op);
5258
5294
  else setDraftOperator(op);
5259
5295
  };
5260
- const [mode2, setMode] = React32.useState("search");
5261
- const [query, setQuery] = React32.useState("");
5262
- const [asyncState, setAsyncState] = React32.useState(
5296
+ const [mode2, setMode] = React33.useState("search");
5297
+ const [query, setQuery] = React33.useState("");
5298
+ const [asyncState, setAsyncState] = React33.useState(
5263
5299
  { options: null, loading: !!field.loadOptions, error: false }
5264
5300
  );
5265
- const [retryTick, setRetryTick] = React32.useState(0);
5266
- const inputRef = React32.useRef(null);
5267
- const listRef = React32.useRef(null);
5268
- const listId = React32.useId();
5301
+ const [retryTick, setRetryTick] = React33.useState(0);
5302
+ const inputRef = React33.useRef(null);
5303
+ const listRef = React33.useRef(null);
5304
+ const listId = React33.useId();
5269
5305
  const loadOptionsRef = useLatest(field.loadOptions);
5270
- React32.useEffect(() => {
5306
+ React33.useEffect(() => {
5271
5307
  inputRef.current?.focus();
5272
5308
  }, []);
5273
- React32.useEffect(() => {
5309
+ React33.useEffect(() => {
5274
5310
  const load = loadOptionsRef.current;
5275
5311
  if (!load) return;
5276
5312
  const controller = new AbortController();
@@ -5303,17 +5339,17 @@ function MultiSelectPanel({
5303
5339
  };
5304
5340
  const nav = useListboxNav({ count: options.length, onSelect: (i) => toggle(options[i]) });
5305
5341
  useListboxScrollIntoView(nav.active, listRef, hasListbox);
5306
- React32.useEffect(() => {
5342
+ React33.useEffect(() => {
5307
5343
  nav.setActive(0);
5308
5344
  }, [query, options.length]);
5309
5345
  const activeId = hasListbox && options[nav.active] ? listId + "-opt-" + nav.active : void 0;
5310
5346
  const liveMessage = showLoading ? "Loading\u2026" : showError ? "Couldn't load options." : options.length === 0 ? query === "" && field.emptyText || "No matches" : atLimit ? "Limit reached: at most " + field.maxValues + " values" : "";
5311
- const [pasteText, setPasteText] = React32.useState("");
5312
- const [pasteLoading, setPasteLoading] = React32.useState(false);
5313
- const [unmatchedTokens, setUnmatchedTokens] = React32.useState([]);
5314
- const [pasteError, setPasteError] = React32.useState(null);
5315
- const pasteWrapRef = React32.useRef(null);
5316
- React32.useEffect(() => {
5347
+ const [pasteText, setPasteText] = React33.useState("");
5348
+ const [pasteLoading, setPasteLoading] = React33.useState(false);
5349
+ const [unmatchedTokens, setUnmatchedTokens] = React33.useState([]);
5350
+ const [pasteError, setPasteError] = React33.useState(null);
5351
+ const pasteWrapRef = React33.useRef(null);
5352
+ React33.useEffect(() => {
5317
5353
  if (mode2 === "paste") pasteWrapRef.current?.querySelector("textarea")?.focus();
5318
5354
  }, [mode2]);
5319
5355
  const doResolve = () => {
@@ -5486,8 +5522,8 @@ function MultiSelectPanel({
5486
5522
  );
5487
5523
  }
5488
5524
  function useTextValidity(onFlip) {
5489
- const invalidRef = React32.useRef(/* @__PURE__ */ new Set());
5490
- const [, rerender] = React32.useReducer((n) => n + 1, 0);
5525
+ const invalidRef = React33.useRef(/* @__PURE__ */ new Set());
5526
+ const [, rerender] = React33.useReducer((n) => n + 1, 0);
5491
5527
  const onFlipRef = useLatest(onFlip);
5492
5528
  const record = (name, valid) => {
5493
5529
  const invalid = invalidRef.current;
@@ -5530,15 +5566,15 @@ function sameValue(a, b) {
5530
5566
  return true;
5531
5567
  }
5532
5568
  function useReseedFromProps(value, applies, reseed) {
5533
- const seen = React32.useRef(value);
5534
- React32.useLayoutEffect(() => {
5569
+ const seen = React33.useRef(value);
5570
+ React33.useLayoutEffect(() => {
5535
5571
  if (seen.current === value) return;
5536
5572
  seen.current = value;
5537
5573
  if (!sameValue(value, applies())) reseed(value);
5538
5574
  }, [value, applies, reseed]);
5539
5575
  }
5540
5576
  function usePreserveFocusAcrossRemount(seed, fields) {
5541
- const pendingName = React32.useRef(null);
5577
+ const pendingName = React33.useRef(null);
5542
5578
  const fieldsRef = useLatest(fields);
5543
5579
  const capture = () => {
5544
5580
  const active = document.activeElement;
@@ -5551,7 +5587,7 @@ function usePreserveFocusAcrossRemount(seed, fields) {
5551
5587
  }
5552
5588
  }
5553
5589
  };
5554
- React32.useLayoutEffect(() => {
5590
+ React33.useLayoutEffect(() => {
5555
5591
  const name = pendingName.current;
5556
5592
  if (!name) return;
5557
5593
  pendingName.current = null;
@@ -5567,14 +5603,14 @@ function RangePanel({
5567
5603
  onCommit,
5568
5604
  onClose
5569
5605
  }) {
5570
- const [draft, setDraft] = React32.useState(() => rangeDraft(value));
5571
- const [seed, setSeed] = React32.useState(0);
5572
- const minId = React32.useId();
5573
- const maxId = React32.useId();
5574
- const minWrapRef = React32.useRef(null);
5575
- const maxWrapRef = React32.useRef(null);
5606
+ const [draft, setDraft] = React33.useState(() => rangeDraft(value));
5607
+ const [seed, setSeed] = React33.useState(0);
5608
+ const minId = React33.useId();
5609
+ const maxId = React33.useId();
5610
+ const minWrapRef = React33.useRef(null);
5611
+ const maxWrapRef = React33.useRef(null);
5576
5612
  const preserveFocus = usePreserveFocusAcrossRemount(seed, { min: minWrapRef, max: maxWrapRef });
5577
- const draftRef = React32.useRef(draft);
5613
+ const draftRef = React33.useRef(draft);
5578
5614
  const shown = () => {
5579
5615
  const { min, max } = draftRef.current;
5580
5616
  return applicable(field, min == null && max == null ? void 0 : { min, max }, validity.allValid());
@@ -5666,15 +5702,15 @@ function DatePanel({
5666
5702
  onClose
5667
5703
  }) {
5668
5704
  const maxDays = effectiveMaxDays(field);
5669
- const [initial] = React32.useState(() => dateDraft(field, value));
5670
- const [kind, setKind] = React32.useState(initial.kind);
5671
- const [daysDraft, setDaysDraft] = React32.useState(initial.days);
5672
- const daysRef = React32.useRef(daysDraft);
5673
- const daysConfirmed = React32.useRef(value?.kind === "withinDays");
5674
- const [between, setBetween] = React32.useState(initial.between);
5675
- const [seed, setSeed] = React32.useState(0);
5676
- const daysId = React32.useId();
5677
- const daysWrapRef = React32.useRef(null);
5705
+ const [initial] = React33.useState(() => dateDraft(field, value));
5706
+ const [kind, setKind] = React33.useState(initial.kind);
5707
+ const [daysDraft, setDaysDraft] = React33.useState(initial.days);
5708
+ const daysRef = React33.useRef(daysDraft);
5709
+ const daysConfirmed = React33.useRef(value?.kind === "withinDays");
5710
+ const [between, setBetween] = React33.useState(initial.between);
5711
+ const [seed, setSeed] = React33.useState(0);
5712
+ const daysId = React33.useId();
5713
+ const daysWrapRef = React33.useRef(null);
5678
5714
  const preserveFocus = usePreserveFocusAcrossRemount(seed, { days: daysWrapRef });
5679
5715
  const shownWithinDays = () => {
5680
5716
  const days = daysRef.current;
@@ -5792,11 +5828,11 @@ function FilterButton({ children, ...rest }) {
5792
5828
  ] });
5793
5829
  }
5794
5830
  function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align = "left", actions, onClearAll, showActiveCount = false, loading = false, loadingLabel = "Loading the filters", className = "", ...rest }) {
5795
- const [panel, setPanel] = React32.useState(null);
5796
- const editAnchorRef = React32.useRef(null);
5797
- const addAnchorRef = React32.useRef(null);
5798
- const textInputRef = React32.useRef(null);
5799
- const optionsRef = React32.useRef(null);
5831
+ const [panel, setPanel] = React33.useState(null);
5832
+ const editAnchorRef = React33.useRef(null);
5833
+ const addAnchorRef = React33.useRef(null);
5834
+ const textInputRef = React33.useRef(null);
5835
+ const optionsRef = React33.useRef(null);
5800
5836
  if (process.env.NODE_ENV !== "production") {
5801
5837
  for (const f of fields) assertValidFieldDefinition(f);
5802
5838
  }
@@ -5819,7 +5855,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
5819
5855
  const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
5820
5856
  const startEditing = (key) => setPanel({ kind: "edit", key });
5821
5857
  const closeEditing = () => setPanel(null);
5822
- React32.useEffect(() => {
5858
+ React33.useEffect(() => {
5823
5859
  if (!panel || panel.kind !== "edit") return;
5824
5860
  if (editingField?.type === "text") {
5825
5861
  textInputRef.current?.focus();
@@ -6074,10 +6110,10 @@ function StatTile(props) {
6074
6110
  }
6075
6111
 
6076
6112
  // src/components/data/CodeBlock.tsx
6077
- var React34 = __toESM(require("react"), 1);
6113
+ var React35 = __toESM(require("react"), 1);
6078
6114
 
6079
6115
  // src/kits/clipboard.ts
6080
- var React33 = __toESM(require("react"), 1);
6116
+ var React34 = __toESM(require("react"), 1);
6081
6117
  var COPIED_FEEDBACK_MS = 1600;
6082
6118
  function copyThroughSelection(text) {
6083
6119
  const previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
@@ -6107,17 +6143,17 @@ async function copyToClipboard(text) {
6107
6143
  return copyThroughSelection(text);
6108
6144
  }
6109
6145
  function useCopyToClipboard() {
6110
- const [copied, setCopied] = React33.useState(false);
6111
- const timer = React33.useRef(null);
6112
- const mounted = React33.useRef(true);
6113
- React33.useEffect(() => {
6146
+ const [copied, setCopied] = React34.useState(false);
6147
+ const timer = React34.useRef(null);
6148
+ const mounted = React34.useRef(true);
6149
+ React34.useEffect(() => {
6114
6150
  mounted.current = true;
6115
6151
  return () => {
6116
6152
  mounted.current = false;
6117
6153
  if (timer.current) clearTimeout(timer.current);
6118
6154
  };
6119
6155
  }, []);
6120
- const copy = React33.useCallback(async (text) => {
6156
+ const copy = React34.useCallback(async (text) => {
6121
6157
  const ok = await copyToClipboard(text);
6122
6158
  if (ok && mounted.current) {
6123
6159
  setCopied(true);
@@ -6285,7 +6321,7 @@ function tokenize(src, lang) {
6285
6321
  return out;
6286
6322
  }
6287
6323
  function Highlighted({ code, lang }) {
6288
- const toks = React34.useMemo(() => tokenize(code, lang), [code, lang]);
6324
+ const toks = React35.useMemo(() => tokenize(code, lang), [code, lang]);
6289
6325
  return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_jsx_runtime54.Fragment, { children: toks.map((tk, i) => tk.c ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "tok-" + tk.c, children: tk.t }, i) : tk.t) });
6290
6326
  }
6291
6327
  function CodeBlock({
@@ -6299,8 +6335,8 @@ function CodeBlock({
6299
6335
  actions,
6300
6336
  className = ""
6301
6337
  }) {
6302
- const [wrap, setWrap] = React34.useState(!!wrapDefault);
6303
- const [open2, setOpen] = React34.useState(false);
6338
+ const [wrap, setWrap] = React35.useState(!!wrapDefault);
6339
+ const [open2, setOpen] = React35.useState(false);
6304
6340
  const [copied, copy] = useCopyToClipboard();
6305
6341
  const body = String(code).replace(/\n$/, "");
6306
6342
  const lines = body.split("\n");
@@ -6329,7 +6365,7 @@ function CodeBlock({
6329
6365
  ] });
6330
6366
  }
6331
6367
  function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
6332
- const [open2, setOpen] = React34.useState(false);
6368
+ const [open2, setOpen] = React35.useState(false);
6333
6369
  const [copied, copy] = useCopyToClipboard();
6334
6370
  const raw = String(diff).replace(/\n$/, "");
6335
6371
  const all = raw.split("\n").map((line) => {
@@ -6375,7 +6411,7 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
6375
6411
  }
6376
6412
 
6377
6413
  // src/components/data/Markdown.tsx
6378
- var React35 = __toESM(require("react"), 1);
6414
+ var React36 = __toESM(require("react"), 1);
6379
6415
 
6380
6416
  // src/components/data/markdownEscape.ts
6381
6417
  var ESCAPABLE = /\\([!-/:-@[-`{-~])/g;
@@ -6448,7 +6484,7 @@ function hiddenInlineNodes(hidden, ctx, keyBase) {
6448
6484
  const href = safeHref(d(g(2)));
6449
6485
  out.push(href ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("a", { href, title: g(3) ? d(g(3)) : void 0, target: /^https?:/i.test(href) ? "_blank" : void 0, rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: hiddenInlineNodes(g(1), ctx, key()) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { children: d(g(1)) }, key()));
6450
6486
  } else if (kind === "cite") {
6451
- out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(React35.Fragment, { children: ctx.renderCitation(d(g(1))) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("sup", { className: "fd-md-cite", children: d(g(1)) }, key()));
6487
+ out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(React36.Fragment, { children: ctx.renderCitation(d(g(1))) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("sup", { className: "fd-md-cite", children: d(g(1)) }, key()));
6452
6488
  } else if (kind === "strongem") out.push(/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("strong", { children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("em", { children: hiddenInlineNodes(g(1), ctx, key()) }) }, key()));
6453
6489
  else if (kind === "strong") out.push(/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("strong", { children: hiddenInlineNodes(g(1) || g(2), ctx, key()) }, key()));
6454
6490
  else if (kind === "em") out.push(/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("em", { children: hiddenInlineNodes(g(1) || g(2), ctx, key()) }, key()));
@@ -6635,7 +6671,7 @@ function Markdown({
6635
6671
  tone = "default"
6636
6672
  }) {
6637
6673
  const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
6638
- const blocks = React35.useMemo(() => parseBlocks(source), [source]);
6674
+ const blocks = React36.useMemo(() => parseBlocks(source), [source]);
6639
6675
  return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: mdClass("fd-md", size, tone, className), children: renderBlocks(blocks, ctx, "b") });
6640
6676
  }
6641
6677
  function MarkdownInline({ source = "", className = "", onLinkClick, size, tone }) {
@@ -6746,7 +6782,7 @@ function Pagination({
6746
6782
  }
6747
6783
 
6748
6784
  // src/components/data/RelativeTime.tsx
6749
- var React36 = __toESM(require("react"), 1);
6785
+ var React37 = __toESM(require("react"), 1);
6750
6786
  var import_jsx_runtime58 = require("react/jsx-runtime");
6751
6787
  var MIN = 6e4;
6752
6788
  var HOUR = 36e5;
@@ -6798,9 +6834,9 @@ function formatDuration(ms) {
6798
6834
  return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
6799
6835
  }
6800
6836
  function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
6801
- const [, force] = React36.useState(0);
6837
+ const [, force] = React37.useState(0);
6802
6838
  const t = value instanceof Date ? value.getTime() : Date.parse(value);
6803
- React36.useEffect(() => {
6839
+ React37.useEffect(() => {
6804
6840
  if (!refresh2 || !t || isNaN(t)) return;
6805
6841
  const abs2 = Math.abs(t - Date.now());
6806
6842
  if (abs2 > DAY) return;
@@ -6816,7 +6852,7 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
6816
6852
  }
6817
6853
 
6818
6854
  // src/components/data/ScoreMeter.tsx
6819
- var React37 = __toESM(require("react"), 1);
6855
+ var React38 = __toESM(require("react"), 1);
6820
6856
  var import_jsx_runtime59 = require("react/jsx-runtime");
6821
6857
  function ScoreMeter({
6822
6858
  score,
@@ -6831,10 +6867,10 @@ function ScoreMeter({
6831
6867
  breakdownWidth = 280,
6832
6868
  className = ""
6833
6869
  }) {
6834
- const [open2, setOpen] = React37.useState(false);
6835
- const ref = React37.useRef(null);
6870
+ const [open2, setOpen] = React38.useState(false);
6871
+ const ref = React38.useRef(null);
6836
6872
  const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
6837
- const body = /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React37.Fragment, { children: [
6873
+ const body = /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React38.Fragment, { children: [
6838
6874
  /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-scoremeter-rail", style: { width }, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(SegmentedMeter, { total: 100, segments, height, showTotal: false, showPercent: false, legend: false }) }),
6839
6875
  showScore ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
6840
6876
  ] });
@@ -6853,7 +6889,7 @@ function ScoreMeter({
6853
6889
  }
6854
6890
  );
6855
6891
  }
6856
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React37.Fragment, { children: [
6892
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React38.Fragment, { children: [
6857
6893
  /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
6858
6894
  "button",
6859
6895
  {
@@ -6884,11 +6920,11 @@ function ScoreMeter({
6884
6920
  }
6885
6921
 
6886
6922
  // src/components/actions/inlinePanel.tsx
6887
- var React38 = __toESM(require("react"), 1);
6923
+ var React39 = __toESM(require("react"), 1);
6888
6924
  var import_jsx_runtime60 = require("react/jsx-runtime");
6889
6925
  function useInlinePanel() {
6890
- const [open2, setOpen] = React38.useState(false);
6891
- const ref = React38.useRef(null);
6926
+ const [open2, setOpen] = React39.useState(false);
6927
+ const ref = React39.useRef(null);
6892
6928
  return { open: open2, setOpen, ref };
6893
6929
  }
6894
6930
  function InlinePanelSurface({ panel, align = "right", ...popover }) {
@@ -7059,7 +7095,7 @@ function SortMenu({
7059
7095
  }
7060
7096
 
7061
7097
  // src/components/data/StepList.tsx
7062
- var React39 = __toESM(require("react"), 1);
7098
+ var React40 = __toESM(require("react"), 1);
7063
7099
  var import_jsx_runtime62 = require("react/jsx-runtime");
7064
7100
  var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
7065
7101
  function StepList({
@@ -7073,9 +7109,9 @@ function StepList({
7073
7109
  className = "",
7074
7110
  active = false
7075
7111
  }) {
7076
- const [openState, setOpenState] = React39.useState(defaultOpen);
7112
+ const [openState, setOpenState] = React40.useState(defaultOpen);
7077
7113
  const open2 = openProp == null ? openState : openProp;
7078
- const [expanded, setExpanded] = React39.useState({});
7114
+ const [expanded, setExpanded] = React40.useState({});
7079
7115
  if (!steps.length) return null;
7080
7116
  const running = steps.some((s) => s.status === "running");
7081
7117
  const failed = steps.filter((s) => s.status === "error").length;
@@ -7133,7 +7169,7 @@ function StepList({
7133
7169
  }
7134
7170
 
7135
7171
  // src/components/data/VirtualList.tsx
7136
- var React40 = __toESM(require("react"), 1);
7172
+ var React41 = __toESM(require("react"), 1);
7137
7173
  var import_jsx_runtime63 = require("react/jsx-runtime");
7138
7174
  var VIRTUAL_LIST_BUFFER_ROWS = 20;
7139
7175
  var VIRTUAL_LIST_ROW_GAP = 6;
@@ -7185,35 +7221,35 @@ function VirtualList({
7185
7221
  className = "",
7186
7222
  style
7187
7223
  }) {
7188
- const [scrollTop, setScrollTop] = React40.useState(0);
7189
- const loaded = React40.useMemo(
7224
+ const [scrollTop, setScrollTop] = React41.useState(0);
7225
+ const loaded = React41.useMemo(
7190
7226
  () => ({ firstItemIndex, count: items.length }),
7191
7227
  [firstItemIndex, items.length]
7192
7228
  );
7193
7229
  const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
7194
7230
  const bandKey = firstItemIndex + ":" + items.length;
7195
- const win = React40.useMemo(
7231
+ const win = React41.useMemo(
7196
7232
  () => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
7197
7233
  [scrollTop, height, itemHeight, total, loaded]
7198
7234
  );
7199
- const need = React40.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
7235
+ const need = React41.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
7200
7236
  const wantStart = need.start && hasMore?.start !== false;
7201
7237
  const wantEnd = need.end && hasMore?.end !== false;
7202
7238
  const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
7203
7239
  const askKey = bandKey + "@" + bucket2;
7204
- const asked = React40.useRef({ start: null, end: null });
7205
- React40.useEffect(() => {
7240
+ const asked = React41.useRef({ start: null, end: null });
7241
+ React41.useEffect(() => {
7206
7242
  if (loading || !wantStart || asked.current.start === askKey) return;
7207
7243
  asked.current.start = askKey;
7208
7244
  onNeedMore("start", win);
7209
7245
  }, [wantStart, loading, askKey, onNeedMore, win]);
7210
- React40.useEffect(() => {
7246
+ React41.useEffect(() => {
7211
7247
  if (loading || !wantEnd || asked.current.end === askKey) return;
7212
7248
  asked.current.end = askKey;
7213
7249
  onNeedMore("end", win);
7214
7250
  }, [wantEnd, loading, askKey, onNeedMore, win]);
7215
- const lastKeysRef = React40.useRef(null);
7216
- const newKeys = React40.useMemo(() => {
7251
+ const lastKeysRef = React41.useRef(null);
7252
+ const newKeys = React41.useMemo(() => {
7217
7253
  const prev = lastKeysRef.current;
7218
7254
  if (!prev) return /* @__PURE__ */ new Set();
7219
7255
  const fresh = /* @__PURE__ */ new Set();
@@ -7223,7 +7259,7 @@ function VirtualList({
7223
7259
  }
7224
7260
  return fresh;
7225
7261
  }, [items]);
7226
- React40.useEffect(() => {
7262
+ React41.useEffect(() => {
7227
7263
  lastKeysRef.current = new Set(items.map(keyOf));
7228
7264
  }, [items]);
7229
7265
  const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
@@ -7268,7 +7304,7 @@ function VirtualList({
7268
7304
  }
7269
7305
 
7270
7306
  // src/components/data/EntityRow.tsx
7271
- var React41 = __toESM(require("react"), 1);
7307
+ var React42 = __toESM(require("react"), 1);
7272
7308
  var import_jsx_runtime64 = require("react/jsx-runtime");
7273
7309
  var ENTITY_ROW_METRIC_WIDTH = 74;
7274
7310
  var METRIC_TONE_COLOR = {
@@ -7281,7 +7317,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
7281
7317
  const key = m.id || m.label || i;
7282
7318
  const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
7283
7319
  const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
7284
- const content = /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(React41.Fragment, { children: [
7320
+ const content = /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(React42.Fragment, { children: [
7285
7321
  m.icon ? /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
7286
7322
  /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
7287
7323
  /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-sr", children: " " + m.label })
@@ -7373,7 +7409,7 @@ function EntityRow({
7373
7409
  }
7374
7410
 
7375
7411
  // src/components/data/TransferList.tsx
7376
- var React42 = __toESM(require("react"), 1);
7412
+ var React43 = __toESM(require("react"), 1);
7377
7413
  var import_react_dom6 = require("react-dom");
7378
7414
 
7379
7415
  // src/components/forms/Input.tsx
@@ -7479,12 +7515,12 @@ function TransferList({
7479
7515
  listHeight = 440,
7480
7516
  className = ""
7481
7517
  }) {
7482
- const [drag, setDrag] = React42.useState(null);
7483
- const [dragOverSide, setDragOverSide] = React42.useState(null);
7484
- const dragRef = React42.useRef(null);
7485
- const armedRef = React42.useRef(null);
7486
- const sideRefs = React42.useRef({ left: null, right: null });
7487
- const hitTestSide = React42.useCallback((x, y) => {
7518
+ const [drag, setDrag] = React43.useState(null);
7519
+ const [dragOverSide, setDragOverSide] = React43.useState(null);
7520
+ const dragRef = React43.useRef(null);
7521
+ const armedRef = React43.useRef(null);
7522
+ const sideRefs = React43.useRef({ left: null, right: null });
7523
+ const hitTestSide = React43.useCallback((x, y) => {
7488
7524
  for (const side of ["left", "right"]) {
7489
7525
  const el = sideRefs.current[side];
7490
7526
  if (!el) continue;
@@ -7493,7 +7529,7 @@ function TransferList({
7493
7529
  }
7494
7530
  return null;
7495
7531
  }, []);
7496
- const findItem = React42.useCallback(
7532
+ const findItem = React43.useCallback(
7497
7533
  (side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
7498
7534
  [left.items, right.items, keyOf]
7499
7535
  );
@@ -7515,7 +7551,7 @@ function TransferList({
7515
7551
  height: rect.height
7516
7552
  };
7517
7553
  };
7518
- React42.useEffect(() => {
7554
+ React43.useEffect(() => {
7519
7555
  const onMovePointer = (e) => {
7520
7556
  const armed = armedRef.current;
7521
7557
  if (!armed || e.pointerId !== armed.pointerId) return;
@@ -7568,7 +7604,7 @@ function TransferList({
7568
7604
  window.removeEventListener("pointercancel", endDrag);
7569
7605
  };
7570
7606
  }, [hitTestSide, findItem, onMove]);
7571
- React42.useEffect(() => {
7607
+ React43.useEffect(() => {
7572
7608
  if (!drag || typeof document === "undefined") return;
7573
7609
  const prev = document.body.style.userSelect;
7574
7610
  document.body.style.userSelect = "none";
@@ -7685,7 +7721,7 @@ function FactList({ facts = [], className = "", ...rest }) {
7685
7721
  }
7686
7722
 
7687
7723
  // src/components/data/USChoropleth.tsx
7688
- var React44 = __toESM(require("react"), 1);
7724
+ var React45 = __toESM(require("react"), 1);
7689
7725
  init_usStates();
7690
7726
 
7691
7727
  // src/components/data/usChoropleth/mapBox.ts
@@ -7752,11 +7788,11 @@ function buildChoroplethModel(values, topN, givenTotal) {
7752
7788
  }
7753
7789
 
7754
7790
  // src/components/data/usChoropleth/useUsStateShapes.ts
7755
- var React43 = __toESM(require("react"), 1);
7791
+ var React44 = __toESM(require("react"), 1);
7756
7792
  function useUsStateShapes() {
7757
- const [token, setToken] = React43.useState(0);
7758
- const [settled, setSettled] = React43.useState(null);
7759
- React43.useEffect(() => {
7793
+ const [token, setToken] = React44.useState(0);
7794
+ const [settled, setSettled] = React44.useState(null);
7795
+ React44.useEffect(() => {
7760
7796
  let current2 = true;
7761
7797
  Promise.resolve().then(() => (init_usStateShapes(), usStateShapes_exports)).then(({ STATE_SHAPES: STATE_SHAPES2 }) => {
7762
7798
  if (current2) setSettled({ token, state: { status: "ready", shapes: STATE_SHAPES2 } });
@@ -7798,7 +7834,7 @@ function nextCode(key, from) {
7798
7834
  }
7799
7835
  function StateMap({ shapes, model, figures, label, formatReadout }) {
7800
7836
  const tip = useTooltip();
7801
- const [stop, setStop] = React44.useState(US_STATE_CODES[0]);
7837
+ const [stop, setStop] = React45.useState(US_STATE_CODES[0]);
7802
7838
  const onKeyDown = (event) => {
7803
7839
  const from = event.target.getAttribute("data-state");
7804
7840
  const to = from && nextCode(event.key, from);
@@ -7846,8 +7882,8 @@ function StateTable({ model, valueLabel, formatValue }) {
7846
7882
  return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(Collapsible, { title: TABLE_TITLE, children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(DataTable, { columns, rows: model.rows, rowKey: "code", compact: true }) });
7847
7883
  }
7848
7884
  function USChoropleth({ values, label, valueLabel, formatValue, formatReadout, topN, total, className = "" }) {
7849
- const model = React44.useMemo(() => buildChoroplethModel(values, topN ?? 0, total), [values, topN, total]);
7850
- const figures = React44.useMemo(() => new Map(model.rows.map((row) => [row.code, row])), [model]);
7885
+ const model = React45.useMemo(() => buildChoroplethModel(values, topN ?? 0, total), [values, topN, total]);
7886
+ const figures = React45.useMemo(() => new Map(model.rows.map((row) => [row.code, row])), [model]);
7851
7887
  const { state, retry } = useUsStateShapes();
7852
7888
  return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: ["fd-uschoro", className].filter(Boolean).join(" "), children: [
7853
7889
  /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fd-uschoro-layout", children: [
@@ -7885,11 +7921,11 @@ function USChoropleth({ values, label, valueLabel, formatValue, formatReadout, t
7885
7921
  init_usStates();
7886
7922
 
7887
7923
  // src/components/forms/Checkbox.tsx
7888
- var React45 = __toESM(require("react"), 1);
7924
+ var React46 = __toESM(require("react"), 1);
7889
7925
  var import_jsx_runtime70 = require("react/jsx-runtime");
7890
7926
  function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
7891
- const ref = React45.useRef(null);
7892
- React45.useEffect(() => {
7927
+ const ref = React46.useRef(null);
7928
+ React46.useEffect(() => {
7893
7929
  if (ref.current) ref.current.indeterminate = indeterminate;
7894
7930
  }, [indeterminate]);
7895
7931
  return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
@@ -7936,7 +7972,7 @@ function Switch({ label, description, className = "", ...rest }) {
7936
7972
  }
7937
7973
 
7938
7974
  // src/components/forms/Select.tsx
7939
- var React46 = __toESM(require("react"), 1);
7975
+ var React47 = __toESM(require("react"), 1);
7940
7976
  var import_jsx_runtime73 = require("react/jsx-runtime");
7941
7977
  var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
7942
7978
  function Select({
@@ -7964,12 +8000,12 @@ function Select({
7964
8000
  const isOn = (v) => multiple ? vals.includes(v) : v === value;
7965
8001
  const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
7966
8002
  const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id, hiddenLabel);
7967
- const [open2, setOpen] = React46.useState(false);
7968
- const [q, setQ] = React46.useState("");
7969
- const rootRef = React46.useRef(null);
7970
- const boxRef = React46.useRef(null);
7971
- const listRef = React46.useRef(null);
7972
- const typeBuf = React46.useRef({ s: "", t: 0 });
8003
+ const [open2, setOpen] = React47.useState(false);
8004
+ const [q, setQ] = React47.useState("");
8005
+ const rootRef = React47.useRef(null);
8006
+ const boxRef = React47.useRef(null);
8007
+ const listRef = React47.useRef(null);
8008
+ const typeBuf = React47.useRef({ s: "", t: 0 });
7973
8009
  const selected = multiple ? null : opts.find((o) => o.value === value);
7974
8010
  const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
7975
8011
  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;
@@ -8105,7 +8141,7 @@ function Select({
8105
8141
  ),
8106
8142
  q ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
8107
8143
  ] }) : void 0,
8108
- footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(React46.Fragment, { children: [
8144
+ footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(React47.Fragment, { children: [
8109
8145
  /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
8110
8146
  "button",
8111
8147
  {
@@ -8136,7 +8172,7 @@ function Select({
8136
8172
  'Nothing matches "',
8137
8173
  q,
8138
8174
  '".'
8139
- ] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(React46.Fragment, { children: [
8175
+ ] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(React47.Fragment, { children: [
8140
8176
  grp.g ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
8141
8177
  grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
8142
8178
  "button",
@@ -8173,7 +8209,7 @@ function Select({
8173
8209
  }
8174
8210
 
8175
8211
  // src/components/forms/TimePicker.tsx
8176
- var React47 = __toESM(require("react"), 1);
8212
+ var React48 = __toESM(require("react"), 1);
8177
8213
  var import_jsx_runtime74 = require("react/jsx-runtime");
8178
8214
  var pad = (n) => String(n).padStart(2, "0");
8179
8215
  function ClockFace({ value = "09:00", onChange }) {
@@ -8182,9 +8218,9 @@ function ClockFace({ value = "09:00", onChange }) {
8182
8218
  if (isNaN(m)) m = 0;
8183
8219
  const pm = h24 >= 12;
8184
8220
  const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
8185
- const [mode2, setMode] = React47.useState("h");
8186
- const faceRef = React47.useRef(null);
8187
- const dragging = React47.useRef(false);
8221
+ const [mode2, setMode] = React48.useState("h");
8222
+ const faceRef = React48.useRef(null);
8223
+ const dragging = React48.useRef(false);
8188
8224
  const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
8189
8225
  const R = 108, NR = 80;
8190
8226
  const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
@@ -8257,9 +8293,9 @@ function ClockFace({ value = "09:00", onChange }) {
8257
8293
  }
8258
8294
  function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
8259
8295
  const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
8260
- const [open2, setOpen] = React47.useState(false);
8261
- const rootRef = React47.useRef(null);
8262
- const boxRef = React47.useRef(null);
8296
+ const [open2, setOpen] = React48.useState(false);
8297
+ const rootRef = React48.useRef(null);
8298
+ const boxRef = React48.useRef(null);
8263
8299
  const disp = () => {
8264
8300
  if (!value) return "";
8265
8301
  const [h, m] = value.split(":").map(Number);
@@ -8302,7 +8338,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
8302
8338
  offset: 6,
8303
8339
  width: 262,
8304
8340
  role: "presentation",
8305
- footer: /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(React47.Fragment, { children: [
8341
+ footer: /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(React48.Fragment, { children: [
8306
8342
  /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
8307
8343
  "button",
8308
8344
  {
@@ -8330,7 +8366,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
8330
8366
  }
8331
8367
 
8332
8368
  // src/components/forms/Slider.tsx
8333
- var React48 = __toESM(require("react"), 1);
8369
+ var React49 = __toESM(require("react"), 1);
8334
8370
  var import_jsx_runtime75 = require("react/jsx-runtime");
8335
8371
  function Slider({
8336
8372
  label,
@@ -8348,7 +8384,7 @@ function Slider({
8348
8384
  ...rest
8349
8385
  }) {
8350
8386
  const fieldId = useFieldId(id);
8351
- const [dragging, setDragging] = React48.useState(false);
8387
+ const [dragging, setDragging] = React49.useState(false);
8352
8388
  const v = value === void 0 ? min : Number(value);
8353
8389
  const pct = max === min ? 0 : (v - min) / (max - min) * 100;
8354
8390
  return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
@@ -8382,7 +8418,7 @@ function Slider({
8382
8418
  }
8383
8419
 
8384
8420
  // src/components/forms/RangeSlider.tsx
8385
- var React49 = __toESM(require("react"), 1);
8421
+ var React50 = __toESM(require("react"), 1);
8386
8422
  var import_jsx_runtime76 = require("react/jsx-runtime");
8387
8423
  function RangeSlider({
8388
8424
  label,
@@ -8402,9 +8438,9 @@ function RangeSlider({
8402
8438
  }) {
8403
8439
  const fmt2 = format || ((v) => String(v));
8404
8440
  const [a, b] = value || [min, max];
8405
- const [drag, setDrag] = React49.useState(null);
8406
- const [focus, setFocus] = React49.useState(null);
8407
- const railRef = React49.useRef(null);
8441
+ const [drag, setDrag] = React50.useState(null);
8442
+ const [focus, setFocus] = React50.useState(null);
8443
+ const railRef = React50.useRef(null);
8408
8444
  const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
8409
8445
  const clampPair = (i, v) => {
8410
8446
  v = Math.min(max, Math.max(min, Math.round(v / step) * step));
@@ -8419,7 +8455,7 @@ function RangeSlider({
8419
8455
  const r = railRef.current.getBoundingClientRect();
8420
8456
  return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
8421
8457
  };
8422
- React49.useEffect(() => {
8458
+ React50.useEffect(() => {
8423
8459
  if (drag === null) return;
8424
8460
  const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
8425
8461
  const upH = () => setDrag(null);
@@ -8500,7 +8536,7 @@ function RangeSlider({
8500
8536
  /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
8501
8537
  /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-range-rail", ref: railRef }),
8502
8538
  /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
8503
- marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React49.Fragment, { children: [
8539
+ marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React50.Fragment, { children: [
8504
8540
  /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
8505
8541
  m.label ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
8506
8542
  ] }, m.value)),
@@ -8529,7 +8565,7 @@ function RangeSlider({
8529
8565
  }
8530
8566
 
8531
8567
  // src/components/forms/Dropzone.tsx
8532
- var React50 = __toESM(require("react"), 1);
8568
+ var React51 = __toESM(require("react"), 1);
8533
8569
  var import_jsx_runtime77 = require("react/jsx-runtime");
8534
8570
  function Dropzone({
8535
8571
  onFiles,
@@ -8544,8 +8580,8 @@ function Dropzone({
8544
8580
  className = "",
8545
8581
  style
8546
8582
  }) {
8547
- const [over, setOver] = React50.useState(false);
8548
- const depth = React50.useRef(0);
8583
+ const [over, setOver] = React51.useState(false);
8584
+ const depth = React51.useRef(0);
8549
8585
  const has = (e) => {
8550
8586
  const dt = e.dataTransfer;
8551
8587
  if (!dt) return false;
@@ -8607,8 +8643,8 @@ function FilePickButton({
8607
8643
  className = "",
8608
8644
  children
8609
8645
  }) {
8610
- const ref = React50.useRef(null);
8611
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(React50.Fragment, { children: [
8646
+ const ref = React51.useRef(null);
8647
+ return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(React51.Fragment, { children: [
8612
8648
  /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8613
8649
  "button",
8614
8650
  {
@@ -8641,10 +8677,10 @@ function FilePickButton({
8641
8677
  }
8642
8678
  function useStagedFiles(upload, opts) {
8643
8679
  const o = opts || {};
8644
- const [items, setItems] = React50.useState([]);
8645
- const controllers = React50.useRef({});
8680
+ const [items, setItems] = React51.useState([]);
8681
+ const controllers = React51.useRef({});
8646
8682
  const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
8647
- const run = React50.useCallback((att) => {
8683
+ const run = React51.useCallback((att) => {
8648
8684
  if (!upload) return;
8649
8685
  const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
8650
8686
  controllers.current[att.id] = ac;
@@ -8661,14 +8697,14 @@ function useStagedFiles(upload, opts) {
8661
8697
  delete controllers.current[att.id];
8662
8698
  });
8663
8699
  }, [upload]);
8664
- const add = React50.useCallback((files) => {
8700
+ const add = React51.useCallback((files) => {
8665
8701
  if (!upload) return [];
8666
8702
  const atts = Array.from(files).map((f) => toAttachment(f));
8667
8703
  setItems((list) => list.concat(atts));
8668
8704
  atts.forEach(run);
8669
8705
  return atts;
8670
8706
  }, [upload, run]);
8671
- const remove = React50.useCallback((att) => {
8707
+ const remove = React51.useCallback((att) => {
8672
8708
  const ac = controllers.current[att.id];
8673
8709
  if (ac) {
8674
8710
  try {
@@ -8679,10 +8715,10 @@ function useStagedFiles(upload, opts) {
8679
8715
  }
8680
8716
  setItems((list) => list.filter((f) => f.id !== att.id));
8681
8717
  }, []);
8682
- const retry = React50.useCallback((att) => {
8718
+ const retry = React51.useCallback((att) => {
8683
8719
  run(att);
8684
8720
  }, [run]);
8685
- const clear = React50.useCallback(() => {
8721
+ const clear = React51.useCallback(() => {
8686
8722
  Object.values(controllers.current).forEach((ac) => {
8687
8723
  try {
8688
8724
  ac && ac.abort();
@@ -8806,7 +8842,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
8806
8842
  }
8807
8843
 
8808
8844
  // src/components/forms/MarkdownEditor.tsx
8809
- var React51 = __toESM(require("react"), 1);
8845
+ var React52 = __toESM(require("react"), 1);
8810
8846
  var import_jsx_runtime79 = require("react/jsx-runtime");
8811
8847
  var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
8812
8848
  var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
@@ -9020,7 +9056,7 @@ function syncDom(root, value) {
9020
9056
  while (root.children.length > lines.length) root.removeChild(root.lastChild);
9021
9057
  }
9022
9058
  var LIST_CONT = RE_LI;
9023
- var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
9059
+ var MarkdownEditor = React52.forwardRef(function MarkdownEditor2({
9024
9060
  value = "",
9025
9061
  onChange,
9026
9062
  onSubmit,
@@ -9039,10 +9075,10 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
9039
9075
  className = "",
9040
9076
  id
9041
9077
  }, ref) {
9042
- const boxRef = React51.useRef(null);
9043
- const composing = React51.useRef(false);
9044
- const pendingCaret = React51.useRef(null);
9045
- React51.useLayoutEffect(() => {
9078
+ const boxRef = React52.useRef(null);
9079
+ const composing = React52.useRef(false);
9080
+ const pendingCaret = React52.useRef(null);
9081
+ React52.useLayoutEffect(() => {
9046
9082
  const root = boxRef.current;
9047
9083
  if (!root || composing.current) return;
9048
9084
  const active = document.activeElement === root || root.contains(document.activeElement);
@@ -9051,7 +9087,7 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
9051
9087
  pendingCaret.current = null;
9052
9088
  if (active && caret != null) placeCaret(root, caret);
9053
9089
  }, [value]);
9054
- React51.useEffect(() => {
9090
+ React52.useEffect(() => {
9055
9091
  if (autoFocus && boxRef.current) boxRef.current.focus();
9056
9092
  }, [autoFocus]);
9057
9093
  const caretNow = () => {
@@ -9118,8 +9154,8 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
9118
9154
  api.replaceRange(from, to, next, from + next.length);
9119
9155
  }
9120
9156
  };
9121
- React51.useImperativeHandle(ref, () => api);
9122
- const caretAtKeydown = React51.useRef(-1);
9157
+ React52.useImperativeHandle(ref, () => api);
9158
+ const caretAtKeydown = React52.useRef(-1);
9123
9159
  function detect(text, caret) {
9124
9160
  if (!onTrigger) return;
9125
9161
  const upto = text.slice(0, caret);
@@ -9272,7 +9308,7 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
9272
9308
  });
9273
9309
 
9274
9310
  // src/components/forms/CodeEditor.tsx
9275
- var React52 = __toESM(require("react"), 1);
9311
+ var React53 = __toESM(require("react"), 1);
9276
9312
  var import_view = require("@codemirror/view");
9277
9313
  var import_state = require("@codemirror/state");
9278
9314
  var import_commands = require("@codemirror/commands");
@@ -9376,16 +9412,16 @@ function CodeEditor({
9376
9412
  const fieldId = useFieldId(id);
9377
9413
  const descId = fieldId + "-desc";
9378
9414
  const liveId = fieldId + "-live";
9379
- const hostRef = React52.useRef(null);
9380
- const viewRef = React52.useRef(null);
9381
- const valueRef = React52.useRef(value);
9382
- const onChangeRef = React52.useRef(onChange);
9415
+ const hostRef = React53.useRef(null);
9416
+ const viewRef = React53.useRef(null);
9417
+ const valueRef = React53.useRef(value);
9418
+ const onChangeRef = React53.useRef(onChange);
9383
9419
  onChangeRef.current = onChange;
9384
- const editableCompartment = React52.useRef(new import_state.Compartment()).current;
9385
- const attributesCompartment = React52.useRef(new import_state.Compartment()).current;
9386
- const errorRef = React52.useRef(error);
9420
+ const editableCompartment = React53.useRef(new import_state.Compartment()).current;
9421
+ const attributesCompartment = React53.useRef(new import_state.Compartment()).current;
9422
+ const errorRef = React53.useRef(error);
9387
9423
  errorRef.current = error;
9388
- const diagnosticsCountRef = React52.useRef(diagnostics.length);
9424
+ const diagnosticsCountRef = React53.useRef(diagnostics.length);
9389
9425
  diagnosticsCountRef.current = diagnostics.length;
9390
9426
  function contentAttributes() {
9391
9427
  return {
@@ -9395,7 +9431,7 @@ function CodeEditor({
9395
9431
  ...label ? { "aria-label": label } : {}
9396
9432
  };
9397
9433
  }
9398
- React52.useEffect(() => {
9434
+ React53.useEffect(() => {
9399
9435
  const host2 = hostRef.current;
9400
9436
  if (!host2) return;
9401
9437
  const updateListener = import_view.EditorView.updateListener.of((update) => {
@@ -9437,7 +9473,7 @@ function CodeEditor({
9437
9473
  viewRef.current = null;
9438
9474
  };
9439
9475
  }, []);
9440
- React52.useEffect(() => {
9476
+ React53.useEffect(() => {
9441
9477
  const view = viewRef.current;
9442
9478
  if (!view) return;
9443
9479
  const current2 = view.state.doc.toString();
@@ -9446,12 +9482,12 @@ function CodeEditor({
9446
9482
  }
9447
9483
  valueRef.current = value;
9448
9484
  }, [value]);
9449
- React52.useEffect(() => {
9485
+ React53.useEffect(() => {
9450
9486
  const view = viewRef.current;
9451
9487
  if (!view) return;
9452
9488
  view.dispatch({ effects: editableCompartment.reconfigure(import_view.EditorView.editable.of(!disabled)) });
9453
9489
  }, [disabled, editableCompartment]);
9454
- React52.useEffect(() => {
9490
+ React53.useEffect(() => {
9455
9491
  const view = viewRef.current;
9456
9492
  if (!view) return;
9457
9493
  view.dispatch({
@@ -9509,11 +9545,11 @@ function CodeEditor({
9509
9545
  }
9510
9546
 
9511
9547
  // src/components/forms/RadioGroup.tsx
9512
- var React53 = __toESM(require("react"), 1);
9548
+ var React54 = __toESM(require("react"), 1);
9513
9549
  var import_jsx_runtime81 = require("react/jsx-runtime");
9514
9550
  function RadioGroup({ label, labelledBy, options, value, onChange, card = false, disabled = false, name, className = "" }) {
9515
- const autoName = React53.useId();
9516
- const labelId = React53.useId();
9551
+ const autoName = React54.useId();
9552
+ const labelId = React54.useId();
9517
9553
  return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { role: "radiogroup", "aria-labelledby": labelledBy ?? labelId, "aria-disabled": disabled || void 0, className: ["fd-radiogroup", className].filter(Boolean).join(" "), children: [
9518
9554
  labelledBy === void 0 && /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { id: labelId, className: "fd-radiogroup-label", children: label }),
9519
9555
  options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
@@ -9541,16 +9577,16 @@ function Fieldset({ busy = false, className = "", ...rest }) {
9541
9577
  }
9542
9578
 
9543
9579
  // src/components/platform/AccountMenu.tsx
9544
- var React55 = __toESM(require("react"), 1);
9580
+ var React56 = __toESM(require("react"), 1);
9545
9581
 
9546
9582
  // src/kits/sessionContext.tsx
9547
- var React54 = __toESM(require("react"), 1);
9548
- var SessionContext = React54.createContext(null);
9583
+ var React55 = __toESM(require("react"), 1);
9584
+ var SessionContext = React55.createContext(null);
9549
9585
  function SessionProvider({ value, children }) {
9550
- return React54.createElement(SessionContext.Provider, { value }, children);
9586
+ return React55.createElement(SessionContext.Provider, { value }, children);
9551
9587
  }
9552
9588
  function useSessionContext() {
9553
- const ctx = React54.useContext(SessionContext);
9589
+ const ctx = React55.useContext(SessionContext);
9554
9590
  if (!ctx) {
9555
9591
  throw new Error(
9556
9592
  "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."
@@ -9590,11 +9626,11 @@ function AccountMenu({
9590
9626
  ...rest
9591
9627
  }) {
9592
9628
  const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
9593
- const [open2, setOpen] = React55.useState(false);
9594
- const [switching, setSwitching] = React55.useState(false);
9595
- const [signingOut, setSigningOut] = React55.useState(false);
9596
- const [signOutError, setSignOutError] = React55.useState(null);
9597
- const ref = React55.useRef(null);
9629
+ const [open2, setOpen] = React56.useState(false);
9630
+ const [switching, setSwitching] = React56.useState(false);
9631
+ const [signingOut, setSigningOut] = React56.useState(false);
9632
+ const [signOutError, setSignOutError] = React56.useState(null);
9633
+ const ref = React56.useRef(null);
9598
9634
  const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
9599
9635
  const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || !pending && can2(l.perm)) })).filter((g) => g.links.length);
9600
9636
  const closeMenu = () => {
@@ -9719,13 +9755,13 @@ function AccountMenu({
9719
9755
  }
9720
9756
 
9721
9757
  // src/components/platform/AppSwitcher.tsx
9722
- var React56 = __toESM(require("react"), 1);
9758
+ var React57 = __toESM(require("react"), 1);
9723
9759
  var import_jsx_runtime84 = require("react/jsx-runtime");
9724
9760
  function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
9725
9761
  const { apps: contextApps } = useSessionContext();
9726
9762
  const apps = appsProp ?? contextApps ?? [];
9727
- const [open2, setOpen] = React56.useState(false);
9728
- const anchorRef = React56.useRef(null);
9763
+ const [open2, setOpen] = React57.useState(false);
9764
+ const anchorRef = React57.useRef(null);
9729
9765
  if (!apps.length) return null;
9730
9766
  const items = apps.map((app) => ({
9731
9767
  id: app.key,
@@ -9739,7 +9775,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
9739
9775
  window.location.href = app.url;
9740
9776
  }
9741
9777
  }));
9742
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(React56.Fragment, { children: [
9778
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(React57.Fragment, { children: [
9743
9779
  /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
9744
9780
  IconButton,
9745
9781
  {
@@ -9768,10 +9804,10 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
9768
9804
  }
9769
9805
 
9770
9806
  // src/components/platform/AppearanceMenu.tsx
9771
- var React59 = __toESM(require("react"), 1);
9807
+ var React60 = __toESM(require("react"), 1);
9772
9808
 
9773
9809
  // src/kits/appearance.ts
9774
- var React57 = __toESM(require("react"), 1);
9810
+ var React58 = __toESM(require("react"), 1);
9775
9811
  var DEFAULT_STORAGE_KEY = "fd-appearance";
9776
9812
  var DEFAULT_PREFS = {
9777
9813
  theme: "system",
@@ -9883,8 +9919,8 @@ function watchAppearance(store, root = document.documentElement) {
9883
9919
  };
9884
9920
  }
9885
9921
  function useAppearancePrefs(store) {
9886
- const prefs = React57.useSyncExternalStore(store.subscribe, store.getSnapshot);
9887
- const update = React57.useCallback(
9922
+ const prefs = React58.useSyncExternalStore(store.subscribe, store.getSnapshot);
9923
+ const update = React58.useCallback(
9888
9924
  (patch) => {
9889
9925
  store.write({ ...store.getSnapshot(), ...patch });
9890
9926
  },
@@ -9894,15 +9930,15 @@ function useAppearancePrefs(store) {
9894
9930
  }
9895
9931
 
9896
9932
  // src/components/platform/AppearanceProvider.tsx
9897
- var React58 = __toESM(require("react"), 1);
9933
+ var React59 = __toESM(require("react"), 1);
9898
9934
  var import_jsx_runtime85 = require("react/jsx-runtime");
9899
- var AppearanceStoreContext = React58.createContext(null);
9935
+ var AppearanceStoreContext = React59.createContext(null);
9900
9936
  function AppearanceProvider({ store, children }) {
9901
- React58.useLayoutEffect(() => watchAppearance(store), [store]);
9937
+ React59.useLayoutEffect(() => watchAppearance(store), [store]);
9902
9938
  return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(AppearanceStoreContext.Provider, { value: store, children });
9903
9939
  }
9904
9940
  function useAppearanceStore() {
9905
- const store = React58.useContext(AppearanceStoreContext);
9941
+ const store = React59.useContext(AppearanceStoreContext);
9906
9942
  if (!store) throw new Error("AppearanceMenu and useAppearanceStore must be rendered inside an <AppearanceProvider>.");
9907
9943
  return store;
9908
9944
  }
@@ -9922,10 +9958,10 @@ var TEXT_SCALE_OPTIONS = [
9922
9958
  ];
9923
9959
  function AppearanceMenu({ className = "" }) {
9924
9960
  const [prefs, update] = useAppearancePrefs(useAppearanceStore());
9925
- const [open2, setOpen] = React59.useState(false);
9926
- const anchorRef = React59.useRef(null);
9961
+ const [open2, setOpen] = React60.useState(false);
9962
+ const anchorRef = React60.useRef(null);
9927
9963
  const patch = (p) => update(p);
9928
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(React59.Fragment, { children: [
9964
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(React60.Fragment, { children: [
9929
9965
  /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
9930
9966
  IconButton,
9931
9967
  {
@@ -9994,14 +10030,14 @@ function AppearanceMenu({ className = "" }) {
9994
10030
  }
9995
10031
 
9996
10032
  // src/components/platform/ApiSpecBrowser.tsx
9997
- var React60 = __toESM(require("react"), 1);
10033
+ var React61 = __toESM(require("react"), 1);
9998
10034
  var import_jsx_runtime87 = require("react/jsx-runtime");
9999
10035
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
10000
10036
  function Json({ obj }) {
10001
10037
  return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
10002
10038
  }
10003
10039
  function Endpoint({ s, onRequest }) {
10004
- const [tried, setTried] = React60.useState(null);
10040
+ const [tried, setTried] = React61.useState(null);
10005
10041
  const run = async () => {
10006
10042
  setTried("busy");
10007
10043
  const t0 = (window.performance || Date).now();
@@ -10074,10 +10110,10 @@ function ApiSpecBrowser({
10074
10110
  className = "",
10075
10111
  ...rest
10076
10112
  }) {
10077
- const [q, setQ] = React60.useState("");
10078
- const [method, setMethod] = React60.useState(null);
10079
- const [mod, setMod] = React60.useState(null);
10080
- const [listOnly, setListOnly] = React60.useState(false);
10113
+ const [q, setQ] = React61.useState("");
10114
+ const [method, setMethod] = React61.useState(null);
10115
+ const [mod, setMod] = React61.useState(null);
10116
+ const [listOnly, setListOnly] = React61.useState(false);
10081
10117
  const activeModule = modules && modules.find((m) => m.id === mod);
10082
10118
  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())));
10083
10119
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
@@ -10156,7 +10192,7 @@ function ApiSpecBrowser({
10156
10192
  }
10157
10193
 
10158
10194
  // src/components/platform/ProfilePage.tsx
10159
- var React61 = __toESM(require("react"), 1);
10195
+ var React62 = __toESM(require("react"), 1);
10160
10196
  var import_jsx_runtime88 = require("react/jsx-runtime");
10161
10197
  function fieldInitialValue(field, user) {
10162
10198
  if (field.value) return field.value(user);
@@ -10192,21 +10228,21 @@ function ProfilePage({
10192
10228
  }) {
10193
10229
  const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
10194
10230
  const user = userProp || sessionUser;
10195
- const initialFieldValues = React61.useMemo(() => {
10231
+ const initialFieldValues = React62.useMemo(() => {
10196
10232
  const values2 = {};
10197
10233
  for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
10198
10234
  return values2;
10199
10235
  }, [user.id, fields]);
10200
- const initialNotify = React61.useMemo(() => {
10236
+ const initialNotify = React62.useMemo(() => {
10201
10237
  const values2 = {};
10202
10238
  for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
10203
10239
  return values2;
10204
10240
  }, [user.id, notifications]);
10205
- const [values, setValues] = React61.useState(initialFieldValues);
10206
- const [notify, setNotify] = React61.useState(initialNotify);
10207
- const [saving, setSaving] = React61.useState(false);
10208
- const [saved, setSaved] = React61.useState(false);
10209
- const [prevUserId, setPrevUserId] = React61.useState(user.id);
10241
+ const [values, setValues] = React62.useState(initialFieldValues);
10242
+ const [notify, setNotify] = React62.useState(initialNotify);
10243
+ const [saving, setSaving] = React62.useState(false);
10244
+ const [saved, setSaved] = React62.useState(false);
10245
+ const [prevUserId, setPrevUserId] = React62.useState(user.id);
10210
10246
  if (user.id !== prevUserId) {
10211
10247
  setPrevUserId(user.id);
10212
10248
  setValues(initialFieldValues);
@@ -10394,7 +10430,7 @@ function ProfilePage({
10394
10430
  }
10395
10431
 
10396
10432
  // src/components/platform/SessionScreen.tsx
10397
- var React62 = __toESM(require("react"), 1);
10433
+ var React63 = __toESM(require("react"), 1);
10398
10434
  var import_jsx_runtime89 = require("react/jsx-runtime");
10399
10435
  var COPY = {
10400
10436
  "signing-in": { busy: "Signing you in\u2026" },
@@ -10408,13 +10444,13 @@ function SessionScreen({ kind, error, onRetry, productName }) {
10408
10444
  const copy = COPY[kind];
10409
10445
  const busyMessage = "busy" in copy ? copy.busy : null;
10410
10446
  const failureTitle = "failure" in copy ? copy.failure : null;
10411
- const [announced, setAnnounced] = React62.useState("");
10412
- React62.useEffect(() => {
10447
+ const [announced, setAnnounced] = React63.useState("");
10448
+ React63.useEffect(() => {
10413
10449
  setAnnounced(busyMessage ?? "");
10414
10450
  }, [busyMessage]);
10415
- const titleRef = React62.useRef(null);
10451
+ const titleRef = React63.useRef(null);
10416
10452
  const failed = failureTitle !== null;
10417
- React62.useEffect(() => {
10453
+ React63.useEffect(() => {
10418
10454
  titleRef.current?.focus({ preventScroll: true });
10419
10455
  }, [failed]);
10420
10456
  return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("main", { className: "fd-session-screen", children: /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-session-screen-inner", children: [
@@ -10437,10 +10473,10 @@ function SessionScreen({ kind, error, onRetry, productName }) {
10437
10473
  }
10438
10474
 
10439
10475
  // src/components/platform/RoadmapTimeline.tsx
10440
- var React65 = __toESM(require("react"), 1);
10476
+ var React66 = __toESM(require("react"), 1);
10441
10477
 
10442
10478
  // src/kits/session.ts
10443
- var React63 = __toESM(require("react"), 1);
10479
+ var React64 = __toESM(require("react"), 1);
10444
10480
  var PERMISSION_CATALOG = [
10445
10481
  { group: "Plans", items: [
10446
10482
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -12007,8 +12043,8 @@ function roadmap(overrides) {
12007
12043
  };
12008
12044
  }
12009
12045
  function useSession() {
12010
- const [s, setS] = React63.useState(getSession);
12011
- React63.useEffect(() => subscribe(setS), []);
12046
+ const [s, setS] = React64.useState(getSession);
12047
+ React64.useEffect(() => subscribe(setS), []);
12012
12048
  return s;
12013
12049
  }
12014
12050
  var SessionKit = {
@@ -12041,7 +12077,7 @@ var SessionKit = {
12041
12077
  };
12042
12078
  function DemoSessionProvider({ children }) {
12043
12079
  const session = useSession();
12044
- const value = React63.useMemo(
12080
+ const value = React64.useMemo(
12045
12081
  () => ({
12046
12082
  user: session.user,
12047
12083
  roles: session.roles,
@@ -12057,11 +12093,11 @@ function DemoSessionProvider({ children }) {
12057
12093
  }),
12058
12094
  [session]
12059
12095
  );
12060
- return React63.createElement(SessionProvider, { value }, children);
12096
+ return React64.createElement(SessionProvider, { value }, children);
12061
12097
  }
12062
12098
 
12063
12099
  // src/kits/runtime.ts
12064
- var React64 = __toESM(require("react"), 1);
12100
+ var React65 = __toESM(require("react"), 1);
12065
12101
  var WIRED_ENDPOINTS = [
12066
12102
  // Nothing yet. Every id below would come from a real service:
12067
12103
  // "plan.get", "placements.list", …
@@ -12232,8 +12268,8 @@ var RuntimeKit = {
12232
12268
  };
12233
12269
  RuntimeKit.declare(FEATURE_NEEDS);
12234
12270
  function useRuntimeMode() {
12235
- const [m, setM] = React64.useState(RuntimeKit.getMode());
12236
- React64.useEffect(() => RuntimeKit.subscribe(setM), []);
12271
+ const [m, setM] = React65.useState(RuntimeKit.getMode());
12272
+ React65.useEffect(() => RuntimeKit.subscribe(setM), []);
12237
12273
  return m;
12238
12274
  }
12239
12275
  function useFeatureStatus(key) {
@@ -12316,12 +12352,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
12316
12352
  }
12317
12353
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12318
12354
  const session = SessionKit.useSession();
12319
- const [project, setProject] = React65.useState("");
12320
- const [q, setQ] = React65.useState("");
12321
- const scrollRef = React65.useRef(null);
12322
- const nowRef = React65.useRef(null);
12323
- const rm = React65.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
12324
- const byKey = React65.useMemo(() => {
12355
+ const [project, setProject] = React66.useState("");
12356
+ const [q, setQ] = React66.useState("");
12357
+ const scrollRef = React66.useRef(null);
12358
+ const nowRef = React66.useRef(null);
12359
+ const rm = React66.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
12360
+ const byKey = React66.useMemo(() => {
12325
12361
  const m = {};
12326
12362
  rm.items.forEach((i) => {
12327
12363
  m[i.key] = i;
@@ -12330,7 +12366,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12330
12366
  }, [rm]);
12331
12367
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
12332
12368
  const projects = [...new Set(rm.items.map((i) => i.project))];
12333
- React65.useEffect(() => {
12369
+ React66.useEffect(() => {
12334
12370
  let raf1 = 0, raf2 = 0;
12335
12371
  const place = () => {
12336
12372
  const box = scrollRef.current, mark = nowRef.current;
@@ -12404,7 +12440,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12404
12440
  lastPhase = item.phase;
12405
12441
  const inPhase = items.filter((i) => i.phase === item.phase).length;
12406
12442
  const isBoundary = n === firstPending;
12407
- return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(React65.Fragment, { children: [
12443
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(React66.Fragment, { children: [
12408
12444
  showPhase ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "fd-rm-era", children: [
12409
12445
  /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
12410
12446
  /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
@@ -12448,7 +12484,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12448
12484
  }
12449
12485
 
12450
12486
  // src/components/platform/ComingSoon.tsx
12451
- var React66 = __toESM(require("react"), 1);
12487
+ var React67 = __toESM(require("react"), 1);
12452
12488
  var import_react_dom7 = require("react-dom");
12453
12489
  var import_jsx_runtime91 = require("react/jsx-runtime");
12454
12490
  var BYPASS_STORE = "fd.soon.bypass.v1";
@@ -12466,8 +12502,8 @@ function writeBypassed(list) {
12466
12502
  }
12467
12503
  }
12468
12504
  function useBypass(key) {
12469
- const [on, setOn] = React66.useState(() => !!key && readBypassed().indexOf(key) >= 0);
12470
- React66.useEffect(() => {
12505
+ const [on, setOn] = React67.useState(() => !!key && readBypassed().indexOf(key) >= 0);
12506
+ React67.useEffect(() => {
12471
12507
  setOn(!!key && readBypassed().indexOf(key) >= 0);
12472
12508
  }, [key]);
12473
12509
  const set = (next) => {
@@ -12514,9 +12550,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
12514
12550
  ] });
12515
12551
  }
12516
12552
  function useHoverCard(open2) {
12517
- const anchor = React66.useRef(null);
12518
- const [pos, setPos] = React66.useState(null);
12519
- React66.useLayoutEffect(() => {
12553
+ const anchor = React67.useRef(null);
12554
+ const [pos, setPos] = React67.useState(null);
12555
+ React67.useLayoutEffect(() => {
12520
12556
  if (!open2 || !anchor.current) {
12521
12557
  setPos(null);
12522
12558
  return;
@@ -12643,12 +12679,12 @@ function ComingSoon({
12643
12679
  ] });
12644
12680
  }
12645
12681
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
12646
- const [open2, setOpen] = React66.useState(false);
12682
+ const [open2, setOpen] = React67.useState(false);
12647
12683
  const [anchor, pos] = useHoverCard(open2);
12648
- const hoverCardRef = React66.useRef(null);
12684
+ const hoverCardRef = React67.useRef(null);
12649
12685
  const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
12650
12686
  const zIndex = useLayerZIndex(hoverLayer);
12651
- const close2 = React66.useRef(null);
12687
+ const close2 = React67.useRef(null);
12652
12688
  const show = () => {
12653
12689
  if (close2.current) {
12654
12690
  clearTimeout(close2.current);
@@ -12664,7 +12700,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
12664
12700
  setOpen(false);
12665
12701
  }, 140);
12666
12702
  };
12667
- React66.useEffect(() => () => {
12703
+ React67.useEffect(() => () => {
12668
12704
  if (close2.current) clearTimeout(close2.current);
12669
12705
  }, []);
12670
12706
  return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
@@ -13116,7 +13152,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
13116
13152
  }
13117
13153
 
13118
13154
  // src/components/planner/MixGap.tsx
13119
- var React67 = __toESM(require("react"), 1);
13155
+ var React68 = __toESM(require("react"), 1);
13120
13156
  var import_jsx_runtime96 = require("react/jsx-runtime");
13121
13157
  var MIX_GAP_LAYOUT = {
13122
13158
  trackHeight: 30,
@@ -13131,7 +13167,7 @@ function mixGapOffset(value, max) {
13131
13167
  }
13132
13168
  function MixGap({ rows = [], loading = false, className = "" }) {
13133
13169
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
13134
- const [hover, setHover] = React67.useState(null);
13170
+ const [hover, setHover] = React68.useState(null);
13135
13171
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
13136
13172
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
13137
13173
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
@@ -13274,7 +13310,7 @@ function ChannelContribution({
13274
13310
  }
13275
13311
 
13276
13312
  // src/components/planner/BudgetReallocator.tsx
13277
- var React68 = __toESM(require("react"), 1);
13313
+ var React69 = __toESM(require("react"), 1);
13278
13314
  var import_jsx_runtime98 = require("react/jsx-runtime");
13279
13315
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
13280
13316
  function BudgetReallocator({
@@ -13290,8 +13326,8 @@ function BudgetReallocator({
13290
13326
  onCancel,
13291
13327
  className = ""
13292
13328
  }) {
13293
- const [draft, setDraft] = React68.useState(spend);
13294
- React68.useEffect(() => setDraft(spend), [spend]);
13329
+ const [draft, setDraft] = React69.useState(spend);
13330
+ React69.useEffect(() => setDraft(spend), [spend]);
13295
13331
  const dirty = draft !== spend;
13296
13332
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
13297
13333
  const nextBand = bandFor(nextCrp);
@@ -13306,10 +13342,10 @@ function BudgetReallocator({
13306
13342
  setDraft(spend);
13307
13343
  if (onCancel) onCancel();
13308
13344
  };
13309
- const trackRef = React68.useRef(null);
13310
- const chipRef = React68.useRef(null);
13311
- const [chipLeft, setChipLeft] = React68.useState(null);
13312
- React68.useLayoutEffect(() => {
13345
+ const trackRef = React69.useRef(null);
13346
+ const chipRef = React69.useRef(null);
13347
+ const [chipLeft, setChipLeft] = React69.useState(null);
13348
+ React69.useLayoutEffect(() => {
13313
13349
  const track = trackRef.current;
13314
13350
  if (!dirty || !track) {
13315
13351
  setChipLeft(null);
@@ -13497,7 +13533,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
13497
13533
  }
13498
13534
 
13499
13535
  // src/components/planner/PreferenceMeter.tsx
13500
- var React69 = __toESM(require("react"), 1);
13536
+ var React70 = __toESM(require("react"), 1);
13501
13537
  var import_jsx_runtime101 = require("react/jsx-runtime");
13502
13538
  function preferenceScore(criteria) {
13503
13539
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
@@ -13527,7 +13563,7 @@ function PreferenceMeter({
13527
13563
  className = ""
13528
13564
  }) {
13529
13565
  const value = score == null ? preferenceScore(criteria) : score;
13530
- const segments = React69.useMemo(() => preferenceSegments(criteria), [criteria]);
13566
+ const segments = React70.useMemo(() => preferenceSegments(criteria), [criteria]);
13531
13567
  return /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
13532
13568
  ScoreMeter,
13533
13569
  {
@@ -13566,17 +13602,13 @@ function PreferenceMeter({
13566
13602
  }
13567
13603
 
13568
13604
  // src/components/chat/AgentChatPanel.tsx
13569
- var React75 = __toESM(require("react"), 1);
13605
+ var React77 = __toESM(require("react"), 1);
13570
13606
 
13571
13607
  // src/components/chat/chatEngine.ts
13572
- var React70 = __toESM(require("react"), 1);
13573
- var CHAT_UNAVAILABLE = "chat_unavailable";
13574
- var JOB_PENDING = ["queued", "running"];
13575
- var JOB_SUCCESS = ["completed", "recovered"];
13576
- var STORAGE_PREFIX = "fdchat:job:";
13577
- var seq = 0;
13578
- var uid = (p) => p + "_" + ++seq + "_" + Date.now().toString(36);
13579
- var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
13608
+ var React72 = __toESM(require("react"), 1);
13609
+
13610
+ // src/components/chat/chatStore.ts
13611
+ var React71 = __toESM(require("react"), 1);
13580
13612
  var safeStore = {
13581
13613
  get(k) {
13582
13614
  try {
@@ -13598,6 +13630,38 @@ var safeStore = {
13598
13630
  }
13599
13631
  }
13600
13632
  };
13633
+ var part = (v) => encodeURIComponent(v);
13634
+ var jobKey = (threadId) => "fdchat:job:" + part(threadId);
13635
+ var draftKey = (owner, contextType, contextId) => "fdchat:draft:" + [owner, contextType, contextId].map(part).join(":");
13636
+ function useChatDraft(owner, contextType, contextId, store = safeStore) {
13637
+ if (owner === "") throw new Error("useChatDraft: draftOwner is an empty string; pass the signed-in user's id, or null for no owner.");
13638
+ const key = owner === null ? null : draftKey(owner, contextType, contextId);
13639
+ const read2 = (k) => k ? store.get(k) || "" : "";
13640
+ const [state, setState] = React71.useState(() => ({ key, text: read2(key) }));
13641
+ let current2 = state;
13642
+ if (state.key !== key) {
13643
+ current2 = { key, text: read2(key) };
13644
+ setState(current2);
13645
+ }
13646
+ const setText = React71.useCallback((text) => {
13647
+ if (key) {
13648
+ if (text) {
13649
+ store.set(key, text);
13650
+ if (store.get(key) !== text) store.del(key);
13651
+ } else store.del(key);
13652
+ }
13653
+ setState({ key, text });
13654
+ }, [key, store]);
13655
+ return [current2.text, setText];
13656
+ }
13657
+
13658
+ // src/components/chat/chatEngine.ts
13659
+ var CHAT_UNAVAILABLE = "chat_unavailable";
13660
+ var JOB_PENDING = ["queued", "running"];
13661
+ var JOB_SUCCESS = ["completed", "recovered"];
13662
+ var seq = 0;
13663
+ var uid = (p) => p + "_" + ++seq + "_" + Date.now().toString(36);
13664
+ var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
13601
13665
  var isSystemMessage = (m) => !!m && (m.role === "system" || m.metadata != null && m.metadata.type === "system");
13602
13666
  var visibleMessages = (list) => (list || []).filter((m) => !isSystemMessage(m));
13603
13667
  function jobBucket(status) {
@@ -13638,33 +13702,33 @@ function useChatEngine(opts) {
13638
13702
  onClear,
13639
13703
  onFeedback
13640
13704
  } = opts || {};
13641
- const [status, setStatus] = React70.useState("idle");
13642
- const [threadId, setThreadId] = React70.useState(null);
13643
- const [messages, setMessages] = React70.useState([]);
13644
- const [queue, setQueue] = React70.useState([]);
13645
- const [fatal, setFatal] = React70.useState(null);
13646
- const [busy, setBusy] = React70.useState(false);
13647
- const [turnStartedAt, setTurnStartedAt] = React70.useState(null);
13648
- const listRef = React70.useRef([]);
13649
- const queueRef = React70.useRef([]);
13650
- const busyRef = React70.useRef(false);
13651
- const loadedRef = React70.useRef(false);
13652
- const stoppedRef = React70.useRef(false);
13653
- const abortRef = React70.useRef(null);
13654
- const serverCount = React70.useRef(0);
13655
- const serverIds = React70.useRef(/* @__PURE__ */ new Set());
13656
- const liveTurn = React70.useRef(null);
13657
- const lastTurnOwn = React70.useRef(/* @__PURE__ */ new Set());
13658
- const retired = React70.useRef(/* @__PURE__ */ new Set());
13659
- const threadRef = React70.useRef(null);
13660
- const mounted = React70.useRef(true);
13661
- React70.useEffect(() => {
13705
+ const [status, setStatus] = React72.useState("idle");
13706
+ const [threadId, setThreadId] = React72.useState(null);
13707
+ const [messages, setMessages] = React72.useState([]);
13708
+ const [queue, setQueue] = React72.useState([]);
13709
+ const [fatal, setFatal] = React72.useState(null);
13710
+ const [busy, setBusy] = React72.useState(false);
13711
+ const [turnStartedAt, setTurnStartedAt] = React72.useState(null);
13712
+ const listRef = React72.useRef([]);
13713
+ const queueRef = React72.useRef([]);
13714
+ const busyRef = React72.useRef(false);
13715
+ const loadedRef = React72.useRef(false);
13716
+ const stoppedRef = React72.useRef(false);
13717
+ const abortRef = React72.useRef(null);
13718
+ const serverCount = React72.useRef(0);
13719
+ const serverIds = React72.useRef(/* @__PURE__ */ new Set());
13720
+ const liveTurn = React72.useRef(null);
13721
+ const lastTurnOwn = React72.useRef(/* @__PURE__ */ new Set());
13722
+ const retired = React72.useRef(/* @__PURE__ */ new Set());
13723
+ const threadRef = React72.useRef(null);
13724
+ const mounted = React72.useRef(true);
13725
+ React72.useEffect(() => {
13662
13726
  mounted.current = true;
13663
13727
  return () => {
13664
13728
  mounted.current = false;
13665
13729
  };
13666
13730
  }, []);
13667
- const describeWaitingRef = React70.useRef(describeWaiting);
13731
+ const describeWaitingRef = React72.useRef(describeWaiting);
13668
13732
  describeWaitingRef.current = describeWaiting;
13669
13733
  const commit = (next) => {
13670
13734
  const derived = withWaiting(next, (pending) => describeWaitingRef.current(pending));
@@ -13683,7 +13747,7 @@ function useChatEngine(opts) {
13683
13747
  }
13684
13748
  return false;
13685
13749
  };
13686
- const loadThread = React70.useCallback(async (id) => {
13750
+ const loadThread = React72.useCallback(async (id) => {
13687
13751
  const data = await apiAdapter.getThread(id);
13688
13752
  const list = [...data && data.messages || []];
13689
13753
  serverCount.current = list.length;
@@ -13723,7 +13787,7 @@ function useChatEngine(opts) {
13723
13787
  packet: progress.packet ?? holder.packet
13724
13788
  });
13725
13789
  }
13726
- React70.useEffect(() => {
13790
+ React72.useEffect(() => {
13727
13791
  if (!apiAdapter) {
13728
13792
  setStatus("idle");
13729
13793
  setFatal(null);
@@ -13770,7 +13834,7 @@ function useChatEngine(opts) {
13770
13834
  setStatus("ready");
13771
13835
  loadedRef.current = true;
13772
13836
  onThreadReady && onThreadReady(id);
13773
- const stored = store.get(STORAGE_PREFIX + id);
13837
+ const stored = store.get(jobKey(id));
13774
13838
  const last = [...visibleMessages(listRef.current)].reverse().find((m) => m.role === "assistant");
13775
13839
  if (stored) resumeJob(stored);
13776
13840
  else if (last && last.working && last.jobId) resumeJob(last.jobId, last.id);
@@ -13789,7 +13853,7 @@ function useChatEngine(opts) {
13789
13853
  };
13790
13854
  }, [apiAdapter, contextType, contextId, threadIdProp]);
13791
13855
  async function pollJob(jobId, placeholderId) {
13792
- store.set(STORAGE_PREFIX + threadRef.current, jobId);
13856
+ store.set(jobKey(threadRef.current), jobId);
13793
13857
  const deadline = Date.now() + pendingTimeoutMs;
13794
13858
  while (true) {
13795
13859
  if (stoppedRef.current) break;
@@ -13837,7 +13901,7 @@ function useChatEngine(opts) {
13837
13901
  }
13838
13902
  }
13839
13903
  async function finishJob(_jobId, _job) {
13840
- store.del(STORAGE_PREFIX + threadRef.current);
13904
+ store.del(jobKey(threadRef.current));
13841
13905
  try {
13842
13906
  const list = await loadThread(threadRef.current);
13843
13907
  const withPacket = [...list].reverse().find((m) => m && m.packet);
@@ -13847,7 +13911,7 @@ function useChatEngine(opts) {
13847
13911
  }
13848
13912
  }
13849
13913
  function recordFailure(placeholderId, code, retryable, job) {
13850
- store.del(STORAGE_PREFIX + threadRef.current);
13914
+ store.del(jobKey(threadRef.current));
13851
13915
  if (!listRef.current.some((m) => m.id === placeholderId)) {
13852
13916
  push({ id: placeholderId, role: "assistant", text: null });
13853
13917
  }
@@ -13955,7 +14019,7 @@ function useChatEngine(opts) {
13955
14019
  await dispatchTurn(turn);
13956
14020
  }
13957
14021
  }
13958
- const send = React70.useCallback((text, attachments) => {
14022
+ const send = React72.useCallback((text, attachments) => {
13959
14023
  const body = (text || "").trim();
13960
14024
  if (!body && !(attachments && attachments.length)) return;
13961
14025
  if (status === "disconnected") return;
@@ -13965,7 +14029,7 @@ function useChatEngine(opts) {
13965
14029
  stoppedRef.current = false;
13966
14030
  drain();
13967
14031
  }, [status]);
13968
- const stop = React70.useCallback(() => {
14032
+ const stop = React72.useCallback(() => {
13969
14033
  stoppedRef.current = true;
13970
14034
  const ac = abortRef.current;
13971
14035
  if (ac) {
@@ -13981,14 +14045,14 @@ function useChatEngine(opts) {
13981
14045
  Promise.resolve(apiAdapter.cancelJob(holder.jobId)).catch(() => {
13982
14046
  });
13983
14047
  }
13984
- store.del(STORAGE_PREFIX + threadRef.current);
14048
+ store.del(jobKey(threadRef.current));
13985
14049
  }
13986
14050
  }, [apiAdapter]);
13987
- const removeQueued = React70.useCallback((id) => {
14051
+ const removeQueued = React72.useCallback((id) => {
13988
14052
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
13989
14053
  setQueue(queueRef.current.slice());
13990
14054
  }, []);
13991
- const retry = React70.useCallback(() => {
14055
+ const retry = React72.useCallback(() => {
13992
14056
  const list = listRef.current;
13993
14057
  let at = -1;
13994
14058
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -14005,19 +14069,19 @@ function useChatEngine(opts) {
14005
14069
  setQueue(queueRef.current.slice());
14006
14070
  drain();
14007
14071
  }, []);
14008
- const clear = React70.useCallback(() => {
14072
+ const clear = React72.useCallback(() => {
14009
14073
  commit([]);
14010
14074
  serverCount.current = 0;
14011
14075
  queueRef.current = [];
14012
14076
  setQueue([]);
14013
14077
  onClear && onClear();
14014
14078
  }, [onClear]);
14015
- const setFeedback = React70.useCallback((id, value) => {
14079
+ const setFeedback = React72.useCallback((id, value) => {
14016
14080
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
14017
14081
  const msg = listRef.current.find((m) => m.id === id);
14018
14082
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
14019
14083
  }, [onFeedback]);
14020
- const reload = React70.useCallback(async () => {
14084
+ const reload = React72.useCallback(async () => {
14021
14085
  if (!threadRef.current) return;
14022
14086
  setStatus("loading");
14023
14087
  try {
@@ -14055,10 +14119,10 @@ var ChatKit = {
14055
14119
  };
14056
14120
 
14057
14121
  // src/components/chat/ChatTranscript.tsx
14058
- var React72 = __toESM(require("react"), 1);
14122
+ var React74 = __toESM(require("react"), 1);
14059
14123
 
14060
14124
  // src/components/chat/ChatTurn.tsx
14061
- var React71 = __toESM(require("react"), 1);
14125
+ var React73 = __toESM(require("react"), 1);
14062
14126
  var import_jsx_runtime102 = require("react/jsx-runtime");
14063
14127
  function JsonView({ value }) {
14064
14128
  let text;
@@ -14095,7 +14159,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
14095
14159
  ] });
14096
14160
  }
14097
14161
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
14098
- const [open2, setOpen] = React71.useState(defaultOpen);
14162
+ const [open2, setOpen] = React73.useState(defaultOpen);
14099
14163
  if (!text) return null;
14100
14164
  return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
14101
14165
  /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -14112,7 +14176,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
14112
14176
  ] });
14113
14177
  }
14114
14178
  function Citations({ items = [], onOpen }) {
14115
- const [open2, setOpen] = React71.useState(false);
14179
+ const [open2, setOpen] = React73.useState(false);
14116
14180
  if (!items.length) return null;
14117
14181
  return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-cites", children: [
14118
14182
  /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -14138,7 +14202,7 @@ function clampText(text, max) {
14138
14202
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
14139
14203
  }
14140
14204
  function MessageBody({ message: m, ctx }) {
14141
- const [expanded, setExpanded] = React71.useState(false);
14205
+ const [expanded, setExpanded] = React73.useState(false);
14142
14206
  const isUser = m.role === "user";
14143
14207
  const raw = m.text || "";
14144
14208
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
@@ -14217,7 +14281,7 @@ function RunActions({ group, ctx }) {
14217
14281
  ] }),
14218
14282
  isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
14219
14283
  group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
14220
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)(React71.Fragment, { children: [
14284
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)(React73.Fragment, { children: [
14221
14285
  /* @__PURE__ */ (0, import_jsx_runtime102.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_runtime102.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
14222
14286
  /* @__PURE__ */ (0, import_jsx_runtime102.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_runtime102.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
14223
14287
  ] }) : null,
@@ -14312,10 +14376,10 @@ function ChatTranscript({
14312
14376
  renderEmpty,
14313
14377
  className = ""
14314
14378
  }) {
14315
- const scroller = React72.useRef(null);
14316
- const stick = React72.useRef(true);
14317
- const [pill, setPill] = React72.useState(0);
14318
- const seen = React72.useRef(0);
14379
+ const scroller = React74.useRef(null);
14380
+ const stick = React74.useRef(true);
14381
+ const [pill, setPill] = React74.useState(0);
14382
+ const seen = React74.useRef(0);
14319
14383
  const toBottom = (smooth) => {
14320
14384
  const el = scroller.current;
14321
14385
  if (!el) return;
@@ -14334,7 +14398,7 @@ function ChatTranscript({
14334
14398
  seen.current = messages.length;
14335
14399
  }
14336
14400
  };
14337
- React72.useLayoutEffect(() => {
14401
+ React74.useLayoutEffect(() => {
14338
14402
  const el = scroller.current;
14339
14403
  if (!el) return;
14340
14404
  if (stick.current) {
@@ -14342,7 +14406,7 @@ function ChatTranscript({
14342
14406
  seen.current = messages.length;
14343
14407
  } else setPill(Math.max(0, messages.length - seen.current));
14344
14408
  }, [messages]);
14345
- React72.useEffect(() => {
14409
+ React74.useEffect(() => {
14346
14410
  const el = scroller.current;
14347
14411
  const inner = el && el.firstChild;
14348
14412
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -14352,7 +14416,7 @@ function ChatTranscript({
14352
14416
  ro.observe(inner);
14353
14417
  return () => ro.disconnect();
14354
14418
  }, []);
14355
- const groups = React72.useMemo(() => groupMessages(messages), [messages]);
14419
+ const groups = React74.useMemo(() => groupMessages(messages), [messages]);
14356
14420
  const empty = !messages.length && status === "ready";
14357
14421
  return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
14358
14422
  /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
@@ -14376,7 +14440,7 @@ function ChatTranscript({
14376
14440
  const prev = groups[i - 1];
14377
14441
  const k = dayKey(g.messages[0].timestamp);
14378
14442
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
14379
- return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)(React72.Fragment, { children: [
14443
+ return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)(React74.Fragment, { children: [
14380
14444
  showDay ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { children: dayLabel(k) }) }) : null,
14381
14445
  /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(ChatTurn, { group: g, ctx })
14382
14446
  ] }, g.key || i);
@@ -14393,7 +14457,7 @@ function ChatTranscript({
14393
14457
  var TranscriptKit = { groupMessages };
14394
14458
 
14395
14459
  // src/components/chat/ChatComposer.tsx
14396
- var React73 = __toESM(require("react"), 1);
14460
+ var React75 = __toESM(require("react"), 1);
14397
14461
  var import_jsx_runtime104 = require("react/jsx-runtime");
14398
14462
  function ChatComposer({
14399
14463
  onSubmit,
@@ -14421,17 +14485,17 @@ function ChatComposer({
14421
14485
  onReject,
14422
14486
  onOpenAttachment
14423
14487
  }) {
14424
- const [text, setText] = React73.useState(draft || "");
14425
- const [trigger, setTrigger] = React73.useState(null);
14426
- const [mentionItems, setMentionItems] = React73.useState([]);
14427
- const [listening, setListening] = React73.useState(false);
14428
- const [notice, setNotice] = React73.useState(null);
14429
- const editor = React73.useRef(null);
14430
- const wrap = React73.useRef(null);
14431
- const stopVoice = React73.useRef(null);
14488
+ const [text, setText] = React75.useState(draft || "");
14489
+ const [trigger, setTrigger] = React75.useState(null);
14490
+ const [mentionItems, setMentionItems] = React75.useState([]);
14491
+ const [listening, setListening] = React75.useState(false);
14492
+ const [notice, setNotice] = React75.useState(null);
14493
+ const editor = React75.useRef(null);
14494
+ const wrap = React75.useRef(null);
14495
+ const stopVoice = React75.useRef(null);
14432
14496
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
14433
14497
  } });
14434
- React73.useEffect(() => {
14498
+ React75.useEffect(() => {
14435
14499
  if (draft != null && draft !== text) setText(draft);
14436
14500
  }, [draft]);
14437
14501
  const change = (v) => {
@@ -14467,7 +14531,7 @@ function ChatComposer({
14467
14531
  e.preventDefault();
14468
14532
  staged.add(found.files);
14469
14533
  };
14470
- React73.useEffect(() => {
14534
+ React75.useEffect(() => {
14471
14535
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
14472
14536
  setMentionItems([]);
14473
14537
  return;
@@ -14485,7 +14549,7 @@ function ChatComposer({
14485
14549
  const q = (trigger.query || "").toLowerCase();
14486
14550
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
14487
14551
  }, [trigger, mentionSources]);
14488
- const slashItems = React73.useMemo(() => {
14552
+ const slashItems = React75.useMemo(() => {
14489
14553
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
14490
14554
  const q = (trigger.query || "").toLowerCase();
14491
14555
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -14655,12 +14719,12 @@ function ChatComposer({
14655
14719
  }
14656
14720
 
14657
14721
  // src/components/chat/ChatSessionBar.tsx
14658
- var React74 = __toESM(require("react"), 1);
14722
+ var React76 = __toESM(require("react"), 1);
14659
14723
  var import_jsx_runtime105 = require("react/jsx-runtime");
14660
14724
  var compact2 = meterFormats.compact;
14661
14725
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
14662
- const [open2, setOpen] = React74.useState(false);
14663
- const anchor = React74.useRef(null);
14726
+ const [open2, setOpen] = React76.useState(false);
14727
+ const anchor = React76.useRef(null);
14664
14728
  const stats = sessionStats || null;
14665
14729
  const cu = contextUsage || null;
14666
14730
  const limits = usageLimits || null;
@@ -14675,7 +14739,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
14675
14739
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
14676
14740
  if (cu) bits.push(pct + "% context");
14677
14741
  const expandable = !!(cu || limits);
14678
- return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(React74.Fragment, { children: [
14742
+ return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(React76.Fragment, { children: [
14679
14743
  /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("div", { className: "fdc-bar", children: [
14680
14744
  /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(
14681
14745
  "button",
@@ -14816,7 +14880,7 @@ function ModelControls({
14816
14880
  ] })
14817
14881
  });
14818
14882
  }
14819
- return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(React74.Fragment, { children: [
14883
+ return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(React76.Fragment, { children: [
14820
14884
  /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
14821
14885
  MenuButton,
14822
14886
  {
@@ -14855,6 +14919,7 @@ function AgentChatPanel({
14855
14919
  /* required */
14856
14920
  contextType,
14857
14921
  contextId,
14922
+ draftOwner,
14858
14923
  apiAdapter,
14859
14924
  threadId,
14860
14925
  /* identity + chrome */
@@ -14935,11 +15000,11 @@ function AgentChatPanel({
14935
15000
  onFeedback,
14936
15001
  onEditMessage
14937
15002
  }) {
14938
- const [panelWidth, setPanelWidth] = React75.useState(width);
14939
- const [applied, setApplied] = React75.useState({});
14940
- const [draft, setDraft] = React75.useState("");
14941
- const dragging = React75.useRef(null);
14942
- React75.useEffect(() => setPanelWidth(width), [width]);
15003
+ const [panelWidth, setPanelWidth] = React77.useState(width);
15004
+ const [applied, setApplied] = React77.useState({});
15005
+ const [draft, setDraft] = useChatDraft(draftOwner, contextType, contextId);
15006
+ const dragging = React77.useRef(null);
15007
+ React77.useEffect(() => setPanelWidth(width), [width]);
14943
15008
  const engine = useChatEngine({
14944
15009
  contextType,
14945
15010
  contextId,
@@ -15145,7 +15210,7 @@ function AgentChatPanel({
15145
15210
  }
15146
15211
 
15147
15212
  // src/components/files/FileViewer.tsx
15148
- var React76 = __toESM(require("react"), 1);
15213
+ var React78 = __toESM(require("react"), 1);
15149
15214
  var import_jsx_runtime107 = require("react/jsx-runtime");
15150
15215
  function previewKindOf(file) {
15151
15216
  const mime = (file.mime || "").toLowerCase();
@@ -15202,13 +15267,13 @@ function parseDelimited(text, delimiter) {
15202
15267
  return rows;
15203
15268
  }
15204
15269
  function usePreview(file, kind, resolveUrl) {
15205
- const [state, setState] = React76.useState({ status: "loading" });
15206
- const [attempt, setAttempt] = React76.useState(0);
15207
- const resolveRef = React76.useRef(resolveUrl);
15208
- React76.useEffect(() => {
15270
+ const [state, setState] = React78.useState({ status: "loading" });
15271
+ const [attempt, setAttempt] = React78.useState(0);
15272
+ const resolveRef = React78.useRef(resolveUrl);
15273
+ React78.useEffect(() => {
15209
15274
  resolveRef.current = resolveUrl;
15210
15275
  }, [resolveUrl]);
15211
- React76.useEffect(() => {
15276
+ React78.useEffect(() => {
15212
15277
  if (kind === "none") {
15213
15278
  setState({ status: "ready" });
15214
15279
  return;
@@ -15238,7 +15303,7 @@ function usePreview(file, kind, resolveUrl) {
15238
15303
  if (ac) ac.abort();
15239
15304
  };
15240
15305
  }, [file.id, kind, attempt]);
15241
- return { ...state, retry: React76.useCallback(() => setAttempt((a) => a + 1), []) };
15306
+ return { ...state, retry: React78.useCallback(() => setAttempt((a) => a + 1), []) };
15242
15307
  }
15243
15308
  function PreviewBody({ file, kind, state }) {
15244
15309
  if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
@@ -15283,13 +15348,13 @@ function PreviewBody({ file, kind, state }) {
15283
15348
  ] });
15284
15349
  }
15285
15350
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
15286
- const kind = React76.useMemo(() => previewKindOf(file), [file]);
15351
+ const kind = React78.useMemo(() => previewKindOf(file), [file]);
15287
15352
  const preview = usePreview(file, kind, resolveUrl);
15288
- const [tab, setTab] = React76.useState("preview");
15289
- const [downloading, setDownloading] = React76.useState(false);
15290
- const [downloadError, setDownloadError] = React76.useState(null);
15353
+ const [tab, setTab] = React78.useState("preview");
15354
+ const [downloading, setDownloading] = React78.useState(false);
15355
+ const [downloadError, setDownloadError] = React78.useState(null);
15291
15356
  const hasSide = sidePanel != null;
15292
- React76.useEffect(() => {
15357
+ React78.useEffect(() => {
15293
15358
  setTab("preview");
15294
15359
  }, [file.id]);
15295
15360
  const download = () => {
@@ -15356,7 +15421,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
15356
15421
  }
15357
15422
 
15358
15423
  // src/components/files/FileBrowser.tsx
15359
- var React77 = __toESM(require("react"), 1);
15424
+ var React79 = __toESM(require("react"), 1);
15360
15425
  var import_jsx_runtime108 = require("react/jsx-runtime");
15361
15426
  function childrenOf(folders, parentId) {
15362
15427
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
@@ -15466,8 +15531,8 @@ function FolderPickerMenu({
15466
15531
  ] });
15467
15532
  }
15468
15533
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
15469
- const [over, setOver] = React77.useState(false);
15470
- const dragCounter = React77.useRef(0);
15534
+ const [over, setOver] = React79.useState(false);
15535
+ const dragCounter = React79.useRef(0);
15471
15536
  const dropHandlers = isDropTarget ? {
15472
15537
  onDragEnter: (e) => {
15473
15538
  if (!hasInternalPayload(e)) return;
@@ -15515,8 +15580,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
15515
15580
  }
15516
15581
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
15517
15582
  const kids = childrenOf(folders, folder.id);
15518
- const [expanded, setExpanded] = React77.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
15519
- React77.useEffect(() => {
15583
+ const [expanded, setExpanded] = React79.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
15584
+ React79.useEffect(() => {
15520
15585
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
15521
15586
  }, [currentFolderId, folder.id, folders]);
15522
15587
  const isCurrent = folder.id === currentFolderId;
@@ -15582,15 +15647,15 @@ function FileBrowser({
15582
15647
  const canUpload = perm.canUpload !== false && !!onUpload;
15583
15648
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
15584
15649
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
15585
- const [createOpen, setCreateOpen] = React77.useState(false);
15586
- const [createName, setCreateName] = React77.useState("");
15587
- const [renameTarget, setRenameTarget] = React77.useState(null);
15588
- const [renameValue, setRenameValue] = React77.useState("");
15589
- const [deleteTarget, setDeleteTarget] = React77.useState(null);
15590
- const uploadInputRef = React77.useRef(null);
15591
- const crumbFolders = React77.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
15592
- const subfolders = React77.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
15593
- const currentFiles = React77.useMemo(
15650
+ const [createOpen, setCreateOpen] = React79.useState(false);
15651
+ const [createName, setCreateName] = React79.useState("");
15652
+ const [renameTarget, setRenameTarget] = React79.useState(null);
15653
+ const [renameValue, setRenameValue] = React79.useState("");
15654
+ const [deleteTarget, setDeleteTarget] = React79.useState(null);
15655
+ const uploadInputRef = React79.useRef(null);
15656
+ const crumbFolders = React79.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
15657
+ const subfolders = React79.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
15658
+ const currentFiles = React79.useMemo(
15594
15659
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
15595
15660
  [files, currentFolderId]
15596
15661
  );
@@ -15822,8 +15887,8 @@ function BreadcrumbCrumb({
15822
15887
  isDropTarget,
15823
15888
  onDropPayload
15824
15889
  }) {
15825
- const [over, setOver] = React77.useState(false);
15826
- const dragCounter = React77.useRef(0);
15890
+ const [over, setOver] = React79.useState(false);
15891
+ const dragCounter = React79.useRef(0);
15827
15892
  const dropHandlers = isDropTarget ? {
15828
15893
  onDragEnter: (e) => {
15829
15894
  if (!hasInternalPayload(e)) return;
@@ -15852,7 +15917,7 @@ function BreadcrumbCrumb({
15852
15917
  }
15853
15918
 
15854
15919
  // src/kits/query.ts
15855
- var React78 = __toESM(require("react"), 1);
15920
+ var React80 = __toESM(require("react"), 1);
15856
15921
 
15857
15922
  // src/kits/queryUrl.ts
15858
15923
  var historyUrlAdapter = {
@@ -15990,38 +16055,38 @@ function requestFor(params, query, paging, after) {
15990
16055
  }
15991
16056
  var toError = (e) => e instanceof Error ? e : new Error(String(e));
15992
16057
  function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "page", url }) {
15993
- const [base] = React78.useState(() => {
16058
+ const [base] = React80.useState(() => {
15994
16059
  const store = PREFS || window.PlannerPrefs;
15995
16060
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
15996
16061
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
15997
16062
  });
15998
- const [mountParams] = React78.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
15999
- const address = React78.useRef(mountParams);
16000
- const [query, setQuery] = React78.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
16001
- const savePref = React78.useCallback((patch2) => {
16063
+ const [mountParams] = React80.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
16064
+ const address = React80.useRef(mountParams);
16065
+ const [query, setQuery] = React80.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
16066
+ const savePref = React80.useCallback((patch2) => {
16002
16067
  const store = PREFS || window.PlannerPrefs;
16003
16068
  if (prefsKey && store) store.setTable(prefsKey, patch2);
16004
16069
  }, [prefsKey]);
16005
- const [res, setRes] = React78.useState(null);
16006
- const [loading, setLoading] = React78.useState(true);
16007
- const [loadingMore, setLoadingMore] = React78.useState(false);
16008
- const [failure, setFailure] = React78.useState(null);
16009
- const [reloadToken, setReloadToken] = React78.useState(0);
16010
- const moreController = React78.useRef(null);
16070
+ const [res, setRes] = React80.useState(null);
16071
+ const [loading, setLoading] = React80.useState(true);
16072
+ const [loadingMore, setLoadingMore] = React80.useState(false);
16073
+ const [failure, setFailure] = React80.useState(null);
16074
+ const [reloadToken, setReloadToken] = React80.useState(0);
16075
+ const moreController = React80.useRef(null);
16011
16076
  const depKey = (deps || []).join("|");
16012
16077
  const paramKey = JSON.stringify(params || {});
16013
16078
  const queryKey = JSON.stringify(query);
16014
- const lifetime = React78.useRef(null);
16015
- React78.useEffect(() => {
16079
+ const lifetime = React80.useRef(null);
16080
+ React80.useEffect(() => {
16016
16081
  const controller = new AbortController();
16017
16082
  lifetime.current = controller;
16018
16083
  return () => controller.abort();
16019
16084
  }, []);
16020
- const latest = React78.useRef({ res, loading, query, params, endpoint, url, base });
16021
- React78.useLayoutEffect(() => {
16085
+ const latest = React80.useRef({ res, loading, query, params, endpoint, url, base });
16086
+ React80.useLayoutEffect(() => {
16022
16087
  latest.current = { res, loading, query, params, endpoint, url, base };
16023
16088
  });
16024
- React78.useEffect(() => {
16089
+ React80.useEffect(() => {
16025
16090
  const controller = new AbortController();
16026
16091
  const { signal } = controller;
16027
16092
  setLoading(true);
@@ -16057,7 +16122,7 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "
16057
16122
  };
16058
16123
  }, [endpoint, queryKey, paramKey, depKey, paging, reloadToken]);
16059
16124
  const adapter = url ? url.adapter ?? historyUrlAdapter : null;
16060
- React78.useEffect(() => {
16125
+ React80.useEffect(() => {
16061
16126
  if (!adapter) return;
16062
16127
  return adapter.subscribe((params2) => {
16063
16128
  const { url: u, base: b } = latest.current;
@@ -16407,12 +16472,12 @@ function createVersionStore(initialState, options) {
16407
16472
  }
16408
16473
 
16409
16474
  // src/kits/documentTitle.ts
16410
- var React79 = __toESM(require("react"), 1);
16475
+ var React81 = __toESM(require("react"), 1);
16411
16476
  function formatDocumentTitle(routeTitle, appName) {
16412
- return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
16477
+ return [routeTitle, appName, "Flytedesk"].filter((part2) => !!part2 && part2.length > 0).join(" \xB7 ");
16413
16478
  }
16414
16479
  function useDocumentTitle(routeTitle, appName) {
16415
- React79.useEffect(() => {
16480
+ React81.useEffect(() => {
16416
16481
  if (typeof document === "undefined") return;
16417
16482
  document.title = formatDocumentTitle(routeTitle, appName);
16418
16483
  }, [routeTitle, appName]);
@@ -16523,6 +16588,7 @@ function useDocumentTitle(routeTitle, appName) {
16523
16588
  ModeSwitch,
16524
16589
  ModelControls,
16525
16590
  NumberInput,
16591
+ OVERLAY_BREAKPOINT,
16526
16592
  OVERLAY_CEILING,
16527
16593
  POPOVER_BODY_MIN,
16528
16594
  PacketCard,
@@ -16647,6 +16713,7 @@ function useDocumentTitle(routeTitle, appName) {
16647
16713
  useDocumentTitle,
16648
16714
  useFeatureStatus,
16649
16715
  useLayerZIndex,
16716
+ useOverlayLayout,
16650
16717
  usePopoverPosition,
16651
16718
  useResponsiveRail,
16652
16719
  useRuntimeMode,