@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.js CHANGED
@@ -937,23 +937,48 @@ function Collapsible({
937
937
  }
938
938
 
939
939
  // src/components/surfaces/Drawer.tsx
940
- import * as React6 from "react";
940
+ import * as React7 from "react";
941
941
  import { createPortal as createPortal2 } from "react-dom";
942
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
943
- function Drawer({ open: open2 = true, title, label, onClose, footer, bare = false, children, className = "", ...rest }) {
944
- const asideRef = React6.useRef(null);
942
+
943
+ // src/kits/useClosingAnimation.ts
944
+ import * as React6 from "react";
945
+ function useClosingAnimation(open2, onClose, durationMs) {
945
946
  const [closing, setClosing] = React6.useState(false);
947
+ const timer = React6.useRef(null);
948
+ const cancel = React6.useCallback(() => {
949
+ if (timer.current !== null) clearTimeout(timer.current);
950
+ timer.current = null;
951
+ }, []);
952
+ React6.useEffect(() => {
953
+ if (!open2) {
954
+ cancel();
955
+ setClosing(false);
956
+ }
957
+ }, [open2, cancel]);
958
+ React6.useEffect(() => cancel, [cancel]);
946
959
  const close2 = React6.useCallback(() => {
947
960
  if (!onClose) return;
961
+ cancel();
948
962
  setClosing(true);
949
- setTimeout(onClose, 210);
950
- }, [onClose]);
963
+ timer.current = setTimeout(() => {
964
+ timer.current = null;
965
+ onClose();
966
+ }, durationMs);
967
+ }, [onClose, durationMs, cancel]);
968
+ return { closing, close: close2 };
969
+ }
970
+
971
+ // src/components/surfaces/Drawer.tsx
972
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
973
+ function Drawer({ open: open2 = true, title, label, onClose, footer, bare = false, children, className = "", ...rest }) {
974
+ const asideRef = React7.useRef(null);
975
+ const { closing, close: close2 } = useClosingAnimation(!!open2, onClose, 210);
951
976
  const layer = useStackedLayer({ active: !!open2, containerRef: asideRef, trap: true, onEscape: onClose ? close2 : void 0 });
952
977
  const zIndex = useLayerZIndex(layer);
953
- const titleId = React6.useId();
978
+ const titleId = React7.useId();
954
979
  const accessibleName = bare ? label ?? (typeof title === "string" ? title : void 0) : label;
955
980
  const unnamed = !!open2 && bare && !accessibleName;
956
- React6.useEffect(() => {
981
+ React7.useEffect(() => {
957
982
  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.");
958
983
  }, [unnamed]);
959
984
  if (!open2) return null;
@@ -974,17 +999,12 @@ function Drawer({ open: open2 = true, title, label, onClose, footer, bare = fals
974
999
  }
975
1000
 
976
1001
  // src/components/surfaces/Modal.tsx
977
- import * as React7 from "react";
1002
+ import * as React8 from "react";
978
1003
  import { createPortal as createPortal3 } from "react-dom";
979
1004
  import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
980
1005
  function Modal({ open: open2 = true, title, description, onClose, footer, wide = false, children, className = "", ...rest }) {
981
- const [closing, setClosing] = React7.useState(false);
982
- const boxRef = React7.useRef(null);
983
- const close2 = React7.useCallback(() => {
984
- if (!onClose) return;
985
- setClosing(true);
986
- setTimeout(onClose, 190);
987
- }, [onClose]);
1006
+ const boxRef = React8.useRef(null);
1007
+ const { closing, close: close2 } = useClosingAnimation(!!open2, onClose, 190);
988
1008
  const layer = useStackedLayer({ active: !!open2, containerRef: boxRef, trap: true, onEscape: onClose ? close2 : void 0 });
989
1009
  const zIndex = useLayerZIndex(layer);
990
1010
  if (!open2) return null;
@@ -1067,13 +1087,13 @@ function ScreenHead({ kicker, title, lede, actions }) {
1067
1087
  }
1068
1088
 
1069
1089
  // src/components/layout/CardGrid.tsx
1070
- import * as React8 from "react";
1090
+ import * as React9 from "react";
1071
1091
  import { jsx as jsx12 } from "react/jsx-runtime";
1072
1092
  function flattenFragments(children) {
1073
1093
  const out = [];
1074
- React8.Children.forEach(children, (child) => {
1094
+ React9.Children.forEach(children, (child) => {
1075
1095
  if (child === null || child === void 0 || typeof child === "boolean") return;
1076
- if (React8.isValidElement(child) && child.type === React8.Fragment) {
1096
+ if (React9.isValidElement(child) && child.type === React9.Fragment) {
1077
1097
  const fragmentChildren = child.props.children;
1078
1098
  out.push(...flattenFragments(fragmentChildren));
1079
1099
  return;
@@ -1091,7 +1111,7 @@ function CardGrid({ children, minCardWidth = 280, gap = "lg", className = "", st
1091
1111
  className: ["fd-card-grid", "fd-gap-" + gap, className].filter(Boolean).join(" "),
1092
1112
  style: { ["--card-grid-min"]: minCardWidth + "px", ...style },
1093
1113
  children: items.map((child, i) => {
1094
- if (React8.isValidElement(child)) {
1114
+ if (React9.isValidElement(child)) {
1095
1115
  const existingRole = child.props.role;
1096
1116
  if (existingRole) return child;
1097
1117
  return /* @__PURE__ */ jsx12("div", { role: "listitem", children: child }, child.key ?? i);
@@ -1141,10 +1161,10 @@ function LoadingRegion({
1141
1161
  }
1142
1162
 
1143
1163
  // src/components/loading/JobTray.tsx
1144
- import * as React10 from "react";
1164
+ import * as React11 from "react";
1145
1165
 
1146
1166
  // src/kits/cornerStack.tsx
1147
- import * as React9 from "react";
1167
+ import * as React10 from "react";
1148
1168
  import { createPortal as createPortal4 } from "react-dom";
1149
1169
  var CORNER_STACK_INSET_PROPERTY = "--fd-corner-stack-inset";
1150
1170
  var SLOTS = ["jobs", "toasts"];
@@ -1194,9 +1214,9 @@ function release(slot) {
1194
1214
  slotElements.clear();
1195
1215
  }
1196
1216
  }
1197
- var useSlotEffect = typeof document === "undefined" ? React9.useEffect : React9.useLayoutEffect;
1217
+ var useSlotEffect = typeof document === "undefined" ? React10.useEffect : React10.useLayoutEffect;
1198
1218
  function useCornerStackSlot(slot) {
1199
- const [element, setElement] = React9.useState(null);
1219
+ const [element, setElement] = React10.useState(null);
1200
1220
  useSlotEffect(() => {
1201
1221
  setElement(acquire(slot));
1202
1222
  return () => {
@@ -1253,9 +1273,9 @@ function announcementFor(job) {
1253
1273
  return title + ": in progress";
1254
1274
  }
1255
1275
  function JobTray({ jobs: jobs2, onDismiss, className = "" }) {
1256
- const [announcement, setAnnouncement] = React10.useState("");
1257
- const prevStatuses = React10.useRef({});
1258
- React10.useEffect(() => {
1276
+ const [announcement, setAnnouncement] = React11.useState("");
1277
+ const prevStatuses = React11.useRef({});
1278
+ React11.useEffect(() => {
1259
1279
  let next = "";
1260
1280
  for (const job of jobs2) {
1261
1281
  if (prevStatuses.current[job.id] !== job.status) {
@@ -1306,7 +1326,7 @@ function JobCard({ job, onDismiss }) {
1306
1326
  }
1307
1327
 
1308
1328
  // src/components/loading/PhasedProgress.tsx
1309
- import * as React11 from "react";
1329
+ import * as React12 from "react";
1310
1330
  import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
1311
1331
  var ICON = {
1312
1332
  pending: "ph-circle",
@@ -1319,9 +1339,9 @@ function textOf2(node) {
1319
1339
  return "";
1320
1340
  }
1321
1341
  function PhasedProgress({ phases, summary, className = "" }) {
1322
- const [announcement, setAnnouncement] = React11.useState("");
1323
- const prevStatuses = React11.useRef({});
1324
- React11.useEffect(() => {
1342
+ const [announcement, setAnnouncement] = React12.useState("");
1343
+ const prevStatuses = React12.useRef({});
1344
+ React12.useEffect(() => {
1325
1345
  let next = "";
1326
1346
  for (const phase of phases) {
1327
1347
  if (prevStatuses.current[phase.id] !== phase.status) {
@@ -1401,12 +1421,12 @@ function Spinner({ size = "md", label = "Loading", className = "", style, ...res
1401
1421
  }
1402
1422
 
1403
1423
  // src/components/navigation/SidebarNav.tsx
1404
- import * as React12 from "react";
1424
+ import * as React13 from "react";
1405
1425
  import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
1406
1426
  function Tip({ label, children }) {
1407
1427
  return /* @__PURE__ */ jsx20("span", { title: label, style: { display: "inline-flex", flex: "none" }, children });
1408
1428
  }
1409
- var SidebarNav = React12.forwardRef(function SidebarNav2({ brand, groups = [], current: current2, onNavigate, footer, open: open2 = false, className = "", ...rest }, ref) {
1429
+ var SidebarNav = React13.forwardRef(function SidebarNav2({ brand, groups = [], current: current2, onNavigate, footer, open: open2 = false, className = "", ...rest }, ref) {
1410
1430
  return /* @__PURE__ */ jsxs14(
1411
1431
  "nav",
1412
1432
  {
@@ -1445,15 +1465,15 @@ var SidebarNav = React12.forwardRef(function SidebarNav2({ brand, groups = [], c
1445
1465
  });
1446
1466
 
1447
1467
  // src/components/navigation/Topbar.tsx
1448
- import * as React14 from "react";
1468
+ import * as React15 from "react";
1449
1469
 
1450
1470
  // src/kits/useIsNarrow.ts
1451
- import * as React13 from "react";
1471
+ import * as React14 from "react";
1452
1472
  function useIsNarrow(breakpoint) {
1453
- const [narrow, setNarrow] = React13.useState(
1473
+ const [narrow, setNarrow] = React14.useState(
1454
1474
  () => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
1455
1475
  );
1456
- React13.useEffect(() => {
1476
+ React14.useEffect(() => {
1457
1477
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
1458
1478
  const mq = window.matchMedia(`(max-width: ${breakpoint}px)`);
1459
1479
  const apply = () => setNarrow(mq.matches);
@@ -1477,11 +1497,11 @@ function Topbar({
1477
1497
  ...rest
1478
1498
  }) {
1479
1499
  const narrow = useIsNarrow(overflowBreakpoint);
1480
- const [moreOpen, setMoreOpen] = React14.useState(false);
1481
- const moreRef = React14.useRef(null);
1500
+ const [moreOpen, setMoreOpen] = React15.useState(false);
1501
+ const moreRef = React15.useRef(null);
1482
1502
  return /* @__PURE__ */ jsxs15("header", { className: ["fd-topbar", narrow ? "is-narrow" : "", className].filter(Boolean).join(" "), ...rest, children: [
1483
1503
  onMenu ? /* @__PURE__ */ jsx21("button", { type: "button", className: "fd-btn-icon", "aria-label": "Menu", onClick: onMenu, children: /* @__PURE__ */ jsx21("i", { className: "ph ph-list" }) }) : null,
1484
- /* @__PURE__ */ jsx21("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ jsxs15(React14.Fragment, { children: [
1504
+ /* @__PURE__ */ jsx21("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ jsxs15(React15.Fragment, { children: [
1485
1505
  i > 0 ? /* @__PURE__ */ jsx21("i", { className: "ph ph-caret-right", style: { fontSize: 11, opacity: 0.6 }, "aria-hidden": "true" }) : null,
1486
1506
  i === crumbs.length - 1 ? (
1487
1507
  // MP-141: the current crumb mixes a static route label with (usually) a
@@ -1534,7 +1554,7 @@ function Topbar({
1534
1554
  }
1535
1555
 
1536
1556
  // src/kits/useResponsiveRail.ts
1537
- import * as React15 from "react";
1557
+ import * as React16 from "react";
1538
1558
 
1539
1559
  // src/kits/overlayLayout.ts
1540
1560
  var OVERLAY_BREAKPOINT = 1024;
@@ -1545,26 +1565,26 @@ function useOverlayLayout() {
1545
1565
  // src/kits/useResponsiveRail.ts
1546
1566
  function useResponsiveRail(options = {}) {
1547
1567
  const { breakpoint = OVERLAY_BREAKPOINT, initialOpen = true, onPersist } = options;
1548
- const navRef = React15.useRef(null);
1568
+ const navRef = React16.useRef(null);
1549
1569
  const overlay = useIsNarrow(breakpoint);
1550
- const [open2, setOpenRaw] = React15.useState(() => overlay ? false : initialOpen);
1551
- const setOpen = React15.useCallback(
1570
+ const [open2, setOpenRaw] = React16.useState(() => overlay ? false : initialOpen);
1571
+ const setOpen = React16.useCallback(
1552
1572
  (value) => {
1553
1573
  setOpenRaw(value);
1554
1574
  if (!overlay) onPersist?.(value);
1555
1575
  },
1556
1576
  [overlay, onPersist]
1557
1577
  );
1558
- const toggle = React15.useCallback(() => setOpen(!open2), [open2, setOpen]);
1559
- const close2 = React15.useCallback(() => setOpenRaw(false), []);
1560
- const lastOverlay = React15.useRef(overlay);
1561
- React15.useEffect(() => {
1578
+ const toggle = React16.useCallback(() => setOpen(!open2), [open2, setOpen]);
1579
+ const close2 = React16.useCallback(() => setOpenRaw(false), []);
1580
+ const lastOverlay = React16.useRef(overlay);
1581
+ React16.useEffect(() => {
1562
1582
  if (lastOverlay.current === overlay) return;
1563
1583
  lastOverlay.current = overlay;
1564
1584
  setOpenRaw(!overlay);
1565
1585
  }, [overlay]);
1566
1586
  const layer = useStackedLayer({ active: overlay && open2, containerRef: navRef, trap: true, onEscape: close2 });
1567
- React15.useEffect(() => {
1587
+ React16.useEffect(() => {
1568
1588
  if (!overlay || !open2) return;
1569
1589
  const previousOverflow = document.body.style.overflow;
1570
1590
  document.body.style.overflow = "hidden";
@@ -1691,20 +1711,20 @@ function installFlytedeskFavicon(url) {
1691
1711
  }
1692
1712
 
1693
1713
  // src/components/navigation/Tabs.tsx
1694
- import * as React16 from "react";
1714
+ import * as React17 from "react";
1695
1715
  import { jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
1696
1716
  var FADE_WIDTH = 32;
1697
1717
  function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
1698
- const strip = React16.useRef(null);
1699
- const [more, setMore] = React16.useState({ start: false, end: false });
1700
- const measure = React16.useCallback(() => {
1718
+ const strip = React17.useRef(null);
1719
+ const [more, setMore] = React17.useState({ start: false, end: false });
1720
+ const measure = React17.useCallback(() => {
1701
1721
  const el = strip.current;
1702
1722
  if (!el) return;
1703
1723
  const start = el.scrollLeft > 1;
1704
1724
  const end = el.scrollLeft + el.clientWidth < el.scrollWidth - 1;
1705
1725
  setMore((m) => m.start === start && m.end === end ? m : { start, end });
1706
1726
  }, []);
1707
- React16.useLayoutEffect(() => {
1727
+ React17.useLayoutEffect(() => {
1708
1728
  const el = strip.current;
1709
1729
  measure();
1710
1730
  if (!el || typeof ResizeObserver === "undefined") return;
@@ -1712,7 +1732,7 @@ function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
1712
1732
  observer.observe(el);
1713
1733
  return () => observer.disconnect();
1714
1734
  }, [measure, tabs]);
1715
- const revealActive = React16.useCallback(() => {
1735
+ const revealActive = React17.useCallback(() => {
1716
1736
  const el = strip.current;
1717
1737
  const active = el?.querySelector('[aria-selected="true"]');
1718
1738
  if (!el || !active || el.scrollWidth <= el.clientWidth) return;
@@ -1722,9 +1742,9 @@ function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
1722
1742
  else if (tab.right > box.right - FADE_WIDTH) el.scrollLeft += tab.right - box.right + FADE_WIDTH;
1723
1743
  measure();
1724
1744
  }, [measure]);
1725
- React16.useLayoutEffect(revealActive, [value, revealActive]);
1745
+ React17.useLayoutEffect(revealActive, [value, revealActive]);
1726
1746
  const tabKeys = tabs.map((t) => typeof t === "string" ? t : t.value).join(",");
1727
- React16.useLayoutEffect(() => {
1747
+ React17.useLayoutEffect(() => {
1728
1748
  const el = strip.current;
1729
1749
  if (!el || typeof ResizeObserver === "undefined") return;
1730
1750
  const observer = new ResizeObserver(revealActive);
@@ -1979,15 +1999,15 @@ function Toast({ title, children, tone = "success", onUndo, onDismiss, className
1979
1999
  }
1980
2000
 
1981
2001
  // src/components/feedback/ToastProvider.tsx
1982
- import * as React17 from "react";
2002
+ import * as React18 from "react";
1983
2003
  import { jsx as jsx33, jsxs as jsxs26 } from "react/jsx-runtime";
1984
2004
  var DEFAULT_TOAST_DURATION_MS = 5e3;
1985
- var ToastContext = React17.createContext(null);
2005
+ var ToastContext = React18.createContext(null);
1986
2006
  function ToastProvider({ children }) {
1987
- const [items, setItems] = React17.useState([]);
1988
- const timers = React17.useRef(/* @__PURE__ */ new Map());
1989
- const nextId = React17.useRef(1);
1990
- const dismiss = React17.useCallback((id) => {
2007
+ const [items, setItems] = React18.useState([]);
2008
+ const timers = React18.useRef(/* @__PURE__ */ new Map());
2009
+ const nextId = React18.useRef(1);
2010
+ const dismiss = React18.useCallback((id) => {
1991
2011
  setItems((current2) => current2.filter((item) => item.id !== id));
1992
2012
  const timer = timers.current.get(id);
1993
2013
  if (timer !== void 0) {
@@ -1995,7 +2015,7 @@ function ToastProvider({ children }) {
1995
2015
  timers.current.delete(id);
1996
2016
  }
1997
2017
  }, []);
1998
- const show = React17.useCallback(
2018
+ const show = React18.useCallback(
1999
2019
  (title, options = {}) => {
2000
2020
  const { tone = "success", duration = DEFAULT_TOAST_DURATION_MS } = options;
2001
2021
  const id = nextId.current++;
@@ -2004,36 +2024,36 @@ function ToastProvider({ children }) {
2004
2024
  },
2005
2025
  [dismiss]
2006
2026
  );
2007
- React17.useEffect(() => {
2027
+ React18.useEffect(() => {
2008
2028
  const pending = timers.current;
2009
2029
  return () => {
2010
2030
  pending.forEach(clearTimeout);
2011
2031
  pending.clear();
2012
2032
  };
2013
2033
  }, []);
2014
- const api = React17.useMemo(() => ({ show }), [show]);
2034
+ const api = React18.useMemo(() => ({ show }), [show]);
2015
2035
  return /* @__PURE__ */ jsxs26(ToastContext.Provider, { value: api, children: [
2016
2036
  children,
2017
2037
  /* @__PURE__ */ jsx33(CornerStackPortal, { slot: "toasts", children: /* @__PURE__ */ jsx33("div", { className: "fd-toast-region", "aria-live": "polite", children: items.map((item) => /* @__PURE__ */ jsx33(Toast, { title: item.title, tone: item.tone, onDismiss: () => dismiss(item.id) }, item.id)) }) })
2018
2038
  ] });
2019
2039
  }
2020
2040
  function useToast() {
2021
- const api = React17.useContext(ToastContext);
2041
+ const api = React18.useContext(ToastContext);
2022
2042
  if (!api) throw new Error("useToast must be used inside a <ToastProvider>");
2023
2043
  return api;
2024
2044
  }
2025
2045
 
2026
2046
  // src/components/feedback/Tooltip.tsx
2027
- import * as React19 from "react";
2047
+ import * as React20 from "react";
2028
2048
 
2029
2049
  // src/components/feedback/useTooltip.tsx
2030
- import * as React18 from "react";
2050
+ import * as React19 from "react";
2031
2051
  import { jsx as jsx34 } from "react/jsx-runtime";
2032
2052
  var CLOSE_DELAY_MS = 120;
2033
2053
  var isMouse = (e) => e.pointerType === "mouse";
2034
2054
  function TooltipBubble({ open: open2, labels, placement, className, onHide, onEnter, onLeave }) {
2035
- const anchorRef = React18.useRef(open2.anchor);
2036
- const bubbleRef = React18.useRef(null);
2055
+ const anchorRef = React19.useRef(open2.anchor);
2056
+ const bubbleRef = React19.useRef(null);
2037
2057
  const pos = usePopoverPosition(true, anchorRef, {
2038
2058
  placement: placement === "bottom" ? "bottom-center" : "top-center",
2039
2059
  offset: 8,
@@ -2044,7 +2064,7 @@ function TooltipBubble({ open: open2, labels, placement, className, onHide, onEn
2044
2064
  });
2045
2065
  const layer = useStackedLayer({ active: true, containerRef: bubbleRef, onEscape: onHide, returnFocus: false });
2046
2066
  const zIndex = useLayerZIndex(layer);
2047
- React18.useEffect(() => {
2067
+ React19.useEffect(() => {
2048
2068
  const away = (e) => {
2049
2069
  const t = e.target;
2050
2070
  if (open2.anchor.contains(t)) return;
@@ -2075,16 +2095,16 @@ function TooltipBubble({ open: open2, labels, placement, className, onHide, onEn
2075
2095
  );
2076
2096
  }
2077
2097
  function useTooltip({ placement = "top", className = "" } = {}) {
2078
- const [open2, setOpen] = React18.useState(null);
2079
- const closeTimer = React18.useRef(null);
2080
- const focused = React18.useRef(null);
2081
- const cancelClose = React18.useCallback(() => {
2098
+ const [open2, setOpen] = React19.useState(null);
2099
+ const closeTimer = React19.useRef(null);
2100
+ const focused = React19.useRef(null);
2101
+ const cancelClose = React19.useCallback(() => {
2082
2102
  if (closeTimer.current) {
2083
2103
  clearTimeout(closeTimer.current);
2084
2104
  closeTimer.current = null;
2085
2105
  }
2086
2106
  }, []);
2087
- const hide = React18.useCallback(() => {
2107
+ const hide = React19.useCallback(() => {
2088
2108
  cancelClose();
2089
2109
  focused.current = null;
2090
2110
  setOpen(null);
@@ -2104,7 +2124,7 @@ function useTooltip({ placement = "top", className = "" } = {}) {
2104
2124
  setOpen((o) => o && o.reason === "hover" ? focused.current : o);
2105
2125
  }, CLOSE_DELAY_MS);
2106
2126
  };
2107
- React18.useEffect(() => cancelClose, [cancelClose]);
2127
+ React19.useEffect(() => cancelClose, [cancelClose]);
2108
2128
  const labels = /* @__PURE__ */ new Map();
2109
2129
  const bind = (id, label) => {
2110
2130
  labels.set(id, label);
@@ -2157,17 +2177,17 @@ function useTooltip({ placement = "top", className = "" } = {}) {
2157
2177
  // src/components/feedback/Tooltip.tsx
2158
2178
  import { jsx as jsx35, jsxs as jsxs27 } from "react/jsx-runtime";
2159
2179
  function Tooltip({ label, placement = "top", children, className = "" }) {
2160
- const id = React19.useId();
2180
+ const id = React20.useId();
2161
2181
  const descId = id + "-desc";
2162
2182
  const tip = useTooltip({ placement, className });
2163
- const described = React19.isValidElement(children) ? React19.cloneElement(children, {
2183
+ const described = React20.isValidElement(children) ? React20.cloneElement(children, {
2164
2184
  "aria-describedby": [children.props["aria-describedby"], descId].filter(Boolean).join(" ")
2165
2185
  }) : children;
2166
2186
  return /* @__PURE__ */ jsxs27(
2167
2187
  "span",
2168
2188
  {
2169
2189
  className: "fd-tooltip-anchor",
2170
- "aria-describedby": React19.isValidElement(children) ? void 0 : descId,
2190
+ "aria-describedby": React20.isValidElement(children) ? void 0 : descId,
2171
2191
  ...tip.bind(id, label),
2172
2192
  children: [
2173
2193
  described,
@@ -2179,16 +2199,16 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
2179
2199
  }
2180
2200
 
2181
2201
  // src/components/data/AnimNum.tsx
2182
- import * as React20 from "react";
2202
+ import * as React21 from "react";
2183
2203
  import { Fragment as Fragment6, jsx as jsx36 } from "react/jsx-runtime";
2184
2204
  function shouldSkipEasing() {
2185
2205
  if (typeof document !== "undefined" && document.hidden) return true;
2186
2206
  return window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false;
2187
2207
  }
2188
2208
  function AnimNum({ value, format, duration = 550 }) {
2189
- const [display, setDisplay] = React20.useState(value);
2190
- const prev = React20.useRef(value);
2191
- React20.useEffect(() => {
2209
+ const [display, setDisplay] = React21.useState(value);
2210
+ const prev = React21.useRef(value);
2211
+ React21.useEffect(() => {
2192
2212
  const from = prev.current;
2193
2213
  const to = value;
2194
2214
  prev.current = to;
@@ -2216,14 +2236,14 @@ function AnimNum({ value, format, duration = 550 }) {
2216
2236
  }
2217
2237
 
2218
2238
  // src/components/data/TrendChart.tsx
2219
- import * as React23 from "react";
2239
+ import * as React24 from "react";
2220
2240
 
2221
2241
  // src/components/useMeasuredWidth.ts
2222
- import * as React21 from "react";
2242
+ import * as React22 from "react";
2223
2243
  function useMeasuredWidth(fallback) {
2224
- const [element, setElement] = React21.useState(null);
2225
- const [width, setWidth] = React21.useState(fallback);
2226
- React21.useLayoutEffect(() => {
2244
+ const [element, setElement] = React22.useState(null);
2245
+ const [width, setWidth] = React22.useState(fallback);
2246
+ React22.useLayoutEffect(() => {
2227
2247
  if (!element || typeof ResizeObserver === "undefined") return;
2228
2248
  const measure = () => {
2229
2249
  const measured = Math.round(element.getBoundingClientRect().width);
@@ -2238,7 +2258,7 @@ function useMeasuredWidth(fallback) {
2238
2258
  }
2239
2259
 
2240
2260
  // src/components/data/SegmentedMeter.tsx
2241
- import * as React22 from "react";
2261
+ import * as React23 from "react";
2242
2262
 
2243
2263
  // src/kits/files.ts
2244
2264
  function formatBytes(n) {
@@ -2443,7 +2463,7 @@ function SegmentedMeter({
2443
2463
  const pct = safeTotal ? Math.min(100, Math.round(used / safeTotal * 100)) : 0;
2444
2464
  const w = (v) => safeTotal ? Math.max(0, Math.min(100, Number(v) / safeTotal * 100)) : 0;
2445
2465
  const fill = (s, i) => s.color || (s.variant ? VARIANT_FILL[s.variant] : void 0) || CHART[i % CHART.length];
2446
- const generatedId = React22.useId();
2466
+ const generatedId = React23.useId();
2447
2467
  const uid2 = id || generatedId;
2448
2468
  return /* @__PURE__ */ jsxs28("div", { className: ["fd-segmeter", className].filter(Boolean).join(" "), onClick, children: [
2449
2469
  label || showTotal ? /* @__PURE__ */ jsxs28("div", { className: "fd-segmeter-head", children: [
@@ -2594,8 +2614,8 @@ function TrendChart({
2594
2614
  onRetry,
2595
2615
  className = ""
2596
2616
  }) {
2597
- const [activeId, setActiveId] = React23.useState(null);
2598
- const [pointTip, setPointTip] = React23.useState(null);
2617
+ const [activeId, setActiveId] = React24.useState(null);
2618
+ const [pointTip, setPointTip] = React24.useState(null);
2599
2619
  const isEmpty = state === "ready" && (!categories.length || !series.length || series.every((s) => !s.values.length));
2600
2620
  const effectiveState = isEmpty ? "empty" : state;
2601
2621
  const [plotRef, VBW] = useMeasuredWidth(INITIAL_WIDTH);
@@ -2709,7 +2729,7 @@ function TrendChart({
2709
2729
  }
2710
2730
 
2711
2731
  // src/components/data/DonutChart.tsx
2712
- import * as React24 from "react";
2732
+ import * as React25 from "react";
2713
2733
  import { jsx as jsx40, jsxs as jsxs31 } from "react/jsx-runtime";
2714
2734
  function DonutChart({
2715
2735
  segments,
@@ -2724,7 +2744,7 @@ function DonutChart({
2724
2744
  onRetry,
2725
2745
  className = ""
2726
2746
  }) {
2727
- const [activeId, setActiveId] = React24.useState(null);
2747
+ const [activeId, setActiveId] = React25.useState(null);
2728
2748
  const items = segments.filter((s) => Number(s.value) > 0);
2729
2749
  const total = items.reduce((n, s) => n + Number(s.value), 0);
2730
2750
  const isEmpty = state === "ready" && (!items.length || total <= 0);
@@ -2816,7 +2836,7 @@ function DonutChart({
2816
2836
  }
2817
2837
 
2818
2838
  // src/components/data/BarList.tsx
2819
- import * as React25 from "react";
2839
+ import * as React26 from "react";
2820
2840
  import { jsx as jsx41, jsxs as jsxs32 } from "react/jsx-runtime";
2821
2841
  var wholePercent = (share) => formatPercent(Math.round(share * 100));
2822
2842
  function BarList({
@@ -2833,7 +2853,7 @@ function BarList({
2833
2853
  onRetry,
2834
2854
  className = ""
2835
2855
  }) {
2836
- const ordered = React25.useMemo(() => {
2856
+ const ordered = React26.useMemo(() => {
2837
2857
  const list = sort ? [...rows].sort((a, b) => Number(b.value) - Number(a.value)) : rows;
2838
2858
  return maxRows ? list.slice(0, maxRows) : list;
2839
2859
  }, [rows, sort, maxRows]);
@@ -2975,7 +2995,7 @@ function FunnelChart({
2975
2995
  }
2976
2996
 
2977
2997
  // src/components/data/Clamp.tsx
2978
- import * as React26 from "react";
2998
+ import * as React27 from "react";
2979
2999
  import { jsx as jsx43, jsxs as jsxs34 } from "react/jsx-runtime";
2980
3000
  function Clamp({
2981
3001
  children,
@@ -2987,16 +3007,16 @@ function Clamp({
2987
3007
  onToggle,
2988
3008
  className = ""
2989
3009
  }) {
2990
- const [open2, setOpen] = React26.useState(false);
2991
- const [overflows, setOverflows] = React26.useState(false);
2992
- const bodyRef = React26.useRef(null);
2993
- const charClamped = React26.useMemo(() => {
3010
+ const [open2, setOpen] = React27.useState(false);
3011
+ const [overflows, setOverflows] = React27.useState(false);
3012
+ const bodyRef = React27.useRef(null);
3013
+ const charClamped = React27.useMemo(() => {
2994
3014
  if (open2 || !maxChars || typeof text !== "string" || text.length <= maxChars) return null;
2995
3015
  const cut = text.slice(0, maxChars);
2996
3016
  const at = cut.lastIndexOf(" ");
2997
3017
  return (at > maxChars * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
2998
3018
  }, [text, maxChars, open2]);
2999
- React26.useLayoutEffect(() => {
3019
+ React27.useLayoutEffect(() => {
3000
3020
  const node = bodyRef.current;
3001
3021
  if (maxChars || !node || !maxHeight) return;
3002
3022
  const measure = () => {
@@ -3096,6 +3116,7 @@ function RowActionCell({ action }) {
3096
3116
  return /* @__PURE__ */ jsx45("td", { className: "fd-table-action", children: action ? /* @__PURE__ */ jsx45(RowActionButton, { action, size: "sm" }) : null });
3097
3117
  }
3098
3118
  var cellOf = (c, row) => c.render ? c.render(row) : row[c.key];
3119
+ var cardCellOf = (c, row) => c.phoneRender ? c.phoneRender(row) : cellOf(c, row);
3099
3120
  function rowInteraction(row, onRowClick) {
3100
3121
  if (!onRowClick) return {};
3101
3122
  return {
@@ -3238,11 +3259,11 @@ function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort
3238
3259
  ...semantics,
3239
3260
  ...rowInteraction(r, onRowClick),
3240
3261
  children: [
3241
- /* @__PURE__ */ jsx45("div", { className: "fd-dt-card-title", children: primary.map((c) => /* @__PURE__ */ jsx45("span", { className: c.numeric ? "is-num" : void 0, children: cellOf(c, r) }, c.key)) }),
3262
+ /* @__PURE__ */ jsx45("div", { className: "fd-dt-card-title", children: primary.map((c) => /* @__PURE__ */ jsx45("span", { className: c.numeric ? "is-num" : void 0, children: cardCellOf(c, r) }, c.key)) }),
3242
3263
  secondary.length ? /* @__PURE__ */ jsx45("div", { className: "fd-dt-card-meta", children: secondary.map((c) => /* @__PURE__ */ jsxs36("span", { className: c.numeric ? "is-num" : void 0, children: [
3243
3264
  /* @__PURE__ */ jsx45("span", { className: "fd-dt-card-label", children: c.label }),
3244
3265
  " ",
3245
- cellOf(c, r)
3266
+ cardCellOf(c, r)
3246
3267
  ] }, c.key)) }) : null
3247
3268
  ]
3248
3269
  }
@@ -3254,16 +3275,16 @@ function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort
3254
3275
  }
3255
3276
 
3256
3277
  // src/components/data/FilterBar.tsx
3257
- import * as React32 from "react";
3278
+ import * as React33 from "react";
3258
3279
 
3259
3280
  // src/components/forms/NumberInput.tsx
3260
- import * as React29 from "react";
3281
+ import * as React30 from "react";
3261
3282
 
3262
3283
  // src/components/forms/field.tsx
3263
- import * as React27 from "react";
3284
+ import * as React28 from "react";
3264
3285
  import { jsx as jsx46, jsxs as jsxs37 } from "react/jsx-runtime";
3265
3286
  function useFieldId(id) {
3266
- const generated = React27.useId();
3287
+ const generated = React28.useId();
3267
3288
  return id || generated;
3268
3289
  }
3269
3290
  function FieldLabel({ htmlFor, id, required = false, onClick, children }) {
@@ -3282,10 +3303,10 @@ function HiddenFieldLabel({ id, children }) {
3282
3303
  }
3283
3304
 
3284
3305
  // src/components/useLatest.ts
3285
- import * as React28 from "react";
3306
+ import * as React29 from "react";
3286
3307
  function useLatest(value) {
3287
- const ref = React28.useRef(value);
3288
- React28.useInsertionEffect(() => {
3308
+ const ref = React29.useRef(value);
3309
+ React29.useInsertionEffect(() => {
3289
3310
  ref.current = value;
3290
3311
  });
3291
3312
  return ref;
@@ -3368,20 +3389,20 @@ function NumberInput({
3368
3389
  const n = typeof v === "number" ? v : parseNumberText(v);
3369
3390
  return n == null || Number.isNaN(n) ? null : n;
3370
3391
  };
3371
- const [text, setText] = React29.useState(() => toText(value));
3372
- const [editing, setEditing] = React29.useState(false);
3392
+ const [text, setText] = React30.useState(() => toText(value));
3393
+ const [editing, setEditing] = React30.useState(false);
3373
3394
  const parsed = parseNumberText(text);
3374
3395
  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;
3375
3396
  const valid = invalidMessage == null;
3376
- const committedRef = React29.useRef(toNumber(value));
3397
+ const committedRef = React30.useRef(toNumber(value));
3377
3398
  const onChangeRef = useLatest(onChange);
3378
3399
  const onValidityChangeRef = useLatest(onValidityChange);
3379
- const focusedRef = React29.useRef(false);
3380
- React29.useEffect(() => {
3400
+ const focusedRef = React30.useRef(false);
3401
+ React30.useEffect(() => {
3381
3402
  committedRef.current = toNumber(value);
3382
3403
  if (!focusedRef.current) setText(toText(value));
3383
3404
  }, [value]);
3384
- React29.useLayoutEffect(() => {
3405
+ React30.useLayoutEffect(() => {
3385
3406
  onValidityChangeRef.current?.(valid);
3386
3407
  }, [valid, onValidityChangeRef]);
3387
3408
  const fire = (n) => {
@@ -3397,7 +3418,7 @@ function NumberInput({
3397
3418
  return true;
3398
3419
  };
3399
3420
  const bumpRef = useLatest(bump);
3400
- const holdTimer = React29.useRef(null);
3421
+ const holdTimer = React30.useRef(null);
3401
3422
  const release2 = () => {
3402
3423
  if (holdTimer.current) clearTimeout(holdTimer.current);
3403
3424
  holdTimer.current = null;
@@ -3416,7 +3437,7 @@ function NumberInput({
3416
3437
  };
3417
3438
  holdTimer.current = setTimeout(tick, HOLD_DELAY_MS);
3418
3439
  };
3419
- React29.useEffect(() => () => {
3440
+ React30.useEffect(() => () => {
3420
3441
  if (holdTimer.current) clearTimeout(holdTimer.current);
3421
3442
  }, []);
3422
3443
  const current2 = committedRef.current;
@@ -3519,7 +3540,7 @@ function NumberInput({
3519
3540
  }
3520
3541
 
3521
3542
  // src/components/forms/DatePicker.tsx
3522
- import * as React30 from "react";
3543
+ import * as React31 from "react";
3523
3544
  import { jsx as jsx48, jsxs as jsxs39 } from "react/jsx-runtime";
3524
3545
  var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
3525
3546
  var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
@@ -3552,10 +3573,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3552
3573
  const today = /* @__PURE__ */ new Date();
3553
3574
  const sel = range ? value || {} : { start: value, end: value };
3554
3575
  const anchor = parse(sel.start) || parse(initialMonth) || today;
3555
- const [vy, setVy] = React30.useState(anchor.getFullYear());
3556
- const [vm, setVm] = React30.useState(anchor.getMonth());
3557
- const [mode2, setMode] = React30.useState("days");
3558
- const [hover, setHover] = React30.useState(null);
3576
+ const [vy, setVy] = React31.useState(anchor.getFullYear());
3577
+ const [vm, setVm] = React31.useState(anchor.getMonth());
3578
+ const [mode2, setMode] = React31.useState("days");
3579
+ const [hover, setHover] = React31.useState(null);
3559
3580
  const s = parse(sel.start), e = parse(sel.end);
3560
3581
  const hoverEnd = range && s && !e && hover ? parse(hover) : null;
3561
3582
  const inRange = (d) => {
@@ -3566,12 +3587,12 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3566
3587
  const isEnd = (d) => !!e && iso(d) === iso(e);
3567
3588
  const isEdge = (d) => isStart(d) || isEnd(d);
3568
3589
  const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
3569
- const [activeDate, setActiveDate] = React30.useState(() => {
3590
+ const [activeDate, setActiveDate] = React31.useState(() => {
3570
3591
  if (s) return s;
3571
3592
  if (sameMonth(today, anchor.getFullYear(), anchor.getMonth())) return today;
3572
3593
  return new Date(anchor.getFullYear(), anchor.getMonth(), 1);
3573
3594
  });
3574
- const calRef = React30.useRef(null);
3595
+ const calRef = React31.useRef(null);
3575
3596
  const pageToShow = (y, m) => {
3576
3597
  const idx = y * 12 + m, firstIdx = vy * 12 + vm, secondIdx = firstIdx + 1;
3577
3598
  if (idx === firstIdx || months > 1 && idx === secondIdx) return;
@@ -3588,7 +3609,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3588
3609
  setActiveDate(next);
3589
3610
  pageToShow(next.getFullYear(), next.getMonth());
3590
3611
  };
3591
- React30.useEffect(() => {
3612
+ React31.useEffect(() => {
3592
3613
  const el = calRef.current?.querySelector('[data-iso="' + iso(activeDate) + '"]');
3593
3614
  if (el) el.focus({ preventScroll: true });
3594
3615
  }, [activeDate, vy, vm]);
@@ -3781,9 +3802,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3781
3802
  }
3782
3803
  function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, "aria-label": hiddenLabel, ...rest }) {
3783
3804
  const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id, hiddenLabel);
3784
- const [open2, setOpen] = React30.useState(false);
3785
- const rootRef = React30.useRef(null);
3786
- const boxRef = React30.useRef(null);
3805
+ const [open2, setOpen] = React31.useState(false);
3806
+ const rootRef = React31.useRef(null);
3807
+ const boxRef = React31.useRef(null);
3787
3808
  const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
3788
3809
  const toggle = () => {
3789
3810
  if (!disabled) setOpen(!open2);
@@ -3872,9 +3893,9 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
3872
3893
  }
3873
3894
 
3874
3895
  // src/components/forms/listbox.ts
3875
- import * as React31 from "react";
3896
+ import * as React32 from "react";
3876
3897
  function useListboxNav({ count, onSelect }) {
3877
- const [active, setActive] = React31.useState(-1);
3898
+ const [active, setActive] = React32.useState(-1);
3878
3899
  return {
3879
3900
  active,
3880
3901
  setActive,
@@ -3887,7 +3908,7 @@ function useListboxNav({ count, onSelect }) {
3887
3908
  };
3888
3909
  }
3889
3910
  function useListboxScrollIntoView(active, listRef, enabled) {
3890
- React31.useEffect(() => {
3911
+ React32.useEffect(() => {
3891
3912
  if (!enabled || active < 0 || !listRef.current) return;
3892
3913
  const list = listRef.current;
3893
3914
  const el = list.querySelector('[data-i="' + active + '"]');
@@ -4108,13 +4129,13 @@ function MultiSelectPanel({
4108
4129
  onClose
4109
4130
  }) {
4110
4131
  const allowedOps = operatorsFor(field);
4111
- const [draftOperator, setDraftOperator] = React32.useState(value?.operator ?? allowedOps[0]);
4132
+ const [draftOperator, setDraftOperator] = React33.useState(value?.operator ?? allowedOps[0]);
4112
4133
  const operator = allowedOps.length === 1 ? allowedOps[0] : value?.operator ?? draftOperator;
4113
4134
  const selected = value?.values ?? [];
4114
4135
  const selectedRef = useLatest(selected);
4115
4136
  const operatorRef = useLatest(operator);
4116
- const mountedRef = React32.useRef(true);
4117
- React32.useEffect(() => {
4137
+ const mountedRef = React33.useRef(true);
4138
+ React33.useEffect(() => {
4118
4139
  mountedRef.current = true;
4119
4140
  return () => {
4120
4141
  mountedRef.current = false;
@@ -4128,20 +4149,20 @@ function MultiSelectPanel({
4128
4149
  if (selectedRef.current.length > 0) commit(selectedRef.current, op);
4129
4150
  else setDraftOperator(op);
4130
4151
  };
4131
- const [mode2, setMode] = React32.useState("search");
4132
- const [query, setQuery] = React32.useState("");
4133
- const [asyncState, setAsyncState] = React32.useState(
4152
+ const [mode2, setMode] = React33.useState("search");
4153
+ const [query, setQuery] = React33.useState("");
4154
+ const [asyncState, setAsyncState] = React33.useState(
4134
4155
  { options: null, loading: !!field.loadOptions, error: false }
4135
4156
  );
4136
- const [retryTick, setRetryTick] = React32.useState(0);
4137
- const inputRef = React32.useRef(null);
4138
- const listRef = React32.useRef(null);
4139
- const listId = React32.useId();
4157
+ const [retryTick, setRetryTick] = React33.useState(0);
4158
+ const inputRef = React33.useRef(null);
4159
+ const listRef = React33.useRef(null);
4160
+ const listId = React33.useId();
4140
4161
  const loadOptionsRef = useLatest(field.loadOptions);
4141
- React32.useEffect(() => {
4162
+ React33.useEffect(() => {
4142
4163
  inputRef.current?.focus();
4143
4164
  }, []);
4144
- React32.useEffect(() => {
4165
+ React33.useEffect(() => {
4145
4166
  const load = loadOptionsRef.current;
4146
4167
  if (!load) return;
4147
4168
  const controller = new AbortController();
@@ -4174,17 +4195,17 @@ function MultiSelectPanel({
4174
4195
  };
4175
4196
  const nav = useListboxNav({ count: options.length, onSelect: (i) => toggle(options[i]) });
4176
4197
  useListboxScrollIntoView(nav.active, listRef, hasListbox);
4177
- React32.useEffect(() => {
4198
+ React33.useEffect(() => {
4178
4199
  nav.setActive(0);
4179
4200
  }, [query, options.length]);
4180
4201
  const activeId = hasListbox && options[nav.active] ? listId + "-opt-" + nav.active : void 0;
4181
4202
  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" : "";
4182
- const [pasteText, setPasteText] = React32.useState("");
4183
- const [pasteLoading, setPasteLoading] = React32.useState(false);
4184
- const [unmatchedTokens, setUnmatchedTokens] = React32.useState([]);
4185
- const [pasteError, setPasteError] = React32.useState(null);
4186
- const pasteWrapRef = React32.useRef(null);
4187
- React32.useEffect(() => {
4203
+ const [pasteText, setPasteText] = React33.useState("");
4204
+ const [pasteLoading, setPasteLoading] = React33.useState(false);
4205
+ const [unmatchedTokens, setUnmatchedTokens] = React33.useState([]);
4206
+ const [pasteError, setPasteError] = React33.useState(null);
4207
+ const pasteWrapRef = React33.useRef(null);
4208
+ React33.useEffect(() => {
4188
4209
  if (mode2 === "paste") pasteWrapRef.current?.querySelector("textarea")?.focus();
4189
4210
  }, [mode2]);
4190
4211
  const doResolve = () => {
@@ -4357,8 +4378,8 @@ function MultiSelectPanel({
4357
4378
  );
4358
4379
  }
4359
4380
  function useTextValidity(onFlip) {
4360
- const invalidRef = React32.useRef(/* @__PURE__ */ new Set());
4361
- const [, rerender] = React32.useReducer((n) => n + 1, 0);
4381
+ const invalidRef = React33.useRef(/* @__PURE__ */ new Set());
4382
+ const [, rerender] = React33.useReducer((n) => n + 1, 0);
4362
4383
  const onFlipRef = useLatest(onFlip);
4363
4384
  const record = (name, valid) => {
4364
4385
  const invalid = invalidRef.current;
@@ -4401,15 +4422,15 @@ function sameValue(a, b) {
4401
4422
  return true;
4402
4423
  }
4403
4424
  function useReseedFromProps(value, applies, reseed) {
4404
- const seen = React32.useRef(value);
4405
- React32.useLayoutEffect(() => {
4425
+ const seen = React33.useRef(value);
4426
+ React33.useLayoutEffect(() => {
4406
4427
  if (seen.current === value) return;
4407
4428
  seen.current = value;
4408
4429
  if (!sameValue(value, applies())) reseed(value);
4409
4430
  }, [value, applies, reseed]);
4410
4431
  }
4411
4432
  function usePreserveFocusAcrossRemount(seed, fields) {
4412
- const pendingName = React32.useRef(null);
4433
+ const pendingName = React33.useRef(null);
4413
4434
  const fieldsRef = useLatest(fields);
4414
4435
  const capture = () => {
4415
4436
  const active = document.activeElement;
@@ -4422,7 +4443,7 @@ function usePreserveFocusAcrossRemount(seed, fields) {
4422
4443
  }
4423
4444
  }
4424
4445
  };
4425
- React32.useLayoutEffect(() => {
4446
+ React33.useLayoutEffect(() => {
4426
4447
  const name = pendingName.current;
4427
4448
  if (!name) return;
4428
4449
  pendingName.current = null;
@@ -4438,14 +4459,14 @@ function RangePanel({
4438
4459
  onCommit,
4439
4460
  onClose
4440
4461
  }) {
4441
- const [draft, setDraft] = React32.useState(() => rangeDraft(value));
4442
- const [seed, setSeed] = React32.useState(0);
4443
- const minId = React32.useId();
4444
- const maxId = React32.useId();
4445
- const minWrapRef = React32.useRef(null);
4446
- const maxWrapRef = React32.useRef(null);
4462
+ const [draft, setDraft] = React33.useState(() => rangeDraft(value));
4463
+ const [seed, setSeed] = React33.useState(0);
4464
+ const minId = React33.useId();
4465
+ const maxId = React33.useId();
4466
+ const minWrapRef = React33.useRef(null);
4467
+ const maxWrapRef = React33.useRef(null);
4447
4468
  const preserveFocus = usePreserveFocusAcrossRemount(seed, { min: minWrapRef, max: maxWrapRef });
4448
- const draftRef = React32.useRef(draft);
4469
+ const draftRef = React33.useRef(draft);
4449
4470
  const shown = () => {
4450
4471
  const { min, max } = draftRef.current;
4451
4472
  return applicable(field, min == null && max == null ? void 0 : { min, max }, validity.allValid());
@@ -4537,15 +4558,15 @@ function DatePanel({
4537
4558
  onClose
4538
4559
  }) {
4539
4560
  const maxDays = effectiveMaxDays(field);
4540
- const [initial] = React32.useState(() => dateDraft(field, value));
4541
- const [kind, setKind] = React32.useState(initial.kind);
4542
- const [daysDraft, setDaysDraft] = React32.useState(initial.days);
4543
- const daysRef = React32.useRef(daysDraft);
4544
- const daysConfirmed = React32.useRef(value?.kind === "withinDays");
4545
- const [between, setBetween] = React32.useState(initial.between);
4546
- const [seed, setSeed] = React32.useState(0);
4547
- const daysId = React32.useId();
4548
- const daysWrapRef = React32.useRef(null);
4561
+ const [initial] = React33.useState(() => dateDraft(field, value));
4562
+ const [kind, setKind] = React33.useState(initial.kind);
4563
+ const [daysDraft, setDaysDraft] = React33.useState(initial.days);
4564
+ const daysRef = React33.useRef(daysDraft);
4565
+ const daysConfirmed = React33.useRef(value?.kind === "withinDays");
4566
+ const [between, setBetween] = React33.useState(initial.between);
4567
+ const [seed, setSeed] = React33.useState(0);
4568
+ const daysId = React33.useId();
4569
+ const daysWrapRef = React33.useRef(null);
4549
4570
  const preserveFocus = usePreserveFocusAcrossRemount(seed, { days: daysWrapRef });
4550
4571
  const shownWithinDays = () => {
4551
4572
  const days = daysRef.current;
@@ -4663,11 +4684,11 @@ function FilterButton({ children, ...rest }) {
4663
4684
  ] });
4664
4685
  }
4665
4686
  function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align = "left", actions, onClearAll, showActiveCount = false, loading = false, loadingLabel = "Loading the filters", className = "", ...rest }) {
4666
- const [panel, setPanel] = React32.useState(null);
4667
- const editAnchorRef = React32.useRef(null);
4668
- const addAnchorRef = React32.useRef(null);
4669
- const textInputRef = React32.useRef(null);
4670
- const optionsRef = React32.useRef(null);
4687
+ const [panel, setPanel] = React33.useState(null);
4688
+ const editAnchorRef = React33.useRef(null);
4689
+ const addAnchorRef = React33.useRef(null);
4690
+ const textInputRef = React33.useRef(null);
4691
+ const optionsRef = React33.useRef(null);
4671
4692
  if (process.env.NODE_ENV !== "production") {
4672
4693
  for (const f of fields) assertValidFieldDefinition(f);
4673
4694
  }
@@ -4690,7 +4711,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
4690
4711
  const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
4691
4712
  const startEditing = (key) => setPanel({ kind: "edit", key });
4692
4713
  const closeEditing = () => setPanel(null);
4693
- React32.useEffect(() => {
4714
+ React33.useEffect(() => {
4694
4715
  if (!panel || panel.kind !== "edit") return;
4695
4716
  if (editingField?.type === "text") {
4696
4717
  textInputRef.current?.focus();
@@ -4945,10 +4966,10 @@ function StatTile(props) {
4945
4966
  }
4946
4967
 
4947
4968
  // src/components/data/CodeBlock.tsx
4948
- import * as React34 from "react";
4969
+ import * as React35 from "react";
4949
4970
 
4950
4971
  // src/kits/clipboard.ts
4951
- import * as React33 from "react";
4972
+ import * as React34 from "react";
4952
4973
  var COPIED_FEEDBACK_MS = 1600;
4953
4974
  function copyThroughSelection(text) {
4954
4975
  const previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
@@ -4978,17 +4999,17 @@ async function copyToClipboard(text) {
4978
4999
  return copyThroughSelection(text);
4979
5000
  }
4980
5001
  function useCopyToClipboard() {
4981
- const [copied, setCopied] = React33.useState(false);
4982
- const timer = React33.useRef(null);
4983
- const mounted = React33.useRef(true);
4984
- React33.useEffect(() => {
5002
+ const [copied, setCopied] = React34.useState(false);
5003
+ const timer = React34.useRef(null);
5004
+ const mounted = React34.useRef(true);
5005
+ React34.useEffect(() => {
4985
5006
  mounted.current = true;
4986
5007
  return () => {
4987
5008
  mounted.current = false;
4988
5009
  if (timer.current) clearTimeout(timer.current);
4989
5010
  };
4990
5011
  }, []);
4991
- const copy = React33.useCallback(async (text) => {
5012
+ const copy = React34.useCallback(async (text) => {
4992
5013
  const ok = await copyToClipboard(text);
4993
5014
  if (ok && mounted.current) {
4994
5015
  setCopied(true);
@@ -5156,7 +5177,7 @@ function tokenize(src, lang) {
5156
5177
  return out;
5157
5178
  }
5158
5179
  function Highlighted({ code, lang }) {
5159
- const toks = React34.useMemo(() => tokenize(code, lang), [code, lang]);
5180
+ const toks = React35.useMemo(() => tokenize(code, lang), [code, lang]);
5160
5181
  return /* @__PURE__ */ jsx54(Fragment9, { children: toks.map((tk, i) => tk.c ? /* @__PURE__ */ jsx54("span", { className: "tok-" + tk.c, children: tk.t }, i) : tk.t) });
5161
5182
  }
5162
5183
  function CodeBlock({
@@ -5170,8 +5191,8 @@ function CodeBlock({
5170
5191
  actions,
5171
5192
  className = ""
5172
5193
  }) {
5173
- const [wrap, setWrap] = React34.useState(!!wrapDefault);
5174
- const [open2, setOpen] = React34.useState(false);
5194
+ const [wrap, setWrap] = React35.useState(!!wrapDefault);
5195
+ const [open2, setOpen] = React35.useState(false);
5175
5196
  const [copied, copy] = useCopyToClipboard();
5176
5197
  const body = String(code).replace(/\n$/, "");
5177
5198
  const lines = body.split("\n");
@@ -5200,7 +5221,7 @@ function CodeBlock({
5200
5221
  ] });
5201
5222
  }
5202
5223
  function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
5203
- const [open2, setOpen] = React34.useState(false);
5224
+ const [open2, setOpen] = React35.useState(false);
5204
5225
  const [copied, copy] = useCopyToClipboard();
5205
5226
  const raw = String(diff).replace(/\n$/, "");
5206
5227
  const all = raw.split("\n").map((line) => {
@@ -5246,7 +5267,7 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
5246
5267
  }
5247
5268
 
5248
5269
  // src/components/data/Markdown.tsx
5249
- import * as React35 from "react";
5270
+ import * as React36 from "react";
5250
5271
  import { jsx as jsx55, jsxs as jsxs45 } from "react/jsx-runtime";
5251
5272
  var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
5252
5273
  var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
@@ -5289,7 +5310,7 @@ function hiddenInlineNodes(hidden, ctx, keyBase) {
5289
5310
  const href = safeHref(d(g(2)));
5290
5311
  out.push(href ? /* @__PURE__ */ jsx55("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__ */ jsx55("span", { children: d(g(1)) }, key()));
5291
5312
  } else if (kind === "cite") {
5292
- out.push(ctx.renderCitation ? /* @__PURE__ */ jsx55(React35.Fragment, { children: ctx.renderCitation(d(g(1))) }, key()) : /* @__PURE__ */ jsx55("sup", { className: "fd-md-cite", children: d(g(1)) }, key()));
5313
+ out.push(ctx.renderCitation ? /* @__PURE__ */ jsx55(React36.Fragment, { children: ctx.renderCitation(d(g(1))) }, key()) : /* @__PURE__ */ jsx55("sup", { className: "fd-md-cite", children: d(g(1)) }, key()));
5293
5314
  } else if (kind === "strongem") out.push(/* @__PURE__ */ jsx55("strong", { children: /* @__PURE__ */ jsx55("em", { children: hiddenInlineNodes(g(1), ctx, key()) }) }, key()));
5294
5315
  else if (kind === "strong") out.push(/* @__PURE__ */ jsx55("strong", { children: hiddenInlineNodes(g(1) || g(2), ctx, key()) }, key()));
5295
5316
  else if (kind === "em") out.push(/* @__PURE__ */ jsx55("em", { children: hiddenInlineNodes(g(1) || g(2), ctx, key()) }, key()));
@@ -5476,7 +5497,7 @@ function Markdown({
5476
5497
  tone = "default"
5477
5498
  }) {
5478
5499
  const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
5479
- const blocks = React35.useMemo(() => parseBlocks(source), [source]);
5500
+ const blocks = React36.useMemo(() => parseBlocks(source), [source]);
5480
5501
  return /* @__PURE__ */ jsx55("div", { className: mdClass("fd-md", size, tone, className), children: renderBlocks(blocks, ctx, "b") });
5481
5502
  }
5482
5503
  function MarkdownInline({ source = "", className = "", onLinkClick, size, tone }) {
@@ -5587,7 +5608,7 @@ function Pagination({
5587
5608
  }
5588
5609
 
5589
5610
  // src/components/data/RelativeTime.tsx
5590
- import * as React36 from "react";
5611
+ import * as React37 from "react";
5591
5612
  import { jsxs as jsxs48 } from "react/jsx-runtime";
5592
5613
  var MIN = 6e4;
5593
5614
  var HOUR = 36e5;
@@ -5639,9 +5660,9 @@ function formatDuration(ms) {
5639
5660
  return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
5640
5661
  }
5641
5662
  function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
5642
- const [, force] = React36.useState(0);
5663
+ const [, force] = React37.useState(0);
5643
5664
  const t = value instanceof Date ? value.getTime() : Date.parse(value);
5644
- React36.useEffect(() => {
5665
+ React37.useEffect(() => {
5645
5666
  if (!refresh2 || !t || isNaN(t)) return;
5646
5667
  const abs = Math.abs(t - Date.now());
5647
5668
  if (abs > DAY) return;
@@ -5657,7 +5678,7 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
5657
5678
  }
5658
5679
 
5659
5680
  // src/components/data/ScoreMeter.tsx
5660
- import * as React37 from "react";
5681
+ import * as React38 from "react";
5661
5682
  import { jsx as jsx58, jsxs as jsxs49 } from "react/jsx-runtime";
5662
5683
  function ScoreMeter({
5663
5684
  score,
@@ -5672,10 +5693,10 @@ function ScoreMeter({
5672
5693
  breakdownWidth = 280,
5673
5694
  className = ""
5674
5695
  }) {
5675
- const [open2, setOpen] = React37.useState(false);
5676
- const ref = React37.useRef(null);
5696
+ const [open2, setOpen] = React38.useState(false);
5697
+ const ref = React38.useRef(null);
5677
5698
  const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
5678
- const body = /* @__PURE__ */ jsxs49(React37.Fragment, { children: [
5699
+ const body = /* @__PURE__ */ jsxs49(React38.Fragment, { children: [
5679
5700
  /* @__PURE__ */ jsx58("span", { className: "fd-scoremeter-rail", style: { width }, "aria-hidden": "true", children: /* @__PURE__ */ jsx58(SegmentedMeter, { total: 100, segments, height, showTotal: false, showPercent: false, legend: false }) }),
5680
5701
  showScore ? /* @__PURE__ */ jsx58("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
5681
5702
  ] });
@@ -5694,7 +5715,7 @@ function ScoreMeter({
5694
5715
  }
5695
5716
  );
5696
5717
  }
5697
- return /* @__PURE__ */ jsxs49(React37.Fragment, { children: [
5718
+ return /* @__PURE__ */ jsxs49(React38.Fragment, { children: [
5698
5719
  /* @__PURE__ */ jsx58(
5699
5720
  "button",
5700
5721
  {
@@ -5725,11 +5746,11 @@ function ScoreMeter({
5725
5746
  }
5726
5747
 
5727
5748
  // src/components/actions/inlinePanel.tsx
5728
- import * as React38 from "react";
5749
+ import * as React39 from "react";
5729
5750
  import { jsx as jsx59 } from "react/jsx-runtime";
5730
5751
  function useInlinePanel() {
5731
- const [open2, setOpen] = React38.useState(false);
5732
- const ref = React38.useRef(null);
5752
+ const [open2, setOpen] = React39.useState(false);
5753
+ const ref = React39.useRef(null);
5733
5754
  return { open: open2, setOpen, ref };
5734
5755
  }
5735
5756
  function InlinePanelSurface({ panel, align = "right", ...popover }) {
@@ -5900,7 +5921,7 @@ function SortMenu({
5900
5921
  }
5901
5922
 
5902
5923
  // src/components/data/StepList.tsx
5903
- import * as React39 from "react";
5924
+ import * as React40 from "react";
5904
5925
  import { jsx as jsx61, jsxs as jsxs51 } from "react/jsx-runtime";
5905
5926
  var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
5906
5927
  function StepList({
@@ -5914,9 +5935,9 @@ function StepList({
5914
5935
  className = "",
5915
5936
  active = false
5916
5937
  }) {
5917
- const [openState, setOpenState] = React39.useState(defaultOpen);
5938
+ const [openState, setOpenState] = React40.useState(defaultOpen);
5918
5939
  const open2 = openProp == null ? openState : openProp;
5919
- const [expanded, setExpanded] = React39.useState({});
5940
+ const [expanded, setExpanded] = React40.useState({});
5920
5941
  if (!steps.length) return null;
5921
5942
  const running = steps.some((s) => s.status === "running");
5922
5943
  const failed = steps.filter((s) => s.status === "error").length;
@@ -5974,7 +5995,7 @@ function StepList({
5974
5995
  }
5975
5996
 
5976
5997
  // src/components/data/VirtualList.tsx
5977
- import * as React40 from "react";
5998
+ import * as React41 from "react";
5978
5999
  import { jsx as jsx62, jsxs as jsxs52 } from "react/jsx-runtime";
5979
6000
  var VIRTUAL_LIST_BUFFER_ROWS = 20;
5980
6001
  var VIRTUAL_LIST_ROW_GAP = 6;
@@ -6026,35 +6047,35 @@ function VirtualList({
6026
6047
  className = "",
6027
6048
  style
6028
6049
  }) {
6029
- const [scrollTop, setScrollTop] = React40.useState(0);
6030
- const loaded = React40.useMemo(
6050
+ const [scrollTop, setScrollTop] = React41.useState(0);
6051
+ const loaded = React41.useMemo(
6031
6052
  () => ({ firstItemIndex, count: items.length }),
6032
6053
  [firstItemIndex, items.length]
6033
6054
  );
6034
6055
  const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
6035
6056
  const bandKey = firstItemIndex + ":" + items.length;
6036
- const win = React40.useMemo(
6057
+ const win = React41.useMemo(
6037
6058
  () => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
6038
6059
  [scrollTop, height, itemHeight, total, loaded]
6039
6060
  );
6040
- const need = React40.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
6061
+ const need = React41.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
6041
6062
  const wantStart = need.start && hasMore?.start !== false;
6042
6063
  const wantEnd = need.end && hasMore?.end !== false;
6043
6064
  const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
6044
6065
  const askKey = bandKey + "@" + bucket2;
6045
- const asked = React40.useRef({ start: null, end: null });
6046
- React40.useEffect(() => {
6066
+ const asked = React41.useRef({ start: null, end: null });
6067
+ React41.useEffect(() => {
6047
6068
  if (loading || !wantStart || asked.current.start === askKey) return;
6048
6069
  asked.current.start = askKey;
6049
6070
  onNeedMore("start", win);
6050
6071
  }, [wantStart, loading, askKey, onNeedMore, win]);
6051
- React40.useEffect(() => {
6072
+ React41.useEffect(() => {
6052
6073
  if (loading || !wantEnd || asked.current.end === askKey) return;
6053
6074
  asked.current.end = askKey;
6054
6075
  onNeedMore("end", win);
6055
6076
  }, [wantEnd, loading, askKey, onNeedMore, win]);
6056
- const lastKeysRef = React40.useRef(null);
6057
- const newKeys = React40.useMemo(() => {
6077
+ const lastKeysRef = React41.useRef(null);
6078
+ const newKeys = React41.useMemo(() => {
6058
6079
  const prev = lastKeysRef.current;
6059
6080
  if (!prev) return /* @__PURE__ */ new Set();
6060
6081
  const fresh = /* @__PURE__ */ new Set();
@@ -6064,7 +6085,7 @@ function VirtualList({
6064
6085
  }
6065
6086
  return fresh;
6066
6087
  }, [items]);
6067
- React40.useEffect(() => {
6088
+ React41.useEffect(() => {
6068
6089
  lastKeysRef.current = new Set(items.map(keyOf));
6069
6090
  }, [items]);
6070
6091
  const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
@@ -6109,7 +6130,7 @@ function VirtualList({
6109
6130
  }
6110
6131
 
6111
6132
  // src/components/data/EntityRow.tsx
6112
- import * as React41 from "react";
6133
+ import * as React42 from "react";
6113
6134
  import { jsx as jsx63, jsxs as jsxs53 } from "react/jsx-runtime";
6114
6135
  var ENTITY_ROW_METRIC_WIDTH = 74;
6115
6136
  var METRIC_TONE_COLOR = {
@@ -6122,7 +6143,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
6122
6143
  const key = m.id || m.label || i;
6123
6144
  const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
6124
6145
  const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
6125
- const content = /* @__PURE__ */ jsxs53(React41.Fragment, { children: [
6146
+ const content = /* @__PURE__ */ jsxs53(React42.Fragment, { children: [
6126
6147
  m.icon ? /* @__PURE__ */ jsx63("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
6127
6148
  /* @__PURE__ */ jsx63("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
6128
6149
  /* @__PURE__ */ jsx63("span", { className: "fd-sr", children: " " + m.label })
@@ -6214,7 +6235,7 @@ function EntityRow({
6214
6235
  }
6215
6236
 
6216
6237
  // src/components/data/TransferList.tsx
6217
- import * as React42 from "react";
6238
+ import * as React43 from "react";
6218
6239
  import { createPortal as createPortal5 } from "react-dom";
6219
6240
 
6220
6241
  // src/components/forms/Input.tsx
@@ -6320,12 +6341,12 @@ function TransferList({
6320
6341
  listHeight = 440,
6321
6342
  className = ""
6322
6343
  }) {
6323
- const [drag, setDrag] = React42.useState(null);
6324
- const [dragOverSide, setDragOverSide] = React42.useState(null);
6325
- const dragRef = React42.useRef(null);
6326
- const armedRef = React42.useRef(null);
6327
- const sideRefs = React42.useRef({ left: null, right: null });
6328
- const hitTestSide = React42.useCallback((x, y) => {
6344
+ const [drag, setDrag] = React43.useState(null);
6345
+ const [dragOverSide, setDragOverSide] = React43.useState(null);
6346
+ const dragRef = React43.useRef(null);
6347
+ const armedRef = React43.useRef(null);
6348
+ const sideRefs = React43.useRef({ left: null, right: null });
6349
+ const hitTestSide = React43.useCallback((x, y) => {
6329
6350
  for (const side of ["left", "right"]) {
6330
6351
  const el = sideRefs.current[side];
6331
6352
  if (!el) continue;
@@ -6334,7 +6355,7 @@ function TransferList({
6334
6355
  }
6335
6356
  return null;
6336
6357
  }, []);
6337
- const findItem = React42.useCallback(
6358
+ const findItem = React43.useCallback(
6338
6359
  (side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
6339
6360
  [left.items, right.items, keyOf]
6340
6361
  );
@@ -6356,7 +6377,7 @@ function TransferList({
6356
6377
  height: rect.height
6357
6378
  };
6358
6379
  };
6359
- React42.useEffect(() => {
6380
+ React43.useEffect(() => {
6360
6381
  const onMovePointer = (e) => {
6361
6382
  const armed = armedRef.current;
6362
6383
  if (!armed || e.pointerId !== armed.pointerId) return;
@@ -6409,7 +6430,7 @@ function TransferList({
6409
6430
  window.removeEventListener("pointercancel", endDrag);
6410
6431
  };
6411
6432
  }, [hitTestSide, findItem, onMove]);
6412
- React42.useEffect(() => {
6433
+ React43.useEffect(() => {
6413
6434
  if (!drag || typeof document === "undefined") return;
6414
6435
  const prev = document.body.style.userSelect;
6415
6436
  document.body.style.userSelect = "none";
@@ -6526,7 +6547,7 @@ function FactList({ facts = [], className = "", ...rest }) {
6526
6547
  }
6527
6548
 
6528
6549
  // src/components/data/USChoropleth.tsx
6529
- import * as React44 from "react";
6550
+ import * as React45 from "react";
6530
6551
 
6531
6552
  // src/components/data/usChoropleth/mapBox.ts
6532
6553
  var MAP_WIDTH = 975;
@@ -6591,11 +6612,11 @@ function buildChoroplethModel(values, topN, givenTotal) {
6591
6612
  }
6592
6613
 
6593
6614
  // src/components/data/usChoropleth/useUsStateShapes.ts
6594
- import * as React43 from "react";
6615
+ import * as React44 from "react";
6595
6616
  function useUsStateShapes() {
6596
- const [token, setToken] = React43.useState(0);
6597
- const [settled, setSettled] = React43.useState(null);
6598
- React43.useEffect(() => {
6617
+ const [token, setToken] = React44.useState(0);
6618
+ const [settled, setSettled] = React44.useState(null);
6619
+ React44.useEffect(() => {
6599
6620
  let current2 = true;
6600
6621
  import("./usStateShapes-JJARDNLL.js").then(({ STATE_SHAPES }) => {
6601
6622
  if (current2) setSettled({ token, state: { status: "ready", shapes: STATE_SHAPES } });
@@ -6637,7 +6658,7 @@ function nextCode(key, from) {
6637
6658
  }
6638
6659
  function StateMap({ shapes, model, figures, label, formatReadout }) {
6639
6660
  const tip = useTooltip();
6640
- const [stop, setStop] = React44.useState(US_STATE_CODES[0]);
6661
+ const [stop, setStop] = React45.useState(US_STATE_CODES[0]);
6641
6662
  const onKeyDown = (event) => {
6642
6663
  const from = event.target.getAttribute("data-state");
6643
6664
  const to = from && nextCode(event.key, from);
@@ -6685,8 +6706,8 @@ function StateTable({ model, valueLabel, formatValue }) {
6685
6706
  return /* @__PURE__ */ jsx68(Collapsible, { title: TABLE_TITLE, children: /* @__PURE__ */ jsx68(DataTable, { columns, rows: model.rows, rowKey: "code", compact: true }) });
6686
6707
  }
6687
6708
  function USChoropleth({ values, label, valueLabel, formatValue, formatReadout, topN, total, className = "" }) {
6688
- const model = React44.useMemo(() => buildChoroplethModel(values, topN ?? 0, total), [values, topN, total]);
6689
- const figures = React44.useMemo(() => new Map(model.rows.map((row) => [row.code, row])), [model]);
6709
+ const model = React45.useMemo(() => buildChoroplethModel(values, topN ?? 0, total), [values, topN, total]);
6710
+ const figures = React45.useMemo(() => new Map(model.rows.map((row) => [row.code, row])), [model]);
6690
6711
  const { state, retry } = useUsStateShapes();
6691
6712
  return /* @__PURE__ */ jsxs57("div", { className: ["fd-uschoro", className].filter(Boolean).join(" "), children: [
6692
6713
  /* @__PURE__ */ jsxs57("div", { className: "fd-uschoro-layout", children: [
@@ -6721,11 +6742,11 @@ function USChoropleth({ values, label, valueLabel, formatValue, formatReadout, t
6721
6742
  }
6722
6743
 
6723
6744
  // src/components/forms/Checkbox.tsx
6724
- import * as React45 from "react";
6745
+ import * as React46 from "react";
6725
6746
  import { jsx as jsx69, jsxs as jsxs58 } from "react/jsx-runtime";
6726
6747
  function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
6727
- const ref = React45.useRef(null);
6728
- React45.useEffect(() => {
6748
+ const ref = React46.useRef(null);
6749
+ React46.useEffect(() => {
6729
6750
  if (ref.current) ref.current.indeterminate = indeterminate;
6730
6751
  }, [indeterminate]);
6731
6752
  return /* @__PURE__ */ jsxs58("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
@@ -6772,7 +6793,7 @@ function Switch({ label, description, className = "", ...rest }) {
6772
6793
  }
6773
6794
 
6774
6795
  // src/components/forms/Select.tsx
6775
- import * as React46 from "react";
6796
+ import * as React47 from "react";
6776
6797
  import { jsx as jsx72, jsxs as jsxs61 } from "react/jsx-runtime";
6777
6798
  var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
6778
6799
  function Select({
@@ -6800,12 +6821,12 @@ function Select({
6800
6821
  const isOn = (v) => multiple ? vals.includes(v) : v === value;
6801
6822
  const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
6802
6823
  const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id, hiddenLabel);
6803
- const [open2, setOpen] = React46.useState(false);
6804
- const [q, setQ] = React46.useState("");
6805
- const rootRef = React46.useRef(null);
6806
- const boxRef = React46.useRef(null);
6807
- const listRef = React46.useRef(null);
6808
- const typeBuf = React46.useRef({ s: "", t: 0 });
6824
+ const [open2, setOpen] = React47.useState(false);
6825
+ const [q, setQ] = React47.useState("");
6826
+ const rootRef = React47.useRef(null);
6827
+ const boxRef = React47.useRef(null);
6828
+ const listRef = React47.useRef(null);
6829
+ const typeBuf = React47.useRef({ s: "", t: 0 });
6809
6830
  const selected = multiple ? null : opts.find((o) => o.value === value);
6810
6831
  const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
6811
6832
  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;
@@ -6941,7 +6962,7 @@ function Select({
6941
6962
  ),
6942
6963
  q ? /* @__PURE__ */ jsx72("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
6943
6964
  ] }) : void 0,
6944
- footer: multiple ? /* @__PURE__ */ jsxs61(React46.Fragment, { children: [
6965
+ footer: multiple ? /* @__PURE__ */ jsxs61(React47.Fragment, { children: [
6945
6966
  /* @__PURE__ */ jsx72(
6946
6967
  "button",
6947
6968
  {
@@ -6972,7 +6993,7 @@ function Select({
6972
6993
  'Nothing matches "',
6973
6994
  q,
6974
6995
  '".'
6975
- ] }) : groups.map((grp) => /* @__PURE__ */ jsxs61(React46.Fragment, { children: [
6996
+ ] }) : groups.map((grp) => /* @__PURE__ */ jsxs61(React47.Fragment, { children: [
6976
6997
  grp.g ? /* @__PURE__ */ jsx72("div", { className: "fd-pop-group", children: grp.g }) : null,
6977
6998
  grp.items.map(({ o, i }) => /* @__PURE__ */ jsxs61(
6978
6999
  "button",
@@ -7009,7 +7030,7 @@ function Select({
7009
7030
  }
7010
7031
 
7011
7032
  // src/components/forms/TimePicker.tsx
7012
- import * as React47 from "react";
7033
+ import * as React48 from "react";
7013
7034
  import { jsx as jsx73, jsxs as jsxs62 } from "react/jsx-runtime";
7014
7035
  var pad = (n) => String(n).padStart(2, "0");
7015
7036
  function ClockFace({ value = "09:00", onChange }) {
@@ -7018,9 +7039,9 @@ function ClockFace({ value = "09:00", onChange }) {
7018
7039
  if (isNaN(m)) m = 0;
7019
7040
  const pm = h24 >= 12;
7020
7041
  const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
7021
- const [mode2, setMode] = React47.useState("h");
7022
- const faceRef = React47.useRef(null);
7023
- const dragging = React47.useRef(false);
7042
+ const [mode2, setMode] = React48.useState("h");
7043
+ const faceRef = React48.useRef(null);
7044
+ const dragging = React48.useRef(false);
7024
7045
  const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
7025
7046
  const R = 108, NR = 80;
7026
7047
  const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
@@ -7093,9 +7114,9 @@ function ClockFace({ value = "09:00", onChange }) {
7093
7114
  }
7094
7115
  function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
7095
7116
  const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
7096
- const [open2, setOpen] = React47.useState(false);
7097
- const rootRef = React47.useRef(null);
7098
- const boxRef = React47.useRef(null);
7117
+ const [open2, setOpen] = React48.useState(false);
7118
+ const rootRef = React48.useRef(null);
7119
+ const boxRef = React48.useRef(null);
7099
7120
  const disp = () => {
7100
7121
  if (!value) return "";
7101
7122
  const [h, m] = value.split(":").map(Number);
@@ -7138,7 +7159,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
7138
7159
  offset: 6,
7139
7160
  width: 262,
7140
7161
  role: "presentation",
7141
- footer: /* @__PURE__ */ jsxs62(React47.Fragment, { children: [
7162
+ footer: /* @__PURE__ */ jsxs62(React48.Fragment, { children: [
7142
7163
  /* @__PURE__ */ jsx73(
7143
7164
  "button",
7144
7165
  {
@@ -7166,7 +7187,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
7166
7187
  }
7167
7188
 
7168
7189
  // src/components/forms/Slider.tsx
7169
- import * as React48 from "react";
7190
+ import * as React49 from "react";
7170
7191
  import { jsx as jsx74, jsxs as jsxs63 } from "react/jsx-runtime";
7171
7192
  function Slider({
7172
7193
  label,
@@ -7184,7 +7205,7 @@ function Slider({
7184
7205
  ...rest
7185
7206
  }) {
7186
7207
  const fieldId = useFieldId(id);
7187
- const [dragging, setDragging] = React48.useState(false);
7208
+ const [dragging, setDragging] = React49.useState(false);
7188
7209
  const v = value === void 0 ? min : Number(value);
7189
7210
  const pct = max === min ? 0 : (v - min) / (max - min) * 100;
7190
7211
  return /* @__PURE__ */ jsxs63("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
@@ -7218,7 +7239,7 @@ function Slider({
7218
7239
  }
7219
7240
 
7220
7241
  // src/components/forms/RangeSlider.tsx
7221
- import * as React49 from "react";
7242
+ import * as React50 from "react";
7222
7243
  import { jsx as jsx75, jsxs as jsxs64 } from "react/jsx-runtime";
7223
7244
  function RangeSlider({
7224
7245
  label,
@@ -7238,9 +7259,9 @@ function RangeSlider({
7238
7259
  }) {
7239
7260
  const fmt2 = format || ((v) => String(v));
7240
7261
  const [a, b] = value || [min, max];
7241
- const [drag, setDrag] = React49.useState(null);
7242
- const [focus, setFocus] = React49.useState(null);
7243
- const railRef = React49.useRef(null);
7262
+ const [drag, setDrag] = React50.useState(null);
7263
+ const [focus, setFocus] = React50.useState(null);
7264
+ const railRef = React50.useRef(null);
7244
7265
  const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
7245
7266
  const clampPair = (i, v) => {
7246
7267
  v = Math.min(max, Math.max(min, Math.round(v / step) * step));
@@ -7255,7 +7276,7 @@ function RangeSlider({
7255
7276
  const r = railRef.current.getBoundingClientRect();
7256
7277
  return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
7257
7278
  };
7258
- React49.useEffect(() => {
7279
+ React50.useEffect(() => {
7259
7280
  if (drag === null) return;
7260
7281
  const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
7261
7282
  const upH = () => setDrag(null);
@@ -7336,7 +7357,7 @@ function RangeSlider({
7336
7357
  /* @__PURE__ */ jsxs64("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
7337
7358
  /* @__PURE__ */ jsx75("span", { className: "fd-range-rail", ref: railRef }),
7338
7359
  /* @__PURE__ */ jsx75("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
7339
- marks.map((m) => /* @__PURE__ */ jsxs64(React49.Fragment, { children: [
7360
+ marks.map((m) => /* @__PURE__ */ jsxs64(React50.Fragment, { children: [
7340
7361
  /* @__PURE__ */ jsx75("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
7341
7362
  m.label ? /* @__PURE__ */ jsx75("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
7342
7363
  ] }, m.value)),
@@ -7365,7 +7386,7 @@ function RangeSlider({
7365
7386
  }
7366
7387
 
7367
7388
  // src/components/forms/Dropzone.tsx
7368
- import * as React50 from "react";
7389
+ import * as React51 from "react";
7369
7390
  import { jsx as jsx76, jsxs as jsxs65 } from "react/jsx-runtime";
7370
7391
  function Dropzone({
7371
7392
  onFiles,
@@ -7380,8 +7401,8 @@ function Dropzone({
7380
7401
  className = "",
7381
7402
  style
7382
7403
  }) {
7383
- const [over, setOver] = React50.useState(false);
7384
- const depth = React50.useRef(0);
7404
+ const [over, setOver] = React51.useState(false);
7405
+ const depth = React51.useRef(0);
7385
7406
  const has = (e) => {
7386
7407
  const dt = e.dataTransfer;
7387
7408
  if (!dt) return false;
@@ -7443,8 +7464,8 @@ function FilePickButton({
7443
7464
  className = "",
7444
7465
  children
7445
7466
  }) {
7446
- const ref = React50.useRef(null);
7447
- return /* @__PURE__ */ jsxs65(React50.Fragment, { children: [
7467
+ const ref = React51.useRef(null);
7468
+ return /* @__PURE__ */ jsxs65(React51.Fragment, { children: [
7448
7469
  /* @__PURE__ */ jsx76(
7449
7470
  "button",
7450
7471
  {
@@ -7477,10 +7498,10 @@ function FilePickButton({
7477
7498
  }
7478
7499
  function useStagedFiles(upload, opts) {
7479
7500
  const o = opts || {};
7480
- const [items, setItems] = React50.useState([]);
7481
- const controllers = React50.useRef({});
7501
+ const [items, setItems] = React51.useState([]);
7502
+ const controllers = React51.useRef({});
7482
7503
  const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
7483
- const run = React50.useCallback((att) => {
7504
+ const run = React51.useCallback((att) => {
7484
7505
  if (!upload) return;
7485
7506
  const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
7486
7507
  controllers.current[att.id] = ac;
@@ -7497,14 +7518,14 @@ function useStagedFiles(upload, opts) {
7497
7518
  delete controllers.current[att.id];
7498
7519
  });
7499
7520
  }, [upload]);
7500
- const add = React50.useCallback((files) => {
7521
+ const add = React51.useCallback((files) => {
7501
7522
  if (!upload) return [];
7502
7523
  const atts = Array.from(files).map((f) => toAttachment(f));
7503
7524
  setItems((list) => list.concat(atts));
7504
7525
  atts.forEach(run);
7505
7526
  return atts;
7506
7527
  }, [upload, run]);
7507
- const remove = React50.useCallback((att) => {
7528
+ const remove = React51.useCallback((att) => {
7508
7529
  const ac = controllers.current[att.id];
7509
7530
  if (ac) {
7510
7531
  try {
@@ -7515,10 +7536,10 @@ function useStagedFiles(upload, opts) {
7515
7536
  }
7516
7537
  setItems((list) => list.filter((f) => f.id !== att.id));
7517
7538
  }, []);
7518
- const retry = React50.useCallback((att) => {
7539
+ const retry = React51.useCallback((att) => {
7519
7540
  run(att);
7520
7541
  }, [run]);
7521
- const clear = React50.useCallback(() => {
7542
+ const clear = React51.useCallback(() => {
7522
7543
  Object.values(controllers.current).forEach((ac) => {
7523
7544
  try {
7524
7545
  ac && ac.abort();
@@ -7642,7 +7663,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
7642
7663
  }
7643
7664
 
7644
7665
  // src/components/forms/MarkdownEditor.tsx
7645
- import * as React51 from "react";
7666
+ import * as React52 from "react";
7646
7667
  import { jsx as jsx78, jsxs as jsxs67 } from "react/jsx-runtime";
7647
7668
  var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
7648
7669
  var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
@@ -7856,7 +7877,7 @@ function syncDom(root, value) {
7856
7877
  while (root.children.length > lines.length) root.removeChild(root.lastChild);
7857
7878
  }
7858
7879
  var LIST_CONT = RE_LI;
7859
- var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
7880
+ var MarkdownEditor = React52.forwardRef(function MarkdownEditor2({
7860
7881
  value = "",
7861
7882
  onChange,
7862
7883
  onSubmit,
@@ -7875,10 +7896,10 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
7875
7896
  className = "",
7876
7897
  id
7877
7898
  }, ref) {
7878
- const boxRef = React51.useRef(null);
7879
- const composing = React51.useRef(false);
7880
- const pendingCaret = React51.useRef(null);
7881
- React51.useLayoutEffect(() => {
7899
+ const boxRef = React52.useRef(null);
7900
+ const composing = React52.useRef(false);
7901
+ const pendingCaret = React52.useRef(null);
7902
+ React52.useLayoutEffect(() => {
7882
7903
  const root = boxRef.current;
7883
7904
  if (!root || composing.current) return;
7884
7905
  const active = document.activeElement === root || root.contains(document.activeElement);
@@ -7887,7 +7908,7 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
7887
7908
  pendingCaret.current = null;
7888
7909
  if (active && caret != null) placeCaret(root, caret);
7889
7910
  }, [value]);
7890
- React51.useEffect(() => {
7911
+ React52.useEffect(() => {
7891
7912
  if (autoFocus && boxRef.current) boxRef.current.focus();
7892
7913
  }, [autoFocus]);
7893
7914
  const caretNow = () => {
@@ -7954,8 +7975,8 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
7954
7975
  api.replaceRange(from, to, next, from + next.length);
7955
7976
  }
7956
7977
  };
7957
- React51.useImperativeHandle(ref, () => api);
7958
- const caretAtKeydown = React51.useRef(-1);
7978
+ React52.useImperativeHandle(ref, () => api);
7979
+ const caretAtKeydown = React52.useRef(-1);
7959
7980
  function detect(text, caret) {
7960
7981
  if (!onTrigger) return;
7961
7982
  const upto = text.slice(0, caret);
@@ -8108,7 +8129,7 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
8108
8129
  });
8109
8130
 
8110
8131
  // src/components/forms/CodeEditor.tsx
8111
- import * as React52 from "react";
8132
+ import * as React53 from "react";
8112
8133
  import { EditorView, keymap, lineNumbers, placeholder as cmPlaceholder, drawSelection, Decoration } from "@codemirror/view";
8113
8134
  import { EditorState, StateEffect, StateField, Compartment } from "@codemirror/state";
8114
8135
  import { defaultKeymap, history, historyKeymap, indentMore, indentLess } from "@codemirror/commands";
@@ -8212,16 +8233,16 @@ function CodeEditor({
8212
8233
  const fieldId = useFieldId(id);
8213
8234
  const descId = fieldId + "-desc";
8214
8235
  const liveId = fieldId + "-live";
8215
- const hostRef = React52.useRef(null);
8216
- const viewRef = React52.useRef(null);
8217
- const valueRef = React52.useRef(value);
8218
- const onChangeRef = React52.useRef(onChange);
8236
+ const hostRef = React53.useRef(null);
8237
+ const viewRef = React53.useRef(null);
8238
+ const valueRef = React53.useRef(value);
8239
+ const onChangeRef = React53.useRef(onChange);
8219
8240
  onChangeRef.current = onChange;
8220
- const editableCompartment = React52.useRef(new Compartment()).current;
8221
- const attributesCompartment = React52.useRef(new Compartment()).current;
8222
- const errorRef = React52.useRef(error);
8241
+ const editableCompartment = React53.useRef(new Compartment()).current;
8242
+ const attributesCompartment = React53.useRef(new Compartment()).current;
8243
+ const errorRef = React53.useRef(error);
8223
8244
  errorRef.current = error;
8224
- const diagnosticsCountRef = React52.useRef(diagnostics.length);
8245
+ const diagnosticsCountRef = React53.useRef(diagnostics.length);
8225
8246
  diagnosticsCountRef.current = diagnostics.length;
8226
8247
  function contentAttributes() {
8227
8248
  return {
@@ -8231,7 +8252,7 @@ function CodeEditor({
8231
8252
  ...label ? { "aria-label": label } : {}
8232
8253
  };
8233
8254
  }
8234
- React52.useEffect(() => {
8255
+ React53.useEffect(() => {
8235
8256
  const host2 = hostRef.current;
8236
8257
  if (!host2) return;
8237
8258
  const updateListener = EditorView.updateListener.of((update) => {
@@ -8273,7 +8294,7 @@ function CodeEditor({
8273
8294
  viewRef.current = null;
8274
8295
  };
8275
8296
  }, []);
8276
- React52.useEffect(() => {
8297
+ React53.useEffect(() => {
8277
8298
  const view = viewRef.current;
8278
8299
  if (!view) return;
8279
8300
  const current2 = view.state.doc.toString();
@@ -8282,12 +8303,12 @@ function CodeEditor({
8282
8303
  }
8283
8304
  valueRef.current = value;
8284
8305
  }, [value]);
8285
- React52.useEffect(() => {
8306
+ React53.useEffect(() => {
8286
8307
  const view = viewRef.current;
8287
8308
  if (!view) return;
8288
8309
  view.dispatch({ effects: editableCompartment.reconfigure(EditorView.editable.of(!disabled)) });
8289
8310
  }, [disabled, editableCompartment]);
8290
- React52.useEffect(() => {
8311
+ React53.useEffect(() => {
8291
8312
  const view = viewRef.current;
8292
8313
  if (!view) return;
8293
8314
  view.dispatch({
@@ -8345,11 +8366,11 @@ function CodeEditor({
8345
8366
  }
8346
8367
 
8347
8368
  // src/components/forms/RadioGroup.tsx
8348
- import * as React53 from "react";
8369
+ import * as React54 from "react";
8349
8370
  import { jsx as jsx80, jsxs as jsxs69 } from "react/jsx-runtime";
8350
8371
  function RadioGroup({ label, labelledBy, options, value, onChange, card = false, disabled = false, name, className = "" }) {
8351
- const autoName = React53.useId();
8352
- const labelId = React53.useId();
8372
+ const autoName = React54.useId();
8373
+ const labelId = React54.useId();
8353
8374
  return /* @__PURE__ */ jsxs69("div", { role: "radiogroup", "aria-labelledby": labelledBy ?? labelId, "aria-disabled": disabled || void 0, className: ["fd-radiogroup", className].filter(Boolean).join(" "), children: [
8354
8375
  labelledBy === void 0 && /* @__PURE__ */ jsx80("span", { id: labelId, className: "fd-radiogroup-label", children: label }),
8355
8376
  options.map((o) => /* @__PURE__ */ jsx80(
@@ -8377,16 +8398,16 @@ function Fieldset({ busy = false, className = "", ...rest }) {
8377
8398
  }
8378
8399
 
8379
8400
  // src/components/platform/AccountMenu.tsx
8380
- import * as React55 from "react";
8401
+ import * as React56 from "react";
8381
8402
 
8382
8403
  // src/kits/sessionContext.tsx
8383
- import * as React54 from "react";
8384
- var SessionContext = React54.createContext(null);
8404
+ import * as React55 from "react";
8405
+ var SessionContext = React55.createContext(null);
8385
8406
  function SessionProvider({ value, children }) {
8386
- return React54.createElement(SessionContext.Provider, { value }, children);
8407
+ return React55.createElement(SessionContext.Provider, { value }, children);
8387
8408
  }
8388
8409
  function useSessionContext() {
8389
- const ctx = React54.useContext(SessionContext);
8410
+ const ctx = React55.useContext(SessionContext);
8390
8411
  if (!ctx) {
8391
8412
  throw new Error(
8392
8413
  "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."
@@ -8426,11 +8447,11 @@ function AccountMenu({
8426
8447
  ...rest
8427
8448
  }) {
8428
8449
  const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
8429
- const [open2, setOpen] = React55.useState(false);
8430
- const [switching, setSwitching] = React55.useState(false);
8431
- const [signingOut, setSigningOut] = React55.useState(false);
8432
- const [signOutError, setSignOutError] = React55.useState(null);
8433
- const ref = React55.useRef(null);
8450
+ const [open2, setOpen] = React56.useState(false);
8451
+ const [switching, setSwitching] = React56.useState(false);
8452
+ const [signingOut, setSigningOut] = React56.useState(false);
8453
+ const [signOutError, setSignOutError] = React56.useState(null);
8454
+ const ref = React56.useRef(null);
8434
8455
  const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
8435
8456
  const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || !pending && can2(l.perm)) })).filter((g) => g.links.length);
8436
8457
  const closeMenu = () => {
@@ -8555,13 +8576,13 @@ function AccountMenu({
8555
8576
  }
8556
8577
 
8557
8578
  // src/components/platform/AppSwitcher.tsx
8558
- import * as React56 from "react";
8579
+ import * as React57 from "react";
8559
8580
  import { jsx as jsx83, jsxs as jsxs71 } from "react/jsx-runtime";
8560
8581
  function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
8561
8582
  const { apps: contextApps } = useSessionContext();
8562
8583
  const apps = appsProp ?? contextApps ?? [];
8563
- const [open2, setOpen] = React56.useState(false);
8564
- const anchorRef = React56.useRef(null);
8584
+ const [open2, setOpen] = React57.useState(false);
8585
+ const anchorRef = React57.useRef(null);
8565
8586
  if (!apps.length) return null;
8566
8587
  const items = apps.map((app) => ({
8567
8588
  id: app.key,
@@ -8575,7 +8596,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
8575
8596
  window.location.href = app.url;
8576
8597
  }
8577
8598
  }));
8578
- return /* @__PURE__ */ jsxs71(React56.Fragment, { children: [
8599
+ return /* @__PURE__ */ jsxs71(React57.Fragment, { children: [
8579
8600
  /* @__PURE__ */ jsx83("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx83(
8580
8601
  IconButton,
8581
8602
  {
@@ -8604,10 +8625,10 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
8604
8625
  }
8605
8626
 
8606
8627
  // src/components/platform/AppearanceMenu.tsx
8607
- import * as React59 from "react";
8628
+ import * as React60 from "react";
8608
8629
 
8609
8630
  // src/kits/appearance.ts
8610
- import * as React57 from "react";
8631
+ import * as React58 from "react";
8611
8632
  var DEFAULT_STORAGE_KEY = "fd-appearance";
8612
8633
  var DEFAULT_PREFS = {
8613
8634
  theme: "system",
@@ -8719,8 +8740,8 @@ function watchAppearance(store, root = document.documentElement) {
8719
8740
  };
8720
8741
  }
8721
8742
  function useAppearancePrefs(store) {
8722
- const prefs = React57.useSyncExternalStore(store.subscribe, store.getSnapshot);
8723
- const update = React57.useCallback(
8743
+ const prefs = React58.useSyncExternalStore(store.subscribe, store.getSnapshot);
8744
+ const update = React58.useCallback(
8724
8745
  (patch) => {
8725
8746
  store.write({ ...store.getSnapshot(), ...patch });
8726
8747
  },
@@ -8730,15 +8751,15 @@ function useAppearancePrefs(store) {
8730
8751
  }
8731
8752
 
8732
8753
  // src/components/platform/AppearanceProvider.tsx
8733
- import * as React58 from "react";
8754
+ import * as React59 from "react";
8734
8755
  import { jsx as jsx84 } from "react/jsx-runtime";
8735
- var AppearanceStoreContext = React58.createContext(null);
8756
+ var AppearanceStoreContext = React59.createContext(null);
8736
8757
  function AppearanceProvider({ store, children }) {
8737
- React58.useLayoutEffect(() => watchAppearance(store), [store]);
8758
+ React59.useLayoutEffect(() => watchAppearance(store), [store]);
8738
8759
  return /* @__PURE__ */ jsx84(AppearanceStoreContext.Provider, { value: store, children });
8739
8760
  }
8740
8761
  function useAppearanceStore() {
8741
- const store = React58.useContext(AppearanceStoreContext);
8762
+ const store = React59.useContext(AppearanceStoreContext);
8742
8763
  if (!store) throw new Error("AppearanceMenu and useAppearanceStore must be rendered inside an <AppearanceProvider>.");
8743
8764
  return store;
8744
8765
  }
@@ -8758,10 +8779,10 @@ var TEXT_SCALE_OPTIONS = [
8758
8779
  ];
8759
8780
  function AppearanceMenu({ className = "" }) {
8760
8781
  const [prefs, update] = useAppearancePrefs(useAppearanceStore());
8761
- const [open2, setOpen] = React59.useState(false);
8762
- const anchorRef = React59.useRef(null);
8782
+ const [open2, setOpen] = React60.useState(false);
8783
+ const anchorRef = React60.useRef(null);
8763
8784
  const patch = (p) => update(p);
8764
- return /* @__PURE__ */ jsxs72(React59.Fragment, { children: [
8785
+ return /* @__PURE__ */ jsxs72(React60.Fragment, { children: [
8765
8786
  /* @__PURE__ */ jsx85("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx85(
8766
8787
  IconButton,
8767
8788
  {
@@ -8830,14 +8851,14 @@ function AppearanceMenu({ className = "" }) {
8830
8851
  }
8831
8852
 
8832
8853
  // src/components/platform/ApiSpecBrowser.tsx
8833
- import * as React60 from "react";
8854
+ import * as React61 from "react";
8834
8855
  import { jsx as jsx86, jsxs as jsxs73 } from "react/jsx-runtime";
8835
8856
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
8836
8857
  function Json({ obj }) {
8837
8858
  return /* @__PURE__ */ jsx86("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
8838
8859
  }
8839
8860
  function Endpoint({ s, onRequest }) {
8840
- const [tried, setTried] = React60.useState(null);
8861
+ const [tried, setTried] = React61.useState(null);
8841
8862
  const run = async () => {
8842
8863
  setTried("busy");
8843
8864
  const t0 = (window.performance || Date).now();
@@ -8910,10 +8931,10 @@ function ApiSpecBrowser({
8910
8931
  className = "",
8911
8932
  ...rest
8912
8933
  }) {
8913
- const [q, setQ] = React60.useState("");
8914
- const [method, setMethod] = React60.useState(null);
8915
- const [mod, setMod] = React60.useState(null);
8916
- const [listOnly, setListOnly] = React60.useState(false);
8934
+ const [q, setQ] = React61.useState("");
8935
+ const [method, setMethod] = React61.useState(null);
8936
+ const [mod, setMod] = React61.useState(null);
8937
+ const [listOnly, setListOnly] = React61.useState(false);
8917
8938
  const activeModule = modules && modules.find((m) => m.id === mod);
8918
8939
  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())));
8919
8940
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
@@ -8992,7 +9013,7 @@ function ApiSpecBrowser({
8992
9013
  }
8993
9014
 
8994
9015
  // src/components/platform/ProfilePage.tsx
8995
- import * as React61 from "react";
9016
+ import * as React62 from "react";
8996
9017
  import { jsx as jsx87, jsxs as jsxs74 } from "react/jsx-runtime";
8997
9018
  function fieldInitialValue(field, user) {
8998
9019
  if (field.value) return field.value(user);
@@ -9028,21 +9049,21 @@ function ProfilePage({
9028
9049
  }) {
9029
9050
  const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
9030
9051
  const user = userProp || sessionUser;
9031
- const initialFieldValues = React61.useMemo(() => {
9052
+ const initialFieldValues = React62.useMemo(() => {
9032
9053
  const values2 = {};
9033
9054
  for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
9034
9055
  return values2;
9035
9056
  }, [user.id, fields]);
9036
- const initialNotify = React61.useMemo(() => {
9057
+ const initialNotify = React62.useMemo(() => {
9037
9058
  const values2 = {};
9038
9059
  for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
9039
9060
  return values2;
9040
9061
  }, [user.id, notifications]);
9041
- const [values, setValues] = React61.useState(initialFieldValues);
9042
- const [notify, setNotify] = React61.useState(initialNotify);
9043
- const [saving, setSaving] = React61.useState(false);
9044
- const [saved, setSaved] = React61.useState(false);
9045
- const [prevUserId, setPrevUserId] = React61.useState(user.id);
9062
+ const [values, setValues] = React62.useState(initialFieldValues);
9063
+ const [notify, setNotify] = React62.useState(initialNotify);
9064
+ const [saving, setSaving] = React62.useState(false);
9065
+ const [saved, setSaved] = React62.useState(false);
9066
+ const [prevUserId, setPrevUserId] = React62.useState(user.id);
9046
9067
  if (user.id !== prevUserId) {
9047
9068
  setPrevUserId(user.id);
9048
9069
  setValues(initialFieldValues);
@@ -9230,7 +9251,7 @@ function ProfilePage({
9230
9251
  }
9231
9252
 
9232
9253
  // src/components/platform/SessionScreen.tsx
9233
- import * as React62 from "react";
9254
+ import * as React63 from "react";
9234
9255
  import { Fragment as Fragment22, jsx as jsx88, jsxs as jsxs75 } from "react/jsx-runtime";
9235
9256
  var COPY = {
9236
9257
  "signing-in": { busy: "Signing you in\u2026" },
@@ -9244,13 +9265,13 @@ function SessionScreen({ kind, error, onRetry, productName }) {
9244
9265
  const copy = COPY[kind];
9245
9266
  const busyMessage = "busy" in copy ? copy.busy : null;
9246
9267
  const failureTitle = "failure" in copy ? copy.failure : null;
9247
- const [announced, setAnnounced] = React62.useState("");
9248
- React62.useEffect(() => {
9268
+ const [announced, setAnnounced] = React63.useState("");
9269
+ React63.useEffect(() => {
9249
9270
  setAnnounced(busyMessage ?? "");
9250
9271
  }, [busyMessage]);
9251
- const titleRef = React62.useRef(null);
9272
+ const titleRef = React63.useRef(null);
9252
9273
  const failed = failureTitle !== null;
9253
- React62.useEffect(() => {
9274
+ React63.useEffect(() => {
9254
9275
  titleRef.current?.focus({ preventScroll: true });
9255
9276
  }, [failed]);
9256
9277
  return /* @__PURE__ */ jsx88("main", { className: "fd-session-screen", children: /* @__PURE__ */ jsxs75("div", { className: "fd-session-screen-inner", children: [
@@ -9273,10 +9294,10 @@ function SessionScreen({ kind, error, onRetry, productName }) {
9273
9294
  }
9274
9295
 
9275
9296
  // src/components/platform/RoadmapTimeline.tsx
9276
- import * as React65 from "react";
9297
+ import * as React66 from "react";
9277
9298
 
9278
9299
  // src/kits/session.ts
9279
- import * as React63 from "react";
9300
+ import * as React64 from "react";
9280
9301
  var PERMISSION_CATALOG = [
9281
9302
  { group: "Plans", items: [
9282
9303
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -10843,8 +10864,8 @@ function roadmap(overrides) {
10843
10864
  };
10844
10865
  }
10845
10866
  function useSession() {
10846
- const [s, setS] = React63.useState(getSession);
10847
- React63.useEffect(() => subscribe(setS), []);
10867
+ const [s, setS] = React64.useState(getSession);
10868
+ React64.useEffect(() => subscribe(setS), []);
10848
10869
  return s;
10849
10870
  }
10850
10871
  var SessionKit = {
@@ -10877,7 +10898,7 @@ var SessionKit = {
10877
10898
  };
10878
10899
  function DemoSessionProvider({ children }) {
10879
10900
  const session = useSession();
10880
- const value = React63.useMemo(
10901
+ const value = React64.useMemo(
10881
10902
  () => ({
10882
10903
  user: session.user,
10883
10904
  roles: session.roles,
@@ -10893,11 +10914,11 @@ function DemoSessionProvider({ children }) {
10893
10914
  }),
10894
10915
  [session]
10895
10916
  );
10896
- return React63.createElement(SessionProvider, { value }, children);
10917
+ return React64.createElement(SessionProvider, { value }, children);
10897
10918
  }
10898
10919
 
10899
10920
  // src/kits/runtime.ts
10900
- import * as React64 from "react";
10921
+ import * as React65 from "react";
10901
10922
  var WIRED_ENDPOINTS = [
10902
10923
  // Nothing yet. Every id below would come from a real service:
10903
10924
  // "plan.get", "placements.list", …
@@ -11068,8 +11089,8 @@ var RuntimeKit = {
11068
11089
  };
11069
11090
  RuntimeKit.declare(FEATURE_NEEDS);
11070
11091
  function useRuntimeMode() {
11071
- const [m, setM] = React64.useState(RuntimeKit.getMode());
11072
- React64.useEffect(() => RuntimeKit.subscribe(setM), []);
11092
+ const [m, setM] = React65.useState(RuntimeKit.getMode());
11093
+ React65.useEffect(() => RuntimeKit.subscribe(setM), []);
11073
11094
  return m;
11074
11095
  }
11075
11096
  function useFeatureStatus(key) {
@@ -11152,12 +11173,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
11152
11173
  }
11153
11174
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11154
11175
  const session = SessionKit.useSession();
11155
- const [project, setProject] = React65.useState("");
11156
- const [q, setQ] = React65.useState("");
11157
- const scrollRef = React65.useRef(null);
11158
- const nowRef = React65.useRef(null);
11159
- const rm = React65.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
11160
- const byKey = React65.useMemo(() => {
11176
+ const [project, setProject] = React66.useState("");
11177
+ const [q, setQ] = React66.useState("");
11178
+ const scrollRef = React66.useRef(null);
11179
+ const nowRef = React66.useRef(null);
11180
+ const rm = React66.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
11181
+ const byKey = React66.useMemo(() => {
11161
11182
  const m = {};
11162
11183
  rm.items.forEach((i) => {
11163
11184
  m[i.key] = i;
@@ -11166,7 +11187,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11166
11187
  }, [rm]);
11167
11188
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
11168
11189
  const projects = [...new Set(rm.items.map((i) => i.project))];
11169
- React65.useEffect(() => {
11190
+ React66.useEffect(() => {
11170
11191
  let raf1 = 0, raf2 = 0;
11171
11192
  const place = () => {
11172
11193
  const box = scrollRef.current, mark = nowRef.current;
@@ -11240,7 +11261,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11240
11261
  lastPhase = item.phase;
11241
11262
  const inPhase = items.filter((i) => i.phase === item.phase).length;
11242
11263
  const isBoundary = n === firstPending;
11243
- return /* @__PURE__ */ jsxs76(React65.Fragment, { children: [
11264
+ return /* @__PURE__ */ jsxs76(React66.Fragment, { children: [
11244
11265
  showPhase ? /* @__PURE__ */ jsxs76("div", { className: "fd-rm-era", children: [
11245
11266
  /* @__PURE__ */ jsxs76("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
11246
11267
  /* @__PURE__ */ jsx89("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
@@ -11284,7 +11305,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11284
11305
  }
11285
11306
 
11286
11307
  // src/components/platform/ComingSoon.tsx
11287
- import * as React66 from "react";
11308
+ import * as React67 from "react";
11288
11309
  import { createPortal as createPortal6 } from "react-dom";
11289
11310
  import { Fragment as Fragment24, jsx as jsx90, jsxs as jsxs77 } from "react/jsx-runtime";
11290
11311
  var BYPASS_STORE = "fd.soon.bypass.v1";
@@ -11302,8 +11323,8 @@ function writeBypassed(list) {
11302
11323
  }
11303
11324
  }
11304
11325
  function useBypass(key) {
11305
- const [on, setOn] = React66.useState(() => !!key && readBypassed().indexOf(key) >= 0);
11306
- React66.useEffect(() => {
11326
+ const [on, setOn] = React67.useState(() => !!key && readBypassed().indexOf(key) >= 0);
11327
+ React67.useEffect(() => {
11307
11328
  setOn(!!key && readBypassed().indexOf(key) >= 0);
11308
11329
  }, [key]);
11309
11330
  const set = (next) => {
@@ -11350,9 +11371,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
11350
11371
  ] });
11351
11372
  }
11352
11373
  function useHoverCard(open2) {
11353
- const anchor = React66.useRef(null);
11354
- const [pos, setPos] = React66.useState(null);
11355
- React66.useLayoutEffect(() => {
11374
+ const anchor = React67.useRef(null);
11375
+ const [pos, setPos] = React67.useState(null);
11376
+ React67.useLayoutEffect(() => {
11356
11377
  if (!open2 || !anchor.current) {
11357
11378
  setPos(null);
11358
11379
  return;
@@ -11479,12 +11500,12 @@ function ComingSoon({
11479
11500
  ] });
11480
11501
  }
11481
11502
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
11482
- const [open2, setOpen] = React66.useState(false);
11503
+ const [open2, setOpen] = React67.useState(false);
11483
11504
  const [anchor, pos] = useHoverCard(open2);
11484
- const hoverCardRef = React66.useRef(null);
11505
+ const hoverCardRef = React67.useRef(null);
11485
11506
  const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
11486
11507
  const zIndex = useLayerZIndex(hoverLayer);
11487
- const close2 = React66.useRef(null);
11508
+ const close2 = React67.useRef(null);
11488
11509
  const show = () => {
11489
11510
  if (close2.current) {
11490
11511
  clearTimeout(close2.current);
@@ -11500,7 +11521,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
11500
11521
  setOpen(false);
11501
11522
  }, 140);
11502
11523
  };
11503
- React66.useEffect(() => () => {
11524
+ React67.useEffect(() => () => {
11504
11525
  if (close2.current) clearTimeout(close2.current);
11505
11526
  }, []);
11506
11527
  return /* @__PURE__ */ jsxs77(
@@ -11952,7 +11973,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11952
11973
  }
11953
11974
 
11954
11975
  // src/components/planner/MixGap.tsx
11955
- import * as React67 from "react";
11976
+ import * as React68 from "react";
11956
11977
  import { Fragment as Fragment26, jsx as jsx95, jsxs as jsxs82 } from "react/jsx-runtime";
11957
11978
  var MIX_GAP_LAYOUT = {
11958
11979
  trackHeight: 30,
@@ -11967,7 +11988,7 @@ function mixGapOffset(value, max) {
11967
11988
  }
11968
11989
  function MixGap({ rows = [], loading = false, className = "" }) {
11969
11990
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
11970
- const [hover, setHover] = React67.useState(null);
11991
+ const [hover, setHover] = React68.useState(null);
11971
11992
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
11972
11993
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
11973
11994
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
@@ -12110,7 +12131,7 @@ function ChannelContribution({
12110
12131
  }
12111
12132
 
12112
12133
  // src/components/planner/BudgetReallocator.tsx
12113
- import * as React68 from "react";
12134
+ import * as React69 from "react";
12114
12135
  import { Fragment as Fragment27, jsx as jsx97, jsxs as jsxs84 } from "react/jsx-runtime";
12115
12136
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
12116
12137
  function BudgetReallocator({
@@ -12126,8 +12147,8 @@ function BudgetReallocator({
12126
12147
  onCancel,
12127
12148
  className = ""
12128
12149
  }) {
12129
- const [draft, setDraft] = React68.useState(spend);
12130
- React68.useEffect(() => setDraft(spend), [spend]);
12150
+ const [draft, setDraft] = React69.useState(spend);
12151
+ React69.useEffect(() => setDraft(spend), [spend]);
12131
12152
  const dirty = draft !== spend;
12132
12153
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
12133
12154
  const nextBand = bandFor(nextCrp);
@@ -12142,10 +12163,10 @@ function BudgetReallocator({
12142
12163
  setDraft(spend);
12143
12164
  if (onCancel) onCancel();
12144
12165
  };
12145
- const trackRef = React68.useRef(null);
12146
- const chipRef = React68.useRef(null);
12147
- const [chipLeft, setChipLeft] = React68.useState(null);
12148
- React68.useLayoutEffect(() => {
12166
+ const trackRef = React69.useRef(null);
12167
+ const chipRef = React69.useRef(null);
12168
+ const [chipLeft, setChipLeft] = React69.useState(null);
12169
+ React69.useLayoutEffect(() => {
12149
12170
  const track = trackRef.current;
12150
12171
  if (!dirty || !track) {
12151
12172
  setChipLeft(null);
@@ -12333,7 +12354,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
12333
12354
  }
12334
12355
 
12335
12356
  // src/components/planner/PreferenceMeter.tsx
12336
- import * as React69 from "react";
12357
+ import * as React70 from "react";
12337
12358
  import { jsx as jsx100, jsxs as jsxs87 } from "react/jsx-runtime";
12338
12359
  function preferenceScore(criteria) {
12339
12360
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
@@ -12363,7 +12384,7 @@ function PreferenceMeter({
12363
12384
  className = ""
12364
12385
  }) {
12365
12386
  const value = score == null ? preferenceScore(criteria) : score;
12366
- const segments = React69.useMemo(() => preferenceSegments(criteria), [criteria]);
12387
+ const segments = React70.useMemo(() => preferenceSegments(criteria), [criteria]);
12367
12388
  return /* @__PURE__ */ jsx100(
12368
12389
  ScoreMeter,
12369
12390
  {
@@ -12402,13 +12423,13 @@ function PreferenceMeter({
12402
12423
  }
12403
12424
 
12404
12425
  // src/components/chat/AgentChatPanel.tsx
12405
- import * as React76 from "react";
12426
+ import * as React77 from "react";
12406
12427
 
12407
12428
  // src/components/chat/chatEngine.ts
12408
- import * as React71 from "react";
12429
+ import * as React72 from "react";
12409
12430
 
12410
12431
  // src/components/chat/chatStore.ts
12411
- import * as React70 from "react";
12432
+ import * as React71 from "react";
12412
12433
  var safeStore = {
12413
12434
  get(k) {
12414
12435
  try {
@@ -12437,13 +12458,13 @@ function useChatDraft(owner, contextType, contextId, store = safeStore) {
12437
12458
  if (owner === "") throw new Error("useChatDraft: draftOwner is an empty string; pass the signed-in user's id, or null for no owner.");
12438
12459
  const key = owner === null ? null : draftKey(owner, contextType, contextId);
12439
12460
  const read2 = (k) => k ? store.get(k) || "" : "";
12440
- const [state, setState] = React70.useState(() => ({ key, text: read2(key) }));
12461
+ const [state, setState] = React71.useState(() => ({ key, text: read2(key) }));
12441
12462
  let current2 = state;
12442
12463
  if (state.key !== key) {
12443
12464
  current2 = { key, text: read2(key) };
12444
12465
  setState(current2);
12445
12466
  }
12446
- const setText = React70.useCallback((text) => {
12467
+ const setText = React71.useCallback((text) => {
12447
12468
  if (key) {
12448
12469
  if (text) {
12449
12470
  store.set(key, text);
@@ -12502,33 +12523,33 @@ function useChatEngine(opts) {
12502
12523
  onClear,
12503
12524
  onFeedback
12504
12525
  } = opts || {};
12505
- const [status, setStatus] = React71.useState("idle");
12506
- const [threadId, setThreadId] = React71.useState(null);
12507
- const [messages, setMessages] = React71.useState([]);
12508
- const [queue, setQueue] = React71.useState([]);
12509
- const [fatal, setFatal] = React71.useState(null);
12510
- const [busy, setBusy] = React71.useState(false);
12511
- const [turnStartedAt, setTurnStartedAt] = React71.useState(null);
12512
- const listRef = React71.useRef([]);
12513
- const queueRef = React71.useRef([]);
12514
- const busyRef = React71.useRef(false);
12515
- const loadedRef = React71.useRef(false);
12516
- const stoppedRef = React71.useRef(false);
12517
- const abortRef = React71.useRef(null);
12518
- const serverCount = React71.useRef(0);
12519
- const serverIds = React71.useRef(/* @__PURE__ */ new Set());
12520
- const liveTurn = React71.useRef(null);
12521
- const lastTurnOwn = React71.useRef(/* @__PURE__ */ new Set());
12522
- const retired = React71.useRef(/* @__PURE__ */ new Set());
12523
- const threadRef = React71.useRef(null);
12524
- const mounted = React71.useRef(true);
12525
- React71.useEffect(() => {
12526
+ const [status, setStatus] = React72.useState("idle");
12527
+ const [threadId, setThreadId] = React72.useState(null);
12528
+ const [messages, setMessages] = React72.useState([]);
12529
+ const [queue, setQueue] = React72.useState([]);
12530
+ const [fatal, setFatal] = React72.useState(null);
12531
+ const [busy, setBusy] = React72.useState(false);
12532
+ const [turnStartedAt, setTurnStartedAt] = React72.useState(null);
12533
+ const listRef = React72.useRef([]);
12534
+ const queueRef = React72.useRef([]);
12535
+ const busyRef = React72.useRef(false);
12536
+ const loadedRef = React72.useRef(false);
12537
+ const stoppedRef = React72.useRef(false);
12538
+ const abortRef = React72.useRef(null);
12539
+ const serverCount = React72.useRef(0);
12540
+ const serverIds = React72.useRef(/* @__PURE__ */ new Set());
12541
+ const liveTurn = React72.useRef(null);
12542
+ const lastTurnOwn = React72.useRef(/* @__PURE__ */ new Set());
12543
+ const retired = React72.useRef(/* @__PURE__ */ new Set());
12544
+ const threadRef = React72.useRef(null);
12545
+ const mounted = React72.useRef(true);
12546
+ React72.useEffect(() => {
12526
12547
  mounted.current = true;
12527
12548
  return () => {
12528
12549
  mounted.current = false;
12529
12550
  };
12530
12551
  }, []);
12531
- const describeWaitingRef = React71.useRef(describeWaiting);
12552
+ const describeWaitingRef = React72.useRef(describeWaiting);
12532
12553
  describeWaitingRef.current = describeWaiting;
12533
12554
  const commit = (next) => {
12534
12555
  const derived = withWaiting(next, (pending) => describeWaitingRef.current(pending));
@@ -12547,7 +12568,7 @@ function useChatEngine(opts) {
12547
12568
  }
12548
12569
  return false;
12549
12570
  };
12550
- const loadThread = React71.useCallback(async (id) => {
12571
+ const loadThread = React72.useCallback(async (id) => {
12551
12572
  const data = await apiAdapter.getThread(id);
12552
12573
  const list = [...data && data.messages || []];
12553
12574
  serverCount.current = list.length;
@@ -12587,7 +12608,7 @@ function useChatEngine(opts) {
12587
12608
  packet: progress.packet ?? holder.packet
12588
12609
  });
12589
12610
  }
12590
- React71.useEffect(() => {
12611
+ React72.useEffect(() => {
12591
12612
  if (!apiAdapter) {
12592
12613
  setStatus("idle");
12593
12614
  setFatal(null);
@@ -12819,7 +12840,7 @@ function useChatEngine(opts) {
12819
12840
  await dispatchTurn(turn);
12820
12841
  }
12821
12842
  }
12822
- const send = React71.useCallback((text, attachments) => {
12843
+ const send = React72.useCallback((text, attachments) => {
12823
12844
  const body = (text || "").trim();
12824
12845
  if (!body && !(attachments && attachments.length)) return;
12825
12846
  if (status === "disconnected") return;
@@ -12829,7 +12850,7 @@ function useChatEngine(opts) {
12829
12850
  stoppedRef.current = false;
12830
12851
  drain();
12831
12852
  }, [status]);
12832
- const stop = React71.useCallback(() => {
12853
+ const stop = React72.useCallback(() => {
12833
12854
  stoppedRef.current = true;
12834
12855
  const ac = abortRef.current;
12835
12856
  if (ac) {
@@ -12848,11 +12869,11 @@ function useChatEngine(opts) {
12848
12869
  store.del(jobKey(threadRef.current));
12849
12870
  }
12850
12871
  }, [apiAdapter]);
12851
- const removeQueued = React71.useCallback((id) => {
12872
+ const removeQueued = React72.useCallback((id) => {
12852
12873
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
12853
12874
  setQueue(queueRef.current.slice());
12854
12875
  }, []);
12855
- const retry = React71.useCallback(() => {
12876
+ const retry = React72.useCallback(() => {
12856
12877
  const list = listRef.current;
12857
12878
  let at = -1;
12858
12879
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -12869,19 +12890,19 @@ function useChatEngine(opts) {
12869
12890
  setQueue(queueRef.current.slice());
12870
12891
  drain();
12871
12892
  }, []);
12872
- const clear = React71.useCallback(() => {
12893
+ const clear = React72.useCallback(() => {
12873
12894
  commit([]);
12874
12895
  serverCount.current = 0;
12875
12896
  queueRef.current = [];
12876
12897
  setQueue([]);
12877
12898
  onClear && onClear();
12878
12899
  }, [onClear]);
12879
- const setFeedback = React71.useCallback((id, value) => {
12900
+ const setFeedback = React72.useCallback((id, value) => {
12880
12901
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
12881
12902
  const msg = listRef.current.find((m) => m.id === id);
12882
12903
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
12883
12904
  }, [onFeedback]);
12884
- const reload = React71.useCallback(async () => {
12905
+ const reload = React72.useCallback(async () => {
12885
12906
  if (!threadRef.current) return;
12886
12907
  setStatus("loading");
12887
12908
  try {
@@ -12919,10 +12940,10 @@ var ChatKit = {
12919
12940
  };
12920
12941
 
12921
12942
  // src/components/chat/ChatTranscript.tsx
12922
- import * as React73 from "react";
12943
+ import * as React74 from "react";
12923
12944
 
12924
12945
  // src/components/chat/ChatTurn.tsx
12925
- import * as React72 from "react";
12946
+ import * as React73 from "react";
12926
12947
  import { jsx as jsx101, jsxs as jsxs88 } from "react/jsx-runtime";
12927
12948
  function JsonView({ value }) {
12928
12949
  let text;
@@ -12959,7 +12980,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
12959
12980
  ] });
12960
12981
  }
12961
12982
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
12962
- const [open2, setOpen] = React72.useState(defaultOpen);
12983
+ const [open2, setOpen] = React73.useState(defaultOpen);
12963
12984
  if (!text) return null;
12964
12985
  return /* @__PURE__ */ jsxs88("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
12965
12986
  /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -12976,7 +12997,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
12976
12997
  ] });
12977
12998
  }
12978
12999
  function Citations({ items = [], onOpen }) {
12979
- const [open2, setOpen] = React72.useState(false);
13000
+ const [open2, setOpen] = React73.useState(false);
12980
13001
  if (!items.length) return null;
12981
13002
  return /* @__PURE__ */ jsxs88("div", { className: "fdc-cites", children: [
12982
13003
  /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -13002,7 +13023,7 @@ function clampText(text, max) {
13002
13023
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
13003
13024
  }
13004
13025
  function MessageBody({ message: m, ctx }) {
13005
- const [expanded, setExpanded] = React72.useState(false);
13026
+ const [expanded, setExpanded] = React73.useState(false);
13006
13027
  const isUser = m.role === "user";
13007
13028
  const raw = m.text || "";
13008
13029
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
@@ -13081,7 +13102,7 @@ function RunActions({ group, ctx }) {
13081
13102
  ] }),
13082
13103
  isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx101("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx101("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
13083
13104
  group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx101("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx101("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
13084
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs88(React72.Fragment, { children: [
13105
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs88(React73.Fragment, { children: [
13085
13106
  /* @__PURE__ */ jsx101("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__ */ jsx101("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
13086
13107
  /* @__PURE__ */ jsx101("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__ */ jsx101("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
13087
13108
  ] }) : null,
@@ -13176,10 +13197,10 @@ function ChatTranscript({
13176
13197
  renderEmpty,
13177
13198
  className = ""
13178
13199
  }) {
13179
- const scroller = React73.useRef(null);
13180
- const stick = React73.useRef(true);
13181
- const [pill, setPill] = React73.useState(0);
13182
- const seen = React73.useRef(0);
13200
+ const scroller = React74.useRef(null);
13201
+ const stick = React74.useRef(true);
13202
+ const [pill, setPill] = React74.useState(0);
13203
+ const seen = React74.useRef(0);
13183
13204
  const toBottom = (smooth) => {
13184
13205
  const el = scroller.current;
13185
13206
  if (!el) return;
@@ -13198,7 +13219,7 @@ function ChatTranscript({
13198
13219
  seen.current = messages.length;
13199
13220
  }
13200
13221
  };
13201
- React73.useLayoutEffect(() => {
13222
+ React74.useLayoutEffect(() => {
13202
13223
  const el = scroller.current;
13203
13224
  if (!el) return;
13204
13225
  if (stick.current) {
@@ -13206,7 +13227,7 @@ function ChatTranscript({
13206
13227
  seen.current = messages.length;
13207
13228
  } else setPill(Math.max(0, messages.length - seen.current));
13208
13229
  }, [messages]);
13209
- React73.useEffect(() => {
13230
+ React74.useEffect(() => {
13210
13231
  const el = scroller.current;
13211
13232
  const inner = el && el.firstChild;
13212
13233
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -13216,7 +13237,7 @@ function ChatTranscript({
13216
13237
  ro.observe(inner);
13217
13238
  return () => ro.disconnect();
13218
13239
  }, []);
13219
- const groups = React73.useMemo(() => groupMessages(messages), [messages]);
13240
+ const groups = React74.useMemo(() => groupMessages(messages), [messages]);
13220
13241
  const empty = !messages.length && status === "ready";
13221
13242
  return /* @__PURE__ */ jsxs89("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
13222
13243
  /* @__PURE__ */ jsxs89("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
@@ -13240,7 +13261,7 @@ function ChatTranscript({
13240
13261
  const prev = groups[i - 1];
13241
13262
  const k = dayKey(g.messages[0].timestamp);
13242
13263
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
13243
- return /* @__PURE__ */ jsxs89(React73.Fragment, { children: [
13264
+ return /* @__PURE__ */ jsxs89(React74.Fragment, { children: [
13244
13265
  showDay ? /* @__PURE__ */ jsx102("div", { className: "fdc-day", children: /* @__PURE__ */ jsx102("span", { children: dayLabel(k) }) }) : null,
13245
13266
  /* @__PURE__ */ jsx102(ChatTurn, { group: g, ctx })
13246
13267
  ] }, g.key || i);
@@ -13257,7 +13278,7 @@ function ChatTranscript({
13257
13278
  var TranscriptKit = { groupMessages };
13258
13279
 
13259
13280
  // src/components/chat/ChatComposer.tsx
13260
- import * as React74 from "react";
13281
+ import * as React75 from "react";
13261
13282
  import { jsx as jsx103, jsxs as jsxs90 } from "react/jsx-runtime";
13262
13283
  function ChatComposer({
13263
13284
  onSubmit,
@@ -13285,17 +13306,17 @@ function ChatComposer({
13285
13306
  onReject,
13286
13307
  onOpenAttachment
13287
13308
  }) {
13288
- const [text, setText] = React74.useState(draft || "");
13289
- const [trigger, setTrigger] = React74.useState(null);
13290
- const [mentionItems, setMentionItems] = React74.useState([]);
13291
- const [listening, setListening] = React74.useState(false);
13292
- const [notice, setNotice] = React74.useState(null);
13293
- const editor = React74.useRef(null);
13294
- const wrap = React74.useRef(null);
13295
- const stopVoice = React74.useRef(null);
13309
+ const [text, setText] = React75.useState(draft || "");
13310
+ const [trigger, setTrigger] = React75.useState(null);
13311
+ const [mentionItems, setMentionItems] = React75.useState([]);
13312
+ const [listening, setListening] = React75.useState(false);
13313
+ const [notice, setNotice] = React75.useState(null);
13314
+ const editor = React75.useRef(null);
13315
+ const wrap = React75.useRef(null);
13316
+ const stopVoice = React75.useRef(null);
13296
13317
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
13297
13318
  } });
13298
- React74.useEffect(() => {
13319
+ React75.useEffect(() => {
13299
13320
  if (draft != null && draft !== text) setText(draft);
13300
13321
  }, [draft]);
13301
13322
  const change = (v) => {
@@ -13331,7 +13352,7 @@ function ChatComposer({
13331
13352
  e.preventDefault();
13332
13353
  staged.add(found.files);
13333
13354
  };
13334
- React74.useEffect(() => {
13355
+ React75.useEffect(() => {
13335
13356
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
13336
13357
  setMentionItems([]);
13337
13358
  return;
@@ -13349,7 +13370,7 @@ function ChatComposer({
13349
13370
  const q = (trigger.query || "").toLowerCase();
13350
13371
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
13351
13372
  }, [trigger, mentionSources]);
13352
- const slashItems = React74.useMemo(() => {
13373
+ const slashItems = React75.useMemo(() => {
13353
13374
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
13354
13375
  const q = (trigger.query || "").toLowerCase();
13355
13376
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -13519,12 +13540,12 @@ function ChatComposer({
13519
13540
  }
13520
13541
 
13521
13542
  // src/components/chat/ChatSessionBar.tsx
13522
- import * as React75 from "react";
13543
+ import * as React76 from "react";
13523
13544
  import { jsx as jsx104, jsxs as jsxs91 } from "react/jsx-runtime";
13524
13545
  var compact2 = meterFormats.compact;
13525
13546
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
13526
- const [open2, setOpen] = React75.useState(false);
13527
- const anchor = React75.useRef(null);
13547
+ const [open2, setOpen] = React76.useState(false);
13548
+ const anchor = React76.useRef(null);
13528
13549
  const stats = sessionStats || null;
13529
13550
  const cu = contextUsage || null;
13530
13551
  const limits = usageLimits || null;
@@ -13539,7 +13560,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
13539
13560
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
13540
13561
  if (cu) bits.push(pct + "% context");
13541
13562
  const expandable = !!(cu || limits);
13542
- return /* @__PURE__ */ jsxs91(React75.Fragment, { children: [
13563
+ return /* @__PURE__ */ jsxs91(React76.Fragment, { children: [
13543
13564
  /* @__PURE__ */ jsxs91("div", { className: "fdc-bar", children: [
13544
13565
  /* @__PURE__ */ jsxs91(
13545
13566
  "button",
@@ -13680,7 +13701,7 @@ function ModelControls({
13680
13701
  ] })
13681
13702
  });
13682
13703
  }
13683
- return /* @__PURE__ */ jsxs91(React75.Fragment, { children: [
13704
+ return /* @__PURE__ */ jsxs91(React76.Fragment, { children: [
13684
13705
  /* @__PURE__ */ jsx104(
13685
13706
  MenuButton,
13686
13707
  {
@@ -13800,11 +13821,11 @@ function AgentChatPanel({
13800
13821
  onFeedback,
13801
13822
  onEditMessage
13802
13823
  }) {
13803
- const [panelWidth, setPanelWidth] = React76.useState(width);
13804
- const [applied, setApplied] = React76.useState({});
13824
+ const [panelWidth, setPanelWidth] = React77.useState(width);
13825
+ const [applied, setApplied] = React77.useState({});
13805
13826
  const [draft, setDraft] = useChatDraft(draftOwner, contextType, contextId);
13806
- const dragging = React76.useRef(null);
13807
- React76.useEffect(() => setPanelWidth(width), [width]);
13827
+ const dragging = React77.useRef(null);
13828
+ React77.useEffect(() => setPanelWidth(width), [width]);
13808
13829
  const engine = useChatEngine({
13809
13830
  contextType,
13810
13831
  contextId,
@@ -14010,7 +14031,7 @@ function AgentChatPanel({
14010
14031
  }
14011
14032
 
14012
14033
  // src/components/files/FileViewer.tsx
14013
- import * as React77 from "react";
14034
+ import * as React78 from "react";
14014
14035
  import { jsx as jsx106, jsxs as jsxs93 } from "react/jsx-runtime";
14015
14036
  function previewKindOf(file) {
14016
14037
  const mime = (file.mime || "").toLowerCase();
@@ -14067,13 +14088,13 @@ function parseDelimited(text, delimiter) {
14067
14088
  return rows;
14068
14089
  }
14069
14090
  function usePreview(file, kind, resolveUrl) {
14070
- const [state, setState] = React77.useState({ status: "loading" });
14071
- const [attempt, setAttempt] = React77.useState(0);
14072
- const resolveRef = React77.useRef(resolveUrl);
14073
- React77.useEffect(() => {
14091
+ const [state, setState] = React78.useState({ status: "loading" });
14092
+ const [attempt, setAttempt] = React78.useState(0);
14093
+ const resolveRef = React78.useRef(resolveUrl);
14094
+ React78.useEffect(() => {
14074
14095
  resolveRef.current = resolveUrl;
14075
14096
  }, [resolveUrl]);
14076
- React77.useEffect(() => {
14097
+ React78.useEffect(() => {
14077
14098
  if (kind === "none") {
14078
14099
  setState({ status: "ready" });
14079
14100
  return;
@@ -14103,7 +14124,7 @@ function usePreview(file, kind, resolveUrl) {
14103
14124
  if (ac) ac.abort();
14104
14125
  };
14105
14126
  }, [file.id, kind, attempt]);
14106
- return { ...state, retry: React77.useCallback(() => setAttempt((a) => a + 1), []) };
14127
+ return { ...state, retry: React78.useCallback(() => setAttempt((a) => a + 1), []) };
14107
14128
  }
14108
14129
  function PreviewBody({ file, kind, state }) {
14109
14130
  if (kind === "image") return /* @__PURE__ */ jsx106("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
@@ -14148,13 +14169,13 @@ function PreviewBody({ file, kind, state }) {
14148
14169
  ] });
14149
14170
  }
14150
14171
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
14151
- const kind = React77.useMemo(() => previewKindOf(file), [file]);
14172
+ const kind = React78.useMemo(() => previewKindOf(file), [file]);
14152
14173
  const preview = usePreview(file, kind, resolveUrl);
14153
- const [tab, setTab] = React77.useState("preview");
14154
- const [downloading, setDownloading] = React77.useState(false);
14155
- const [downloadError, setDownloadError] = React77.useState(null);
14174
+ const [tab, setTab] = React78.useState("preview");
14175
+ const [downloading, setDownloading] = React78.useState(false);
14176
+ const [downloadError, setDownloadError] = React78.useState(null);
14156
14177
  const hasSide = sidePanel != null;
14157
- React77.useEffect(() => {
14178
+ React78.useEffect(() => {
14158
14179
  setTab("preview");
14159
14180
  }, [file.id]);
14160
14181
  const download = () => {
@@ -14221,7 +14242,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
14221
14242
  }
14222
14243
 
14223
14244
  // src/components/files/FileBrowser.tsx
14224
- import * as React78 from "react";
14245
+ import * as React79 from "react";
14225
14246
  import { Fragment as Fragment31, jsx as jsx107, jsxs as jsxs94 } from "react/jsx-runtime";
14226
14247
  function childrenOf(folders, parentId) {
14227
14248
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
@@ -14331,8 +14352,8 @@ function FolderPickerMenu({
14331
14352
  ] });
14332
14353
  }
14333
14354
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
14334
- const [over, setOver] = React78.useState(false);
14335
- const dragCounter = React78.useRef(0);
14355
+ const [over, setOver] = React79.useState(false);
14356
+ const dragCounter = React79.useRef(0);
14336
14357
  const dropHandlers = isDropTarget ? {
14337
14358
  onDragEnter: (e) => {
14338
14359
  if (!hasInternalPayload(e)) return;
@@ -14380,8 +14401,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
14380
14401
  }
14381
14402
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
14382
14403
  const kids = childrenOf(folders, folder.id);
14383
- const [expanded, setExpanded] = React78.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
14384
- React78.useEffect(() => {
14404
+ const [expanded, setExpanded] = React79.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
14405
+ React79.useEffect(() => {
14385
14406
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
14386
14407
  }, [currentFolderId, folder.id, folders]);
14387
14408
  const isCurrent = folder.id === currentFolderId;
@@ -14447,15 +14468,15 @@ function FileBrowser({
14447
14468
  const canUpload = perm.canUpload !== false && !!onUpload;
14448
14469
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
14449
14470
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
14450
- const [createOpen, setCreateOpen] = React78.useState(false);
14451
- const [createName, setCreateName] = React78.useState("");
14452
- const [renameTarget, setRenameTarget] = React78.useState(null);
14453
- const [renameValue, setRenameValue] = React78.useState("");
14454
- const [deleteTarget, setDeleteTarget] = React78.useState(null);
14455
- const uploadInputRef = React78.useRef(null);
14456
- const crumbFolders = React78.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
14457
- const subfolders = React78.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
14458
- const currentFiles = React78.useMemo(
14471
+ const [createOpen, setCreateOpen] = React79.useState(false);
14472
+ const [createName, setCreateName] = React79.useState("");
14473
+ const [renameTarget, setRenameTarget] = React79.useState(null);
14474
+ const [renameValue, setRenameValue] = React79.useState("");
14475
+ const [deleteTarget, setDeleteTarget] = React79.useState(null);
14476
+ const uploadInputRef = React79.useRef(null);
14477
+ const crumbFolders = React79.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
14478
+ const subfolders = React79.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
14479
+ const currentFiles = React79.useMemo(
14459
14480
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
14460
14481
  [files, currentFolderId]
14461
14482
  );
@@ -14687,8 +14708,8 @@ function BreadcrumbCrumb({
14687
14708
  isDropTarget,
14688
14709
  onDropPayload
14689
14710
  }) {
14690
- const [over, setOver] = React78.useState(false);
14691
- const dragCounter = React78.useRef(0);
14711
+ const [over, setOver] = React79.useState(false);
14712
+ const dragCounter = React79.useRef(0);
14692
14713
  const dropHandlers = isDropTarget ? {
14693
14714
  onDragEnter: (e) => {
14694
14715
  if (!hasInternalPayload(e)) return;
@@ -14717,7 +14738,7 @@ function BreadcrumbCrumb({
14717
14738
  }
14718
14739
 
14719
14740
  // src/kits/query.ts
14720
- import * as React79 from "react";
14741
+ import * as React80 from "react";
14721
14742
 
14722
14743
  // src/kits/queryUrl.ts
14723
14744
  var historyUrlAdapter = {
@@ -14855,38 +14876,38 @@ function requestFor(params, query, paging, after) {
14855
14876
  }
14856
14877
  var toError = (e) => e instanceof Error ? e : new Error(String(e));
14857
14878
  function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "page", url }) {
14858
- const [base] = React79.useState(() => {
14879
+ const [base] = React80.useState(() => {
14859
14880
  const store = PREFS || window.PlannerPrefs;
14860
14881
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
14861
14882
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
14862
14883
  });
14863
- const [mountParams] = React79.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
14864
- const address = React79.useRef(mountParams);
14865
- const [query, setQuery] = React79.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
14866
- const savePref = React79.useCallback((patch2) => {
14884
+ const [mountParams] = React80.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
14885
+ const address = React80.useRef(mountParams);
14886
+ const [query, setQuery] = React80.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
14887
+ const savePref = React80.useCallback((patch2) => {
14867
14888
  const store = PREFS || window.PlannerPrefs;
14868
14889
  if (prefsKey && store) store.setTable(prefsKey, patch2);
14869
14890
  }, [prefsKey]);
14870
- const [res, setRes] = React79.useState(null);
14871
- const [loading, setLoading] = React79.useState(true);
14872
- const [loadingMore, setLoadingMore] = React79.useState(false);
14873
- const [failure, setFailure] = React79.useState(null);
14874
- const [reloadToken, setReloadToken] = React79.useState(0);
14875
- const moreController = React79.useRef(null);
14891
+ const [res, setRes] = React80.useState(null);
14892
+ const [loading, setLoading] = React80.useState(true);
14893
+ const [loadingMore, setLoadingMore] = React80.useState(false);
14894
+ const [failure, setFailure] = React80.useState(null);
14895
+ const [reloadToken, setReloadToken] = React80.useState(0);
14896
+ const moreController = React80.useRef(null);
14876
14897
  const depKey = (deps || []).join("|");
14877
14898
  const paramKey = JSON.stringify(params || {});
14878
14899
  const queryKey = JSON.stringify(query);
14879
- const lifetime = React79.useRef(null);
14880
- React79.useEffect(() => {
14900
+ const lifetime = React80.useRef(null);
14901
+ React80.useEffect(() => {
14881
14902
  const controller = new AbortController();
14882
14903
  lifetime.current = controller;
14883
14904
  return () => controller.abort();
14884
14905
  }, []);
14885
- const latest = React79.useRef({ res, loading, query, params, endpoint, url, base });
14886
- React79.useLayoutEffect(() => {
14906
+ const latest = React80.useRef({ res, loading, query, params, endpoint, url, base });
14907
+ React80.useLayoutEffect(() => {
14887
14908
  latest.current = { res, loading, query, params, endpoint, url, base };
14888
14909
  });
14889
- React79.useEffect(() => {
14910
+ React80.useEffect(() => {
14890
14911
  const controller = new AbortController();
14891
14912
  const { signal } = controller;
14892
14913
  setLoading(true);
@@ -14922,7 +14943,7 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "
14922
14943
  };
14923
14944
  }, [endpoint, queryKey, paramKey, depKey, paging, reloadToken]);
14924
14945
  const adapter = url ? url.adapter ?? historyUrlAdapter : null;
14925
- React79.useEffect(() => {
14946
+ React80.useEffect(() => {
14926
14947
  if (!adapter) return;
14927
14948
  return adapter.subscribe((params2) => {
14928
14949
  const { url: u, base: b } = latest.current;
@@ -15272,12 +15293,12 @@ function createVersionStore(initialState, options) {
15272
15293
  }
15273
15294
 
15274
15295
  // src/kits/documentTitle.ts
15275
- import * as React80 from "react";
15296
+ import * as React81 from "react";
15276
15297
  function formatDocumentTitle(routeTitle, appName) {
15277
15298
  return [routeTitle, appName, "Flytedesk"].filter((part2) => !!part2 && part2.length > 0).join(" \xB7 ");
15278
15299
  }
15279
15300
  function useDocumentTitle(routeTitle, appName) {
15280
- React80.useEffect(() => {
15301
+ React81.useEffect(() => {
15281
15302
  if (typeof document === "undefined") return;
15282
15303
  document.title = formatDocumentTitle(routeTitle, appName);
15283
15304
  }, [routeTitle, appName]);