@flytedan/flytebot-design-system 0.73.0 → 0.73.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.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 = () => {
@@ -3254,16 +3274,16 @@ function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort
3254
3274
  }
3255
3275
 
3256
3276
  // src/components/data/FilterBar.tsx
3257
- import * as React32 from "react";
3277
+ import * as React33 from "react";
3258
3278
 
3259
3279
  // src/components/forms/NumberInput.tsx
3260
- import * as React29 from "react";
3280
+ import * as React30 from "react";
3261
3281
 
3262
3282
  // src/components/forms/field.tsx
3263
- import * as React27 from "react";
3283
+ import * as React28 from "react";
3264
3284
  import { jsx as jsx46, jsxs as jsxs37 } from "react/jsx-runtime";
3265
3285
  function useFieldId(id) {
3266
- const generated = React27.useId();
3286
+ const generated = React28.useId();
3267
3287
  return id || generated;
3268
3288
  }
3269
3289
  function FieldLabel({ htmlFor, id, required = false, onClick, children }) {
@@ -3282,10 +3302,10 @@ function HiddenFieldLabel({ id, children }) {
3282
3302
  }
3283
3303
 
3284
3304
  // src/components/useLatest.ts
3285
- import * as React28 from "react";
3305
+ import * as React29 from "react";
3286
3306
  function useLatest(value) {
3287
- const ref = React28.useRef(value);
3288
- React28.useInsertionEffect(() => {
3307
+ const ref = React29.useRef(value);
3308
+ React29.useInsertionEffect(() => {
3289
3309
  ref.current = value;
3290
3310
  });
3291
3311
  return ref;
@@ -3368,20 +3388,20 @@ function NumberInput({
3368
3388
  const n = typeof v === "number" ? v : parseNumberText(v);
3369
3389
  return n == null || Number.isNaN(n) ? null : n;
3370
3390
  };
3371
- const [text, setText] = React29.useState(() => toText(value));
3372
- const [editing, setEditing] = React29.useState(false);
3391
+ const [text, setText] = React30.useState(() => toText(value));
3392
+ const [editing, setEditing] = React30.useState(false);
3373
3393
  const parsed = parseNumberText(text);
3374
3394
  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
3395
  const valid = invalidMessage == null;
3376
- const committedRef = React29.useRef(toNumber(value));
3396
+ const committedRef = React30.useRef(toNumber(value));
3377
3397
  const onChangeRef = useLatest(onChange);
3378
3398
  const onValidityChangeRef = useLatest(onValidityChange);
3379
- const focusedRef = React29.useRef(false);
3380
- React29.useEffect(() => {
3399
+ const focusedRef = React30.useRef(false);
3400
+ React30.useEffect(() => {
3381
3401
  committedRef.current = toNumber(value);
3382
3402
  if (!focusedRef.current) setText(toText(value));
3383
3403
  }, [value]);
3384
- React29.useLayoutEffect(() => {
3404
+ React30.useLayoutEffect(() => {
3385
3405
  onValidityChangeRef.current?.(valid);
3386
3406
  }, [valid, onValidityChangeRef]);
3387
3407
  const fire = (n) => {
@@ -3397,7 +3417,7 @@ function NumberInput({
3397
3417
  return true;
3398
3418
  };
3399
3419
  const bumpRef = useLatest(bump);
3400
- const holdTimer = React29.useRef(null);
3420
+ const holdTimer = React30.useRef(null);
3401
3421
  const release2 = () => {
3402
3422
  if (holdTimer.current) clearTimeout(holdTimer.current);
3403
3423
  holdTimer.current = null;
@@ -3416,7 +3436,7 @@ function NumberInput({
3416
3436
  };
3417
3437
  holdTimer.current = setTimeout(tick, HOLD_DELAY_MS);
3418
3438
  };
3419
- React29.useEffect(() => () => {
3439
+ React30.useEffect(() => () => {
3420
3440
  if (holdTimer.current) clearTimeout(holdTimer.current);
3421
3441
  }, []);
3422
3442
  const current2 = committedRef.current;
@@ -3519,7 +3539,7 @@ function NumberInput({
3519
3539
  }
3520
3540
 
3521
3541
  // src/components/forms/DatePicker.tsx
3522
- import * as React30 from "react";
3542
+ import * as React31 from "react";
3523
3543
  import { jsx as jsx48, jsxs as jsxs39 } from "react/jsx-runtime";
3524
3544
  var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
3525
3545
  var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
@@ -3552,10 +3572,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3552
3572
  const today = /* @__PURE__ */ new Date();
3553
3573
  const sel = range ? value || {} : { start: value, end: value };
3554
3574
  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);
3575
+ const [vy, setVy] = React31.useState(anchor.getFullYear());
3576
+ const [vm, setVm] = React31.useState(anchor.getMonth());
3577
+ const [mode2, setMode] = React31.useState("days");
3578
+ const [hover, setHover] = React31.useState(null);
3559
3579
  const s = parse(sel.start), e = parse(sel.end);
3560
3580
  const hoverEnd = range && s && !e && hover ? parse(hover) : null;
3561
3581
  const inRange = (d) => {
@@ -3566,12 +3586,12 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3566
3586
  const isEnd = (d) => !!e && iso(d) === iso(e);
3567
3587
  const isEdge = (d) => isStart(d) || isEnd(d);
3568
3588
  const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
3569
- const [activeDate, setActiveDate] = React30.useState(() => {
3589
+ const [activeDate, setActiveDate] = React31.useState(() => {
3570
3590
  if (s) return s;
3571
3591
  if (sameMonth(today, anchor.getFullYear(), anchor.getMonth())) return today;
3572
3592
  return new Date(anchor.getFullYear(), anchor.getMonth(), 1);
3573
3593
  });
3574
- const calRef = React30.useRef(null);
3594
+ const calRef = React31.useRef(null);
3575
3595
  const pageToShow = (y, m) => {
3576
3596
  const idx = y * 12 + m, firstIdx = vy * 12 + vm, secondIdx = firstIdx + 1;
3577
3597
  if (idx === firstIdx || months > 1 && idx === secondIdx) return;
@@ -3588,7 +3608,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3588
3608
  setActiveDate(next);
3589
3609
  pageToShow(next.getFullYear(), next.getMonth());
3590
3610
  };
3591
- React30.useEffect(() => {
3611
+ React31.useEffect(() => {
3592
3612
  const el = calRef.current?.querySelector('[data-iso="' + iso(activeDate) + '"]');
3593
3613
  if (el) el.focus({ preventScroll: true });
3594
3614
  }, [activeDate, vy, vm]);
@@ -3781,9 +3801,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3781
3801
  }
3782
3802
  function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, "aria-label": hiddenLabel, ...rest }) {
3783
3803
  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);
3804
+ const [open2, setOpen] = React31.useState(false);
3805
+ const rootRef = React31.useRef(null);
3806
+ const boxRef = React31.useRef(null);
3787
3807
  const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
3788
3808
  const toggle = () => {
3789
3809
  if (!disabled) setOpen(!open2);
@@ -3872,9 +3892,9 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
3872
3892
  }
3873
3893
 
3874
3894
  // src/components/forms/listbox.ts
3875
- import * as React31 from "react";
3895
+ import * as React32 from "react";
3876
3896
  function useListboxNav({ count, onSelect }) {
3877
- const [active, setActive] = React31.useState(-1);
3897
+ const [active, setActive] = React32.useState(-1);
3878
3898
  return {
3879
3899
  active,
3880
3900
  setActive,
@@ -3887,7 +3907,7 @@ function useListboxNav({ count, onSelect }) {
3887
3907
  };
3888
3908
  }
3889
3909
  function useListboxScrollIntoView(active, listRef, enabled) {
3890
- React31.useEffect(() => {
3910
+ React32.useEffect(() => {
3891
3911
  if (!enabled || active < 0 || !listRef.current) return;
3892
3912
  const list = listRef.current;
3893
3913
  const el = list.querySelector('[data-i="' + active + '"]');
@@ -4108,13 +4128,13 @@ function MultiSelectPanel({
4108
4128
  onClose
4109
4129
  }) {
4110
4130
  const allowedOps = operatorsFor(field);
4111
- const [draftOperator, setDraftOperator] = React32.useState(value?.operator ?? allowedOps[0]);
4131
+ const [draftOperator, setDraftOperator] = React33.useState(value?.operator ?? allowedOps[0]);
4112
4132
  const operator = allowedOps.length === 1 ? allowedOps[0] : value?.operator ?? draftOperator;
4113
4133
  const selected = value?.values ?? [];
4114
4134
  const selectedRef = useLatest(selected);
4115
4135
  const operatorRef = useLatest(operator);
4116
- const mountedRef = React32.useRef(true);
4117
- React32.useEffect(() => {
4136
+ const mountedRef = React33.useRef(true);
4137
+ React33.useEffect(() => {
4118
4138
  mountedRef.current = true;
4119
4139
  return () => {
4120
4140
  mountedRef.current = false;
@@ -4128,20 +4148,20 @@ function MultiSelectPanel({
4128
4148
  if (selectedRef.current.length > 0) commit(selectedRef.current, op);
4129
4149
  else setDraftOperator(op);
4130
4150
  };
4131
- const [mode2, setMode] = React32.useState("search");
4132
- const [query, setQuery] = React32.useState("");
4133
- const [asyncState, setAsyncState] = React32.useState(
4151
+ const [mode2, setMode] = React33.useState("search");
4152
+ const [query, setQuery] = React33.useState("");
4153
+ const [asyncState, setAsyncState] = React33.useState(
4134
4154
  { options: null, loading: !!field.loadOptions, error: false }
4135
4155
  );
4136
- const [retryTick, setRetryTick] = React32.useState(0);
4137
- const inputRef = React32.useRef(null);
4138
- const listRef = React32.useRef(null);
4139
- const listId = React32.useId();
4156
+ const [retryTick, setRetryTick] = React33.useState(0);
4157
+ const inputRef = React33.useRef(null);
4158
+ const listRef = React33.useRef(null);
4159
+ const listId = React33.useId();
4140
4160
  const loadOptionsRef = useLatest(field.loadOptions);
4141
- React32.useEffect(() => {
4161
+ React33.useEffect(() => {
4142
4162
  inputRef.current?.focus();
4143
4163
  }, []);
4144
- React32.useEffect(() => {
4164
+ React33.useEffect(() => {
4145
4165
  const load = loadOptionsRef.current;
4146
4166
  if (!load) return;
4147
4167
  const controller = new AbortController();
@@ -4174,17 +4194,17 @@ function MultiSelectPanel({
4174
4194
  };
4175
4195
  const nav = useListboxNav({ count: options.length, onSelect: (i) => toggle(options[i]) });
4176
4196
  useListboxScrollIntoView(nav.active, listRef, hasListbox);
4177
- React32.useEffect(() => {
4197
+ React33.useEffect(() => {
4178
4198
  nav.setActive(0);
4179
4199
  }, [query, options.length]);
4180
4200
  const activeId = hasListbox && options[nav.active] ? listId + "-opt-" + nav.active : void 0;
4181
4201
  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(() => {
4202
+ const [pasteText, setPasteText] = React33.useState("");
4203
+ const [pasteLoading, setPasteLoading] = React33.useState(false);
4204
+ const [unmatchedTokens, setUnmatchedTokens] = React33.useState([]);
4205
+ const [pasteError, setPasteError] = React33.useState(null);
4206
+ const pasteWrapRef = React33.useRef(null);
4207
+ React33.useEffect(() => {
4188
4208
  if (mode2 === "paste") pasteWrapRef.current?.querySelector("textarea")?.focus();
4189
4209
  }, [mode2]);
4190
4210
  const doResolve = () => {
@@ -4357,8 +4377,8 @@ function MultiSelectPanel({
4357
4377
  );
4358
4378
  }
4359
4379
  function useTextValidity(onFlip) {
4360
- const invalidRef = React32.useRef(/* @__PURE__ */ new Set());
4361
- const [, rerender] = React32.useReducer((n) => n + 1, 0);
4380
+ const invalidRef = React33.useRef(/* @__PURE__ */ new Set());
4381
+ const [, rerender] = React33.useReducer((n) => n + 1, 0);
4362
4382
  const onFlipRef = useLatest(onFlip);
4363
4383
  const record = (name, valid) => {
4364
4384
  const invalid = invalidRef.current;
@@ -4401,15 +4421,15 @@ function sameValue(a, b) {
4401
4421
  return true;
4402
4422
  }
4403
4423
  function useReseedFromProps(value, applies, reseed) {
4404
- const seen = React32.useRef(value);
4405
- React32.useLayoutEffect(() => {
4424
+ const seen = React33.useRef(value);
4425
+ React33.useLayoutEffect(() => {
4406
4426
  if (seen.current === value) return;
4407
4427
  seen.current = value;
4408
4428
  if (!sameValue(value, applies())) reseed(value);
4409
4429
  }, [value, applies, reseed]);
4410
4430
  }
4411
4431
  function usePreserveFocusAcrossRemount(seed, fields) {
4412
- const pendingName = React32.useRef(null);
4432
+ const pendingName = React33.useRef(null);
4413
4433
  const fieldsRef = useLatest(fields);
4414
4434
  const capture = () => {
4415
4435
  const active = document.activeElement;
@@ -4422,7 +4442,7 @@ function usePreserveFocusAcrossRemount(seed, fields) {
4422
4442
  }
4423
4443
  }
4424
4444
  };
4425
- React32.useLayoutEffect(() => {
4445
+ React33.useLayoutEffect(() => {
4426
4446
  const name = pendingName.current;
4427
4447
  if (!name) return;
4428
4448
  pendingName.current = null;
@@ -4438,14 +4458,14 @@ function RangePanel({
4438
4458
  onCommit,
4439
4459
  onClose
4440
4460
  }) {
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);
4461
+ const [draft, setDraft] = React33.useState(() => rangeDraft(value));
4462
+ const [seed, setSeed] = React33.useState(0);
4463
+ const minId = React33.useId();
4464
+ const maxId = React33.useId();
4465
+ const minWrapRef = React33.useRef(null);
4466
+ const maxWrapRef = React33.useRef(null);
4447
4467
  const preserveFocus = usePreserveFocusAcrossRemount(seed, { min: minWrapRef, max: maxWrapRef });
4448
- const draftRef = React32.useRef(draft);
4468
+ const draftRef = React33.useRef(draft);
4449
4469
  const shown = () => {
4450
4470
  const { min, max } = draftRef.current;
4451
4471
  return applicable(field, min == null && max == null ? void 0 : { min, max }, validity.allValid());
@@ -4537,15 +4557,15 @@ function DatePanel({
4537
4557
  onClose
4538
4558
  }) {
4539
4559
  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);
4560
+ const [initial] = React33.useState(() => dateDraft(field, value));
4561
+ const [kind, setKind] = React33.useState(initial.kind);
4562
+ const [daysDraft, setDaysDraft] = React33.useState(initial.days);
4563
+ const daysRef = React33.useRef(daysDraft);
4564
+ const daysConfirmed = React33.useRef(value?.kind === "withinDays");
4565
+ const [between, setBetween] = React33.useState(initial.between);
4566
+ const [seed, setSeed] = React33.useState(0);
4567
+ const daysId = React33.useId();
4568
+ const daysWrapRef = React33.useRef(null);
4549
4569
  const preserveFocus = usePreserveFocusAcrossRemount(seed, { days: daysWrapRef });
4550
4570
  const shownWithinDays = () => {
4551
4571
  const days = daysRef.current;
@@ -4663,11 +4683,11 @@ function FilterButton({ children, ...rest }) {
4663
4683
  ] });
4664
4684
  }
4665
4685
  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);
4686
+ const [panel, setPanel] = React33.useState(null);
4687
+ const editAnchorRef = React33.useRef(null);
4688
+ const addAnchorRef = React33.useRef(null);
4689
+ const textInputRef = React33.useRef(null);
4690
+ const optionsRef = React33.useRef(null);
4671
4691
  if (process.env.NODE_ENV !== "production") {
4672
4692
  for (const f of fields) assertValidFieldDefinition(f);
4673
4693
  }
@@ -4690,7 +4710,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
4690
4710
  const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
4691
4711
  const startEditing = (key) => setPanel({ kind: "edit", key });
4692
4712
  const closeEditing = () => setPanel(null);
4693
- React32.useEffect(() => {
4713
+ React33.useEffect(() => {
4694
4714
  if (!panel || panel.kind !== "edit") return;
4695
4715
  if (editingField?.type === "text") {
4696
4716
  textInputRef.current?.focus();
@@ -4945,10 +4965,10 @@ function StatTile(props) {
4945
4965
  }
4946
4966
 
4947
4967
  // src/components/data/CodeBlock.tsx
4948
- import * as React34 from "react";
4968
+ import * as React35 from "react";
4949
4969
 
4950
4970
  // src/kits/clipboard.ts
4951
- import * as React33 from "react";
4971
+ import * as React34 from "react";
4952
4972
  var COPIED_FEEDBACK_MS = 1600;
4953
4973
  function copyThroughSelection(text) {
4954
4974
  const previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
@@ -4978,17 +4998,17 @@ async function copyToClipboard(text) {
4978
4998
  return copyThroughSelection(text);
4979
4999
  }
4980
5000
  function useCopyToClipboard() {
4981
- const [copied, setCopied] = React33.useState(false);
4982
- const timer = React33.useRef(null);
4983
- const mounted = React33.useRef(true);
4984
- React33.useEffect(() => {
5001
+ const [copied, setCopied] = React34.useState(false);
5002
+ const timer = React34.useRef(null);
5003
+ const mounted = React34.useRef(true);
5004
+ React34.useEffect(() => {
4985
5005
  mounted.current = true;
4986
5006
  return () => {
4987
5007
  mounted.current = false;
4988
5008
  if (timer.current) clearTimeout(timer.current);
4989
5009
  };
4990
5010
  }, []);
4991
- const copy = React33.useCallback(async (text) => {
5011
+ const copy = React34.useCallback(async (text) => {
4992
5012
  const ok = await copyToClipboard(text);
4993
5013
  if (ok && mounted.current) {
4994
5014
  setCopied(true);
@@ -5156,7 +5176,7 @@ function tokenize(src, lang) {
5156
5176
  return out;
5157
5177
  }
5158
5178
  function Highlighted({ code, lang }) {
5159
- const toks = React34.useMemo(() => tokenize(code, lang), [code, lang]);
5179
+ const toks = React35.useMemo(() => tokenize(code, lang), [code, lang]);
5160
5180
  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
5181
  }
5162
5182
  function CodeBlock({
@@ -5170,8 +5190,8 @@ function CodeBlock({
5170
5190
  actions,
5171
5191
  className = ""
5172
5192
  }) {
5173
- const [wrap, setWrap] = React34.useState(!!wrapDefault);
5174
- const [open2, setOpen] = React34.useState(false);
5193
+ const [wrap, setWrap] = React35.useState(!!wrapDefault);
5194
+ const [open2, setOpen] = React35.useState(false);
5175
5195
  const [copied, copy] = useCopyToClipboard();
5176
5196
  const body = String(code).replace(/\n$/, "");
5177
5197
  const lines = body.split("\n");
@@ -5200,7 +5220,7 @@ function CodeBlock({
5200
5220
  ] });
5201
5221
  }
5202
5222
  function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
5203
- const [open2, setOpen] = React34.useState(false);
5223
+ const [open2, setOpen] = React35.useState(false);
5204
5224
  const [copied, copy] = useCopyToClipboard();
5205
5225
  const raw = String(diff).replace(/\n$/, "");
5206
5226
  const all = raw.split("\n").map((line) => {
@@ -5246,7 +5266,7 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
5246
5266
  }
5247
5267
 
5248
5268
  // src/components/data/Markdown.tsx
5249
- import * as React35 from "react";
5269
+ import * as React36 from "react";
5250
5270
  import { jsx as jsx55, jsxs as jsxs45 } from "react/jsx-runtime";
5251
5271
  var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
5252
5272
  var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
@@ -5289,7 +5309,7 @@ function hiddenInlineNodes(hidden, ctx, keyBase) {
5289
5309
  const href = safeHref(d(g(2)));
5290
5310
  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
5311
  } 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()));
5312
+ 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
5313
  } else if (kind === "strongem") out.push(/* @__PURE__ */ jsx55("strong", { children: /* @__PURE__ */ jsx55("em", { children: hiddenInlineNodes(g(1), ctx, key()) }) }, key()));
5294
5314
  else if (kind === "strong") out.push(/* @__PURE__ */ jsx55("strong", { children: hiddenInlineNodes(g(1) || g(2), ctx, key()) }, key()));
5295
5315
  else if (kind === "em") out.push(/* @__PURE__ */ jsx55("em", { children: hiddenInlineNodes(g(1) || g(2), ctx, key()) }, key()));
@@ -5476,7 +5496,7 @@ function Markdown({
5476
5496
  tone = "default"
5477
5497
  }) {
5478
5498
  const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
5479
- const blocks = React35.useMemo(() => parseBlocks(source), [source]);
5499
+ const blocks = React36.useMemo(() => parseBlocks(source), [source]);
5480
5500
  return /* @__PURE__ */ jsx55("div", { className: mdClass("fd-md", size, tone, className), children: renderBlocks(blocks, ctx, "b") });
5481
5501
  }
5482
5502
  function MarkdownInline({ source = "", className = "", onLinkClick, size, tone }) {
@@ -5587,7 +5607,7 @@ function Pagination({
5587
5607
  }
5588
5608
 
5589
5609
  // src/components/data/RelativeTime.tsx
5590
- import * as React36 from "react";
5610
+ import * as React37 from "react";
5591
5611
  import { jsxs as jsxs48 } from "react/jsx-runtime";
5592
5612
  var MIN = 6e4;
5593
5613
  var HOUR = 36e5;
@@ -5639,9 +5659,9 @@ function formatDuration(ms) {
5639
5659
  return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
5640
5660
  }
5641
5661
  function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
5642
- const [, force] = React36.useState(0);
5662
+ const [, force] = React37.useState(0);
5643
5663
  const t = value instanceof Date ? value.getTime() : Date.parse(value);
5644
- React36.useEffect(() => {
5664
+ React37.useEffect(() => {
5645
5665
  if (!refresh2 || !t || isNaN(t)) return;
5646
5666
  const abs = Math.abs(t - Date.now());
5647
5667
  if (abs > DAY) return;
@@ -5657,7 +5677,7 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
5657
5677
  }
5658
5678
 
5659
5679
  // src/components/data/ScoreMeter.tsx
5660
- import * as React37 from "react";
5680
+ import * as React38 from "react";
5661
5681
  import { jsx as jsx58, jsxs as jsxs49 } from "react/jsx-runtime";
5662
5682
  function ScoreMeter({
5663
5683
  score,
@@ -5672,10 +5692,10 @@ function ScoreMeter({
5672
5692
  breakdownWidth = 280,
5673
5693
  className = ""
5674
5694
  }) {
5675
- const [open2, setOpen] = React37.useState(false);
5676
- const ref = React37.useRef(null);
5695
+ const [open2, setOpen] = React38.useState(false);
5696
+ const ref = React38.useRef(null);
5677
5697
  const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
5678
- const body = /* @__PURE__ */ jsxs49(React37.Fragment, { children: [
5698
+ const body = /* @__PURE__ */ jsxs49(React38.Fragment, { children: [
5679
5699
  /* @__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
5700
  showScore ? /* @__PURE__ */ jsx58("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
5681
5701
  ] });
@@ -5694,7 +5714,7 @@ function ScoreMeter({
5694
5714
  }
5695
5715
  );
5696
5716
  }
5697
- return /* @__PURE__ */ jsxs49(React37.Fragment, { children: [
5717
+ return /* @__PURE__ */ jsxs49(React38.Fragment, { children: [
5698
5718
  /* @__PURE__ */ jsx58(
5699
5719
  "button",
5700
5720
  {
@@ -5725,11 +5745,11 @@ function ScoreMeter({
5725
5745
  }
5726
5746
 
5727
5747
  // src/components/actions/inlinePanel.tsx
5728
- import * as React38 from "react";
5748
+ import * as React39 from "react";
5729
5749
  import { jsx as jsx59 } from "react/jsx-runtime";
5730
5750
  function useInlinePanel() {
5731
- const [open2, setOpen] = React38.useState(false);
5732
- const ref = React38.useRef(null);
5751
+ const [open2, setOpen] = React39.useState(false);
5752
+ const ref = React39.useRef(null);
5733
5753
  return { open: open2, setOpen, ref };
5734
5754
  }
5735
5755
  function InlinePanelSurface({ panel, align = "right", ...popover }) {
@@ -5900,7 +5920,7 @@ function SortMenu({
5900
5920
  }
5901
5921
 
5902
5922
  // src/components/data/StepList.tsx
5903
- import * as React39 from "react";
5923
+ import * as React40 from "react";
5904
5924
  import { jsx as jsx61, jsxs as jsxs51 } from "react/jsx-runtime";
5905
5925
  var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
5906
5926
  function StepList({
@@ -5914,9 +5934,9 @@ function StepList({
5914
5934
  className = "",
5915
5935
  active = false
5916
5936
  }) {
5917
- const [openState, setOpenState] = React39.useState(defaultOpen);
5937
+ const [openState, setOpenState] = React40.useState(defaultOpen);
5918
5938
  const open2 = openProp == null ? openState : openProp;
5919
- const [expanded, setExpanded] = React39.useState({});
5939
+ const [expanded, setExpanded] = React40.useState({});
5920
5940
  if (!steps.length) return null;
5921
5941
  const running = steps.some((s) => s.status === "running");
5922
5942
  const failed = steps.filter((s) => s.status === "error").length;
@@ -5974,7 +5994,7 @@ function StepList({
5974
5994
  }
5975
5995
 
5976
5996
  // src/components/data/VirtualList.tsx
5977
- import * as React40 from "react";
5997
+ import * as React41 from "react";
5978
5998
  import { jsx as jsx62, jsxs as jsxs52 } from "react/jsx-runtime";
5979
5999
  var VIRTUAL_LIST_BUFFER_ROWS = 20;
5980
6000
  var VIRTUAL_LIST_ROW_GAP = 6;
@@ -6026,35 +6046,35 @@ function VirtualList({
6026
6046
  className = "",
6027
6047
  style
6028
6048
  }) {
6029
- const [scrollTop, setScrollTop] = React40.useState(0);
6030
- const loaded = React40.useMemo(
6049
+ const [scrollTop, setScrollTop] = React41.useState(0);
6050
+ const loaded = React41.useMemo(
6031
6051
  () => ({ firstItemIndex, count: items.length }),
6032
6052
  [firstItemIndex, items.length]
6033
6053
  );
6034
6054
  const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
6035
6055
  const bandKey = firstItemIndex + ":" + items.length;
6036
- const win = React40.useMemo(
6056
+ const win = React41.useMemo(
6037
6057
  () => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
6038
6058
  [scrollTop, height, itemHeight, total, loaded]
6039
6059
  );
6040
- const need = React40.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
6060
+ const need = React41.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
6041
6061
  const wantStart = need.start && hasMore?.start !== false;
6042
6062
  const wantEnd = need.end && hasMore?.end !== false;
6043
6063
  const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
6044
6064
  const askKey = bandKey + "@" + bucket2;
6045
- const asked = React40.useRef({ start: null, end: null });
6046
- React40.useEffect(() => {
6065
+ const asked = React41.useRef({ start: null, end: null });
6066
+ React41.useEffect(() => {
6047
6067
  if (loading || !wantStart || asked.current.start === askKey) return;
6048
6068
  asked.current.start = askKey;
6049
6069
  onNeedMore("start", win);
6050
6070
  }, [wantStart, loading, askKey, onNeedMore, win]);
6051
- React40.useEffect(() => {
6071
+ React41.useEffect(() => {
6052
6072
  if (loading || !wantEnd || asked.current.end === askKey) return;
6053
6073
  asked.current.end = askKey;
6054
6074
  onNeedMore("end", win);
6055
6075
  }, [wantEnd, loading, askKey, onNeedMore, win]);
6056
- const lastKeysRef = React40.useRef(null);
6057
- const newKeys = React40.useMemo(() => {
6076
+ const lastKeysRef = React41.useRef(null);
6077
+ const newKeys = React41.useMemo(() => {
6058
6078
  const prev = lastKeysRef.current;
6059
6079
  if (!prev) return /* @__PURE__ */ new Set();
6060
6080
  const fresh = /* @__PURE__ */ new Set();
@@ -6064,7 +6084,7 @@ function VirtualList({
6064
6084
  }
6065
6085
  return fresh;
6066
6086
  }, [items]);
6067
- React40.useEffect(() => {
6087
+ React41.useEffect(() => {
6068
6088
  lastKeysRef.current = new Set(items.map(keyOf));
6069
6089
  }, [items]);
6070
6090
  const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
@@ -6109,7 +6129,7 @@ function VirtualList({
6109
6129
  }
6110
6130
 
6111
6131
  // src/components/data/EntityRow.tsx
6112
- import * as React41 from "react";
6132
+ import * as React42 from "react";
6113
6133
  import { jsx as jsx63, jsxs as jsxs53 } from "react/jsx-runtime";
6114
6134
  var ENTITY_ROW_METRIC_WIDTH = 74;
6115
6135
  var METRIC_TONE_COLOR = {
@@ -6122,7 +6142,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
6122
6142
  const key = m.id || m.label || i;
6123
6143
  const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
6124
6144
  const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
6125
- const content = /* @__PURE__ */ jsxs53(React41.Fragment, { children: [
6145
+ const content = /* @__PURE__ */ jsxs53(React42.Fragment, { children: [
6126
6146
  m.icon ? /* @__PURE__ */ jsx63("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
6127
6147
  /* @__PURE__ */ jsx63("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
6128
6148
  /* @__PURE__ */ jsx63("span", { className: "fd-sr", children: " " + m.label })
@@ -6214,7 +6234,7 @@ function EntityRow({
6214
6234
  }
6215
6235
 
6216
6236
  // src/components/data/TransferList.tsx
6217
- import * as React42 from "react";
6237
+ import * as React43 from "react";
6218
6238
  import { createPortal as createPortal5 } from "react-dom";
6219
6239
 
6220
6240
  // src/components/forms/Input.tsx
@@ -6320,12 +6340,12 @@ function TransferList({
6320
6340
  listHeight = 440,
6321
6341
  className = ""
6322
6342
  }) {
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) => {
6343
+ const [drag, setDrag] = React43.useState(null);
6344
+ const [dragOverSide, setDragOverSide] = React43.useState(null);
6345
+ const dragRef = React43.useRef(null);
6346
+ const armedRef = React43.useRef(null);
6347
+ const sideRefs = React43.useRef({ left: null, right: null });
6348
+ const hitTestSide = React43.useCallback((x, y) => {
6329
6349
  for (const side of ["left", "right"]) {
6330
6350
  const el = sideRefs.current[side];
6331
6351
  if (!el) continue;
@@ -6334,7 +6354,7 @@ function TransferList({
6334
6354
  }
6335
6355
  return null;
6336
6356
  }, []);
6337
- const findItem = React42.useCallback(
6357
+ const findItem = React43.useCallback(
6338
6358
  (side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
6339
6359
  [left.items, right.items, keyOf]
6340
6360
  );
@@ -6356,7 +6376,7 @@ function TransferList({
6356
6376
  height: rect.height
6357
6377
  };
6358
6378
  };
6359
- React42.useEffect(() => {
6379
+ React43.useEffect(() => {
6360
6380
  const onMovePointer = (e) => {
6361
6381
  const armed = armedRef.current;
6362
6382
  if (!armed || e.pointerId !== armed.pointerId) return;
@@ -6409,7 +6429,7 @@ function TransferList({
6409
6429
  window.removeEventListener("pointercancel", endDrag);
6410
6430
  };
6411
6431
  }, [hitTestSide, findItem, onMove]);
6412
- React42.useEffect(() => {
6432
+ React43.useEffect(() => {
6413
6433
  if (!drag || typeof document === "undefined") return;
6414
6434
  const prev = document.body.style.userSelect;
6415
6435
  document.body.style.userSelect = "none";
@@ -6526,7 +6546,7 @@ function FactList({ facts = [], className = "", ...rest }) {
6526
6546
  }
6527
6547
 
6528
6548
  // src/components/data/USChoropleth.tsx
6529
- import * as React44 from "react";
6549
+ import * as React45 from "react";
6530
6550
 
6531
6551
  // src/components/data/usChoropleth/mapBox.ts
6532
6552
  var MAP_WIDTH = 975;
@@ -6591,11 +6611,11 @@ function buildChoroplethModel(values, topN, givenTotal) {
6591
6611
  }
6592
6612
 
6593
6613
  // src/components/data/usChoropleth/useUsStateShapes.ts
6594
- import * as React43 from "react";
6614
+ import * as React44 from "react";
6595
6615
  function useUsStateShapes() {
6596
- const [token, setToken] = React43.useState(0);
6597
- const [settled, setSettled] = React43.useState(null);
6598
- React43.useEffect(() => {
6616
+ const [token, setToken] = React44.useState(0);
6617
+ const [settled, setSettled] = React44.useState(null);
6618
+ React44.useEffect(() => {
6599
6619
  let current2 = true;
6600
6620
  import("./usStateShapes-JJARDNLL.js").then(({ STATE_SHAPES }) => {
6601
6621
  if (current2) setSettled({ token, state: { status: "ready", shapes: STATE_SHAPES } });
@@ -6637,7 +6657,7 @@ function nextCode(key, from) {
6637
6657
  }
6638
6658
  function StateMap({ shapes, model, figures, label, formatReadout }) {
6639
6659
  const tip = useTooltip();
6640
- const [stop, setStop] = React44.useState(US_STATE_CODES[0]);
6660
+ const [stop, setStop] = React45.useState(US_STATE_CODES[0]);
6641
6661
  const onKeyDown = (event) => {
6642
6662
  const from = event.target.getAttribute("data-state");
6643
6663
  const to = from && nextCode(event.key, from);
@@ -6685,8 +6705,8 @@ function StateTable({ model, valueLabel, formatValue }) {
6685
6705
  return /* @__PURE__ */ jsx68(Collapsible, { title: TABLE_TITLE, children: /* @__PURE__ */ jsx68(DataTable, { columns, rows: model.rows, rowKey: "code", compact: true }) });
6686
6706
  }
6687
6707
  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]);
6708
+ const model = React45.useMemo(() => buildChoroplethModel(values, topN ?? 0, total), [values, topN, total]);
6709
+ const figures = React45.useMemo(() => new Map(model.rows.map((row) => [row.code, row])), [model]);
6690
6710
  const { state, retry } = useUsStateShapes();
6691
6711
  return /* @__PURE__ */ jsxs57("div", { className: ["fd-uschoro", className].filter(Boolean).join(" "), children: [
6692
6712
  /* @__PURE__ */ jsxs57("div", { className: "fd-uschoro-layout", children: [
@@ -6721,11 +6741,11 @@ function USChoropleth({ values, label, valueLabel, formatValue, formatReadout, t
6721
6741
  }
6722
6742
 
6723
6743
  // src/components/forms/Checkbox.tsx
6724
- import * as React45 from "react";
6744
+ import * as React46 from "react";
6725
6745
  import { jsx as jsx69, jsxs as jsxs58 } from "react/jsx-runtime";
6726
6746
  function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
6727
- const ref = React45.useRef(null);
6728
- React45.useEffect(() => {
6747
+ const ref = React46.useRef(null);
6748
+ React46.useEffect(() => {
6729
6749
  if (ref.current) ref.current.indeterminate = indeterminate;
6730
6750
  }, [indeterminate]);
6731
6751
  return /* @__PURE__ */ jsxs58("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
@@ -6772,7 +6792,7 @@ function Switch({ label, description, className = "", ...rest }) {
6772
6792
  }
6773
6793
 
6774
6794
  // src/components/forms/Select.tsx
6775
- import * as React46 from "react";
6795
+ import * as React47 from "react";
6776
6796
  import { jsx as jsx72, jsxs as jsxs61 } from "react/jsx-runtime";
6777
6797
  var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
6778
6798
  function Select({
@@ -6800,12 +6820,12 @@ function Select({
6800
6820
  const isOn = (v) => multiple ? vals.includes(v) : v === value;
6801
6821
  const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
6802
6822
  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 });
6823
+ const [open2, setOpen] = React47.useState(false);
6824
+ const [q, setQ] = React47.useState("");
6825
+ const rootRef = React47.useRef(null);
6826
+ const boxRef = React47.useRef(null);
6827
+ const listRef = React47.useRef(null);
6828
+ const typeBuf = React47.useRef({ s: "", t: 0 });
6809
6829
  const selected = multiple ? null : opts.find((o) => o.value === value);
6810
6830
  const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
6811
6831
  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 +6961,7 @@ function Select({
6941
6961
  ),
6942
6962
  q ? /* @__PURE__ */ jsx72("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
6943
6963
  ] }) : void 0,
6944
- footer: multiple ? /* @__PURE__ */ jsxs61(React46.Fragment, { children: [
6964
+ footer: multiple ? /* @__PURE__ */ jsxs61(React47.Fragment, { children: [
6945
6965
  /* @__PURE__ */ jsx72(
6946
6966
  "button",
6947
6967
  {
@@ -6972,7 +6992,7 @@ function Select({
6972
6992
  'Nothing matches "',
6973
6993
  q,
6974
6994
  '".'
6975
- ] }) : groups.map((grp) => /* @__PURE__ */ jsxs61(React46.Fragment, { children: [
6995
+ ] }) : groups.map((grp) => /* @__PURE__ */ jsxs61(React47.Fragment, { children: [
6976
6996
  grp.g ? /* @__PURE__ */ jsx72("div", { className: "fd-pop-group", children: grp.g }) : null,
6977
6997
  grp.items.map(({ o, i }) => /* @__PURE__ */ jsxs61(
6978
6998
  "button",
@@ -7009,7 +7029,7 @@ function Select({
7009
7029
  }
7010
7030
 
7011
7031
  // src/components/forms/TimePicker.tsx
7012
- import * as React47 from "react";
7032
+ import * as React48 from "react";
7013
7033
  import { jsx as jsx73, jsxs as jsxs62 } from "react/jsx-runtime";
7014
7034
  var pad = (n) => String(n).padStart(2, "0");
7015
7035
  function ClockFace({ value = "09:00", onChange }) {
@@ -7018,9 +7038,9 @@ function ClockFace({ value = "09:00", onChange }) {
7018
7038
  if (isNaN(m)) m = 0;
7019
7039
  const pm = h24 >= 12;
7020
7040
  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);
7041
+ const [mode2, setMode] = React48.useState("h");
7042
+ const faceRef = React48.useRef(null);
7043
+ const dragging = React48.useRef(false);
7024
7044
  const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
7025
7045
  const R = 108, NR = 80;
7026
7046
  const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
@@ -7093,9 +7113,9 @@ function ClockFace({ value = "09:00", onChange }) {
7093
7113
  }
7094
7114
  function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
7095
7115
  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);
7116
+ const [open2, setOpen] = React48.useState(false);
7117
+ const rootRef = React48.useRef(null);
7118
+ const boxRef = React48.useRef(null);
7099
7119
  const disp = () => {
7100
7120
  if (!value) return "";
7101
7121
  const [h, m] = value.split(":").map(Number);
@@ -7138,7 +7158,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
7138
7158
  offset: 6,
7139
7159
  width: 262,
7140
7160
  role: "presentation",
7141
- footer: /* @__PURE__ */ jsxs62(React47.Fragment, { children: [
7161
+ footer: /* @__PURE__ */ jsxs62(React48.Fragment, { children: [
7142
7162
  /* @__PURE__ */ jsx73(
7143
7163
  "button",
7144
7164
  {
@@ -7166,7 +7186,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
7166
7186
  }
7167
7187
 
7168
7188
  // src/components/forms/Slider.tsx
7169
- import * as React48 from "react";
7189
+ import * as React49 from "react";
7170
7190
  import { jsx as jsx74, jsxs as jsxs63 } from "react/jsx-runtime";
7171
7191
  function Slider({
7172
7192
  label,
@@ -7184,7 +7204,7 @@ function Slider({
7184
7204
  ...rest
7185
7205
  }) {
7186
7206
  const fieldId = useFieldId(id);
7187
- const [dragging, setDragging] = React48.useState(false);
7207
+ const [dragging, setDragging] = React49.useState(false);
7188
7208
  const v = value === void 0 ? min : Number(value);
7189
7209
  const pct = max === min ? 0 : (v - min) / (max - min) * 100;
7190
7210
  return /* @__PURE__ */ jsxs63("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
@@ -7218,7 +7238,7 @@ function Slider({
7218
7238
  }
7219
7239
 
7220
7240
  // src/components/forms/RangeSlider.tsx
7221
- import * as React49 from "react";
7241
+ import * as React50 from "react";
7222
7242
  import { jsx as jsx75, jsxs as jsxs64 } from "react/jsx-runtime";
7223
7243
  function RangeSlider({
7224
7244
  label,
@@ -7238,9 +7258,9 @@ function RangeSlider({
7238
7258
  }) {
7239
7259
  const fmt2 = format || ((v) => String(v));
7240
7260
  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);
7261
+ const [drag, setDrag] = React50.useState(null);
7262
+ const [focus, setFocus] = React50.useState(null);
7263
+ const railRef = React50.useRef(null);
7244
7264
  const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
7245
7265
  const clampPair = (i, v) => {
7246
7266
  v = Math.min(max, Math.max(min, Math.round(v / step) * step));
@@ -7255,7 +7275,7 @@ function RangeSlider({
7255
7275
  const r = railRef.current.getBoundingClientRect();
7256
7276
  return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
7257
7277
  };
7258
- React49.useEffect(() => {
7278
+ React50.useEffect(() => {
7259
7279
  if (drag === null) return;
7260
7280
  const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
7261
7281
  const upH = () => setDrag(null);
@@ -7336,7 +7356,7 @@ function RangeSlider({
7336
7356
  /* @__PURE__ */ jsxs64("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
7337
7357
  /* @__PURE__ */ jsx75("span", { className: "fd-range-rail", ref: railRef }),
7338
7358
  /* @__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: [
7359
+ marks.map((m) => /* @__PURE__ */ jsxs64(React50.Fragment, { children: [
7340
7360
  /* @__PURE__ */ jsx75("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
7341
7361
  m.label ? /* @__PURE__ */ jsx75("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
7342
7362
  ] }, m.value)),
@@ -7365,7 +7385,7 @@ function RangeSlider({
7365
7385
  }
7366
7386
 
7367
7387
  // src/components/forms/Dropzone.tsx
7368
- import * as React50 from "react";
7388
+ import * as React51 from "react";
7369
7389
  import { jsx as jsx76, jsxs as jsxs65 } from "react/jsx-runtime";
7370
7390
  function Dropzone({
7371
7391
  onFiles,
@@ -7380,8 +7400,8 @@ function Dropzone({
7380
7400
  className = "",
7381
7401
  style
7382
7402
  }) {
7383
- const [over, setOver] = React50.useState(false);
7384
- const depth = React50.useRef(0);
7403
+ const [over, setOver] = React51.useState(false);
7404
+ const depth = React51.useRef(0);
7385
7405
  const has = (e) => {
7386
7406
  const dt = e.dataTransfer;
7387
7407
  if (!dt) return false;
@@ -7443,8 +7463,8 @@ function FilePickButton({
7443
7463
  className = "",
7444
7464
  children
7445
7465
  }) {
7446
- const ref = React50.useRef(null);
7447
- return /* @__PURE__ */ jsxs65(React50.Fragment, { children: [
7466
+ const ref = React51.useRef(null);
7467
+ return /* @__PURE__ */ jsxs65(React51.Fragment, { children: [
7448
7468
  /* @__PURE__ */ jsx76(
7449
7469
  "button",
7450
7470
  {
@@ -7477,10 +7497,10 @@ function FilePickButton({
7477
7497
  }
7478
7498
  function useStagedFiles(upload, opts) {
7479
7499
  const o = opts || {};
7480
- const [items, setItems] = React50.useState([]);
7481
- const controllers = React50.useRef({});
7500
+ const [items, setItems] = React51.useState([]);
7501
+ const controllers = React51.useRef({});
7482
7502
  const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
7483
- const run = React50.useCallback((att) => {
7503
+ const run = React51.useCallback((att) => {
7484
7504
  if (!upload) return;
7485
7505
  const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
7486
7506
  controllers.current[att.id] = ac;
@@ -7497,14 +7517,14 @@ function useStagedFiles(upload, opts) {
7497
7517
  delete controllers.current[att.id];
7498
7518
  });
7499
7519
  }, [upload]);
7500
- const add = React50.useCallback((files) => {
7520
+ const add = React51.useCallback((files) => {
7501
7521
  if (!upload) return [];
7502
7522
  const atts = Array.from(files).map((f) => toAttachment(f));
7503
7523
  setItems((list) => list.concat(atts));
7504
7524
  atts.forEach(run);
7505
7525
  return atts;
7506
7526
  }, [upload, run]);
7507
- const remove = React50.useCallback((att) => {
7527
+ const remove = React51.useCallback((att) => {
7508
7528
  const ac = controllers.current[att.id];
7509
7529
  if (ac) {
7510
7530
  try {
@@ -7515,10 +7535,10 @@ function useStagedFiles(upload, opts) {
7515
7535
  }
7516
7536
  setItems((list) => list.filter((f) => f.id !== att.id));
7517
7537
  }, []);
7518
- const retry = React50.useCallback((att) => {
7538
+ const retry = React51.useCallback((att) => {
7519
7539
  run(att);
7520
7540
  }, [run]);
7521
- const clear = React50.useCallback(() => {
7541
+ const clear = React51.useCallback(() => {
7522
7542
  Object.values(controllers.current).forEach((ac) => {
7523
7543
  try {
7524
7544
  ac && ac.abort();
@@ -7642,7 +7662,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
7642
7662
  }
7643
7663
 
7644
7664
  // src/components/forms/MarkdownEditor.tsx
7645
- import * as React51 from "react";
7665
+ import * as React52 from "react";
7646
7666
  import { jsx as jsx78, jsxs as jsxs67 } from "react/jsx-runtime";
7647
7667
  var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
7648
7668
  var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
@@ -7856,7 +7876,7 @@ function syncDom(root, value) {
7856
7876
  while (root.children.length > lines.length) root.removeChild(root.lastChild);
7857
7877
  }
7858
7878
  var LIST_CONT = RE_LI;
7859
- var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
7879
+ var MarkdownEditor = React52.forwardRef(function MarkdownEditor2({
7860
7880
  value = "",
7861
7881
  onChange,
7862
7882
  onSubmit,
@@ -7875,10 +7895,10 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
7875
7895
  className = "",
7876
7896
  id
7877
7897
  }, ref) {
7878
- const boxRef = React51.useRef(null);
7879
- const composing = React51.useRef(false);
7880
- const pendingCaret = React51.useRef(null);
7881
- React51.useLayoutEffect(() => {
7898
+ const boxRef = React52.useRef(null);
7899
+ const composing = React52.useRef(false);
7900
+ const pendingCaret = React52.useRef(null);
7901
+ React52.useLayoutEffect(() => {
7882
7902
  const root = boxRef.current;
7883
7903
  if (!root || composing.current) return;
7884
7904
  const active = document.activeElement === root || root.contains(document.activeElement);
@@ -7887,7 +7907,7 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
7887
7907
  pendingCaret.current = null;
7888
7908
  if (active && caret != null) placeCaret(root, caret);
7889
7909
  }, [value]);
7890
- React51.useEffect(() => {
7910
+ React52.useEffect(() => {
7891
7911
  if (autoFocus && boxRef.current) boxRef.current.focus();
7892
7912
  }, [autoFocus]);
7893
7913
  const caretNow = () => {
@@ -7954,8 +7974,8 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
7954
7974
  api.replaceRange(from, to, next, from + next.length);
7955
7975
  }
7956
7976
  };
7957
- React51.useImperativeHandle(ref, () => api);
7958
- const caretAtKeydown = React51.useRef(-1);
7977
+ React52.useImperativeHandle(ref, () => api);
7978
+ const caretAtKeydown = React52.useRef(-1);
7959
7979
  function detect(text, caret) {
7960
7980
  if (!onTrigger) return;
7961
7981
  const upto = text.slice(0, caret);
@@ -8108,7 +8128,7 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
8108
8128
  });
8109
8129
 
8110
8130
  // src/components/forms/CodeEditor.tsx
8111
- import * as React52 from "react";
8131
+ import * as React53 from "react";
8112
8132
  import { EditorView, keymap, lineNumbers, placeholder as cmPlaceholder, drawSelection, Decoration } from "@codemirror/view";
8113
8133
  import { EditorState, StateEffect, StateField, Compartment } from "@codemirror/state";
8114
8134
  import { defaultKeymap, history, historyKeymap, indentMore, indentLess } from "@codemirror/commands";
@@ -8212,16 +8232,16 @@ function CodeEditor({
8212
8232
  const fieldId = useFieldId(id);
8213
8233
  const descId = fieldId + "-desc";
8214
8234
  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);
8235
+ const hostRef = React53.useRef(null);
8236
+ const viewRef = React53.useRef(null);
8237
+ const valueRef = React53.useRef(value);
8238
+ const onChangeRef = React53.useRef(onChange);
8219
8239
  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);
8240
+ const editableCompartment = React53.useRef(new Compartment()).current;
8241
+ const attributesCompartment = React53.useRef(new Compartment()).current;
8242
+ const errorRef = React53.useRef(error);
8223
8243
  errorRef.current = error;
8224
- const diagnosticsCountRef = React52.useRef(diagnostics.length);
8244
+ const diagnosticsCountRef = React53.useRef(diagnostics.length);
8225
8245
  diagnosticsCountRef.current = diagnostics.length;
8226
8246
  function contentAttributes() {
8227
8247
  return {
@@ -8231,7 +8251,7 @@ function CodeEditor({
8231
8251
  ...label ? { "aria-label": label } : {}
8232
8252
  };
8233
8253
  }
8234
- React52.useEffect(() => {
8254
+ React53.useEffect(() => {
8235
8255
  const host2 = hostRef.current;
8236
8256
  if (!host2) return;
8237
8257
  const updateListener = EditorView.updateListener.of((update) => {
@@ -8273,7 +8293,7 @@ function CodeEditor({
8273
8293
  viewRef.current = null;
8274
8294
  };
8275
8295
  }, []);
8276
- React52.useEffect(() => {
8296
+ React53.useEffect(() => {
8277
8297
  const view = viewRef.current;
8278
8298
  if (!view) return;
8279
8299
  const current2 = view.state.doc.toString();
@@ -8282,12 +8302,12 @@ function CodeEditor({
8282
8302
  }
8283
8303
  valueRef.current = value;
8284
8304
  }, [value]);
8285
- React52.useEffect(() => {
8305
+ React53.useEffect(() => {
8286
8306
  const view = viewRef.current;
8287
8307
  if (!view) return;
8288
8308
  view.dispatch({ effects: editableCompartment.reconfigure(EditorView.editable.of(!disabled)) });
8289
8309
  }, [disabled, editableCompartment]);
8290
- React52.useEffect(() => {
8310
+ React53.useEffect(() => {
8291
8311
  const view = viewRef.current;
8292
8312
  if (!view) return;
8293
8313
  view.dispatch({
@@ -8345,11 +8365,11 @@ function CodeEditor({
8345
8365
  }
8346
8366
 
8347
8367
  // src/components/forms/RadioGroup.tsx
8348
- import * as React53 from "react";
8368
+ import * as React54 from "react";
8349
8369
  import { jsx as jsx80, jsxs as jsxs69 } from "react/jsx-runtime";
8350
8370
  function RadioGroup({ label, labelledBy, options, value, onChange, card = false, disabled = false, name, className = "" }) {
8351
- const autoName = React53.useId();
8352
- const labelId = React53.useId();
8371
+ const autoName = React54.useId();
8372
+ const labelId = React54.useId();
8353
8373
  return /* @__PURE__ */ jsxs69("div", { role: "radiogroup", "aria-labelledby": labelledBy ?? labelId, "aria-disabled": disabled || void 0, className: ["fd-radiogroup", className].filter(Boolean).join(" "), children: [
8354
8374
  labelledBy === void 0 && /* @__PURE__ */ jsx80("span", { id: labelId, className: "fd-radiogroup-label", children: label }),
8355
8375
  options.map((o) => /* @__PURE__ */ jsx80(
@@ -8377,16 +8397,16 @@ function Fieldset({ busy = false, className = "", ...rest }) {
8377
8397
  }
8378
8398
 
8379
8399
  // src/components/platform/AccountMenu.tsx
8380
- import * as React55 from "react";
8400
+ import * as React56 from "react";
8381
8401
 
8382
8402
  // src/kits/sessionContext.tsx
8383
- import * as React54 from "react";
8384
- var SessionContext = React54.createContext(null);
8403
+ import * as React55 from "react";
8404
+ var SessionContext = React55.createContext(null);
8385
8405
  function SessionProvider({ value, children }) {
8386
- return React54.createElement(SessionContext.Provider, { value }, children);
8406
+ return React55.createElement(SessionContext.Provider, { value }, children);
8387
8407
  }
8388
8408
  function useSessionContext() {
8389
- const ctx = React54.useContext(SessionContext);
8409
+ const ctx = React55.useContext(SessionContext);
8390
8410
  if (!ctx) {
8391
8411
  throw new Error(
8392
8412
  "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 +8446,11 @@ function AccountMenu({
8426
8446
  ...rest
8427
8447
  }) {
8428
8448
  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);
8449
+ const [open2, setOpen] = React56.useState(false);
8450
+ const [switching, setSwitching] = React56.useState(false);
8451
+ const [signingOut, setSigningOut] = React56.useState(false);
8452
+ const [signOutError, setSignOutError] = React56.useState(null);
8453
+ const ref = React56.useRef(null);
8434
8454
  const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
8435
8455
  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
8456
  const closeMenu = () => {
@@ -8555,13 +8575,13 @@ function AccountMenu({
8555
8575
  }
8556
8576
 
8557
8577
  // src/components/platform/AppSwitcher.tsx
8558
- import * as React56 from "react";
8578
+ import * as React57 from "react";
8559
8579
  import { jsx as jsx83, jsxs as jsxs71 } from "react/jsx-runtime";
8560
8580
  function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
8561
8581
  const { apps: contextApps } = useSessionContext();
8562
8582
  const apps = appsProp ?? contextApps ?? [];
8563
- const [open2, setOpen] = React56.useState(false);
8564
- const anchorRef = React56.useRef(null);
8583
+ const [open2, setOpen] = React57.useState(false);
8584
+ const anchorRef = React57.useRef(null);
8565
8585
  if (!apps.length) return null;
8566
8586
  const items = apps.map((app) => ({
8567
8587
  id: app.key,
@@ -8575,7 +8595,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
8575
8595
  window.location.href = app.url;
8576
8596
  }
8577
8597
  }));
8578
- return /* @__PURE__ */ jsxs71(React56.Fragment, { children: [
8598
+ return /* @__PURE__ */ jsxs71(React57.Fragment, { children: [
8579
8599
  /* @__PURE__ */ jsx83("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx83(
8580
8600
  IconButton,
8581
8601
  {
@@ -8604,10 +8624,10 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
8604
8624
  }
8605
8625
 
8606
8626
  // src/components/platform/AppearanceMenu.tsx
8607
- import * as React59 from "react";
8627
+ import * as React60 from "react";
8608
8628
 
8609
8629
  // src/kits/appearance.ts
8610
- import * as React57 from "react";
8630
+ import * as React58 from "react";
8611
8631
  var DEFAULT_STORAGE_KEY = "fd-appearance";
8612
8632
  var DEFAULT_PREFS = {
8613
8633
  theme: "system",
@@ -8719,8 +8739,8 @@ function watchAppearance(store, root = document.documentElement) {
8719
8739
  };
8720
8740
  }
8721
8741
  function useAppearancePrefs(store) {
8722
- const prefs = React57.useSyncExternalStore(store.subscribe, store.getSnapshot);
8723
- const update = React57.useCallback(
8742
+ const prefs = React58.useSyncExternalStore(store.subscribe, store.getSnapshot);
8743
+ const update = React58.useCallback(
8724
8744
  (patch) => {
8725
8745
  store.write({ ...store.getSnapshot(), ...patch });
8726
8746
  },
@@ -8730,15 +8750,15 @@ function useAppearancePrefs(store) {
8730
8750
  }
8731
8751
 
8732
8752
  // src/components/platform/AppearanceProvider.tsx
8733
- import * as React58 from "react";
8753
+ import * as React59 from "react";
8734
8754
  import { jsx as jsx84 } from "react/jsx-runtime";
8735
- var AppearanceStoreContext = React58.createContext(null);
8755
+ var AppearanceStoreContext = React59.createContext(null);
8736
8756
  function AppearanceProvider({ store, children }) {
8737
- React58.useLayoutEffect(() => watchAppearance(store), [store]);
8757
+ React59.useLayoutEffect(() => watchAppearance(store), [store]);
8738
8758
  return /* @__PURE__ */ jsx84(AppearanceStoreContext.Provider, { value: store, children });
8739
8759
  }
8740
8760
  function useAppearanceStore() {
8741
- const store = React58.useContext(AppearanceStoreContext);
8761
+ const store = React59.useContext(AppearanceStoreContext);
8742
8762
  if (!store) throw new Error("AppearanceMenu and useAppearanceStore must be rendered inside an <AppearanceProvider>.");
8743
8763
  return store;
8744
8764
  }
@@ -8758,10 +8778,10 @@ var TEXT_SCALE_OPTIONS = [
8758
8778
  ];
8759
8779
  function AppearanceMenu({ className = "" }) {
8760
8780
  const [prefs, update] = useAppearancePrefs(useAppearanceStore());
8761
- const [open2, setOpen] = React59.useState(false);
8762
- const anchorRef = React59.useRef(null);
8781
+ const [open2, setOpen] = React60.useState(false);
8782
+ const anchorRef = React60.useRef(null);
8763
8783
  const patch = (p) => update(p);
8764
- return /* @__PURE__ */ jsxs72(React59.Fragment, { children: [
8784
+ return /* @__PURE__ */ jsxs72(React60.Fragment, { children: [
8765
8785
  /* @__PURE__ */ jsx85("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx85(
8766
8786
  IconButton,
8767
8787
  {
@@ -8830,14 +8850,14 @@ function AppearanceMenu({ className = "" }) {
8830
8850
  }
8831
8851
 
8832
8852
  // src/components/platform/ApiSpecBrowser.tsx
8833
- import * as React60 from "react";
8853
+ import * as React61 from "react";
8834
8854
  import { jsx as jsx86, jsxs as jsxs73 } from "react/jsx-runtime";
8835
8855
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
8836
8856
  function Json({ obj }) {
8837
8857
  return /* @__PURE__ */ jsx86("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
8838
8858
  }
8839
8859
  function Endpoint({ s, onRequest }) {
8840
- const [tried, setTried] = React60.useState(null);
8860
+ const [tried, setTried] = React61.useState(null);
8841
8861
  const run = async () => {
8842
8862
  setTried("busy");
8843
8863
  const t0 = (window.performance || Date).now();
@@ -8910,10 +8930,10 @@ function ApiSpecBrowser({
8910
8930
  className = "",
8911
8931
  ...rest
8912
8932
  }) {
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);
8933
+ const [q, setQ] = React61.useState("");
8934
+ const [method, setMethod] = React61.useState(null);
8935
+ const [mod, setMod] = React61.useState(null);
8936
+ const [listOnly, setListOnly] = React61.useState(false);
8917
8937
  const activeModule = modules && modules.find((m) => m.id === mod);
8918
8938
  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
8939
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
@@ -8992,7 +9012,7 @@ function ApiSpecBrowser({
8992
9012
  }
8993
9013
 
8994
9014
  // src/components/platform/ProfilePage.tsx
8995
- import * as React61 from "react";
9015
+ import * as React62 from "react";
8996
9016
  import { jsx as jsx87, jsxs as jsxs74 } from "react/jsx-runtime";
8997
9017
  function fieldInitialValue(field, user) {
8998
9018
  if (field.value) return field.value(user);
@@ -9028,21 +9048,21 @@ function ProfilePage({
9028
9048
  }) {
9029
9049
  const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
9030
9050
  const user = userProp || sessionUser;
9031
- const initialFieldValues = React61.useMemo(() => {
9051
+ const initialFieldValues = React62.useMemo(() => {
9032
9052
  const values2 = {};
9033
9053
  for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
9034
9054
  return values2;
9035
9055
  }, [user.id, fields]);
9036
- const initialNotify = React61.useMemo(() => {
9056
+ const initialNotify = React62.useMemo(() => {
9037
9057
  const values2 = {};
9038
9058
  for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
9039
9059
  return values2;
9040
9060
  }, [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);
9061
+ const [values, setValues] = React62.useState(initialFieldValues);
9062
+ const [notify, setNotify] = React62.useState(initialNotify);
9063
+ const [saving, setSaving] = React62.useState(false);
9064
+ const [saved, setSaved] = React62.useState(false);
9065
+ const [prevUserId, setPrevUserId] = React62.useState(user.id);
9046
9066
  if (user.id !== prevUserId) {
9047
9067
  setPrevUserId(user.id);
9048
9068
  setValues(initialFieldValues);
@@ -9230,7 +9250,7 @@ function ProfilePage({
9230
9250
  }
9231
9251
 
9232
9252
  // src/components/platform/SessionScreen.tsx
9233
- import * as React62 from "react";
9253
+ import * as React63 from "react";
9234
9254
  import { Fragment as Fragment22, jsx as jsx88, jsxs as jsxs75 } from "react/jsx-runtime";
9235
9255
  var COPY = {
9236
9256
  "signing-in": { busy: "Signing you in\u2026" },
@@ -9244,13 +9264,13 @@ function SessionScreen({ kind, error, onRetry, productName }) {
9244
9264
  const copy = COPY[kind];
9245
9265
  const busyMessage = "busy" in copy ? copy.busy : null;
9246
9266
  const failureTitle = "failure" in copy ? copy.failure : null;
9247
- const [announced, setAnnounced] = React62.useState("");
9248
- React62.useEffect(() => {
9267
+ const [announced, setAnnounced] = React63.useState("");
9268
+ React63.useEffect(() => {
9249
9269
  setAnnounced(busyMessage ?? "");
9250
9270
  }, [busyMessage]);
9251
- const titleRef = React62.useRef(null);
9271
+ const titleRef = React63.useRef(null);
9252
9272
  const failed = failureTitle !== null;
9253
- React62.useEffect(() => {
9273
+ React63.useEffect(() => {
9254
9274
  titleRef.current?.focus({ preventScroll: true });
9255
9275
  }, [failed]);
9256
9276
  return /* @__PURE__ */ jsx88("main", { className: "fd-session-screen", children: /* @__PURE__ */ jsxs75("div", { className: "fd-session-screen-inner", children: [
@@ -9273,10 +9293,10 @@ function SessionScreen({ kind, error, onRetry, productName }) {
9273
9293
  }
9274
9294
 
9275
9295
  // src/components/platform/RoadmapTimeline.tsx
9276
- import * as React65 from "react";
9296
+ import * as React66 from "react";
9277
9297
 
9278
9298
  // src/kits/session.ts
9279
- import * as React63 from "react";
9299
+ import * as React64 from "react";
9280
9300
  var PERMISSION_CATALOG = [
9281
9301
  { group: "Plans", items: [
9282
9302
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -10843,8 +10863,8 @@ function roadmap(overrides) {
10843
10863
  };
10844
10864
  }
10845
10865
  function useSession() {
10846
- const [s, setS] = React63.useState(getSession);
10847
- React63.useEffect(() => subscribe(setS), []);
10866
+ const [s, setS] = React64.useState(getSession);
10867
+ React64.useEffect(() => subscribe(setS), []);
10848
10868
  return s;
10849
10869
  }
10850
10870
  var SessionKit = {
@@ -10877,7 +10897,7 @@ var SessionKit = {
10877
10897
  };
10878
10898
  function DemoSessionProvider({ children }) {
10879
10899
  const session = useSession();
10880
- const value = React63.useMemo(
10900
+ const value = React64.useMemo(
10881
10901
  () => ({
10882
10902
  user: session.user,
10883
10903
  roles: session.roles,
@@ -10893,11 +10913,11 @@ function DemoSessionProvider({ children }) {
10893
10913
  }),
10894
10914
  [session]
10895
10915
  );
10896
- return React63.createElement(SessionProvider, { value }, children);
10916
+ return React64.createElement(SessionProvider, { value }, children);
10897
10917
  }
10898
10918
 
10899
10919
  // src/kits/runtime.ts
10900
- import * as React64 from "react";
10920
+ import * as React65 from "react";
10901
10921
  var WIRED_ENDPOINTS = [
10902
10922
  // Nothing yet. Every id below would come from a real service:
10903
10923
  // "plan.get", "placements.list", …
@@ -11068,8 +11088,8 @@ var RuntimeKit = {
11068
11088
  };
11069
11089
  RuntimeKit.declare(FEATURE_NEEDS);
11070
11090
  function useRuntimeMode() {
11071
- const [m, setM] = React64.useState(RuntimeKit.getMode());
11072
- React64.useEffect(() => RuntimeKit.subscribe(setM), []);
11091
+ const [m, setM] = React65.useState(RuntimeKit.getMode());
11092
+ React65.useEffect(() => RuntimeKit.subscribe(setM), []);
11073
11093
  return m;
11074
11094
  }
11075
11095
  function useFeatureStatus(key) {
@@ -11152,12 +11172,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
11152
11172
  }
11153
11173
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11154
11174
  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(() => {
11175
+ const [project, setProject] = React66.useState("");
11176
+ const [q, setQ] = React66.useState("");
11177
+ const scrollRef = React66.useRef(null);
11178
+ const nowRef = React66.useRef(null);
11179
+ const rm = React66.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
11180
+ const byKey = React66.useMemo(() => {
11161
11181
  const m = {};
11162
11182
  rm.items.forEach((i) => {
11163
11183
  m[i.key] = i;
@@ -11166,7 +11186,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11166
11186
  }, [rm]);
11167
11187
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
11168
11188
  const projects = [...new Set(rm.items.map((i) => i.project))];
11169
- React65.useEffect(() => {
11189
+ React66.useEffect(() => {
11170
11190
  let raf1 = 0, raf2 = 0;
11171
11191
  const place = () => {
11172
11192
  const box = scrollRef.current, mark = nowRef.current;
@@ -11240,7 +11260,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11240
11260
  lastPhase = item.phase;
11241
11261
  const inPhase = items.filter((i) => i.phase === item.phase).length;
11242
11262
  const isBoundary = n === firstPending;
11243
- return /* @__PURE__ */ jsxs76(React65.Fragment, { children: [
11263
+ return /* @__PURE__ */ jsxs76(React66.Fragment, { children: [
11244
11264
  showPhase ? /* @__PURE__ */ jsxs76("div", { className: "fd-rm-era", children: [
11245
11265
  /* @__PURE__ */ jsxs76("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
11246
11266
  /* @__PURE__ */ jsx89("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
@@ -11284,7 +11304,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11284
11304
  }
11285
11305
 
11286
11306
  // src/components/platform/ComingSoon.tsx
11287
- import * as React66 from "react";
11307
+ import * as React67 from "react";
11288
11308
  import { createPortal as createPortal6 } from "react-dom";
11289
11309
  import { Fragment as Fragment24, jsx as jsx90, jsxs as jsxs77 } from "react/jsx-runtime";
11290
11310
  var BYPASS_STORE = "fd.soon.bypass.v1";
@@ -11302,8 +11322,8 @@ function writeBypassed(list) {
11302
11322
  }
11303
11323
  }
11304
11324
  function useBypass(key) {
11305
- const [on, setOn] = React66.useState(() => !!key && readBypassed().indexOf(key) >= 0);
11306
- React66.useEffect(() => {
11325
+ const [on, setOn] = React67.useState(() => !!key && readBypassed().indexOf(key) >= 0);
11326
+ React67.useEffect(() => {
11307
11327
  setOn(!!key && readBypassed().indexOf(key) >= 0);
11308
11328
  }, [key]);
11309
11329
  const set = (next) => {
@@ -11350,9 +11370,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
11350
11370
  ] });
11351
11371
  }
11352
11372
  function useHoverCard(open2) {
11353
- const anchor = React66.useRef(null);
11354
- const [pos, setPos] = React66.useState(null);
11355
- React66.useLayoutEffect(() => {
11373
+ const anchor = React67.useRef(null);
11374
+ const [pos, setPos] = React67.useState(null);
11375
+ React67.useLayoutEffect(() => {
11356
11376
  if (!open2 || !anchor.current) {
11357
11377
  setPos(null);
11358
11378
  return;
@@ -11479,12 +11499,12 @@ function ComingSoon({
11479
11499
  ] });
11480
11500
  }
11481
11501
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
11482
- const [open2, setOpen] = React66.useState(false);
11502
+ const [open2, setOpen] = React67.useState(false);
11483
11503
  const [anchor, pos] = useHoverCard(open2);
11484
- const hoverCardRef = React66.useRef(null);
11504
+ const hoverCardRef = React67.useRef(null);
11485
11505
  const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
11486
11506
  const zIndex = useLayerZIndex(hoverLayer);
11487
- const close2 = React66.useRef(null);
11507
+ const close2 = React67.useRef(null);
11488
11508
  const show = () => {
11489
11509
  if (close2.current) {
11490
11510
  clearTimeout(close2.current);
@@ -11500,7 +11520,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
11500
11520
  setOpen(false);
11501
11521
  }, 140);
11502
11522
  };
11503
- React66.useEffect(() => () => {
11523
+ React67.useEffect(() => () => {
11504
11524
  if (close2.current) clearTimeout(close2.current);
11505
11525
  }, []);
11506
11526
  return /* @__PURE__ */ jsxs77(
@@ -11952,7 +11972,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11952
11972
  }
11953
11973
 
11954
11974
  // src/components/planner/MixGap.tsx
11955
- import * as React67 from "react";
11975
+ import * as React68 from "react";
11956
11976
  import { Fragment as Fragment26, jsx as jsx95, jsxs as jsxs82 } from "react/jsx-runtime";
11957
11977
  var MIX_GAP_LAYOUT = {
11958
11978
  trackHeight: 30,
@@ -11967,7 +11987,7 @@ function mixGapOffset(value, max) {
11967
11987
  }
11968
11988
  function MixGap({ rows = [], loading = false, className = "" }) {
11969
11989
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
11970
- const [hover, setHover] = React67.useState(null);
11990
+ const [hover, setHover] = React68.useState(null);
11971
11991
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
11972
11992
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
11973
11993
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
@@ -12110,7 +12130,7 @@ function ChannelContribution({
12110
12130
  }
12111
12131
 
12112
12132
  // src/components/planner/BudgetReallocator.tsx
12113
- import * as React68 from "react";
12133
+ import * as React69 from "react";
12114
12134
  import { Fragment as Fragment27, jsx as jsx97, jsxs as jsxs84 } from "react/jsx-runtime";
12115
12135
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
12116
12136
  function BudgetReallocator({
@@ -12126,8 +12146,8 @@ function BudgetReallocator({
12126
12146
  onCancel,
12127
12147
  className = ""
12128
12148
  }) {
12129
- const [draft, setDraft] = React68.useState(spend);
12130
- React68.useEffect(() => setDraft(spend), [spend]);
12149
+ const [draft, setDraft] = React69.useState(spend);
12150
+ React69.useEffect(() => setDraft(spend), [spend]);
12131
12151
  const dirty = draft !== spend;
12132
12152
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
12133
12153
  const nextBand = bandFor(nextCrp);
@@ -12142,10 +12162,10 @@ function BudgetReallocator({
12142
12162
  setDraft(spend);
12143
12163
  if (onCancel) onCancel();
12144
12164
  };
12145
- const trackRef = React68.useRef(null);
12146
- const chipRef = React68.useRef(null);
12147
- const [chipLeft, setChipLeft] = React68.useState(null);
12148
- React68.useLayoutEffect(() => {
12165
+ const trackRef = React69.useRef(null);
12166
+ const chipRef = React69.useRef(null);
12167
+ const [chipLeft, setChipLeft] = React69.useState(null);
12168
+ React69.useLayoutEffect(() => {
12149
12169
  const track = trackRef.current;
12150
12170
  if (!dirty || !track) {
12151
12171
  setChipLeft(null);
@@ -12333,7 +12353,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
12333
12353
  }
12334
12354
 
12335
12355
  // src/components/planner/PreferenceMeter.tsx
12336
- import * as React69 from "react";
12356
+ import * as React70 from "react";
12337
12357
  import { jsx as jsx100, jsxs as jsxs87 } from "react/jsx-runtime";
12338
12358
  function preferenceScore(criteria) {
12339
12359
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
@@ -12363,7 +12383,7 @@ function PreferenceMeter({
12363
12383
  className = ""
12364
12384
  }) {
12365
12385
  const value = score == null ? preferenceScore(criteria) : score;
12366
- const segments = React69.useMemo(() => preferenceSegments(criteria), [criteria]);
12386
+ const segments = React70.useMemo(() => preferenceSegments(criteria), [criteria]);
12367
12387
  return /* @__PURE__ */ jsx100(
12368
12388
  ScoreMeter,
12369
12389
  {
@@ -12402,13 +12422,13 @@ function PreferenceMeter({
12402
12422
  }
12403
12423
 
12404
12424
  // src/components/chat/AgentChatPanel.tsx
12405
- import * as React76 from "react";
12425
+ import * as React77 from "react";
12406
12426
 
12407
12427
  // src/components/chat/chatEngine.ts
12408
- import * as React71 from "react";
12428
+ import * as React72 from "react";
12409
12429
 
12410
12430
  // src/components/chat/chatStore.ts
12411
- import * as React70 from "react";
12431
+ import * as React71 from "react";
12412
12432
  var safeStore = {
12413
12433
  get(k) {
12414
12434
  try {
@@ -12437,13 +12457,13 @@ function useChatDraft(owner, contextType, contextId, store = safeStore) {
12437
12457
  if (owner === "") throw new Error("useChatDraft: draftOwner is an empty string; pass the signed-in user's id, or null for no owner.");
12438
12458
  const key = owner === null ? null : draftKey(owner, contextType, contextId);
12439
12459
  const read2 = (k) => k ? store.get(k) || "" : "";
12440
- const [state, setState] = React70.useState(() => ({ key, text: read2(key) }));
12460
+ const [state, setState] = React71.useState(() => ({ key, text: read2(key) }));
12441
12461
  let current2 = state;
12442
12462
  if (state.key !== key) {
12443
12463
  current2 = { key, text: read2(key) };
12444
12464
  setState(current2);
12445
12465
  }
12446
- const setText = React70.useCallback((text) => {
12466
+ const setText = React71.useCallback((text) => {
12447
12467
  if (key) {
12448
12468
  if (text) {
12449
12469
  store.set(key, text);
@@ -12502,33 +12522,33 @@ function useChatEngine(opts) {
12502
12522
  onClear,
12503
12523
  onFeedback
12504
12524
  } = 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(() => {
12525
+ const [status, setStatus] = React72.useState("idle");
12526
+ const [threadId, setThreadId] = React72.useState(null);
12527
+ const [messages, setMessages] = React72.useState([]);
12528
+ const [queue, setQueue] = React72.useState([]);
12529
+ const [fatal, setFatal] = React72.useState(null);
12530
+ const [busy, setBusy] = React72.useState(false);
12531
+ const [turnStartedAt, setTurnStartedAt] = React72.useState(null);
12532
+ const listRef = React72.useRef([]);
12533
+ const queueRef = React72.useRef([]);
12534
+ const busyRef = React72.useRef(false);
12535
+ const loadedRef = React72.useRef(false);
12536
+ const stoppedRef = React72.useRef(false);
12537
+ const abortRef = React72.useRef(null);
12538
+ const serverCount = React72.useRef(0);
12539
+ const serverIds = React72.useRef(/* @__PURE__ */ new Set());
12540
+ const liveTurn = React72.useRef(null);
12541
+ const lastTurnOwn = React72.useRef(/* @__PURE__ */ new Set());
12542
+ const retired = React72.useRef(/* @__PURE__ */ new Set());
12543
+ const threadRef = React72.useRef(null);
12544
+ const mounted = React72.useRef(true);
12545
+ React72.useEffect(() => {
12526
12546
  mounted.current = true;
12527
12547
  return () => {
12528
12548
  mounted.current = false;
12529
12549
  };
12530
12550
  }, []);
12531
- const describeWaitingRef = React71.useRef(describeWaiting);
12551
+ const describeWaitingRef = React72.useRef(describeWaiting);
12532
12552
  describeWaitingRef.current = describeWaiting;
12533
12553
  const commit = (next) => {
12534
12554
  const derived = withWaiting(next, (pending) => describeWaitingRef.current(pending));
@@ -12547,7 +12567,7 @@ function useChatEngine(opts) {
12547
12567
  }
12548
12568
  return false;
12549
12569
  };
12550
- const loadThread = React71.useCallback(async (id) => {
12570
+ const loadThread = React72.useCallback(async (id) => {
12551
12571
  const data = await apiAdapter.getThread(id);
12552
12572
  const list = [...data && data.messages || []];
12553
12573
  serverCount.current = list.length;
@@ -12587,7 +12607,7 @@ function useChatEngine(opts) {
12587
12607
  packet: progress.packet ?? holder.packet
12588
12608
  });
12589
12609
  }
12590
- React71.useEffect(() => {
12610
+ React72.useEffect(() => {
12591
12611
  if (!apiAdapter) {
12592
12612
  setStatus("idle");
12593
12613
  setFatal(null);
@@ -12819,7 +12839,7 @@ function useChatEngine(opts) {
12819
12839
  await dispatchTurn(turn);
12820
12840
  }
12821
12841
  }
12822
- const send = React71.useCallback((text, attachments) => {
12842
+ const send = React72.useCallback((text, attachments) => {
12823
12843
  const body = (text || "").trim();
12824
12844
  if (!body && !(attachments && attachments.length)) return;
12825
12845
  if (status === "disconnected") return;
@@ -12829,7 +12849,7 @@ function useChatEngine(opts) {
12829
12849
  stoppedRef.current = false;
12830
12850
  drain();
12831
12851
  }, [status]);
12832
- const stop = React71.useCallback(() => {
12852
+ const stop = React72.useCallback(() => {
12833
12853
  stoppedRef.current = true;
12834
12854
  const ac = abortRef.current;
12835
12855
  if (ac) {
@@ -12848,11 +12868,11 @@ function useChatEngine(opts) {
12848
12868
  store.del(jobKey(threadRef.current));
12849
12869
  }
12850
12870
  }, [apiAdapter]);
12851
- const removeQueued = React71.useCallback((id) => {
12871
+ const removeQueued = React72.useCallback((id) => {
12852
12872
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
12853
12873
  setQueue(queueRef.current.slice());
12854
12874
  }, []);
12855
- const retry = React71.useCallback(() => {
12875
+ const retry = React72.useCallback(() => {
12856
12876
  const list = listRef.current;
12857
12877
  let at = -1;
12858
12878
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -12869,19 +12889,19 @@ function useChatEngine(opts) {
12869
12889
  setQueue(queueRef.current.slice());
12870
12890
  drain();
12871
12891
  }, []);
12872
- const clear = React71.useCallback(() => {
12892
+ const clear = React72.useCallback(() => {
12873
12893
  commit([]);
12874
12894
  serverCount.current = 0;
12875
12895
  queueRef.current = [];
12876
12896
  setQueue([]);
12877
12897
  onClear && onClear();
12878
12898
  }, [onClear]);
12879
- const setFeedback = React71.useCallback((id, value) => {
12899
+ const setFeedback = React72.useCallback((id, value) => {
12880
12900
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
12881
12901
  const msg = listRef.current.find((m) => m.id === id);
12882
12902
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
12883
12903
  }, [onFeedback]);
12884
- const reload = React71.useCallback(async () => {
12904
+ const reload = React72.useCallback(async () => {
12885
12905
  if (!threadRef.current) return;
12886
12906
  setStatus("loading");
12887
12907
  try {
@@ -12919,10 +12939,10 @@ var ChatKit = {
12919
12939
  };
12920
12940
 
12921
12941
  // src/components/chat/ChatTranscript.tsx
12922
- import * as React73 from "react";
12942
+ import * as React74 from "react";
12923
12943
 
12924
12944
  // src/components/chat/ChatTurn.tsx
12925
- import * as React72 from "react";
12945
+ import * as React73 from "react";
12926
12946
  import { jsx as jsx101, jsxs as jsxs88 } from "react/jsx-runtime";
12927
12947
  function JsonView({ value }) {
12928
12948
  let text;
@@ -12959,7 +12979,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
12959
12979
  ] });
12960
12980
  }
12961
12981
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
12962
- const [open2, setOpen] = React72.useState(defaultOpen);
12982
+ const [open2, setOpen] = React73.useState(defaultOpen);
12963
12983
  if (!text) return null;
12964
12984
  return /* @__PURE__ */ jsxs88("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
12965
12985
  /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -12976,7 +12996,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
12976
12996
  ] });
12977
12997
  }
12978
12998
  function Citations({ items = [], onOpen }) {
12979
- const [open2, setOpen] = React72.useState(false);
12999
+ const [open2, setOpen] = React73.useState(false);
12980
13000
  if (!items.length) return null;
12981
13001
  return /* @__PURE__ */ jsxs88("div", { className: "fdc-cites", children: [
12982
13002
  /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -13002,7 +13022,7 @@ function clampText(text, max) {
13002
13022
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
13003
13023
  }
13004
13024
  function MessageBody({ message: m, ctx }) {
13005
- const [expanded, setExpanded] = React72.useState(false);
13025
+ const [expanded, setExpanded] = React73.useState(false);
13006
13026
  const isUser = m.role === "user";
13007
13027
  const raw = m.text || "";
13008
13028
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
@@ -13081,7 +13101,7 @@ function RunActions({ group, ctx }) {
13081
13101
  ] }),
13082
13102
  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
13103
  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: [
13104
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs88(React73.Fragment, { children: [
13085
13105
  /* @__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
13106
  /* @__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
13107
  ] }) : null,
@@ -13176,10 +13196,10 @@ function ChatTranscript({
13176
13196
  renderEmpty,
13177
13197
  className = ""
13178
13198
  }) {
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);
13199
+ const scroller = React74.useRef(null);
13200
+ const stick = React74.useRef(true);
13201
+ const [pill, setPill] = React74.useState(0);
13202
+ const seen = React74.useRef(0);
13183
13203
  const toBottom = (smooth) => {
13184
13204
  const el = scroller.current;
13185
13205
  if (!el) return;
@@ -13198,7 +13218,7 @@ function ChatTranscript({
13198
13218
  seen.current = messages.length;
13199
13219
  }
13200
13220
  };
13201
- React73.useLayoutEffect(() => {
13221
+ React74.useLayoutEffect(() => {
13202
13222
  const el = scroller.current;
13203
13223
  if (!el) return;
13204
13224
  if (stick.current) {
@@ -13206,7 +13226,7 @@ function ChatTranscript({
13206
13226
  seen.current = messages.length;
13207
13227
  } else setPill(Math.max(0, messages.length - seen.current));
13208
13228
  }, [messages]);
13209
- React73.useEffect(() => {
13229
+ React74.useEffect(() => {
13210
13230
  const el = scroller.current;
13211
13231
  const inner = el && el.firstChild;
13212
13232
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -13216,7 +13236,7 @@ function ChatTranscript({
13216
13236
  ro.observe(inner);
13217
13237
  return () => ro.disconnect();
13218
13238
  }, []);
13219
- const groups = React73.useMemo(() => groupMessages(messages), [messages]);
13239
+ const groups = React74.useMemo(() => groupMessages(messages), [messages]);
13220
13240
  const empty = !messages.length && status === "ready";
13221
13241
  return /* @__PURE__ */ jsxs89("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
13222
13242
  /* @__PURE__ */ jsxs89("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
@@ -13240,7 +13260,7 @@ function ChatTranscript({
13240
13260
  const prev = groups[i - 1];
13241
13261
  const k = dayKey(g.messages[0].timestamp);
13242
13262
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
13243
- return /* @__PURE__ */ jsxs89(React73.Fragment, { children: [
13263
+ return /* @__PURE__ */ jsxs89(React74.Fragment, { children: [
13244
13264
  showDay ? /* @__PURE__ */ jsx102("div", { className: "fdc-day", children: /* @__PURE__ */ jsx102("span", { children: dayLabel(k) }) }) : null,
13245
13265
  /* @__PURE__ */ jsx102(ChatTurn, { group: g, ctx })
13246
13266
  ] }, g.key || i);
@@ -13257,7 +13277,7 @@ function ChatTranscript({
13257
13277
  var TranscriptKit = { groupMessages };
13258
13278
 
13259
13279
  // src/components/chat/ChatComposer.tsx
13260
- import * as React74 from "react";
13280
+ import * as React75 from "react";
13261
13281
  import { jsx as jsx103, jsxs as jsxs90 } from "react/jsx-runtime";
13262
13282
  function ChatComposer({
13263
13283
  onSubmit,
@@ -13285,17 +13305,17 @@ function ChatComposer({
13285
13305
  onReject,
13286
13306
  onOpenAttachment
13287
13307
  }) {
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);
13308
+ const [text, setText] = React75.useState(draft || "");
13309
+ const [trigger, setTrigger] = React75.useState(null);
13310
+ const [mentionItems, setMentionItems] = React75.useState([]);
13311
+ const [listening, setListening] = React75.useState(false);
13312
+ const [notice, setNotice] = React75.useState(null);
13313
+ const editor = React75.useRef(null);
13314
+ const wrap = React75.useRef(null);
13315
+ const stopVoice = React75.useRef(null);
13296
13316
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
13297
13317
  } });
13298
- React74.useEffect(() => {
13318
+ React75.useEffect(() => {
13299
13319
  if (draft != null && draft !== text) setText(draft);
13300
13320
  }, [draft]);
13301
13321
  const change = (v) => {
@@ -13331,7 +13351,7 @@ function ChatComposer({
13331
13351
  e.preventDefault();
13332
13352
  staged.add(found.files);
13333
13353
  };
13334
- React74.useEffect(() => {
13354
+ React75.useEffect(() => {
13335
13355
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
13336
13356
  setMentionItems([]);
13337
13357
  return;
@@ -13349,7 +13369,7 @@ function ChatComposer({
13349
13369
  const q = (trigger.query || "").toLowerCase();
13350
13370
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
13351
13371
  }, [trigger, mentionSources]);
13352
- const slashItems = React74.useMemo(() => {
13372
+ const slashItems = React75.useMemo(() => {
13353
13373
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
13354
13374
  const q = (trigger.query || "").toLowerCase();
13355
13375
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -13519,12 +13539,12 @@ function ChatComposer({
13519
13539
  }
13520
13540
 
13521
13541
  // src/components/chat/ChatSessionBar.tsx
13522
- import * as React75 from "react";
13542
+ import * as React76 from "react";
13523
13543
  import { jsx as jsx104, jsxs as jsxs91 } from "react/jsx-runtime";
13524
13544
  var compact2 = meterFormats.compact;
13525
13545
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
13526
- const [open2, setOpen] = React75.useState(false);
13527
- const anchor = React75.useRef(null);
13546
+ const [open2, setOpen] = React76.useState(false);
13547
+ const anchor = React76.useRef(null);
13528
13548
  const stats = sessionStats || null;
13529
13549
  const cu = contextUsage || null;
13530
13550
  const limits = usageLimits || null;
@@ -13539,7 +13559,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
13539
13559
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
13540
13560
  if (cu) bits.push(pct + "% context");
13541
13561
  const expandable = !!(cu || limits);
13542
- return /* @__PURE__ */ jsxs91(React75.Fragment, { children: [
13562
+ return /* @__PURE__ */ jsxs91(React76.Fragment, { children: [
13543
13563
  /* @__PURE__ */ jsxs91("div", { className: "fdc-bar", children: [
13544
13564
  /* @__PURE__ */ jsxs91(
13545
13565
  "button",
@@ -13680,7 +13700,7 @@ function ModelControls({
13680
13700
  ] })
13681
13701
  });
13682
13702
  }
13683
- return /* @__PURE__ */ jsxs91(React75.Fragment, { children: [
13703
+ return /* @__PURE__ */ jsxs91(React76.Fragment, { children: [
13684
13704
  /* @__PURE__ */ jsx104(
13685
13705
  MenuButton,
13686
13706
  {
@@ -13800,11 +13820,11 @@ function AgentChatPanel({
13800
13820
  onFeedback,
13801
13821
  onEditMessage
13802
13822
  }) {
13803
- const [panelWidth, setPanelWidth] = React76.useState(width);
13804
- const [applied, setApplied] = React76.useState({});
13823
+ const [panelWidth, setPanelWidth] = React77.useState(width);
13824
+ const [applied, setApplied] = React77.useState({});
13805
13825
  const [draft, setDraft] = useChatDraft(draftOwner, contextType, contextId);
13806
- const dragging = React76.useRef(null);
13807
- React76.useEffect(() => setPanelWidth(width), [width]);
13826
+ const dragging = React77.useRef(null);
13827
+ React77.useEffect(() => setPanelWidth(width), [width]);
13808
13828
  const engine = useChatEngine({
13809
13829
  contextType,
13810
13830
  contextId,
@@ -14010,7 +14030,7 @@ function AgentChatPanel({
14010
14030
  }
14011
14031
 
14012
14032
  // src/components/files/FileViewer.tsx
14013
- import * as React77 from "react";
14033
+ import * as React78 from "react";
14014
14034
  import { jsx as jsx106, jsxs as jsxs93 } from "react/jsx-runtime";
14015
14035
  function previewKindOf(file) {
14016
14036
  const mime = (file.mime || "").toLowerCase();
@@ -14067,13 +14087,13 @@ function parseDelimited(text, delimiter) {
14067
14087
  return rows;
14068
14088
  }
14069
14089
  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(() => {
14090
+ const [state, setState] = React78.useState({ status: "loading" });
14091
+ const [attempt, setAttempt] = React78.useState(0);
14092
+ const resolveRef = React78.useRef(resolveUrl);
14093
+ React78.useEffect(() => {
14074
14094
  resolveRef.current = resolveUrl;
14075
14095
  }, [resolveUrl]);
14076
- React77.useEffect(() => {
14096
+ React78.useEffect(() => {
14077
14097
  if (kind === "none") {
14078
14098
  setState({ status: "ready" });
14079
14099
  return;
@@ -14103,7 +14123,7 @@ function usePreview(file, kind, resolveUrl) {
14103
14123
  if (ac) ac.abort();
14104
14124
  };
14105
14125
  }, [file.id, kind, attempt]);
14106
- return { ...state, retry: React77.useCallback(() => setAttempt((a) => a + 1), []) };
14126
+ return { ...state, retry: React78.useCallback(() => setAttempt((a) => a + 1), []) };
14107
14127
  }
14108
14128
  function PreviewBody({ file, kind, state }) {
14109
14129
  if (kind === "image") return /* @__PURE__ */ jsx106("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
@@ -14148,13 +14168,13 @@ function PreviewBody({ file, kind, state }) {
14148
14168
  ] });
14149
14169
  }
14150
14170
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
14151
- const kind = React77.useMemo(() => previewKindOf(file), [file]);
14171
+ const kind = React78.useMemo(() => previewKindOf(file), [file]);
14152
14172
  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);
14173
+ const [tab, setTab] = React78.useState("preview");
14174
+ const [downloading, setDownloading] = React78.useState(false);
14175
+ const [downloadError, setDownloadError] = React78.useState(null);
14156
14176
  const hasSide = sidePanel != null;
14157
- React77.useEffect(() => {
14177
+ React78.useEffect(() => {
14158
14178
  setTab("preview");
14159
14179
  }, [file.id]);
14160
14180
  const download = () => {
@@ -14221,7 +14241,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
14221
14241
  }
14222
14242
 
14223
14243
  // src/components/files/FileBrowser.tsx
14224
- import * as React78 from "react";
14244
+ import * as React79 from "react";
14225
14245
  import { Fragment as Fragment31, jsx as jsx107, jsxs as jsxs94 } from "react/jsx-runtime";
14226
14246
  function childrenOf(folders, parentId) {
14227
14247
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
@@ -14331,8 +14351,8 @@ function FolderPickerMenu({
14331
14351
  ] });
14332
14352
  }
14333
14353
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
14334
- const [over, setOver] = React78.useState(false);
14335
- const dragCounter = React78.useRef(0);
14354
+ const [over, setOver] = React79.useState(false);
14355
+ const dragCounter = React79.useRef(0);
14336
14356
  const dropHandlers = isDropTarget ? {
14337
14357
  onDragEnter: (e) => {
14338
14358
  if (!hasInternalPayload(e)) return;
@@ -14380,8 +14400,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
14380
14400
  }
14381
14401
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
14382
14402
  const kids = childrenOf(folders, folder.id);
14383
- const [expanded, setExpanded] = React78.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
14384
- React78.useEffect(() => {
14403
+ const [expanded, setExpanded] = React79.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
14404
+ React79.useEffect(() => {
14385
14405
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
14386
14406
  }, [currentFolderId, folder.id, folders]);
14387
14407
  const isCurrent = folder.id === currentFolderId;
@@ -14447,15 +14467,15 @@ function FileBrowser({
14447
14467
  const canUpload = perm.canUpload !== false && !!onUpload;
14448
14468
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
14449
14469
  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(
14470
+ const [createOpen, setCreateOpen] = React79.useState(false);
14471
+ const [createName, setCreateName] = React79.useState("");
14472
+ const [renameTarget, setRenameTarget] = React79.useState(null);
14473
+ const [renameValue, setRenameValue] = React79.useState("");
14474
+ const [deleteTarget, setDeleteTarget] = React79.useState(null);
14475
+ const uploadInputRef = React79.useRef(null);
14476
+ const crumbFolders = React79.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
14477
+ const subfolders = React79.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
14478
+ const currentFiles = React79.useMemo(
14459
14479
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
14460
14480
  [files, currentFolderId]
14461
14481
  );
@@ -14687,8 +14707,8 @@ function BreadcrumbCrumb({
14687
14707
  isDropTarget,
14688
14708
  onDropPayload
14689
14709
  }) {
14690
- const [over, setOver] = React78.useState(false);
14691
- const dragCounter = React78.useRef(0);
14710
+ const [over, setOver] = React79.useState(false);
14711
+ const dragCounter = React79.useRef(0);
14692
14712
  const dropHandlers = isDropTarget ? {
14693
14713
  onDragEnter: (e) => {
14694
14714
  if (!hasInternalPayload(e)) return;
@@ -14717,7 +14737,7 @@ function BreadcrumbCrumb({
14717
14737
  }
14718
14738
 
14719
14739
  // src/kits/query.ts
14720
- import * as React79 from "react";
14740
+ import * as React80 from "react";
14721
14741
 
14722
14742
  // src/kits/queryUrl.ts
14723
14743
  var historyUrlAdapter = {
@@ -14855,38 +14875,38 @@ function requestFor(params, query, paging, after) {
14855
14875
  }
14856
14876
  var toError = (e) => e instanceof Error ? e : new Error(String(e));
14857
14877
  function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "page", url }) {
14858
- const [base] = React79.useState(() => {
14878
+ const [base] = React80.useState(() => {
14859
14879
  const store = PREFS || window.PlannerPrefs;
14860
14880
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
14861
14881
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
14862
14882
  });
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) => {
14883
+ const [mountParams] = React80.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
14884
+ const address = React80.useRef(mountParams);
14885
+ const [query, setQuery] = React80.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
14886
+ const savePref = React80.useCallback((patch2) => {
14867
14887
  const store = PREFS || window.PlannerPrefs;
14868
14888
  if (prefsKey && store) store.setTable(prefsKey, patch2);
14869
14889
  }, [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);
14890
+ const [res, setRes] = React80.useState(null);
14891
+ const [loading, setLoading] = React80.useState(true);
14892
+ const [loadingMore, setLoadingMore] = React80.useState(false);
14893
+ const [failure, setFailure] = React80.useState(null);
14894
+ const [reloadToken, setReloadToken] = React80.useState(0);
14895
+ const moreController = React80.useRef(null);
14876
14896
  const depKey = (deps || []).join("|");
14877
14897
  const paramKey = JSON.stringify(params || {});
14878
14898
  const queryKey = JSON.stringify(query);
14879
- const lifetime = React79.useRef(null);
14880
- React79.useEffect(() => {
14899
+ const lifetime = React80.useRef(null);
14900
+ React80.useEffect(() => {
14881
14901
  const controller = new AbortController();
14882
14902
  lifetime.current = controller;
14883
14903
  return () => controller.abort();
14884
14904
  }, []);
14885
- const latest = React79.useRef({ res, loading, query, params, endpoint, url, base });
14886
- React79.useLayoutEffect(() => {
14905
+ const latest = React80.useRef({ res, loading, query, params, endpoint, url, base });
14906
+ React80.useLayoutEffect(() => {
14887
14907
  latest.current = { res, loading, query, params, endpoint, url, base };
14888
14908
  });
14889
- React79.useEffect(() => {
14909
+ React80.useEffect(() => {
14890
14910
  const controller = new AbortController();
14891
14911
  const { signal } = controller;
14892
14912
  setLoading(true);
@@ -14922,7 +14942,7 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "
14922
14942
  };
14923
14943
  }, [endpoint, queryKey, paramKey, depKey, paging, reloadToken]);
14924
14944
  const adapter = url ? url.adapter ?? historyUrlAdapter : null;
14925
- React79.useEffect(() => {
14945
+ React80.useEffect(() => {
14926
14946
  if (!adapter) return;
14927
14947
  return adapter.subscribe((params2) => {
14928
14948
  const { url: u, base: b } = latest.current;
@@ -15272,12 +15292,12 @@ function createVersionStore(initialState, options) {
15272
15292
  }
15273
15293
 
15274
15294
  // src/kits/documentTitle.ts
15275
- import * as React80 from "react";
15295
+ import * as React81 from "react";
15276
15296
  function formatDocumentTitle(routeTitle, appName) {
15277
15297
  return [routeTitle, appName, "Flytedesk"].filter((part2) => !!part2 && part2.length > 0).join(" \xB7 ");
15278
15298
  }
15279
15299
  function useDocumentTitle(routeTitle, appName) {
15280
- React80.useEffect(() => {
15300
+ React81.useEffect(() => {
15281
15301
  if (typeof document === "undefined") return;
15282
15302
  document.title = formatDocumentTitle(routeTitle, appName);
15283
15303
  }, [routeTitle, appName]);