@flytedan/flytebot-design-system 0.72.0 → 0.73.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +586 -519
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -13
- package/dist/index.d.ts +31 -13
- package/dist/index.js +584 -519
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -937,26 +937,57 @@ function Collapsible({
|
|
|
937
937
|
}
|
|
938
938
|
|
|
939
939
|
// src/components/surfaces/Drawer.tsx
|
|
940
|
-
import * as
|
|
940
|
+
import * as React7 from "react";
|
|
941
941
|
import { createPortal as createPortal2 } from "react-dom";
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
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(
|
|
950
|
-
|
|
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);
|
|
978
|
+
const titleId = React7.useId();
|
|
979
|
+
const accessibleName = bare ? label ?? (typeof title === "string" ? title : void 0) : label;
|
|
980
|
+
const unnamed = !!open2 && bare && !accessibleName;
|
|
981
|
+
React7.useEffect(() => {
|
|
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.");
|
|
983
|
+
}, [unnamed]);
|
|
953
984
|
if (!open2) return null;
|
|
954
985
|
return createPortal2(
|
|
955
986
|
/* @__PURE__ */ jsxs6(StackedLayerProvider, { layer, children: [
|
|
956
987
|
/* @__PURE__ */ jsx9("div", { className: "fd-scrim" + (closing ? " is-closing" : ""), style: { display: "block", zIndex: zIndex - LAYER_STEP }, onClick: close2 }),
|
|
957
|
-
/* @__PURE__ */ jsxs6("aside", { ref: asideRef, className: ["fd-drawer", bare ? "is-bare" : "", closing ? "is-closing" : "", className].filter(Boolean).join(" "), role: "dialog", "aria-modal": "true", "aria-label":
|
|
988
|
+
/* @__PURE__ */ jsxs6("aside", { ref: asideRef, className: ["fd-drawer", bare ? "is-bare" : "", closing ? "is-closing" : "", className].filter(Boolean).join(" "), role: "dialog", "aria-modal": "true", "aria-label": accessibleName, "aria-labelledby": bare || label ? void 0 : titleId, ...rest, style: { zIndex }, children: [
|
|
958
989
|
bare ? null : /* @__PURE__ */ jsxs6("div", { className: "fd-card-head", style: { flex: "none" }, children: [
|
|
959
|
-
/* @__PURE__ */ jsx9("span", { className: "fd-card-head-title", title: truncationTitle(title), children: title }),
|
|
990
|
+
/* @__PURE__ */ jsx9("span", { id: titleId, className: "fd-card-head-title", title: truncationTitle(title), children: title }),
|
|
960
991
|
onClose ? /* @__PURE__ */ jsx9("button", { type: "button", className: "fd-btn-icon", "aria-label": "Close", onClick: close2, children: /* @__PURE__ */ jsx9("i", { className: "ph ph-x" }) }) : null
|
|
961
992
|
] }),
|
|
962
993
|
/* @__PURE__ */ jsx9("div", { style: bare ? { flex: "1 1 auto", minHeight: 0, display: "flex", flexDirection: "column" } : { flex: "1 1 auto", minHeight: 0, overflow: "auto", padding: 20 }, children: typeof children === "function" ? children(close2) : children }),
|
|
@@ -968,17 +999,12 @@ function Drawer({ open: open2 = true, title, onClose, footer, bare = false, chil
|
|
|
968
999
|
}
|
|
969
1000
|
|
|
970
1001
|
// src/components/surfaces/Modal.tsx
|
|
971
|
-
import * as
|
|
1002
|
+
import * as React8 from "react";
|
|
972
1003
|
import { createPortal as createPortal3 } from "react-dom";
|
|
973
1004
|
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
974
1005
|
function Modal({ open: open2 = true, title, description, onClose, footer, wide = false, children, className = "", ...rest }) {
|
|
975
|
-
const
|
|
976
|
-
const
|
|
977
|
-
const close2 = React7.useCallback(() => {
|
|
978
|
-
if (!onClose) return;
|
|
979
|
-
setClosing(true);
|
|
980
|
-
setTimeout(onClose, 190);
|
|
981
|
-
}, [onClose]);
|
|
1006
|
+
const boxRef = React8.useRef(null);
|
|
1007
|
+
const { closing, close: close2 } = useClosingAnimation(!!open2, onClose, 190);
|
|
982
1008
|
const layer = useStackedLayer({ active: !!open2, containerRef: boxRef, trap: true, onEscape: onClose ? close2 : void 0 });
|
|
983
1009
|
const zIndex = useLayerZIndex(layer);
|
|
984
1010
|
if (!open2) return null;
|
|
@@ -1061,13 +1087,13 @@ function ScreenHead({ kicker, title, lede, actions }) {
|
|
|
1061
1087
|
}
|
|
1062
1088
|
|
|
1063
1089
|
// src/components/layout/CardGrid.tsx
|
|
1064
|
-
import * as
|
|
1090
|
+
import * as React9 from "react";
|
|
1065
1091
|
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
1066
1092
|
function flattenFragments(children) {
|
|
1067
1093
|
const out = [];
|
|
1068
|
-
|
|
1094
|
+
React9.Children.forEach(children, (child) => {
|
|
1069
1095
|
if (child === null || child === void 0 || typeof child === "boolean") return;
|
|
1070
|
-
if (
|
|
1096
|
+
if (React9.isValidElement(child) && child.type === React9.Fragment) {
|
|
1071
1097
|
const fragmentChildren = child.props.children;
|
|
1072
1098
|
out.push(...flattenFragments(fragmentChildren));
|
|
1073
1099
|
return;
|
|
@@ -1085,7 +1111,7 @@ function CardGrid({ children, minCardWidth = 280, gap = "lg", className = "", st
|
|
|
1085
1111
|
className: ["fd-card-grid", "fd-gap-" + gap, className].filter(Boolean).join(" "),
|
|
1086
1112
|
style: { ["--card-grid-min"]: minCardWidth + "px", ...style },
|
|
1087
1113
|
children: items.map((child, i) => {
|
|
1088
|
-
if (
|
|
1114
|
+
if (React9.isValidElement(child)) {
|
|
1089
1115
|
const existingRole = child.props.role;
|
|
1090
1116
|
if (existingRole) return child;
|
|
1091
1117
|
return /* @__PURE__ */ jsx12("div", { role: "listitem", children: child }, child.key ?? i);
|
|
@@ -1135,10 +1161,10 @@ function LoadingRegion({
|
|
|
1135
1161
|
}
|
|
1136
1162
|
|
|
1137
1163
|
// src/components/loading/JobTray.tsx
|
|
1138
|
-
import * as
|
|
1164
|
+
import * as React11 from "react";
|
|
1139
1165
|
|
|
1140
1166
|
// src/kits/cornerStack.tsx
|
|
1141
|
-
import * as
|
|
1167
|
+
import * as React10 from "react";
|
|
1142
1168
|
import { createPortal as createPortal4 } from "react-dom";
|
|
1143
1169
|
var CORNER_STACK_INSET_PROPERTY = "--fd-corner-stack-inset";
|
|
1144
1170
|
var SLOTS = ["jobs", "toasts"];
|
|
@@ -1188,9 +1214,9 @@ function release(slot) {
|
|
|
1188
1214
|
slotElements.clear();
|
|
1189
1215
|
}
|
|
1190
1216
|
}
|
|
1191
|
-
var useSlotEffect = typeof document === "undefined" ?
|
|
1217
|
+
var useSlotEffect = typeof document === "undefined" ? React10.useEffect : React10.useLayoutEffect;
|
|
1192
1218
|
function useCornerStackSlot(slot) {
|
|
1193
|
-
const [element, setElement] =
|
|
1219
|
+
const [element, setElement] = React10.useState(null);
|
|
1194
1220
|
useSlotEffect(() => {
|
|
1195
1221
|
setElement(acquire(slot));
|
|
1196
1222
|
return () => {
|
|
@@ -1247,9 +1273,9 @@ function announcementFor(job) {
|
|
|
1247
1273
|
return title + ": in progress";
|
|
1248
1274
|
}
|
|
1249
1275
|
function JobTray({ jobs: jobs2, onDismiss, className = "" }) {
|
|
1250
|
-
const [announcement, setAnnouncement] =
|
|
1251
|
-
const prevStatuses =
|
|
1252
|
-
|
|
1276
|
+
const [announcement, setAnnouncement] = React11.useState("");
|
|
1277
|
+
const prevStatuses = React11.useRef({});
|
|
1278
|
+
React11.useEffect(() => {
|
|
1253
1279
|
let next = "";
|
|
1254
1280
|
for (const job of jobs2) {
|
|
1255
1281
|
if (prevStatuses.current[job.id] !== job.status) {
|
|
@@ -1300,7 +1326,7 @@ function JobCard({ job, onDismiss }) {
|
|
|
1300
1326
|
}
|
|
1301
1327
|
|
|
1302
1328
|
// src/components/loading/PhasedProgress.tsx
|
|
1303
|
-
import * as
|
|
1329
|
+
import * as React12 from "react";
|
|
1304
1330
|
import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1305
1331
|
var ICON = {
|
|
1306
1332
|
pending: "ph-circle",
|
|
@@ -1313,9 +1339,9 @@ function textOf2(node) {
|
|
|
1313
1339
|
return "";
|
|
1314
1340
|
}
|
|
1315
1341
|
function PhasedProgress({ phases, summary, className = "" }) {
|
|
1316
|
-
const [announcement, setAnnouncement] =
|
|
1317
|
-
const prevStatuses =
|
|
1318
|
-
|
|
1342
|
+
const [announcement, setAnnouncement] = React12.useState("");
|
|
1343
|
+
const prevStatuses = React12.useRef({});
|
|
1344
|
+
React12.useEffect(() => {
|
|
1319
1345
|
let next = "";
|
|
1320
1346
|
for (const phase of phases) {
|
|
1321
1347
|
if (prevStatuses.current[phase.id] !== phase.status) {
|
|
@@ -1395,12 +1421,12 @@ function Spinner({ size = "md", label = "Loading", className = "", style, ...res
|
|
|
1395
1421
|
}
|
|
1396
1422
|
|
|
1397
1423
|
// src/components/navigation/SidebarNav.tsx
|
|
1398
|
-
import * as
|
|
1424
|
+
import * as React13 from "react";
|
|
1399
1425
|
import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1400
1426
|
function Tip({ label, children }) {
|
|
1401
1427
|
return /* @__PURE__ */ jsx20("span", { title: label, style: { display: "inline-flex", flex: "none" }, children });
|
|
1402
1428
|
}
|
|
1403
|
-
var SidebarNav =
|
|
1429
|
+
var SidebarNav = React13.forwardRef(function SidebarNav2({ brand, groups = [], current: current2, onNavigate, footer, open: open2 = false, className = "", ...rest }, ref) {
|
|
1404
1430
|
return /* @__PURE__ */ jsxs14(
|
|
1405
1431
|
"nav",
|
|
1406
1432
|
{
|
|
@@ -1439,15 +1465,15 @@ var SidebarNav = React12.forwardRef(function SidebarNav2({ brand, groups = [], c
|
|
|
1439
1465
|
});
|
|
1440
1466
|
|
|
1441
1467
|
// src/components/navigation/Topbar.tsx
|
|
1442
|
-
import * as
|
|
1468
|
+
import * as React15 from "react";
|
|
1443
1469
|
|
|
1444
1470
|
// src/kits/useIsNarrow.ts
|
|
1445
|
-
import * as
|
|
1471
|
+
import * as React14 from "react";
|
|
1446
1472
|
function useIsNarrow(breakpoint) {
|
|
1447
|
-
const [narrow, setNarrow] =
|
|
1473
|
+
const [narrow, setNarrow] = React14.useState(
|
|
1448
1474
|
() => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
|
|
1449
1475
|
);
|
|
1450
|
-
|
|
1476
|
+
React14.useEffect(() => {
|
|
1451
1477
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
1452
1478
|
const mq = window.matchMedia(`(max-width: ${breakpoint}px)`);
|
|
1453
1479
|
const apply = () => setNarrow(mq.matches);
|
|
@@ -1471,11 +1497,11 @@ function Topbar({
|
|
|
1471
1497
|
...rest
|
|
1472
1498
|
}) {
|
|
1473
1499
|
const narrow = useIsNarrow(overflowBreakpoint);
|
|
1474
|
-
const [moreOpen, setMoreOpen] =
|
|
1475
|
-
const moreRef =
|
|
1500
|
+
const [moreOpen, setMoreOpen] = React15.useState(false);
|
|
1501
|
+
const moreRef = React15.useRef(null);
|
|
1476
1502
|
return /* @__PURE__ */ jsxs15("header", { className: ["fd-topbar", narrow ? "is-narrow" : "", className].filter(Boolean).join(" "), ...rest, children: [
|
|
1477
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,
|
|
1478
|
-
/* @__PURE__ */ jsx21("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ jsxs15(
|
|
1504
|
+
/* @__PURE__ */ jsx21("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ jsxs15(React15.Fragment, { children: [
|
|
1479
1505
|
i > 0 ? /* @__PURE__ */ jsx21("i", { className: "ph ph-caret-right", style: { fontSize: 11, opacity: 0.6 }, "aria-hidden": "true" }) : null,
|
|
1480
1506
|
i === crumbs.length - 1 ? (
|
|
1481
1507
|
// MP-141: the current crumb mixes a static route label with (usually) a
|
|
@@ -1528,29 +1554,37 @@ function Topbar({
|
|
|
1528
1554
|
}
|
|
1529
1555
|
|
|
1530
1556
|
// src/kits/useResponsiveRail.ts
|
|
1531
|
-
import * as
|
|
1557
|
+
import * as React16 from "react";
|
|
1558
|
+
|
|
1559
|
+
// src/kits/overlayLayout.ts
|
|
1560
|
+
var OVERLAY_BREAKPOINT = 1024;
|
|
1561
|
+
function useOverlayLayout() {
|
|
1562
|
+
return useIsNarrow(OVERLAY_BREAKPOINT);
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
// src/kits/useResponsiveRail.ts
|
|
1532
1566
|
function useResponsiveRail(options = {}) {
|
|
1533
|
-
const { breakpoint =
|
|
1534
|
-
const navRef =
|
|
1567
|
+
const { breakpoint = OVERLAY_BREAKPOINT, initialOpen = true, onPersist } = options;
|
|
1568
|
+
const navRef = React16.useRef(null);
|
|
1535
1569
|
const overlay = useIsNarrow(breakpoint);
|
|
1536
|
-
const [open2, setOpenRaw] =
|
|
1537
|
-
const setOpen =
|
|
1570
|
+
const [open2, setOpenRaw] = React16.useState(() => overlay ? false : initialOpen);
|
|
1571
|
+
const setOpen = React16.useCallback(
|
|
1538
1572
|
(value) => {
|
|
1539
1573
|
setOpenRaw(value);
|
|
1540
1574
|
if (!overlay) onPersist?.(value);
|
|
1541
1575
|
},
|
|
1542
1576
|
[overlay, onPersist]
|
|
1543
1577
|
);
|
|
1544
|
-
const toggle =
|
|
1545
|
-
const close2 =
|
|
1546
|
-
const lastOverlay =
|
|
1547
|
-
|
|
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(() => {
|
|
1548
1582
|
if (lastOverlay.current === overlay) return;
|
|
1549
1583
|
lastOverlay.current = overlay;
|
|
1550
1584
|
setOpenRaw(!overlay);
|
|
1551
1585
|
}, [overlay]);
|
|
1552
1586
|
const layer = useStackedLayer({ active: overlay && open2, containerRef: navRef, trap: true, onEscape: close2 });
|
|
1553
|
-
|
|
1587
|
+
React16.useEffect(() => {
|
|
1554
1588
|
if (!overlay || !open2) return;
|
|
1555
1589
|
const previousOverflow = document.body.style.overflow;
|
|
1556
1590
|
document.body.style.overflow = "hidden";
|
|
@@ -1571,7 +1605,7 @@ function AppShell({
|
|
|
1571
1605
|
navFooter,
|
|
1572
1606
|
initialNavOpen = true,
|
|
1573
1607
|
onNavOpenChange,
|
|
1574
|
-
railBreakpoint =
|
|
1608
|
+
railBreakpoint = OVERLAY_BREAKPOINT,
|
|
1575
1609
|
crumbs,
|
|
1576
1610
|
loading,
|
|
1577
1611
|
actions,
|
|
@@ -1677,20 +1711,20 @@ function installFlytedeskFavicon(url) {
|
|
|
1677
1711
|
}
|
|
1678
1712
|
|
|
1679
1713
|
// src/components/navigation/Tabs.tsx
|
|
1680
|
-
import * as
|
|
1714
|
+
import * as React17 from "react";
|
|
1681
1715
|
import { jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1682
1716
|
var FADE_WIDTH = 32;
|
|
1683
1717
|
function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
|
|
1684
|
-
const strip =
|
|
1685
|
-
const [more, setMore] =
|
|
1686
|
-
const measure =
|
|
1718
|
+
const strip = React17.useRef(null);
|
|
1719
|
+
const [more, setMore] = React17.useState({ start: false, end: false });
|
|
1720
|
+
const measure = React17.useCallback(() => {
|
|
1687
1721
|
const el = strip.current;
|
|
1688
1722
|
if (!el) return;
|
|
1689
1723
|
const start = el.scrollLeft > 1;
|
|
1690
1724
|
const end = el.scrollLeft + el.clientWidth < el.scrollWidth - 1;
|
|
1691
1725
|
setMore((m) => m.start === start && m.end === end ? m : { start, end });
|
|
1692
1726
|
}, []);
|
|
1693
|
-
|
|
1727
|
+
React17.useLayoutEffect(() => {
|
|
1694
1728
|
const el = strip.current;
|
|
1695
1729
|
measure();
|
|
1696
1730
|
if (!el || typeof ResizeObserver === "undefined") return;
|
|
@@ -1698,7 +1732,7 @@ function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
|
|
|
1698
1732
|
observer.observe(el);
|
|
1699
1733
|
return () => observer.disconnect();
|
|
1700
1734
|
}, [measure, tabs]);
|
|
1701
|
-
const revealActive =
|
|
1735
|
+
const revealActive = React17.useCallback(() => {
|
|
1702
1736
|
const el = strip.current;
|
|
1703
1737
|
const active = el?.querySelector('[aria-selected="true"]');
|
|
1704
1738
|
if (!el || !active || el.scrollWidth <= el.clientWidth) return;
|
|
@@ -1708,9 +1742,9 @@ function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
|
|
|
1708
1742
|
else if (tab.right > box.right - FADE_WIDTH) el.scrollLeft += tab.right - box.right + FADE_WIDTH;
|
|
1709
1743
|
measure();
|
|
1710
1744
|
}, [measure]);
|
|
1711
|
-
|
|
1745
|
+
React17.useLayoutEffect(revealActive, [value, revealActive]);
|
|
1712
1746
|
const tabKeys = tabs.map((t) => typeof t === "string" ? t : t.value).join(",");
|
|
1713
|
-
|
|
1747
|
+
React17.useLayoutEffect(() => {
|
|
1714
1748
|
const el = strip.current;
|
|
1715
1749
|
if (!el || typeof ResizeObserver === "undefined") return;
|
|
1716
1750
|
const observer = new ResizeObserver(revealActive);
|
|
@@ -1965,15 +1999,15 @@ function Toast({ title, children, tone = "success", onUndo, onDismiss, className
|
|
|
1965
1999
|
}
|
|
1966
2000
|
|
|
1967
2001
|
// src/components/feedback/ToastProvider.tsx
|
|
1968
|
-
import * as
|
|
2002
|
+
import * as React18 from "react";
|
|
1969
2003
|
import { jsx as jsx33, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
1970
2004
|
var DEFAULT_TOAST_DURATION_MS = 5e3;
|
|
1971
|
-
var ToastContext =
|
|
2005
|
+
var ToastContext = React18.createContext(null);
|
|
1972
2006
|
function ToastProvider({ children }) {
|
|
1973
|
-
const [items, setItems] =
|
|
1974
|
-
const timers =
|
|
1975
|
-
const nextId =
|
|
1976
|
-
const dismiss =
|
|
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) => {
|
|
1977
2011
|
setItems((current2) => current2.filter((item) => item.id !== id));
|
|
1978
2012
|
const timer = timers.current.get(id);
|
|
1979
2013
|
if (timer !== void 0) {
|
|
@@ -1981,7 +2015,7 @@ function ToastProvider({ children }) {
|
|
|
1981
2015
|
timers.current.delete(id);
|
|
1982
2016
|
}
|
|
1983
2017
|
}, []);
|
|
1984
|
-
const show =
|
|
2018
|
+
const show = React18.useCallback(
|
|
1985
2019
|
(title, options = {}) => {
|
|
1986
2020
|
const { tone = "success", duration = DEFAULT_TOAST_DURATION_MS } = options;
|
|
1987
2021
|
const id = nextId.current++;
|
|
@@ -1990,36 +2024,36 @@ function ToastProvider({ children }) {
|
|
|
1990
2024
|
},
|
|
1991
2025
|
[dismiss]
|
|
1992
2026
|
);
|
|
1993
|
-
|
|
2027
|
+
React18.useEffect(() => {
|
|
1994
2028
|
const pending = timers.current;
|
|
1995
2029
|
return () => {
|
|
1996
2030
|
pending.forEach(clearTimeout);
|
|
1997
2031
|
pending.clear();
|
|
1998
2032
|
};
|
|
1999
2033
|
}, []);
|
|
2000
|
-
const api =
|
|
2034
|
+
const api = React18.useMemo(() => ({ show }), [show]);
|
|
2001
2035
|
return /* @__PURE__ */ jsxs26(ToastContext.Provider, { value: api, children: [
|
|
2002
2036
|
children,
|
|
2003
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)) }) })
|
|
2004
2038
|
] });
|
|
2005
2039
|
}
|
|
2006
2040
|
function useToast() {
|
|
2007
|
-
const api =
|
|
2041
|
+
const api = React18.useContext(ToastContext);
|
|
2008
2042
|
if (!api) throw new Error("useToast must be used inside a <ToastProvider>");
|
|
2009
2043
|
return api;
|
|
2010
2044
|
}
|
|
2011
2045
|
|
|
2012
2046
|
// src/components/feedback/Tooltip.tsx
|
|
2013
|
-
import * as
|
|
2047
|
+
import * as React20 from "react";
|
|
2014
2048
|
|
|
2015
2049
|
// src/components/feedback/useTooltip.tsx
|
|
2016
|
-
import * as
|
|
2050
|
+
import * as React19 from "react";
|
|
2017
2051
|
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
2018
2052
|
var CLOSE_DELAY_MS = 120;
|
|
2019
2053
|
var isMouse = (e) => e.pointerType === "mouse";
|
|
2020
2054
|
function TooltipBubble({ open: open2, labels, placement, className, onHide, onEnter, onLeave }) {
|
|
2021
|
-
const anchorRef =
|
|
2022
|
-
const bubbleRef =
|
|
2055
|
+
const anchorRef = React19.useRef(open2.anchor);
|
|
2056
|
+
const bubbleRef = React19.useRef(null);
|
|
2023
2057
|
const pos = usePopoverPosition(true, anchorRef, {
|
|
2024
2058
|
placement: placement === "bottom" ? "bottom-center" : "top-center",
|
|
2025
2059
|
offset: 8,
|
|
@@ -2030,7 +2064,7 @@ function TooltipBubble({ open: open2, labels, placement, className, onHide, onEn
|
|
|
2030
2064
|
});
|
|
2031
2065
|
const layer = useStackedLayer({ active: true, containerRef: bubbleRef, onEscape: onHide, returnFocus: false });
|
|
2032
2066
|
const zIndex = useLayerZIndex(layer);
|
|
2033
|
-
|
|
2067
|
+
React19.useEffect(() => {
|
|
2034
2068
|
const away = (e) => {
|
|
2035
2069
|
const t = e.target;
|
|
2036
2070
|
if (open2.anchor.contains(t)) return;
|
|
@@ -2061,16 +2095,16 @@ function TooltipBubble({ open: open2, labels, placement, className, onHide, onEn
|
|
|
2061
2095
|
);
|
|
2062
2096
|
}
|
|
2063
2097
|
function useTooltip({ placement = "top", className = "" } = {}) {
|
|
2064
|
-
const [open2, setOpen] =
|
|
2065
|
-
const closeTimer =
|
|
2066
|
-
const focused =
|
|
2067
|
-
const cancelClose =
|
|
2098
|
+
const [open2, setOpen] = React19.useState(null);
|
|
2099
|
+
const closeTimer = React19.useRef(null);
|
|
2100
|
+
const focused = React19.useRef(null);
|
|
2101
|
+
const cancelClose = React19.useCallback(() => {
|
|
2068
2102
|
if (closeTimer.current) {
|
|
2069
2103
|
clearTimeout(closeTimer.current);
|
|
2070
2104
|
closeTimer.current = null;
|
|
2071
2105
|
}
|
|
2072
2106
|
}, []);
|
|
2073
|
-
const hide =
|
|
2107
|
+
const hide = React19.useCallback(() => {
|
|
2074
2108
|
cancelClose();
|
|
2075
2109
|
focused.current = null;
|
|
2076
2110
|
setOpen(null);
|
|
@@ -2090,7 +2124,7 @@ function useTooltip({ placement = "top", className = "" } = {}) {
|
|
|
2090
2124
|
setOpen((o) => o && o.reason === "hover" ? focused.current : o);
|
|
2091
2125
|
}, CLOSE_DELAY_MS);
|
|
2092
2126
|
};
|
|
2093
|
-
|
|
2127
|
+
React19.useEffect(() => cancelClose, [cancelClose]);
|
|
2094
2128
|
const labels = /* @__PURE__ */ new Map();
|
|
2095
2129
|
const bind = (id, label) => {
|
|
2096
2130
|
labels.set(id, label);
|
|
@@ -2143,17 +2177,17 @@ function useTooltip({ placement = "top", className = "" } = {}) {
|
|
|
2143
2177
|
// src/components/feedback/Tooltip.tsx
|
|
2144
2178
|
import { jsx as jsx35, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2145
2179
|
function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
2146
|
-
const id =
|
|
2180
|
+
const id = React20.useId();
|
|
2147
2181
|
const descId = id + "-desc";
|
|
2148
2182
|
const tip = useTooltip({ placement, className });
|
|
2149
|
-
const described =
|
|
2183
|
+
const described = React20.isValidElement(children) ? React20.cloneElement(children, {
|
|
2150
2184
|
"aria-describedby": [children.props["aria-describedby"], descId].filter(Boolean).join(" ")
|
|
2151
2185
|
}) : children;
|
|
2152
2186
|
return /* @__PURE__ */ jsxs27(
|
|
2153
2187
|
"span",
|
|
2154
2188
|
{
|
|
2155
2189
|
className: "fd-tooltip-anchor",
|
|
2156
|
-
"aria-describedby":
|
|
2190
|
+
"aria-describedby": React20.isValidElement(children) ? void 0 : descId,
|
|
2157
2191
|
...tip.bind(id, label),
|
|
2158
2192
|
children: [
|
|
2159
2193
|
described,
|
|
@@ -2165,16 +2199,16 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
2165
2199
|
}
|
|
2166
2200
|
|
|
2167
2201
|
// src/components/data/AnimNum.tsx
|
|
2168
|
-
import * as
|
|
2202
|
+
import * as React21 from "react";
|
|
2169
2203
|
import { Fragment as Fragment6, jsx as jsx36 } from "react/jsx-runtime";
|
|
2170
2204
|
function shouldSkipEasing() {
|
|
2171
2205
|
if (typeof document !== "undefined" && document.hidden) return true;
|
|
2172
2206
|
return window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false;
|
|
2173
2207
|
}
|
|
2174
2208
|
function AnimNum({ value, format, duration = 550 }) {
|
|
2175
|
-
const [display, setDisplay] =
|
|
2176
|
-
const prev =
|
|
2177
|
-
|
|
2209
|
+
const [display, setDisplay] = React21.useState(value);
|
|
2210
|
+
const prev = React21.useRef(value);
|
|
2211
|
+
React21.useEffect(() => {
|
|
2178
2212
|
const from = prev.current;
|
|
2179
2213
|
const to = value;
|
|
2180
2214
|
prev.current = to;
|
|
@@ -2202,14 +2236,14 @@ function AnimNum({ value, format, duration = 550 }) {
|
|
|
2202
2236
|
}
|
|
2203
2237
|
|
|
2204
2238
|
// src/components/data/TrendChart.tsx
|
|
2205
|
-
import * as
|
|
2239
|
+
import * as React24 from "react";
|
|
2206
2240
|
|
|
2207
2241
|
// src/components/useMeasuredWidth.ts
|
|
2208
|
-
import * as
|
|
2242
|
+
import * as React22 from "react";
|
|
2209
2243
|
function useMeasuredWidth(fallback) {
|
|
2210
|
-
const [element, setElement] =
|
|
2211
|
-
const [width, setWidth] =
|
|
2212
|
-
|
|
2244
|
+
const [element, setElement] = React22.useState(null);
|
|
2245
|
+
const [width, setWidth] = React22.useState(fallback);
|
|
2246
|
+
React22.useLayoutEffect(() => {
|
|
2213
2247
|
if (!element || typeof ResizeObserver === "undefined") return;
|
|
2214
2248
|
const measure = () => {
|
|
2215
2249
|
const measured = Math.round(element.getBoundingClientRect().width);
|
|
@@ -2224,7 +2258,7 @@ function useMeasuredWidth(fallback) {
|
|
|
2224
2258
|
}
|
|
2225
2259
|
|
|
2226
2260
|
// src/components/data/SegmentedMeter.tsx
|
|
2227
|
-
import * as
|
|
2261
|
+
import * as React23 from "react";
|
|
2228
2262
|
|
|
2229
2263
|
// src/kits/files.ts
|
|
2230
2264
|
function formatBytes(n) {
|
|
@@ -2429,7 +2463,7 @@ function SegmentedMeter({
|
|
|
2429
2463
|
const pct = safeTotal ? Math.min(100, Math.round(used / safeTotal * 100)) : 0;
|
|
2430
2464
|
const w = (v) => safeTotal ? Math.max(0, Math.min(100, Number(v) / safeTotal * 100)) : 0;
|
|
2431
2465
|
const fill = (s, i) => s.color || (s.variant ? VARIANT_FILL[s.variant] : void 0) || CHART[i % CHART.length];
|
|
2432
|
-
const generatedId =
|
|
2466
|
+
const generatedId = React23.useId();
|
|
2433
2467
|
const uid2 = id || generatedId;
|
|
2434
2468
|
return /* @__PURE__ */ jsxs28("div", { className: ["fd-segmeter", className].filter(Boolean).join(" "), onClick, children: [
|
|
2435
2469
|
label || showTotal ? /* @__PURE__ */ jsxs28("div", { className: "fd-segmeter-head", children: [
|
|
@@ -2580,8 +2614,8 @@ function TrendChart({
|
|
|
2580
2614
|
onRetry,
|
|
2581
2615
|
className = ""
|
|
2582
2616
|
}) {
|
|
2583
|
-
const [activeId, setActiveId] =
|
|
2584
|
-
const [pointTip, setPointTip] =
|
|
2617
|
+
const [activeId, setActiveId] = React24.useState(null);
|
|
2618
|
+
const [pointTip, setPointTip] = React24.useState(null);
|
|
2585
2619
|
const isEmpty = state === "ready" && (!categories.length || !series.length || series.every((s) => !s.values.length));
|
|
2586
2620
|
const effectiveState = isEmpty ? "empty" : state;
|
|
2587
2621
|
const [plotRef, VBW] = useMeasuredWidth(INITIAL_WIDTH);
|
|
@@ -2695,7 +2729,7 @@ function TrendChart({
|
|
|
2695
2729
|
}
|
|
2696
2730
|
|
|
2697
2731
|
// src/components/data/DonutChart.tsx
|
|
2698
|
-
import * as
|
|
2732
|
+
import * as React25 from "react";
|
|
2699
2733
|
import { jsx as jsx40, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2700
2734
|
function DonutChart({
|
|
2701
2735
|
segments,
|
|
@@ -2710,7 +2744,7 @@ function DonutChart({
|
|
|
2710
2744
|
onRetry,
|
|
2711
2745
|
className = ""
|
|
2712
2746
|
}) {
|
|
2713
|
-
const [activeId, setActiveId] =
|
|
2747
|
+
const [activeId, setActiveId] = React25.useState(null);
|
|
2714
2748
|
const items = segments.filter((s) => Number(s.value) > 0);
|
|
2715
2749
|
const total = items.reduce((n, s) => n + Number(s.value), 0);
|
|
2716
2750
|
const isEmpty = state === "ready" && (!items.length || total <= 0);
|
|
@@ -2802,7 +2836,7 @@ function DonutChart({
|
|
|
2802
2836
|
}
|
|
2803
2837
|
|
|
2804
2838
|
// src/components/data/BarList.tsx
|
|
2805
|
-
import * as
|
|
2839
|
+
import * as React26 from "react";
|
|
2806
2840
|
import { jsx as jsx41, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
2807
2841
|
var wholePercent = (share) => formatPercent(Math.round(share * 100));
|
|
2808
2842
|
function BarList({
|
|
@@ -2819,7 +2853,7 @@ function BarList({
|
|
|
2819
2853
|
onRetry,
|
|
2820
2854
|
className = ""
|
|
2821
2855
|
}) {
|
|
2822
|
-
const ordered =
|
|
2856
|
+
const ordered = React26.useMemo(() => {
|
|
2823
2857
|
const list = sort ? [...rows].sort((a, b) => Number(b.value) - Number(a.value)) : rows;
|
|
2824
2858
|
return maxRows ? list.slice(0, maxRows) : list;
|
|
2825
2859
|
}, [rows, sort, maxRows]);
|
|
@@ -2961,7 +2995,7 @@ function FunnelChart({
|
|
|
2961
2995
|
}
|
|
2962
2996
|
|
|
2963
2997
|
// src/components/data/Clamp.tsx
|
|
2964
|
-
import * as
|
|
2998
|
+
import * as React27 from "react";
|
|
2965
2999
|
import { jsx as jsx43, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2966
3000
|
function Clamp({
|
|
2967
3001
|
children,
|
|
@@ -2973,16 +3007,16 @@ function Clamp({
|
|
|
2973
3007
|
onToggle,
|
|
2974
3008
|
className = ""
|
|
2975
3009
|
}) {
|
|
2976
|
-
const [open2, setOpen] =
|
|
2977
|
-
const [overflows, setOverflows] =
|
|
2978
|
-
const bodyRef =
|
|
2979
|
-
const charClamped =
|
|
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(() => {
|
|
2980
3014
|
if (open2 || !maxChars || typeof text !== "string" || text.length <= maxChars) return null;
|
|
2981
3015
|
const cut = text.slice(0, maxChars);
|
|
2982
3016
|
const at = cut.lastIndexOf(" ");
|
|
2983
3017
|
return (at > maxChars * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
2984
3018
|
}, [text, maxChars, open2]);
|
|
2985
|
-
|
|
3019
|
+
React27.useLayoutEffect(() => {
|
|
2986
3020
|
const node = bodyRef.current;
|
|
2987
3021
|
if (maxChars || !node || !maxHeight) return;
|
|
2988
3022
|
const measure = () => {
|
|
@@ -3240,16 +3274,16 @@ function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort
|
|
|
3240
3274
|
}
|
|
3241
3275
|
|
|
3242
3276
|
// src/components/data/FilterBar.tsx
|
|
3243
|
-
import * as
|
|
3277
|
+
import * as React33 from "react";
|
|
3244
3278
|
|
|
3245
3279
|
// src/components/forms/NumberInput.tsx
|
|
3246
|
-
import * as
|
|
3280
|
+
import * as React30 from "react";
|
|
3247
3281
|
|
|
3248
3282
|
// src/components/forms/field.tsx
|
|
3249
|
-
import * as
|
|
3283
|
+
import * as React28 from "react";
|
|
3250
3284
|
import { jsx as jsx46, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
3251
3285
|
function useFieldId(id) {
|
|
3252
|
-
const generated =
|
|
3286
|
+
const generated = React28.useId();
|
|
3253
3287
|
return id || generated;
|
|
3254
3288
|
}
|
|
3255
3289
|
function FieldLabel({ htmlFor, id, required = false, onClick, children }) {
|
|
@@ -3268,10 +3302,10 @@ function HiddenFieldLabel({ id, children }) {
|
|
|
3268
3302
|
}
|
|
3269
3303
|
|
|
3270
3304
|
// src/components/useLatest.ts
|
|
3271
|
-
import * as
|
|
3305
|
+
import * as React29 from "react";
|
|
3272
3306
|
function useLatest(value) {
|
|
3273
|
-
const ref =
|
|
3274
|
-
|
|
3307
|
+
const ref = React29.useRef(value);
|
|
3308
|
+
React29.useInsertionEffect(() => {
|
|
3275
3309
|
ref.current = value;
|
|
3276
3310
|
});
|
|
3277
3311
|
return ref;
|
|
@@ -3354,20 +3388,20 @@ function NumberInput({
|
|
|
3354
3388
|
const n = typeof v === "number" ? v : parseNumberText(v);
|
|
3355
3389
|
return n == null || Number.isNaN(n) ? null : n;
|
|
3356
3390
|
};
|
|
3357
|
-
const [text, setText] =
|
|
3358
|
-
const [editing, setEditing] =
|
|
3391
|
+
const [text, setText] = React30.useState(() => toText(value));
|
|
3392
|
+
const [editing, setEditing] = React30.useState(false);
|
|
3359
3393
|
const parsed = parseNumberText(text);
|
|
3360
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;
|
|
3361
3395
|
const valid = invalidMessage == null;
|
|
3362
|
-
const committedRef =
|
|
3396
|
+
const committedRef = React30.useRef(toNumber(value));
|
|
3363
3397
|
const onChangeRef = useLatest(onChange);
|
|
3364
3398
|
const onValidityChangeRef = useLatest(onValidityChange);
|
|
3365
|
-
const focusedRef =
|
|
3366
|
-
|
|
3399
|
+
const focusedRef = React30.useRef(false);
|
|
3400
|
+
React30.useEffect(() => {
|
|
3367
3401
|
committedRef.current = toNumber(value);
|
|
3368
3402
|
if (!focusedRef.current) setText(toText(value));
|
|
3369
3403
|
}, [value]);
|
|
3370
|
-
|
|
3404
|
+
React30.useLayoutEffect(() => {
|
|
3371
3405
|
onValidityChangeRef.current?.(valid);
|
|
3372
3406
|
}, [valid, onValidityChangeRef]);
|
|
3373
3407
|
const fire = (n) => {
|
|
@@ -3383,7 +3417,7 @@ function NumberInput({
|
|
|
3383
3417
|
return true;
|
|
3384
3418
|
};
|
|
3385
3419
|
const bumpRef = useLatest(bump);
|
|
3386
|
-
const holdTimer =
|
|
3420
|
+
const holdTimer = React30.useRef(null);
|
|
3387
3421
|
const release2 = () => {
|
|
3388
3422
|
if (holdTimer.current) clearTimeout(holdTimer.current);
|
|
3389
3423
|
holdTimer.current = null;
|
|
@@ -3402,7 +3436,7 @@ function NumberInput({
|
|
|
3402
3436
|
};
|
|
3403
3437
|
holdTimer.current = setTimeout(tick, HOLD_DELAY_MS);
|
|
3404
3438
|
};
|
|
3405
|
-
|
|
3439
|
+
React30.useEffect(() => () => {
|
|
3406
3440
|
if (holdTimer.current) clearTimeout(holdTimer.current);
|
|
3407
3441
|
}, []);
|
|
3408
3442
|
const current2 = committedRef.current;
|
|
@@ -3505,7 +3539,7 @@ function NumberInput({
|
|
|
3505
3539
|
}
|
|
3506
3540
|
|
|
3507
3541
|
// src/components/forms/DatePicker.tsx
|
|
3508
|
-
import * as
|
|
3542
|
+
import * as React31 from "react";
|
|
3509
3543
|
import { jsx as jsx48, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
3510
3544
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
3511
3545
|
var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
@@ -3538,10 +3572,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3538
3572
|
const today = /* @__PURE__ */ new Date();
|
|
3539
3573
|
const sel = range ? value || {} : { start: value, end: value };
|
|
3540
3574
|
const anchor = parse(sel.start) || parse(initialMonth) || today;
|
|
3541
|
-
const [vy, setVy] =
|
|
3542
|
-
const [vm, setVm] =
|
|
3543
|
-
const [mode2, setMode] =
|
|
3544
|
-
const [hover, setHover] =
|
|
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);
|
|
3545
3579
|
const s = parse(sel.start), e = parse(sel.end);
|
|
3546
3580
|
const hoverEnd = range && s && !e && hover ? parse(hover) : null;
|
|
3547
3581
|
const inRange = (d) => {
|
|
@@ -3552,12 +3586,12 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3552
3586
|
const isEnd = (d) => !!e && iso(d) === iso(e);
|
|
3553
3587
|
const isEdge = (d) => isStart(d) || isEnd(d);
|
|
3554
3588
|
const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
|
|
3555
|
-
const [activeDate, setActiveDate] =
|
|
3589
|
+
const [activeDate, setActiveDate] = React31.useState(() => {
|
|
3556
3590
|
if (s) return s;
|
|
3557
3591
|
if (sameMonth(today, anchor.getFullYear(), anchor.getMonth())) return today;
|
|
3558
3592
|
return new Date(anchor.getFullYear(), anchor.getMonth(), 1);
|
|
3559
3593
|
});
|
|
3560
|
-
const calRef =
|
|
3594
|
+
const calRef = React31.useRef(null);
|
|
3561
3595
|
const pageToShow = (y, m) => {
|
|
3562
3596
|
const idx = y * 12 + m, firstIdx = vy * 12 + vm, secondIdx = firstIdx + 1;
|
|
3563
3597
|
if (idx === firstIdx || months > 1 && idx === secondIdx) return;
|
|
@@ -3574,7 +3608,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3574
3608
|
setActiveDate(next);
|
|
3575
3609
|
pageToShow(next.getFullYear(), next.getMonth());
|
|
3576
3610
|
};
|
|
3577
|
-
|
|
3611
|
+
React31.useEffect(() => {
|
|
3578
3612
|
const el = calRef.current?.querySelector('[data-iso="' + iso(activeDate) + '"]');
|
|
3579
3613
|
if (el) el.focus({ preventScroll: true });
|
|
3580
3614
|
}, [activeDate, vy, vm]);
|
|
@@ -3767,9 +3801,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3767
3801
|
}
|
|
3768
3802
|
function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, "aria-label": hiddenLabel, ...rest }) {
|
|
3769
3803
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id, hiddenLabel);
|
|
3770
|
-
const [open2, setOpen] =
|
|
3771
|
-
const rootRef =
|
|
3772
|
-
const boxRef =
|
|
3804
|
+
const [open2, setOpen] = React31.useState(false);
|
|
3805
|
+
const rootRef = React31.useRef(null);
|
|
3806
|
+
const boxRef = React31.useRef(null);
|
|
3773
3807
|
const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
|
|
3774
3808
|
const toggle = () => {
|
|
3775
3809
|
if (!disabled) setOpen(!open2);
|
|
@@ -3858,9 +3892,9 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
|
|
|
3858
3892
|
}
|
|
3859
3893
|
|
|
3860
3894
|
// src/components/forms/listbox.ts
|
|
3861
|
-
import * as
|
|
3895
|
+
import * as React32 from "react";
|
|
3862
3896
|
function useListboxNav({ count, onSelect }) {
|
|
3863
|
-
const [active, setActive] =
|
|
3897
|
+
const [active, setActive] = React32.useState(-1);
|
|
3864
3898
|
return {
|
|
3865
3899
|
active,
|
|
3866
3900
|
setActive,
|
|
@@ -3873,7 +3907,7 @@ function useListboxNav({ count, onSelect }) {
|
|
|
3873
3907
|
};
|
|
3874
3908
|
}
|
|
3875
3909
|
function useListboxScrollIntoView(active, listRef, enabled) {
|
|
3876
|
-
|
|
3910
|
+
React32.useEffect(() => {
|
|
3877
3911
|
if (!enabled || active < 0 || !listRef.current) return;
|
|
3878
3912
|
const list = listRef.current;
|
|
3879
3913
|
const el = list.querySelector('[data-i="' + active + '"]');
|
|
@@ -3891,7 +3925,7 @@ import { jsx as jsx50, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
|
3891
3925
|
var TAIL_CHARS = 12;
|
|
3892
3926
|
var graphemes = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
3893
3927
|
function splitForMiddleEllipsis(text) {
|
|
3894
|
-
const chars = Array.from(graphemes.segment(text), (
|
|
3928
|
+
const chars = Array.from(graphemes.segment(text), (part2) => part2.segment);
|
|
3895
3929
|
if (chars.length <= TAIL_CHARS) return { head: text, tail: "" };
|
|
3896
3930
|
return { head: chars.slice(0, -TAIL_CHARS).join(""), tail: chars.slice(-TAIL_CHARS).join("") };
|
|
3897
3931
|
}
|
|
@@ -4094,13 +4128,13 @@ function MultiSelectPanel({
|
|
|
4094
4128
|
onClose
|
|
4095
4129
|
}) {
|
|
4096
4130
|
const allowedOps = operatorsFor(field);
|
|
4097
|
-
const [draftOperator, setDraftOperator] =
|
|
4131
|
+
const [draftOperator, setDraftOperator] = React33.useState(value?.operator ?? allowedOps[0]);
|
|
4098
4132
|
const operator = allowedOps.length === 1 ? allowedOps[0] : value?.operator ?? draftOperator;
|
|
4099
4133
|
const selected = value?.values ?? [];
|
|
4100
4134
|
const selectedRef = useLatest(selected);
|
|
4101
4135
|
const operatorRef = useLatest(operator);
|
|
4102
|
-
const mountedRef =
|
|
4103
|
-
|
|
4136
|
+
const mountedRef = React33.useRef(true);
|
|
4137
|
+
React33.useEffect(() => {
|
|
4104
4138
|
mountedRef.current = true;
|
|
4105
4139
|
return () => {
|
|
4106
4140
|
mountedRef.current = false;
|
|
@@ -4114,20 +4148,20 @@ function MultiSelectPanel({
|
|
|
4114
4148
|
if (selectedRef.current.length > 0) commit(selectedRef.current, op);
|
|
4115
4149
|
else setDraftOperator(op);
|
|
4116
4150
|
};
|
|
4117
|
-
const [mode2, setMode] =
|
|
4118
|
-
const [query, setQuery] =
|
|
4119
|
-
const [asyncState, setAsyncState] =
|
|
4151
|
+
const [mode2, setMode] = React33.useState("search");
|
|
4152
|
+
const [query, setQuery] = React33.useState("");
|
|
4153
|
+
const [asyncState, setAsyncState] = React33.useState(
|
|
4120
4154
|
{ options: null, loading: !!field.loadOptions, error: false }
|
|
4121
4155
|
);
|
|
4122
|
-
const [retryTick, setRetryTick] =
|
|
4123
|
-
const inputRef =
|
|
4124
|
-
const listRef =
|
|
4125
|
-
const listId =
|
|
4156
|
+
const [retryTick, setRetryTick] = React33.useState(0);
|
|
4157
|
+
const inputRef = React33.useRef(null);
|
|
4158
|
+
const listRef = React33.useRef(null);
|
|
4159
|
+
const listId = React33.useId();
|
|
4126
4160
|
const loadOptionsRef = useLatest(field.loadOptions);
|
|
4127
|
-
|
|
4161
|
+
React33.useEffect(() => {
|
|
4128
4162
|
inputRef.current?.focus();
|
|
4129
4163
|
}, []);
|
|
4130
|
-
|
|
4164
|
+
React33.useEffect(() => {
|
|
4131
4165
|
const load = loadOptionsRef.current;
|
|
4132
4166
|
if (!load) return;
|
|
4133
4167
|
const controller = new AbortController();
|
|
@@ -4160,17 +4194,17 @@ function MultiSelectPanel({
|
|
|
4160
4194
|
};
|
|
4161
4195
|
const nav = useListboxNav({ count: options.length, onSelect: (i) => toggle(options[i]) });
|
|
4162
4196
|
useListboxScrollIntoView(nav.active, listRef, hasListbox);
|
|
4163
|
-
|
|
4197
|
+
React33.useEffect(() => {
|
|
4164
4198
|
nav.setActive(0);
|
|
4165
4199
|
}, [query, options.length]);
|
|
4166
4200
|
const activeId = hasListbox && options[nav.active] ? listId + "-opt-" + nav.active : void 0;
|
|
4167
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" : "";
|
|
4168
|
-
const [pasteText, setPasteText] =
|
|
4169
|
-
const [pasteLoading, setPasteLoading] =
|
|
4170
|
-
const [unmatchedTokens, setUnmatchedTokens] =
|
|
4171
|
-
const [pasteError, setPasteError] =
|
|
4172
|
-
const pasteWrapRef =
|
|
4173
|
-
|
|
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(() => {
|
|
4174
4208
|
if (mode2 === "paste") pasteWrapRef.current?.querySelector("textarea")?.focus();
|
|
4175
4209
|
}, [mode2]);
|
|
4176
4210
|
const doResolve = () => {
|
|
@@ -4343,8 +4377,8 @@ function MultiSelectPanel({
|
|
|
4343
4377
|
);
|
|
4344
4378
|
}
|
|
4345
4379
|
function useTextValidity(onFlip) {
|
|
4346
|
-
const invalidRef =
|
|
4347
|
-
const [, rerender] =
|
|
4380
|
+
const invalidRef = React33.useRef(/* @__PURE__ */ new Set());
|
|
4381
|
+
const [, rerender] = React33.useReducer((n) => n + 1, 0);
|
|
4348
4382
|
const onFlipRef = useLatest(onFlip);
|
|
4349
4383
|
const record = (name, valid) => {
|
|
4350
4384
|
const invalid = invalidRef.current;
|
|
@@ -4387,15 +4421,15 @@ function sameValue(a, b) {
|
|
|
4387
4421
|
return true;
|
|
4388
4422
|
}
|
|
4389
4423
|
function useReseedFromProps(value, applies, reseed) {
|
|
4390
|
-
const seen =
|
|
4391
|
-
|
|
4424
|
+
const seen = React33.useRef(value);
|
|
4425
|
+
React33.useLayoutEffect(() => {
|
|
4392
4426
|
if (seen.current === value) return;
|
|
4393
4427
|
seen.current = value;
|
|
4394
4428
|
if (!sameValue(value, applies())) reseed(value);
|
|
4395
4429
|
}, [value, applies, reseed]);
|
|
4396
4430
|
}
|
|
4397
4431
|
function usePreserveFocusAcrossRemount(seed, fields) {
|
|
4398
|
-
const pendingName =
|
|
4432
|
+
const pendingName = React33.useRef(null);
|
|
4399
4433
|
const fieldsRef = useLatest(fields);
|
|
4400
4434
|
const capture = () => {
|
|
4401
4435
|
const active = document.activeElement;
|
|
@@ -4408,7 +4442,7 @@ function usePreserveFocusAcrossRemount(seed, fields) {
|
|
|
4408
4442
|
}
|
|
4409
4443
|
}
|
|
4410
4444
|
};
|
|
4411
|
-
|
|
4445
|
+
React33.useLayoutEffect(() => {
|
|
4412
4446
|
const name = pendingName.current;
|
|
4413
4447
|
if (!name) return;
|
|
4414
4448
|
pendingName.current = null;
|
|
@@ -4424,14 +4458,14 @@ function RangePanel({
|
|
|
4424
4458
|
onCommit,
|
|
4425
4459
|
onClose
|
|
4426
4460
|
}) {
|
|
4427
|
-
const [draft, setDraft] =
|
|
4428
|
-
const [seed, setSeed] =
|
|
4429
|
-
const minId =
|
|
4430
|
-
const maxId =
|
|
4431
|
-
const minWrapRef =
|
|
4432
|
-
const maxWrapRef =
|
|
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);
|
|
4433
4467
|
const preserveFocus = usePreserveFocusAcrossRemount(seed, { min: minWrapRef, max: maxWrapRef });
|
|
4434
|
-
const draftRef =
|
|
4468
|
+
const draftRef = React33.useRef(draft);
|
|
4435
4469
|
const shown = () => {
|
|
4436
4470
|
const { min, max } = draftRef.current;
|
|
4437
4471
|
return applicable(field, min == null && max == null ? void 0 : { min, max }, validity.allValid());
|
|
@@ -4523,15 +4557,15 @@ function DatePanel({
|
|
|
4523
4557
|
onClose
|
|
4524
4558
|
}) {
|
|
4525
4559
|
const maxDays = effectiveMaxDays(field);
|
|
4526
|
-
const [initial] =
|
|
4527
|
-
const [kind, setKind] =
|
|
4528
|
-
const [daysDraft, setDaysDraft] =
|
|
4529
|
-
const daysRef =
|
|
4530
|
-
const daysConfirmed =
|
|
4531
|
-
const [between, setBetween] =
|
|
4532
|
-
const [seed, setSeed] =
|
|
4533
|
-
const daysId =
|
|
4534
|
-
const daysWrapRef =
|
|
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);
|
|
4535
4569
|
const preserveFocus = usePreserveFocusAcrossRemount(seed, { days: daysWrapRef });
|
|
4536
4570
|
const shownWithinDays = () => {
|
|
4537
4571
|
const days = daysRef.current;
|
|
@@ -4649,11 +4683,11 @@ function FilterButton({ children, ...rest }) {
|
|
|
4649
4683
|
] });
|
|
4650
4684
|
}
|
|
4651
4685
|
function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align = "left", actions, onClearAll, showActiveCount = false, loading = false, loadingLabel = "Loading the filters", className = "", ...rest }) {
|
|
4652
|
-
const [panel, setPanel] =
|
|
4653
|
-
const editAnchorRef =
|
|
4654
|
-
const addAnchorRef =
|
|
4655
|
-
const textInputRef =
|
|
4656
|
-
const optionsRef =
|
|
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);
|
|
4657
4691
|
if (process.env.NODE_ENV !== "production") {
|
|
4658
4692
|
for (const f of fields) assertValidFieldDefinition(f);
|
|
4659
4693
|
}
|
|
@@ -4676,7 +4710,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
4676
4710
|
const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
|
|
4677
4711
|
const startEditing = (key) => setPanel({ kind: "edit", key });
|
|
4678
4712
|
const closeEditing = () => setPanel(null);
|
|
4679
|
-
|
|
4713
|
+
React33.useEffect(() => {
|
|
4680
4714
|
if (!panel || panel.kind !== "edit") return;
|
|
4681
4715
|
if (editingField?.type === "text") {
|
|
4682
4716
|
textInputRef.current?.focus();
|
|
@@ -4931,10 +4965,10 @@ function StatTile(props) {
|
|
|
4931
4965
|
}
|
|
4932
4966
|
|
|
4933
4967
|
// src/components/data/CodeBlock.tsx
|
|
4934
|
-
import * as
|
|
4968
|
+
import * as React35 from "react";
|
|
4935
4969
|
|
|
4936
4970
|
// src/kits/clipboard.ts
|
|
4937
|
-
import * as
|
|
4971
|
+
import * as React34 from "react";
|
|
4938
4972
|
var COPIED_FEEDBACK_MS = 1600;
|
|
4939
4973
|
function copyThroughSelection(text) {
|
|
4940
4974
|
const previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
@@ -4964,17 +4998,17 @@ async function copyToClipboard(text) {
|
|
|
4964
4998
|
return copyThroughSelection(text);
|
|
4965
4999
|
}
|
|
4966
5000
|
function useCopyToClipboard() {
|
|
4967
|
-
const [copied, setCopied] =
|
|
4968
|
-
const timer =
|
|
4969
|
-
const mounted =
|
|
4970
|
-
|
|
5001
|
+
const [copied, setCopied] = React34.useState(false);
|
|
5002
|
+
const timer = React34.useRef(null);
|
|
5003
|
+
const mounted = React34.useRef(true);
|
|
5004
|
+
React34.useEffect(() => {
|
|
4971
5005
|
mounted.current = true;
|
|
4972
5006
|
return () => {
|
|
4973
5007
|
mounted.current = false;
|
|
4974
5008
|
if (timer.current) clearTimeout(timer.current);
|
|
4975
5009
|
};
|
|
4976
5010
|
}, []);
|
|
4977
|
-
const copy =
|
|
5011
|
+
const copy = React34.useCallback(async (text) => {
|
|
4978
5012
|
const ok = await copyToClipboard(text);
|
|
4979
5013
|
if (ok && mounted.current) {
|
|
4980
5014
|
setCopied(true);
|
|
@@ -5142,7 +5176,7 @@ function tokenize(src, lang) {
|
|
|
5142
5176
|
return out;
|
|
5143
5177
|
}
|
|
5144
5178
|
function Highlighted({ code, lang }) {
|
|
5145
|
-
const toks =
|
|
5179
|
+
const toks = React35.useMemo(() => tokenize(code, lang), [code, lang]);
|
|
5146
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) });
|
|
5147
5181
|
}
|
|
5148
5182
|
function CodeBlock({
|
|
@@ -5156,8 +5190,8 @@ function CodeBlock({
|
|
|
5156
5190
|
actions,
|
|
5157
5191
|
className = ""
|
|
5158
5192
|
}) {
|
|
5159
|
-
const [wrap, setWrap] =
|
|
5160
|
-
const [open2, setOpen] =
|
|
5193
|
+
const [wrap, setWrap] = React35.useState(!!wrapDefault);
|
|
5194
|
+
const [open2, setOpen] = React35.useState(false);
|
|
5161
5195
|
const [copied, copy] = useCopyToClipboard();
|
|
5162
5196
|
const body = String(code).replace(/\n$/, "");
|
|
5163
5197
|
const lines = body.split("\n");
|
|
@@ -5186,7 +5220,7 @@ function CodeBlock({
|
|
|
5186
5220
|
] });
|
|
5187
5221
|
}
|
|
5188
5222
|
function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
|
|
5189
|
-
const [open2, setOpen] =
|
|
5223
|
+
const [open2, setOpen] = React35.useState(false);
|
|
5190
5224
|
const [copied, copy] = useCopyToClipboard();
|
|
5191
5225
|
const raw = String(diff).replace(/\n$/, "");
|
|
5192
5226
|
const all = raw.split("\n").map((line) => {
|
|
@@ -5232,7 +5266,7 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
|
|
|
5232
5266
|
}
|
|
5233
5267
|
|
|
5234
5268
|
// src/components/data/Markdown.tsx
|
|
5235
|
-
import * as
|
|
5269
|
+
import * as React36 from "react";
|
|
5236
5270
|
import { jsx as jsx55, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
5237
5271
|
var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
|
|
5238
5272
|
var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
|
|
@@ -5275,7 +5309,7 @@ function hiddenInlineNodes(hidden, ctx, keyBase) {
|
|
|
5275
5309
|
const href = safeHref(d(g(2)));
|
|
5276
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()));
|
|
5277
5311
|
} else if (kind === "cite") {
|
|
5278
|
-
out.push(ctx.renderCitation ? /* @__PURE__ */ jsx55(
|
|
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()));
|
|
5279
5313
|
} else if (kind === "strongem") out.push(/* @__PURE__ */ jsx55("strong", { children: /* @__PURE__ */ jsx55("em", { children: hiddenInlineNodes(g(1), ctx, key()) }) }, key()));
|
|
5280
5314
|
else if (kind === "strong") out.push(/* @__PURE__ */ jsx55("strong", { children: hiddenInlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
5281
5315
|
else if (kind === "em") out.push(/* @__PURE__ */ jsx55("em", { children: hiddenInlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
@@ -5462,7 +5496,7 @@ function Markdown({
|
|
|
5462
5496
|
tone = "default"
|
|
5463
5497
|
}) {
|
|
5464
5498
|
const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
|
|
5465
|
-
const blocks =
|
|
5499
|
+
const blocks = React36.useMemo(() => parseBlocks(source), [source]);
|
|
5466
5500
|
return /* @__PURE__ */ jsx55("div", { className: mdClass("fd-md", size, tone, className), children: renderBlocks(blocks, ctx, "b") });
|
|
5467
5501
|
}
|
|
5468
5502
|
function MarkdownInline({ source = "", className = "", onLinkClick, size, tone }) {
|
|
@@ -5573,7 +5607,7 @@ function Pagination({
|
|
|
5573
5607
|
}
|
|
5574
5608
|
|
|
5575
5609
|
// src/components/data/RelativeTime.tsx
|
|
5576
|
-
import * as
|
|
5610
|
+
import * as React37 from "react";
|
|
5577
5611
|
import { jsxs as jsxs48 } from "react/jsx-runtime";
|
|
5578
5612
|
var MIN = 6e4;
|
|
5579
5613
|
var HOUR = 36e5;
|
|
@@ -5625,9 +5659,9 @@ function formatDuration(ms) {
|
|
|
5625
5659
|
return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
|
|
5626
5660
|
}
|
|
5627
5661
|
function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
|
|
5628
|
-
const [, force] =
|
|
5662
|
+
const [, force] = React37.useState(0);
|
|
5629
5663
|
const t = value instanceof Date ? value.getTime() : Date.parse(value);
|
|
5630
|
-
|
|
5664
|
+
React37.useEffect(() => {
|
|
5631
5665
|
if (!refresh2 || !t || isNaN(t)) return;
|
|
5632
5666
|
const abs = Math.abs(t - Date.now());
|
|
5633
5667
|
if (abs > DAY) return;
|
|
@@ -5643,7 +5677,7 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
|
|
|
5643
5677
|
}
|
|
5644
5678
|
|
|
5645
5679
|
// src/components/data/ScoreMeter.tsx
|
|
5646
|
-
import * as
|
|
5680
|
+
import * as React38 from "react";
|
|
5647
5681
|
import { jsx as jsx58, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
5648
5682
|
function ScoreMeter({
|
|
5649
5683
|
score,
|
|
@@ -5658,10 +5692,10 @@ function ScoreMeter({
|
|
|
5658
5692
|
breakdownWidth = 280,
|
|
5659
5693
|
className = ""
|
|
5660
5694
|
}) {
|
|
5661
|
-
const [open2, setOpen] =
|
|
5662
|
-
const ref =
|
|
5695
|
+
const [open2, setOpen] = React38.useState(false);
|
|
5696
|
+
const ref = React38.useRef(null);
|
|
5663
5697
|
const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
|
|
5664
|
-
const body = /* @__PURE__ */ jsxs49(
|
|
5698
|
+
const body = /* @__PURE__ */ jsxs49(React38.Fragment, { children: [
|
|
5665
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 }) }),
|
|
5666
5700
|
showScore ? /* @__PURE__ */ jsx58("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
|
|
5667
5701
|
] });
|
|
@@ -5680,7 +5714,7 @@ function ScoreMeter({
|
|
|
5680
5714
|
}
|
|
5681
5715
|
);
|
|
5682
5716
|
}
|
|
5683
|
-
return /* @__PURE__ */ jsxs49(
|
|
5717
|
+
return /* @__PURE__ */ jsxs49(React38.Fragment, { children: [
|
|
5684
5718
|
/* @__PURE__ */ jsx58(
|
|
5685
5719
|
"button",
|
|
5686
5720
|
{
|
|
@@ -5711,11 +5745,11 @@ function ScoreMeter({
|
|
|
5711
5745
|
}
|
|
5712
5746
|
|
|
5713
5747
|
// src/components/actions/inlinePanel.tsx
|
|
5714
|
-
import * as
|
|
5748
|
+
import * as React39 from "react";
|
|
5715
5749
|
import { jsx as jsx59 } from "react/jsx-runtime";
|
|
5716
5750
|
function useInlinePanel() {
|
|
5717
|
-
const [open2, setOpen] =
|
|
5718
|
-
const ref =
|
|
5751
|
+
const [open2, setOpen] = React39.useState(false);
|
|
5752
|
+
const ref = React39.useRef(null);
|
|
5719
5753
|
return { open: open2, setOpen, ref };
|
|
5720
5754
|
}
|
|
5721
5755
|
function InlinePanelSurface({ panel, align = "right", ...popover }) {
|
|
@@ -5886,7 +5920,7 @@ function SortMenu({
|
|
|
5886
5920
|
}
|
|
5887
5921
|
|
|
5888
5922
|
// src/components/data/StepList.tsx
|
|
5889
|
-
import * as
|
|
5923
|
+
import * as React40 from "react";
|
|
5890
5924
|
import { jsx as jsx61, jsxs as jsxs51 } from "react/jsx-runtime";
|
|
5891
5925
|
var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
|
|
5892
5926
|
function StepList({
|
|
@@ -5900,9 +5934,9 @@ function StepList({
|
|
|
5900
5934
|
className = "",
|
|
5901
5935
|
active = false
|
|
5902
5936
|
}) {
|
|
5903
|
-
const [openState, setOpenState] =
|
|
5937
|
+
const [openState, setOpenState] = React40.useState(defaultOpen);
|
|
5904
5938
|
const open2 = openProp == null ? openState : openProp;
|
|
5905
|
-
const [expanded, setExpanded] =
|
|
5939
|
+
const [expanded, setExpanded] = React40.useState({});
|
|
5906
5940
|
if (!steps.length) return null;
|
|
5907
5941
|
const running = steps.some((s) => s.status === "running");
|
|
5908
5942
|
const failed = steps.filter((s) => s.status === "error").length;
|
|
@@ -5960,7 +5994,7 @@ function StepList({
|
|
|
5960
5994
|
}
|
|
5961
5995
|
|
|
5962
5996
|
// src/components/data/VirtualList.tsx
|
|
5963
|
-
import * as
|
|
5997
|
+
import * as React41 from "react";
|
|
5964
5998
|
import { jsx as jsx62, jsxs as jsxs52 } from "react/jsx-runtime";
|
|
5965
5999
|
var VIRTUAL_LIST_BUFFER_ROWS = 20;
|
|
5966
6000
|
var VIRTUAL_LIST_ROW_GAP = 6;
|
|
@@ -6012,35 +6046,35 @@ function VirtualList({
|
|
|
6012
6046
|
className = "",
|
|
6013
6047
|
style
|
|
6014
6048
|
}) {
|
|
6015
|
-
const [scrollTop, setScrollTop] =
|
|
6016
|
-
const loaded =
|
|
6049
|
+
const [scrollTop, setScrollTop] = React41.useState(0);
|
|
6050
|
+
const loaded = React41.useMemo(
|
|
6017
6051
|
() => ({ firstItemIndex, count: items.length }),
|
|
6018
6052
|
[firstItemIndex, items.length]
|
|
6019
6053
|
);
|
|
6020
6054
|
const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
|
|
6021
6055
|
const bandKey = firstItemIndex + ":" + items.length;
|
|
6022
|
-
const win =
|
|
6056
|
+
const win = React41.useMemo(
|
|
6023
6057
|
() => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
|
|
6024
6058
|
[scrollTop, height, itemHeight, total, loaded]
|
|
6025
6059
|
);
|
|
6026
|
-
const need =
|
|
6060
|
+
const need = React41.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
|
|
6027
6061
|
const wantStart = need.start && hasMore?.start !== false;
|
|
6028
6062
|
const wantEnd = need.end && hasMore?.end !== false;
|
|
6029
6063
|
const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
|
|
6030
6064
|
const askKey = bandKey + "@" + bucket2;
|
|
6031
|
-
const asked =
|
|
6032
|
-
|
|
6065
|
+
const asked = React41.useRef({ start: null, end: null });
|
|
6066
|
+
React41.useEffect(() => {
|
|
6033
6067
|
if (loading || !wantStart || asked.current.start === askKey) return;
|
|
6034
6068
|
asked.current.start = askKey;
|
|
6035
6069
|
onNeedMore("start", win);
|
|
6036
6070
|
}, [wantStart, loading, askKey, onNeedMore, win]);
|
|
6037
|
-
|
|
6071
|
+
React41.useEffect(() => {
|
|
6038
6072
|
if (loading || !wantEnd || asked.current.end === askKey) return;
|
|
6039
6073
|
asked.current.end = askKey;
|
|
6040
6074
|
onNeedMore("end", win);
|
|
6041
6075
|
}, [wantEnd, loading, askKey, onNeedMore, win]);
|
|
6042
|
-
const lastKeysRef =
|
|
6043
|
-
const newKeys =
|
|
6076
|
+
const lastKeysRef = React41.useRef(null);
|
|
6077
|
+
const newKeys = React41.useMemo(() => {
|
|
6044
6078
|
const prev = lastKeysRef.current;
|
|
6045
6079
|
if (!prev) return /* @__PURE__ */ new Set();
|
|
6046
6080
|
const fresh = /* @__PURE__ */ new Set();
|
|
@@ -6050,7 +6084,7 @@ function VirtualList({
|
|
|
6050
6084
|
}
|
|
6051
6085
|
return fresh;
|
|
6052
6086
|
}, [items]);
|
|
6053
|
-
|
|
6087
|
+
React41.useEffect(() => {
|
|
6054
6088
|
lastKeysRef.current = new Set(items.map(keyOf));
|
|
6055
6089
|
}, [items]);
|
|
6056
6090
|
const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
|
|
@@ -6095,7 +6129,7 @@ function VirtualList({
|
|
|
6095
6129
|
}
|
|
6096
6130
|
|
|
6097
6131
|
// src/components/data/EntityRow.tsx
|
|
6098
|
-
import * as
|
|
6132
|
+
import * as React42 from "react";
|
|
6099
6133
|
import { jsx as jsx63, jsxs as jsxs53 } from "react/jsx-runtime";
|
|
6100
6134
|
var ENTITY_ROW_METRIC_WIDTH = 74;
|
|
6101
6135
|
var METRIC_TONE_COLOR = {
|
|
@@ -6108,7 +6142,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
|
|
|
6108
6142
|
const key = m.id || m.label || i;
|
|
6109
6143
|
const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
|
|
6110
6144
|
const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
|
|
6111
|
-
const content = /* @__PURE__ */ jsxs53(
|
|
6145
|
+
const content = /* @__PURE__ */ jsxs53(React42.Fragment, { children: [
|
|
6112
6146
|
m.icon ? /* @__PURE__ */ jsx63("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
|
|
6113
6147
|
/* @__PURE__ */ jsx63("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
|
|
6114
6148
|
/* @__PURE__ */ jsx63("span", { className: "fd-sr", children: " " + m.label })
|
|
@@ -6200,7 +6234,7 @@ function EntityRow({
|
|
|
6200
6234
|
}
|
|
6201
6235
|
|
|
6202
6236
|
// src/components/data/TransferList.tsx
|
|
6203
|
-
import * as
|
|
6237
|
+
import * as React43 from "react";
|
|
6204
6238
|
import { createPortal as createPortal5 } from "react-dom";
|
|
6205
6239
|
|
|
6206
6240
|
// src/components/forms/Input.tsx
|
|
@@ -6306,12 +6340,12 @@ function TransferList({
|
|
|
6306
6340
|
listHeight = 440,
|
|
6307
6341
|
className = ""
|
|
6308
6342
|
}) {
|
|
6309
|
-
const [drag, setDrag] =
|
|
6310
|
-
const [dragOverSide, setDragOverSide] =
|
|
6311
|
-
const dragRef =
|
|
6312
|
-
const armedRef =
|
|
6313
|
-
const sideRefs =
|
|
6314
|
-
const hitTestSide =
|
|
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) => {
|
|
6315
6349
|
for (const side of ["left", "right"]) {
|
|
6316
6350
|
const el = sideRefs.current[side];
|
|
6317
6351
|
if (!el) continue;
|
|
@@ -6320,7 +6354,7 @@ function TransferList({
|
|
|
6320
6354
|
}
|
|
6321
6355
|
return null;
|
|
6322
6356
|
}, []);
|
|
6323
|
-
const findItem =
|
|
6357
|
+
const findItem = React43.useCallback(
|
|
6324
6358
|
(side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
|
|
6325
6359
|
[left.items, right.items, keyOf]
|
|
6326
6360
|
);
|
|
@@ -6342,7 +6376,7 @@ function TransferList({
|
|
|
6342
6376
|
height: rect.height
|
|
6343
6377
|
};
|
|
6344
6378
|
};
|
|
6345
|
-
|
|
6379
|
+
React43.useEffect(() => {
|
|
6346
6380
|
const onMovePointer = (e) => {
|
|
6347
6381
|
const armed = armedRef.current;
|
|
6348
6382
|
if (!armed || e.pointerId !== armed.pointerId) return;
|
|
@@ -6395,7 +6429,7 @@ function TransferList({
|
|
|
6395
6429
|
window.removeEventListener("pointercancel", endDrag);
|
|
6396
6430
|
};
|
|
6397
6431
|
}, [hitTestSide, findItem, onMove]);
|
|
6398
|
-
|
|
6432
|
+
React43.useEffect(() => {
|
|
6399
6433
|
if (!drag || typeof document === "undefined") return;
|
|
6400
6434
|
const prev = document.body.style.userSelect;
|
|
6401
6435
|
document.body.style.userSelect = "none";
|
|
@@ -6512,7 +6546,7 @@ function FactList({ facts = [], className = "", ...rest }) {
|
|
|
6512
6546
|
}
|
|
6513
6547
|
|
|
6514
6548
|
// src/components/data/USChoropleth.tsx
|
|
6515
|
-
import * as
|
|
6549
|
+
import * as React45 from "react";
|
|
6516
6550
|
|
|
6517
6551
|
// src/components/data/usChoropleth/mapBox.ts
|
|
6518
6552
|
var MAP_WIDTH = 975;
|
|
@@ -6577,11 +6611,11 @@ function buildChoroplethModel(values, topN, givenTotal) {
|
|
|
6577
6611
|
}
|
|
6578
6612
|
|
|
6579
6613
|
// src/components/data/usChoropleth/useUsStateShapes.ts
|
|
6580
|
-
import * as
|
|
6614
|
+
import * as React44 from "react";
|
|
6581
6615
|
function useUsStateShapes() {
|
|
6582
|
-
const [token, setToken] =
|
|
6583
|
-
const [settled, setSettled] =
|
|
6584
|
-
|
|
6616
|
+
const [token, setToken] = React44.useState(0);
|
|
6617
|
+
const [settled, setSettled] = React44.useState(null);
|
|
6618
|
+
React44.useEffect(() => {
|
|
6585
6619
|
let current2 = true;
|
|
6586
6620
|
import("./usStateShapes-JJARDNLL.js").then(({ STATE_SHAPES }) => {
|
|
6587
6621
|
if (current2) setSettled({ token, state: { status: "ready", shapes: STATE_SHAPES } });
|
|
@@ -6623,7 +6657,7 @@ function nextCode(key, from) {
|
|
|
6623
6657
|
}
|
|
6624
6658
|
function StateMap({ shapes, model, figures, label, formatReadout }) {
|
|
6625
6659
|
const tip = useTooltip();
|
|
6626
|
-
const [stop, setStop] =
|
|
6660
|
+
const [stop, setStop] = React45.useState(US_STATE_CODES[0]);
|
|
6627
6661
|
const onKeyDown = (event) => {
|
|
6628
6662
|
const from = event.target.getAttribute("data-state");
|
|
6629
6663
|
const to = from && nextCode(event.key, from);
|
|
@@ -6671,8 +6705,8 @@ function StateTable({ model, valueLabel, formatValue }) {
|
|
|
6671
6705
|
return /* @__PURE__ */ jsx68(Collapsible, { title: TABLE_TITLE, children: /* @__PURE__ */ jsx68(DataTable, { columns, rows: model.rows, rowKey: "code", compact: true }) });
|
|
6672
6706
|
}
|
|
6673
6707
|
function USChoropleth({ values, label, valueLabel, formatValue, formatReadout, topN, total, className = "" }) {
|
|
6674
|
-
const model =
|
|
6675
|
-
const figures =
|
|
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]);
|
|
6676
6710
|
const { state, retry } = useUsStateShapes();
|
|
6677
6711
|
return /* @__PURE__ */ jsxs57("div", { className: ["fd-uschoro", className].filter(Boolean).join(" "), children: [
|
|
6678
6712
|
/* @__PURE__ */ jsxs57("div", { className: "fd-uschoro-layout", children: [
|
|
@@ -6707,11 +6741,11 @@ function USChoropleth({ values, label, valueLabel, formatValue, formatReadout, t
|
|
|
6707
6741
|
}
|
|
6708
6742
|
|
|
6709
6743
|
// src/components/forms/Checkbox.tsx
|
|
6710
|
-
import * as
|
|
6744
|
+
import * as React46 from "react";
|
|
6711
6745
|
import { jsx as jsx69, jsxs as jsxs58 } from "react/jsx-runtime";
|
|
6712
6746
|
function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
|
|
6713
|
-
const ref =
|
|
6714
|
-
|
|
6747
|
+
const ref = React46.useRef(null);
|
|
6748
|
+
React46.useEffect(() => {
|
|
6715
6749
|
if (ref.current) ref.current.indeterminate = indeterminate;
|
|
6716
6750
|
}, [indeterminate]);
|
|
6717
6751
|
return /* @__PURE__ */ jsxs58("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
@@ -6758,7 +6792,7 @@ function Switch({ label, description, className = "", ...rest }) {
|
|
|
6758
6792
|
}
|
|
6759
6793
|
|
|
6760
6794
|
// src/components/forms/Select.tsx
|
|
6761
|
-
import * as
|
|
6795
|
+
import * as React47 from "react";
|
|
6762
6796
|
import { jsx as jsx72, jsxs as jsxs61 } from "react/jsx-runtime";
|
|
6763
6797
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
6764
6798
|
function Select({
|
|
@@ -6786,12 +6820,12 @@ function Select({
|
|
|
6786
6820
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
6787
6821
|
const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
|
|
6788
6822
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id, hiddenLabel);
|
|
6789
|
-
const [open2, setOpen] =
|
|
6790
|
-
const [q, setQ] =
|
|
6791
|
-
const rootRef =
|
|
6792
|
-
const boxRef =
|
|
6793
|
-
const listRef =
|
|
6794
|
-
const typeBuf =
|
|
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 });
|
|
6795
6829
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
6796
6830
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
6797
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;
|
|
@@ -6927,7 +6961,7 @@ function Select({
|
|
|
6927
6961
|
),
|
|
6928
6962
|
q ? /* @__PURE__ */ jsx72("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
6929
6963
|
] }) : void 0,
|
|
6930
|
-
footer: multiple ? /* @__PURE__ */ jsxs61(
|
|
6964
|
+
footer: multiple ? /* @__PURE__ */ jsxs61(React47.Fragment, { children: [
|
|
6931
6965
|
/* @__PURE__ */ jsx72(
|
|
6932
6966
|
"button",
|
|
6933
6967
|
{
|
|
@@ -6958,7 +6992,7 @@ function Select({
|
|
|
6958
6992
|
'Nothing matches "',
|
|
6959
6993
|
q,
|
|
6960
6994
|
'".'
|
|
6961
|
-
] }) : groups.map((grp) => /* @__PURE__ */ jsxs61(
|
|
6995
|
+
] }) : groups.map((grp) => /* @__PURE__ */ jsxs61(React47.Fragment, { children: [
|
|
6962
6996
|
grp.g ? /* @__PURE__ */ jsx72("div", { className: "fd-pop-group", children: grp.g }) : null,
|
|
6963
6997
|
grp.items.map(({ o, i }) => /* @__PURE__ */ jsxs61(
|
|
6964
6998
|
"button",
|
|
@@ -6995,7 +7029,7 @@ function Select({
|
|
|
6995
7029
|
}
|
|
6996
7030
|
|
|
6997
7031
|
// src/components/forms/TimePicker.tsx
|
|
6998
|
-
import * as
|
|
7032
|
+
import * as React48 from "react";
|
|
6999
7033
|
import { jsx as jsx73, jsxs as jsxs62 } from "react/jsx-runtime";
|
|
7000
7034
|
var pad = (n) => String(n).padStart(2, "0");
|
|
7001
7035
|
function ClockFace({ value = "09:00", onChange }) {
|
|
@@ -7004,9 +7038,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
7004
7038
|
if (isNaN(m)) m = 0;
|
|
7005
7039
|
const pm = h24 >= 12;
|
|
7006
7040
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
7007
|
-
const [mode2, setMode] =
|
|
7008
|
-
const faceRef =
|
|
7009
|
-
const dragging =
|
|
7041
|
+
const [mode2, setMode] = React48.useState("h");
|
|
7042
|
+
const faceRef = React48.useRef(null);
|
|
7043
|
+
const dragging = React48.useRef(false);
|
|
7010
7044
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
7011
7045
|
const R = 108, NR = 80;
|
|
7012
7046
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -7079,9 +7113,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
7079
7113
|
}
|
|
7080
7114
|
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
|
|
7081
7115
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
7082
|
-
const [open2, setOpen] =
|
|
7083
|
-
const rootRef =
|
|
7084
|
-
const boxRef =
|
|
7116
|
+
const [open2, setOpen] = React48.useState(false);
|
|
7117
|
+
const rootRef = React48.useRef(null);
|
|
7118
|
+
const boxRef = React48.useRef(null);
|
|
7085
7119
|
const disp = () => {
|
|
7086
7120
|
if (!value) return "";
|
|
7087
7121
|
const [h, m] = value.split(":").map(Number);
|
|
@@ -7124,7 +7158,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
7124
7158
|
offset: 6,
|
|
7125
7159
|
width: 262,
|
|
7126
7160
|
role: "presentation",
|
|
7127
|
-
footer: /* @__PURE__ */ jsxs62(
|
|
7161
|
+
footer: /* @__PURE__ */ jsxs62(React48.Fragment, { children: [
|
|
7128
7162
|
/* @__PURE__ */ jsx73(
|
|
7129
7163
|
"button",
|
|
7130
7164
|
{
|
|
@@ -7152,7 +7186,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
7152
7186
|
}
|
|
7153
7187
|
|
|
7154
7188
|
// src/components/forms/Slider.tsx
|
|
7155
|
-
import * as
|
|
7189
|
+
import * as React49 from "react";
|
|
7156
7190
|
import { jsx as jsx74, jsxs as jsxs63 } from "react/jsx-runtime";
|
|
7157
7191
|
function Slider({
|
|
7158
7192
|
label,
|
|
@@ -7170,7 +7204,7 @@ function Slider({
|
|
|
7170
7204
|
...rest
|
|
7171
7205
|
}) {
|
|
7172
7206
|
const fieldId = useFieldId(id);
|
|
7173
|
-
const [dragging, setDragging] =
|
|
7207
|
+
const [dragging, setDragging] = React49.useState(false);
|
|
7174
7208
|
const v = value === void 0 ? min : Number(value);
|
|
7175
7209
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
7176
7210
|
return /* @__PURE__ */ jsxs63("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
|
|
@@ -7204,7 +7238,7 @@ function Slider({
|
|
|
7204
7238
|
}
|
|
7205
7239
|
|
|
7206
7240
|
// src/components/forms/RangeSlider.tsx
|
|
7207
|
-
import * as
|
|
7241
|
+
import * as React50 from "react";
|
|
7208
7242
|
import { jsx as jsx75, jsxs as jsxs64 } from "react/jsx-runtime";
|
|
7209
7243
|
function RangeSlider({
|
|
7210
7244
|
label,
|
|
@@ -7224,9 +7258,9 @@ function RangeSlider({
|
|
|
7224
7258
|
}) {
|
|
7225
7259
|
const fmt2 = format || ((v) => String(v));
|
|
7226
7260
|
const [a, b] = value || [min, max];
|
|
7227
|
-
const [drag, setDrag] =
|
|
7228
|
-
const [focus, setFocus] =
|
|
7229
|
-
const railRef =
|
|
7261
|
+
const [drag, setDrag] = React50.useState(null);
|
|
7262
|
+
const [focus, setFocus] = React50.useState(null);
|
|
7263
|
+
const railRef = React50.useRef(null);
|
|
7230
7264
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
7231
7265
|
const clampPair = (i, v) => {
|
|
7232
7266
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -7241,7 +7275,7 @@ function RangeSlider({
|
|
|
7241
7275
|
const r = railRef.current.getBoundingClientRect();
|
|
7242
7276
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
7243
7277
|
};
|
|
7244
|
-
|
|
7278
|
+
React50.useEffect(() => {
|
|
7245
7279
|
if (drag === null) return;
|
|
7246
7280
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
7247
7281
|
const upH = () => setDrag(null);
|
|
@@ -7322,7 +7356,7 @@ function RangeSlider({
|
|
|
7322
7356
|
/* @__PURE__ */ jsxs64("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
|
|
7323
7357
|
/* @__PURE__ */ jsx75("span", { className: "fd-range-rail", ref: railRef }),
|
|
7324
7358
|
/* @__PURE__ */ jsx75("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
|
|
7325
|
-
marks.map((m) => /* @__PURE__ */ jsxs64(
|
|
7359
|
+
marks.map((m) => /* @__PURE__ */ jsxs64(React50.Fragment, { children: [
|
|
7326
7360
|
/* @__PURE__ */ jsx75("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
|
|
7327
7361
|
m.label ? /* @__PURE__ */ jsx75("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
|
|
7328
7362
|
] }, m.value)),
|
|
@@ -7351,7 +7385,7 @@ function RangeSlider({
|
|
|
7351
7385
|
}
|
|
7352
7386
|
|
|
7353
7387
|
// src/components/forms/Dropzone.tsx
|
|
7354
|
-
import * as
|
|
7388
|
+
import * as React51 from "react";
|
|
7355
7389
|
import { jsx as jsx76, jsxs as jsxs65 } from "react/jsx-runtime";
|
|
7356
7390
|
function Dropzone({
|
|
7357
7391
|
onFiles,
|
|
@@ -7366,8 +7400,8 @@ function Dropzone({
|
|
|
7366
7400
|
className = "",
|
|
7367
7401
|
style
|
|
7368
7402
|
}) {
|
|
7369
|
-
const [over, setOver] =
|
|
7370
|
-
const depth =
|
|
7403
|
+
const [over, setOver] = React51.useState(false);
|
|
7404
|
+
const depth = React51.useRef(0);
|
|
7371
7405
|
const has = (e) => {
|
|
7372
7406
|
const dt = e.dataTransfer;
|
|
7373
7407
|
if (!dt) return false;
|
|
@@ -7429,8 +7463,8 @@ function FilePickButton({
|
|
|
7429
7463
|
className = "",
|
|
7430
7464
|
children
|
|
7431
7465
|
}) {
|
|
7432
|
-
const ref =
|
|
7433
|
-
return /* @__PURE__ */ jsxs65(
|
|
7466
|
+
const ref = React51.useRef(null);
|
|
7467
|
+
return /* @__PURE__ */ jsxs65(React51.Fragment, { children: [
|
|
7434
7468
|
/* @__PURE__ */ jsx76(
|
|
7435
7469
|
"button",
|
|
7436
7470
|
{
|
|
@@ -7463,10 +7497,10 @@ function FilePickButton({
|
|
|
7463
7497
|
}
|
|
7464
7498
|
function useStagedFiles(upload, opts) {
|
|
7465
7499
|
const o = opts || {};
|
|
7466
|
-
const [items, setItems] =
|
|
7467
|
-
const controllers =
|
|
7500
|
+
const [items, setItems] = React51.useState([]);
|
|
7501
|
+
const controllers = React51.useRef({});
|
|
7468
7502
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
7469
|
-
const run =
|
|
7503
|
+
const run = React51.useCallback((att) => {
|
|
7470
7504
|
if (!upload) return;
|
|
7471
7505
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
7472
7506
|
controllers.current[att.id] = ac;
|
|
@@ -7483,14 +7517,14 @@ function useStagedFiles(upload, opts) {
|
|
|
7483
7517
|
delete controllers.current[att.id];
|
|
7484
7518
|
});
|
|
7485
7519
|
}, [upload]);
|
|
7486
|
-
const add =
|
|
7520
|
+
const add = React51.useCallback((files) => {
|
|
7487
7521
|
if (!upload) return [];
|
|
7488
7522
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
7489
7523
|
setItems((list) => list.concat(atts));
|
|
7490
7524
|
atts.forEach(run);
|
|
7491
7525
|
return atts;
|
|
7492
7526
|
}, [upload, run]);
|
|
7493
|
-
const remove =
|
|
7527
|
+
const remove = React51.useCallback((att) => {
|
|
7494
7528
|
const ac = controllers.current[att.id];
|
|
7495
7529
|
if (ac) {
|
|
7496
7530
|
try {
|
|
@@ -7501,10 +7535,10 @@ function useStagedFiles(upload, opts) {
|
|
|
7501
7535
|
}
|
|
7502
7536
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
7503
7537
|
}, []);
|
|
7504
|
-
const retry =
|
|
7538
|
+
const retry = React51.useCallback((att) => {
|
|
7505
7539
|
run(att);
|
|
7506
7540
|
}, [run]);
|
|
7507
|
-
const clear =
|
|
7541
|
+
const clear = React51.useCallback(() => {
|
|
7508
7542
|
Object.values(controllers.current).forEach((ac) => {
|
|
7509
7543
|
try {
|
|
7510
7544
|
ac && ac.abort();
|
|
@@ -7628,7 +7662,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
7628
7662
|
}
|
|
7629
7663
|
|
|
7630
7664
|
// src/components/forms/MarkdownEditor.tsx
|
|
7631
|
-
import * as
|
|
7665
|
+
import * as React52 from "react";
|
|
7632
7666
|
import { jsx as jsx78, jsxs as jsxs67 } from "react/jsx-runtime";
|
|
7633
7667
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
7634
7668
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
@@ -7842,7 +7876,7 @@ function syncDom(root, value) {
|
|
|
7842
7876
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
7843
7877
|
}
|
|
7844
7878
|
var LIST_CONT = RE_LI;
|
|
7845
|
-
var MarkdownEditor =
|
|
7879
|
+
var MarkdownEditor = React52.forwardRef(function MarkdownEditor2({
|
|
7846
7880
|
value = "",
|
|
7847
7881
|
onChange,
|
|
7848
7882
|
onSubmit,
|
|
@@ -7861,10 +7895,10 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
|
|
|
7861
7895
|
className = "",
|
|
7862
7896
|
id
|
|
7863
7897
|
}, ref) {
|
|
7864
|
-
const boxRef =
|
|
7865
|
-
const composing =
|
|
7866
|
-
const pendingCaret =
|
|
7867
|
-
|
|
7898
|
+
const boxRef = React52.useRef(null);
|
|
7899
|
+
const composing = React52.useRef(false);
|
|
7900
|
+
const pendingCaret = React52.useRef(null);
|
|
7901
|
+
React52.useLayoutEffect(() => {
|
|
7868
7902
|
const root = boxRef.current;
|
|
7869
7903
|
if (!root || composing.current) return;
|
|
7870
7904
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -7873,7 +7907,7 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
|
|
|
7873
7907
|
pendingCaret.current = null;
|
|
7874
7908
|
if (active && caret != null) placeCaret(root, caret);
|
|
7875
7909
|
}, [value]);
|
|
7876
|
-
|
|
7910
|
+
React52.useEffect(() => {
|
|
7877
7911
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
7878
7912
|
}, [autoFocus]);
|
|
7879
7913
|
const caretNow = () => {
|
|
@@ -7940,8 +7974,8 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
|
|
|
7940
7974
|
api.replaceRange(from, to, next, from + next.length);
|
|
7941
7975
|
}
|
|
7942
7976
|
};
|
|
7943
|
-
|
|
7944
|
-
const caretAtKeydown =
|
|
7977
|
+
React52.useImperativeHandle(ref, () => api);
|
|
7978
|
+
const caretAtKeydown = React52.useRef(-1);
|
|
7945
7979
|
function detect(text, caret) {
|
|
7946
7980
|
if (!onTrigger) return;
|
|
7947
7981
|
const upto = text.slice(0, caret);
|
|
@@ -8094,7 +8128,7 @@ var MarkdownEditor = React51.forwardRef(function MarkdownEditor2({
|
|
|
8094
8128
|
});
|
|
8095
8129
|
|
|
8096
8130
|
// src/components/forms/CodeEditor.tsx
|
|
8097
|
-
import * as
|
|
8131
|
+
import * as React53 from "react";
|
|
8098
8132
|
import { EditorView, keymap, lineNumbers, placeholder as cmPlaceholder, drawSelection, Decoration } from "@codemirror/view";
|
|
8099
8133
|
import { EditorState, StateEffect, StateField, Compartment } from "@codemirror/state";
|
|
8100
8134
|
import { defaultKeymap, history, historyKeymap, indentMore, indentLess } from "@codemirror/commands";
|
|
@@ -8198,16 +8232,16 @@ function CodeEditor({
|
|
|
8198
8232
|
const fieldId = useFieldId(id);
|
|
8199
8233
|
const descId = fieldId + "-desc";
|
|
8200
8234
|
const liveId = fieldId + "-live";
|
|
8201
|
-
const hostRef =
|
|
8202
|
-
const viewRef =
|
|
8203
|
-
const valueRef =
|
|
8204
|
-
const onChangeRef =
|
|
8235
|
+
const hostRef = React53.useRef(null);
|
|
8236
|
+
const viewRef = React53.useRef(null);
|
|
8237
|
+
const valueRef = React53.useRef(value);
|
|
8238
|
+
const onChangeRef = React53.useRef(onChange);
|
|
8205
8239
|
onChangeRef.current = onChange;
|
|
8206
|
-
const editableCompartment =
|
|
8207
|
-
const attributesCompartment =
|
|
8208
|
-
const errorRef =
|
|
8240
|
+
const editableCompartment = React53.useRef(new Compartment()).current;
|
|
8241
|
+
const attributesCompartment = React53.useRef(new Compartment()).current;
|
|
8242
|
+
const errorRef = React53.useRef(error);
|
|
8209
8243
|
errorRef.current = error;
|
|
8210
|
-
const diagnosticsCountRef =
|
|
8244
|
+
const diagnosticsCountRef = React53.useRef(diagnostics.length);
|
|
8211
8245
|
diagnosticsCountRef.current = diagnostics.length;
|
|
8212
8246
|
function contentAttributes() {
|
|
8213
8247
|
return {
|
|
@@ -8217,7 +8251,7 @@ function CodeEditor({
|
|
|
8217
8251
|
...label ? { "aria-label": label } : {}
|
|
8218
8252
|
};
|
|
8219
8253
|
}
|
|
8220
|
-
|
|
8254
|
+
React53.useEffect(() => {
|
|
8221
8255
|
const host2 = hostRef.current;
|
|
8222
8256
|
if (!host2) return;
|
|
8223
8257
|
const updateListener = EditorView.updateListener.of((update) => {
|
|
@@ -8259,7 +8293,7 @@ function CodeEditor({
|
|
|
8259
8293
|
viewRef.current = null;
|
|
8260
8294
|
};
|
|
8261
8295
|
}, []);
|
|
8262
|
-
|
|
8296
|
+
React53.useEffect(() => {
|
|
8263
8297
|
const view = viewRef.current;
|
|
8264
8298
|
if (!view) return;
|
|
8265
8299
|
const current2 = view.state.doc.toString();
|
|
@@ -8268,12 +8302,12 @@ function CodeEditor({
|
|
|
8268
8302
|
}
|
|
8269
8303
|
valueRef.current = value;
|
|
8270
8304
|
}, [value]);
|
|
8271
|
-
|
|
8305
|
+
React53.useEffect(() => {
|
|
8272
8306
|
const view = viewRef.current;
|
|
8273
8307
|
if (!view) return;
|
|
8274
8308
|
view.dispatch({ effects: editableCompartment.reconfigure(EditorView.editable.of(!disabled)) });
|
|
8275
8309
|
}, [disabled, editableCompartment]);
|
|
8276
|
-
|
|
8310
|
+
React53.useEffect(() => {
|
|
8277
8311
|
const view = viewRef.current;
|
|
8278
8312
|
if (!view) return;
|
|
8279
8313
|
view.dispatch({
|
|
@@ -8331,11 +8365,11 @@ function CodeEditor({
|
|
|
8331
8365
|
}
|
|
8332
8366
|
|
|
8333
8367
|
// src/components/forms/RadioGroup.tsx
|
|
8334
|
-
import * as
|
|
8368
|
+
import * as React54 from "react";
|
|
8335
8369
|
import { jsx as jsx80, jsxs as jsxs69 } from "react/jsx-runtime";
|
|
8336
8370
|
function RadioGroup({ label, labelledBy, options, value, onChange, card = false, disabled = false, name, className = "" }) {
|
|
8337
|
-
const autoName =
|
|
8338
|
-
const labelId =
|
|
8371
|
+
const autoName = React54.useId();
|
|
8372
|
+
const labelId = React54.useId();
|
|
8339
8373
|
return /* @__PURE__ */ jsxs69("div", { role: "radiogroup", "aria-labelledby": labelledBy ?? labelId, "aria-disabled": disabled || void 0, className: ["fd-radiogroup", className].filter(Boolean).join(" "), children: [
|
|
8340
8374
|
labelledBy === void 0 && /* @__PURE__ */ jsx80("span", { id: labelId, className: "fd-radiogroup-label", children: label }),
|
|
8341
8375
|
options.map((o) => /* @__PURE__ */ jsx80(
|
|
@@ -8363,16 +8397,16 @@ function Fieldset({ busy = false, className = "", ...rest }) {
|
|
|
8363
8397
|
}
|
|
8364
8398
|
|
|
8365
8399
|
// src/components/platform/AccountMenu.tsx
|
|
8366
|
-
import * as
|
|
8400
|
+
import * as React56 from "react";
|
|
8367
8401
|
|
|
8368
8402
|
// src/kits/sessionContext.tsx
|
|
8369
|
-
import * as
|
|
8370
|
-
var SessionContext =
|
|
8403
|
+
import * as React55 from "react";
|
|
8404
|
+
var SessionContext = React55.createContext(null);
|
|
8371
8405
|
function SessionProvider({ value, children }) {
|
|
8372
|
-
return
|
|
8406
|
+
return React55.createElement(SessionContext.Provider, { value }, children);
|
|
8373
8407
|
}
|
|
8374
8408
|
function useSessionContext() {
|
|
8375
|
-
const ctx =
|
|
8409
|
+
const ctx = React55.useContext(SessionContext);
|
|
8376
8410
|
if (!ctx) {
|
|
8377
8411
|
throw new Error(
|
|
8378
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."
|
|
@@ -8412,11 +8446,11 @@ function AccountMenu({
|
|
|
8412
8446
|
...rest
|
|
8413
8447
|
}) {
|
|
8414
8448
|
const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
|
|
8415
|
-
const [open2, setOpen] =
|
|
8416
|
-
const [switching, setSwitching] =
|
|
8417
|
-
const [signingOut, setSigningOut] =
|
|
8418
|
-
const [signOutError, setSignOutError] =
|
|
8419
|
-
const ref =
|
|
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);
|
|
8420
8454
|
const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
|
|
8421
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);
|
|
8422
8456
|
const closeMenu = () => {
|
|
@@ -8541,13 +8575,13 @@ function AccountMenu({
|
|
|
8541
8575
|
}
|
|
8542
8576
|
|
|
8543
8577
|
// src/components/platform/AppSwitcher.tsx
|
|
8544
|
-
import * as
|
|
8578
|
+
import * as React57 from "react";
|
|
8545
8579
|
import { jsx as jsx83, jsxs as jsxs71 } from "react/jsx-runtime";
|
|
8546
8580
|
function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
8547
8581
|
const { apps: contextApps } = useSessionContext();
|
|
8548
8582
|
const apps = appsProp ?? contextApps ?? [];
|
|
8549
|
-
const [open2, setOpen] =
|
|
8550
|
-
const anchorRef =
|
|
8583
|
+
const [open2, setOpen] = React57.useState(false);
|
|
8584
|
+
const anchorRef = React57.useRef(null);
|
|
8551
8585
|
if (!apps.length) return null;
|
|
8552
8586
|
const items = apps.map((app) => ({
|
|
8553
8587
|
id: app.key,
|
|
@@ -8561,7 +8595,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
8561
8595
|
window.location.href = app.url;
|
|
8562
8596
|
}
|
|
8563
8597
|
}));
|
|
8564
|
-
return /* @__PURE__ */ jsxs71(
|
|
8598
|
+
return /* @__PURE__ */ jsxs71(React57.Fragment, { children: [
|
|
8565
8599
|
/* @__PURE__ */ jsx83("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx83(
|
|
8566
8600
|
IconButton,
|
|
8567
8601
|
{
|
|
@@ -8590,10 +8624,10 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
8590
8624
|
}
|
|
8591
8625
|
|
|
8592
8626
|
// src/components/platform/AppearanceMenu.tsx
|
|
8593
|
-
import * as
|
|
8627
|
+
import * as React60 from "react";
|
|
8594
8628
|
|
|
8595
8629
|
// src/kits/appearance.ts
|
|
8596
|
-
import * as
|
|
8630
|
+
import * as React58 from "react";
|
|
8597
8631
|
var DEFAULT_STORAGE_KEY = "fd-appearance";
|
|
8598
8632
|
var DEFAULT_PREFS = {
|
|
8599
8633
|
theme: "system",
|
|
@@ -8705,8 +8739,8 @@ function watchAppearance(store, root = document.documentElement) {
|
|
|
8705
8739
|
};
|
|
8706
8740
|
}
|
|
8707
8741
|
function useAppearancePrefs(store) {
|
|
8708
|
-
const prefs =
|
|
8709
|
-
const update =
|
|
8742
|
+
const prefs = React58.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
8743
|
+
const update = React58.useCallback(
|
|
8710
8744
|
(patch) => {
|
|
8711
8745
|
store.write({ ...store.getSnapshot(), ...patch });
|
|
8712
8746
|
},
|
|
@@ -8716,15 +8750,15 @@ function useAppearancePrefs(store) {
|
|
|
8716
8750
|
}
|
|
8717
8751
|
|
|
8718
8752
|
// src/components/platform/AppearanceProvider.tsx
|
|
8719
|
-
import * as
|
|
8753
|
+
import * as React59 from "react";
|
|
8720
8754
|
import { jsx as jsx84 } from "react/jsx-runtime";
|
|
8721
|
-
var AppearanceStoreContext =
|
|
8755
|
+
var AppearanceStoreContext = React59.createContext(null);
|
|
8722
8756
|
function AppearanceProvider({ store, children }) {
|
|
8723
|
-
|
|
8757
|
+
React59.useLayoutEffect(() => watchAppearance(store), [store]);
|
|
8724
8758
|
return /* @__PURE__ */ jsx84(AppearanceStoreContext.Provider, { value: store, children });
|
|
8725
8759
|
}
|
|
8726
8760
|
function useAppearanceStore() {
|
|
8727
|
-
const store =
|
|
8761
|
+
const store = React59.useContext(AppearanceStoreContext);
|
|
8728
8762
|
if (!store) throw new Error("AppearanceMenu and useAppearanceStore must be rendered inside an <AppearanceProvider>.");
|
|
8729
8763
|
return store;
|
|
8730
8764
|
}
|
|
@@ -8744,10 +8778,10 @@ var TEXT_SCALE_OPTIONS = [
|
|
|
8744
8778
|
];
|
|
8745
8779
|
function AppearanceMenu({ className = "" }) {
|
|
8746
8780
|
const [prefs, update] = useAppearancePrefs(useAppearanceStore());
|
|
8747
|
-
const [open2, setOpen] =
|
|
8748
|
-
const anchorRef =
|
|
8781
|
+
const [open2, setOpen] = React60.useState(false);
|
|
8782
|
+
const anchorRef = React60.useRef(null);
|
|
8749
8783
|
const patch = (p) => update(p);
|
|
8750
|
-
return /* @__PURE__ */ jsxs72(
|
|
8784
|
+
return /* @__PURE__ */ jsxs72(React60.Fragment, { children: [
|
|
8751
8785
|
/* @__PURE__ */ jsx85("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx85(
|
|
8752
8786
|
IconButton,
|
|
8753
8787
|
{
|
|
@@ -8816,14 +8850,14 @@ function AppearanceMenu({ className = "" }) {
|
|
|
8816
8850
|
}
|
|
8817
8851
|
|
|
8818
8852
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
8819
|
-
import * as
|
|
8853
|
+
import * as React61 from "react";
|
|
8820
8854
|
import { jsx as jsx86, jsxs as jsxs73 } from "react/jsx-runtime";
|
|
8821
8855
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
8822
8856
|
function Json({ obj }) {
|
|
8823
8857
|
return /* @__PURE__ */ jsx86("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
8824
8858
|
}
|
|
8825
8859
|
function Endpoint({ s, onRequest }) {
|
|
8826
|
-
const [tried, setTried] =
|
|
8860
|
+
const [tried, setTried] = React61.useState(null);
|
|
8827
8861
|
const run = async () => {
|
|
8828
8862
|
setTried("busy");
|
|
8829
8863
|
const t0 = (window.performance || Date).now();
|
|
@@ -8896,10 +8930,10 @@ function ApiSpecBrowser({
|
|
|
8896
8930
|
className = "",
|
|
8897
8931
|
...rest
|
|
8898
8932
|
}) {
|
|
8899
|
-
const [q, setQ] =
|
|
8900
|
-
const [method, setMethod] =
|
|
8901
|
-
const [mod, setMod] =
|
|
8902
|
-
const [listOnly, setListOnly] =
|
|
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);
|
|
8903
8937
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
8904
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())));
|
|
8905
8939
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
@@ -8978,7 +9012,7 @@ function ApiSpecBrowser({
|
|
|
8978
9012
|
}
|
|
8979
9013
|
|
|
8980
9014
|
// src/components/platform/ProfilePage.tsx
|
|
8981
|
-
import * as
|
|
9015
|
+
import * as React62 from "react";
|
|
8982
9016
|
import { jsx as jsx87, jsxs as jsxs74 } from "react/jsx-runtime";
|
|
8983
9017
|
function fieldInitialValue(field, user) {
|
|
8984
9018
|
if (field.value) return field.value(user);
|
|
@@ -9014,21 +9048,21 @@ function ProfilePage({
|
|
|
9014
9048
|
}) {
|
|
9015
9049
|
const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
|
|
9016
9050
|
const user = userProp || sessionUser;
|
|
9017
|
-
const initialFieldValues =
|
|
9051
|
+
const initialFieldValues = React62.useMemo(() => {
|
|
9018
9052
|
const values2 = {};
|
|
9019
9053
|
for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
|
|
9020
9054
|
return values2;
|
|
9021
9055
|
}, [user.id, fields]);
|
|
9022
|
-
const initialNotify =
|
|
9056
|
+
const initialNotify = React62.useMemo(() => {
|
|
9023
9057
|
const values2 = {};
|
|
9024
9058
|
for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
|
|
9025
9059
|
return values2;
|
|
9026
9060
|
}, [user.id, notifications]);
|
|
9027
|
-
const [values, setValues] =
|
|
9028
|
-
const [notify, setNotify] =
|
|
9029
|
-
const [saving, setSaving] =
|
|
9030
|
-
const [saved, setSaved] =
|
|
9031
|
-
const [prevUserId, setPrevUserId] =
|
|
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);
|
|
9032
9066
|
if (user.id !== prevUserId) {
|
|
9033
9067
|
setPrevUserId(user.id);
|
|
9034
9068
|
setValues(initialFieldValues);
|
|
@@ -9216,7 +9250,7 @@ function ProfilePage({
|
|
|
9216
9250
|
}
|
|
9217
9251
|
|
|
9218
9252
|
// src/components/platform/SessionScreen.tsx
|
|
9219
|
-
import * as
|
|
9253
|
+
import * as React63 from "react";
|
|
9220
9254
|
import { Fragment as Fragment22, jsx as jsx88, jsxs as jsxs75 } from "react/jsx-runtime";
|
|
9221
9255
|
var COPY = {
|
|
9222
9256
|
"signing-in": { busy: "Signing you in\u2026" },
|
|
@@ -9230,13 +9264,13 @@ function SessionScreen({ kind, error, onRetry, productName }) {
|
|
|
9230
9264
|
const copy = COPY[kind];
|
|
9231
9265
|
const busyMessage = "busy" in copy ? copy.busy : null;
|
|
9232
9266
|
const failureTitle = "failure" in copy ? copy.failure : null;
|
|
9233
|
-
const [announced, setAnnounced] =
|
|
9234
|
-
|
|
9267
|
+
const [announced, setAnnounced] = React63.useState("");
|
|
9268
|
+
React63.useEffect(() => {
|
|
9235
9269
|
setAnnounced(busyMessage ?? "");
|
|
9236
9270
|
}, [busyMessage]);
|
|
9237
|
-
const titleRef =
|
|
9271
|
+
const titleRef = React63.useRef(null);
|
|
9238
9272
|
const failed = failureTitle !== null;
|
|
9239
|
-
|
|
9273
|
+
React63.useEffect(() => {
|
|
9240
9274
|
titleRef.current?.focus({ preventScroll: true });
|
|
9241
9275
|
}, [failed]);
|
|
9242
9276
|
return /* @__PURE__ */ jsx88("main", { className: "fd-session-screen", children: /* @__PURE__ */ jsxs75("div", { className: "fd-session-screen-inner", children: [
|
|
@@ -9259,10 +9293,10 @@ function SessionScreen({ kind, error, onRetry, productName }) {
|
|
|
9259
9293
|
}
|
|
9260
9294
|
|
|
9261
9295
|
// src/components/platform/RoadmapTimeline.tsx
|
|
9262
|
-
import * as
|
|
9296
|
+
import * as React66 from "react";
|
|
9263
9297
|
|
|
9264
9298
|
// src/kits/session.ts
|
|
9265
|
-
import * as
|
|
9299
|
+
import * as React64 from "react";
|
|
9266
9300
|
var PERMISSION_CATALOG = [
|
|
9267
9301
|
{ group: "Plans", items: [
|
|
9268
9302
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -10829,8 +10863,8 @@ function roadmap(overrides) {
|
|
|
10829
10863
|
};
|
|
10830
10864
|
}
|
|
10831
10865
|
function useSession() {
|
|
10832
|
-
const [s, setS] =
|
|
10833
|
-
|
|
10866
|
+
const [s, setS] = React64.useState(getSession);
|
|
10867
|
+
React64.useEffect(() => subscribe(setS), []);
|
|
10834
10868
|
return s;
|
|
10835
10869
|
}
|
|
10836
10870
|
var SessionKit = {
|
|
@@ -10863,7 +10897,7 @@ var SessionKit = {
|
|
|
10863
10897
|
};
|
|
10864
10898
|
function DemoSessionProvider({ children }) {
|
|
10865
10899
|
const session = useSession();
|
|
10866
|
-
const value =
|
|
10900
|
+
const value = React64.useMemo(
|
|
10867
10901
|
() => ({
|
|
10868
10902
|
user: session.user,
|
|
10869
10903
|
roles: session.roles,
|
|
@@ -10879,11 +10913,11 @@ function DemoSessionProvider({ children }) {
|
|
|
10879
10913
|
}),
|
|
10880
10914
|
[session]
|
|
10881
10915
|
);
|
|
10882
|
-
return
|
|
10916
|
+
return React64.createElement(SessionProvider, { value }, children);
|
|
10883
10917
|
}
|
|
10884
10918
|
|
|
10885
10919
|
// src/kits/runtime.ts
|
|
10886
|
-
import * as
|
|
10920
|
+
import * as React65 from "react";
|
|
10887
10921
|
var WIRED_ENDPOINTS = [
|
|
10888
10922
|
// Nothing yet. Every id below would come from a real service:
|
|
10889
10923
|
// "plan.get", "placements.list", …
|
|
@@ -11054,8 +11088,8 @@ var RuntimeKit = {
|
|
|
11054
11088
|
};
|
|
11055
11089
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
11056
11090
|
function useRuntimeMode() {
|
|
11057
|
-
const [m, setM] =
|
|
11058
|
-
|
|
11091
|
+
const [m, setM] = React65.useState(RuntimeKit.getMode());
|
|
11092
|
+
React65.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
11059
11093
|
return m;
|
|
11060
11094
|
}
|
|
11061
11095
|
function useFeatureStatus(key) {
|
|
@@ -11138,12 +11172,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
11138
11172
|
}
|
|
11139
11173
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
11140
11174
|
const session = SessionKit.useSession();
|
|
11141
|
-
const [project, setProject] =
|
|
11142
|
-
const [q, setQ] =
|
|
11143
|
-
const scrollRef =
|
|
11144
|
-
const nowRef =
|
|
11145
|
-
const rm =
|
|
11146
|
-
const byKey =
|
|
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(() => {
|
|
11147
11181
|
const m = {};
|
|
11148
11182
|
rm.items.forEach((i) => {
|
|
11149
11183
|
m[i.key] = i;
|
|
@@ -11152,7 +11186,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
11152
11186
|
}, [rm]);
|
|
11153
11187
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
11154
11188
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
11155
|
-
|
|
11189
|
+
React66.useEffect(() => {
|
|
11156
11190
|
let raf1 = 0, raf2 = 0;
|
|
11157
11191
|
const place = () => {
|
|
11158
11192
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -11226,7 +11260,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
11226
11260
|
lastPhase = item.phase;
|
|
11227
11261
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
11228
11262
|
const isBoundary = n === firstPending;
|
|
11229
|
-
return /* @__PURE__ */ jsxs76(
|
|
11263
|
+
return /* @__PURE__ */ jsxs76(React66.Fragment, { children: [
|
|
11230
11264
|
showPhase ? /* @__PURE__ */ jsxs76("div", { className: "fd-rm-era", children: [
|
|
11231
11265
|
/* @__PURE__ */ jsxs76("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
11232
11266
|
/* @__PURE__ */ jsx89("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
@@ -11270,7 +11304,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
11270
11304
|
}
|
|
11271
11305
|
|
|
11272
11306
|
// src/components/platform/ComingSoon.tsx
|
|
11273
|
-
import * as
|
|
11307
|
+
import * as React67 from "react";
|
|
11274
11308
|
import { createPortal as createPortal6 } from "react-dom";
|
|
11275
11309
|
import { Fragment as Fragment24, jsx as jsx90, jsxs as jsxs77 } from "react/jsx-runtime";
|
|
11276
11310
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
@@ -11288,8 +11322,8 @@ function writeBypassed(list) {
|
|
|
11288
11322
|
}
|
|
11289
11323
|
}
|
|
11290
11324
|
function useBypass(key) {
|
|
11291
|
-
const [on, setOn] =
|
|
11292
|
-
|
|
11325
|
+
const [on, setOn] = React67.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
11326
|
+
React67.useEffect(() => {
|
|
11293
11327
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
11294
11328
|
}, [key]);
|
|
11295
11329
|
const set = (next) => {
|
|
@@ -11336,9 +11370,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
|
|
|
11336
11370
|
] });
|
|
11337
11371
|
}
|
|
11338
11372
|
function useHoverCard(open2) {
|
|
11339
|
-
const anchor =
|
|
11340
|
-
const [pos, setPos] =
|
|
11341
|
-
|
|
11373
|
+
const anchor = React67.useRef(null);
|
|
11374
|
+
const [pos, setPos] = React67.useState(null);
|
|
11375
|
+
React67.useLayoutEffect(() => {
|
|
11342
11376
|
if (!open2 || !anchor.current) {
|
|
11343
11377
|
setPos(null);
|
|
11344
11378
|
return;
|
|
@@ -11465,12 +11499,12 @@ function ComingSoon({
|
|
|
11465
11499
|
] });
|
|
11466
11500
|
}
|
|
11467
11501
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
11468
|
-
const [open2, setOpen] =
|
|
11502
|
+
const [open2, setOpen] = React67.useState(false);
|
|
11469
11503
|
const [anchor, pos] = useHoverCard(open2);
|
|
11470
|
-
const hoverCardRef =
|
|
11504
|
+
const hoverCardRef = React67.useRef(null);
|
|
11471
11505
|
const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
|
|
11472
11506
|
const zIndex = useLayerZIndex(hoverLayer);
|
|
11473
|
-
const close2 =
|
|
11507
|
+
const close2 = React67.useRef(null);
|
|
11474
11508
|
const show = () => {
|
|
11475
11509
|
if (close2.current) {
|
|
11476
11510
|
clearTimeout(close2.current);
|
|
@@ -11486,7 +11520,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
11486
11520
|
setOpen(false);
|
|
11487
11521
|
}, 140);
|
|
11488
11522
|
};
|
|
11489
|
-
|
|
11523
|
+
React67.useEffect(() => () => {
|
|
11490
11524
|
if (close2.current) clearTimeout(close2.current);
|
|
11491
11525
|
}, []);
|
|
11492
11526
|
return /* @__PURE__ */ jsxs77(
|
|
@@ -11938,7 +11972,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11938
11972
|
}
|
|
11939
11973
|
|
|
11940
11974
|
// src/components/planner/MixGap.tsx
|
|
11941
|
-
import * as
|
|
11975
|
+
import * as React68 from "react";
|
|
11942
11976
|
import { Fragment as Fragment26, jsx as jsx95, jsxs as jsxs82 } from "react/jsx-runtime";
|
|
11943
11977
|
var MIX_GAP_LAYOUT = {
|
|
11944
11978
|
trackHeight: 30,
|
|
@@ -11953,7 +11987,7 @@ function mixGapOffset(value, max) {
|
|
|
11953
11987
|
}
|
|
11954
11988
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
11955
11989
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
11956
|
-
const [hover, setHover] =
|
|
11990
|
+
const [hover, setHover] = React68.useState(null);
|
|
11957
11991
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
11958
11992
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
11959
11993
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
@@ -12096,7 +12130,7 @@ function ChannelContribution({
|
|
|
12096
12130
|
}
|
|
12097
12131
|
|
|
12098
12132
|
// src/components/planner/BudgetReallocator.tsx
|
|
12099
|
-
import * as
|
|
12133
|
+
import * as React69 from "react";
|
|
12100
12134
|
import { Fragment as Fragment27, jsx as jsx97, jsxs as jsxs84 } from "react/jsx-runtime";
|
|
12101
12135
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
12102
12136
|
function BudgetReallocator({
|
|
@@ -12112,8 +12146,8 @@ function BudgetReallocator({
|
|
|
12112
12146
|
onCancel,
|
|
12113
12147
|
className = ""
|
|
12114
12148
|
}) {
|
|
12115
|
-
const [draft, setDraft] =
|
|
12116
|
-
|
|
12149
|
+
const [draft, setDraft] = React69.useState(spend);
|
|
12150
|
+
React69.useEffect(() => setDraft(spend), [spend]);
|
|
12117
12151
|
const dirty = draft !== spend;
|
|
12118
12152
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
12119
12153
|
const nextBand = bandFor(nextCrp);
|
|
@@ -12128,10 +12162,10 @@ function BudgetReallocator({
|
|
|
12128
12162
|
setDraft(spend);
|
|
12129
12163
|
if (onCancel) onCancel();
|
|
12130
12164
|
};
|
|
12131
|
-
const trackRef =
|
|
12132
|
-
const chipRef =
|
|
12133
|
-
const [chipLeft, setChipLeft] =
|
|
12134
|
-
|
|
12165
|
+
const trackRef = React69.useRef(null);
|
|
12166
|
+
const chipRef = React69.useRef(null);
|
|
12167
|
+
const [chipLeft, setChipLeft] = React69.useState(null);
|
|
12168
|
+
React69.useLayoutEffect(() => {
|
|
12135
12169
|
const track = trackRef.current;
|
|
12136
12170
|
if (!dirty || !track) {
|
|
12137
12171
|
setChipLeft(null);
|
|
@@ -12319,7 +12353,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
|
|
|
12319
12353
|
}
|
|
12320
12354
|
|
|
12321
12355
|
// src/components/planner/PreferenceMeter.tsx
|
|
12322
|
-
import * as
|
|
12356
|
+
import * as React70 from "react";
|
|
12323
12357
|
import { jsx as jsx100, jsxs as jsxs87 } from "react/jsx-runtime";
|
|
12324
12358
|
function preferenceScore(criteria) {
|
|
12325
12359
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
@@ -12349,7 +12383,7 @@ function PreferenceMeter({
|
|
|
12349
12383
|
className = ""
|
|
12350
12384
|
}) {
|
|
12351
12385
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
12352
|
-
const segments =
|
|
12386
|
+
const segments = React70.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
12353
12387
|
return /* @__PURE__ */ jsx100(
|
|
12354
12388
|
ScoreMeter,
|
|
12355
12389
|
{
|
|
@@ -12388,17 +12422,13 @@ function PreferenceMeter({
|
|
|
12388
12422
|
}
|
|
12389
12423
|
|
|
12390
12424
|
// src/components/chat/AgentChatPanel.tsx
|
|
12391
|
-
import * as
|
|
12425
|
+
import * as React77 from "react";
|
|
12392
12426
|
|
|
12393
12427
|
// src/components/chat/chatEngine.ts
|
|
12394
|
-
import * as
|
|
12395
|
-
|
|
12396
|
-
|
|
12397
|
-
|
|
12398
|
-
var STORAGE_PREFIX = "fdchat:job:";
|
|
12399
|
-
var seq = 0;
|
|
12400
|
-
var uid = (p) => p + "_" + ++seq + "_" + Date.now().toString(36);
|
|
12401
|
-
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
12428
|
+
import * as React72 from "react";
|
|
12429
|
+
|
|
12430
|
+
// src/components/chat/chatStore.ts
|
|
12431
|
+
import * as React71 from "react";
|
|
12402
12432
|
var safeStore = {
|
|
12403
12433
|
get(k) {
|
|
12404
12434
|
try {
|
|
@@ -12420,6 +12450,38 @@ var safeStore = {
|
|
|
12420
12450
|
}
|
|
12421
12451
|
}
|
|
12422
12452
|
};
|
|
12453
|
+
var part = (v) => encodeURIComponent(v);
|
|
12454
|
+
var jobKey = (threadId) => "fdchat:job:" + part(threadId);
|
|
12455
|
+
var draftKey = (owner, contextType, contextId) => "fdchat:draft:" + [owner, contextType, contextId].map(part).join(":");
|
|
12456
|
+
function useChatDraft(owner, contextType, contextId, store = safeStore) {
|
|
12457
|
+
if (owner === "") throw new Error("useChatDraft: draftOwner is an empty string; pass the signed-in user's id, or null for no owner.");
|
|
12458
|
+
const key = owner === null ? null : draftKey(owner, contextType, contextId);
|
|
12459
|
+
const read2 = (k) => k ? store.get(k) || "" : "";
|
|
12460
|
+
const [state, setState] = React71.useState(() => ({ key, text: read2(key) }));
|
|
12461
|
+
let current2 = state;
|
|
12462
|
+
if (state.key !== key) {
|
|
12463
|
+
current2 = { key, text: read2(key) };
|
|
12464
|
+
setState(current2);
|
|
12465
|
+
}
|
|
12466
|
+
const setText = React71.useCallback((text) => {
|
|
12467
|
+
if (key) {
|
|
12468
|
+
if (text) {
|
|
12469
|
+
store.set(key, text);
|
|
12470
|
+
if (store.get(key) !== text) store.del(key);
|
|
12471
|
+
} else store.del(key);
|
|
12472
|
+
}
|
|
12473
|
+
setState({ key, text });
|
|
12474
|
+
}, [key, store]);
|
|
12475
|
+
return [current2.text, setText];
|
|
12476
|
+
}
|
|
12477
|
+
|
|
12478
|
+
// src/components/chat/chatEngine.ts
|
|
12479
|
+
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
12480
|
+
var JOB_PENDING = ["queued", "running"];
|
|
12481
|
+
var JOB_SUCCESS = ["completed", "recovered"];
|
|
12482
|
+
var seq = 0;
|
|
12483
|
+
var uid = (p) => p + "_" + ++seq + "_" + Date.now().toString(36);
|
|
12484
|
+
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
12423
12485
|
var isSystemMessage = (m) => !!m && (m.role === "system" || m.metadata != null && m.metadata.type === "system");
|
|
12424
12486
|
var visibleMessages = (list) => (list || []).filter((m) => !isSystemMessage(m));
|
|
12425
12487
|
function jobBucket(status) {
|
|
@@ -12460,33 +12522,33 @@ function useChatEngine(opts) {
|
|
|
12460
12522
|
onClear,
|
|
12461
12523
|
onFeedback
|
|
12462
12524
|
} = opts || {};
|
|
12463
|
-
const [status, setStatus] =
|
|
12464
|
-
const [threadId, setThreadId] =
|
|
12465
|
-
const [messages, setMessages] =
|
|
12466
|
-
const [queue, setQueue] =
|
|
12467
|
-
const [fatal, setFatal] =
|
|
12468
|
-
const [busy, setBusy] =
|
|
12469
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
12470
|
-
const listRef =
|
|
12471
|
-
const queueRef =
|
|
12472
|
-
const busyRef =
|
|
12473
|
-
const loadedRef =
|
|
12474
|
-
const stoppedRef =
|
|
12475
|
-
const abortRef =
|
|
12476
|
-
const serverCount =
|
|
12477
|
-
const serverIds =
|
|
12478
|
-
const liveTurn =
|
|
12479
|
-
const lastTurnOwn =
|
|
12480
|
-
const retired =
|
|
12481
|
-
const threadRef =
|
|
12482
|
-
const mounted =
|
|
12483
|
-
|
|
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(() => {
|
|
12484
12546
|
mounted.current = true;
|
|
12485
12547
|
return () => {
|
|
12486
12548
|
mounted.current = false;
|
|
12487
12549
|
};
|
|
12488
12550
|
}, []);
|
|
12489
|
-
const describeWaitingRef =
|
|
12551
|
+
const describeWaitingRef = React72.useRef(describeWaiting);
|
|
12490
12552
|
describeWaitingRef.current = describeWaiting;
|
|
12491
12553
|
const commit = (next) => {
|
|
12492
12554
|
const derived = withWaiting(next, (pending) => describeWaitingRef.current(pending));
|
|
@@ -12505,7 +12567,7 @@ function useChatEngine(opts) {
|
|
|
12505
12567
|
}
|
|
12506
12568
|
return false;
|
|
12507
12569
|
};
|
|
12508
|
-
const loadThread =
|
|
12570
|
+
const loadThread = React72.useCallback(async (id) => {
|
|
12509
12571
|
const data = await apiAdapter.getThread(id);
|
|
12510
12572
|
const list = [...data && data.messages || []];
|
|
12511
12573
|
serverCount.current = list.length;
|
|
@@ -12545,7 +12607,7 @@ function useChatEngine(opts) {
|
|
|
12545
12607
|
packet: progress.packet ?? holder.packet
|
|
12546
12608
|
});
|
|
12547
12609
|
}
|
|
12548
|
-
|
|
12610
|
+
React72.useEffect(() => {
|
|
12549
12611
|
if (!apiAdapter) {
|
|
12550
12612
|
setStatus("idle");
|
|
12551
12613
|
setFatal(null);
|
|
@@ -12592,7 +12654,7 @@ function useChatEngine(opts) {
|
|
|
12592
12654
|
setStatus("ready");
|
|
12593
12655
|
loadedRef.current = true;
|
|
12594
12656
|
onThreadReady && onThreadReady(id);
|
|
12595
|
-
const stored = store.get(
|
|
12657
|
+
const stored = store.get(jobKey(id));
|
|
12596
12658
|
const last = [...visibleMessages(listRef.current)].reverse().find((m) => m.role === "assistant");
|
|
12597
12659
|
if (stored) resumeJob(stored);
|
|
12598
12660
|
else if (last && last.working && last.jobId) resumeJob(last.jobId, last.id);
|
|
@@ -12611,7 +12673,7 @@ function useChatEngine(opts) {
|
|
|
12611
12673
|
};
|
|
12612
12674
|
}, [apiAdapter, contextType, contextId, threadIdProp]);
|
|
12613
12675
|
async function pollJob(jobId, placeholderId) {
|
|
12614
|
-
store.set(
|
|
12676
|
+
store.set(jobKey(threadRef.current), jobId);
|
|
12615
12677
|
const deadline = Date.now() + pendingTimeoutMs;
|
|
12616
12678
|
while (true) {
|
|
12617
12679
|
if (stoppedRef.current) break;
|
|
@@ -12659,7 +12721,7 @@ function useChatEngine(opts) {
|
|
|
12659
12721
|
}
|
|
12660
12722
|
}
|
|
12661
12723
|
async function finishJob(_jobId, _job) {
|
|
12662
|
-
store.del(
|
|
12724
|
+
store.del(jobKey(threadRef.current));
|
|
12663
12725
|
try {
|
|
12664
12726
|
const list = await loadThread(threadRef.current);
|
|
12665
12727
|
const withPacket = [...list].reverse().find((m) => m && m.packet);
|
|
@@ -12669,7 +12731,7 @@ function useChatEngine(opts) {
|
|
|
12669
12731
|
}
|
|
12670
12732
|
}
|
|
12671
12733
|
function recordFailure(placeholderId, code, retryable, job) {
|
|
12672
|
-
store.del(
|
|
12734
|
+
store.del(jobKey(threadRef.current));
|
|
12673
12735
|
if (!listRef.current.some((m) => m.id === placeholderId)) {
|
|
12674
12736
|
push({ id: placeholderId, role: "assistant", text: null });
|
|
12675
12737
|
}
|
|
@@ -12777,7 +12839,7 @@ function useChatEngine(opts) {
|
|
|
12777
12839
|
await dispatchTurn(turn);
|
|
12778
12840
|
}
|
|
12779
12841
|
}
|
|
12780
|
-
const send =
|
|
12842
|
+
const send = React72.useCallback((text, attachments) => {
|
|
12781
12843
|
const body = (text || "").trim();
|
|
12782
12844
|
if (!body && !(attachments && attachments.length)) return;
|
|
12783
12845
|
if (status === "disconnected") return;
|
|
@@ -12787,7 +12849,7 @@ function useChatEngine(opts) {
|
|
|
12787
12849
|
stoppedRef.current = false;
|
|
12788
12850
|
drain();
|
|
12789
12851
|
}, [status]);
|
|
12790
|
-
const stop =
|
|
12852
|
+
const stop = React72.useCallback(() => {
|
|
12791
12853
|
stoppedRef.current = true;
|
|
12792
12854
|
const ac = abortRef.current;
|
|
12793
12855
|
if (ac) {
|
|
@@ -12803,14 +12865,14 @@ function useChatEngine(opts) {
|
|
|
12803
12865
|
Promise.resolve(apiAdapter.cancelJob(holder.jobId)).catch(() => {
|
|
12804
12866
|
});
|
|
12805
12867
|
}
|
|
12806
|
-
store.del(
|
|
12868
|
+
store.del(jobKey(threadRef.current));
|
|
12807
12869
|
}
|
|
12808
12870
|
}, [apiAdapter]);
|
|
12809
|
-
const removeQueued =
|
|
12871
|
+
const removeQueued = React72.useCallback((id) => {
|
|
12810
12872
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
12811
12873
|
setQueue(queueRef.current.slice());
|
|
12812
12874
|
}, []);
|
|
12813
|
-
const retry =
|
|
12875
|
+
const retry = React72.useCallback(() => {
|
|
12814
12876
|
const list = listRef.current;
|
|
12815
12877
|
let at = -1;
|
|
12816
12878
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -12827,19 +12889,19 @@ function useChatEngine(opts) {
|
|
|
12827
12889
|
setQueue(queueRef.current.slice());
|
|
12828
12890
|
drain();
|
|
12829
12891
|
}, []);
|
|
12830
|
-
const clear =
|
|
12892
|
+
const clear = React72.useCallback(() => {
|
|
12831
12893
|
commit([]);
|
|
12832
12894
|
serverCount.current = 0;
|
|
12833
12895
|
queueRef.current = [];
|
|
12834
12896
|
setQueue([]);
|
|
12835
12897
|
onClear && onClear();
|
|
12836
12898
|
}, [onClear]);
|
|
12837
|
-
const setFeedback =
|
|
12899
|
+
const setFeedback = React72.useCallback((id, value) => {
|
|
12838
12900
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
12839
12901
|
const msg = listRef.current.find((m) => m.id === id);
|
|
12840
12902
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
12841
12903
|
}, [onFeedback]);
|
|
12842
|
-
const reload =
|
|
12904
|
+
const reload = React72.useCallback(async () => {
|
|
12843
12905
|
if (!threadRef.current) return;
|
|
12844
12906
|
setStatus("loading");
|
|
12845
12907
|
try {
|
|
@@ -12877,10 +12939,10 @@ var ChatKit = {
|
|
|
12877
12939
|
};
|
|
12878
12940
|
|
|
12879
12941
|
// src/components/chat/ChatTranscript.tsx
|
|
12880
|
-
import * as
|
|
12942
|
+
import * as React74 from "react";
|
|
12881
12943
|
|
|
12882
12944
|
// src/components/chat/ChatTurn.tsx
|
|
12883
|
-
import * as
|
|
12945
|
+
import * as React73 from "react";
|
|
12884
12946
|
import { jsx as jsx101, jsxs as jsxs88 } from "react/jsx-runtime";
|
|
12885
12947
|
function JsonView({ value }) {
|
|
12886
12948
|
let text;
|
|
@@ -12917,7 +12979,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
|
12917
12979
|
] });
|
|
12918
12980
|
}
|
|
12919
12981
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
12920
|
-
const [open2, setOpen] =
|
|
12982
|
+
const [open2, setOpen] = React73.useState(defaultOpen);
|
|
12921
12983
|
if (!text) return null;
|
|
12922
12984
|
return /* @__PURE__ */ jsxs88("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
|
|
12923
12985
|
/* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
@@ -12934,7 +12996,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
|
12934
12996
|
] });
|
|
12935
12997
|
}
|
|
12936
12998
|
function Citations({ items = [], onOpen }) {
|
|
12937
|
-
const [open2, setOpen] =
|
|
12999
|
+
const [open2, setOpen] = React73.useState(false);
|
|
12938
13000
|
if (!items.length) return null;
|
|
12939
13001
|
return /* @__PURE__ */ jsxs88("div", { className: "fdc-cites", children: [
|
|
12940
13002
|
/* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
@@ -12960,7 +13022,7 @@ function clampText(text, max) {
|
|
|
12960
13022
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
12961
13023
|
}
|
|
12962
13024
|
function MessageBody({ message: m, ctx }) {
|
|
12963
|
-
const [expanded, setExpanded] =
|
|
13025
|
+
const [expanded, setExpanded] = React73.useState(false);
|
|
12964
13026
|
const isUser = m.role === "user";
|
|
12965
13027
|
const raw = m.text || "";
|
|
12966
13028
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
@@ -13039,7 +13101,7 @@ function RunActions({ group, ctx }) {
|
|
|
13039
13101
|
] }),
|
|
13040
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,
|
|
13041
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,
|
|
13042
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs88(
|
|
13104
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs88(React73.Fragment, { children: [
|
|
13043
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" }) }),
|
|
13044
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" }) })
|
|
13045
13107
|
] }) : null,
|
|
@@ -13134,10 +13196,10 @@ function ChatTranscript({
|
|
|
13134
13196
|
renderEmpty,
|
|
13135
13197
|
className = ""
|
|
13136
13198
|
}) {
|
|
13137
|
-
const scroller =
|
|
13138
|
-
const stick =
|
|
13139
|
-
const [pill, setPill] =
|
|
13140
|
-
const seen =
|
|
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);
|
|
13141
13203
|
const toBottom = (smooth) => {
|
|
13142
13204
|
const el = scroller.current;
|
|
13143
13205
|
if (!el) return;
|
|
@@ -13156,7 +13218,7 @@ function ChatTranscript({
|
|
|
13156
13218
|
seen.current = messages.length;
|
|
13157
13219
|
}
|
|
13158
13220
|
};
|
|
13159
|
-
|
|
13221
|
+
React74.useLayoutEffect(() => {
|
|
13160
13222
|
const el = scroller.current;
|
|
13161
13223
|
if (!el) return;
|
|
13162
13224
|
if (stick.current) {
|
|
@@ -13164,7 +13226,7 @@ function ChatTranscript({
|
|
|
13164
13226
|
seen.current = messages.length;
|
|
13165
13227
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
13166
13228
|
}, [messages]);
|
|
13167
|
-
|
|
13229
|
+
React74.useEffect(() => {
|
|
13168
13230
|
const el = scroller.current;
|
|
13169
13231
|
const inner = el && el.firstChild;
|
|
13170
13232
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -13174,7 +13236,7 @@ function ChatTranscript({
|
|
|
13174
13236
|
ro.observe(inner);
|
|
13175
13237
|
return () => ro.disconnect();
|
|
13176
13238
|
}, []);
|
|
13177
|
-
const groups =
|
|
13239
|
+
const groups = React74.useMemo(() => groupMessages(messages), [messages]);
|
|
13178
13240
|
const empty = !messages.length && status === "ready";
|
|
13179
13241
|
return /* @__PURE__ */ jsxs89("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
13180
13242
|
/* @__PURE__ */ jsxs89("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
@@ -13198,7 +13260,7 @@ function ChatTranscript({
|
|
|
13198
13260
|
const prev = groups[i - 1];
|
|
13199
13261
|
const k = dayKey(g.messages[0].timestamp);
|
|
13200
13262
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
13201
|
-
return /* @__PURE__ */ jsxs89(
|
|
13263
|
+
return /* @__PURE__ */ jsxs89(React74.Fragment, { children: [
|
|
13202
13264
|
showDay ? /* @__PURE__ */ jsx102("div", { className: "fdc-day", children: /* @__PURE__ */ jsx102("span", { children: dayLabel(k) }) }) : null,
|
|
13203
13265
|
/* @__PURE__ */ jsx102(ChatTurn, { group: g, ctx })
|
|
13204
13266
|
] }, g.key || i);
|
|
@@ -13215,7 +13277,7 @@ function ChatTranscript({
|
|
|
13215
13277
|
var TranscriptKit = { groupMessages };
|
|
13216
13278
|
|
|
13217
13279
|
// src/components/chat/ChatComposer.tsx
|
|
13218
|
-
import * as
|
|
13280
|
+
import * as React75 from "react";
|
|
13219
13281
|
import { jsx as jsx103, jsxs as jsxs90 } from "react/jsx-runtime";
|
|
13220
13282
|
function ChatComposer({
|
|
13221
13283
|
onSubmit,
|
|
@@ -13243,17 +13305,17 @@ function ChatComposer({
|
|
|
13243
13305
|
onReject,
|
|
13244
13306
|
onOpenAttachment
|
|
13245
13307
|
}) {
|
|
13246
|
-
const [text, setText] =
|
|
13247
|
-
const [trigger, setTrigger] =
|
|
13248
|
-
const [mentionItems, setMentionItems] =
|
|
13249
|
-
const [listening, setListening] =
|
|
13250
|
-
const [notice, setNotice] =
|
|
13251
|
-
const editor =
|
|
13252
|
-
const wrap =
|
|
13253
|
-
const stopVoice =
|
|
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);
|
|
13254
13316
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
13255
13317
|
} });
|
|
13256
|
-
|
|
13318
|
+
React75.useEffect(() => {
|
|
13257
13319
|
if (draft != null && draft !== text) setText(draft);
|
|
13258
13320
|
}, [draft]);
|
|
13259
13321
|
const change = (v) => {
|
|
@@ -13289,7 +13351,7 @@ function ChatComposer({
|
|
|
13289
13351
|
e.preventDefault();
|
|
13290
13352
|
staged.add(found.files);
|
|
13291
13353
|
};
|
|
13292
|
-
|
|
13354
|
+
React75.useEffect(() => {
|
|
13293
13355
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
13294
13356
|
setMentionItems([]);
|
|
13295
13357
|
return;
|
|
@@ -13307,7 +13369,7 @@ function ChatComposer({
|
|
|
13307
13369
|
const q = (trigger.query || "").toLowerCase();
|
|
13308
13370
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
13309
13371
|
}, [trigger, mentionSources]);
|
|
13310
|
-
const slashItems =
|
|
13372
|
+
const slashItems = React75.useMemo(() => {
|
|
13311
13373
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
13312
13374
|
const q = (trigger.query || "").toLowerCase();
|
|
13313
13375
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -13477,12 +13539,12 @@ function ChatComposer({
|
|
|
13477
13539
|
}
|
|
13478
13540
|
|
|
13479
13541
|
// src/components/chat/ChatSessionBar.tsx
|
|
13480
|
-
import * as
|
|
13542
|
+
import * as React76 from "react";
|
|
13481
13543
|
import { jsx as jsx104, jsxs as jsxs91 } from "react/jsx-runtime";
|
|
13482
13544
|
var compact2 = meterFormats.compact;
|
|
13483
13545
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
13484
|
-
const [open2, setOpen] =
|
|
13485
|
-
const anchor =
|
|
13546
|
+
const [open2, setOpen] = React76.useState(false);
|
|
13547
|
+
const anchor = React76.useRef(null);
|
|
13486
13548
|
const stats = sessionStats || null;
|
|
13487
13549
|
const cu = contextUsage || null;
|
|
13488
13550
|
const limits = usageLimits || null;
|
|
@@ -13497,7 +13559,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
13497
13559
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
13498
13560
|
if (cu) bits.push(pct + "% context");
|
|
13499
13561
|
const expandable = !!(cu || limits);
|
|
13500
|
-
return /* @__PURE__ */ jsxs91(
|
|
13562
|
+
return /* @__PURE__ */ jsxs91(React76.Fragment, { children: [
|
|
13501
13563
|
/* @__PURE__ */ jsxs91("div", { className: "fdc-bar", children: [
|
|
13502
13564
|
/* @__PURE__ */ jsxs91(
|
|
13503
13565
|
"button",
|
|
@@ -13638,7 +13700,7 @@ function ModelControls({
|
|
|
13638
13700
|
] })
|
|
13639
13701
|
});
|
|
13640
13702
|
}
|
|
13641
|
-
return /* @__PURE__ */ jsxs91(
|
|
13703
|
+
return /* @__PURE__ */ jsxs91(React76.Fragment, { children: [
|
|
13642
13704
|
/* @__PURE__ */ jsx104(
|
|
13643
13705
|
MenuButton,
|
|
13644
13706
|
{
|
|
@@ -13677,6 +13739,7 @@ function AgentChatPanel({
|
|
|
13677
13739
|
/* required */
|
|
13678
13740
|
contextType,
|
|
13679
13741
|
contextId,
|
|
13742
|
+
draftOwner,
|
|
13680
13743
|
apiAdapter,
|
|
13681
13744
|
threadId,
|
|
13682
13745
|
/* identity + chrome */
|
|
@@ -13757,11 +13820,11 @@ function AgentChatPanel({
|
|
|
13757
13820
|
onFeedback,
|
|
13758
13821
|
onEditMessage
|
|
13759
13822
|
}) {
|
|
13760
|
-
const [panelWidth, setPanelWidth] =
|
|
13761
|
-
const [applied, setApplied] =
|
|
13762
|
-
const [draft, setDraft] =
|
|
13763
|
-
const dragging =
|
|
13764
|
-
|
|
13823
|
+
const [panelWidth, setPanelWidth] = React77.useState(width);
|
|
13824
|
+
const [applied, setApplied] = React77.useState({});
|
|
13825
|
+
const [draft, setDraft] = useChatDraft(draftOwner, contextType, contextId);
|
|
13826
|
+
const dragging = React77.useRef(null);
|
|
13827
|
+
React77.useEffect(() => setPanelWidth(width), [width]);
|
|
13765
13828
|
const engine = useChatEngine({
|
|
13766
13829
|
contextType,
|
|
13767
13830
|
contextId,
|
|
@@ -13967,7 +14030,7 @@ function AgentChatPanel({
|
|
|
13967
14030
|
}
|
|
13968
14031
|
|
|
13969
14032
|
// src/components/files/FileViewer.tsx
|
|
13970
|
-
import * as
|
|
14033
|
+
import * as React78 from "react";
|
|
13971
14034
|
import { jsx as jsx106, jsxs as jsxs93 } from "react/jsx-runtime";
|
|
13972
14035
|
function previewKindOf(file) {
|
|
13973
14036
|
const mime = (file.mime || "").toLowerCase();
|
|
@@ -14024,13 +14087,13 @@ function parseDelimited(text, delimiter) {
|
|
|
14024
14087
|
return rows;
|
|
14025
14088
|
}
|
|
14026
14089
|
function usePreview(file, kind, resolveUrl) {
|
|
14027
|
-
const [state, setState] =
|
|
14028
|
-
const [attempt, setAttempt] =
|
|
14029
|
-
const resolveRef =
|
|
14030
|
-
|
|
14090
|
+
const [state, setState] = React78.useState({ status: "loading" });
|
|
14091
|
+
const [attempt, setAttempt] = React78.useState(0);
|
|
14092
|
+
const resolveRef = React78.useRef(resolveUrl);
|
|
14093
|
+
React78.useEffect(() => {
|
|
14031
14094
|
resolveRef.current = resolveUrl;
|
|
14032
14095
|
}, [resolveUrl]);
|
|
14033
|
-
|
|
14096
|
+
React78.useEffect(() => {
|
|
14034
14097
|
if (kind === "none") {
|
|
14035
14098
|
setState({ status: "ready" });
|
|
14036
14099
|
return;
|
|
@@ -14060,7 +14123,7 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
14060
14123
|
if (ac) ac.abort();
|
|
14061
14124
|
};
|
|
14062
14125
|
}, [file.id, kind, attempt]);
|
|
14063
|
-
return { ...state, retry:
|
|
14126
|
+
return { ...state, retry: React78.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
14064
14127
|
}
|
|
14065
14128
|
function PreviewBody({ file, kind, state }) {
|
|
14066
14129
|
if (kind === "image") return /* @__PURE__ */ jsx106("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
@@ -14105,13 +14168,13 @@ function PreviewBody({ file, kind, state }) {
|
|
|
14105
14168
|
] });
|
|
14106
14169
|
}
|
|
14107
14170
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
14108
|
-
const kind =
|
|
14171
|
+
const kind = React78.useMemo(() => previewKindOf(file), [file]);
|
|
14109
14172
|
const preview = usePreview(file, kind, resolveUrl);
|
|
14110
|
-
const [tab, setTab] =
|
|
14111
|
-
const [downloading, setDownloading] =
|
|
14112
|
-
const [downloadError, setDownloadError] =
|
|
14173
|
+
const [tab, setTab] = React78.useState("preview");
|
|
14174
|
+
const [downloading, setDownloading] = React78.useState(false);
|
|
14175
|
+
const [downloadError, setDownloadError] = React78.useState(null);
|
|
14113
14176
|
const hasSide = sidePanel != null;
|
|
14114
|
-
|
|
14177
|
+
React78.useEffect(() => {
|
|
14115
14178
|
setTab("preview");
|
|
14116
14179
|
}, [file.id]);
|
|
14117
14180
|
const download = () => {
|
|
@@ -14178,7 +14241,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
14178
14241
|
}
|
|
14179
14242
|
|
|
14180
14243
|
// src/components/files/FileBrowser.tsx
|
|
14181
|
-
import * as
|
|
14244
|
+
import * as React79 from "react";
|
|
14182
14245
|
import { Fragment as Fragment31, jsx as jsx107, jsxs as jsxs94 } from "react/jsx-runtime";
|
|
14183
14246
|
function childrenOf(folders, parentId) {
|
|
14184
14247
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -14288,8 +14351,8 @@ function FolderPickerMenu({
|
|
|
14288
14351
|
] });
|
|
14289
14352
|
}
|
|
14290
14353
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
14291
|
-
const [over, setOver] =
|
|
14292
|
-
const dragCounter =
|
|
14354
|
+
const [over, setOver] = React79.useState(false);
|
|
14355
|
+
const dragCounter = React79.useRef(0);
|
|
14293
14356
|
const dropHandlers = isDropTarget ? {
|
|
14294
14357
|
onDragEnter: (e) => {
|
|
14295
14358
|
if (!hasInternalPayload(e)) return;
|
|
@@ -14337,8 +14400,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
14337
14400
|
}
|
|
14338
14401
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
14339
14402
|
const kids = childrenOf(folders, folder.id);
|
|
14340
|
-
const [expanded, setExpanded] =
|
|
14341
|
-
|
|
14403
|
+
const [expanded, setExpanded] = React79.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
14404
|
+
React79.useEffect(() => {
|
|
14342
14405
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
14343
14406
|
}, [currentFolderId, folder.id, folders]);
|
|
14344
14407
|
const isCurrent = folder.id === currentFolderId;
|
|
@@ -14404,15 +14467,15 @@ function FileBrowser({
|
|
|
14404
14467
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
14405
14468
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
14406
14469
|
const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
|
|
14407
|
-
const [createOpen, setCreateOpen] =
|
|
14408
|
-
const [createName, setCreateName] =
|
|
14409
|
-
const [renameTarget, setRenameTarget] =
|
|
14410
|
-
const [renameValue, setRenameValue] =
|
|
14411
|
-
const [deleteTarget, setDeleteTarget] =
|
|
14412
|
-
const uploadInputRef =
|
|
14413
|
-
const crumbFolders =
|
|
14414
|
-
const subfolders =
|
|
14415
|
-
const currentFiles =
|
|
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(
|
|
14416
14479
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
14417
14480
|
[files, currentFolderId]
|
|
14418
14481
|
);
|
|
@@ -14644,8 +14707,8 @@ function BreadcrumbCrumb({
|
|
|
14644
14707
|
isDropTarget,
|
|
14645
14708
|
onDropPayload
|
|
14646
14709
|
}) {
|
|
14647
|
-
const [over, setOver] =
|
|
14648
|
-
const dragCounter =
|
|
14710
|
+
const [over, setOver] = React79.useState(false);
|
|
14711
|
+
const dragCounter = React79.useRef(0);
|
|
14649
14712
|
const dropHandlers = isDropTarget ? {
|
|
14650
14713
|
onDragEnter: (e) => {
|
|
14651
14714
|
if (!hasInternalPayload(e)) return;
|
|
@@ -14674,7 +14737,7 @@ function BreadcrumbCrumb({
|
|
|
14674
14737
|
}
|
|
14675
14738
|
|
|
14676
14739
|
// src/kits/query.ts
|
|
14677
|
-
import * as
|
|
14740
|
+
import * as React80 from "react";
|
|
14678
14741
|
|
|
14679
14742
|
// src/kits/queryUrl.ts
|
|
14680
14743
|
var historyUrlAdapter = {
|
|
@@ -14812,38 +14875,38 @@ function requestFor(params, query, paging, after) {
|
|
|
14812
14875
|
}
|
|
14813
14876
|
var toError = (e) => e instanceof Error ? e : new Error(String(e));
|
|
14814
14877
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "page", url }) {
|
|
14815
|
-
const [base] =
|
|
14878
|
+
const [base] = React80.useState(() => {
|
|
14816
14879
|
const store = PREFS || window.PlannerPrefs;
|
|
14817
14880
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
14818
14881
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
14819
14882
|
});
|
|
14820
|
-
const [mountParams] =
|
|
14821
|
-
const address =
|
|
14822
|
-
const [query, setQuery] =
|
|
14823
|
-
const savePref =
|
|
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) => {
|
|
14824
14887
|
const store = PREFS || window.PlannerPrefs;
|
|
14825
14888
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
14826
14889
|
}, [prefsKey]);
|
|
14827
|
-
const [res, setRes] =
|
|
14828
|
-
const [loading, setLoading] =
|
|
14829
|
-
const [loadingMore, setLoadingMore] =
|
|
14830
|
-
const [failure, setFailure] =
|
|
14831
|
-
const [reloadToken, setReloadToken] =
|
|
14832
|
-
const moreController =
|
|
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);
|
|
14833
14896
|
const depKey = (deps || []).join("|");
|
|
14834
14897
|
const paramKey = JSON.stringify(params || {});
|
|
14835
14898
|
const queryKey = JSON.stringify(query);
|
|
14836
|
-
const lifetime =
|
|
14837
|
-
|
|
14899
|
+
const lifetime = React80.useRef(null);
|
|
14900
|
+
React80.useEffect(() => {
|
|
14838
14901
|
const controller = new AbortController();
|
|
14839
14902
|
lifetime.current = controller;
|
|
14840
14903
|
return () => controller.abort();
|
|
14841
14904
|
}, []);
|
|
14842
|
-
const latest =
|
|
14843
|
-
|
|
14905
|
+
const latest = React80.useRef({ res, loading, query, params, endpoint, url, base });
|
|
14906
|
+
React80.useLayoutEffect(() => {
|
|
14844
14907
|
latest.current = { res, loading, query, params, endpoint, url, base };
|
|
14845
14908
|
});
|
|
14846
|
-
|
|
14909
|
+
React80.useEffect(() => {
|
|
14847
14910
|
const controller = new AbortController();
|
|
14848
14911
|
const { signal } = controller;
|
|
14849
14912
|
setLoading(true);
|
|
@@ -14879,7 +14942,7 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "
|
|
|
14879
14942
|
};
|
|
14880
14943
|
}, [endpoint, queryKey, paramKey, depKey, paging, reloadToken]);
|
|
14881
14944
|
const adapter = url ? url.adapter ?? historyUrlAdapter : null;
|
|
14882
|
-
|
|
14945
|
+
React80.useEffect(() => {
|
|
14883
14946
|
if (!adapter) return;
|
|
14884
14947
|
return adapter.subscribe((params2) => {
|
|
14885
14948
|
const { url: u, base: b } = latest.current;
|
|
@@ -15229,12 +15292,12 @@ function createVersionStore(initialState, options) {
|
|
|
15229
15292
|
}
|
|
15230
15293
|
|
|
15231
15294
|
// src/kits/documentTitle.ts
|
|
15232
|
-
import * as
|
|
15295
|
+
import * as React81 from "react";
|
|
15233
15296
|
function formatDocumentTitle(routeTitle, appName) {
|
|
15234
|
-
return [routeTitle, appName, "Flytedesk"].filter((
|
|
15297
|
+
return [routeTitle, appName, "Flytedesk"].filter((part2) => !!part2 && part2.length > 0).join(" \xB7 ");
|
|
15235
15298
|
}
|
|
15236
15299
|
function useDocumentTitle(routeTitle, appName) {
|
|
15237
|
-
|
|
15300
|
+
React81.useEffect(() => {
|
|
15238
15301
|
if (typeof document === "undefined") return;
|
|
15239
15302
|
document.title = formatDocumentTitle(routeTitle, appName);
|
|
15240
15303
|
}, [routeTitle, appName]);
|
|
@@ -15344,6 +15407,7 @@ export {
|
|
|
15344
15407
|
ModeSwitch,
|
|
15345
15408
|
ModelControls,
|
|
15346
15409
|
NumberInput,
|
|
15410
|
+
OVERLAY_BREAKPOINT,
|
|
15347
15411
|
OVERLAY_CEILING,
|
|
15348
15412
|
POPOVER_BODY_MIN,
|
|
15349
15413
|
PacketCard,
|
|
@@ -15468,6 +15532,7 @@ export {
|
|
|
15468
15532
|
useDocumentTitle,
|
|
15469
15533
|
useFeatureStatus,
|
|
15470
15534
|
useLayerZIndex,
|
|
15535
|
+
useOverlayLayout,
|
|
15471
15536
|
usePopoverPosition,
|
|
15472
15537
|
useResponsiveRail,
|
|
15473
15538
|
useRuntimeMode,
|