@flytedan/flytebot-design-system 0.73.0 → 0.74.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.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 = () => {
@@ -4241,6 +4261,7 @@ function RowActionCell({ action }) {
4241
4261
  return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("td", { className: "fd-table-action", children: action ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(RowActionButton, { action, size: "sm" }) : null });
4242
4262
  }
4243
4263
  var cellOf = (c, row) => c.render ? c.render(row) : row[c.key];
4264
+ var cardCellOf = (c, row) => c.phoneRender ? c.phoneRender(row) : cellOf(c, row);
4244
4265
  function rowInteraction(row, onRowClick) {
4245
4266
  if (!onRowClick) return {};
4246
4267
  return {
@@ -4383,11 +4404,11 @@ function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort
4383
4404
  ...semantics,
4384
4405
  ...rowInteraction(r, onRowClick),
4385
4406
  children: [
4386
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "fd-dt-card-title", children: primary.map((c) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: c.numeric ? "is-num" : void 0, children: cellOf(c, r) }, c.key)) }),
4407
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "fd-dt-card-title", children: primary.map((c) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: c.numeric ? "is-num" : void 0, children: cardCellOf(c, r) }, c.key)) }),
4387
4408
  secondary.length ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "fd-dt-card-meta", children: secondary.map((c) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: c.numeric ? "is-num" : void 0, children: [
4388
4409
  /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-dt-card-label", children: c.label }),
4389
4410
  " ",
4390
- cellOf(c, r)
4411
+ cardCellOf(c, r)
4391
4412
  ] }, c.key)) }) : null
4392
4413
  ]
4393
4414
  }
@@ -4399,16 +4420,16 @@ function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort
4399
4420
  }
4400
4421
 
4401
4422
  // src/components/data/FilterBar.tsx
4402
- var React32 = __toESM(require("react"), 1);
4423
+ var React33 = __toESM(require("react"), 1);
4403
4424
 
4404
4425
  // src/components/forms/NumberInput.tsx
4405
- var React29 = __toESM(require("react"), 1);
4426
+ var React30 = __toESM(require("react"), 1);
4406
4427
 
4407
4428
  // src/components/forms/field.tsx
4408
- var React27 = __toESM(require("react"), 1);
4429
+ var React28 = __toESM(require("react"), 1);
4409
4430
  var import_jsx_runtime46 = require("react/jsx-runtime");
4410
4431
  function useFieldId(id) {
4411
- const generated = React27.useId();
4432
+ const generated = React28.useId();
4412
4433
  return id || generated;
4413
4434
  }
4414
4435
  function FieldLabel({ htmlFor, id, required = false, onClick, children }) {
@@ -4427,10 +4448,10 @@ function HiddenFieldLabel({ id, children }) {
4427
4448
  }
4428
4449
 
4429
4450
  // src/components/useLatest.ts
4430
- var React28 = __toESM(require("react"), 1);
4451
+ var React29 = __toESM(require("react"), 1);
4431
4452
  function useLatest(value) {
4432
- const ref = React28.useRef(value);
4433
- React28.useInsertionEffect(() => {
4453
+ const ref = React29.useRef(value);
4454
+ React29.useInsertionEffect(() => {
4434
4455
  ref.current = value;
4435
4456
  });
4436
4457
  return ref;
@@ -4513,20 +4534,20 @@ function NumberInput({
4513
4534
  const n = typeof v === "number" ? v : parseNumberText(v);
4514
4535
  return n == null || Number.isNaN(n) ? null : n;
4515
4536
  };
4516
- const [text, setText] = React29.useState(() => toText(value));
4517
- const [editing, setEditing] = React29.useState(false);
4537
+ const [text, setText] = React30.useState(() => toText(value));
4538
+ const [editing, setEditing] = React30.useState(false);
4518
4539
  const parsed = parseNumberText(text);
4519
4540
  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
4541
  const valid = invalidMessage == null;
4521
- const committedRef = React29.useRef(toNumber(value));
4542
+ const committedRef = React30.useRef(toNumber(value));
4522
4543
  const onChangeRef = useLatest(onChange);
4523
4544
  const onValidityChangeRef = useLatest(onValidityChange);
4524
- const focusedRef = React29.useRef(false);
4525
- React29.useEffect(() => {
4545
+ const focusedRef = React30.useRef(false);
4546
+ React30.useEffect(() => {
4526
4547
  committedRef.current = toNumber(value);
4527
4548
  if (!focusedRef.current) setText(toText(value));
4528
4549
  }, [value]);
4529
- React29.useLayoutEffect(() => {
4550
+ React30.useLayoutEffect(() => {
4530
4551
  onValidityChangeRef.current?.(valid);
4531
4552
  }, [valid, onValidityChangeRef]);
4532
4553
  const fire = (n) => {
@@ -4542,7 +4563,7 @@ function NumberInput({
4542
4563
  return true;
4543
4564
  };
4544
4565
  const bumpRef = useLatest(bump);
4545
- const holdTimer = React29.useRef(null);
4566
+ const holdTimer = React30.useRef(null);
4546
4567
  const release2 = () => {
4547
4568
  if (holdTimer.current) clearTimeout(holdTimer.current);
4548
4569
  holdTimer.current = null;
@@ -4561,7 +4582,7 @@ function NumberInput({
4561
4582
  };
4562
4583
  holdTimer.current = setTimeout(tick, HOLD_DELAY_MS);
4563
4584
  };
4564
- React29.useEffect(() => () => {
4585
+ React30.useEffect(() => () => {
4565
4586
  if (holdTimer.current) clearTimeout(holdTimer.current);
4566
4587
  }, []);
4567
4588
  const current2 = committedRef.current;
@@ -4664,7 +4685,7 @@ function NumberInput({
4664
4685
  }
4665
4686
 
4666
4687
  // src/components/forms/DatePicker.tsx
4667
- var React30 = __toESM(require("react"), 1);
4688
+ var React31 = __toESM(require("react"), 1);
4668
4689
  var import_jsx_runtime48 = require("react/jsx-runtime");
4669
4690
  var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
4670
4691
  var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
@@ -4697,10 +4718,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
4697
4718
  const today = /* @__PURE__ */ new Date();
4698
4719
  const sel = range ? value || {} : { start: value, end: value };
4699
4720
  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);
4721
+ const [vy, setVy] = React31.useState(anchor.getFullYear());
4722
+ const [vm, setVm] = React31.useState(anchor.getMonth());
4723
+ const [mode2, setMode] = React31.useState("days");
4724
+ const [hover, setHover] = React31.useState(null);
4704
4725
  const s = parse(sel.start), e = parse(sel.end);
4705
4726
  const hoverEnd = range && s && !e && hover ? parse(hover) : null;
4706
4727
  const inRange = (d) => {
@@ -4711,12 +4732,12 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
4711
4732
  const isEnd = (d) => !!e && iso(d) === iso(e);
4712
4733
  const isEdge = (d) => isStart(d) || isEnd(d);
4713
4734
  const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
4714
- const [activeDate, setActiveDate] = React30.useState(() => {
4735
+ const [activeDate, setActiveDate] = React31.useState(() => {
4715
4736
  if (s) return s;
4716
4737
  if (sameMonth(today, anchor.getFullYear(), anchor.getMonth())) return today;
4717
4738
  return new Date(anchor.getFullYear(), anchor.getMonth(), 1);
4718
4739
  });
4719
- const calRef = React30.useRef(null);
4740
+ const calRef = React31.useRef(null);
4720
4741
  const pageToShow = (y, m) => {
4721
4742
  const idx = y * 12 + m, firstIdx = vy * 12 + vm, secondIdx = firstIdx + 1;
4722
4743
  if (idx === firstIdx || months > 1 && idx === secondIdx) return;
@@ -4733,7 +4754,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
4733
4754
  setActiveDate(next);
4734
4755
  pageToShow(next.getFullYear(), next.getMonth());
4735
4756
  };
4736
- React30.useEffect(() => {
4757
+ React31.useEffect(() => {
4737
4758
  const el = calRef.current?.querySelector('[data-iso="' + iso(activeDate) + '"]');
4738
4759
  if (el) el.focus({ preventScroll: true });
4739
4760
  }, [activeDate, vy, vm]);
@@ -4926,9 +4947,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
4926
4947
  }
4927
4948
  function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, "aria-label": hiddenLabel, ...rest }) {
4928
4949
  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);
4950
+ const [open2, setOpen] = React31.useState(false);
4951
+ const rootRef = React31.useRef(null);
4952
+ const boxRef = React31.useRef(null);
4932
4953
  const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
4933
4954
  const toggle = () => {
4934
4955
  if (!disabled) setOpen(!open2);
@@ -5017,9 +5038,9 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
5017
5038
  }
5018
5039
 
5019
5040
  // src/components/forms/listbox.ts
5020
- var React31 = __toESM(require("react"), 1);
5041
+ var React32 = __toESM(require("react"), 1);
5021
5042
  function useListboxNav({ count, onSelect }) {
5022
- const [active, setActive] = React31.useState(-1);
5043
+ const [active, setActive] = React32.useState(-1);
5023
5044
  return {
5024
5045
  active,
5025
5046
  setActive,
@@ -5032,7 +5053,7 @@ function useListboxNav({ count, onSelect }) {
5032
5053
  };
5033
5054
  }
5034
5055
  function useListboxScrollIntoView(active, listRef, enabled) {
5035
- React31.useEffect(() => {
5056
+ React32.useEffect(() => {
5036
5057
  if (!enabled || active < 0 || !listRef.current) return;
5037
5058
  const list = listRef.current;
5038
5059
  const el = list.querySelector('[data-i="' + active + '"]');
@@ -5253,13 +5274,13 @@ function MultiSelectPanel({
5253
5274
  onClose
5254
5275
  }) {
5255
5276
  const allowedOps = operatorsFor(field);
5256
- const [draftOperator, setDraftOperator] = React32.useState(value?.operator ?? allowedOps[0]);
5277
+ const [draftOperator, setDraftOperator] = React33.useState(value?.operator ?? allowedOps[0]);
5257
5278
  const operator = allowedOps.length === 1 ? allowedOps[0] : value?.operator ?? draftOperator;
5258
5279
  const selected = value?.values ?? [];
5259
5280
  const selectedRef = useLatest(selected);
5260
5281
  const operatorRef = useLatest(operator);
5261
- const mountedRef = React32.useRef(true);
5262
- React32.useEffect(() => {
5282
+ const mountedRef = React33.useRef(true);
5283
+ React33.useEffect(() => {
5263
5284
  mountedRef.current = true;
5264
5285
  return () => {
5265
5286
  mountedRef.current = false;
@@ -5273,20 +5294,20 @@ function MultiSelectPanel({
5273
5294
  if (selectedRef.current.length > 0) commit(selectedRef.current, op);
5274
5295
  else setDraftOperator(op);
5275
5296
  };
5276
- const [mode2, setMode] = React32.useState("search");
5277
- const [query, setQuery] = React32.useState("");
5278
- const [asyncState, setAsyncState] = React32.useState(
5297
+ const [mode2, setMode] = React33.useState("search");
5298
+ const [query, setQuery] = React33.useState("");
5299
+ const [asyncState, setAsyncState] = React33.useState(
5279
5300
  { options: null, loading: !!field.loadOptions, error: false }
5280
5301
  );
5281
- const [retryTick, setRetryTick] = React32.useState(0);
5282
- const inputRef = React32.useRef(null);
5283
- const listRef = React32.useRef(null);
5284
- const listId = React32.useId();
5302
+ const [retryTick, setRetryTick] = React33.useState(0);
5303
+ const inputRef = React33.useRef(null);
5304
+ const listRef = React33.useRef(null);
5305
+ const listId = React33.useId();
5285
5306
  const loadOptionsRef = useLatest(field.loadOptions);
5286
- React32.useEffect(() => {
5307
+ React33.useEffect(() => {
5287
5308
  inputRef.current?.focus();
5288
5309
  }, []);
5289
- React32.useEffect(() => {
5310
+ React33.useEffect(() => {
5290
5311
  const load = loadOptionsRef.current;
5291
5312
  if (!load) return;
5292
5313
  const controller = new AbortController();
@@ -5319,17 +5340,17 @@ function MultiSelectPanel({
5319
5340
  };
5320
5341
  const nav = useListboxNav({ count: options.length, onSelect: (i) => toggle(options[i]) });
5321
5342
  useListboxScrollIntoView(nav.active, listRef, hasListbox);
5322
- React32.useEffect(() => {
5343
+ React33.useEffect(() => {
5323
5344
  nav.setActive(0);
5324
5345
  }, [query, options.length]);
5325
5346
  const activeId = hasListbox && options[nav.active] ? listId + "-opt-" + nav.active : void 0;
5326
5347
  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(() => {
5348
+ const [pasteText, setPasteText] = React33.useState("");
5349
+ const [pasteLoading, setPasteLoading] = React33.useState(false);
5350
+ const [unmatchedTokens, setUnmatchedTokens] = React33.useState([]);
5351
+ const [pasteError, setPasteError] = React33.useState(null);
5352
+ const pasteWrapRef = React33.useRef(null);
5353
+ React33.useEffect(() => {
5333
5354
  if (mode2 === "paste") pasteWrapRef.current?.querySelector("textarea")?.focus();
5334
5355
  }, [mode2]);
5335
5356
  const doResolve = () => {
@@ -5502,8 +5523,8 @@ function MultiSelectPanel({
5502
5523
  );
5503
5524
  }
5504
5525
  function useTextValidity(onFlip) {
5505
- const invalidRef = React32.useRef(/* @__PURE__ */ new Set());
5506
- const [, rerender] = React32.useReducer((n) => n + 1, 0);
5526
+ const invalidRef = React33.useRef(/* @__PURE__ */ new Set());
5527
+ const [, rerender] = React33.useReducer((n) => n + 1, 0);
5507
5528
  const onFlipRef = useLatest(onFlip);
5508
5529
  const record = (name, valid) => {
5509
5530
  const invalid = invalidRef.current;
@@ -5546,15 +5567,15 @@ function sameValue(a, b) {
5546
5567
  return true;
5547
5568
  }
5548
5569
  function useReseedFromProps(value, applies, reseed) {
5549
- const seen = React32.useRef(value);
5550
- React32.useLayoutEffect(() => {
5570
+ const seen = React33.useRef(value);
5571
+ React33.useLayoutEffect(() => {
5551
5572
  if (seen.current === value) return;
5552
5573
  seen.current = value;
5553
5574
  if (!sameValue(value, applies())) reseed(value);
5554
5575
  }, [value, applies, reseed]);
5555
5576
  }
5556
5577
  function usePreserveFocusAcrossRemount(seed, fields) {
5557
- const pendingName = React32.useRef(null);
5578
+ const pendingName = React33.useRef(null);
5558
5579
  const fieldsRef = useLatest(fields);
5559
5580
  const capture = () => {
5560
5581
  const active = document.activeElement;
@@ -5567,7 +5588,7 @@ function usePreserveFocusAcrossRemount(seed, fields) {
5567
5588
  }
5568
5589
  }
5569
5590
  };
5570
- React32.useLayoutEffect(() => {
5591
+ React33.useLayoutEffect(() => {
5571
5592
  const name = pendingName.current;
5572
5593
  if (!name) return;
5573
5594
  pendingName.current = null;
@@ -5583,14 +5604,14 @@ function RangePanel({
5583
5604
  onCommit,
5584
5605
  onClose
5585
5606
  }) {
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);
5607
+ const [draft, setDraft] = React33.useState(() => rangeDraft(value));
5608
+ const [seed, setSeed] = React33.useState(0);
5609
+ const minId = React33.useId();
5610
+ const maxId = React33.useId();
5611
+ const minWrapRef = React33.useRef(null);
5612
+ const maxWrapRef = React33.useRef(null);
5592
5613
  const preserveFocus = usePreserveFocusAcrossRemount(seed, { min: minWrapRef, max: maxWrapRef });
5593
- const draftRef = React32.useRef(draft);
5614
+ const draftRef = React33.useRef(draft);
5594
5615
  const shown = () => {
5595
5616
  const { min, max } = draftRef.current;
5596
5617
  return applicable(field, min == null && max == null ? void 0 : { min, max }, validity.allValid());
@@ -5682,15 +5703,15 @@ function DatePanel({
5682
5703
  onClose
5683
5704
  }) {
5684
5705
  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);
5706
+ const [initial] = React33.useState(() => dateDraft(field, value));
5707
+ const [kind, setKind] = React33.useState(initial.kind);
5708
+ const [daysDraft, setDaysDraft] = React33.useState(initial.days);
5709
+ const daysRef = React33.useRef(daysDraft);
5710
+ const daysConfirmed = React33.useRef(value?.kind === "withinDays");
5711
+ const [between, setBetween] = React33.useState(initial.between);
5712
+ const [seed, setSeed] = React33.useState(0);
5713
+ const daysId = React33.useId();
5714
+ const daysWrapRef = React33.useRef(null);
5694
5715
  const preserveFocus = usePreserveFocusAcrossRemount(seed, { days: daysWrapRef });
5695
5716
  const shownWithinDays = () => {
5696
5717
  const days = daysRef.current;
@@ -5808,11 +5829,11 @@ function FilterButton({ children, ...rest }) {
5808
5829
  ] });
5809
5830
  }
5810
5831
  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);
5832
+ const [panel, setPanel] = React33.useState(null);
5833
+ const editAnchorRef = React33.useRef(null);
5834
+ const addAnchorRef = React33.useRef(null);
5835
+ const textInputRef = React33.useRef(null);
5836
+ const optionsRef = React33.useRef(null);
5816
5837
  if (process.env.NODE_ENV !== "production") {
5817
5838
  for (const f of fields) assertValidFieldDefinition(f);
5818
5839
  }
@@ -5835,7 +5856,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
5835
5856
  const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
5836
5857
  const startEditing = (key) => setPanel({ kind: "edit", key });
5837
5858
  const closeEditing = () => setPanel(null);
5838
- React32.useEffect(() => {
5859
+ React33.useEffect(() => {
5839
5860
  if (!panel || panel.kind !== "edit") return;
5840
5861
  if (editingField?.type === "text") {
5841
5862
  textInputRef.current?.focus();
@@ -6090,10 +6111,10 @@ function StatTile(props) {
6090
6111
  }
6091
6112
 
6092
6113
  // src/components/data/CodeBlock.tsx
6093
- var React34 = __toESM(require("react"), 1);
6114
+ var React35 = __toESM(require("react"), 1);
6094
6115
 
6095
6116
  // src/kits/clipboard.ts
6096
- var React33 = __toESM(require("react"), 1);
6117
+ var React34 = __toESM(require("react"), 1);
6097
6118
  var COPIED_FEEDBACK_MS = 1600;
6098
6119
  function copyThroughSelection(text) {
6099
6120
  const previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
@@ -6123,17 +6144,17 @@ async function copyToClipboard(text) {
6123
6144
  return copyThroughSelection(text);
6124
6145
  }
6125
6146
  function useCopyToClipboard() {
6126
- const [copied, setCopied] = React33.useState(false);
6127
- const timer = React33.useRef(null);
6128
- const mounted = React33.useRef(true);
6129
- React33.useEffect(() => {
6147
+ const [copied, setCopied] = React34.useState(false);
6148
+ const timer = React34.useRef(null);
6149
+ const mounted = React34.useRef(true);
6150
+ React34.useEffect(() => {
6130
6151
  mounted.current = true;
6131
6152
  return () => {
6132
6153
  mounted.current = false;
6133
6154
  if (timer.current) clearTimeout(timer.current);
6134
6155
  };
6135
6156
  }, []);
6136
- const copy = React33.useCallback(async (text) => {
6157
+ const copy = React34.useCallback(async (text) => {
6137
6158
  const ok = await copyToClipboard(text);
6138
6159
  if (ok && mounted.current) {
6139
6160
  setCopied(true);
@@ -6301,7 +6322,7 @@ function tokenize(src, lang) {
6301
6322
  return out;
6302
6323
  }
6303
6324
  function Highlighted({ code, lang }) {
6304
- const toks = React34.useMemo(() => tokenize(code, lang), [code, lang]);
6325
+ const toks = React35.useMemo(() => tokenize(code, lang), [code, lang]);
6305
6326
  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
6327
  }
6307
6328
  function CodeBlock({
@@ -6315,8 +6336,8 @@ function CodeBlock({
6315
6336
  actions,
6316
6337
  className = ""
6317
6338
  }) {
6318
- const [wrap, setWrap] = React34.useState(!!wrapDefault);
6319
- const [open2, setOpen] = React34.useState(false);
6339
+ const [wrap, setWrap] = React35.useState(!!wrapDefault);
6340
+ const [open2, setOpen] = React35.useState(false);
6320
6341
  const [copied, copy] = useCopyToClipboard();
6321
6342
  const body = String(code).replace(/\n$/, "");
6322
6343
  const lines = body.split("\n");
@@ -6345,7 +6366,7 @@ function CodeBlock({
6345
6366
  ] });
6346
6367
  }
6347
6368
  function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
6348
- const [open2, setOpen] = React34.useState(false);
6369
+ const [open2, setOpen] = React35.useState(false);
6349
6370
  const [copied, copy] = useCopyToClipboard();
6350
6371
  const raw = String(diff).replace(/\n$/, "");
6351
6372
  const all = raw.split("\n").map((line) => {
@@ -6391,7 +6412,7 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
6391
6412
  }
6392
6413
 
6393
6414
  // src/components/data/Markdown.tsx
6394
- var React35 = __toESM(require("react"), 1);
6415
+ var React36 = __toESM(require("react"), 1);
6395
6416
 
6396
6417
  // src/components/data/markdownEscape.ts
6397
6418
  var ESCAPABLE = /\\([!-/:-@[-`{-~])/g;
@@ -6464,7 +6485,7 @@ function hiddenInlineNodes(hidden, ctx, keyBase) {
6464
6485
  const href = safeHref(d(g(2)));
6465
6486
  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
6487
  } 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()));
6488
+ 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
6489
  } 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
6490
  else if (kind === "strong") out.push(/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("strong", { children: hiddenInlineNodes(g(1) || g(2), ctx, key()) }, key()));
6470
6491
  else if (kind === "em") out.push(/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("em", { children: hiddenInlineNodes(g(1) || g(2), ctx, key()) }, key()));
@@ -6651,7 +6672,7 @@ function Markdown({
6651
6672
  tone = "default"
6652
6673
  }) {
6653
6674
  const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
6654
- const blocks = React35.useMemo(() => parseBlocks(source), [source]);
6675
+ const blocks = React36.useMemo(() => parseBlocks(source), [source]);
6655
6676
  return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: mdClass("fd-md", size, tone, className), children: renderBlocks(blocks, ctx, "b") });
6656
6677
  }
6657
6678
  function MarkdownInline({ source = "", className = "", onLinkClick, size, tone }) {
@@ -6762,7 +6783,7 @@ function Pagination({
6762
6783
  }
6763
6784
 
6764
6785
  // src/components/data/RelativeTime.tsx
6765
- var React36 = __toESM(require("react"), 1);
6786
+ var React37 = __toESM(require("react"), 1);
6766
6787
  var import_jsx_runtime58 = require("react/jsx-runtime");
6767
6788
  var MIN = 6e4;
6768
6789
  var HOUR = 36e5;
@@ -6814,9 +6835,9 @@ function formatDuration(ms) {
6814
6835
  return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
6815
6836
  }
6816
6837
  function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
6817
- const [, force] = React36.useState(0);
6838
+ const [, force] = React37.useState(0);
6818
6839
  const t = value instanceof Date ? value.getTime() : Date.parse(value);
6819
- React36.useEffect(() => {
6840
+ React37.useEffect(() => {
6820
6841
  if (!refresh2 || !t || isNaN(t)) return;
6821
6842
  const abs2 = Math.abs(t - Date.now());
6822
6843
  if (abs2 > DAY) return;
@@ -6832,7 +6853,7 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
6832
6853
  }
6833
6854
 
6834
6855
  // src/components/data/ScoreMeter.tsx
6835
- var React37 = __toESM(require("react"), 1);
6856
+ var React38 = __toESM(require("react"), 1);
6836
6857
  var import_jsx_runtime59 = require("react/jsx-runtime");
6837
6858
  function ScoreMeter({
6838
6859
  score,
@@ -6847,10 +6868,10 @@ function ScoreMeter({
6847
6868
  breakdownWidth = 280,
6848
6869
  className = ""
6849
6870
  }) {
6850
- const [open2, setOpen] = React37.useState(false);
6851
- const ref = React37.useRef(null);
6871
+ const [open2, setOpen] = React38.useState(false);
6872
+ const ref = React38.useRef(null);
6852
6873
  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: [
6874
+ const body = /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React38.Fragment, { children: [
6854
6875
  /* @__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
6876
  showScore ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
6856
6877
  ] });
@@ -6869,7 +6890,7 @@ function ScoreMeter({
6869
6890
  }
6870
6891
  );
6871
6892
  }
6872
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React37.Fragment, { children: [
6893
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React38.Fragment, { children: [
6873
6894
  /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
6874
6895
  "button",
6875
6896
  {
@@ -6900,11 +6921,11 @@ function ScoreMeter({
6900
6921
  }
6901
6922
 
6902
6923
  // src/components/actions/inlinePanel.tsx
6903
- var React38 = __toESM(require("react"), 1);
6924
+ var React39 = __toESM(require("react"), 1);
6904
6925
  var import_jsx_runtime60 = require("react/jsx-runtime");
6905
6926
  function useInlinePanel() {
6906
- const [open2, setOpen] = React38.useState(false);
6907
- const ref = React38.useRef(null);
6927
+ const [open2, setOpen] = React39.useState(false);
6928
+ const ref = React39.useRef(null);
6908
6929
  return { open: open2, setOpen, ref };
6909
6930
  }
6910
6931
  function InlinePanelSurface({ panel, align = "right", ...popover }) {
@@ -7075,7 +7096,7 @@ function SortMenu({
7075
7096
  }
7076
7097
 
7077
7098
  // src/components/data/StepList.tsx
7078
- var React39 = __toESM(require("react"), 1);
7099
+ var React40 = __toESM(require("react"), 1);
7079
7100
  var import_jsx_runtime62 = require("react/jsx-runtime");
7080
7101
  var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
7081
7102
  function StepList({
@@ -7089,9 +7110,9 @@ function StepList({
7089
7110
  className = "",
7090
7111
  active = false
7091
7112
  }) {
7092
- const [openState, setOpenState] = React39.useState(defaultOpen);
7113
+ const [openState, setOpenState] = React40.useState(defaultOpen);
7093
7114
  const open2 = openProp == null ? openState : openProp;
7094
- const [expanded, setExpanded] = React39.useState({});
7115
+ const [expanded, setExpanded] = React40.useState({});
7095
7116
  if (!steps.length) return null;
7096
7117
  const running = steps.some((s) => s.status === "running");
7097
7118
  const failed = steps.filter((s) => s.status === "error").length;
@@ -7149,7 +7170,7 @@ function StepList({
7149
7170
  }
7150
7171
 
7151
7172
  // src/components/data/VirtualList.tsx
7152
- var React40 = __toESM(require("react"), 1);
7173
+ var React41 = __toESM(require("react"), 1);
7153
7174
  var import_jsx_runtime63 = require("react/jsx-runtime");
7154
7175
  var VIRTUAL_LIST_BUFFER_ROWS = 20;
7155
7176
  var VIRTUAL_LIST_ROW_GAP = 6;
@@ -7201,35 +7222,35 @@ function VirtualList({
7201
7222
  className = "",
7202
7223
  style
7203
7224
  }) {
7204
- const [scrollTop, setScrollTop] = React40.useState(0);
7205
- const loaded = React40.useMemo(
7225
+ const [scrollTop, setScrollTop] = React41.useState(0);
7226
+ const loaded = React41.useMemo(
7206
7227
  () => ({ firstItemIndex, count: items.length }),
7207
7228
  [firstItemIndex, items.length]
7208
7229
  );
7209
7230
  const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
7210
7231
  const bandKey = firstItemIndex + ":" + items.length;
7211
- const win = React40.useMemo(
7232
+ const win = React41.useMemo(
7212
7233
  () => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
7213
7234
  [scrollTop, height, itemHeight, total, loaded]
7214
7235
  );
7215
- const need = React40.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
7236
+ const need = React41.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
7216
7237
  const wantStart = need.start && hasMore?.start !== false;
7217
7238
  const wantEnd = need.end && hasMore?.end !== false;
7218
7239
  const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
7219
7240
  const askKey = bandKey + "@" + bucket2;
7220
- const asked = React40.useRef({ start: null, end: null });
7221
- React40.useEffect(() => {
7241
+ const asked = React41.useRef({ start: null, end: null });
7242
+ React41.useEffect(() => {
7222
7243
  if (loading || !wantStart || asked.current.start === askKey) return;
7223
7244
  asked.current.start = askKey;
7224
7245
  onNeedMore("start", win);
7225
7246
  }, [wantStart, loading, askKey, onNeedMore, win]);
7226
- React40.useEffect(() => {
7247
+ React41.useEffect(() => {
7227
7248
  if (loading || !wantEnd || asked.current.end === askKey) return;
7228
7249
  asked.current.end = askKey;
7229
7250
  onNeedMore("end", win);
7230
7251
  }, [wantEnd, loading, askKey, onNeedMore, win]);
7231
- const lastKeysRef = React40.useRef(null);
7232
- const newKeys = React40.useMemo(() => {
7252
+ const lastKeysRef = React41.useRef(null);
7253
+ const newKeys = React41.useMemo(() => {
7233
7254
  const prev = lastKeysRef.current;
7234
7255
  if (!prev) return /* @__PURE__ */ new Set();
7235
7256
  const fresh = /* @__PURE__ */ new Set();
@@ -7239,7 +7260,7 @@ function VirtualList({
7239
7260
  }
7240
7261
  return fresh;
7241
7262
  }, [items]);
7242
- React40.useEffect(() => {
7263
+ React41.useEffect(() => {
7243
7264
  lastKeysRef.current = new Set(items.map(keyOf));
7244
7265
  }, [items]);
7245
7266
  const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
@@ -7284,7 +7305,7 @@ function VirtualList({
7284
7305
  }
7285
7306
 
7286
7307
  // src/components/data/EntityRow.tsx
7287
- var React41 = __toESM(require("react"), 1);
7308
+ var React42 = __toESM(require("react"), 1);
7288
7309
  var import_jsx_runtime64 = require("react/jsx-runtime");
7289
7310
  var ENTITY_ROW_METRIC_WIDTH = 74;
7290
7311
  var METRIC_TONE_COLOR = {
@@ -7297,7 +7318,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
7297
7318
  const key = m.id || m.label || i;
7298
7319
  const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
7299
7320
  const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
7300
- const content = /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(React41.Fragment, { children: [
7321
+ const content = /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(React42.Fragment, { children: [
7301
7322
  m.icon ? /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
7302
7323
  /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
7303
7324
  /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-sr", children: " " + m.label })
@@ -7389,7 +7410,7 @@ function EntityRow({
7389
7410
  }
7390
7411
 
7391
7412
  // src/components/data/TransferList.tsx
7392
- var React42 = __toESM(require("react"), 1);
7413
+ var React43 = __toESM(require("react"), 1);
7393
7414
  var import_react_dom6 = require("react-dom");
7394
7415
 
7395
7416
  // src/components/forms/Input.tsx
@@ -7495,12 +7516,12 @@ function TransferList({
7495
7516
  listHeight = 440,
7496
7517
  className = ""
7497
7518
  }) {
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) => {
7519
+ const [drag, setDrag] = React43.useState(null);
7520
+ const [dragOverSide, setDragOverSide] = React43.useState(null);
7521
+ const dragRef = React43.useRef(null);
7522
+ const armedRef = React43.useRef(null);
7523
+ const sideRefs = React43.useRef({ left: null, right: null });
7524
+ const hitTestSide = React43.useCallback((x, y) => {
7504
7525
  for (const side of ["left", "right"]) {
7505
7526
  const el = sideRefs.current[side];
7506
7527
  if (!el) continue;
@@ -7509,7 +7530,7 @@ function TransferList({
7509
7530
  }
7510
7531
  return null;
7511
7532
  }, []);
7512
- const findItem = React42.useCallback(
7533
+ const findItem = React43.useCallback(
7513
7534
  (side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
7514
7535
  [left.items, right.items, keyOf]
7515
7536
  );
@@ -7531,7 +7552,7 @@ function TransferList({
7531
7552
  height: rect.height
7532
7553
  };
7533
7554
  };
7534
- React42.useEffect(() => {
7555
+ React43.useEffect(() => {
7535
7556
  const onMovePointer = (e) => {
7536
7557
  const armed = armedRef.current;
7537
7558
  if (!armed || e.pointerId !== armed.pointerId) return;
@@ -7584,7 +7605,7 @@ function TransferList({
7584
7605
  window.removeEventListener("pointercancel", endDrag);
7585
7606
  };
7586
7607
  }, [hitTestSide, findItem, onMove]);
7587
- React42.useEffect(() => {
7608
+ React43.useEffect(() => {
7588
7609
  if (!drag || typeof document === "undefined") return;
7589
7610
  const prev = document.body.style.userSelect;
7590
7611
  document.body.style.userSelect = "none";
@@ -7701,7 +7722,7 @@ function FactList({ facts = [], className = "", ...rest }) {
7701
7722
  }
7702
7723
 
7703
7724
  // src/components/data/USChoropleth.tsx
7704
- var React44 = __toESM(require("react"), 1);
7725
+ var React45 = __toESM(require("react"), 1);
7705
7726
  init_usStates();
7706
7727
 
7707
7728
  // src/components/data/usChoropleth/mapBox.ts
@@ -7768,11 +7789,11 @@ function buildChoroplethModel(values, topN, givenTotal) {
7768
7789
  }
7769
7790
 
7770
7791
  // src/components/data/usChoropleth/useUsStateShapes.ts
7771
- var React43 = __toESM(require("react"), 1);
7792
+ var React44 = __toESM(require("react"), 1);
7772
7793
  function useUsStateShapes() {
7773
- const [token, setToken] = React43.useState(0);
7774
- const [settled, setSettled] = React43.useState(null);
7775
- React43.useEffect(() => {
7794
+ const [token, setToken] = React44.useState(0);
7795
+ const [settled, setSettled] = React44.useState(null);
7796
+ React44.useEffect(() => {
7776
7797
  let current2 = true;
7777
7798
  Promise.resolve().then(() => (init_usStateShapes(), usStateShapes_exports)).then(({ STATE_SHAPES: STATE_SHAPES2 }) => {
7778
7799
  if (current2) setSettled({ token, state: { status: "ready", shapes: STATE_SHAPES2 } });
@@ -7814,7 +7835,7 @@ function nextCode(key, from) {
7814
7835
  }
7815
7836
  function StateMap({ shapes, model, figures, label, formatReadout }) {
7816
7837
  const tip = useTooltip();
7817
- const [stop, setStop] = React44.useState(US_STATE_CODES[0]);
7838
+ const [stop, setStop] = React45.useState(US_STATE_CODES[0]);
7818
7839
  const onKeyDown = (event) => {
7819
7840
  const from = event.target.getAttribute("data-state");
7820
7841
  const to = from && nextCode(event.key, from);
@@ -7862,8 +7883,8 @@ function StateTable({ model, valueLabel, formatValue }) {
7862
7883
  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
7884
  }
7864
7885
  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]);
7886
+ const model = React45.useMemo(() => buildChoroplethModel(values, topN ?? 0, total), [values, topN, total]);
7887
+ const figures = React45.useMemo(() => new Map(model.rows.map((row) => [row.code, row])), [model]);
7867
7888
  const { state, retry } = useUsStateShapes();
7868
7889
  return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: ["fd-uschoro", className].filter(Boolean).join(" "), children: [
7869
7890
  /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fd-uschoro-layout", children: [
@@ -7901,11 +7922,11 @@ function USChoropleth({ values, label, valueLabel, formatValue, formatReadout, t
7901
7922
  init_usStates();
7902
7923
 
7903
7924
  // src/components/forms/Checkbox.tsx
7904
- var React45 = __toESM(require("react"), 1);
7925
+ var React46 = __toESM(require("react"), 1);
7905
7926
  var import_jsx_runtime70 = require("react/jsx-runtime");
7906
7927
  function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
7907
- const ref = React45.useRef(null);
7908
- React45.useEffect(() => {
7928
+ const ref = React46.useRef(null);
7929
+ React46.useEffect(() => {
7909
7930
  if (ref.current) ref.current.indeterminate = indeterminate;
7910
7931
  }, [indeterminate]);
7911
7932
  return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
@@ -7952,7 +7973,7 @@ function Switch({ label, description, className = "", ...rest }) {
7952
7973
  }
7953
7974
 
7954
7975
  // src/components/forms/Select.tsx
7955
- var React46 = __toESM(require("react"), 1);
7976
+ var React47 = __toESM(require("react"), 1);
7956
7977
  var import_jsx_runtime73 = require("react/jsx-runtime");
7957
7978
  var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
7958
7979
  function Select({
@@ -7980,12 +8001,12 @@ function Select({
7980
8001
  const isOn = (v) => multiple ? vals.includes(v) : v === value;
7981
8002
  const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
7982
8003
  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 });
8004
+ const [open2, setOpen] = React47.useState(false);
8005
+ const [q, setQ] = React47.useState("");
8006
+ const rootRef = React47.useRef(null);
8007
+ const boxRef = React47.useRef(null);
8008
+ const listRef = React47.useRef(null);
8009
+ const typeBuf = React47.useRef({ s: "", t: 0 });
7989
8010
  const selected = multiple ? null : opts.find((o) => o.value === value);
7990
8011
  const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
7991
8012
  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 +8142,7 @@ function Select({
8121
8142
  ),
8122
8143
  q ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
8123
8144
  ] }) : void 0,
8124
- footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(React46.Fragment, { children: [
8145
+ footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(React47.Fragment, { children: [
8125
8146
  /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
8126
8147
  "button",
8127
8148
  {
@@ -8152,7 +8173,7 @@ function Select({
8152
8173
  'Nothing matches "',
8153
8174
  q,
8154
8175
  '".'
8155
- ] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(React46.Fragment, { children: [
8176
+ ] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(React47.Fragment, { children: [
8156
8177
  grp.g ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
8157
8178
  grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
8158
8179
  "button",
@@ -8189,7 +8210,7 @@ function Select({
8189
8210
  }
8190
8211
 
8191
8212
  // src/components/forms/TimePicker.tsx
8192
- var React47 = __toESM(require("react"), 1);
8213
+ var React48 = __toESM(require("react"), 1);
8193
8214
  var import_jsx_runtime74 = require("react/jsx-runtime");
8194
8215
  var pad = (n) => String(n).padStart(2, "0");
8195
8216
  function ClockFace({ value = "09:00", onChange }) {
@@ -8198,9 +8219,9 @@ function ClockFace({ value = "09:00", onChange }) {
8198
8219
  if (isNaN(m)) m = 0;
8199
8220
  const pm = h24 >= 12;
8200
8221
  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);
8222
+ const [mode2, setMode] = React48.useState("h");
8223
+ const faceRef = React48.useRef(null);
8224
+ const dragging = React48.useRef(false);
8204
8225
  const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
8205
8226
  const R = 108, NR = 80;
8206
8227
  const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
@@ -8273,9 +8294,9 @@ function ClockFace({ value = "09:00", onChange }) {
8273
8294
  }
8274
8295
  function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
8275
8296
  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);
8297
+ const [open2, setOpen] = React48.useState(false);
8298
+ const rootRef = React48.useRef(null);
8299
+ const boxRef = React48.useRef(null);
8279
8300
  const disp = () => {
8280
8301
  if (!value) return "";
8281
8302
  const [h, m] = value.split(":").map(Number);
@@ -8318,7 +8339,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
8318
8339
  offset: 6,
8319
8340
  width: 262,
8320
8341
  role: "presentation",
8321
- footer: /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(React47.Fragment, { children: [
8342
+ footer: /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(React48.Fragment, { children: [
8322
8343
  /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
8323
8344
  "button",
8324
8345
  {
@@ -8346,7 +8367,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
8346
8367
  }
8347
8368
 
8348
8369
  // src/components/forms/Slider.tsx
8349
- var React48 = __toESM(require("react"), 1);
8370
+ var React49 = __toESM(require("react"), 1);
8350
8371
  var import_jsx_runtime75 = require("react/jsx-runtime");
8351
8372
  function Slider({
8352
8373
  label,
@@ -8364,7 +8385,7 @@ function Slider({
8364
8385
  ...rest
8365
8386
  }) {
8366
8387
  const fieldId = useFieldId(id);
8367
- const [dragging, setDragging] = React48.useState(false);
8388
+ const [dragging, setDragging] = React49.useState(false);
8368
8389
  const v = value === void 0 ? min : Number(value);
8369
8390
  const pct = max === min ? 0 : (v - min) / (max - min) * 100;
8370
8391
  return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
@@ -8398,7 +8419,7 @@ function Slider({
8398
8419
  }
8399
8420
 
8400
8421
  // src/components/forms/RangeSlider.tsx
8401
- var React49 = __toESM(require("react"), 1);
8422
+ var React50 = __toESM(require("react"), 1);
8402
8423
  var import_jsx_runtime76 = require("react/jsx-runtime");
8403
8424
  function RangeSlider({
8404
8425
  label,
@@ -8418,9 +8439,9 @@ function RangeSlider({
8418
8439
  }) {
8419
8440
  const fmt2 = format || ((v) => String(v));
8420
8441
  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);
8442
+ const [drag, setDrag] = React50.useState(null);
8443
+ const [focus, setFocus] = React50.useState(null);
8444
+ const railRef = React50.useRef(null);
8424
8445
  const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
8425
8446
  const clampPair = (i, v) => {
8426
8447
  v = Math.min(max, Math.max(min, Math.round(v / step) * step));
@@ -8435,7 +8456,7 @@ function RangeSlider({
8435
8456
  const r = railRef.current.getBoundingClientRect();
8436
8457
  return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
8437
8458
  };
8438
- React49.useEffect(() => {
8459
+ React50.useEffect(() => {
8439
8460
  if (drag === null) return;
8440
8461
  const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
8441
8462
  const upH = () => setDrag(null);
@@ -8516,7 +8537,7 @@ function RangeSlider({
8516
8537
  /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
8517
8538
  /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-range-rail", ref: railRef }),
8518
8539
  /* @__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: [
8540
+ marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React50.Fragment, { children: [
8520
8541
  /* @__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
8542
  m.label ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
8522
8543
  ] }, m.value)),
@@ -8545,7 +8566,7 @@ function RangeSlider({
8545
8566
  }
8546
8567
 
8547
8568
  // src/components/forms/Dropzone.tsx
8548
- var React50 = __toESM(require("react"), 1);
8569
+ var React51 = __toESM(require("react"), 1);
8549
8570
  var import_jsx_runtime77 = require("react/jsx-runtime");
8550
8571
  function Dropzone({
8551
8572
  onFiles,
@@ -8560,8 +8581,8 @@ function Dropzone({
8560
8581
  className = "",
8561
8582
  style
8562
8583
  }) {
8563
- const [over, setOver] = React50.useState(false);
8564
- const depth = React50.useRef(0);
8584
+ const [over, setOver] = React51.useState(false);
8585
+ const depth = React51.useRef(0);
8565
8586
  const has = (e) => {
8566
8587
  const dt = e.dataTransfer;
8567
8588
  if (!dt) return false;
@@ -8623,8 +8644,8 @@ function FilePickButton({
8623
8644
  className = "",
8624
8645
  children
8625
8646
  }) {
8626
- const ref = React50.useRef(null);
8627
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(React50.Fragment, { children: [
8647
+ const ref = React51.useRef(null);
8648
+ return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(React51.Fragment, { children: [
8628
8649
  /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8629
8650
  "button",
8630
8651
  {
@@ -8657,10 +8678,10 @@ function FilePickButton({
8657
8678
  }
8658
8679
  function useStagedFiles(upload, opts) {
8659
8680
  const o = opts || {};
8660
- const [items, setItems] = React50.useState([]);
8661
- const controllers = React50.useRef({});
8681
+ const [items, setItems] = React51.useState([]);
8682
+ const controllers = React51.useRef({});
8662
8683
  const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
8663
- const run = React50.useCallback((att) => {
8684
+ const run = React51.useCallback((att) => {
8664
8685
  if (!upload) return;
8665
8686
  const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
8666
8687
  controllers.current[att.id] = ac;
@@ -8677,14 +8698,14 @@ function useStagedFiles(upload, opts) {
8677
8698
  delete controllers.current[att.id];
8678
8699
  });
8679
8700
  }, [upload]);
8680
- const add = React50.useCallback((files) => {
8701
+ const add = React51.useCallback((files) => {
8681
8702
  if (!upload) return [];
8682
8703
  const atts = Array.from(files).map((f) => toAttachment(f));
8683
8704
  setItems((list) => list.concat(atts));
8684
8705
  atts.forEach(run);
8685
8706
  return atts;
8686
8707
  }, [upload, run]);
8687
- const remove = React50.useCallback((att) => {
8708
+ const remove = React51.useCallback((att) => {
8688
8709
  const ac = controllers.current[att.id];
8689
8710
  if (ac) {
8690
8711
  try {
@@ -8695,10 +8716,10 @@ function useStagedFiles(upload, opts) {
8695
8716
  }
8696
8717
  setItems((list) => list.filter((f) => f.id !== att.id));
8697
8718
  }, []);
8698
- const retry = React50.useCallback((att) => {
8719
+ const retry = React51.useCallback((att) => {
8699
8720
  run(att);
8700
8721
  }, [run]);
8701
- const clear = React50.useCallback(() => {
8722
+ const clear = React51.useCallback(() => {
8702
8723
  Object.values(controllers.current).forEach((ac) => {
8703
8724
  try {
8704
8725
  ac && ac.abort();
@@ -8822,7 +8843,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
8822
8843
  }
8823
8844
 
8824
8845
  // src/components/forms/MarkdownEditor.tsx
8825
- var React51 = __toESM(require("react"), 1);
8846
+ var React52 = __toESM(require("react"), 1);
8826
8847
  var import_jsx_runtime79 = require("react/jsx-runtime");
8827
8848
  var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
8828
8849
  var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
@@ -9036,7 +9057,7 @@ function syncDom(root, value) {
9036
9057
  while (root.children.length > lines.length) root.removeChild(root.lastChild);
9037
9058
  }
9038
9059
  var LIST_CONT = RE_LI;
9039
- var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
9060
+ var MarkdownEditor = React52.forwardRef(function MarkdownEditor2({
9040
9061
  value = "",
9041
9062
  onChange,
9042
9063
  onSubmit,
@@ -9055,10 +9076,10 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
9055
9076
  className = "",
9056
9077
  id
9057
9078
  }, ref) {
9058
- const boxRef = React51.useRef(null);
9059
- const composing = React51.useRef(false);
9060
- const pendingCaret = React51.useRef(null);
9061
- React51.useLayoutEffect(() => {
9079
+ const boxRef = React52.useRef(null);
9080
+ const composing = React52.useRef(false);
9081
+ const pendingCaret = React52.useRef(null);
9082
+ React52.useLayoutEffect(() => {
9062
9083
  const root = boxRef.current;
9063
9084
  if (!root || composing.current) return;
9064
9085
  const active = document.activeElement === root || root.contains(document.activeElement);
@@ -9067,7 +9088,7 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
9067
9088
  pendingCaret.current = null;
9068
9089
  if (active && caret != null) placeCaret(root, caret);
9069
9090
  }, [value]);
9070
- React51.useEffect(() => {
9091
+ React52.useEffect(() => {
9071
9092
  if (autoFocus && boxRef.current) boxRef.current.focus();
9072
9093
  }, [autoFocus]);
9073
9094
  const caretNow = () => {
@@ -9134,8 +9155,8 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
9134
9155
  api.replaceRange(from, to, next, from + next.length);
9135
9156
  }
9136
9157
  };
9137
- React51.useImperativeHandle(ref, () => api);
9138
- const caretAtKeydown = React51.useRef(-1);
9158
+ React52.useImperativeHandle(ref, () => api);
9159
+ const caretAtKeydown = React52.useRef(-1);
9139
9160
  function detect(text, caret) {
9140
9161
  if (!onTrigger) return;
9141
9162
  const upto = text.slice(0, caret);
@@ -9288,7 +9309,7 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
9288
9309
  });
9289
9310
 
9290
9311
  // src/components/forms/CodeEditor.tsx
9291
- var React52 = __toESM(require("react"), 1);
9312
+ var React53 = __toESM(require("react"), 1);
9292
9313
  var import_view = require("@codemirror/view");
9293
9314
  var import_state = require("@codemirror/state");
9294
9315
  var import_commands = require("@codemirror/commands");
@@ -9392,16 +9413,16 @@ function CodeEditor({
9392
9413
  const fieldId = useFieldId(id);
9393
9414
  const descId = fieldId + "-desc";
9394
9415
  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);
9416
+ const hostRef = React53.useRef(null);
9417
+ const viewRef = React53.useRef(null);
9418
+ const valueRef = React53.useRef(value);
9419
+ const onChangeRef = React53.useRef(onChange);
9399
9420
  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);
9421
+ const editableCompartment = React53.useRef(new import_state.Compartment()).current;
9422
+ const attributesCompartment = React53.useRef(new import_state.Compartment()).current;
9423
+ const errorRef = React53.useRef(error);
9403
9424
  errorRef.current = error;
9404
- const diagnosticsCountRef = React52.useRef(diagnostics.length);
9425
+ const diagnosticsCountRef = React53.useRef(diagnostics.length);
9405
9426
  diagnosticsCountRef.current = diagnostics.length;
9406
9427
  function contentAttributes() {
9407
9428
  return {
@@ -9411,7 +9432,7 @@ function CodeEditor({
9411
9432
  ...label ? { "aria-label": label } : {}
9412
9433
  };
9413
9434
  }
9414
- React52.useEffect(() => {
9435
+ React53.useEffect(() => {
9415
9436
  const host2 = hostRef.current;
9416
9437
  if (!host2) return;
9417
9438
  const updateListener = import_view.EditorView.updateListener.of((update) => {
@@ -9453,7 +9474,7 @@ function CodeEditor({
9453
9474
  viewRef.current = null;
9454
9475
  };
9455
9476
  }, []);
9456
- React52.useEffect(() => {
9477
+ React53.useEffect(() => {
9457
9478
  const view = viewRef.current;
9458
9479
  if (!view) return;
9459
9480
  const current2 = view.state.doc.toString();
@@ -9462,12 +9483,12 @@ function CodeEditor({
9462
9483
  }
9463
9484
  valueRef.current = value;
9464
9485
  }, [value]);
9465
- React52.useEffect(() => {
9486
+ React53.useEffect(() => {
9466
9487
  const view = viewRef.current;
9467
9488
  if (!view) return;
9468
9489
  view.dispatch({ effects: editableCompartment.reconfigure(import_view.EditorView.editable.of(!disabled)) });
9469
9490
  }, [disabled, editableCompartment]);
9470
- React52.useEffect(() => {
9491
+ React53.useEffect(() => {
9471
9492
  const view = viewRef.current;
9472
9493
  if (!view) return;
9473
9494
  view.dispatch({
@@ -9525,11 +9546,11 @@ function CodeEditor({
9525
9546
  }
9526
9547
 
9527
9548
  // src/components/forms/RadioGroup.tsx
9528
- var React53 = __toESM(require("react"), 1);
9549
+ var React54 = __toESM(require("react"), 1);
9529
9550
  var import_jsx_runtime81 = require("react/jsx-runtime");
9530
9551
  function RadioGroup({ label, labelledBy, options, value, onChange, card = false, disabled = false, name, className = "" }) {
9531
- const autoName = React53.useId();
9532
- const labelId = React53.useId();
9552
+ const autoName = React54.useId();
9553
+ const labelId = React54.useId();
9533
9554
  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
9555
  labelledBy === void 0 && /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { id: labelId, className: "fd-radiogroup-label", children: label }),
9535
9556
  options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
@@ -9557,16 +9578,16 @@ function Fieldset({ busy = false, className = "", ...rest }) {
9557
9578
  }
9558
9579
 
9559
9580
  // src/components/platform/AccountMenu.tsx
9560
- var React55 = __toESM(require("react"), 1);
9581
+ var React56 = __toESM(require("react"), 1);
9561
9582
 
9562
9583
  // src/kits/sessionContext.tsx
9563
- var React54 = __toESM(require("react"), 1);
9564
- var SessionContext = React54.createContext(null);
9584
+ var React55 = __toESM(require("react"), 1);
9585
+ var SessionContext = React55.createContext(null);
9565
9586
  function SessionProvider({ value, children }) {
9566
- return React54.createElement(SessionContext.Provider, { value }, children);
9587
+ return React55.createElement(SessionContext.Provider, { value }, children);
9567
9588
  }
9568
9589
  function useSessionContext() {
9569
- const ctx = React54.useContext(SessionContext);
9590
+ const ctx = React55.useContext(SessionContext);
9570
9591
  if (!ctx) {
9571
9592
  throw new Error(
9572
9593
  "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 +9627,11 @@ function AccountMenu({
9606
9627
  ...rest
9607
9628
  }) {
9608
9629
  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);
9630
+ const [open2, setOpen] = React56.useState(false);
9631
+ const [switching, setSwitching] = React56.useState(false);
9632
+ const [signingOut, setSigningOut] = React56.useState(false);
9633
+ const [signOutError, setSignOutError] = React56.useState(null);
9634
+ const ref = React56.useRef(null);
9614
9635
  const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
9615
9636
  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
9637
  const closeMenu = () => {
@@ -9735,13 +9756,13 @@ function AccountMenu({
9735
9756
  }
9736
9757
 
9737
9758
  // src/components/platform/AppSwitcher.tsx
9738
- var React56 = __toESM(require("react"), 1);
9759
+ var React57 = __toESM(require("react"), 1);
9739
9760
  var import_jsx_runtime84 = require("react/jsx-runtime");
9740
9761
  function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
9741
9762
  const { apps: contextApps } = useSessionContext();
9742
9763
  const apps = appsProp ?? contextApps ?? [];
9743
- const [open2, setOpen] = React56.useState(false);
9744
- const anchorRef = React56.useRef(null);
9764
+ const [open2, setOpen] = React57.useState(false);
9765
+ const anchorRef = React57.useRef(null);
9745
9766
  if (!apps.length) return null;
9746
9767
  const items = apps.map((app) => ({
9747
9768
  id: app.key,
@@ -9755,7 +9776,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
9755
9776
  window.location.href = app.url;
9756
9777
  }
9757
9778
  }));
9758
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(React56.Fragment, { children: [
9779
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(React57.Fragment, { children: [
9759
9780
  /* @__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
9781
  IconButton,
9761
9782
  {
@@ -9784,10 +9805,10 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
9784
9805
  }
9785
9806
 
9786
9807
  // src/components/platform/AppearanceMenu.tsx
9787
- var React59 = __toESM(require("react"), 1);
9808
+ var React60 = __toESM(require("react"), 1);
9788
9809
 
9789
9810
  // src/kits/appearance.ts
9790
- var React57 = __toESM(require("react"), 1);
9811
+ var React58 = __toESM(require("react"), 1);
9791
9812
  var DEFAULT_STORAGE_KEY = "fd-appearance";
9792
9813
  var DEFAULT_PREFS = {
9793
9814
  theme: "system",
@@ -9899,8 +9920,8 @@ function watchAppearance(store, root = document.documentElement) {
9899
9920
  };
9900
9921
  }
9901
9922
  function useAppearancePrefs(store) {
9902
- const prefs = React57.useSyncExternalStore(store.subscribe, store.getSnapshot);
9903
- const update = React57.useCallback(
9923
+ const prefs = React58.useSyncExternalStore(store.subscribe, store.getSnapshot);
9924
+ const update = React58.useCallback(
9904
9925
  (patch) => {
9905
9926
  store.write({ ...store.getSnapshot(), ...patch });
9906
9927
  },
@@ -9910,15 +9931,15 @@ function useAppearancePrefs(store) {
9910
9931
  }
9911
9932
 
9912
9933
  // src/components/platform/AppearanceProvider.tsx
9913
- var React58 = __toESM(require("react"), 1);
9934
+ var React59 = __toESM(require("react"), 1);
9914
9935
  var import_jsx_runtime85 = require("react/jsx-runtime");
9915
- var AppearanceStoreContext = React58.createContext(null);
9936
+ var AppearanceStoreContext = React59.createContext(null);
9916
9937
  function AppearanceProvider({ store, children }) {
9917
- React58.useLayoutEffect(() => watchAppearance(store), [store]);
9938
+ React59.useLayoutEffect(() => watchAppearance(store), [store]);
9918
9939
  return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(AppearanceStoreContext.Provider, { value: store, children });
9919
9940
  }
9920
9941
  function useAppearanceStore() {
9921
- const store = React58.useContext(AppearanceStoreContext);
9942
+ const store = React59.useContext(AppearanceStoreContext);
9922
9943
  if (!store) throw new Error("AppearanceMenu and useAppearanceStore must be rendered inside an <AppearanceProvider>.");
9923
9944
  return store;
9924
9945
  }
@@ -9938,10 +9959,10 @@ var TEXT_SCALE_OPTIONS = [
9938
9959
  ];
9939
9960
  function AppearanceMenu({ className = "" }) {
9940
9961
  const [prefs, update] = useAppearancePrefs(useAppearanceStore());
9941
- const [open2, setOpen] = React59.useState(false);
9942
- const anchorRef = React59.useRef(null);
9962
+ const [open2, setOpen] = React60.useState(false);
9963
+ const anchorRef = React60.useRef(null);
9943
9964
  const patch = (p) => update(p);
9944
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(React59.Fragment, { children: [
9965
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(React60.Fragment, { children: [
9945
9966
  /* @__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
9967
  IconButton,
9947
9968
  {
@@ -10010,14 +10031,14 @@ function AppearanceMenu({ className = "" }) {
10010
10031
  }
10011
10032
 
10012
10033
  // src/components/platform/ApiSpecBrowser.tsx
10013
- var React60 = __toESM(require("react"), 1);
10034
+ var React61 = __toESM(require("react"), 1);
10014
10035
  var import_jsx_runtime87 = require("react/jsx-runtime");
10015
10036
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
10016
10037
  function Json({ obj }) {
10017
10038
  return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
10018
10039
  }
10019
10040
  function Endpoint({ s, onRequest }) {
10020
- const [tried, setTried] = React60.useState(null);
10041
+ const [tried, setTried] = React61.useState(null);
10021
10042
  const run = async () => {
10022
10043
  setTried("busy");
10023
10044
  const t0 = (window.performance || Date).now();
@@ -10090,10 +10111,10 @@ function ApiSpecBrowser({
10090
10111
  className = "",
10091
10112
  ...rest
10092
10113
  }) {
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);
10114
+ const [q, setQ] = React61.useState("");
10115
+ const [method, setMethod] = React61.useState(null);
10116
+ const [mod, setMod] = React61.useState(null);
10117
+ const [listOnly, setListOnly] = React61.useState(false);
10097
10118
  const activeModule = modules && modules.find((m) => m.id === mod);
10098
10119
  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
10120
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
@@ -10172,7 +10193,7 @@ function ApiSpecBrowser({
10172
10193
  }
10173
10194
 
10174
10195
  // src/components/platform/ProfilePage.tsx
10175
- var React61 = __toESM(require("react"), 1);
10196
+ var React62 = __toESM(require("react"), 1);
10176
10197
  var import_jsx_runtime88 = require("react/jsx-runtime");
10177
10198
  function fieldInitialValue(field, user) {
10178
10199
  if (field.value) return field.value(user);
@@ -10208,21 +10229,21 @@ function ProfilePage({
10208
10229
  }) {
10209
10230
  const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
10210
10231
  const user = userProp || sessionUser;
10211
- const initialFieldValues = React61.useMemo(() => {
10232
+ const initialFieldValues = React62.useMemo(() => {
10212
10233
  const values2 = {};
10213
10234
  for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
10214
10235
  return values2;
10215
10236
  }, [user.id, fields]);
10216
- const initialNotify = React61.useMemo(() => {
10237
+ const initialNotify = React62.useMemo(() => {
10217
10238
  const values2 = {};
10218
10239
  for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
10219
10240
  return values2;
10220
10241
  }, [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);
10242
+ const [values, setValues] = React62.useState(initialFieldValues);
10243
+ const [notify, setNotify] = React62.useState(initialNotify);
10244
+ const [saving, setSaving] = React62.useState(false);
10245
+ const [saved, setSaved] = React62.useState(false);
10246
+ const [prevUserId, setPrevUserId] = React62.useState(user.id);
10226
10247
  if (user.id !== prevUserId) {
10227
10248
  setPrevUserId(user.id);
10228
10249
  setValues(initialFieldValues);
@@ -10410,7 +10431,7 @@ function ProfilePage({
10410
10431
  }
10411
10432
 
10412
10433
  // src/components/platform/SessionScreen.tsx
10413
- var React62 = __toESM(require("react"), 1);
10434
+ var React63 = __toESM(require("react"), 1);
10414
10435
  var import_jsx_runtime89 = require("react/jsx-runtime");
10415
10436
  var COPY = {
10416
10437
  "signing-in": { busy: "Signing you in\u2026" },
@@ -10424,13 +10445,13 @@ function SessionScreen({ kind, error, onRetry, productName }) {
10424
10445
  const copy = COPY[kind];
10425
10446
  const busyMessage = "busy" in copy ? copy.busy : null;
10426
10447
  const failureTitle = "failure" in copy ? copy.failure : null;
10427
- const [announced, setAnnounced] = React62.useState("");
10428
- React62.useEffect(() => {
10448
+ const [announced, setAnnounced] = React63.useState("");
10449
+ React63.useEffect(() => {
10429
10450
  setAnnounced(busyMessage ?? "");
10430
10451
  }, [busyMessage]);
10431
- const titleRef = React62.useRef(null);
10452
+ const titleRef = React63.useRef(null);
10432
10453
  const failed = failureTitle !== null;
10433
- React62.useEffect(() => {
10454
+ React63.useEffect(() => {
10434
10455
  titleRef.current?.focus({ preventScroll: true });
10435
10456
  }, [failed]);
10436
10457
  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 +10474,10 @@ function SessionScreen({ kind, error, onRetry, productName }) {
10453
10474
  }
10454
10475
 
10455
10476
  // src/components/platform/RoadmapTimeline.tsx
10456
- var React65 = __toESM(require("react"), 1);
10477
+ var React66 = __toESM(require("react"), 1);
10457
10478
 
10458
10479
  // src/kits/session.ts
10459
- var React63 = __toESM(require("react"), 1);
10480
+ var React64 = __toESM(require("react"), 1);
10460
10481
  var PERMISSION_CATALOG = [
10461
10482
  { group: "Plans", items: [
10462
10483
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -12023,8 +12044,8 @@ function roadmap(overrides) {
12023
12044
  };
12024
12045
  }
12025
12046
  function useSession() {
12026
- const [s, setS] = React63.useState(getSession);
12027
- React63.useEffect(() => subscribe(setS), []);
12047
+ const [s, setS] = React64.useState(getSession);
12048
+ React64.useEffect(() => subscribe(setS), []);
12028
12049
  return s;
12029
12050
  }
12030
12051
  var SessionKit = {
@@ -12057,7 +12078,7 @@ var SessionKit = {
12057
12078
  };
12058
12079
  function DemoSessionProvider({ children }) {
12059
12080
  const session = useSession();
12060
- const value = React63.useMemo(
12081
+ const value = React64.useMemo(
12061
12082
  () => ({
12062
12083
  user: session.user,
12063
12084
  roles: session.roles,
@@ -12073,11 +12094,11 @@ function DemoSessionProvider({ children }) {
12073
12094
  }),
12074
12095
  [session]
12075
12096
  );
12076
- return React63.createElement(SessionProvider, { value }, children);
12097
+ return React64.createElement(SessionProvider, { value }, children);
12077
12098
  }
12078
12099
 
12079
12100
  // src/kits/runtime.ts
12080
- var React64 = __toESM(require("react"), 1);
12101
+ var React65 = __toESM(require("react"), 1);
12081
12102
  var WIRED_ENDPOINTS = [
12082
12103
  // Nothing yet. Every id below would come from a real service:
12083
12104
  // "plan.get", "placements.list", …
@@ -12248,8 +12269,8 @@ var RuntimeKit = {
12248
12269
  };
12249
12270
  RuntimeKit.declare(FEATURE_NEEDS);
12250
12271
  function useRuntimeMode() {
12251
- const [m, setM] = React64.useState(RuntimeKit.getMode());
12252
- React64.useEffect(() => RuntimeKit.subscribe(setM), []);
12272
+ const [m, setM] = React65.useState(RuntimeKit.getMode());
12273
+ React65.useEffect(() => RuntimeKit.subscribe(setM), []);
12253
12274
  return m;
12254
12275
  }
12255
12276
  function useFeatureStatus(key) {
@@ -12332,12 +12353,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
12332
12353
  }
12333
12354
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12334
12355
  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(() => {
12356
+ const [project, setProject] = React66.useState("");
12357
+ const [q, setQ] = React66.useState("");
12358
+ const scrollRef = React66.useRef(null);
12359
+ const nowRef = React66.useRef(null);
12360
+ const rm = React66.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
12361
+ const byKey = React66.useMemo(() => {
12341
12362
  const m = {};
12342
12363
  rm.items.forEach((i) => {
12343
12364
  m[i.key] = i;
@@ -12346,7 +12367,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12346
12367
  }, [rm]);
12347
12368
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
12348
12369
  const projects = [...new Set(rm.items.map((i) => i.project))];
12349
- React65.useEffect(() => {
12370
+ React66.useEffect(() => {
12350
12371
  let raf1 = 0, raf2 = 0;
12351
12372
  const place = () => {
12352
12373
  const box = scrollRef.current, mark = nowRef.current;
@@ -12420,7 +12441,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12420
12441
  lastPhase = item.phase;
12421
12442
  const inPhase = items.filter((i) => i.phase === item.phase).length;
12422
12443
  const isBoundary = n === firstPending;
12423
- return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(React65.Fragment, { children: [
12444
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(React66.Fragment, { children: [
12424
12445
  showPhase ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "fd-rm-era", children: [
12425
12446
  /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
12426
12447
  /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
@@ -12464,7 +12485,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12464
12485
  }
12465
12486
 
12466
12487
  // src/components/platform/ComingSoon.tsx
12467
- var React66 = __toESM(require("react"), 1);
12488
+ var React67 = __toESM(require("react"), 1);
12468
12489
  var import_react_dom7 = require("react-dom");
12469
12490
  var import_jsx_runtime91 = require("react/jsx-runtime");
12470
12491
  var BYPASS_STORE = "fd.soon.bypass.v1";
@@ -12482,8 +12503,8 @@ function writeBypassed(list) {
12482
12503
  }
12483
12504
  }
12484
12505
  function useBypass(key) {
12485
- const [on, setOn] = React66.useState(() => !!key && readBypassed().indexOf(key) >= 0);
12486
- React66.useEffect(() => {
12506
+ const [on, setOn] = React67.useState(() => !!key && readBypassed().indexOf(key) >= 0);
12507
+ React67.useEffect(() => {
12487
12508
  setOn(!!key && readBypassed().indexOf(key) >= 0);
12488
12509
  }, [key]);
12489
12510
  const set = (next) => {
@@ -12530,9 +12551,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
12530
12551
  ] });
12531
12552
  }
12532
12553
  function useHoverCard(open2) {
12533
- const anchor = React66.useRef(null);
12534
- const [pos, setPos] = React66.useState(null);
12535
- React66.useLayoutEffect(() => {
12554
+ const anchor = React67.useRef(null);
12555
+ const [pos, setPos] = React67.useState(null);
12556
+ React67.useLayoutEffect(() => {
12536
12557
  if (!open2 || !anchor.current) {
12537
12558
  setPos(null);
12538
12559
  return;
@@ -12659,12 +12680,12 @@ function ComingSoon({
12659
12680
  ] });
12660
12681
  }
12661
12682
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
12662
- const [open2, setOpen] = React66.useState(false);
12683
+ const [open2, setOpen] = React67.useState(false);
12663
12684
  const [anchor, pos] = useHoverCard(open2);
12664
- const hoverCardRef = React66.useRef(null);
12685
+ const hoverCardRef = React67.useRef(null);
12665
12686
  const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
12666
12687
  const zIndex = useLayerZIndex(hoverLayer);
12667
- const close2 = React66.useRef(null);
12688
+ const close2 = React67.useRef(null);
12668
12689
  const show = () => {
12669
12690
  if (close2.current) {
12670
12691
  clearTimeout(close2.current);
@@ -12680,7 +12701,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
12680
12701
  setOpen(false);
12681
12702
  }, 140);
12682
12703
  };
12683
- React66.useEffect(() => () => {
12704
+ React67.useEffect(() => () => {
12684
12705
  if (close2.current) clearTimeout(close2.current);
12685
12706
  }, []);
12686
12707
  return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
@@ -13132,7 +13153,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
13132
13153
  }
13133
13154
 
13134
13155
  // src/components/planner/MixGap.tsx
13135
- var React67 = __toESM(require("react"), 1);
13156
+ var React68 = __toESM(require("react"), 1);
13136
13157
  var import_jsx_runtime96 = require("react/jsx-runtime");
13137
13158
  var MIX_GAP_LAYOUT = {
13138
13159
  trackHeight: 30,
@@ -13147,7 +13168,7 @@ function mixGapOffset(value, max) {
13147
13168
  }
13148
13169
  function MixGap({ rows = [], loading = false, className = "" }) {
13149
13170
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
13150
- const [hover, setHover] = React67.useState(null);
13171
+ const [hover, setHover] = React68.useState(null);
13151
13172
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
13152
13173
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
13153
13174
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
@@ -13290,7 +13311,7 @@ function ChannelContribution({
13290
13311
  }
13291
13312
 
13292
13313
  // src/components/planner/BudgetReallocator.tsx
13293
- var React68 = __toESM(require("react"), 1);
13314
+ var React69 = __toESM(require("react"), 1);
13294
13315
  var import_jsx_runtime98 = require("react/jsx-runtime");
13295
13316
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
13296
13317
  function BudgetReallocator({
@@ -13306,8 +13327,8 @@ function BudgetReallocator({
13306
13327
  onCancel,
13307
13328
  className = ""
13308
13329
  }) {
13309
- const [draft, setDraft] = React68.useState(spend);
13310
- React68.useEffect(() => setDraft(spend), [spend]);
13330
+ const [draft, setDraft] = React69.useState(spend);
13331
+ React69.useEffect(() => setDraft(spend), [spend]);
13311
13332
  const dirty = draft !== spend;
13312
13333
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
13313
13334
  const nextBand = bandFor(nextCrp);
@@ -13322,10 +13343,10 @@ function BudgetReallocator({
13322
13343
  setDraft(spend);
13323
13344
  if (onCancel) onCancel();
13324
13345
  };
13325
- const trackRef = React68.useRef(null);
13326
- const chipRef = React68.useRef(null);
13327
- const [chipLeft, setChipLeft] = React68.useState(null);
13328
- React68.useLayoutEffect(() => {
13346
+ const trackRef = React69.useRef(null);
13347
+ const chipRef = React69.useRef(null);
13348
+ const [chipLeft, setChipLeft] = React69.useState(null);
13349
+ React69.useLayoutEffect(() => {
13329
13350
  const track = trackRef.current;
13330
13351
  if (!dirty || !track) {
13331
13352
  setChipLeft(null);
@@ -13513,7 +13534,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
13513
13534
  }
13514
13535
 
13515
13536
  // src/components/planner/PreferenceMeter.tsx
13516
- var React69 = __toESM(require("react"), 1);
13537
+ var React70 = __toESM(require("react"), 1);
13517
13538
  var import_jsx_runtime101 = require("react/jsx-runtime");
13518
13539
  function preferenceScore(criteria) {
13519
13540
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
@@ -13543,7 +13564,7 @@ function PreferenceMeter({
13543
13564
  className = ""
13544
13565
  }) {
13545
13566
  const value = score == null ? preferenceScore(criteria) : score;
13546
- const segments = React69.useMemo(() => preferenceSegments(criteria), [criteria]);
13567
+ const segments = React70.useMemo(() => preferenceSegments(criteria), [criteria]);
13547
13568
  return /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
13548
13569
  ScoreMeter,
13549
13570
  {
@@ -13582,13 +13603,13 @@ function PreferenceMeter({
13582
13603
  }
13583
13604
 
13584
13605
  // src/components/chat/AgentChatPanel.tsx
13585
- var React76 = __toESM(require("react"), 1);
13606
+ var React77 = __toESM(require("react"), 1);
13586
13607
 
13587
13608
  // src/components/chat/chatEngine.ts
13588
- var React71 = __toESM(require("react"), 1);
13609
+ var React72 = __toESM(require("react"), 1);
13589
13610
 
13590
13611
  // src/components/chat/chatStore.ts
13591
- var React70 = __toESM(require("react"), 1);
13612
+ var React71 = __toESM(require("react"), 1);
13592
13613
  var safeStore = {
13593
13614
  get(k) {
13594
13615
  try {
@@ -13617,13 +13638,13 @@ function useChatDraft(owner, contextType, contextId, store = safeStore) {
13617
13638
  if (owner === "") throw new Error("useChatDraft: draftOwner is an empty string; pass the signed-in user's id, or null for no owner.");
13618
13639
  const key = owner === null ? null : draftKey(owner, contextType, contextId);
13619
13640
  const read2 = (k) => k ? store.get(k) || "" : "";
13620
- const [state, setState] = React70.useState(() => ({ key, text: read2(key) }));
13641
+ const [state, setState] = React71.useState(() => ({ key, text: read2(key) }));
13621
13642
  let current2 = state;
13622
13643
  if (state.key !== key) {
13623
13644
  current2 = { key, text: read2(key) };
13624
13645
  setState(current2);
13625
13646
  }
13626
- const setText = React70.useCallback((text) => {
13647
+ const setText = React71.useCallback((text) => {
13627
13648
  if (key) {
13628
13649
  if (text) {
13629
13650
  store.set(key, text);
@@ -13682,33 +13703,33 @@ function useChatEngine(opts) {
13682
13703
  onClear,
13683
13704
  onFeedback
13684
13705
  } = 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(() => {
13706
+ const [status, setStatus] = React72.useState("idle");
13707
+ const [threadId, setThreadId] = React72.useState(null);
13708
+ const [messages, setMessages] = React72.useState([]);
13709
+ const [queue, setQueue] = React72.useState([]);
13710
+ const [fatal, setFatal] = React72.useState(null);
13711
+ const [busy, setBusy] = React72.useState(false);
13712
+ const [turnStartedAt, setTurnStartedAt] = React72.useState(null);
13713
+ const listRef = React72.useRef([]);
13714
+ const queueRef = React72.useRef([]);
13715
+ const busyRef = React72.useRef(false);
13716
+ const loadedRef = React72.useRef(false);
13717
+ const stoppedRef = React72.useRef(false);
13718
+ const abortRef = React72.useRef(null);
13719
+ const serverCount = React72.useRef(0);
13720
+ const serverIds = React72.useRef(/* @__PURE__ */ new Set());
13721
+ const liveTurn = React72.useRef(null);
13722
+ const lastTurnOwn = React72.useRef(/* @__PURE__ */ new Set());
13723
+ const retired = React72.useRef(/* @__PURE__ */ new Set());
13724
+ const threadRef = React72.useRef(null);
13725
+ const mounted = React72.useRef(true);
13726
+ React72.useEffect(() => {
13706
13727
  mounted.current = true;
13707
13728
  return () => {
13708
13729
  mounted.current = false;
13709
13730
  };
13710
13731
  }, []);
13711
- const describeWaitingRef = React71.useRef(describeWaiting);
13732
+ const describeWaitingRef = React72.useRef(describeWaiting);
13712
13733
  describeWaitingRef.current = describeWaiting;
13713
13734
  const commit = (next) => {
13714
13735
  const derived = withWaiting(next, (pending) => describeWaitingRef.current(pending));
@@ -13727,7 +13748,7 @@ function useChatEngine(opts) {
13727
13748
  }
13728
13749
  return false;
13729
13750
  };
13730
- const loadThread = React71.useCallback(async (id) => {
13751
+ const loadThread = React72.useCallback(async (id) => {
13731
13752
  const data = await apiAdapter.getThread(id);
13732
13753
  const list = [...data && data.messages || []];
13733
13754
  serverCount.current = list.length;
@@ -13767,7 +13788,7 @@ function useChatEngine(opts) {
13767
13788
  packet: progress.packet ?? holder.packet
13768
13789
  });
13769
13790
  }
13770
- React71.useEffect(() => {
13791
+ React72.useEffect(() => {
13771
13792
  if (!apiAdapter) {
13772
13793
  setStatus("idle");
13773
13794
  setFatal(null);
@@ -13999,7 +14020,7 @@ function useChatEngine(opts) {
13999
14020
  await dispatchTurn(turn);
14000
14021
  }
14001
14022
  }
14002
- const send = React71.useCallback((text, attachments) => {
14023
+ const send = React72.useCallback((text, attachments) => {
14003
14024
  const body = (text || "").trim();
14004
14025
  if (!body && !(attachments && attachments.length)) return;
14005
14026
  if (status === "disconnected") return;
@@ -14009,7 +14030,7 @@ function useChatEngine(opts) {
14009
14030
  stoppedRef.current = false;
14010
14031
  drain();
14011
14032
  }, [status]);
14012
- const stop = React71.useCallback(() => {
14033
+ const stop = React72.useCallback(() => {
14013
14034
  stoppedRef.current = true;
14014
14035
  const ac = abortRef.current;
14015
14036
  if (ac) {
@@ -14028,11 +14049,11 @@ function useChatEngine(opts) {
14028
14049
  store.del(jobKey(threadRef.current));
14029
14050
  }
14030
14051
  }, [apiAdapter]);
14031
- const removeQueued = React71.useCallback((id) => {
14052
+ const removeQueued = React72.useCallback((id) => {
14032
14053
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
14033
14054
  setQueue(queueRef.current.slice());
14034
14055
  }, []);
14035
- const retry = React71.useCallback(() => {
14056
+ const retry = React72.useCallback(() => {
14036
14057
  const list = listRef.current;
14037
14058
  let at = -1;
14038
14059
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -14049,19 +14070,19 @@ function useChatEngine(opts) {
14049
14070
  setQueue(queueRef.current.slice());
14050
14071
  drain();
14051
14072
  }, []);
14052
- const clear = React71.useCallback(() => {
14073
+ const clear = React72.useCallback(() => {
14053
14074
  commit([]);
14054
14075
  serverCount.current = 0;
14055
14076
  queueRef.current = [];
14056
14077
  setQueue([]);
14057
14078
  onClear && onClear();
14058
14079
  }, [onClear]);
14059
- const setFeedback = React71.useCallback((id, value) => {
14080
+ const setFeedback = React72.useCallback((id, value) => {
14060
14081
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
14061
14082
  const msg = listRef.current.find((m) => m.id === id);
14062
14083
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
14063
14084
  }, [onFeedback]);
14064
- const reload = React71.useCallback(async () => {
14085
+ const reload = React72.useCallback(async () => {
14065
14086
  if (!threadRef.current) return;
14066
14087
  setStatus("loading");
14067
14088
  try {
@@ -14099,10 +14120,10 @@ var ChatKit = {
14099
14120
  };
14100
14121
 
14101
14122
  // src/components/chat/ChatTranscript.tsx
14102
- var React73 = __toESM(require("react"), 1);
14123
+ var React74 = __toESM(require("react"), 1);
14103
14124
 
14104
14125
  // src/components/chat/ChatTurn.tsx
14105
- var React72 = __toESM(require("react"), 1);
14126
+ var React73 = __toESM(require("react"), 1);
14106
14127
  var import_jsx_runtime102 = require("react/jsx-runtime");
14107
14128
  function JsonView({ value }) {
14108
14129
  let text;
@@ -14139,7 +14160,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
14139
14160
  ] });
14140
14161
  }
14141
14162
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
14142
- const [open2, setOpen] = React72.useState(defaultOpen);
14163
+ const [open2, setOpen] = React73.useState(defaultOpen);
14143
14164
  if (!text) return null;
14144
14165
  return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
14145
14166
  /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -14156,7 +14177,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
14156
14177
  ] });
14157
14178
  }
14158
14179
  function Citations({ items = [], onOpen }) {
14159
- const [open2, setOpen] = React72.useState(false);
14180
+ const [open2, setOpen] = React73.useState(false);
14160
14181
  if (!items.length) return null;
14161
14182
  return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-cites", children: [
14162
14183
  /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -14182,7 +14203,7 @@ function clampText(text, max) {
14182
14203
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
14183
14204
  }
14184
14205
  function MessageBody({ message: m, ctx }) {
14185
- const [expanded, setExpanded] = React72.useState(false);
14206
+ const [expanded, setExpanded] = React73.useState(false);
14186
14207
  const isUser = m.role === "user";
14187
14208
  const raw = m.text || "";
14188
14209
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
@@ -14261,7 +14282,7 @@ function RunActions({ group, ctx }) {
14261
14282
  ] }),
14262
14283
  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
14284
  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: [
14285
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)(React73.Fragment, { children: [
14265
14286
  /* @__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
14287
  /* @__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
14288
  ] }) : null,
@@ -14356,10 +14377,10 @@ function ChatTranscript({
14356
14377
  renderEmpty,
14357
14378
  className = ""
14358
14379
  }) {
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);
14380
+ const scroller = React74.useRef(null);
14381
+ const stick = React74.useRef(true);
14382
+ const [pill, setPill] = React74.useState(0);
14383
+ const seen = React74.useRef(0);
14363
14384
  const toBottom = (smooth) => {
14364
14385
  const el = scroller.current;
14365
14386
  if (!el) return;
@@ -14378,7 +14399,7 @@ function ChatTranscript({
14378
14399
  seen.current = messages.length;
14379
14400
  }
14380
14401
  };
14381
- React73.useLayoutEffect(() => {
14402
+ React74.useLayoutEffect(() => {
14382
14403
  const el = scroller.current;
14383
14404
  if (!el) return;
14384
14405
  if (stick.current) {
@@ -14386,7 +14407,7 @@ function ChatTranscript({
14386
14407
  seen.current = messages.length;
14387
14408
  } else setPill(Math.max(0, messages.length - seen.current));
14388
14409
  }, [messages]);
14389
- React73.useEffect(() => {
14410
+ React74.useEffect(() => {
14390
14411
  const el = scroller.current;
14391
14412
  const inner = el && el.firstChild;
14392
14413
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -14396,7 +14417,7 @@ function ChatTranscript({
14396
14417
  ro.observe(inner);
14397
14418
  return () => ro.disconnect();
14398
14419
  }, []);
14399
- const groups = React73.useMemo(() => groupMessages(messages), [messages]);
14420
+ const groups = React74.useMemo(() => groupMessages(messages), [messages]);
14400
14421
  const empty = !messages.length && status === "ready";
14401
14422
  return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
14402
14423
  /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
@@ -14420,7 +14441,7 @@ function ChatTranscript({
14420
14441
  const prev = groups[i - 1];
14421
14442
  const k = dayKey(g.messages[0].timestamp);
14422
14443
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
14423
- return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)(React73.Fragment, { children: [
14444
+ return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)(React74.Fragment, { children: [
14424
14445
  showDay ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { children: dayLabel(k) }) }) : null,
14425
14446
  /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(ChatTurn, { group: g, ctx })
14426
14447
  ] }, g.key || i);
@@ -14437,7 +14458,7 @@ function ChatTranscript({
14437
14458
  var TranscriptKit = { groupMessages };
14438
14459
 
14439
14460
  // src/components/chat/ChatComposer.tsx
14440
- var React74 = __toESM(require("react"), 1);
14461
+ var React75 = __toESM(require("react"), 1);
14441
14462
  var import_jsx_runtime104 = require("react/jsx-runtime");
14442
14463
  function ChatComposer({
14443
14464
  onSubmit,
@@ -14465,17 +14486,17 @@ function ChatComposer({
14465
14486
  onReject,
14466
14487
  onOpenAttachment
14467
14488
  }) {
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);
14489
+ const [text, setText] = React75.useState(draft || "");
14490
+ const [trigger, setTrigger] = React75.useState(null);
14491
+ const [mentionItems, setMentionItems] = React75.useState([]);
14492
+ const [listening, setListening] = React75.useState(false);
14493
+ const [notice, setNotice] = React75.useState(null);
14494
+ const editor = React75.useRef(null);
14495
+ const wrap = React75.useRef(null);
14496
+ const stopVoice = React75.useRef(null);
14476
14497
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
14477
14498
  } });
14478
- React74.useEffect(() => {
14499
+ React75.useEffect(() => {
14479
14500
  if (draft != null && draft !== text) setText(draft);
14480
14501
  }, [draft]);
14481
14502
  const change = (v) => {
@@ -14511,7 +14532,7 @@ function ChatComposer({
14511
14532
  e.preventDefault();
14512
14533
  staged.add(found.files);
14513
14534
  };
14514
- React74.useEffect(() => {
14535
+ React75.useEffect(() => {
14515
14536
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
14516
14537
  setMentionItems([]);
14517
14538
  return;
@@ -14529,7 +14550,7 @@ function ChatComposer({
14529
14550
  const q = (trigger.query || "").toLowerCase();
14530
14551
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
14531
14552
  }, [trigger, mentionSources]);
14532
- const slashItems = React74.useMemo(() => {
14553
+ const slashItems = React75.useMemo(() => {
14533
14554
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
14534
14555
  const q = (trigger.query || "").toLowerCase();
14535
14556
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -14699,12 +14720,12 @@ function ChatComposer({
14699
14720
  }
14700
14721
 
14701
14722
  // src/components/chat/ChatSessionBar.tsx
14702
- var React75 = __toESM(require("react"), 1);
14723
+ var React76 = __toESM(require("react"), 1);
14703
14724
  var import_jsx_runtime105 = require("react/jsx-runtime");
14704
14725
  var compact2 = meterFormats.compact;
14705
14726
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
14706
- const [open2, setOpen] = React75.useState(false);
14707
- const anchor = React75.useRef(null);
14727
+ const [open2, setOpen] = React76.useState(false);
14728
+ const anchor = React76.useRef(null);
14708
14729
  const stats = sessionStats || null;
14709
14730
  const cu = contextUsage || null;
14710
14731
  const limits = usageLimits || null;
@@ -14719,7 +14740,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
14719
14740
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
14720
14741
  if (cu) bits.push(pct + "% context");
14721
14742
  const expandable = !!(cu || limits);
14722
- return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(React75.Fragment, { children: [
14743
+ return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(React76.Fragment, { children: [
14723
14744
  /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("div", { className: "fdc-bar", children: [
14724
14745
  /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(
14725
14746
  "button",
@@ -14860,7 +14881,7 @@ function ModelControls({
14860
14881
  ] })
14861
14882
  });
14862
14883
  }
14863
- return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(React75.Fragment, { children: [
14884
+ return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(React76.Fragment, { children: [
14864
14885
  /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
14865
14886
  MenuButton,
14866
14887
  {
@@ -14980,11 +15001,11 @@ function AgentChatPanel({
14980
15001
  onFeedback,
14981
15002
  onEditMessage
14982
15003
  }) {
14983
- const [panelWidth, setPanelWidth] = React76.useState(width);
14984
- const [applied, setApplied] = React76.useState({});
15004
+ const [panelWidth, setPanelWidth] = React77.useState(width);
15005
+ const [applied, setApplied] = React77.useState({});
14985
15006
  const [draft, setDraft] = useChatDraft(draftOwner, contextType, contextId);
14986
- const dragging = React76.useRef(null);
14987
- React76.useEffect(() => setPanelWidth(width), [width]);
15007
+ const dragging = React77.useRef(null);
15008
+ React77.useEffect(() => setPanelWidth(width), [width]);
14988
15009
  const engine = useChatEngine({
14989
15010
  contextType,
14990
15011
  contextId,
@@ -15190,7 +15211,7 @@ function AgentChatPanel({
15190
15211
  }
15191
15212
 
15192
15213
  // src/components/files/FileViewer.tsx
15193
- var React77 = __toESM(require("react"), 1);
15214
+ var React78 = __toESM(require("react"), 1);
15194
15215
  var import_jsx_runtime107 = require("react/jsx-runtime");
15195
15216
  function previewKindOf(file) {
15196
15217
  const mime = (file.mime || "").toLowerCase();
@@ -15247,13 +15268,13 @@ function parseDelimited(text, delimiter) {
15247
15268
  return rows;
15248
15269
  }
15249
15270
  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(() => {
15271
+ const [state, setState] = React78.useState({ status: "loading" });
15272
+ const [attempt, setAttempt] = React78.useState(0);
15273
+ const resolveRef = React78.useRef(resolveUrl);
15274
+ React78.useEffect(() => {
15254
15275
  resolveRef.current = resolveUrl;
15255
15276
  }, [resolveUrl]);
15256
- React77.useEffect(() => {
15277
+ React78.useEffect(() => {
15257
15278
  if (kind === "none") {
15258
15279
  setState({ status: "ready" });
15259
15280
  return;
@@ -15283,7 +15304,7 @@ function usePreview(file, kind, resolveUrl) {
15283
15304
  if (ac) ac.abort();
15284
15305
  };
15285
15306
  }, [file.id, kind, attempt]);
15286
- return { ...state, retry: React77.useCallback(() => setAttempt((a) => a + 1), []) };
15307
+ return { ...state, retry: React78.useCallback(() => setAttempt((a) => a + 1), []) };
15287
15308
  }
15288
15309
  function PreviewBody({ file, kind, state }) {
15289
15310
  if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
@@ -15328,13 +15349,13 @@ function PreviewBody({ file, kind, state }) {
15328
15349
  ] });
15329
15350
  }
15330
15351
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
15331
- const kind = React77.useMemo(() => previewKindOf(file), [file]);
15352
+ const kind = React78.useMemo(() => previewKindOf(file), [file]);
15332
15353
  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);
15354
+ const [tab, setTab] = React78.useState("preview");
15355
+ const [downloading, setDownloading] = React78.useState(false);
15356
+ const [downloadError, setDownloadError] = React78.useState(null);
15336
15357
  const hasSide = sidePanel != null;
15337
- React77.useEffect(() => {
15358
+ React78.useEffect(() => {
15338
15359
  setTab("preview");
15339
15360
  }, [file.id]);
15340
15361
  const download = () => {
@@ -15401,7 +15422,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
15401
15422
  }
15402
15423
 
15403
15424
  // src/components/files/FileBrowser.tsx
15404
- var React78 = __toESM(require("react"), 1);
15425
+ var React79 = __toESM(require("react"), 1);
15405
15426
  var import_jsx_runtime108 = require("react/jsx-runtime");
15406
15427
  function childrenOf(folders, parentId) {
15407
15428
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
@@ -15511,8 +15532,8 @@ function FolderPickerMenu({
15511
15532
  ] });
15512
15533
  }
15513
15534
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
15514
- const [over, setOver] = React78.useState(false);
15515
- const dragCounter = React78.useRef(0);
15535
+ const [over, setOver] = React79.useState(false);
15536
+ const dragCounter = React79.useRef(0);
15516
15537
  const dropHandlers = isDropTarget ? {
15517
15538
  onDragEnter: (e) => {
15518
15539
  if (!hasInternalPayload(e)) return;
@@ -15560,8 +15581,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
15560
15581
  }
15561
15582
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
15562
15583
  const kids = childrenOf(folders, folder.id);
15563
- const [expanded, setExpanded] = React78.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
15564
- React78.useEffect(() => {
15584
+ const [expanded, setExpanded] = React79.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
15585
+ React79.useEffect(() => {
15565
15586
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
15566
15587
  }, [currentFolderId, folder.id, folders]);
15567
15588
  const isCurrent = folder.id === currentFolderId;
@@ -15627,15 +15648,15 @@ function FileBrowser({
15627
15648
  const canUpload = perm.canUpload !== false && !!onUpload;
15628
15649
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
15629
15650
  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(
15651
+ const [createOpen, setCreateOpen] = React79.useState(false);
15652
+ const [createName, setCreateName] = React79.useState("");
15653
+ const [renameTarget, setRenameTarget] = React79.useState(null);
15654
+ const [renameValue, setRenameValue] = React79.useState("");
15655
+ const [deleteTarget, setDeleteTarget] = React79.useState(null);
15656
+ const uploadInputRef = React79.useRef(null);
15657
+ const crumbFolders = React79.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
15658
+ const subfolders = React79.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
15659
+ const currentFiles = React79.useMemo(
15639
15660
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
15640
15661
  [files, currentFolderId]
15641
15662
  );
@@ -15867,8 +15888,8 @@ function BreadcrumbCrumb({
15867
15888
  isDropTarget,
15868
15889
  onDropPayload
15869
15890
  }) {
15870
- const [over, setOver] = React78.useState(false);
15871
- const dragCounter = React78.useRef(0);
15891
+ const [over, setOver] = React79.useState(false);
15892
+ const dragCounter = React79.useRef(0);
15872
15893
  const dropHandlers = isDropTarget ? {
15873
15894
  onDragEnter: (e) => {
15874
15895
  if (!hasInternalPayload(e)) return;
@@ -15897,7 +15918,7 @@ function BreadcrumbCrumb({
15897
15918
  }
15898
15919
 
15899
15920
  // src/kits/query.ts
15900
- var React79 = __toESM(require("react"), 1);
15921
+ var React80 = __toESM(require("react"), 1);
15901
15922
 
15902
15923
  // src/kits/queryUrl.ts
15903
15924
  var historyUrlAdapter = {
@@ -16035,38 +16056,38 @@ function requestFor(params, query, paging, after) {
16035
16056
  }
16036
16057
  var toError = (e) => e instanceof Error ? e : new Error(String(e));
16037
16058
  function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "page", url }) {
16038
- const [base] = React79.useState(() => {
16059
+ const [base] = React80.useState(() => {
16039
16060
  const store = PREFS || window.PlannerPrefs;
16040
16061
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
16041
16062
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
16042
16063
  });
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) => {
16064
+ const [mountParams] = React80.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
16065
+ const address = React80.useRef(mountParams);
16066
+ const [query, setQuery] = React80.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
16067
+ const savePref = React80.useCallback((patch2) => {
16047
16068
  const store = PREFS || window.PlannerPrefs;
16048
16069
  if (prefsKey && store) store.setTable(prefsKey, patch2);
16049
16070
  }, [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);
16071
+ const [res, setRes] = React80.useState(null);
16072
+ const [loading, setLoading] = React80.useState(true);
16073
+ const [loadingMore, setLoadingMore] = React80.useState(false);
16074
+ const [failure, setFailure] = React80.useState(null);
16075
+ const [reloadToken, setReloadToken] = React80.useState(0);
16076
+ const moreController = React80.useRef(null);
16056
16077
  const depKey = (deps || []).join("|");
16057
16078
  const paramKey = JSON.stringify(params || {});
16058
16079
  const queryKey = JSON.stringify(query);
16059
- const lifetime = React79.useRef(null);
16060
- React79.useEffect(() => {
16080
+ const lifetime = React80.useRef(null);
16081
+ React80.useEffect(() => {
16061
16082
  const controller = new AbortController();
16062
16083
  lifetime.current = controller;
16063
16084
  return () => controller.abort();
16064
16085
  }, []);
16065
- const latest = React79.useRef({ res, loading, query, params, endpoint, url, base });
16066
- React79.useLayoutEffect(() => {
16086
+ const latest = React80.useRef({ res, loading, query, params, endpoint, url, base });
16087
+ React80.useLayoutEffect(() => {
16067
16088
  latest.current = { res, loading, query, params, endpoint, url, base };
16068
16089
  });
16069
- React79.useEffect(() => {
16090
+ React80.useEffect(() => {
16070
16091
  const controller = new AbortController();
16071
16092
  const { signal } = controller;
16072
16093
  setLoading(true);
@@ -16102,7 +16123,7 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "
16102
16123
  };
16103
16124
  }, [endpoint, queryKey, paramKey, depKey, paging, reloadToken]);
16104
16125
  const adapter = url ? url.adapter ?? historyUrlAdapter : null;
16105
- React79.useEffect(() => {
16126
+ React80.useEffect(() => {
16106
16127
  if (!adapter) return;
16107
16128
  return adapter.subscribe((params2) => {
16108
16129
  const { url: u, base: b } = latest.current;
@@ -16452,12 +16473,12 @@ function createVersionStore(initialState, options) {
16452
16473
  }
16453
16474
 
16454
16475
  // src/kits/documentTitle.ts
16455
- var React80 = __toESM(require("react"), 1);
16476
+ var React81 = __toESM(require("react"), 1);
16456
16477
  function formatDocumentTitle(routeTitle, appName) {
16457
16478
  return [routeTitle, appName, "Flytedesk"].filter((part2) => !!part2 && part2.length > 0).join(" \xB7 ");
16458
16479
  }
16459
16480
  function useDocumentTitle(routeTitle, appName) {
16460
- React80.useEffect(() => {
16481
+ React81.useEffect(() => {
16461
16482
  if (typeof document === "undefined") return;
16462
16483
  document.title = formatDocumentTitle(routeTitle, appName);
16463
16484
  }, [routeTitle, appName]);