@flytedan/flytebot-design-system 0.73.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
@@ -2082,23 +2082,48 @@ function Collapsible({
2082
2082
  }
2083
2083
 
2084
2084
  // src/components/surfaces/Drawer.tsx
2085
- var React6 = __toESM(require("react"), 1);
2085
+ var React7 = __toESM(require("react"), 1);
2086
2086
  var import_react_dom3 = require("react-dom");
2087
- var import_jsx_runtime9 = require("react/jsx-runtime");
2088
- function Drawer({ open: open2 = true, title, label, onClose, footer, bare = false, children, className = "", ...rest }) {
2089
- const asideRef = React6.useRef(null);
2087
+
2088
+ // src/kits/useClosingAnimation.ts
2089
+ var React6 = __toESM(require("react"), 1);
2090
+ function useClosingAnimation(open2, onClose, durationMs) {
2090
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]);
2091
2104
  const close2 = React6.useCallback(() => {
2092
2105
  if (!onClose) return;
2106
+ cancel();
2093
2107
  setClosing(true);
2094
- setTimeout(onClose, 210);
2095
- }, [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);
2096
2121
  const layer = useStackedLayer({ active: !!open2, containerRef: asideRef, trap: true, onEscape: onClose ? close2 : void 0 });
2097
2122
  const zIndex = useLayerZIndex(layer);
2098
- const titleId = React6.useId();
2123
+ const titleId = React7.useId();
2099
2124
  const accessibleName = bare ? label ?? (typeof title === "string" ? title : void 0) : label;
2100
2125
  const unnamed = !!open2 && bare && !accessibleName;
2101
- React6.useEffect(() => {
2126
+ React7.useEffect(() => {
2102
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.");
2103
2128
  }, [unnamed]);
2104
2129
  if (!open2) return null;
@@ -2119,17 +2144,12 @@ function Drawer({ open: open2 = true, title, label, onClose, footer, bare = fals
2119
2144
  }
2120
2145
 
2121
2146
  // src/components/surfaces/Modal.tsx
2122
- var React7 = __toESM(require("react"), 1);
2147
+ var React8 = __toESM(require("react"), 1);
2123
2148
  var import_react_dom4 = require("react-dom");
2124
2149
  var import_jsx_runtime10 = require("react/jsx-runtime");
2125
2150
  function Modal({ open: open2 = true, title, description, onClose, footer, wide = false, children, className = "", ...rest }) {
2126
- const [closing, setClosing] = React7.useState(false);
2127
- const boxRef = React7.useRef(null);
2128
- const close2 = React7.useCallback(() => {
2129
- if (!onClose) return;
2130
- setClosing(true);
2131
- setTimeout(onClose, 190);
2132
- }, [onClose]);
2151
+ const boxRef = React8.useRef(null);
2152
+ const { closing, close: close2 } = useClosingAnimation(!!open2, onClose, 190);
2133
2153
  const layer = useStackedLayer({ active: !!open2, containerRef: boxRef, trap: true, onEscape: onClose ? close2 : void 0 });
2134
2154
  const zIndex = useLayerZIndex(layer);
2135
2155
  if (!open2) return null;
@@ -2212,13 +2232,13 @@ function ScreenHead({ kicker, title, lede, actions }) {
2212
2232
  }
2213
2233
 
2214
2234
  // src/components/layout/CardGrid.tsx
2215
- var React8 = __toESM(require("react"), 1);
2235
+ var React9 = __toESM(require("react"), 1);
2216
2236
  var import_jsx_runtime12 = require("react/jsx-runtime");
2217
2237
  function flattenFragments(children) {
2218
2238
  const out = [];
2219
- React8.Children.forEach(children, (child) => {
2239
+ React9.Children.forEach(children, (child) => {
2220
2240
  if (child === null || child === void 0 || typeof child === "boolean") return;
2221
- if (React8.isValidElement(child) && child.type === React8.Fragment) {
2241
+ if (React9.isValidElement(child) && child.type === React9.Fragment) {
2222
2242
  const fragmentChildren = child.props.children;
2223
2243
  out.push(...flattenFragments(fragmentChildren));
2224
2244
  return;
@@ -2236,7 +2256,7 @@ function CardGrid({ children, minCardWidth = 280, gap = "lg", className = "", st
2236
2256
  className: ["fd-card-grid", "fd-gap-" + gap, className].filter(Boolean).join(" "),
2237
2257
  style: { ["--card-grid-min"]: minCardWidth + "px", ...style },
2238
2258
  children: items.map((child, i) => {
2239
- if (React8.isValidElement(child)) {
2259
+ if (React9.isValidElement(child)) {
2240
2260
  const existingRole = child.props.role;
2241
2261
  if (existingRole) return child;
2242
2262
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { role: "listitem", children: child }, child.key ?? i);
@@ -2286,10 +2306,10 @@ function LoadingRegion({
2286
2306
  }
2287
2307
 
2288
2308
  // src/components/loading/JobTray.tsx
2289
- var React10 = __toESM(require("react"), 1);
2309
+ var React11 = __toESM(require("react"), 1);
2290
2310
 
2291
2311
  // src/kits/cornerStack.tsx
2292
- var React9 = __toESM(require("react"), 1);
2312
+ var React10 = __toESM(require("react"), 1);
2293
2313
  var import_react_dom5 = require("react-dom");
2294
2314
  var CORNER_STACK_INSET_PROPERTY = "--fd-corner-stack-inset";
2295
2315
  var SLOTS = ["jobs", "toasts"];
@@ -2339,9 +2359,9 @@ function release(slot) {
2339
2359
  slotElements.clear();
2340
2360
  }
2341
2361
  }
2342
- var useSlotEffect = typeof document === "undefined" ? React9.useEffect : React9.useLayoutEffect;
2362
+ var useSlotEffect = typeof document === "undefined" ? React10.useEffect : React10.useLayoutEffect;
2343
2363
  function useCornerStackSlot(slot) {
2344
- const [element, setElement] = React9.useState(null);
2364
+ const [element, setElement] = React10.useState(null);
2345
2365
  useSlotEffect(() => {
2346
2366
  setElement(acquire(slot));
2347
2367
  return () => {
@@ -2398,9 +2418,9 @@ function announcementFor(job) {
2398
2418
  return title + ": in progress";
2399
2419
  }
2400
2420
  function JobTray({ jobs: jobs2, onDismiss, className = "" }) {
2401
- const [announcement, setAnnouncement] = React10.useState("");
2402
- const prevStatuses = React10.useRef({});
2403
- React10.useEffect(() => {
2421
+ const [announcement, setAnnouncement] = React11.useState("");
2422
+ const prevStatuses = React11.useRef({});
2423
+ React11.useEffect(() => {
2404
2424
  let next = "";
2405
2425
  for (const job of jobs2) {
2406
2426
  if (prevStatuses.current[job.id] !== job.status) {
@@ -2451,7 +2471,7 @@ function JobCard({ job, onDismiss }) {
2451
2471
  }
2452
2472
 
2453
2473
  // src/components/loading/PhasedProgress.tsx
2454
- var React11 = __toESM(require("react"), 1);
2474
+ var React12 = __toESM(require("react"), 1);
2455
2475
  var import_jsx_runtime16 = require("react/jsx-runtime");
2456
2476
  var ICON = {
2457
2477
  pending: "ph-circle",
@@ -2464,9 +2484,9 @@ function textOf2(node) {
2464
2484
  return "";
2465
2485
  }
2466
2486
  function PhasedProgress({ phases, summary, className = "" }) {
2467
- const [announcement, setAnnouncement] = React11.useState("");
2468
- const prevStatuses = React11.useRef({});
2469
- React11.useEffect(() => {
2487
+ const [announcement, setAnnouncement] = React12.useState("");
2488
+ const prevStatuses = React12.useRef({});
2489
+ React12.useEffect(() => {
2470
2490
  let next = "";
2471
2491
  for (const phase of phases) {
2472
2492
  if (prevStatuses.current[phase.id] !== phase.status) {
@@ -2546,12 +2566,12 @@ function Spinner({ size = "md", label = "Loading", className = "", style, ...res
2546
2566
  }
2547
2567
 
2548
2568
  // src/components/navigation/SidebarNav.tsx
2549
- var React12 = __toESM(require("react"), 1);
2569
+ var React13 = __toESM(require("react"), 1);
2550
2570
  var import_jsx_runtime20 = require("react/jsx-runtime");
2551
2571
  function Tip({ label, children }) {
2552
2572
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { title: label, style: { display: "inline-flex", flex: "none" }, children });
2553
2573
  }
2554
- 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) {
2555
2575
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
2556
2576
  "nav",
2557
2577
  {
@@ -2590,15 +2610,15 @@ var SidebarNav = React12.forwardRef(function SidebarNav2({ brand, groups = [], c
2590
2610
  });
2591
2611
 
2592
2612
  // src/components/navigation/Topbar.tsx
2593
- var React14 = __toESM(require("react"), 1);
2613
+ var React15 = __toESM(require("react"), 1);
2594
2614
 
2595
2615
  // src/kits/useIsNarrow.ts
2596
- var React13 = __toESM(require("react"), 1);
2616
+ var React14 = __toESM(require("react"), 1);
2597
2617
  function useIsNarrow(breakpoint) {
2598
- const [narrow, setNarrow] = React13.useState(
2618
+ const [narrow, setNarrow] = React14.useState(
2599
2619
  () => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
2600
2620
  );
2601
- React13.useEffect(() => {
2621
+ React14.useEffect(() => {
2602
2622
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
2603
2623
  const mq = window.matchMedia(`(max-width: ${breakpoint}px)`);
2604
2624
  const apply = () => setNarrow(mq.matches);
@@ -2622,11 +2642,11 @@ function Topbar({
2622
2642
  ...rest
2623
2643
  }) {
2624
2644
  const narrow = useIsNarrow(overflowBreakpoint);
2625
- const [moreOpen, setMoreOpen] = React14.useState(false);
2626
- const moreRef = React14.useRef(null);
2645
+ const [moreOpen, setMoreOpen] = React15.useState(false);
2646
+ const moreRef = React15.useRef(null);
2627
2647
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("header", { className: ["fd-topbar", narrow ? "is-narrow" : "", className].filter(Boolean).join(" "), ...rest, children: [
2628
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,
2629
- /* @__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: [
2630
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,
2631
2651
  i === crumbs.length - 1 ? (
2632
2652
  // MP-141: the current crumb mixes a static route label with (usually) a
@@ -2679,7 +2699,7 @@ function Topbar({
2679
2699
  }
2680
2700
 
2681
2701
  // src/kits/useResponsiveRail.ts
2682
- var React15 = __toESM(require("react"), 1);
2702
+ var React16 = __toESM(require("react"), 1);
2683
2703
 
2684
2704
  // src/kits/overlayLayout.ts
2685
2705
  var OVERLAY_BREAKPOINT = 1024;
@@ -2690,26 +2710,26 @@ function useOverlayLayout() {
2690
2710
  // src/kits/useResponsiveRail.ts
2691
2711
  function useResponsiveRail(options = {}) {
2692
2712
  const { breakpoint = OVERLAY_BREAKPOINT, initialOpen = true, onPersist } = options;
2693
- const navRef = React15.useRef(null);
2713
+ const navRef = React16.useRef(null);
2694
2714
  const overlay = useIsNarrow(breakpoint);
2695
- const [open2, setOpenRaw] = React15.useState(() => overlay ? false : initialOpen);
2696
- const setOpen = React15.useCallback(
2715
+ const [open2, setOpenRaw] = React16.useState(() => overlay ? false : initialOpen);
2716
+ const setOpen = React16.useCallback(
2697
2717
  (value) => {
2698
2718
  setOpenRaw(value);
2699
2719
  if (!overlay) onPersist?.(value);
2700
2720
  },
2701
2721
  [overlay, onPersist]
2702
2722
  );
2703
- const toggle = React15.useCallback(() => setOpen(!open2), [open2, setOpen]);
2704
- const close2 = React15.useCallback(() => setOpenRaw(false), []);
2705
- const lastOverlay = React15.useRef(overlay);
2706
- 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(() => {
2707
2727
  if (lastOverlay.current === overlay) return;
2708
2728
  lastOverlay.current = overlay;
2709
2729
  setOpenRaw(!overlay);
2710
2730
  }, [overlay]);
2711
2731
  const layer = useStackedLayer({ active: overlay && open2, containerRef: navRef, trap: true, onEscape: close2 });
2712
- React15.useEffect(() => {
2732
+ React16.useEffect(() => {
2713
2733
  if (!overlay || !open2) return;
2714
2734
  const previousOverflow = document.body.style.overflow;
2715
2735
  document.body.style.overflow = "hidden";
@@ -2836,20 +2856,20 @@ function installFlytedeskFavicon(url) {
2836
2856
  }
2837
2857
 
2838
2858
  // src/components/navigation/Tabs.tsx
2839
- var React16 = __toESM(require("react"), 1);
2859
+ var React17 = __toESM(require("react"), 1);
2840
2860
  var import_jsx_runtime24 = require("react/jsx-runtime");
2841
2861
  var FADE_WIDTH = 32;
2842
2862
  function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
2843
- const strip = React16.useRef(null);
2844
- const [more, setMore] = React16.useState({ start: false, end: false });
2845
- 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(() => {
2846
2866
  const el = strip.current;
2847
2867
  if (!el) return;
2848
2868
  const start = el.scrollLeft > 1;
2849
2869
  const end = el.scrollLeft + el.clientWidth < el.scrollWidth - 1;
2850
2870
  setMore((m) => m.start === start && m.end === end ? m : { start, end });
2851
2871
  }, []);
2852
- React16.useLayoutEffect(() => {
2872
+ React17.useLayoutEffect(() => {
2853
2873
  const el = strip.current;
2854
2874
  measure();
2855
2875
  if (!el || typeof ResizeObserver === "undefined") return;
@@ -2857,7 +2877,7 @@ function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
2857
2877
  observer.observe(el);
2858
2878
  return () => observer.disconnect();
2859
2879
  }, [measure, tabs]);
2860
- const revealActive = React16.useCallback(() => {
2880
+ const revealActive = React17.useCallback(() => {
2861
2881
  const el = strip.current;
2862
2882
  const active = el?.querySelector('[aria-selected="true"]');
2863
2883
  if (!el || !active || el.scrollWidth <= el.clientWidth) return;
@@ -2867,9 +2887,9 @@ function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
2867
2887
  else if (tab.right > box.right - FADE_WIDTH) el.scrollLeft += tab.right - box.right + FADE_WIDTH;
2868
2888
  measure();
2869
2889
  }, [measure]);
2870
- React16.useLayoutEffect(revealActive, [value, revealActive]);
2890
+ React17.useLayoutEffect(revealActive, [value, revealActive]);
2871
2891
  const tabKeys = tabs.map((t) => typeof t === "string" ? t : t.value).join(",");
2872
- React16.useLayoutEffect(() => {
2892
+ React17.useLayoutEffect(() => {
2873
2893
  const el = strip.current;
2874
2894
  if (!el || typeof ResizeObserver === "undefined") return;
2875
2895
  const observer = new ResizeObserver(revealActive);
@@ -3124,15 +3144,15 @@ function Toast({ title, children, tone = "success", onUndo, onDismiss, className
3124
3144
  }
3125
3145
 
3126
3146
  // src/components/feedback/ToastProvider.tsx
3127
- var React17 = __toESM(require("react"), 1);
3147
+ var React18 = __toESM(require("react"), 1);
3128
3148
  var import_jsx_runtime33 = require("react/jsx-runtime");
3129
3149
  var DEFAULT_TOAST_DURATION_MS = 5e3;
3130
- var ToastContext = React17.createContext(null);
3150
+ var ToastContext = React18.createContext(null);
3131
3151
  function ToastProvider({ children }) {
3132
- const [items, setItems] = React17.useState([]);
3133
- const timers = React17.useRef(/* @__PURE__ */ new Map());
3134
- const nextId = React17.useRef(1);
3135
- 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) => {
3136
3156
  setItems((current2) => current2.filter((item) => item.id !== id));
3137
3157
  const timer = timers.current.get(id);
3138
3158
  if (timer !== void 0) {
@@ -3140,7 +3160,7 @@ function ToastProvider({ children }) {
3140
3160
  timers.current.delete(id);
3141
3161
  }
3142
3162
  }, []);
3143
- const show = React17.useCallback(
3163
+ const show = React18.useCallback(
3144
3164
  (title, options = {}) => {
3145
3165
  const { tone = "success", duration = DEFAULT_TOAST_DURATION_MS } = options;
3146
3166
  const id = nextId.current++;
@@ -3149,36 +3169,36 @@ function ToastProvider({ children }) {
3149
3169
  },
3150
3170
  [dismiss]
3151
3171
  );
3152
- React17.useEffect(() => {
3172
+ React18.useEffect(() => {
3153
3173
  const pending = timers.current;
3154
3174
  return () => {
3155
3175
  pending.forEach(clearTimeout);
3156
3176
  pending.clear();
3157
3177
  };
3158
3178
  }, []);
3159
- const api = React17.useMemo(() => ({ show }), [show]);
3179
+ const api = React18.useMemo(() => ({ show }), [show]);
3160
3180
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(ToastContext.Provider, { value: api, children: [
3161
3181
  children,
3162
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)) }) })
3163
3183
  ] });
3164
3184
  }
3165
3185
  function useToast() {
3166
- const api = React17.useContext(ToastContext);
3186
+ const api = React18.useContext(ToastContext);
3167
3187
  if (!api) throw new Error("useToast must be used inside a <ToastProvider>");
3168
3188
  return api;
3169
3189
  }
3170
3190
 
3171
3191
  // src/components/feedback/Tooltip.tsx
3172
- var React19 = __toESM(require("react"), 1);
3192
+ var React20 = __toESM(require("react"), 1);
3173
3193
 
3174
3194
  // src/components/feedback/useTooltip.tsx
3175
- var React18 = __toESM(require("react"), 1);
3195
+ var React19 = __toESM(require("react"), 1);
3176
3196
  var import_jsx_runtime34 = require("react/jsx-runtime");
3177
3197
  var CLOSE_DELAY_MS = 120;
3178
3198
  var isMouse = (e) => e.pointerType === "mouse";
3179
3199
  function TooltipBubble({ open: open2, labels, placement, className, onHide, onEnter, onLeave }) {
3180
- const anchorRef = React18.useRef(open2.anchor);
3181
- const bubbleRef = React18.useRef(null);
3200
+ const anchorRef = React19.useRef(open2.anchor);
3201
+ const bubbleRef = React19.useRef(null);
3182
3202
  const pos = usePopoverPosition(true, anchorRef, {
3183
3203
  placement: placement === "bottom" ? "bottom-center" : "top-center",
3184
3204
  offset: 8,
@@ -3189,7 +3209,7 @@ function TooltipBubble({ open: open2, labels, placement, className, onHide, onEn
3189
3209
  });
3190
3210
  const layer = useStackedLayer({ active: true, containerRef: bubbleRef, onEscape: onHide, returnFocus: false });
3191
3211
  const zIndex = useLayerZIndex(layer);
3192
- React18.useEffect(() => {
3212
+ React19.useEffect(() => {
3193
3213
  const away = (e) => {
3194
3214
  const t = e.target;
3195
3215
  if (open2.anchor.contains(t)) return;
@@ -3220,16 +3240,16 @@ function TooltipBubble({ open: open2, labels, placement, className, onHide, onEn
3220
3240
  );
3221
3241
  }
3222
3242
  function useTooltip({ placement = "top", className = "" } = {}) {
3223
- const [open2, setOpen] = React18.useState(null);
3224
- const closeTimer = React18.useRef(null);
3225
- const focused = React18.useRef(null);
3226
- 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(() => {
3227
3247
  if (closeTimer.current) {
3228
3248
  clearTimeout(closeTimer.current);
3229
3249
  closeTimer.current = null;
3230
3250
  }
3231
3251
  }, []);
3232
- const hide = React18.useCallback(() => {
3252
+ const hide = React19.useCallback(() => {
3233
3253
  cancelClose();
3234
3254
  focused.current = null;
3235
3255
  setOpen(null);
@@ -3249,7 +3269,7 @@ function useTooltip({ placement = "top", className = "" } = {}) {
3249
3269
  setOpen((o) => o && o.reason === "hover" ? focused.current : o);
3250
3270
  }, CLOSE_DELAY_MS);
3251
3271
  };
3252
- React18.useEffect(() => cancelClose, [cancelClose]);
3272
+ React19.useEffect(() => cancelClose, [cancelClose]);
3253
3273
  const labels = /* @__PURE__ */ new Map();
3254
3274
  const bind = (id, label) => {
3255
3275
  labels.set(id, label);
@@ -3302,17 +3322,17 @@ function useTooltip({ placement = "top", className = "" } = {}) {
3302
3322
  // src/components/feedback/Tooltip.tsx
3303
3323
  var import_jsx_runtime35 = require("react/jsx-runtime");
3304
3324
  function Tooltip({ label, placement = "top", children, className = "" }) {
3305
- const id = React19.useId();
3325
+ const id = React20.useId();
3306
3326
  const descId = id + "-desc";
3307
3327
  const tip = useTooltip({ placement, className });
3308
- const described = React19.isValidElement(children) ? React19.cloneElement(children, {
3328
+ const described = React20.isValidElement(children) ? React20.cloneElement(children, {
3309
3329
  "aria-describedby": [children.props["aria-describedby"], descId].filter(Boolean).join(" ")
3310
3330
  }) : children;
3311
3331
  return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
3312
3332
  "span",
3313
3333
  {
3314
3334
  className: "fd-tooltip-anchor",
3315
- "aria-describedby": React19.isValidElement(children) ? void 0 : descId,
3335
+ "aria-describedby": React20.isValidElement(children) ? void 0 : descId,
3316
3336
  ...tip.bind(id, label),
3317
3337
  children: [
3318
3338
  described,
@@ -3324,16 +3344,16 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
3324
3344
  }
3325
3345
 
3326
3346
  // src/components/data/AnimNum.tsx
3327
- var React20 = __toESM(require("react"), 1);
3347
+ var React21 = __toESM(require("react"), 1);
3328
3348
  var import_jsx_runtime36 = require("react/jsx-runtime");
3329
3349
  function shouldSkipEasing() {
3330
3350
  if (typeof document !== "undefined" && document.hidden) return true;
3331
3351
  return window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false;
3332
3352
  }
3333
3353
  function AnimNum({ value, format, duration = 550 }) {
3334
- const [display, setDisplay] = React20.useState(value);
3335
- const prev = React20.useRef(value);
3336
- React20.useEffect(() => {
3354
+ const [display, setDisplay] = React21.useState(value);
3355
+ const prev = React21.useRef(value);
3356
+ React21.useEffect(() => {
3337
3357
  const from = prev.current;
3338
3358
  const to = value;
3339
3359
  prev.current = to;
@@ -3361,14 +3381,14 @@ function AnimNum({ value, format, duration = 550 }) {
3361
3381
  }
3362
3382
 
3363
3383
  // src/components/data/TrendChart.tsx
3364
- var React23 = __toESM(require("react"), 1);
3384
+ var React24 = __toESM(require("react"), 1);
3365
3385
 
3366
3386
  // src/components/useMeasuredWidth.ts
3367
- var React21 = __toESM(require("react"), 1);
3387
+ var React22 = __toESM(require("react"), 1);
3368
3388
  function useMeasuredWidth(fallback) {
3369
- const [element, setElement] = React21.useState(null);
3370
- const [width, setWidth] = React21.useState(fallback);
3371
- React21.useLayoutEffect(() => {
3389
+ const [element, setElement] = React22.useState(null);
3390
+ const [width, setWidth] = React22.useState(fallback);
3391
+ React22.useLayoutEffect(() => {
3372
3392
  if (!element || typeof ResizeObserver === "undefined") return;
3373
3393
  const measure = () => {
3374
3394
  const measured = Math.round(element.getBoundingClientRect().width);
@@ -3383,7 +3403,7 @@ function useMeasuredWidth(fallback) {
3383
3403
  }
3384
3404
 
3385
3405
  // src/components/data/SegmentedMeter.tsx
3386
- var React22 = __toESM(require("react"), 1);
3406
+ var React23 = __toESM(require("react"), 1);
3387
3407
 
3388
3408
  // src/kits/files.ts
3389
3409
  function formatBytes(n) {
@@ -3588,7 +3608,7 @@ function SegmentedMeter({
3588
3608
  const pct = safeTotal ? Math.min(100, Math.round(used / safeTotal * 100)) : 0;
3589
3609
  const w = (v) => safeTotal ? Math.max(0, Math.min(100, Number(v) / safeTotal * 100)) : 0;
3590
3610
  const fill = (s, i) => s.color || (s.variant ? VARIANT_FILL[s.variant] : void 0) || CHART[i % CHART.length];
3591
- const generatedId = React22.useId();
3611
+ const generatedId = React23.useId();
3592
3612
  const uid2 = id || generatedId;
3593
3613
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: ["fd-segmeter", className].filter(Boolean).join(" "), onClick, children: [
3594
3614
  label || showTotal ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "fd-segmeter-head", children: [
@@ -3739,8 +3759,8 @@ function TrendChart({
3739
3759
  onRetry,
3740
3760
  className = ""
3741
3761
  }) {
3742
- const [activeId, setActiveId] = React23.useState(null);
3743
- const [pointTip, setPointTip] = React23.useState(null);
3762
+ const [activeId, setActiveId] = React24.useState(null);
3763
+ const [pointTip, setPointTip] = React24.useState(null);
3744
3764
  const isEmpty = state === "ready" && (!categories.length || !series.length || series.every((s) => !s.values.length));
3745
3765
  const effectiveState = isEmpty ? "empty" : state;
3746
3766
  const [plotRef, VBW] = useMeasuredWidth(INITIAL_WIDTH);
@@ -3854,7 +3874,7 @@ function TrendChart({
3854
3874
  }
3855
3875
 
3856
3876
  // src/components/data/DonutChart.tsx
3857
- var React24 = __toESM(require("react"), 1);
3877
+ var React25 = __toESM(require("react"), 1);
3858
3878
  var import_jsx_runtime40 = require("react/jsx-runtime");
3859
3879
  function DonutChart({
3860
3880
  segments,
@@ -3869,7 +3889,7 @@ function DonutChart({
3869
3889
  onRetry,
3870
3890
  className = ""
3871
3891
  }) {
3872
- const [activeId, setActiveId] = React24.useState(null);
3892
+ const [activeId, setActiveId] = React25.useState(null);
3873
3893
  const items = segments.filter((s) => Number(s.value) > 0);
3874
3894
  const total = items.reduce((n, s) => n + Number(s.value), 0);
3875
3895
  const isEmpty = state === "ready" && (!items.length || total <= 0);
@@ -3961,7 +3981,7 @@ function DonutChart({
3961
3981
  }
3962
3982
 
3963
3983
  // src/components/data/BarList.tsx
3964
- var React25 = __toESM(require("react"), 1);
3984
+ var React26 = __toESM(require("react"), 1);
3965
3985
  var import_jsx_runtime41 = require("react/jsx-runtime");
3966
3986
  var wholePercent = (share) => formatPercent(Math.round(share * 100));
3967
3987
  function BarList({
@@ -3978,7 +3998,7 @@ function BarList({
3978
3998
  onRetry,
3979
3999
  className = ""
3980
4000
  }) {
3981
- const ordered = React25.useMemo(() => {
4001
+ const ordered = React26.useMemo(() => {
3982
4002
  const list = sort ? [...rows].sort((a, b) => Number(b.value) - Number(a.value)) : rows;
3983
4003
  return maxRows ? list.slice(0, maxRows) : list;
3984
4004
  }, [rows, sort, maxRows]);
@@ -4120,7 +4140,7 @@ function FunnelChart({
4120
4140
  }
4121
4141
 
4122
4142
  // src/components/data/Clamp.tsx
4123
- var React26 = __toESM(require("react"), 1);
4143
+ var React27 = __toESM(require("react"), 1);
4124
4144
  var import_jsx_runtime43 = require("react/jsx-runtime");
4125
4145
  function Clamp({
4126
4146
  children,
@@ -4132,16 +4152,16 @@ function Clamp({
4132
4152
  onToggle,
4133
4153
  className = ""
4134
4154
  }) {
4135
- const [open2, setOpen] = React26.useState(false);
4136
- const [overflows, setOverflows] = React26.useState(false);
4137
- const bodyRef = React26.useRef(null);
4138
- 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(() => {
4139
4159
  if (open2 || !maxChars || typeof text !== "string" || text.length <= maxChars) return null;
4140
4160
  const cut = text.slice(0, maxChars);
4141
4161
  const at = cut.lastIndexOf(" ");
4142
4162
  return (at > maxChars * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
4143
4163
  }, [text, maxChars, open2]);
4144
- React26.useLayoutEffect(() => {
4164
+ React27.useLayoutEffect(() => {
4145
4165
  const node = bodyRef.current;
4146
4166
  if (maxChars || !node || !maxHeight) return;
4147
4167
  const measure = () => {
@@ -4399,16 +4419,16 @@ function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort
4399
4419
  }
4400
4420
 
4401
4421
  // src/components/data/FilterBar.tsx
4402
- var React32 = __toESM(require("react"), 1);
4422
+ var React33 = __toESM(require("react"), 1);
4403
4423
 
4404
4424
  // src/components/forms/NumberInput.tsx
4405
- var React29 = __toESM(require("react"), 1);
4425
+ var React30 = __toESM(require("react"), 1);
4406
4426
 
4407
4427
  // src/components/forms/field.tsx
4408
- var React27 = __toESM(require("react"), 1);
4428
+ var React28 = __toESM(require("react"), 1);
4409
4429
  var import_jsx_runtime46 = require("react/jsx-runtime");
4410
4430
  function useFieldId(id) {
4411
- const generated = React27.useId();
4431
+ const generated = React28.useId();
4412
4432
  return id || generated;
4413
4433
  }
4414
4434
  function FieldLabel({ htmlFor, id, required = false, onClick, children }) {
@@ -4427,10 +4447,10 @@ function HiddenFieldLabel({ id, children }) {
4427
4447
  }
4428
4448
 
4429
4449
  // src/components/useLatest.ts
4430
- var React28 = __toESM(require("react"), 1);
4450
+ var React29 = __toESM(require("react"), 1);
4431
4451
  function useLatest(value) {
4432
- const ref = React28.useRef(value);
4433
- React28.useInsertionEffect(() => {
4452
+ const ref = React29.useRef(value);
4453
+ React29.useInsertionEffect(() => {
4434
4454
  ref.current = value;
4435
4455
  });
4436
4456
  return ref;
@@ -4513,20 +4533,20 @@ function NumberInput({
4513
4533
  const n = typeof v === "number" ? v : parseNumberText(v);
4514
4534
  return n == null || Number.isNaN(n) ? null : n;
4515
4535
  };
4516
- const [text, setText] = React29.useState(() => toText(value));
4517
- const [editing, setEditing] = React29.useState(false);
4536
+ const [text, setText] = React30.useState(() => toText(value));
4537
+ const [editing, setEditing] = React30.useState(false);
4518
4538
  const parsed = parseNumberText(text);
4519
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;
4520
4540
  const valid = invalidMessage == null;
4521
- const committedRef = React29.useRef(toNumber(value));
4541
+ const committedRef = React30.useRef(toNumber(value));
4522
4542
  const onChangeRef = useLatest(onChange);
4523
4543
  const onValidityChangeRef = useLatest(onValidityChange);
4524
- const focusedRef = React29.useRef(false);
4525
- React29.useEffect(() => {
4544
+ const focusedRef = React30.useRef(false);
4545
+ React30.useEffect(() => {
4526
4546
  committedRef.current = toNumber(value);
4527
4547
  if (!focusedRef.current) setText(toText(value));
4528
4548
  }, [value]);
4529
- React29.useLayoutEffect(() => {
4549
+ React30.useLayoutEffect(() => {
4530
4550
  onValidityChangeRef.current?.(valid);
4531
4551
  }, [valid, onValidityChangeRef]);
4532
4552
  const fire = (n) => {
@@ -4542,7 +4562,7 @@ function NumberInput({
4542
4562
  return true;
4543
4563
  };
4544
4564
  const bumpRef = useLatest(bump);
4545
- const holdTimer = React29.useRef(null);
4565
+ const holdTimer = React30.useRef(null);
4546
4566
  const release2 = () => {
4547
4567
  if (holdTimer.current) clearTimeout(holdTimer.current);
4548
4568
  holdTimer.current = null;
@@ -4561,7 +4581,7 @@ function NumberInput({
4561
4581
  };
4562
4582
  holdTimer.current = setTimeout(tick, HOLD_DELAY_MS);
4563
4583
  };
4564
- React29.useEffect(() => () => {
4584
+ React30.useEffect(() => () => {
4565
4585
  if (holdTimer.current) clearTimeout(holdTimer.current);
4566
4586
  }, []);
4567
4587
  const current2 = committedRef.current;
@@ -4664,7 +4684,7 @@ function NumberInput({
4664
4684
  }
4665
4685
 
4666
4686
  // src/components/forms/DatePicker.tsx
4667
- var React30 = __toESM(require("react"), 1);
4687
+ var React31 = __toESM(require("react"), 1);
4668
4688
  var import_jsx_runtime48 = require("react/jsx-runtime");
4669
4689
  var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
4670
4690
  var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
@@ -4697,10 +4717,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
4697
4717
  const today = /* @__PURE__ */ new Date();
4698
4718
  const sel = range ? value || {} : { start: value, end: value };
4699
4719
  const anchor = parse(sel.start) || parse(initialMonth) || today;
4700
- const [vy, setVy] = React30.useState(anchor.getFullYear());
4701
- const [vm, setVm] = React30.useState(anchor.getMonth());
4702
- const [mode2, setMode] = React30.useState("days");
4703
- 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);
4704
4724
  const s = parse(sel.start), e = parse(sel.end);
4705
4725
  const hoverEnd = range && s && !e && hover ? parse(hover) : null;
4706
4726
  const inRange = (d) => {
@@ -4711,12 +4731,12 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
4711
4731
  const isEnd = (d) => !!e && iso(d) === iso(e);
4712
4732
  const isEdge = (d) => isStart(d) || isEnd(d);
4713
4733
  const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
4714
- const [activeDate, setActiveDate] = React30.useState(() => {
4734
+ const [activeDate, setActiveDate] = React31.useState(() => {
4715
4735
  if (s) return s;
4716
4736
  if (sameMonth(today, anchor.getFullYear(), anchor.getMonth())) return today;
4717
4737
  return new Date(anchor.getFullYear(), anchor.getMonth(), 1);
4718
4738
  });
4719
- const calRef = React30.useRef(null);
4739
+ const calRef = React31.useRef(null);
4720
4740
  const pageToShow = (y, m) => {
4721
4741
  const idx = y * 12 + m, firstIdx = vy * 12 + vm, secondIdx = firstIdx + 1;
4722
4742
  if (idx === firstIdx || months > 1 && idx === secondIdx) return;
@@ -4733,7 +4753,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
4733
4753
  setActiveDate(next);
4734
4754
  pageToShow(next.getFullYear(), next.getMonth());
4735
4755
  };
4736
- React30.useEffect(() => {
4756
+ React31.useEffect(() => {
4737
4757
  const el = calRef.current?.querySelector('[data-iso="' + iso(activeDate) + '"]');
4738
4758
  if (el) el.focus({ preventScroll: true });
4739
4759
  }, [activeDate, vy, vm]);
@@ -4926,9 +4946,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
4926
4946
  }
4927
4947
  function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, "aria-label": hiddenLabel, ...rest }) {
4928
4948
  const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id, hiddenLabel);
4929
- const [open2, setOpen] = React30.useState(false);
4930
- const rootRef = React30.useRef(null);
4931
- const boxRef = React30.useRef(null);
4949
+ const [open2, setOpen] = React31.useState(false);
4950
+ const rootRef = React31.useRef(null);
4951
+ const boxRef = React31.useRef(null);
4932
4952
  const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
4933
4953
  const toggle = () => {
4934
4954
  if (!disabled) setOpen(!open2);
@@ -5017,9 +5037,9 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
5017
5037
  }
5018
5038
 
5019
5039
  // src/components/forms/listbox.ts
5020
- var React31 = __toESM(require("react"), 1);
5040
+ var React32 = __toESM(require("react"), 1);
5021
5041
  function useListboxNav({ count, onSelect }) {
5022
- const [active, setActive] = React31.useState(-1);
5042
+ const [active, setActive] = React32.useState(-1);
5023
5043
  return {
5024
5044
  active,
5025
5045
  setActive,
@@ -5032,7 +5052,7 @@ function useListboxNav({ count, onSelect }) {
5032
5052
  };
5033
5053
  }
5034
5054
  function useListboxScrollIntoView(active, listRef, enabled) {
5035
- React31.useEffect(() => {
5055
+ React32.useEffect(() => {
5036
5056
  if (!enabled || active < 0 || !listRef.current) return;
5037
5057
  const list = listRef.current;
5038
5058
  const el = list.querySelector('[data-i="' + active + '"]');
@@ -5253,13 +5273,13 @@ function MultiSelectPanel({
5253
5273
  onClose
5254
5274
  }) {
5255
5275
  const allowedOps = operatorsFor(field);
5256
- const [draftOperator, setDraftOperator] = React32.useState(value?.operator ?? allowedOps[0]);
5276
+ const [draftOperator, setDraftOperator] = React33.useState(value?.operator ?? allowedOps[0]);
5257
5277
  const operator = allowedOps.length === 1 ? allowedOps[0] : value?.operator ?? draftOperator;
5258
5278
  const selected = value?.values ?? [];
5259
5279
  const selectedRef = useLatest(selected);
5260
5280
  const operatorRef = useLatest(operator);
5261
- const mountedRef = React32.useRef(true);
5262
- React32.useEffect(() => {
5281
+ const mountedRef = React33.useRef(true);
5282
+ React33.useEffect(() => {
5263
5283
  mountedRef.current = true;
5264
5284
  return () => {
5265
5285
  mountedRef.current = false;
@@ -5273,20 +5293,20 @@ function MultiSelectPanel({
5273
5293
  if (selectedRef.current.length > 0) commit(selectedRef.current, op);
5274
5294
  else setDraftOperator(op);
5275
5295
  };
5276
- const [mode2, setMode] = React32.useState("search");
5277
- const [query, setQuery] = React32.useState("");
5278
- const [asyncState, setAsyncState] = React32.useState(
5296
+ const [mode2, setMode] = React33.useState("search");
5297
+ const [query, setQuery] = React33.useState("");
5298
+ const [asyncState, setAsyncState] = React33.useState(
5279
5299
  { options: null, loading: !!field.loadOptions, error: false }
5280
5300
  );
5281
- const [retryTick, setRetryTick] = React32.useState(0);
5282
- const inputRef = React32.useRef(null);
5283
- const listRef = React32.useRef(null);
5284
- 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();
5285
5305
  const loadOptionsRef = useLatest(field.loadOptions);
5286
- React32.useEffect(() => {
5306
+ React33.useEffect(() => {
5287
5307
  inputRef.current?.focus();
5288
5308
  }, []);
5289
- React32.useEffect(() => {
5309
+ React33.useEffect(() => {
5290
5310
  const load = loadOptionsRef.current;
5291
5311
  if (!load) return;
5292
5312
  const controller = new AbortController();
@@ -5319,17 +5339,17 @@ function MultiSelectPanel({
5319
5339
  };
5320
5340
  const nav = useListboxNav({ count: options.length, onSelect: (i) => toggle(options[i]) });
5321
5341
  useListboxScrollIntoView(nav.active, listRef, hasListbox);
5322
- React32.useEffect(() => {
5342
+ React33.useEffect(() => {
5323
5343
  nav.setActive(0);
5324
5344
  }, [query, options.length]);
5325
5345
  const activeId = hasListbox && options[nav.active] ? listId + "-opt-" + nav.active : void 0;
5326
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" : "";
5327
- const [pasteText, setPasteText] = React32.useState("");
5328
- const [pasteLoading, setPasteLoading] = React32.useState(false);
5329
- const [unmatchedTokens, setUnmatchedTokens] = React32.useState([]);
5330
- const [pasteError, setPasteError] = React32.useState(null);
5331
- const pasteWrapRef = React32.useRef(null);
5332
- 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(() => {
5333
5353
  if (mode2 === "paste") pasteWrapRef.current?.querySelector("textarea")?.focus();
5334
5354
  }, [mode2]);
5335
5355
  const doResolve = () => {
@@ -5502,8 +5522,8 @@ function MultiSelectPanel({
5502
5522
  );
5503
5523
  }
5504
5524
  function useTextValidity(onFlip) {
5505
- const invalidRef = React32.useRef(/* @__PURE__ */ new Set());
5506
- 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);
5507
5527
  const onFlipRef = useLatest(onFlip);
5508
5528
  const record = (name, valid) => {
5509
5529
  const invalid = invalidRef.current;
@@ -5546,15 +5566,15 @@ function sameValue(a, b) {
5546
5566
  return true;
5547
5567
  }
5548
5568
  function useReseedFromProps(value, applies, reseed) {
5549
- const seen = React32.useRef(value);
5550
- React32.useLayoutEffect(() => {
5569
+ const seen = React33.useRef(value);
5570
+ React33.useLayoutEffect(() => {
5551
5571
  if (seen.current === value) return;
5552
5572
  seen.current = value;
5553
5573
  if (!sameValue(value, applies())) reseed(value);
5554
5574
  }, [value, applies, reseed]);
5555
5575
  }
5556
5576
  function usePreserveFocusAcrossRemount(seed, fields) {
5557
- const pendingName = React32.useRef(null);
5577
+ const pendingName = React33.useRef(null);
5558
5578
  const fieldsRef = useLatest(fields);
5559
5579
  const capture = () => {
5560
5580
  const active = document.activeElement;
@@ -5567,7 +5587,7 @@ function usePreserveFocusAcrossRemount(seed, fields) {
5567
5587
  }
5568
5588
  }
5569
5589
  };
5570
- React32.useLayoutEffect(() => {
5590
+ React33.useLayoutEffect(() => {
5571
5591
  const name = pendingName.current;
5572
5592
  if (!name) return;
5573
5593
  pendingName.current = null;
@@ -5583,14 +5603,14 @@ function RangePanel({
5583
5603
  onCommit,
5584
5604
  onClose
5585
5605
  }) {
5586
- const [draft, setDraft] = React32.useState(() => rangeDraft(value));
5587
- const [seed, setSeed] = React32.useState(0);
5588
- const minId = React32.useId();
5589
- const maxId = React32.useId();
5590
- const minWrapRef = React32.useRef(null);
5591
- 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);
5592
5612
  const preserveFocus = usePreserveFocusAcrossRemount(seed, { min: minWrapRef, max: maxWrapRef });
5593
- const draftRef = React32.useRef(draft);
5613
+ const draftRef = React33.useRef(draft);
5594
5614
  const shown = () => {
5595
5615
  const { min, max } = draftRef.current;
5596
5616
  return applicable(field, min == null && max == null ? void 0 : { min, max }, validity.allValid());
@@ -5682,15 +5702,15 @@ function DatePanel({
5682
5702
  onClose
5683
5703
  }) {
5684
5704
  const maxDays = effectiveMaxDays(field);
5685
- const [initial] = React32.useState(() => dateDraft(field, value));
5686
- const [kind, setKind] = React32.useState(initial.kind);
5687
- const [daysDraft, setDaysDraft] = React32.useState(initial.days);
5688
- const daysRef = React32.useRef(daysDraft);
5689
- const daysConfirmed = React32.useRef(value?.kind === "withinDays");
5690
- const [between, setBetween] = React32.useState(initial.between);
5691
- const [seed, setSeed] = React32.useState(0);
5692
- const daysId = React32.useId();
5693
- 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);
5694
5714
  const preserveFocus = usePreserveFocusAcrossRemount(seed, { days: daysWrapRef });
5695
5715
  const shownWithinDays = () => {
5696
5716
  const days = daysRef.current;
@@ -5808,11 +5828,11 @@ function FilterButton({ children, ...rest }) {
5808
5828
  ] });
5809
5829
  }
5810
5830
  function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align = "left", actions, onClearAll, showActiveCount = false, loading = false, loadingLabel = "Loading the filters", className = "", ...rest }) {
5811
- const [panel, setPanel] = React32.useState(null);
5812
- const editAnchorRef = React32.useRef(null);
5813
- const addAnchorRef = React32.useRef(null);
5814
- const textInputRef = React32.useRef(null);
5815
- 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);
5816
5836
  if (process.env.NODE_ENV !== "production") {
5817
5837
  for (const f of fields) assertValidFieldDefinition(f);
5818
5838
  }
@@ -5835,7 +5855,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
5835
5855
  const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
5836
5856
  const startEditing = (key) => setPanel({ kind: "edit", key });
5837
5857
  const closeEditing = () => setPanel(null);
5838
- React32.useEffect(() => {
5858
+ React33.useEffect(() => {
5839
5859
  if (!panel || panel.kind !== "edit") return;
5840
5860
  if (editingField?.type === "text") {
5841
5861
  textInputRef.current?.focus();
@@ -6090,10 +6110,10 @@ function StatTile(props) {
6090
6110
  }
6091
6111
 
6092
6112
  // src/components/data/CodeBlock.tsx
6093
- var React34 = __toESM(require("react"), 1);
6113
+ var React35 = __toESM(require("react"), 1);
6094
6114
 
6095
6115
  // src/kits/clipboard.ts
6096
- var React33 = __toESM(require("react"), 1);
6116
+ var React34 = __toESM(require("react"), 1);
6097
6117
  var COPIED_FEEDBACK_MS = 1600;
6098
6118
  function copyThroughSelection(text) {
6099
6119
  const previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
@@ -6123,17 +6143,17 @@ async function copyToClipboard(text) {
6123
6143
  return copyThroughSelection(text);
6124
6144
  }
6125
6145
  function useCopyToClipboard() {
6126
- const [copied, setCopied] = React33.useState(false);
6127
- const timer = React33.useRef(null);
6128
- const mounted = React33.useRef(true);
6129
- React33.useEffect(() => {
6146
+ const [copied, setCopied] = React34.useState(false);
6147
+ const timer = React34.useRef(null);
6148
+ const mounted = React34.useRef(true);
6149
+ React34.useEffect(() => {
6130
6150
  mounted.current = true;
6131
6151
  return () => {
6132
6152
  mounted.current = false;
6133
6153
  if (timer.current) clearTimeout(timer.current);
6134
6154
  };
6135
6155
  }, []);
6136
- const copy = React33.useCallback(async (text) => {
6156
+ const copy = React34.useCallback(async (text) => {
6137
6157
  const ok = await copyToClipboard(text);
6138
6158
  if (ok && mounted.current) {
6139
6159
  setCopied(true);
@@ -6301,7 +6321,7 @@ function tokenize(src, lang) {
6301
6321
  return out;
6302
6322
  }
6303
6323
  function Highlighted({ code, lang }) {
6304
- const toks = React34.useMemo(() => tokenize(code, lang), [code, lang]);
6324
+ const toks = React35.useMemo(() => tokenize(code, lang), [code, lang]);
6305
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) });
6306
6326
  }
6307
6327
  function CodeBlock({
@@ -6315,8 +6335,8 @@ function CodeBlock({
6315
6335
  actions,
6316
6336
  className = ""
6317
6337
  }) {
6318
- const [wrap, setWrap] = React34.useState(!!wrapDefault);
6319
- const [open2, setOpen] = React34.useState(false);
6338
+ const [wrap, setWrap] = React35.useState(!!wrapDefault);
6339
+ const [open2, setOpen] = React35.useState(false);
6320
6340
  const [copied, copy] = useCopyToClipboard();
6321
6341
  const body = String(code).replace(/\n$/, "");
6322
6342
  const lines = body.split("\n");
@@ -6345,7 +6365,7 @@ function CodeBlock({
6345
6365
  ] });
6346
6366
  }
6347
6367
  function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
6348
- const [open2, setOpen] = React34.useState(false);
6368
+ const [open2, setOpen] = React35.useState(false);
6349
6369
  const [copied, copy] = useCopyToClipboard();
6350
6370
  const raw = String(diff).replace(/\n$/, "");
6351
6371
  const all = raw.split("\n").map((line) => {
@@ -6391,7 +6411,7 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
6391
6411
  }
6392
6412
 
6393
6413
  // src/components/data/Markdown.tsx
6394
- var React35 = __toESM(require("react"), 1);
6414
+ var React36 = __toESM(require("react"), 1);
6395
6415
 
6396
6416
  // src/components/data/markdownEscape.ts
6397
6417
  var ESCAPABLE = /\\([!-/:-@[-`{-~])/g;
@@ -6464,7 +6484,7 @@ function hiddenInlineNodes(hidden, ctx, keyBase) {
6464
6484
  const href = safeHref(d(g(2)));
6465
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()));
6466
6486
  } else if (kind === "cite") {
6467
- 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()));
6468
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()));
6469
6489
  else if (kind === "strong") out.push(/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("strong", { children: hiddenInlineNodes(g(1) || g(2), ctx, key()) }, key()));
6470
6490
  else if (kind === "em") out.push(/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("em", { children: hiddenInlineNodes(g(1) || g(2), ctx, key()) }, key()));
@@ -6651,7 +6671,7 @@ function Markdown({
6651
6671
  tone = "default"
6652
6672
  }) {
6653
6673
  const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
6654
- const blocks = React35.useMemo(() => parseBlocks(source), [source]);
6674
+ const blocks = React36.useMemo(() => parseBlocks(source), [source]);
6655
6675
  return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: mdClass("fd-md", size, tone, className), children: renderBlocks(blocks, ctx, "b") });
6656
6676
  }
6657
6677
  function MarkdownInline({ source = "", className = "", onLinkClick, size, tone }) {
@@ -6762,7 +6782,7 @@ function Pagination({
6762
6782
  }
6763
6783
 
6764
6784
  // src/components/data/RelativeTime.tsx
6765
- var React36 = __toESM(require("react"), 1);
6785
+ var React37 = __toESM(require("react"), 1);
6766
6786
  var import_jsx_runtime58 = require("react/jsx-runtime");
6767
6787
  var MIN = 6e4;
6768
6788
  var HOUR = 36e5;
@@ -6814,9 +6834,9 @@ function formatDuration(ms) {
6814
6834
  return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
6815
6835
  }
6816
6836
  function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
6817
- const [, force] = React36.useState(0);
6837
+ const [, force] = React37.useState(0);
6818
6838
  const t = value instanceof Date ? value.getTime() : Date.parse(value);
6819
- React36.useEffect(() => {
6839
+ React37.useEffect(() => {
6820
6840
  if (!refresh2 || !t || isNaN(t)) return;
6821
6841
  const abs2 = Math.abs(t - Date.now());
6822
6842
  if (abs2 > DAY) return;
@@ -6832,7 +6852,7 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
6832
6852
  }
6833
6853
 
6834
6854
  // src/components/data/ScoreMeter.tsx
6835
- var React37 = __toESM(require("react"), 1);
6855
+ var React38 = __toESM(require("react"), 1);
6836
6856
  var import_jsx_runtime59 = require("react/jsx-runtime");
6837
6857
  function ScoreMeter({
6838
6858
  score,
@@ -6847,10 +6867,10 @@ function ScoreMeter({
6847
6867
  breakdownWidth = 280,
6848
6868
  className = ""
6849
6869
  }) {
6850
- const [open2, setOpen] = React37.useState(false);
6851
- const ref = React37.useRef(null);
6870
+ const [open2, setOpen] = React38.useState(false);
6871
+ const ref = React38.useRef(null);
6852
6872
  const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
6853
- const body = /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React37.Fragment, { children: [
6873
+ const body = /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React38.Fragment, { children: [
6854
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 }) }),
6855
6875
  showScore ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
6856
6876
  ] });
@@ -6869,7 +6889,7 @@ function ScoreMeter({
6869
6889
  }
6870
6890
  );
6871
6891
  }
6872
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React37.Fragment, { children: [
6892
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React38.Fragment, { children: [
6873
6893
  /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
6874
6894
  "button",
6875
6895
  {
@@ -6900,11 +6920,11 @@ function ScoreMeter({
6900
6920
  }
6901
6921
 
6902
6922
  // src/components/actions/inlinePanel.tsx
6903
- var React38 = __toESM(require("react"), 1);
6923
+ var React39 = __toESM(require("react"), 1);
6904
6924
  var import_jsx_runtime60 = require("react/jsx-runtime");
6905
6925
  function useInlinePanel() {
6906
- const [open2, setOpen] = React38.useState(false);
6907
- const ref = React38.useRef(null);
6926
+ const [open2, setOpen] = React39.useState(false);
6927
+ const ref = React39.useRef(null);
6908
6928
  return { open: open2, setOpen, ref };
6909
6929
  }
6910
6930
  function InlinePanelSurface({ panel, align = "right", ...popover }) {
@@ -7075,7 +7095,7 @@ function SortMenu({
7075
7095
  }
7076
7096
 
7077
7097
  // src/components/data/StepList.tsx
7078
- var React39 = __toESM(require("react"), 1);
7098
+ var React40 = __toESM(require("react"), 1);
7079
7099
  var import_jsx_runtime62 = require("react/jsx-runtime");
7080
7100
  var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
7081
7101
  function StepList({
@@ -7089,9 +7109,9 @@ function StepList({
7089
7109
  className = "",
7090
7110
  active = false
7091
7111
  }) {
7092
- const [openState, setOpenState] = React39.useState(defaultOpen);
7112
+ const [openState, setOpenState] = React40.useState(defaultOpen);
7093
7113
  const open2 = openProp == null ? openState : openProp;
7094
- const [expanded, setExpanded] = React39.useState({});
7114
+ const [expanded, setExpanded] = React40.useState({});
7095
7115
  if (!steps.length) return null;
7096
7116
  const running = steps.some((s) => s.status === "running");
7097
7117
  const failed = steps.filter((s) => s.status === "error").length;
@@ -7149,7 +7169,7 @@ function StepList({
7149
7169
  }
7150
7170
 
7151
7171
  // src/components/data/VirtualList.tsx
7152
- var React40 = __toESM(require("react"), 1);
7172
+ var React41 = __toESM(require("react"), 1);
7153
7173
  var import_jsx_runtime63 = require("react/jsx-runtime");
7154
7174
  var VIRTUAL_LIST_BUFFER_ROWS = 20;
7155
7175
  var VIRTUAL_LIST_ROW_GAP = 6;
@@ -7201,35 +7221,35 @@ function VirtualList({
7201
7221
  className = "",
7202
7222
  style
7203
7223
  }) {
7204
- const [scrollTop, setScrollTop] = React40.useState(0);
7205
- const loaded = React40.useMemo(
7224
+ const [scrollTop, setScrollTop] = React41.useState(0);
7225
+ const loaded = React41.useMemo(
7206
7226
  () => ({ firstItemIndex, count: items.length }),
7207
7227
  [firstItemIndex, items.length]
7208
7228
  );
7209
7229
  const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
7210
7230
  const bandKey = firstItemIndex + ":" + items.length;
7211
- const win = React40.useMemo(
7231
+ const win = React41.useMemo(
7212
7232
  () => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
7213
7233
  [scrollTop, height, itemHeight, total, loaded]
7214
7234
  );
7215
- const need = React40.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
7235
+ const need = React41.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
7216
7236
  const wantStart = need.start && hasMore?.start !== false;
7217
7237
  const wantEnd = need.end && hasMore?.end !== false;
7218
7238
  const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
7219
7239
  const askKey = bandKey + "@" + bucket2;
7220
- const asked = React40.useRef({ start: null, end: null });
7221
- React40.useEffect(() => {
7240
+ const asked = React41.useRef({ start: null, end: null });
7241
+ React41.useEffect(() => {
7222
7242
  if (loading || !wantStart || asked.current.start === askKey) return;
7223
7243
  asked.current.start = askKey;
7224
7244
  onNeedMore("start", win);
7225
7245
  }, [wantStart, loading, askKey, onNeedMore, win]);
7226
- React40.useEffect(() => {
7246
+ React41.useEffect(() => {
7227
7247
  if (loading || !wantEnd || asked.current.end === askKey) return;
7228
7248
  asked.current.end = askKey;
7229
7249
  onNeedMore("end", win);
7230
7250
  }, [wantEnd, loading, askKey, onNeedMore, win]);
7231
- const lastKeysRef = React40.useRef(null);
7232
- const newKeys = React40.useMemo(() => {
7251
+ const lastKeysRef = React41.useRef(null);
7252
+ const newKeys = React41.useMemo(() => {
7233
7253
  const prev = lastKeysRef.current;
7234
7254
  if (!prev) return /* @__PURE__ */ new Set();
7235
7255
  const fresh = /* @__PURE__ */ new Set();
@@ -7239,7 +7259,7 @@ function VirtualList({
7239
7259
  }
7240
7260
  return fresh;
7241
7261
  }, [items]);
7242
- React40.useEffect(() => {
7262
+ React41.useEffect(() => {
7243
7263
  lastKeysRef.current = new Set(items.map(keyOf));
7244
7264
  }, [items]);
7245
7265
  const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
@@ -7284,7 +7304,7 @@ function VirtualList({
7284
7304
  }
7285
7305
 
7286
7306
  // src/components/data/EntityRow.tsx
7287
- var React41 = __toESM(require("react"), 1);
7307
+ var React42 = __toESM(require("react"), 1);
7288
7308
  var import_jsx_runtime64 = require("react/jsx-runtime");
7289
7309
  var ENTITY_ROW_METRIC_WIDTH = 74;
7290
7310
  var METRIC_TONE_COLOR = {
@@ -7297,7 +7317,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
7297
7317
  const key = m.id || m.label || i;
7298
7318
  const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
7299
7319
  const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
7300
- const content = /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(React41.Fragment, { children: [
7320
+ const content = /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(React42.Fragment, { children: [
7301
7321
  m.icon ? /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
7302
7322
  /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
7303
7323
  /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-sr", children: " " + m.label })
@@ -7389,7 +7409,7 @@ function EntityRow({
7389
7409
  }
7390
7410
 
7391
7411
  // src/components/data/TransferList.tsx
7392
- var React42 = __toESM(require("react"), 1);
7412
+ var React43 = __toESM(require("react"), 1);
7393
7413
  var import_react_dom6 = require("react-dom");
7394
7414
 
7395
7415
  // src/components/forms/Input.tsx
@@ -7495,12 +7515,12 @@ function TransferList({
7495
7515
  listHeight = 440,
7496
7516
  className = ""
7497
7517
  }) {
7498
- const [drag, setDrag] = React42.useState(null);
7499
- const [dragOverSide, setDragOverSide] = React42.useState(null);
7500
- const dragRef = React42.useRef(null);
7501
- const armedRef = React42.useRef(null);
7502
- const sideRefs = React42.useRef({ left: null, right: null });
7503
- 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) => {
7504
7524
  for (const side of ["left", "right"]) {
7505
7525
  const el = sideRefs.current[side];
7506
7526
  if (!el) continue;
@@ -7509,7 +7529,7 @@ function TransferList({
7509
7529
  }
7510
7530
  return null;
7511
7531
  }, []);
7512
- const findItem = React42.useCallback(
7532
+ const findItem = React43.useCallback(
7513
7533
  (side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
7514
7534
  [left.items, right.items, keyOf]
7515
7535
  );
@@ -7531,7 +7551,7 @@ function TransferList({
7531
7551
  height: rect.height
7532
7552
  };
7533
7553
  };
7534
- React42.useEffect(() => {
7554
+ React43.useEffect(() => {
7535
7555
  const onMovePointer = (e) => {
7536
7556
  const armed = armedRef.current;
7537
7557
  if (!armed || e.pointerId !== armed.pointerId) return;
@@ -7584,7 +7604,7 @@ function TransferList({
7584
7604
  window.removeEventListener("pointercancel", endDrag);
7585
7605
  };
7586
7606
  }, [hitTestSide, findItem, onMove]);
7587
- React42.useEffect(() => {
7607
+ React43.useEffect(() => {
7588
7608
  if (!drag || typeof document === "undefined") return;
7589
7609
  const prev = document.body.style.userSelect;
7590
7610
  document.body.style.userSelect = "none";
@@ -7701,7 +7721,7 @@ function FactList({ facts = [], className = "", ...rest }) {
7701
7721
  }
7702
7722
 
7703
7723
  // src/components/data/USChoropleth.tsx
7704
- var React44 = __toESM(require("react"), 1);
7724
+ var React45 = __toESM(require("react"), 1);
7705
7725
  init_usStates();
7706
7726
 
7707
7727
  // src/components/data/usChoropleth/mapBox.ts
@@ -7768,11 +7788,11 @@ function buildChoroplethModel(values, topN, givenTotal) {
7768
7788
  }
7769
7789
 
7770
7790
  // src/components/data/usChoropleth/useUsStateShapes.ts
7771
- var React43 = __toESM(require("react"), 1);
7791
+ var React44 = __toESM(require("react"), 1);
7772
7792
  function useUsStateShapes() {
7773
- const [token, setToken] = React43.useState(0);
7774
- const [settled, setSettled] = React43.useState(null);
7775
- React43.useEffect(() => {
7793
+ const [token, setToken] = React44.useState(0);
7794
+ const [settled, setSettled] = React44.useState(null);
7795
+ React44.useEffect(() => {
7776
7796
  let current2 = true;
7777
7797
  Promise.resolve().then(() => (init_usStateShapes(), usStateShapes_exports)).then(({ STATE_SHAPES: STATE_SHAPES2 }) => {
7778
7798
  if (current2) setSettled({ token, state: { status: "ready", shapes: STATE_SHAPES2 } });
@@ -7814,7 +7834,7 @@ function nextCode(key, from) {
7814
7834
  }
7815
7835
  function StateMap({ shapes, model, figures, label, formatReadout }) {
7816
7836
  const tip = useTooltip();
7817
- const [stop, setStop] = React44.useState(US_STATE_CODES[0]);
7837
+ const [stop, setStop] = React45.useState(US_STATE_CODES[0]);
7818
7838
  const onKeyDown = (event) => {
7819
7839
  const from = event.target.getAttribute("data-state");
7820
7840
  const to = from && nextCode(event.key, from);
@@ -7862,8 +7882,8 @@ function StateTable({ model, valueLabel, formatValue }) {
7862
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 }) });
7863
7883
  }
7864
7884
  function USChoropleth({ values, label, valueLabel, formatValue, formatReadout, topN, total, className = "" }) {
7865
- const model = React44.useMemo(() => buildChoroplethModel(values, topN ?? 0, total), [values, topN, total]);
7866
- 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]);
7867
7887
  const { state, retry } = useUsStateShapes();
7868
7888
  return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: ["fd-uschoro", className].filter(Boolean).join(" "), children: [
7869
7889
  /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fd-uschoro-layout", children: [
@@ -7901,11 +7921,11 @@ function USChoropleth({ values, label, valueLabel, formatValue, formatReadout, t
7901
7921
  init_usStates();
7902
7922
 
7903
7923
  // src/components/forms/Checkbox.tsx
7904
- var React45 = __toESM(require("react"), 1);
7924
+ var React46 = __toESM(require("react"), 1);
7905
7925
  var import_jsx_runtime70 = require("react/jsx-runtime");
7906
7926
  function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
7907
- const ref = React45.useRef(null);
7908
- React45.useEffect(() => {
7927
+ const ref = React46.useRef(null);
7928
+ React46.useEffect(() => {
7909
7929
  if (ref.current) ref.current.indeterminate = indeterminate;
7910
7930
  }, [indeterminate]);
7911
7931
  return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
@@ -7952,7 +7972,7 @@ function Switch({ label, description, className = "", ...rest }) {
7952
7972
  }
7953
7973
 
7954
7974
  // src/components/forms/Select.tsx
7955
- var React46 = __toESM(require("react"), 1);
7975
+ var React47 = __toESM(require("react"), 1);
7956
7976
  var import_jsx_runtime73 = require("react/jsx-runtime");
7957
7977
  var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
7958
7978
  function Select({
@@ -7980,12 +8000,12 @@ function Select({
7980
8000
  const isOn = (v) => multiple ? vals.includes(v) : v === value;
7981
8001
  const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
7982
8002
  const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id, hiddenLabel);
7983
- const [open2, setOpen] = React46.useState(false);
7984
- const [q, setQ] = React46.useState("");
7985
- const rootRef = React46.useRef(null);
7986
- const boxRef = React46.useRef(null);
7987
- const listRef = React46.useRef(null);
7988
- 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 });
7989
8009
  const selected = multiple ? null : opts.find((o) => o.value === value);
7990
8010
  const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
7991
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;
@@ -8121,7 +8141,7 @@ function Select({
8121
8141
  ),
8122
8142
  q ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
8123
8143
  ] }) : void 0,
8124
- footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(React46.Fragment, { children: [
8144
+ footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(React47.Fragment, { children: [
8125
8145
  /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
8126
8146
  "button",
8127
8147
  {
@@ -8152,7 +8172,7 @@ function Select({
8152
8172
  'Nothing matches "',
8153
8173
  q,
8154
8174
  '".'
8155
- ] }) : 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: [
8156
8176
  grp.g ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
8157
8177
  grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
8158
8178
  "button",
@@ -8189,7 +8209,7 @@ function Select({
8189
8209
  }
8190
8210
 
8191
8211
  // src/components/forms/TimePicker.tsx
8192
- var React47 = __toESM(require("react"), 1);
8212
+ var React48 = __toESM(require("react"), 1);
8193
8213
  var import_jsx_runtime74 = require("react/jsx-runtime");
8194
8214
  var pad = (n) => String(n).padStart(2, "0");
8195
8215
  function ClockFace({ value = "09:00", onChange }) {
@@ -8198,9 +8218,9 @@ function ClockFace({ value = "09:00", onChange }) {
8198
8218
  if (isNaN(m)) m = 0;
8199
8219
  const pm = h24 >= 12;
8200
8220
  const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
8201
- const [mode2, setMode] = React47.useState("h");
8202
- const faceRef = React47.useRef(null);
8203
- const dragging = React47.useRef(false);
8221
+ const [mode2, setMode] = React48.useState("h");
8222
+ const faceRef = React48.useRef(null);
8223
+ const dragging = React48.useRef(false);
8204
8224
  const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
8205
8225
  const R = 108, NR = 80;
8206
8226
  const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
@@ -8273,9 +8293,9 @@ function ClockFace({ value = "09:00", onChange }) {
8273
8293
  }
8274
8294
  function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
8275
8295
  const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
8276
- const [open2, setOpen] = React47.useState(false);
8277
- const rootRef = React47.useRef(null);
8278
- const boxRef = React47.useRef(null);
8296
+ const [open2, setOpen] = React48.useState(false);
8297
+ const rootRef = React48.useRef(null);
8298
+ const boxRef = React48.useRef(null);
8279
8299
  const disp = () => {
8280
8300
  if (!value) return "";
8281
8301
  const [h, m] = value.split(":").map(Number);
@@ -8318,7 +8338,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
8318
8338
  offset: 6,
8319
8339
  width: 262,
8320
8340
  role: "presentation",
8321
- footer: /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(React47.Fragment, { children: [
8341
+ footer: /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(React48.Fragment, { children: [
8322
8342
  /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
8323
8343
  "button",
8324
8344
  {
@@ -8346,7 +8366,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
8346
8366
  }
8347
8367
 
8348
8368
  // src/components/forms/Slider.tsx
8349
- var React48 = __toESM(require("react"), 1);
8369
+ var React49 = __toESM(require("react"), 1);
8350
8370
  var import_jsx_runtime75 = require("react/jsx-runtime");
8351
8371
  function Slider({
8352
8372
  label,
@@ -8364,7 +8384,7 @@ function Slider({
8364
8384
  ...rest
8365
8385
  }) {
8366
8386
  const fieldId = useFieldId(id);
8367
- const [dragging, setDragging] = React48.useState(false);
8387
+ const [dragging, setDragging] = React49.useState(false);
8368
8388
  const v = value === void 0 ? min : Number(value);
8369
8389
  const pct = max === min ? 0 : (v - min) / (max - min) * 100;
8370
8390
  return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
@@ -8398,7 +8418,7 @@ function Slider({
8398
8418
  }
8399
8419
 
8400
8420
  // src/components/forms/RangeSlider.tsx
8401
- var React49 = __toESM(require("react"), 1);
8421
+ var React50 = __toESM(require("react"), 1);
8402
8422
  var import_jsx_runtime76 = require("react/jsx-runtime");
8403
8423
  function RangeSlider({
8404
8424
  label,
@@ -8418,9 +8438,9 @@ function RangeSlider({
8418
8438
  }) {
8419
8439
  const fmt2 = format || ((v) => String(v));
8420
8440
  const [a, b] = value || [min, max];
8421
- const [drag, setDrag] = React49.useState(null);
8422
- const [focus, setFocus] = React49.useState(null);
8423
- 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);
8424
8444
  const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
8425
8445
  const clampPair = (i, v) => {
8426
8446
  v = Math.min(max, Math.max(min, Math.round(v / step) * step));
@@ -8435,7 +8455,7 @@ function RangeSlider({
8435
8455
  const r = railRef.current.getBoundingClientRect();
8436
8456
  return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
8437
8457
  };
8438
- React49.useEffect(() => {
8458
+ React50.useEffect(() => {
8439
8459
  if (drag === null) return;
8440
8460
  const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
8441
8461
  const upH = () => setDrag(null);
@@ -8516,7 +8536,7 @@ function RangeSlider({
8516
8536
  /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
8517
8537
  /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-range-rail", ref: railRef }),
8518
8538
  /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
8519
- 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: [
8520
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) + "%" } }),
8521
8541
  m.label ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
8522
8542
  ] }, m.value)),
@@ -8545,7 +8565,7 @@ function RangeSlider({
8545
8565
  }
8546
8566
 
8547
8567
  // src/components/forms/Dropzone.tsx
8548
- var React50 = __toESM(require("react"), 1);
8568
+ var React51 = __toESM(require("react"), 1);
8549
8569
  var import_jsx_runtime77 = require("react/jsx-runtime");
8550
8570
  function Dropzone({
8551
8571
  onFiles,
@@ -8560,8 +8580,8 @@ function Dropzone({
8560
8580
  className = "",
8561
8581
  style
8562
8582
  }) {
8563
- const [over, setOver] = React50.useState(false);
8564
- const depth = React50.useRef(0);
8583
+ const [over, setOver] = React51.useState(false);
8584
+ const depth = React51.useRef(0);
8565
8585
  const has = (e) => {
8566
8586
  const dt = e.dataTransfer;
8567
8587
  if (!dt) return false;
@@ -8623,8 +8643,8 @@ function FilePickButton({
8623
8643
  className = "",
8624
8644
  children
8625
8645
  }) {
8626
- const ref = React50.useRef(null);
8627
- 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: [
8628
8648
  /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8629
8649
  "button",
8630
8650
  {
@@ -8657,10 +8677,10 @@ function FilePickButton({
8657
8677
  }
8658
8678
  function useStagedFiles(upload, opts) {
8659
8679
  const o = opts || {};
8660
- const [items, setItems] = React50.useState([]);
8661
- const controllers = React50.useRef({});
8680
+ const [items, setItems] = React51.useState([]);
8681
+ const controllers = React51.useRef({});
8662
8682
  const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
8663
- const run = React50.useCallback((att) => {
8683
+ const run = React51.useCallback((att) => {
8664
8684
  if (!upload) return;
8665
8685
  const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
8666
8686
  controllers.current[att.id] = ac;
@@ -8677,14 +8697,14 @@ function useStagedFiles(upload, opts) {
8677
8697
  delete controllers.current[att.id];
8678
8698
  });
8679
8699
  }, [upload]);
8680
- const add = React50.useCallback((files) => {
8700
+ const add = React51.useCallback((files) => {
8681
8701
  if (!upload) return [];
8682
8702
  const atts = Array.from(files).map((f) => toAttachment(f));
8683
8703
  setItems((list) => list.concat(atts));
8684
8704
  atts.forEach(run);
8685
8705
  return atts;
8686
8706
  }, [upload, run]);
8687
- const remove = React50.useCallback((att) => {
8707
+ const remove = React51.useCallback((att) => {
8688
8708
  const ac = controllers.current[att.id];
8689
8709
  if (ac) {
8690
8710
  try {
@@ -8695,10 +8715,10 @@ function useStagedFiles(upload, opts) {
8695
8715
  }
8696
8716
  setItems((list) => list.filter((f) => f.id !== att.id));
8697
8717
  }, []);
8698
- const retry = React50.useCallback((att) => {
8718
+ const retry = React51.useCallback((att) => {
8699
8719
  run(att);
8700
8720
  }, [run]);
8701
- const clear = React50.useCallback(() => {
8721
+ const clear = React51.useCallback(() => {
8702
8722
  Object.values(controllers.current).forEach((ac) => {
8703
8723
  try {
8704
8724
  ac && ac.abort();
@@ -8822,7 +8842,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
8822
8842
  }
8823
8843
 
8824
8844
  // src/components/forms/MarkdownEditor.tsx
8825
- var React51 = __toESM(require("react"), 1);
8845
+ var React52 = __toESM(require("react"), 1);
8826
8846
  var import_jsx_runtime79 = require("react/jsx-runtime");
8827
8847
  var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
8828
8848
  var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
@@ -9036,7 +9056,7 @@ function syncDom(root, value) {
9036
9056
  while (root.children.length > lines.length) root.removeChild(root.lastChild);
9037
9057
  }
9038
9058
  var LIST_CONT = RE_LI;
9039
- var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
9059
+ var MarkdownEditor = React52.forwardRef(function MarkdownEditor2({
9040
9060
  value = "",
9041
9061
  onChange,
9042
9062
  onSubmit,
@@ -9055,10 +9075,10 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
9055
9075
  className = "",
9056
9076
  id
9057
9077
  }, ref) {
9058
- const boxRef = React51.useRef(null);
9059
- const composing = React51.useRef(false);
9060
- const pendingCaret = React51.useRef(null);
9061
- React51.useLayoutEffect(() => {
9078
+ const boxRef = React52.useRef(null);
9079
+ const composing = React52.useRef(false);
9080
+ const pendingCaret = React52.useRef(null);
9081
+ React52.useLayoutEffect(() => {
9062
9082
  const root = boxRef.current;
9063
9083
  if (!root || composing.current) return;
9064
9084
  const active = document.activeElement === root || root.contains(document.activeElement);
@@ -9067,7 +9087,7 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
9067
9087
  pendingCaret.current = null;
9068
9088
  if (active && caret != null) placeCaret(root, caret);
9069
9089
  }, [value]);
9070
- React51.useEffect(() => {
9090
+ React52.useEffect(() => {
9071
9091
  if (autoFocus && boxRef.current) boxRef.current.focus();
9072
9092
  }, [autoFocus]);
9073
9093
  const caretNow = () => {
@@ -9134,8 +9154,8 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
9134
9154
  api.replaceRange(from, to, next, from + next.length);
9135
9155
  }
9136
9156
  };
9137
- React51.useImperativeHandle(ref, () => api);
9138
- const caretAtKeydown = React51.useRef(-1);
9157
+ React52.useImperativeHandle(ref, () => api);
9158
+ const caretAtKeydown = React52.useRef(-1);
9139
9159
  function detect(text, caret) {
9140
9160
  if (!onTrigger) return;
9141
9161
  const upto = text.slice(0, caret);
@@ -9288,7 +9308,7 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
9288
9308
  });
9289
9309
 
9290
9310
  // src/components/forms/CodeEditor.tsx
9291
- var React52 = __toESM(require("react"), 1);
9311
+ var React53 = __toESM(require("react"), 1);
9292
9312
  var import_view = require("@codemirror/view");
9293
9313
  var import_state = require("@codemirror/state");
9294
9314
  var import_commands = require("@codemirror/commands");
@@ -9392,16 +9412,16 @@ function CodeEditor({
9392
9412
  const fieldId = useFieldId(id);
9393
9413
  const descId = fieldId + "-desc";
9394
9414
  const liveId = fieldId + "-live";
9395
- const hostRef = React52.useRef(null);
9396
- const viewRef = React52.useRef(null);
9397
- const valueRef = React52.useRef(value);
9398
- 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);
9399
9419
  onChangeRef.current = onChange;
9400
- const editableCompartment = React52.useRef(new import_state.Compartment()).current;
9401
- const attributesCompartment = React52.useRef(new import_state.Compartment()).current;
9402
- 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);
9403
9423
  errorRef.current = error;
9404
- const diagnosticsCountRef = React52.useRef(diagnostics.length);
9424
+ const diagnosticsCountRef = React53.useRef(diagnostics.length);
9405
9425
  diagnosticsCountRef.current = diagnostics.length;
9406
9426
  function contentAttributes() {
9407
9427
  return {
@@ -9411,7 +9431,7 @@ function CodeEditor({
9411
9431
  ...label ? { "aria-label": label } : {}
9412
9432
  };
9413
9433
  }
9414
- React52.useEffect(() => {
9434
+ React53.useEffect(() => {
9415
9435
  const host2 = hostRef.current;
9416
9436
  if (!host2) return;
9417
9437
  const updateListener = import_view.EditorView.updateListener.of((update) => {
@@ -9453,7 +9473,7 @@ function CodeEditor({
9453
9473
  viewRef.current = null;
9454
9474
  };
9455
9475
  }, []);
9456
- React52.useEffect(() => {
9476
+ React53.useEffect(() => {
9457
9477
  const view = viewRef.current;
9458
9478
  if (!view) return;
9459
9479
  const current2 = view.state.doc.toString();
@@ -9462,12 +9482,12 @@ function CodeEditor({
9462
9482
  }
9463
9483
  valueRef.current = value;
9464
9484
  }, [value]);
9465
- React52.useEffect(() => {
9485
+ React53.useEffect(() => {
9466
9486
  const view = viewRef.current;
9467
9487
  if (!view) return;
9468
9488
  view.dispatch({ effects: editableCompartment.reconfigure(import_view.EditorView.editable.of(!disabled)) });
9469
9489
  }, [disabled, editableCompartment]);
9470
- React52.useEffect(() => {
9490
+ React53.useEffect(() => {
9471
9491
  const view = viewRef.current;
9472
9492
  if (!view) return;
9473
9493
  view.dispatch({
@@ -9525,11 +9545,11 @@ function CodeEditor({
9525
9545
  }
9526
9546
 
9527
9547
  // src/components/forms/RadioGroup.tsx
9528
- var React53 = __toESM(require("react"), 1);
9548
+ var React54 = __toESM(require("react"), 1);
9529
9549
  var import_jsx_runtime81 = require("react/jsx-runtime");
9530
9550
  function RadioGroup({ label, labelledBy, options, value, onChange, card = false, disabled = false, name, className = "" }) {
9531
- const autoName = React53.useId();
9532
- const labelId = React53.useId();
9551
+ const autoName = React54.useId();
9552
+ const labelId = React54.useId();
9533
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: [
9534
9554
  labelledBy === void 0 && /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { id: labelId, className: "fd-radiogroup-label", children: label }),
9535
9555
  options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
@@ -9557,16 +9577,16 @@ function Fieldset({ busy = false, className = "", ...rest }) {
9557
9577
  }
9558
9578
 
9559
9579
  // src/components/platform/AccountMenu.tsx
9560
- var React55 = __toESM(require("react"), 1);
9580
+ var React56 = __toESM(require("react"), 1);
9561
9581
 
9562
9582
  // src/kits/sessionContext.tsx
9563
- var React54 = __toESM(require("react"), 1);
9564
- var SessionContext = React54.createContext(null);
9583
+ var React55 = __toESM(require("react"), 1);
9584
+ var SessionContext = React55.createContext(null);
9565
9585
  function SessionProvider({ value, children }) {
9566
- return React54.createElement(SessionContext.Provider, { value }, children);
9586
+ return React55.createElement(SessionContext.Provider, { value }, children);
9567
9587
  }
9568
9588
  function useSessionContext() {
9569
- const ctx = React54.useContext(SessionContext);
9589
+ const ctx = React55.useContext(SessionContext);
9570
9590
  if (!ctx) {
9571
9591
  throw new Error(
9572
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."
@@ -9606,11 +9626,11 @@ function AccountMenu({
9606
9626
  ...rest
9607
9627
  }) {
9608
9628
  const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
9609
- const [open2, setOpen] = React55.useState(false);
9610
- const [switching, setSwitching] = React55.useState(false);
9611
- const [signingOut, setSigningOut] = React55.useState(false);
9612
- const [signOutError, setSignOutError] = React55.useState(null);
9613
- 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);
9614
9634
  const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
9615
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);
9616
9636
  const closeMenu = () => {
@@ -9735,13 +9755,13 @@ function AccountMenu({
9735
9755
  }
9736
9756
 
9737
9757
  // src/components/platform/AppSwitcher.tsx
9738
- var React56 = __toESM(require("react"), 1);
9758
+ var React57 = __toESM(require("react"), 1);
9739
9759
  var import_jsx_runtime84 = require("react/jsx-runtime");
9740
9760
  function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
9741
9761
  const { apps: contextApps } = useSessionContext();
9742
9762
  const apps = appsProp ?? contextApps ?? [];
9743
- const [open2, setOpen] = React56.useState(false);
9744
- const anchorRef = React56.useRef(null);
9763
+ const [open2, setOpen] = React57.useState(false);
9764
+ const anchorRef = React57.useRef(null);
9745
9765
  if (!apps.length) return null;
9746
9766
  const items = apps.map((app) => ({
9747
9767
  id: app.key,
@@ -9755,7 +9775,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
9755
9775
  window.location.href = app.url;
9756
9776
  }
9757
9777
  }));
9758
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(React56.Fragment, { children: [
9778
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(React57.Fragment, { children: [
9759
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)(
9760
9780
  IconButton,
9761
9781
  {
@@ -9784,10 +9804,10 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
9784
9804
  }
9785
9805
 
9786
9806
  // src/components/platform/AppearanceMenu.tsx
9787
- var React59 = __toESM(require("react"), 1);
9807
+ var React60 = __toESM(require("react"), 1);
9788
9808
 
9789
9809
  // src/kits/appearance.ts
9790
- var React57 = __toESM(require("react"), 1);
9810
+ var React58 = __toESM(require("react"), 1);
9791
9811
  var DEFAULT_STORAGE_KEY = "fd-appearance";
9792
9812
  var DEFAULT_PREFS = {
9793
9813
  theme: "system",
@@ -9899,8 +9919,8 @@ function watchAppearance(store, root = document.documentElement) {
9899
9919
  };
9900
9920
  }
9901
9921
  function useAppearancePrefs(store) {
9902
- const prefs = React57.useSyncExternalStore(store.subscribe, store.getSnapshot);
9903
- const update = React57.useCallback(
9922
+ const prefs = React58.useSyncExternalStore(store.subscribe, store.getSnapshot);
9923
+ const update = React58.useCallback(
9904
9924
  (patch) => {
9905
9925
  store.write({ ...store.getSnapshot(), ...patch });
9906
9926
  },
@@ -9910,15 +9930,15 @@ function useAppearancePrefs(store) {
9910
9930
  }
9911
9931
 
9912
9932
  // src/components/platform/AppearanceProvider.tsx
9913
- var React58 = __toESM(require("react"), 1);
9933
+ var React59 = __toESM(require("react"), 1);
9914
9934
  var import_jsx_runtime85 = require("react/jsx-runtime");
9915
- var AppearanceStoreContext = React58.createContext(null);
9935
+ var AppearanceStoreContext = React59.createContext(null);
9916
9936
  function AppearanceProvider({ store, children }) {
9917
- React58.useLayoutEffect(() => watchAppearance(store), [store]);
9937
+ React59.useLayoutEffect(() => watchAppearance(store), [store]);
9918
9938
  return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(AppearanceStoreContext.Provider, { value: store, children });
9919
9939
  }
9920
9940
  function useAppearanceStore() {
9921
- const store = React58.useContext(AppearanceStoreContext);
9941
+ const store = React59.useContext(AppearanceStoreContext);
9922
9942
  if (!store) throw new Error("AppearanceMenu and useAppearanceStore must be rendered inside an <AppearanceProvider>.");
9923
9943
  return store;
9924
9944
  }
@@ -9938,10 +9958,10 @@ var TEXT_SCALE_OPTIONS = [
9938
9958
  ];
9939
9959
  function AppearanceMenu({ className = "" }) {
9940
9960
  const [prefs, update] = useAppearancePrefs(useAppearanceStore());
9941
- const [open2, setOpen] = React59.useState(false);
9942
- const anchorRef = React59.useRef(null);
9961
+ const [open2, setOpen] = React60.useState(false);
9962
+ const anchorRef = React60.useRef(null);
9943
9963
  const patch = (p) => update(p);
9944
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(React59.Fragment, { children: [
9964
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(React60.Fragment, { children: [
9945
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)(
9946
9966
  IconButton,
9947
9967
  {
@@ -10010,14 +10030,14 @@ function AppearanceMenu({ className = "" }) {
10010
10030
  }
10011
10031
 
10012
10032
  // src/components/platform/ApiSpecBrowser.tsx
10013
- var React60 = __toESM(require("react"), 1);
10033
+ var React61 = __toESM(require("react"), 1);
10014
10034
  var import_jsx_runtime87 = require("react/jsx-runtime");
10015
10035
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
10016
10036
  function Json({ obj }) {
10017
10037
  return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
10018
10038
  }
10019
10039
  function Endpoint({ s, onRequest }) {
10020
- const [tried, setTried] = React60.useState(null);
10040
+ const [tried, setTried] = React61.useState(null);
10021
10041
  const run = async () => {
10022
10042
  setTried("busy");
10023
10043
  const t0 = (window.performance || Date).now();
@@ -10090,10 +10110,10 @@ function ApiSpecBrowser({
10090
10110
  className = "",
10091
10111
  ...rest
10092
10112
  }) {
10093
- const [q, setQ] = React60.useState("");
10094
- const [method, setMethod] = React60.useState(null);
10095
- const [mod, setMod] = React60.useState(null);
10096
- 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);
10097
10117
  const activeModule = modules && modules.find((m) => m.id === mod);
10098
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())));
10099
10119
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
@@ -10172,7 +10192,7 @@ function ApiSpecBrowser({
10172
10192
  }
10173
10193
 
10174
10194
  // src/components/platform/ProfilePage.tsx
10175
- var React61 = __toESM(require("react"), 1);
10195
+ var React62 = __toESM(require("react"), 1);
10176
10196
  var import_jsx_runtime88 = require("react/jsx-runtime");
10177
10197
  function fieldInitialValue(field, user) {
10178
10198
  if (field.value) return field.value(user);
@@ -10208,21 +10228,21 @@ function ProfilePage({
10208
10228
  }) {
10209
10229
  const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
10210
10230
  const user = userProp || sessionUser;
10211
- const initialFieldValues = React61.useMemo(() => {
10231
+ const initialFieldValues = React62.useMemo(() => {
10212
10232
  const values2 = {};
10213
10233
  for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
10214
10234
  return values2;
10215
10235
  }, [user.id, fields]);
10216
- const initialNotify = React61.useMemo(() => {
10236
+ const initialNotify = React62.useMemo(() => {
10217
10237
  const values2 = {};
10218
10238
  for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
10219
10239
  return values2;
10220
10240
  }, [user.id, notifications]);
10221
- const [values, setValues] = React61.useState(initialFieldValues);
10222
- const [notify, setNotify] = React61.useState(initialNotify);
10223
- const [saving, setSaving] = React61.useState(false);
10224
- const [saved, setSaved] = React61.useState(false);
10225
- 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);
10226
10246
  if (user.id !== prevUserId) {
10227
10247
  setPrevUserId(user.id);
10228
10248
  setValues(initialFieldValues);
@@ -10410,7 +10430,7 @@ function ProfilePage({
10410
10430
  }
10411
10431
 
10412
10432
  // src/components/platform/SessionScreen.tsx
10413
- var React62 = __toESM(require("react"), 1);
10433
+ var React63 = __toESM(require("react"), 1);
10414
10434
  var import_jsx_runtime89 = require("react/jsx-runtime");
10415
10435
  var COPY = {
10416
10436
  "signing-in": { busy: "Signing you in\u2026" },
@@ -10424,13 +10444,13 @@ function SessionScreen({ kind, error, onRetry, productName }) {
10424
10444
  const copy = COPY[kind];
10425
10445
  const busyMessage = "busy" in copy ? copy.busy : null;
10426
10446
  const failureTitle = "failure" in copy ? copy.failure : null;
10427
- const [announced, setAnnounced] = React62.useState("");
10428
- React62.useEffect(() => {
10447
+ const [announced, setAnnounced] = React63.useState("");
10448
+ React63.useEffect(() => {
10429
10449
  setAnnounced(busyMessage ?? "");
10430
10450
  }, [busyMessage]);
10431
- const titleRef = React62.useRef(null);
10451
+ const titleRef = React63.useRef(null);
10432
10452
  const failed = failureTitle !== null;
10433
- React62.useEffect(() => {
10453
+ React63.useEffect(() => {
10434
10454
  titleRef.current?.focus({ preventScroll: true });
10435
10455
  }, [failed]);
10436
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: [
@@ -10453,10 +10473,10 @@ function SessionScreen({ kind, error, onRetry, productName }) {
10453
10473
  }
10454
10474
 
10455
10475
  // src/components/platform/RoadmapTimeline.tsx
10456
- var React65 = __toESM(require("react"), 1);
10476
+ var React66 = __toESM(require("react"), 1);
10457
10477
 
10458
10478
  // src/kits/session.ts
10459
- var React63 = __toESM(require("react"), 1);
10479
+ var React64 = __toESM(require("react"), 1);
10460
10480
  var PERMISSION_CATALOG = [
10461
10481
  { group: "Plans", items: [
10462
10482
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -12023,8 +12043,8 @@ function roadmap(overrides) {
12023
12043
  };
12024
12044
  }
12025
12045
  function useSession() {
12026
- const [s, setS] = React63.useState(getSession);
12027
- React63.useEffect(() => subscribe(setS), []);
12046
+ const [s, setS] = React64.useState(getSession);
12047
+ React64.useEffect(() => subscribe(setS), []);
12028
12048
  return s;
12029
12049
  }
12030
12050
  var SessionKit = {
@@ -12057,7 +12077,7 @@ var SessionKit = {
12057
12077
  };
12058
12078
  function DemoSessionProvider({ children }) {
12059
12079
  const session = useSession();
12060
- const value = React63.useMemo(
12080
+ const value = React64.useMemo(
12061
12081
  () => ({
12062
12082
  user: session.user,
12063
12083
  roles: session.roles,
@@ -12073,11 +12093,11 @@ function DemoSessionProvider({ children }) {
12073
12093
  }),
12074
12094
  [session]
12075
12095
  );
12076
- return React63.createElement(SessionProvider, { value }, children);
12096
+ return React64.createElement(SessionProvider, { value }, children);
12077
12097
  }
12078
12098
 
12079
12099
  // src/kits/runtime.ts
12080
- var React64 = __toESM(require("react"), 1);
12100
+ var React65 = __toESM(require("react"), 1);
12081
12101
  var WIRED_ENDPOINTS = [
12082
12102
  // Nothing yet. Every id below would come from a real service:
12083
12103
  // "plan.get", "placements.list", …
@@ -12248,8 +12268,8 @@ var RuntimeKit = {
12248
12268
  };
12249
12269
  RuntimeKit.declare(FEATURE_NEEDS);
12250
12270
  function useRuntimeMode() {
12251
- const [m, setM] = React64.useState(RuntimeKit.getMode());
12252
- React64.useEffect(() => RuntimeKit.subscribe(setM), []);
12271
+ const [m, setM] = React65.useState(RuntimeKit.getMode());
12272
+ React65.useEffect(() => RuntimeKit.subscribe(setM), []);
12253
12273
  return m;
12254
12274
  }
12255
12275
  function useFeatureStatus(key) {
@@ -12332,12 +12352,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
12332
12352
  }
12333
12353
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12334
12354
  const session = SessionKit.useSession();
12335
- const [project, setProject] = React65.useState("");
12336
- const [q, setQ] = React65.useState("");
12337
- const scrollRef = React65.useRef(null);
12338
- const nowRef = React65.useRef(null);
12339
- const rm = React65.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
12340
- 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(() => {
12341
12361
  const m = {};
12342
12362
  rm.items.forEach((i) => {
12343
12363
  m[i.key] = i;
@@ -12346,7 +12366,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12346
12366
  }, [rm]);
12347
12367
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
12348
12368
  const projects = [...new Set(rm.items.map((i) => i.project))];
12349
- React65.useEffect(() => {
12369
+ React66.useEffect(() => {
12350
12370
  let raf1 = 0, raf2 = 0;
12351
12371
  const place = () => {
12352
12372
  const box = scrollRef.current, mark = nowRef.current;
@@ -12420,7 +12440,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12420
12440
  lastPhase = item.phase;
12421
12441
  const inPhase = items.filter((i) => i.phase === item.phase).length;
12422
12442
  const isBoundary = n === firstPending;
12423
- return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(React65.Fragment, { children: [
12443
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(React66.Fragment, { children: [
12424
12444
  showPhase ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "fd-rm-era", children: [
12425
12445
  /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
12426
12446
  /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
@@ -12464,7 +12484,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12464
12484
  }
12465
12485
 
12466
12486
  // src/components/platform/ComingSoon.tsx
12467
- var React66 = __toESM(require("react"), 1);
12487
+ var React67 = __toESM(require("react"), 1);
12468
12488
  var import_react_dom7 = require("react-dom");
12469
12489
  var import_jsx_runtime91 = require("react/jsx-runtime");
12470
12490
  var BYPASS_STORE = "fd.soon.bypass.v1";
@@ -12482,8 +12502,8 @@ function writeBypassed(list) {
12482
12502
  }
12483
12503
  }
12484
12504
  function useBypass(key) {
12485
- const [on, setOn] = React66.useState(() => !!key && readBypassed().indexOf(key) >= 0);
12486
- React66.useEffect(() => {
12505
+ const [on, setOn] = React67.useState(() => !!key && readBypassed().indexOf(key) >= 0);
12506
+ React67.useEffect(() => {
12487
12507
  setOn(!!key && readBypassed().indexOf(key) >= 0);
12488
12508
  }, [key]);
12489
12509
  const set = (next) => {
@@ -12530,9 +12550,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
12530
12550
  ] });
12531
12551
  }
12532
12552
  function useHoverCard(open2) {
12533
- const anchor = React66.useRef(null);
12534
- const [pos, setPos] = React66.useState(null);
12535
- React66.useLayoutEffect(() => {
12553
+ const anchor = React67.useRef(null);
12554
+ const [pos, setPos] = React67.useState(null);
12555
+ React67.useLayoutEffect(() => {
12536
12556
  if (!open2 || !anchor.current) {
12537
12557
  setPos(null);
12538
12558
  return;
@@ -12659,12 +12679,12 @@ function ComingSoon({
12659
12679
  ] });
12660
12680
  }
12661
12681
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
12662
- const [open2, setOpen] = React66.useState(false);
12682
+ const [open2, setOpen] = React67.useState(false);
12663
12683
  const [anchor, pos] = useHoverCard(open2);
12664
- const hoverCardRef = React66.useRef(null);
12684
+ const hoverCardRef = React67.useRef(null);
12665
12685
  const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
12666
12686
  const zIndex = useLayerZIndex(hoverLayer);
12667
- const close2 = React66.useRef(null);
12687
+ const close2 = React67.useRef(null);
12668
12688
  const show = () => {
12669
12689
  if (close2.current) {
12670
12690
  clearTimeout(close2.current);
@@ -12680,7 +12700,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
12680
12700
  setOpen(false);
12681
12701
  }, 140);
12682
12702
  };
12683
- React66.useEffect(() => () => {
12703
+ React67.useEffect(() => () => {
12684
12704
  if (close2.current) clearTimeout(close2.current);
12685
12705
  }, []);
12686
12706
  return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
@@ -13132,7 +13152,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
13132
13152
  }
13133
13153
 
13134
13154
  // src/components/planner/MixGap.tsx
13135
- var React67 = __toESM(require("react"), 1);
13155
+ var React68 = __toESM(require("react"), 1);
13136
13156
  var import_jsx_runtime96 = require("react/jsx-runtime");
13137
13157
  var MIX_GAP_LAYOUT = {
13138
13158
  trackHeight: 30,
@@ -13147,7 +13167,7 @@ function mixGapOffset(value, max) {
13147
13167
  }
13148
13168
  function MixGap({ rows = [], loading = false, className = "" }) {
13149
13169
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
13150
- const [hover, setHover] = React67.useState(null);
13170
+ const [hover, setHover] = React68.useState(null);
13151
13171
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
13152
13172
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
13153
13173
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
@@ -13290,7 +13310,7 @@ function ChannelContribution({
13290
13310
  }
13291
13311
 
13292
13312
  // src/components/planner/BudgetReallocator.tsx
13293
- var React68 = __toESM(require("react"), 1);
13313
+ var React69 = __toESM(require("react"), 1);
13294
13314
  var import_jsx_runtime98 = require("react/jsx-runtime");
13295
13315
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
13296
13316
  function BudgetReallocator({
@@ -13306,8 +13326,8 @@ function BudgetReallocator({
13306
13326
  onCancel,
13307
13327
  className = ""
13308
13328
  }) {
13309
- const [draft, setDraft] = React68.useState(spend);
13310
- React68.useEffect(() => setDraft(spend), [spend]);
13329
+ const [draft, setDraft] = React69.useState(spend);
13330
+ React69.useEffect(() => setDraft(spend), [spend]);
13311
13331
  const dirty = draft !== spend;
13312
13332
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
13313
13333
  const nextBand = bandFor(nextCrp);
@@ -13322,10 +13342,10 @@ function BudgetReallocator({
13322
13342
  setDraft(spend);
13323
13343
  if (onCancel) onCancel();
13324
13344
  };
13325
- const trackRef = React68.useRef(null);
13326
- const chipRef = React68.useRef(null);
13327
- const [chipLeft, setChipLeft] = React68.useState(null);
13328
- React68.useLayoutEffect(() => {
13345
+ const trackRef = React69.useRef(null);
13346
+ const chipRef = React69.useRef(null);
13347
+ const [chipLeft, setChipLeft] = React69.useState(null);
13348
+ React69.useLayoutEffect(() => {
13329
13349
  const track = trackRef.current;
13330
13350
  if (!dirty || !track) {
13331
13351
  setChipLeft(null);
@@ -13513,7 +13533,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
13513
13533
  }
13514
13534
 
13515
13535
  // src/components/planner/PreferenceMeter.tsx
13516
- var React69 = __toESM(require("react"), 1);
13536
+ var React70 = __toESM(require("react"), 1);
13517
13537
  var import_jsx_runtime101 = require("react/jsx-runtime");
13518
13538
  function preferenceScore(criteria) {
13519
13539
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
@@ -13543,7 +13563,7 @@ function PreferenceMeter({
13543
13563
  className = ""
13544
13564
  }) {
13545
13565
  const value = score == null ? preferenceScore(criteria) : score;
13546
- const segments = React69.useMemo(() => preferenceSegments(criteria), [criteria]);
13566
+ const segments = React70.useMemo(() => preferenceSegments(criteria), [criteria]);
13547
13567
  return /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
13548
13568
  ScoreMeter,
13549
13569
  {
@@ -13582,13 +13602,13 @@ function PreferenceMeter({
13582
13602
  }
13583
13603
 
13584
13604
  // src/components/chat/AgentChatPanel.tsx
13585
- var React76 = __toESM(require("react"), 1);
13605
+ var React77 = __toESM(require("react"), 1);
13586
13606
 
13587
13607
  // src/components/chat/chatEngine.ts
13588
- var React71 = __toESM(require("react"), 1);
13608
+ var React72 = __toESM(require("react"), 1);
13589
13609
 
13590
13610
  // src/components/chat/chatStore.ts
13591
- var React70 = __toESM(require("react"), 1);
13611
+ var React71 = __toESM(require("react"), 1);
13592
13612
  var safeStore = {
13593
13613
  get(k) {
13594
13614
  try {
@@ -13617,13 +13637,13 @@ function useChatDraft(owner, contextType, contextId, store = safeStore) {
13617
13637
  if (owner === "") throw new Error("useChatDraft: draftOwner is an empty string; pass the signed-in user's id, or null for no owner.");
13618
13638
  const key = owner === null ? null : draftKey(owner, contextType, contextId);
13619
13639
  const read2 = (k) => k ? store.get(k) || "" : "";
13620
- const [state, setState] = React70.useState(() => ({ key, text: read2(key) }));
13640
+ const [state, setState] = React71.useState(() => ({ key, text: read2(key) }));
13621
13641
  let current2 = state;
13622
13642
  if (state.key !== key) {
13623
13643
  current2 = { key, text: read2(key) };
13624
13644
  setState(current2);
13625
13645
  }
13626
- const setText = React70.useCallback((text) => {
13646
+ const setText = React71.useCallback((text) => {
13627
13647
  if (key) {
13628
13648
  if (text) {
13629
13649
  store.set(key, text);
@@ -13682,33 +13702,33 @@ function useChatEngine(opts) {
13682
13702
  onClear,
13683
13703
  onFeedback
13684
13704
  } = opts || {};
13685
- const [status, setStatus] = React71.useState("idle");
13686
- const [threadId, setThreadId] = React71.useState(null);
13687
- const [messages, setMessages] = React71.useState([]);
13688
- const [queue, setQueue] = React71.useState([]);
13689
- const [fatal, setFatal] = React71.useState(null);
13690
- const [busy, setBusy] = React71.useState(false);
13691
- const [turnStartedAt, setTurnStartedAt] = React71.useState(null);
13692
- const listRef = React71.useRef([]);
13693
- const queueRef = React71.useRef([]);
13694
- const busyRef = React71.useRef(false);
13695
- const loadedRef = React71.useRef(false);
13696
- const stoppedRef = React71.useRef(false);
13697
- const abortRef = React71.useRef(null);
13698
- const serverCount = React71.useRef(0);
13699
- const serverIds = React71.useRef(/* @__PURE__ */ new Set());
13700
- const liveTurn = React71.useRef(null);
13701
- const lastTurnOwn = React71.useRef(/* @__PURE__ */ new Set());
13702
- const retired = React71.useRef(/* @__PURE__ */ new Set());
13703
- const threadRef = React71.useRef(null);
13704
- const mounted = React71.useRef(true);
13705
- React71.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(() => {
13706
13726
  mounted.current = true;
13707
13727
  return () => {
13708
13728
  mounted.current = false;
13709
13729
  };
13710
13730
  }, []);
13711
- const describeWaitingRef = React71.useRef(describeWaiting);
13731
+ const describeWaitingRef = React72.useRef(describeWaiting);
13712
13732
  describeWaitingRef.current = describeWaiting;
13713
13733
  const commit = (next) => {
13714
13734
  const derived = withWaiting(next, (pending) => describeWaitingRef.current(pending));
@@ -13727,7 +13747,7 @@ function useChatEngine(opts) {
13727
13747
  }
13728
13748
  return false;
13729
13749
  };
13730
- const loadThread = React71.useCallback(async (id) => {
13750
+ const loadThread = React72.useCallback(async (id) => {
13731
13751
  const data = await apiAdapter.getThread(id);
13732
13752
  const list = [...data && data.messages || []];
13733
13753
  serverCount.current = list.length;
@@ -13767,7 +13787,7 @@ function useChatEngine(opts) {
13767
13787
  packet: progress.packet ?? holder.packet
13768
13788
  });
13769
13789
  }
13770
- React71.useEffect(() => {
13790
+ React72.useEffect(() => {
13771
13791
  if (!apiAdapter) {
13772
13792
  setStatus("idle");
13773
13793
  setFatal(null);
@@ -13999,7 +14019,7 @@ function useChatEngine(opts) {
13999
14019
  await dispatchTurn(turn);
14000
14020
  }
14001
14021
  }
14002
- const send = React71.useCallback((text, attachments) => {
14022
+ const send = React72.useCallback((text, attachments) => {
14003
14023
  const body = (text || "").trim();
14004
14024
  if (!body && !(attachments && attachments.length)) return;
14005
14025
  if (status === "disconnected") return;
@@ -14009,7 +14029,7 @@ function useChatEngine(opts) {
14009
14029
  stoppedRef.current = false;
14010
14030
  drain();
14011
14031
  }, [status]);
14012
- const stop = React71.useCallback(() => {
14032
+ const stop = React72.useCallback(() => {
14013
14033
  stoppedRef.current = true;
14014
14034
  const ac = abortRef.current;
14015
14035
  if (ac) {
@@ -14028,11 +14048,11 @@ function useChatEngine(opts) {
14028
14048
  store.del(jobKey(threadRef.current));
14029
14049
  }
14030
14050
  }, [apiAdapter]);
14031
- const removeQueued = React71.useCallback((id) => {
14051
+ const removeQueued = React72.useCallback((id) => {
14032
14052
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
14033
14053
  setQueue(queueRef.current.slice());
14034
14054
  }, []);
14035
- const retry = React71.useCallback(() => {
14055
+ const retry = React72.useCallback(() => {
14036
14056
  const list = listRef.current;
14037
14057
  let at = -1;
14038
14058
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -14049,19 +14069,19 @@ function useChatEngine(opts) {
14049
14069
  setQueue(queueRef.current.slice());
14050
14070
  drain();
14051
14071
  }, []);
14052
- const clear = React71.useCallback(() => {
14072
+ const clear = React72.useCallback(() => {
14053
14073
  commit([]);
14054
14074
  serverCount.current = 0;
14055
14075
  queueRef.current = [];
14056
14076
  setQueue([]);
14057
14077
  onClear && onClear();
14058
14078
  }, [onClear]);
14059
- const setFeedback = React71.useCallback((id, value) => {
14079
+ const setFeedback = React72.useCallback((id, value) => {
14060
14080
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
14061
14081
  const msg = listRef.current.find((m) => m.id === id);
14062
14082
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
14063
14083
  }, [onFeedback]);
14064
- const reload = React71.useCallback(async () => {
14084
+ const reload = React72.useCallback(async () => {
14065
14085
  if (!threadRef.current) return;
14066
14086
  setStatus("loading");
14067
14087
  try {
@@ -14099,10 +14119,10 @@ var ChatKit = {
14099
14119
  };
14100
14120
 
14101
14121
  // src/components/chat/ChatTranscript.tsx
14102
- var React73 = __toESM(require("react"), 1);
14122
+ var React74 = __toESM(require("react"), 1);
14103
14123
 
14104
14124
  // src/components/chat/ChatTurn.tsx
14105
- var React72 = __toESM(require("react"), 1);
14125
+ var React73 = __toESM(require("react"), 1);
14106
14126
  var import_jsx_runtime102 = require("react/jsx-runtime");
14107
14127
  function JsonView({ value }) {
14108
14128
  let text;
@@ -14139,7 +14159,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
14139
14159
  ] });
14140
14160
  }
14141
14161
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
14142
- const [open2, setOpen] = React72.useState(defaultOpen);
14162
+ const [open2, setOpen] = React73.useState(defaultOpen);
14143
14163
  if (!text) return null;
14144
14164
  return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
14145
14165
  /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -14156,7 +14176,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
14156
14176
  ] });
14157
14177
  }
14158
14178
  function Citations({ items = [], onOpen }) {
14159
- const [open2, setOpen] = React72.useState(false);
14179
+ const [open2, setOpen] = React73.useState(false);
14160
14180
  if (!items.length) return null;
14161
14181
  return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-cites", children: [
14162
14182
  /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -14182,7 +14202,7 @@ function clampText(text, max) {
14182
14202
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
14183
14203
  }
14184
14204
  function MessageBody({ message: m, ctx }) {
14185
- const [expanded, setExpanded] = React72.useState(false);
14205
+ const [expanded, setExpanded] = React73.useState(false);
14186
14206
  const isUser = m.role === "user";
14187
14207
  const raw = m.text || "";
14188
14208
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
@@ -14261,7 +14281,7 @@ function RunActions({ group, ctx }) {
14261
14281
  ] }),
14262
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,
14263
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,
14264
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)(React72.Fragment, { children: [
14284
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)(React73.Fragment, { children: [
14265
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" }) }),
14266
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" }) })
14267
14287
  ] }) : null,
@@ -14356,10 +14376,10 @@ function ChatTranscript({
14356
14376
  renderEmpty,
14357
14377
  className = ""
14358
14378
  }) {
14359
- const scroller = React73.useRef(null);
14360
- const stick = React73.useRef(true);
14361
- const [pill, setPill] = React73.useState(0);
14362
- const seen = React73.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);
14363
14383
  const toBottom = (smooth) => {
14364
14384
  const el = scroller.current;
14365
14385
  if (!el) return;
@@ -14378,7 +14398,7 @@ function ChatTranscript({
14378
14398
  seen.current = messages.length;
14379
14399
  }
14380
14400
  };
14381
- React73.useLayoutEffect(() => {
14401
+ React74.useLayoutEffect(() => {
14382
14402
  const el = scroller.current;
14383
14403
  if (!el) return;
14384
14404
  if (stick.current) {
@@ -14386,7 +14406,7 @@ function ChatTranscript({
14386
14406
  seen.current = messages.length;
14387
14407
  } else setPill(Math.max(0, messages.length - seen.current));
14388
14408
  }, [messages]);
14389
- React73.useEffect(() => {
14409
+ React74.useEffect(() => {
14390
14410
  const el = scroller.current;
14391
14411
  const inner = el && el.firstChild;
14392
14412
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -14396,7 +14416,7 @@ function ChatTranscript({
14396
14416
  ro.observe(inner);
14397
14417
  return () => ro.disconnect();
14398
14418
  }, []);
14399
- const groups = React73.useMemo(() => groupMessages(messages), [messages]);
14419
+ const groups = React74.useMemo(() => groupMessages(messages), [messages]);
14400
14420
  const empty = !messages.length && status === "ready";
14401
14421
  return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
14402
14422
  /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
@@ -14420,7 +14440,7 @@ function ChatTranscript({
14420
14440
  const prev = groups[i - 1];
14421
14441
  const k = dayKey(g.messages[0].timestamp);
14422
14442
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
14423
- return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)(React73.Fragment, { children: [
14443
+ return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)(React74.Fragment, { children: [
14424
14444
  showDay ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { children: dayLabel(k) }) }) : null,
14425
14445
  /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(ChatTurn, { group: g, ctx })
14426
14446
  ] }, g.key || i);
@@ -14437,7 +14457,7 @@ function ChatTranscript({
14437
14457
  var TranscriptKit = { groupMessages };
14438
14458
 
14439
14459
  // src/components/chat/ChatComposer.tsx
14440
- var React74 = __toESM(require("react"), 1);
14460
+ var React75 = __toESM(require("react"), 1);
14441
14461
  var import_jsx_runtime104 = require("react/jsx-runtime");
14442
14462
  function ChatComposer({
14443
14463
  onSubmit,
@@ -14465,17 +14485,17 @@ function ChatComposer({
14465
14485
  onReject,
14466
14486
  onOpenAttachment
14467
14487
  }) {
14468
- const [text, setText] = React74.useState(draft || "");
14469
- const [trigger, setTrigger] = React74.useState(null);
14470
- const [mentionItems, setMentionItems] = React74.useState([]);
14471
- const [listening, setListening] = React74.useState(false);
14472
- const [notice, setNotice] = React74.useState(null);
14473
- const editor = React74.useRef(null);
14474
- const wrap = React74.useRef(null);
14475
- const stopVoice = React74.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);
14476
14496
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
14477
14497
  } });
14478
- React74.useEffect(() => {
14498
+ React75.useEffect(() => {
14479
14499
  if (draft != null && draft !== text) setText(draft);
14480
14500
  }, [draft]);
14481
14501
  const change = (v) => {
@@ -14511,7 +14531,7 @@ function ChatComposer({
14511
14531
  e.preventDefault();
14512
14532
  staged.add(found.files);
14513
14533
  };
14514
- React74.useEffect(() => {
14534
+ React75.useEffect(() => {
14515
14535
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
14516
14536
  setMentionItems([]);
14517
14537
  return;
@@ -14529,7 +14549,7 @@ function ChatComposer({
14529
14549
  const q = (trigger.query || "").toLowerCase();
14530
14550
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
14531
14551
  }, [trigger, mentionSources]);
14532
- const slashItems = React74.useMemo(() => {
14552
+ const slashItems = React75.useMemo(() => {
14533
14553
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
14534
14554
  const q = (trigger.query || "").toLowerCase();
14535
14555
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -14699,12 +14719,12 @@ function ChatComposer({
14699
14719
  }
14700
14720
 
14701
14721
  // src/components/chat/ChatSessionBar.tsx
14702
- var React75 = __toESM(require("react"), 1);
14722
+ var React76 = __toESM(require("react"), 1);
14703
14723
  var import_jsx_runtime105 = require("react/jsx-runtime");
14704
14724
  var compact2 = meterFormats.compact;
14705
14725
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
14706
- const [open2, setOpen] = React75.useState(false);
14707
- const anchor = React75.useRef(null);
14726
+ const [open2, setOpen] = React76.useState(false);
14727
+ const anchor = React76.useRef(null);
14708
14728
  const stats = sessionStats || null;
14709
14729
  const cu = contextUsage || null;
14710
14730
  const limits = usageLimits || null;
@@ -14719,7 +14739,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
14719
14739
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
14720
14740
  if (cu) bits.push(pct + "% context");
14721
14741
  const expandable = !!(cu || limits);
14722
- return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(React75.Fragment, { children: [
14742
+ return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(React76.Fragment, { children: [
14723
14743
  /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("div", { className: "fdc-bar", children: [
14724
14744
  /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(
14725
14745
  "button",
@@ -14860,7 +14880,7 @@ function ModelControls({
14860
14880
  ] })
14861
14881
  });
14862
14882
  }
14863
- return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(React75.Fragment, { children: [
14883
+ return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(React76.Fragment, { children: [
14864
14884
  /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
14865
14885
  MenuButton,
14866
14886
  {
@@ -14980,11 +15000,11 @@ function AgentChatPanel({
14980
15000
  onFeedback,
14981
15001
  onEditMessage
14982
15002
  }) {
14983
- const [panelWidth, setPanelWidth] = React76.useState(width);
14984
- const [applied, setApplied] = React76.useState({});
15003
+ const [panelWidth, setPanelWidth] = React77.useState(width);
15004
+ const [applied, setApplied] = React77.useState({});
14985
15005
  const [draft, setDraft] = useChatDraft(draftOwner, contextType, contextId);
14986
- const dragging = React76.useRef(null);
14987
- React76.useEffect(() => setPanelWidth(width), [width]);
15006
+ const dragging = React77.useRef(null);
15007
+ React77.useEffect(() => setPanelWidth(width), [width]);
14988
15008
  const engine = useChatEngine({
14989
15009
  contextType,
14990
15010
  contextId,
@@ -15190,7 +15210,7 @@ function AgentChatPanel({
15190
15210
  }
15191
15211
 
15192
15212
  // src/components/files/FileViewer.tsx
15193
- var React77 = __toESM(require("react"), 1);
15213
+ var React78 = __toESM(require("react"), 1);
15194
15214
  var import_jsx_runtime107 = require("react/jsx-runtime");
15195
15215
  function previewKindOf(file) {
15196
15216
  const mime = (file.mime || "").toLowerCase();
@@ -15247,13 +15267,13 @@ function parseDelimited(text, delimiter) {
15247
15267
  return rows;
15248
15268
  }
15249
15269
  function usePreview(file, kind, resolveUrl) {
15250
- const [state, setState] = React77.useState({ status: "loading" });
15251
- const [attempt, setAttempt] = React77.useState(0);
15252
- const resolveRef = React77.useRef(resolveUrl);
15253
- React77.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(() => {
15254
15274
  resolveRef.current = resolveUrl;
15255
15275
  }, [resolveUrl]);
15256
- React77.useEffect(() => {
15276
+ React78.useEffect(() => {
15257
15277
  if (kind === "none") {
15258
15278
  setState({ status: "ready" });
15259
15279
  return;
@@ -15283,7 +15303,7 @@ function usePreview(file, kind, resolveUrl) {
15283
15303
  if (ac) ac.abort();
15284
15304
  };
15285
15305
  }, [file.id, kind, attempt]);
15286
- return { ...state, retry: React77.useCallback(() => setAttempt((a) => a + 1), []) };
15306
+ return { ...state, retry: React78.useCallback(() => setAttempt((a) => a + 1), []) };
15287
15307
  }
15288
15308
  function PreviewBody({ file, kind, state }) {
15289
15309
  if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
@@ -15328,13 +15348,13 @@ function PreviewBody({ file, kind, state }) {
15328
15348
  ] });
15329
15349
  }
15330
15350
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
15331
- const kind = React77.useMemo(() => previewKindOf(file), [file]);
15351
+ const kind = React78.useMemo(() => previewKindOf(file), [file]);
15332
15352
  const preview = usePreview(file, kind, resolveUrl);
15333
- const [tab, setTab] = React77.useState("preview");
15334
- const [downloading, setDownloading] = React77.useState(false);
15335
- const [downloadError, setDownloadError] = React77.useState(null);
15353
+ const [tab, setTab] = React78.useState("preview");
15354
+ const [downloading, setDownloading] = React78.useState(false);
15355
+ const [downloadError, setDownloadError] = React78.useState(null);
15336
15356
  const hasSide = sidePanel != null;
15337
- React77.useEffect(() => {
15357
+ React78.useEffect(() => {
15338
15358
  setTab("preview");
15339
15359
  }, [file.id]);
15340
15360
  const download = () => {
@@ -15401,7 +15421,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
15401
15421
  }
15402
15422
 
15403
15423
  // src/components/files/FileBrowser.tsx
15404
- var React78 = __toESM(require("react"), 1);
15424
+ var React79 = __toESM(require("react"), 1);
15405
15425
  var import_jsx_runtime108 = require("react/jsx-runtime");
15406
15426
  function childrenOf(folders, parentId) {
15407
15427
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
@@ -15511,8 +15531,8 @@ function FolderPickerMenu({
15511
15531
  ] });
15512
15532
  }
15513
15533
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
15514
- const [over, setOver] = React78.useState(false);
15515
- const dragCounter = React78.useRef(0);
15534
+ const [over, setOver] = React79.useState(false);
15535
+ const dragCounter = React79.useRef(0);
15516
15536
  const dropHandlers = isDropTarget ? {
15517
15537
  onDragEnter: (e) => {
15518
15538
  if (!hasInternalPayload(e)) return;
@@ -15560,8 +15580,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
15560
15580
  }
15561
15581
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
15562
15582
  const kids = childrenOf(folders, folder.id);
15563
- const [expanded, setExpanded] = React78.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
15564
- React78.useEffect(() => {
15583
+ const [expanded, setExpanded] = React79.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
15584
+ React79.useEffect(() => {
15565
15585
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
15566
15586
  }, [currentFolderId, folder.id, folders]);
15567
15587
  const isCurrent = folder.id === currentFolderId;
@@ -15627,15 +15647,15 @@ function FileBrowser({
15627
15647
  const canUpload = perm.canUpload !== false && !!onUpload;
15628
15648
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
15629
15649
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
15630
- const [createOpen, setCreateOpen] = React78.useState(false);
15631
- const [createName, setCreateName] = React78.useState("");
15632
- const [renameTarget, setRenameTarget] = React78.useState(null);
15633
- const [renameValue, setRenameValue] = React78.useState("");
15634
- const [deleteTarget, setDeleteTarget] = React78.useState(null);
15635
- const uploadInputRef = React78.useRef(null);
15636
- const crumbFolders = React78.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
15637
- const subfolders = React78.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
15638
- const currentFiles = React78.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(
15639
15659
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
15640
15660
  [files, currentFolderId]
15641
15661
  );
@@ -15867,8 +15887,8 @@ function BreadcrumbCrumb({
15867
15887
  isDropTarget,
15868
15888
  onDropPayload
15869
15889
  }) {
15870
- const [over, setOver] = React78.useState(false);
15871
- const dragCounter = React78.useRef(0);
15890
+ const [over, setOver] = React79.useState(false);
15891
+ const dragCounter = React79.useRef(0);
15872
15892
  const dropHandlers = isDropTarget ? {
15873
15893
  onDragEnter: (e) => {
15874
15894
  if (!hasInternalPayload(e)) return;
@@ -15897,7 +15917,7 @@ function BreadcrumbCrumb({
15897
15917
  }
15898
15918
 
15899
15919
  // src/kits/query.ts
15900
- var React79 = __toESM(require("react"), 1);
15920
+ var React80 = __toESM(require("react"), 1);
15901
15921
 
15902
15922
  // src/kits/queryUrl.ts
15903
15923
  var historyUrlAdapter = {
@@ -16035,38 +16055,38 @@ function requestFor(params, query, paging, after) {
16035
16055
  }
16036
16056
  var toError = (e) => e instanceof Error ? e : new Error(String(e));
16037
16057
  function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "page", url }) {
16038
- const [base] = React79.useState(() => {
16058
+ const [base] = React80.useState(() => {
16039
16059
  const store = PREFS || window.PlannerPrefs;
16040
16060
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
16041
16061
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
16042
16062
  });
16043
- const [mountParams] = React79.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
16044
- const address = React79.useRef(mountParams);
16045
- const [query, setQuery] = React79.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
16046
- const savePref = React79.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) => {
16047
16067
  const store = PREFS || window.PlannerPrefs;
16048
16068
  if (prefsKey && store) store.setTable(prefsKey, patch2);
16049
16069
  }, [prefsKey]);
16050
- const [res, setRes] = React79.useState(null);
16051
- const [loading, setLoading] = React79.useState(true);
16052
- const [loadingMore, setLoadingMore] = React79.useState(false);
16053
- const [failure, setFailure] = React79.useState(null);
16054
- const [reloadToken, setReloadToken] = React79.useState(0);
16055
- const moreController = React79.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);
16056
16076
  const depKey = (deps || []).join("|");
16057
16077
  const paramKey = JSON.stringify(params || {});
16058
16078
  const queryKey = JSON.stringify(query);
16059
- const lifetime = React79.useRef(null);
16060
- React79.useEffect(() => {
16079
+ const lifetime = React80.useRef(null);
16080
+ React80.useEffect(() => {
16061
16081
  const controller = new AbortController();
16062
16082
  lifetime.current = controller;
16063
16083
  return () => controller.abort();
16064
16084
  }, []);
16065
- const latest = React79.useRef({ res, loading, query, params, endpoint, url, base });
16066
- React79.useLayoutEffect(() => {
16085
+ const latest = React80.useRef({ res, loading, query, params, endpoint, url, base });
16086
+ React80.useLayoutEffect(() => {
16067
16087
  latest.current = { res, loading, query, params, endpoint, url, base };
16068
16088
  });
16069
- React79.useEffect(() => {
16089
+ React80.useEffect(() => {
16070
16090
  const controller = new AbortController();
16071
16091
  const { signal } = controller;
16072
16092
  setLoading(true);
@@ -16102,7 +16122,7 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "
16102
16122
  };
16103
16123
  }, [endpoint, queryKey, paramKey, depKey, paging, reloadToken]);
16104
16124
  const adapter = url ? url.adapter ?? historyUrlAdapter : null;
16105
- React79.useEffect(() => {
16125
+ React80.useEffect(() => {
16106
16126
  if (!adapter) return;
16107
16127
  return adapter.subscribe((params2) => {
16108
16128
  const { url: u, base: b } = latest.current;
@@ -16452,12 +16472,12 @@ function createVersionStore(initialState, options) {
16452
16472
  }
16453
16473
 
16454
16474
  // src/kits/documentTitle.ts
16455
- var React80 = __toESM(require("react"), 1);
16475
+ var React81 = __toESM(require("react"), 1);
16456
16476
  function formatDocumentTitle(routeTitle, appName) {
16457
16477
  return [routeTitle, appName, "Flytedesk"].filter((part2) => !!part2 && part2.length > 0).join(" \xB7 ");
16458
16478
  }
16459
16479
  function useDocumentTitle(routeTitle, appName) {
16460
- React80.useEffect(() => {
16480
+ React81.useEffect(() => {
16461
16481
  if (typeof document === "undefined") return;
16462
16482
  document.title = formatDocumentTitle(routeTitle, appName);
16463
16483
  }, [routeTitle, appName]);