@flytedan/flytebot-design-system 0.16.0 → 0.17.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 +461 -371
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -2
- package/dist/index.d.ts +55 -2
- package/dist/index.js +460 -371
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -885,37 +885,48 @@ function Spinner({ size = "md", label = "Loading", className = "", style, ...res
|
|
|
885
885
|
}
|
|
886
886
|
|
|
887
887
|
// src/components/navigation/SidebarNav.tsx
|
|
888
|
+
import * as React6 from "react";
|
|
888
889
|
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
889
890
|
function Tip({ label, children }) {
|
|
890
891
|
return /* @__PURE__ */ jsx13("span", { title: label, style: { display: "inline-flex", flex: "none" }, children });
|
|
891
892
|
}
|
|
892
|
-
|
|
893
|
-
return /* @__PURE__ */ jsxs10(
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
children:
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
}
|
|
893
|
+
var SidebarNav = React6.forwardRef(function SidebarNav2({ brand, groups = [], current: current2, onNavigate, footer, open = false, className = "", ...rest }, ref) {
|
|
894
|
+
return /* @__PURE__ */ jsxs10(
|
|
895
|
+
"nav",
|
|
896
|
+
{
|
|
897
|
+
ref,
|
|
898
|
+
tabIndex: -1,
|
|
899
|
+
className: ["fd-side", className].filter(Boolean).join(" "),
|
|
900
|
+
"data-open": open ? "true" : "false",
|
|
901
|
+
...rest,
|
|
902
|
+
children: [
|
|
903
|
+
brand ? /* @__PURE__ */ jsx13("div", { style: { height: "var(--topbar-h)", display: "flex", alignItems: "center", padding: "0 18px", borderBottom: "1px solid var(--border)", flex: "none", overflow: "hidden" }, children: brand }) : null,
|
|
904
|
+
/* @__PURE__ */ jsx13("div", { style: { flex: 1, overflow: "auto", padding: "4px 10px 18px" }, children: groups.map((g, gi) => /* @__PURE__ */ jsxs10("div", { children: [
|
|
905
|
+
g.label ? /* @__PURE__ */ jsx13("div", { className: "fd-side-group", children: g.label }) : null,
|
|
906
|
+
/* @__PURE__ */ jsx13("div", { className: "fd-stack", style: { gap: 2 }, children: g.items.map((it) => /* @__PURE__ */ jsxs10(
|
|
907
|
+
"button",
|
|
908
|
+
{
|
|
909
|
+
type: "button",
|
|
910
|
+
className: "fd-side-item",
|
|
911
|
+
"aria-current": current2 === it.value ? "page" : void 0,
|
|
912
|
+
onClick: onNavigate ? () => onNavigate(it.value) : void 0,
|
|
913
|
+
children: [
|
|
914
|
+
/* @__PURE__ */ jsx13("span", { className: "fd-side-item-icon", children: /* @__PURE__ */ jsx13("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) }),
|
|
915
|
+
/* @__PURE__ */ jsx13("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, title: truncationTitle(it.label), children: it.label }),
|
|
916
|
+
it.preview ? /* @__PURE__ */ jsx13(Tip, { label: "Designed, backend not wired yet", children: /* @__PURE__ */ jsx13("i", { className: "ph ph-traffic-cone", style: { fontSize: 13, color: "var(--warn-solid)", flex: "none" } }) }) : null,
|
|
917
|
+
it.locked ? /* @__PURE__ */ jsx13(Tip, { label: "You do not have permission for this", children: /* @__PURE__ */ jsx13("i", { className: "ph ph-lock-simple", style: { fontSize: 13, color: "var(--text-muted)", flex: "none" } }) }) : null,
|
|
918
|
+
it.count !== void 0 ? /* @__PURE__ */ jsx13("span", { className: "fd-side-item-count", children: it.count }) : null,
|
|
919
|
+
it.loading ? /* @__PURE__ */ jsx13("span", { className: "fd-skel fd-skel-text", style: { width: 22, height: 11, marginLeft: "auto" } }) : null
|
|
920
|
+
]
|
|
921
|
+
},
|
|
922
|
+
it.value
|
|
923
|
+
)) })
|
|
924
|
+
] }, gi)) }),
|
|
925
|
+
footer ? /* @__PURE__ */ jsx13("div", { style: { borderTop: "1px solid var(--border)", padding: 14, flex: "none" }, children: footer }) : null
|
|
926
|
+
]
|
|
927
|
+
}
|
|
928
|
+
);
|
|
929
|
+
});
|
|
919
930
|
|
|
920
931
|
// src/components/navigation/FlytedeskBrand.tsx
|
|
921
932
|
import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
@@ -956,13 +967,13 @@ function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
|
|
|
956
967
|
}
|
|
957
968
|
|
|
958
969
|
// src/components/navigation/Topbar.tsx
|
|
959
|
-
import * as
|
|
970
|
+
import * as React7 from "react";
|
|
960
971
|
import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
961
972
|
function useIsNarrow(breakpoint) {
|
|
962
|
-
const [narrow, setNarrow] =
|
|
973
|
+
const [narrow, setNarrow] = React7.useState(
|
|
963
974
|
() => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
|
|
964
975
|
);
|
|
965
|
-
|
|
976
|
+
React7.useEffect(() => {
|
|
966
977
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
967
978
|
const mq = window.matchMedia(`(max-width: ${breakpoint}px)`);
|
|
968
979
|
const apply = () => setNarrow(mq.matches);
|
|
@@ -983,11 +994,11 @@ function Topbar({
|
|
|
983
994
|
...rest
|
|
984
995
|
}) {
|
|
985
996
|
const narrow = useIsNarrow(overflowBreakpoint);
|
|
986
|
-
const [moreOpen, setMoreOpen] =
|
|
987
|
-
const moreRef =
|
|
997
|
+
const [moreOpen, setMoreOpen] = React7.useState(false);
|
|
998
|
+
const moreRef = React7.useRef(null);
|
|
988
999
|
return /* @__PURE__ */ jsxs13("header", { className: ["fd-topbar", narrow ? "is-narrow" : "", className].filter(Boolean).join(" "), ...rest, children: [
|
|
989
1000
|
onMenu ? /* @__PURE__ */ jsx16("button", { type: "button", className: "fd-btn-icon", "aria-label": "Menu", onClick: onMenu, children: /* @__PURE__ */ jsx16("i", { className: "ph ph-list" }) }) : null,
|
|
990
|
-
/* @__PURE__ */ jsx16("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ jsxs13(
|
|
1001
|
+
/* @__PURE__ */ jsx16("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ jsxs13(React7.Fragment, { children: [
|
|
991
1002
|
i > 0 ? /* @__PURE__ */ jsx16("i", { className: "ph ph-caret-right", style: { fontSize: 11, opacity: 0.6 }, "aria-hidden": "true" }) : null,
|
|
992
1003
|
i === crumbs.length - 1 ? (
|
|
993
1004
|
// MP-141: the current crumb mixes a static route label with (usually) a
|
|
@@ -1196,18 +1207,18 @@ function Toast({ title, children, tone = "success", onUndo, onDismiss, className
|
|
|
1196
1207
|
}
|
|
1197
1208
|
|
|
1198
1209
|
// src/components/feedback/Tooltip.tsx
|
|
1199
|
-
import * as
|
|
1210
|
+
import * as React8 from "react";
|
|
1200
1211
|
import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1201
1212
|
var CLOSE_DELAY_MS = 120;
|
|
1202
1213
|
function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
1203
|
-
const anchorRef =
|
|
1204
|
-
const bubbleRef =
|
|
1205
|
-
const [reason, setReason] =
|
|
1206
|
-
const closeTimer =
|
|
1207
|
-
const id =
|
|
1214
|
+
const anchorRef = React8.useRef(null);
|
|
1215
|
+
const bubbleRef = React8.useRef(null);
|
|
1216
|
+
const [reason, setReason] = React8.useState(null);
|
|
1217
|
+
const closeTimer = React8.useRef(null);
|
|
1218
|
+
const id = React8.useId();
|
|
1208
1219
|
const descId = id + "-desc";
|
|
1209
1220
|
const open = reason != null;
|
|
1210
|
-
const cancelClose =
|
|
1221
|
+
const cancelClose = React8.useCallback(() => {
|
|
1211
1222
|
if (closeTimer.current) {
|
|
1212
1223
|
clearTimeout(closeTimer.current);
|
|
1213
1224
|
closeTimer.current = null;
|
|
@@ -1217,7 +1228,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1217
1228
|
cancelClose();
|
|
1218
1229
|
setReason(why);
|
|
1219
1230
|
};
|
|
1220
|
-
const hide =
|
|
1231
|
+
const hide = React8.useCallback(() => {
|
|
1221
1232
|
cancelClose();
|
|
1222
1233
|
setReason(null);
|
|
1223
1234
|
}, [cancelClose]);
|
|
@@ -1232,7 +1243,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1232
1243
|
setReason((r) => r === "hover" ? null : r);
|
|
1233
1244
|
}, CLOSE_DELAY_MS);
|
|
1234
1245
|
};
|
|
1235
|
-
|
|
1246
|
+
React8.useEffect(() => cancelClose, [cancelClose]);
|
|
1236
1247
|
const pos = usePopoverPosition(open, anchorRef, {
|
|
1237
1248
|
placement: placement === "bottom" ? "bottom-center" : "top-center",
|
|
1238
1249
|
offset: 8,
|
|
@@ -1242,7 +1253,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1242
1253
|
onDetach: hide
|
|
1243
1254
|
});
|
|
1244
1255
|
const zIndex = useOverlayLayer(open);
|
|
1245
|
-
|
|
1256
|
+
React8.useEffect(() => {
|
|
1246
1257
|
if (!open) return;
|
|
1247
1258
|
const key = (e) => {
|
|
1248
1259
|
if (e.key === "Escape") hide();
|
|
@@ -1270,7 +1281,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1270
1281
|
}
|
|
1271
1282
|
if (keyboard) show("focus");
|
|
1272
1283
|
};
|
|
1273
|
-
const described =
|
|
1284
|
+
const described = React8.isValidElement(children) ? React8.cloneElement(children, {
|
|
1274
1285
|
"aria-describedby": [children.props["aria-describedby"], descId].filter(Boolean).join(" ")
|
|
1275
1286
|
}) : children;
|
|
1276
1287
|
return /* @__PURE__ */ jsxs20(
|
|
@@ -1278,7 +1289,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1278
1289
|
{
|
|
1279
1290
|
ref: anchorRef,
|
|
1280
1291
|
className: "fd-tooltip-anchor",
|
|
1281
|
-
"aria-describedby":
|
|
1292
|
+
"aria-describedby": React8.isValidElement(children) ? void 0 : descId,
|
|
1282
1293
|
onPointerEnter: (e) => {
|
|
1283
1294
|
if (isMouse(e)) hover();
|
|
1284
1295
|
},
|
|
@@ -1322,7 +1333,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1322
1333
|
}
|
|
1323
1334
|
|
|
1324
1335
|
// src/components/data/Clamp.tsx
|
|
1325
|
-
import * as
|
|
1336
|
+
import * as React9 from "react";
|
|
1326
1337
|
import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1327
1338
|
function Clamp({
|
|
1328
1339
|
children,
|
|
@@ -1334,16 +1345,16 @@ function Clamp({
|
|
|
1334
1345
|
onToggle,
|
|
1335
1346
|
className = ""
|
|
1336
1347
|
}) {
|
|
1337
|
-
const [open, setOpen] =
|
|
1338
|
-
const [overflows, setOverflows] =
|
|
1339
|
-
const bodyRef =
|
|
1340
|
-
const charClamped =
|
|
1348
|
+
const [open, setOpen] = React9.useState(false);
|
|
1349
|
+
const [overflows, setOverflows] = React9.useState(false);
|
|
1350
|
+
const bodyRef = React9.useRef(null);
|
|
1351
|
+
const charClamped = React9.useMemo(() => {
|
|
1341
1352
|
if (open || !maxChars || typeof text !== "string" || text.length <= maxChars) return null;
|
|
1342
1353
|
const cut = text.slice(0, maxChars);
|
|
1343
1354
|
const at = cut.lastIndexOf(" ");
|
|
1344
1355
|
return (at > maxChars * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
1345
1356
|
}, [text, maxChars, open]);
|
|
1346
|
-
|
|
1357
|
+
React9.useLayoutEffect(() => {
|
|
1347
1358
|
const node = bodyRef.current;
|
|
1348
1359
|
if (maxChars || !node || !maxHeight) return;
|
|
1349
1360
|
const measure = () => {
|
|
@@ -1482,18 +1493,18 @@ function DataTable({
|
|
|
1482
1493
|
}
|
|
1483
1494
|
|
|
1484
1495
|
// src/components/data/FilterBar.tsx
|
|
1485
|
-
import * as
|
|
1496
|
+
import * as React10 from "react";
|
|
1486
1497
|
import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1487
1498
|
var isSet = (v) => !(v == null || v === "" || v === false);
|
|
1488
1499
|
function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align = "left", className = "", ...rest }) {
|
|
1489
|
-
const [panel, setPanel] =
|
|
1500
|
+
const [panel, setPanel] = React10.useState(null);
|
|
1490
1501
|
const zIndex = useOverlayLayer(!!panel);
|
|
1491
|
-
const rootRef =
|
|
1492
|
-
const textInputRef =
|
|
1493
|
-
const optionsRef =
|
|
1502
|
+
const rootRef = React10.useRef(null);
|
|
1503
|
+
const textInputRef = React10.useRef(null);
|
|
1504
|
+
const optionsRef = React10.useRef(null);
|
|
1494
1505
|
const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
|
|
1495
1506
|
const dismissible = !!panel && (panel.kind === "add" || panel.kind === "edit" && editingField?.type === "select");
|
|
1496
|
-
|
|
1507
|
+
React10.useEffect(() => {
|
|
1497
1508
|
if (!dismissible) return;
|
|
1498
1509
|
const away = (e) => {
|
|
1499
1510
|
if (rootRef.current && !rootRef.current.contains(e.target)) setPanel(null);
|
|
@@ -1508,7 +1519,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
1508
1519
|
document.removeEventListener("keydown", esc);
|
|
1509
1520
|
};
|
|
1510
1521
|
}, [dismissible]);
|
|
1511
|
-
|
|
1522
|
+
React10.useEffect(() => {
|
|
1512
1523
|
if (!panel || panel.kind !== "edit") return;
|
|
1513
1524
|
if (editingField?.type === "text") {
|
|
1514
1525
|
textInputRef.current?.focus();
|
|
@@ -1674,7 +1685,7 @@ function StatTile({ label, value, sub, delta, loading = false, compact: compact3
|
|
|
1674
1685
|
}
|
|
1675
1686
|
|
|
1676
1687
|
// src/components/data/CodeBlock.tsx
|
|
1677
|
-
import * as
|
|
1688
|
+
import * as React11 from "react";
|
|
1678
1689
|
import { Fragment as Fragment5, jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
1679
1690
|
var JS_KW = /^(?:const|let|var|function|return|if|else|for|while|do|new|class|extends|import|from|export|default|await|async|try|catch|finally|throw|typeof|instanceof|of|in|switch|case|break|continue|delete|void|yield|static|get|set|this|super|interface|type|enum|implements|public|private|protected|readonly|abstract|as|satisfies|declare|namespace)$/;
|
|
1680
1691
|
var RULES = {
|
|
@@ -1830,13 +1841,13 @@ function tokenize(src, lang) {
|
|
|
1830
1841
|
return out;
|
|
1831
1842
|
}
|
|
1832
1843
|
function Highlighted({ code, lang }) {
|
|
1833
|
-
const toks =
|
|
1844
|
+
const toks = React11.useMemo(() => tokenize(code, lang), [code, lang]);
|
|
1834
1845
|
return /* @__PURE__ */ jsx30(Fragment5, { children: toks.map((tk, i) => tk.c ? /* @__PURE__ */ jsx30("span", { className: "tok-" + tk.c, children: tk.t }, i) : tk.t) });
|
|
1835
1846
|
}
|
|
1836
1847
|
function useCopy() {
|
|
1837
|
-
const [done, setDone] =
|
|
1838
|
-
const timer =
|
|
1839
|
-
|
|
1848
|
+
const [done, setDone] = React11.useState(false);
|
|
1849
|
+
const timer = React11.useRef(null);
|
|
1850
|
+
React11.useEffect(() => () => {
|
|
1840
1851
|
if (timer.current) clearTimeout(timer.current);
|
|
1841
1852
|
}, []);
|
|
1842
1853
|
const copy = (text) => {
|
|
@@ -1872,8 +1883,8 @@ function CodeBlock({
|
|
|
1872
1883
|
actions,
|
|
1873
1884
|
className = ""
|
|
1874
1885
|
}) {
|
|
1875
|
-
const [wrap, setWrap] =
|
|
1876
|
-
const [open, setOpen] =
|
|
1886
|
+
const [wrap, setWrap] = React11.useState(!!wrapDefault);
|
|
1887
|
+
const [open, setOpen] = React11.useState(false);
|
|
1877
1888
|
const [copied, copy] = useCopy();
|
|
1878
1889
|
const body = String(code).replace(/\n$/, "");
|
|
1879
1890
|
const lines = body.split("\n");
|
|
@@ -1902,7 +1913,7 @@ function CodeBlock({
|
|
|
1902
1913
|
] });
|
|
1903
1914
|
}
|
|
1904
1915
|
function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
|
|
1905
|
-
const [open, setOpen] =
|
|
1916
|
+
const [open, setOpen] = React11.useState(false);
|
|
1906
1917
|
const [copied, copy] = useCopy();
|
|
1907
1918
|
const raw = String(diff).replace(/\n$/, "");
|
|
1908
1919
|
const all = raw.split("\n").map((line) => {
|
|
@@ -1948,7 +1959,7 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
|
|
|
1948
1959
|
}
|
|
1949
1960
|
|
|
1950
1961
|
// src/components/data/Markdown.tsx
|
|
1951
|
-
import * as
|
|
1962
|
+
import * as React12 from "react";
|
|
1952
1963
|
import { jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
1953
1964
|
var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
|
|
1954
1965
|
var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
|
|
@@ -1987,7 +1998,7 @@ function inlineNodes(src, ctx, keyBase) {
|
|
|
1987
1998
|
const href = safeHref(g(2));
|
|
1988
1999
|
out.push(href ? /* @__PURE__ */ jsx31("a", { href, title: g(3) || void 0, target: /^https?:/i.test(href) ? "_blank" : void 0, rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: inlineNodes(g(1), ctx, key()) }, key()) : /* @__PURE__ */ jsx31("span", { children: g(1) }, key()));
|
|
1989
2000
|
} else if (kind === "cite") {
|
|
1990
|
-
out.push(ctx.renderCitation ? /* @__PURE__ */ jsx31(
|
|
2001
|
+
out.push(ctx.renderCitation ? /* @__PURE__ */ jsx31(React12.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ jsx31("sup", { className: "fd-md-cite", children: g(1) }, key()));
|
|
1991
2002
|
} else if (kind === "strongem") out.push(/* @__PURE__ */ jsx31("strong", { children: /* @__PURE__ */ jsx31("em", { children: inlineNodes(g(1), ctx, key()) }) }, key()));
|
|
1992
2003
|
else if (kind === "strong") out.push(/* @__PURE__ */ jsx31("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
1993
2004
|
else if (kind === "em") out.push(/* @__PURE__ */ jsx31("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
@@ -2152,7 +2163,7 @@ function Markdown({
|
|
|
2152
2163
|
onLinkClick
|
|
2153
2164
|
}) {
|
|
2154
2165
|
const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
|
|
2155
|
-
const blocks =
|
|
2166
|
+
const blocks = React12.useMemo(() => parseBlocks(source), [source]);
|
|
2156
2167
|
return /* @__PURE__ */ jsx31("div", { className: ["fd-md", className].filter(Boolean).join(" "), children: renderBlocks(blocks, ctx, "b") });
|
|
2157
2168
|
}
|
|
2158
2169
|
function MarkdownInline({ source = "", className = "", onLinkClick }) {
|
|
@@ -2266,7 +2277,7 @@ function Pagination({
|
|
|
2266
2277
|
}
|
|
2267
2278
|
|
|
2268
2279
|
// src/components/data/RelativeTime.tsx
|
|
2269
|
-
import * as
|
|
2280
|
+
import * as React13 from "react";
|
|
2270
2281
|
import { jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2271
2282
|
var MIN = 6e4;
|
|
2272
2283
|
var HOUR = 36e5;
|
|
@@ -2318,9 +2329,9 @@ function formatDuration(ms) {
|
|
|
2318
2329
|
return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
|
|
2319
2330
|
}
|
|
2320
2331
|
function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
|
|
2321
|
-
const [, force] =
|
|
2332
|
+
const [, force] = React13.useState(0);
|
|
2322
2333
|
const t = value instanceof Date ? value.getTime() : Date.parse(value);
|
|
2323
|
-
|
|
2334
|
+
React13.useEffect(() => {
|
|
2324
2335
|
if (!refresh2 || !t || isNaN(t)) return;
|
|
2325
2336
|
const abs = Math.abs(t - Date.now());
|
|
2326
2337
|
if (abs > DAY) return;
|
|
@@ -2336,10 +2347,10 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
|
|
|
2336
2347
|
}
|
|
2337
2348
|
|
|
2338
2349
|
// src/components/data/ScoreMeter.tsx
|
|
2339
|
-
import * as
|
|
2350
|
+
import * as React15 from "react";
|
|
2340
2351
|
|
|
2341
2352
|
// src/components/data/SegmentedMeter.tsx
|
|
2342
|
-
import * as
|
|
2353
|
+
import * as React14 from "react";
|
|
2343
2354
|
|
|
2344
2355
|
// src/kits/files.ts
|
|
2345
2356
|
function formatBytes(n) {
|
|
@@ -2544,7 +2555,7 @@ function SegmentedMeter({
|
|
|
2544
2555
|
const pct = safeTotal ? Math.min(100, Math.round(used / safeTotal * 100)) : 0;
|
|
2545
2556
|
const w = (v) => safeTotal ? Math.max(0, Math.min(100, Number(v) / safeTotal * 100)) : 0;
|
|
2546
2557
|
const fill = (s, i) => s.color || (s.variant ? VARIANT_FILL[s.variant] : void 0) || CHART[i % CHART.length];
|
|
2547
|
-
const generatedId =
|
|
2558
|
+
const generatedId = React14.useId();
|
|
2548
2559
|
const uid2 = id || generatedId;
|
|
2549
2560
|
return /* @__PURE__ */ jsxs31("div", { className: ["fd-segmeter", className].filter(Boolean).join(" "), onClick, children: [
|
|
2550
2561
|
label || showTotal ? /* @__PURE__ */ jsxs31("div", { className: "fd-segmeter-head", children: [
|
|
@@ -2628,10 +2639,10 @@ function ScoreMeter({
|
|
|
2628
2639
|
breakdownWidth = 280,
|
|
2629
2640
|
className = ""
|
|
2630
2641
|
}) {
|
|
2631
|
-
const [open, setOpen] =
|
|
2632
|
-
const ref =
|
|
2642
|
+
const [open, setOpen] = React15.useState(false);
|
|
2643
|
+
const ref = React15.useRef(null);
|
|
2633
2644
|
const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
|
|
2634
|
-
const body = /* @__PURE__ */ jsxs32(
|
|
2645
|
+
const body = /* @__PURE__ */ jsxs32(React15.Fragment, { children: [
|
|
2635
2646
|
/* @__PURE__ */ jsx35("span", { className: "fd-scoremeter-rail", style: { width }, "aria-hidden": "true", children: /* @__PURE__ */ jsx35(SegmentedMeter, { total: 100, segments, height, showTotal: false, showPercent: false, legend: false }) }),
|
|
2636
2647
|
showScore ? /* @__PURE__ */ jsx35("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
|
|
2637
2648
|
] });
|
|
@@ -2650,7 +2661,7 @@ function ScoreMeter({
|
|
|
2650
2661
|
}
|
|
2651
2662
|
);
|
|
2652
2663
|
}
|
|
2653
|
-
return /* @__PURE__ */ jsxs32(
|
|
2664
|
+
return /* @__PURE__ */ jsxs32(React15.Fragment, { children: [
|
|
2654
2665
|
/* @__PURE__ */ jsx35(
|
|
2655
2666
|
"button",
|
|
2656
2667
|
{
|
|
@@ -2681,13 +2692,13 @@ function ScoreMeter({
|
|
|
2681
2692
|
}
|
|
2682
2693
|
|
|
2683
2694
|
// src/components/data/SortMenu.tsx
|
|
2684
|
-
import * as
|
|
2695
|
+
import * as React16 from "react";
|
|
2685
2696
|
import { jsx as jsx36, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2686
2697
|
function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", className = "", ...rest }) {
|
|
2687
|
-
const [open, setOpen] =
|
|
2698
|
+
const [open, setOpen] = React16.useState(false);
|
|
2688
2699
|
const zIndex = useOverlayLayer(open);
|
|
2689
|
-
const ref =
|
|
2690
|
-
|
|
2700
|
+
const ref = React16.useRef(null);
|
|
2701
|
+
React16.useEffect(() => {
|
|
2691
2702
|
if (!open) return;
|
|
2692
2703
|
const away = (e) => {
|
|
2693
2704
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -2749,7 +2760,7 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
|
|
|
2749
2760
|
}
|
|
2750
2761
|
|
|
2751
2762
|
// src/components/data/StepList.tsx
|
|
2752
|
-
import * as
|
|
2763
|
+
import * as React17 from "react";
|
|
2753
2764
|
import { jsx as jsx37, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2754
2765
|
var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
|
|
2755
2766
|
function StepList({
|
|
@@ -2762,9 +2773,9 @@ function StepList({
|
|
|
2762
2773
|
dense = false,
|
|
2763
2774
|
className = ""
|
|
2764
2775
|
}) {
|
|
2765
|
-
const [openState, setOpenState] =
|
|
2776
|
+
const [openState, setOpenState] = React17.useState(defaultOpen);
|
|
2766
2777
|
const open = openProp == null ? openState : openProp;
|
|
2767
|
-
const [expanded, setExpanded] =
|
|
2778
|
+
const [expanded, setExpanded] = React17.useState({});
|
|
2768
2779
|
if (!steps.length) return null;
|
|
2769
2780
|
const running = steps.some((s) => s.status === "running");
|
|
2770
2781
|
const failed = steps.filter((s) => s.status === "error").length;
|
|
@@ -2822,7 +2833,7 @@ function StepList({
|
|
|
2822
2833
|
}
|
|
2823
2834
|
|
|
2824
2835
|
// src/components/data/VirtualList.tsx
|
|
2825
|
-
import * as
|
|
2836
|
+
import * as React18 from "react";
|
|
2826
2837
|
import { jsx as jsx38, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2827
2838
|
var VIRTUAL_LIST_BUFFER_ROWS = 20;
|
|
2828
2839
|
var VIRTUAL_LIST_ROW_GAP = 6;
|
|
@@ -2874,35 +2885,35 @@ function VirtualList({
|
|
|
2874
2885
|
className = "",
|
|
2875
2886
|
style
|
|
2876
2887
|
}) {
|
|
2877
|
-
const [scrollTop, setScrollTop] =
|
|
2878
|
-
const loaded =
|
|
2888
|
+
const [scrollTop, setScrollTop] = React18.useState(0);
|
|
2889
|
+
const loaded = React18.useMemo(
|
|
2879
2890
|
() => ({ firstItemIndex, count: items.length }),
|
|
2880
2891
|
[firstItemIndex, items.length]
|
|
2881
2892
|
);
|
|
2882
2893
|
const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
|
|
2883
2894
|
const bandKey = firstItemIndex + ":" + items.length;
|
|
2884
|
-
const win =
|
|
2895
|
+
const win = React18.useMemo(
|
|
2885
2896
|
() => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
|
|
2886
2897
|
[scrollTop, height, itemHeight, total, loaded]
|
|
2887
2898
|
);
|
|
2888
|
-
const need =
|
|
2899
|
+
const need = React18.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
|
|
2889
2900
|
const wantStart = need.start && hasMore?.start !== false;
|
|
2890
2901
|
const wantEnd = need.end && hasMore?.end !== false;
|
|
2891
2902
|
const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
|
|
2892
2903
|
const askKey = bandKey + "@" + bucket2;
|
|
2893
|
-
const asked =
|
|
2894
|
-
|
|
2904
|
+
const asked = React18.useRef({ start: null, end: null });
|
|
2905
|
+
React18.useEffect(() => {
|
|
2895
2906
|
if (loading || !wantStart || asked.current.start === askKey) return;
|
|
2896
2907
|
asked.current.start = askKey;
|
|
2897
2908
|
onNeedMore("start", win);
|
|
2898
2909
|
}, [wantStart, loading, askKey, onNeedMore, win]);
|
|
2899
|
-
|
|
2910
|
+
React18.useEffect(() => {
|
|
2900
2911
|
if (loading || !wantEnd || asked.current.end === askKey) return;
|
|
2901
2912
|
asked.current.end = askKey;
|
|
2902
2913
|
onNeedMore("end", win);
|
|
2903
2914
|
}, [wantEnd, loading, askKey, onNeedMore, win]);
|
|
2904
|
-
const lastKeysRef =
|
|
2905
|
-
const newKeys =
|
|
2915
|
+
const lastKeysRef = React18.useRef(null);
|
|
2916
|
+
const newKeys = React18.useMemo(() => {
|
|
2906
2917
|
const prev = lastKeysRef.current;
|
|
2907
2918
|
if (!prev) return /* @__PURE__ */ new Set();
|
|
2908
2919
|
const fresh = /* @__PURE__ */ new Set();
|
|
@@ -2912,7 +2923,7 @@ function VirtualList({
|
|
|
2912
2923
|
}
|
|
2913
2924
|
return fresh;
|
|
2914
2925
|
}, [items]);
|
|
2915
|
-
|
|
2926
|
+
React18.useEffect(() => {
|
|
2916
2927
|
lastKeysRef.current = new Set(items.map(keyOf));
|
|
2917
2928
|
}, [items]);
|
|
2918
2929
|
const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
|
|
@@ -2957,7 +2968,7 @@ function VirtualList({
|
|
|
2957
2968
|
}
|
|
2958
2969
|
|
|
2959
2970
|
// src/components/data/EntityRow.tsx
|
|
2960
|
-
import * as
|
|
2971
|
+
import * as React19 from "react";
|
|
2961
2972
|
import { jsx as jsx39, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
2962
2973
|
var ENTITY_ROW_METRIC_WIDTH = 74;
|
|
2963
2974
|
var METRIC_TONE_COLOR = {
|
|
@@ -2970,7 +2981,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
|
|
|
2970
2981
|
const key = m.id || m.label || i;
|
|
2971
2982
|
const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
|
|
2972
2983
|
const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
|
|
2973
|
-
const content = /* @__PURE__ */ jsxs36(
|
|
2984
|
+
const content = /* @__PURE__ */ jsxs36(React19.Fragment, { children: [
|
|
2974
2985
|
m.icon ? /* @__PURE__ */ jsx39("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
|
|
2975
2986
|
/* @__PURE__ */ jsx39("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
|
|
2976
2987
|
/* @__PURE__ */ jsx39("span", { className: "fd-sr", children: " " + m.label })
|
|
@@ -3062,14 +3073,14 @@ function EntityRow({
|
|
|
3062
3073
|
}
|
|
3063
3074
|
|
|
3064
3075
|
// src/components/data/TransferList.tsx
|
|
3065
|
-
import * as
|
|
3076
|
+
import * as React21 from "react";
|
|
3066
3077
|
import { createPortal as createPortal4 } from "react-dom";
|
|
3067
3078
|
|
|
3068
3079
|
// src/components/forms/field.tsx
|
|
3069
|
-
import * as
|
|
3080
|
+
import * as React20 from "react";
|
|
3070
3081
|
import { jsx as jsx40, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
3071
3082
|
function useFieldId(id) {
|
|
3072
|
-
const generated =
|
|
3083
|
+
const generated = React20.useId();
|
|
3073
3084
|
return id || generated;
|
|
3074
3085
|
}
|
|
3075
3086
|
function FieldLabel({ htmlFor, id, required = false, onClick, children }) {
|
|
@@ -3187,12 +3198,12 @@ function TransferList({
|
|
|
3187
3198
|
listHeight = 440,
|
|
3188
3199
|
className = ""
|
|
3189
3200
|
}) {
|
|
3190
|
-
const [drag, setDrag] =
|
|
3191
|
-
const [dragOverSide, setDragOverSide] =
|
|
3192
|
-
const dragRef =
|
|
3193
|
-
const armedRef =
|
|
3194
|
-
const sideRefs =
|
|
3195
|
-
const hitTestSide =
|
|
3201
|
+
const [drag, setDrag] = React21.useState(null);
|
|
3202
|
+
const [dragOverSide, setDragOverSide] = React21.useState(null);
|
|
3203
|
+
const dragRef = React21.useRef(null);
|
|
3204
|
+
const armedRef = React21.useRef(null);
|
|
3205
|
+
const sideRefs = React21.useRef({ left: null, right: null });
|
|
3206
|
+
const hitTestSide = React21.useCallback((x, y) => {
|
|
3196
3207
|
for (const side of ["left", "right"]) {
|
|
3197
3208
|
const el = sideRefs.current[side];
|
|
3198
3209
|
if (!el) continue;
|
|
@@ -3201,7 +3212,7 @@ function TransferList({
|
|
|
3201
3212
|
}
|
|
3202
3213
|
return null;
|
|
3203
3214
|
}, []);
|
|
3204
|
-
const findItem =
|
|
3215
|
+
const findItem = React21.useCallback(
|
|
3205
3216
|
(side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
|
|
3206
3217
|
[left.items, right.items, keyOf]
|
|
3207
3218
|
);
|
|
@@ -3223,7 +3234,7 @@ function TransferList({
|
|
|
3223
3234
|
height: rect.height
|
|
3224
3235
|
};
|
|
3225
3236
|
};
|
|
3226
|
-
|
|
3237
|
+
React21.useEffect(() => {
|
|
3227
3238
|
const onMovePointer = (e) => {
|
|
3228
3239
|
const armed = armedRef.current;
|
|
3229
3240
|
if (!armed || e.pointerId !== armed.pointerId) return;
|
|
@@ -3276,7 +3287,7 @@ function TransferList({
|
|
|
3276
3287
|
window.removeEventListener("pointercancel", endDrag);
|
|
3277
3288
|
};
|
|
3278
3289
|
}, [hitTestSide, findItem, onMove]);
|
|
3279
|
-
|
|
3290
|
+
React21.useEffect(() => {
|
|
3280
3291
|
if (!drag || typeof document === "undefined") return;
|
|
3281
3292
|
const prev = document.body.style.userSelect;
|
|
3282
3293
|
document.body.style.userSelect = "none";
|
|
@@ -3384,11 +3395,11 @@ function TransferList({
|
|
|
3384
3395
|
}
|
|
3385
3396
|
|
|
3386
3397
|
// src/components/forms/Checkbox.tsx
|
|
3387
|
-
import * as
|
|
3398
|
+
import * as React22 from "react";
|
|
3388
3399
|
import { jsx as jsx44, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
3389
3400
|
function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
|
|
3390
|
-
const ref =
|
|
3391
|
-
|
|
3401
|
+
const ref = React22.useRef(null);
|
|
3402
|
+
React22.useEffect(() => {
|
|
3392
3403
|
if (ref.current) ref.current.indeterminate = indeterminate;
|
|
3393
3404
|
}, [indeterminate]);
|
|
3394
3405
|
return /* @__PURE__ */ jsxs40("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
@@ -3447,7 +3458,7 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
|
|
|
3447
3458
|
}
|
|
3448
3459
|
|
|
3449
3460
|
// src/components/forms/NumberInput.tsx
|
|
3450
|
-
import * as
|
|
3461
|
+
import * as React23 from "react";
|
|
3451
3462
|
import { jsx as jsx48, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
3452
3463
|
function NumberInput({
|
|
3453
3464
|
label,
|
|
@@ -3475,10 +3486,10 @@ function NumberInput({
|
|
|
3475
3486
|
const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
|
|
3476
3487
|
return isNaN(n) ? null : n;
|
|
3477
3488
|
};
|
|
3478
|
-
const [text, setText] =
|
|
3479
|
-
const [editing, setEditing] =
|
|
3480
|
-
const timer =
|
|
3481
|
-
|
|
3489
|
+
const [text, setText] = React23.useState(value == null || value === "" ? "" : String(value));
|
|
3490
|
+
const [editing, setEditing] = React23.useState(false);
|
|
3491
|
+
const timer = React23.useRef(null);
|
|
3492
|
+
React23.useEffect(() => {
|
|
3482
3493
|
if (!editing) setText(value == null || value === "" ? "" : String(value));
|
|
3483
3494
|
}, [value, editing]);
|
|
3484
3495
|
const clamp = (n) => Math.min(max, Math.max(min, n));
|
|
@@ -3502,7 +3513,7 @@ function NumberInput({
|
|
|
3502
3513
|
const release = () => {
|
|
3503
3514
|
if (timer.current) clearTimeout(timer.current);
|
|
3504
3515
|
};
|
|
3505
|
-
|
|
3516
|
+
React23.useEffect(() => () => {
|
|
3506
3517
|
if (timer.current) clearTimeout(timer.current);
|
|
3507
3518
|
}, []);
|
|
3508
3519
|
const shown = editing ? text : (() => {
|
|
@@ -3589,7 +3600,7 @@ function NumberInput({
|
|
|
3589
3600
|
}
|
|
3590
3601
|
|
|
3591
3602
|
// src/components/forms/Select.tsx
|
|
3592
|
-
import * as
|
|
3603
|
+
import * as React24 from "react";
|
|
3593
3604
|
import { jsx as jsx49, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
3594
3605
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
3595
3606
|
function Select({
|
|
@@ -3616,13 +3627,13 @@ function Select({
|
|
|
3616
3627
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
3617
3628
|
const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
|
|
3618
3629
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
3619
|
-
const [open, setOpen] =
|
|
3620
|
-
const [q, setQ] =
|
|
3621
|
-
const [active, setActive] =
|
|
3622
|
-
const rootRef =
|
|
3623
|
-
const boxRef =
|
|
3624
|
-
const listRef =
|
|
3625
|
-
const typeBuf =
|
|
3630
|
+
const [open, setOpen] = React24.useState(false);
|
|
3631
|
+
const [q, setQ] = React24.useState("");
|
|
3632
|
+
const [active, setActive] = React24.useState(-1);
|
|
3633
|
+
const rootRef = React24.useRef(null);
|
|
3634
|
+
const boxRef = React24.useRef(null);
|
|
3635
|
+
const listRef = React24.useRef(null);
|
|
3636
|
+
const typeBuf = React24.useRef({ s: "", t: 0 });
|
|
3626
3637
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
3627
3638
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
3628
3639
|
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;
|
|
@@ -3647,7 +3658,7 @@ function Select({
|
|
|
3647
3658
|
}
|
|
3648
3659
|
setOpen(!open);
|
|
3649
3660
|
};
|
|
3650
|
-
|
|
3661
|
+
React24.useEffect(() => {
|
|
3651
3662
|
if (!open || active < 0 || !listRef.current) return;
|
|
3652
3663
|
const el = listRef.current.querySelector('[data-i="' + active + '"]');
|
|
3653
3664
|
if (el) {
|
|
@@ -3768,7 +3779,7 @@ function Select({
|
|
|
3768
3779
|
),
|
|
3769
3780
|
q ? /* @__PURE__ */ jsx49("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
3770
3781
|
] }) : void 0,
|
|
3771
|
-
footer: multiple ? /* @__PURE__ */ jsxs45(
|
|
3782
|
+
footer: multiple ? /* @__PURE__ */ jsxs45(React24.Fragment, { children: [
|
|
3772
3783
|
/* @__PURE__ */ jsx49(
|
|
3773
3784
|
"button",
|
|
3774
3785
|
{
|
|
@@ -3799,7 +3810,7 @@ function Select({
|
|
|
3799
3810
|
'Nothing matches "',
|
|
3800
3811
|
q,
|
|
3801
3812
|
'".'
|
|
3802
|
-
] }) : groups.map((grp) => /* @__PURE__ */ jsxs45(
|
|
3813
|
+
] }) : groups.map((grp) => /* @__PURE__ */ jsxs45(React24.Fragment, { children: [
|
|
3803
3814
|
grp.g ? /* @__PURE__ */ jsx49("div", { className: "fd-pop-group", children: grp.g }) : null,
|
|
3804
3815
|
grp.items.map(({ o, i }) => /* @__PURE__ */ jsxs45(
|
|
3805
3816
|
"button",
|
|
@@ -3836,7 +3847,7 @@ function Select({
|
|
|
3836
3847
|
}
|
|
3837
3848
|
|
|
3838
3849
|
// src/components/forms/DatePicker.tsx
|
|
3839
|
-
import * as
|
|
3850
|
+
import * as React25 from "react";
|
|
3840
3851
|
import { jsx as jsx50, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
3841
3852
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
3842
3853
|
var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
@@ -3854,10 +3865,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3854
3865
|
const today = /* @__PURE__ */ new Date();
|
|
3855
3866
|
const sel = range ? value || {} : { start: value, end: value };
|
|
3856
3867
|
const anchor = parse(sel.start) || parse(initialMonth) || today;
|
|
3857
|
-
const [vy, setVy] =
|
|
3858
|
-
const [vm, setVm] =
|
|
3859
|
-
const [mode2, setMode] =
|
|
3860
|
-
const [hover, setHover] =
|
|
3868
|
+
const [vy, setVy] = React25.useState(anchor.getFullYear());
|
|
3869
|
+
const [vm, setVm] = React25.useState(anchor.getMonth());
|
|
3870
|
+
const [mode2, setMode] = React25.useState("days");
|
|
3871
|
+
const [hover, setHover] = React25.useState(null);
|
|
3861
3872
|
const s = parse(sel.start), e = parse(sel.end);
|
|
3862
3873
|
const hoverEnd = range && s && !e && hover ? parse(hover) : null;
|
|
3863
3874
|
const inRange = (d) => {
|
|
@@ -3973,9 +3984,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3973
3984
|
}
|
|
3974
3985
|
function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, ...rest }) {
|
|
3975
3986
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
3976
|
-
const [open, setOpen] =
|
|
3977
|
-
const rootRef =
|
|
3978
|
-
const boxRef =
|
|
3987
|
+
const [open, setOpen] = React25.useState(false);
|
|
3988
|
+
const rootRef = React25.useRef(null);
|
|
3989
|
+
const boxRef = React25.useRef(null);
|
|
3979
3990
|
const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
|
|
3980
3991
|
const toggle = () => {
|
|
3981
3992
|
if (!disabled) setOpen(!open);
|
|
@@ -4038,7 +4049,7 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
4038
4049
|
}
|
|
4039
4050
|
|
|
4040
4051
|
// src/components/forms/TimePicker.tsx
|
|
4041
|
-
import * as
|
|
4052
|
+
import * as React26 from "react";
|
|
4042
4053
|
import { jsx as jsx51, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
4043
4054
|
var pad = (n) => String(n).padStart(2, "0");
|
|
4044
4055
|
function ClockFace({ value = "09:00", onChange }) {
|
|
@@ -4047,9 +4058,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
4047
4058
|
if (isNaN(m)) m = 0;
|
|
4048
4059
|
const pm = h24 >= 12;
|
|
4049
4060
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
4050
|
-
const [mode2, setMode] =
|
|
4051
|
-
const faceRef =
|
|
4052
|
-
const dragging =
|
|
4061
|
+
const [mode2, setMode] = React26.useState("h");
|
|
4062
|
+
const faceRef = React26.useRef(null);
|
|
4063
|
+
const dragging = React26.useRef(false);
|
|
4053
4064
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
4054
4065
|
const R = 108, NR = 80;
|
|
4055
4066
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -4122,9 +4133,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
4122
4133
|
}
|
|
4123
4134
|
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
|
|
4124
4135
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
4125
|
-
const [open, setOpen] =
|
|
4126
|
-
const rootRef =
|
|
4127
|
-
const boxRef =
|
|
4136
|
+
const [open, setOpen] = React26.useState(false);
|
|
4137
|
+
const rootRef = React26.useRef(null);
|
|
4138
|
+
const boxRef = React26.useRef(null);
|
|
4128
4139
|
const disp = () => {
|
|
4129
4140
|
if (!value) return "";
|
|
4130
4141
|
const [h, m] = value.split(":").map(Number);
|
|
@@ -4167,7 +4178,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4167
4178
|
offset: 6,
|
|
4168
4179
|
width: 262,
|
|
4169
4180
|
role: "presentation",
|
|
4170
|
-
footer: /* @__PURE__ */ jsxs47(
|
|
4181
|
+
footer: /* @__PURE__ */ jsxs47(React26.Fragment, { children: [
|
|
4171
4182
|
/* @__PURE__ */ jsx51(
|
|
4172
4183
|
"button",
|
|
4173
4184
|
{
|
|
@@ -4195,7 +4206,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4195
4206
|
}
|
|
4196
4207
|
|
|
4197
4208
|
// src/components/forms/Slider.tsx
|
|
4198
|
-
import * as
|
|
4209
|
+
import * as React27 from "react";
|
|
4199
4210
|
import { jsx as jsx52, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
4200
4211
|
function Slider({
|
|
4201
4212
|
label,
|
|
@@ -4213,7 +4224,7 @@ function Slider({
|
|
|
4213
4224
|
...rest
|
|
4214
4225
|
}) {
|
|
4215
4226
|
const fieldId = useFieldId(id);
|
|
4216
|
-
const [dragging, setDragging] =
|
|
4227
|
+
const [dragging, setDragging] = React27.useState(false);
|
|
4217
4228
|
const v = value === void 0 ? min : Number(value);
|
|
4218
4229
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
4219
4230
|
return /* @__PURE__ */ jsxs48("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
|
|
@@ -4247,7 +4258,7 @@ function Slider({
|
|
|
4247
4258
|
}
|
|
4248
4259
|
|
|
4249
4260
|
// src/components/forms/RangeSlider.tsx
|
|
4250
|
-
import * as
|
|
4261
|
+
import * as React28 from "react";
|
|
4251
4262
|
import { jsx as jsx53, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
4252
4263
|
function RangeSlider({
|
|
4253
4264
|
label,
|
|
@@ -4267,9 +4278,9 @@ function RangeSlider({
|
|
|
4267
4278
|
}) {
|
|
4268
4279
|
const fmt2 = format || ((v) => String(v));
|
|
4269
4280
|
const [a, b] = value || [min, max];
|
|
4270
|
-
const [drag, setDrag] =
|
|
4271
|
-
const [focus, setFocus] =
|
|
4272
|
-
const railRef =
|
|
4281
|
+
const [drag, setDrag] = React28.useState(null);
|
|
4282
|
+
const [focus, setFocus] = React28.useState(null);
|
|
4283
|
+
const railRef = React28.useRef(null);
|
|
4273
4284
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
4274
4285
|
const clampPair = (i, v) => {
|
|
4275
4286
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -4284,7 +4295,7 @@ function RangeSlider({
|
|
|
4284
4295
|
const r = railRef.current.getBoundingClientRect();
|
|
4285
4296
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
4286
4297
|
};
|
|
4287
|
-
|
|
4298
|
+
React28.useEffect(() => {
|
|
4288
4299
|
if (drag === null) return;
|
|
4289
4300
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
4290
4301
|
const upH = () => setDrag(null);
|
|
@@ -4365,7 +4376,7 @@ function RangeSlider({
|
|
|
4365
4376
|
/* @__PURE__ */ jsxs49("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
|
|
4366
4377
|
/* @__PURE__ */ jsx53("span", { className: "fd-range-rail", ref: railRef }),
|
|
4367
4378
|
/* @__PURE__ */ jsx53("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
|
|
4368
|
-
marks.map((m) => /* @__PURE__ */ jsxs49(
|
|
4379
|
+
marks.map((m) => /* @__PURE__ */ jsxs49(React28.Fragment, { children: [
|
|
4369
4380
|
/* @__PURE__ */ jsx53("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
|
|
4370
4381
|
m.label ? /* @__PURE__ */ jsx53("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
|
|
4371
4382
|
] }, m.value)),
|
|
@@ -4394,7 +4405,7 @@ function RangeSlider({
|
|
|
4394
4405
|
}
|
|
4395
4406
|
|
|
4396
4407
|
// src/components/forms/Dropzone.tsx
|
|
4397
|
-
import * as
|
|
4408
|
+
import * as React29 from "react";
|
|
4398
4409
|
import { jsx as jsx54, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
4399
4410
|
function Dropzone({
|
|
4400
4411
|
onFiles,
|
|
@@ -4409,8 +4420,8 @@ function Dropzone({
|
|
|
4409
4420
|
className = "",
|
|
4410
4421
|
style
|
|
4411
4422
|
}) {
|
|
4412
|
-
const [over, setOver] =
|
|
4413
|
-
const depth =
|
|
4423
|
+
const [over, setOver] = React29.useState(false);
|
|
4424
|
+
const depth = React29.useRef(0);
|
|
4414
4425
|
const has = (e) => {
|
|
4415
4426
|
const dt = e.dataTransfer;
|
|
4416
4427
|
if (!dt) return false;
|
|
@@ -4472,8 +4483,8 @@ function FilePickButton({
|
|
|
4472
4483
|
className = "",
|
|
4473
4484
|
children
|
|
4474
4485
|
}) {
|
|
4475
|
-
const ref =
|
|
4476
|
-
return /* @__PURE__ */ jsxs50(
|
|
4486
|
+
const ref = React29.useRef(null);
|
|
4487
|
+
return /* @__PURE__ */ jsxs50(React29.Fragment, { children: [
|
|
4477
4488
|
/* @__PURE__ */ jsx54(
|
|
4478
4489
|
"button",
|
|
4479
4490
|
{
|
|
@@ -4506,10 +4517,10 @@ function FilePickButton({
|
|
|
4506
4517
|
}
|
|
4507
4518
|
function useStagedFiles(upload, opts) {
|
|
4508
4519
|
const o = opts || {};
|
|
4509
|
-
const [items, setItems] =
|
|
4510
|
-
const controllers =
|
|
4520
|
+
const [items, setItems] = React29.useState([]);
|
|
4521
|
+
const controllers = React29.useRef({});
|
|
4511
4522
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
4512
|
-
const run =
|
|
4523
|
+
const run = React29.useCallback((att) => {
|
|
4513
4524
|
if (!upload) return;
|
|
4514
4525
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
4515
4526
|
controllers.current[att.id] = ac;
|
|
@@ -4526,14 +4537,14 @@ function useStagedFiles(upload, opts) {
|
|
|
4526
4537
|
delete controllers.current[att.id];
|
|
4527
4538
|
});
|
|
4528
4539
|
}, [upload]);
|
|
4529
|
-
const add =
|
|
4540
|
+
const add = React29.useCallback((files) => {
|
|
4530
4541
|
if (!upload) return [];
|
|
4531
4542
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
4532
4543
|
setItems((list) => list.concat(atts));
|
|
4533
4544
|
atts.forEach(run);
|
|
4534
4545
|
return atts;
|
|
4535
4546
|
}, [upload, run]);
|
|
4536
|
-
const remove =
|
|
4547
|
+
const remove = React29.useCallback((att) => {
|
|
4537
4548
|
const ac = controllers.current[att.id];
|
|
4538
4549
|
if (ac) {
|
|
4539
4550
|
try {
|
|
@@ -4544,10 +4555,10 @@ function useStagedFiles(upload, opts) {
|
|
|
4544
4555
|
}
|
|
4545
4556
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
4546
4557
|
}, []);
|
|
4547
|
-
const retry =
|
|
4558
|
+
const retry = React29.useCallback((att) => {
|
|
4548
4559
|
run(att);
|
|
4549
4560
|
}, [run]);
|
|
4550
|
-
const clear =
|
|
4561
|
+
const clear = React29.useCallback(() => {
|
|
4551
4562
|
Object.values(controllers.current).forEach((ac) => {
|
|
4552
4563
|
try {
|
|
4553
4564
|
ac && ac.abort();
|
|
@@ -4671,7 +4682,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
4671
4682
|
}
|
|
4672
4683
|
|
|
4673
4684
|
// src/components/forms/MarkdownEditor.tsx
|
|
4674
|
-
import * as
|
|
4685
|
+
import * as React30 from "react";
|
|
4675
4686
|
import { jsx as jsx56, jsxs as jsxs52 } from "react/jsx-runtime";
|
|
4676
4687
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
4677
4688
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
@@ -4885,7 +4896,7 @@ function syncDom(root, value) {
|
|
|
4885
4896
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
4886
4897
|
}
|
|
4887
4898
|
var LIST_CONT = RE_LI;
|
|
4888
|
-
var MarkdownEditor =
|
|
4899
|
+
var MarkdownEditor = React30.forwardRef(function MarkdownEditor2({
|
|
4889
4900
|
value = "",
|
|
4890
4901
|
onChange,
|
|
4891
4902
|
onSubmit,
|
|
@@ -4904,10 +4915,10 @@ var MarkdownEditor = React29.forwardRef(function MarkdownEditor2({
|
|
|
4904
4915
|
className = "",
|
|
4905
4916
|
id
|
|
4906
4917
|
}, ref) {
|
|
4907
|
-
const boxRef =
|
|
4908
|
-
const composing =
|
|
4909
|
-
const pendingCaret =
|
|
4910
|
-
|
|
4918
|
+
const boxRef = React30.useRef(null);
|
|
4919
|
+
const composing = React30.useRef(false);
|
|
4920
|
+
const pendingCaret = React30.useRef(null);
|
|
4921
|
+
React30.useLayoutEffect(() => {
|
|
4911
4922
|
const root = boxRef.current;
|
|
4912
4923
|
if (!root || composing.current) return;
|
|
4913
4924
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -4916,7 +4927,7 @@ var MarkdownEditor = React29.forwardRef(function MarkdownEditor2({
|
|
|
4916
4927
|
pendingCaret.current = null;
|
|
4917
4928
|
if (active && caret != null) placeCaret(root, caret);
|
|
4918
4929
|
}, [value]);
|
|
4919
|
-
|
|
4930
|
+
React30.useEffect(() => {
|
|
4920
4931
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
4921
4932
|
}, [autoFocus]);
|
|
4922
4933
|
const caretNow = () => {
|
|
@@ -4983,7 +4994,7 @@ var MarkdownEditor = React29.forwardRef(function MarkdownEditor2({
|
|
|
4983
4994
|
api.replaceRange(from, to, next, from + next.length);
|
|
4984
4995
|
}
|
|
4985
4996
|
};
|
|
4986
|
-
|
|
4997
|
+
React30.useImperativeHandle(ref, () => api);
|
|
4987
4998
|
function detect(text, caret) {
|
|
4988
4999
|
if (!onTrigger) return;
|
|
4989
5000
|
const upto = text.slice(0, caret);
|
|
@@ -5135,16 +5146,16 @@ var MarkdownEditor = React29.forwardRef(function MarkdownEditor2({
|
|
|
5135
5146
|
});
|
|
5136
5147
|
|
|
5137
5148
|
// src/components/platform/AccountMenu.tsx
|
|
5138
|
-
import * as
|
|
5149
|
+
import * as React32 from "react";
|
|
5139
5150
|
|
|
5140
5151
|
// src/kits/sessionContext.tsx
|
|
5141
|
-
import * as
|
|
5142
|
-
var SessionContext =
|
|
5152
|
+
import * as React31 from "react";
|
|
5153
|
+
var SessionContext = React31.createContext(null);
|
|
5143
5154
|
function SessionProvider({ value, children }) {
|
|
5144
|
-
return
|
|
5155
|
+
return React31.createElement(SessionContext.Provider, { value }, children);
|
|
5145
5156
|
}
|
|
5146
5157
|
function useSessionContext() {
|
|
5147
|
-
const ctx =
|
|
5158
|
+
const ctx = React31.useContext(SessionContext);
|
|
5148
5159
|
if (!ctx) {
|
|
5149
5160
|
throw new Error(
|
|
5150
5161
|
"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."
|
|
@@ -5155,20 +5166,8 @@ function useSessionContext() {
|
|
|
5155
5166
|
|
|
5156
5167
|
// src/components/platform/AccountMenu.tsx
|
|
5157
5168
|
import { Fragment as Fragment14, jsx as jsx57, jsxs as jsxs53 } from "react/jsx-runtime";
|
|
5158
|
-
var DEFAULT_LINKS = [
|
|
5159
|
-
|
|
5160
|
-
{ id: "preferences", label: "Preferences", icon: "sliders-horizontal", href: "../admin/index.html#preferences" }
|
|
5161
|
-
];
|
|
5162
|
-
var DEFAULT_GROUPS = [
|
|
5163
|
-
{
|
|
5164
|
-
label: "Administration",
|
|
5165
|
-
links: [
|
|
5166
|
-
{ id: "users", label: "Users", icon: "users-three", href: "../admin/index.html#users", perm: "users.view" },
|
|
5167
|
-
{ id: "roles", label: "Roles & permissions", icon: "shield-check", href: "../admin/index.html#roles", perm: "roles.manage" },
|
|
5168
|
-
{ id: "flags", label: "Feature flags", icon: "toggle-right", href: "../admin/index.html#flags", perm: "flags.manage" }
|
|
5169
|
-
]
|
|
5170
|
-
}
|
|
5171
|
-
];
|
|
5169
|
+
var DEFAULT_LINKS = [];
|
|
5170
|
+
var DEFAULT_GROUPS = [];
|
|
5172
5171
|
function Item({ item, onPick }) {
|
|
5173
5172
|
return /* @__PURE__ */ jsxs53(
|
|
5174
5173
|
"button",
|
|
@@ -5196,10 +5195,10 @@ function AccountMenu({
|
|
|
5196
5195
|
...rest
|
|
5197
5196
|
}) {
|
|
5198
5197
|
const { user, roles, can: can2, signOut: ctxSignOut, demo } = useSessionContext();
|
|
5199
|
-
const [open, setOpen] =
|
|
5200
|
-
const [switching, setSwitching] =
|
|
5201
|
-
const [signingOut, setSigningOut] =
|
|
5202
|
-
const ref =
|
|
5198
|
+
const [open, setOpen] = React32.useState(false);
|
|
5199
|
+
const [switching, setSwitching] = React32.useState(false);
|
|
5200
|
+
const [signingOut, setSigningOut] = React32.useState(false);
|
|
5201
|
+
const ref = React32.useRef(null);
|
|
5203
5202
|
const visibleLinks = links.filter((l) => !l.perm || can2(l.perm));
|
|
5204
5203
|
const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || can2(l.perm)) })).filter((g) => g.links.length);
|
|
5205
5204
|
const pick = (item) => {
|
|
@@ -5302,13 +5301,13 @@ function AccountMenu({
|
|
|
5302
5301
|
}
|
|
5303
5302
|
|
|
5304
5303
|
// src/components/platform/AppSwitcher.tsx
|
|
5305
|
-
import * as
|
|
5304
|
+
import * as React33 from "react";
|
|
5306
5305
|
import { jsx as jsx58, jsxs as jsxs54 } from "react/jsx-runtime";
|
|
5307
5306
|
function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
5308
5307
|
const { apps: contextApps } = useSessionContext();
|
|
5309
5308
|
const apps = appsProp ?? contextApps ?? [];
|
|
5310
|
-
const [open, setOpen] =
|
|
5311
|
-
const anchorRef =
|
|
5309
|
+
const [open, setOpen] = React33.useState(false);
|
|
5310
|
+
const anchorRef = React33.useRef(null);
|
|
5312
5311
|
if (!apps.length) return null;
|
|
5313
5312
|
const items = apps.map((app) => ({
|
|
5314
5313
|
id: app.key,
|
|
@@ -5322,7 +5321,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
5322
5321
|
window.location.href = app.url;
|
|
5323
5322
|
}
|
|
5324
5323
|
}));
|
|
5325
|
-
return /* @__PURE__ */ jsxs54(
|
|
5324
|
+
return /* @__PURE__ */ jsxs54(React33.Fragment, { children: [
|
|
5326
5325
|
/* @__PURE__ */ jsx58("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx58(
|
|
5327
5326
|
IconButton,
|
|
5328
5327
|
{
|
|
@@ -5351,10 +5350,10 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
5351
5350
|
}
|
|
5352
5351
|
|
|
5353
5352
|
// src/components/platform/AppearanceMenu.tsx
|
|
5354
|
-
import * as
|
|
5353
|
+
import * as React35 from "react";
|
|
5355
5354
|
|
|
5356
5355
|
// src/kits/appearance.ts
|
|
5357
|
-
import * as
|
|
5356
|
+
import * as React34 from "react";
|
|
5358
5357
|
var DEFAULT_STORAGE_KEY = "fd-appearance";
|
|
5359
5358
|
var DEFAULT_PREFS = {
|
|
5360
5359
|
theme: "system",
|
|
@@ -5449,11 +5448,11 @@ function applyPrefs(prefs, root = document.documentElement) {
|
|
|
5449
5448
|
else root.removeAttribute("data-motion");
|
|
5450
5449
|
}
|
|
5451
5450
|
function useAppearancePrefs(store) {
|
|
5452
|
-
const prefs =
|
|
5453
|
-
|
|
5451
|
+
const prefs = React34.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
5452
|
+
React34.useEffect(() => {
|
|
5454
5453
|
applyPrefs(prefs);
|
|
5455
5454
|
}, [prefs]);
|
|
5456
|
-
|
|
5455
|
+
React34.useEffect(() => {
|
|
5457
5456
|
if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
5458
5457
|
return;
|
|
5459
5458
|
}
|
|
@@ -5462,7 +5461,7 @@ function useAppearancePrefs(store) {
|
|
|
5462
5461
|
mq.addEventListener("change", onChange);
|
|
5463
5462
|
return () => mq.removeEventListener("change", onChange);
|
|
5464
5463
|
}, [prefs]);
|
|
5465
|
-
const update =
|
|
5464
|
+
const update = React34.useCallback(
|
|
5466
5465
|
(patch) => {
|
|
5467
5466
|
store.write({ ...store.getSnapshot(), ...patch });
|
|
5468
5467
|
},
|
|
@@ -5485,15 +5484,15 @@ var TEXT_SCALE_OPTIONS = [
|
|
|
5485
5484
|
{ value: "xl", label: "XL" }
|
|
5486
5485
|
];
|
|
5487
5486
|
function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
|
|
5488
|
-
const store =
|
|
5487
|
+
const store = React35.useMemo(
|
|
5489
5488
|
() => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
|
|
5490
5489
|
[storeProp, storageKey, storage, defaults]
|
|
5491
5490
|
);
|
|
5492
5491
|
const [prefs, update] = useAppearancePrefs(store);
|
|
5493
|
-
const [open, setOpen] =
|
|
5494
|
-
const anchorRef =
|
|
5492
|
+
const [open, setOpen] = React35.useState(false);
|
|
5493
|
+
const anchorRef = React35.useRef(null);
|
|
5495
5494
|
const patch = (p) => update(p);
|
|
5496
|
-
return /* @__PURE__ */ jsxs55(
|
|
5495
|
+
return /* @__PURE__ */ jsxs55(React35.Fragment, { children: [
|
|
5497
5496
|
/* @__PURE__ */ jsx59("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx59(
|
|
5498
5497
|
IconButton,
|
|
5499
5498
|
{
|
|
@@ -5562,14 +5561,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
5562
5561
|
}
|
|
5563
5562
|
|
|
5564
5563
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
5565
|
-
import * as
|
|
5564
|
+
import * as React36 from "react";
|
|
5566
5565
|
import { jsx as jsx60, jsxs as jsxs56 } from "react/jsx-runtime";
|
|
5567
5566
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
5568
5567
|
function Json({ obj }) {
|
|
5569
5568
|
return /* @__PURE__ */ jsx60("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
5570
5569
|
}
|
|
5571
5570
|
function Endpoint({ s, onRequest }) {
|
|
5572
|
-
const [tried, setTried] =
|
|
5571
|
+
const [tried, setTried] = React36.useState(null);
|
|
5573
5572
|
const run = async () => {
|
|
5574
5573
|
setTried("busy");
|
|
5575
5574
|
const t0 = (window.performance || Date).now();
|
|
@@ -5642,10 +5641,10 @@ function ApiSpecBrowser({
|
|
|
5642
5641
|
className = "",
|
|
5643
5642
|
...rest
|
|
5644
5643
|
}) {
|
|
5645
|
-
const [q, setQ] =
|
|
5646
|
-
const [method, setMethod] =
|
|
5647
|
-
const [mod, setMod] =
|
|
5648
|
-
const [listOnly, setListOnly] =
|
|
5644
|
+
const [q, setQ] = React36.useState("");
|
|
5645
|
+
const [method, setMethod] = React36.useState(null);
|
|
5646
|
+
const [mod, setMod] = React36.useState(null);
|
|
5647
|
+
const [listOnly, setListOnly] = React36.useState(false);
|
|
5649
5648
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
5650
5649
|
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())));
|
|
5651
5650
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
@@ -5724,7 +5723,7 @@ function ApiSpecBrowser({
|
|
|
5724
5723
|
}
|
|
5725
5724
|
|
|
5726
5725
|
// src/components/platform/ProfilePage.tsx
|
|
5727
|
-
import * as
|
|
5726
|
+
import * as React37 from "react";
|
|
5728
5727
|
import { jsx as jsx61, jsxs as jsxs57 } from "react/jsx-runtime";
|
|
5729
5728
|
function fieldInitialValue(field, user) {
|
|
5730
5729
|
if (field.value) return field.value(user);
|
|
@@ -5760,21 +5759,21 @@ function ProfilePage({
|
|
|
5760
5759
|
}) {
|
|
5761
5760
|
const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
|
|
5762
5761
|
const user = userProp || sessionUser;
|
|
5763
|
-
const initialFieldValues =
|
|
5762
|
+
const initialFieldValues = React37.useMemo(() => {
|
|
5764
5763
|
const values2 = {};
|
|
5765
5764
|
for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
|
|
5766
5765
|
return values2;
|
|
5767
5766
|
}, [user.id, fields]);
|
|
5768
|
-
const initialNotify =
|
|
5767
|
+
const initialNotify = React37.useMemo(() => {
|
|
5769
5768
|
const values2 = {};
|
|
5770
5769
|
for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
|
|
5771
5770
|
return values2;
|
|
5772
5771
|
}, [user.id, notifications]);
|
|
5773
|
-
const [values, setValues] =
|
|
5774
|
-
const [notify, setNotify] =
|
|
5775
|
-
const [saving, setSaving] =
|
|
5776
|
-
const [saved, setSaved] =
|
|
5777
|
-
const [prevUserId, setPrevUserId] =
|
|
5772
|
+
const [values, setValues] = React37.useState(initialFieldValues);
|
|
5773
|
+
const [notify, setNotify] = React37.useState(initialNotify);
|
|
5774
|
+
const [saving, setSaving] = React37.useState(false);
|
|
5775
|
+
const [saved, setSaved] = React37.useState(false);
|
|
5776
|
+
const [prevUserId, setPrevUserId] = React37.useState(user.id);
|
|
5778
5777
|
if (user.id !== prevUserId) {
|
|
5779
5778
|
setPrevUserId(user.id);
|
|
5780
5779
|
setValues(initialFieldValues);
|
|
@@ -5962,10 +5961,10 @@ function ProfilePage({
|
|
|
5962
5961
|
}
|
|
5963
5962
|
|
|
5964
5963
|
// src/components/platform/RoadmapTimeline.tsx
|
|
5965
|
-
import * as
|
|
5964
|
+
import * as React40 from "react";
|
|
5966
5965
|
|
|
5967
5966
|
// src/kits/session.ts
|
|
5968
|
-
import * as
|
|
5967
|
+
import * as React38 from "react";
|
|
5969
5968
|
var PERMISSION_CATALOG = [
|
|
5970
5969
|
{ group: "Plans", items: [
|
|
5971
5970
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -7532,8 +7531,8 @@ function roadmap(overrides) {
|
|
|
7532
7531
|
};
|
|
7533
7532
|
}
|
|
7534
7533
|
function useSession() {
|
|
7535
|
-
const [s, setS] =
|
|
7536
|
-
|
|
7534
|
+
const [s, setS] = React38.useState(getSession);
|
|
7535
|
+
React38.useEffect(() => subscribe(setS), []);
|
|
7537
7536
|
return s;
|
|
7538
7537
|
}
|
|
7539
7538
|
var SessionKit = {
|
|
@@ -7566,7 +7565,7 @@ var SessionKit = {
|
|
|
7566
7565
|
};
|
|
7567
7566
|
function DemoSessionProvider({ children }) {
|
|
7568
7567
|
const session = useSession();
|
|
7569
|
-
const value =
|
|
7568
|
+
const value = React38.useMemo(
|
|
7570
7569
|
() => ({
|
|
7571
7570
|
user: session.user,
|
|
7572
7571
|
roles: session.roles,
|
|
@@ -7582,11 +7581,11 @@ function DemoSessionProvider({ children }) {
|
|
|
7582
7581
|
}),
|
|
7583
7582
|
[session]
|
|
7584
7583
|
);
|
|
7585
|
-
return
|
|
7584
|
+
return React38.createElement(SessionProvider, { value }, children);
|
|
7586
7585
|
}
|
|
7587
7586
|
|
|
7588
7587
|
// src/kits/runtime.ts
|
|
7589
|
-
import * as
|
|
7588
|
+
import * as React39 from "react";
|
|
7590
7589
|
var WIRED_ENDPOINTS = [
|
|
7591
7590
|
// Nothing yet. Every id below would come from a real service:
|
|
7592
7591
|
// "plan.get", "placements.list", …
|
|
@@ -7757,8 +7756,8 @@ var RuntimeKit = {
|
|
|
7757
7756
|
};
|
|
7758
7757
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
7759
7758
|
function useRuntimeMode() {
|
|
7760
|
-
const [m, setM] =
|
|
7761
|
-
|
|
7759
|
+
const [m, setM] = React39.useState(RuntimeKit.getMode());
|
|
7760
|
+
React39.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
7762
7761
|
return m;
|
|
7763
7762
|
}
|
|
7764
7763
|
function useFeatureStatus(key) {
|
|
@@ -7841,12 +7840,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
7841
7840
|
}
|
|
7842
7841
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
7843
7842
|
const session = SessionKit.useSession();
|
|
7844
|
-
const [project, setProject] =
|
|
7845
|
-
const [q, setQ] =
|
|
7846
|
-
const scrollRef =
|
|
7847
|
-
const nowRef =
|
|
7848
|
-
const rm =
|
|
7849
|
-
const byKey =
|
|
7843
|
+
const [project, setProject] = React40.useState("");
|
|
7844
|
+
const [q, setQ] = React40.useState("");
|
|
7845
|
+
const scrollRef = React40.useRef(null);
|
|
7846
|
+
const nowRef = React40.useRef(null);
|
|
7847
|
+
const rm = React40.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
7848
|
+
const byKey = React40.useMemo(() => {
|
|
7850
7849
|
const m = {};
|
|
7851
7850
|
rm.items.forEach((i) => {
|
|
7852
7851
|
m[i.key] = i;
|
|
@@ -7855,7 +7854,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7855
7854
|
}, [rm]);
|
|
7856
7855
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
7857
7856
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
7858
|
-
|
|
7857
|
+
React40.useEffect(() => {
|
|
7859
7858
|
let raf1 = 0, raf2 = 0;
|
|
7860
7859
|
const place = () => {
|
|
7861
7860
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -7929,7 +7928,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7929
7928
|
lastPhase = item.phase;
|
|
7930
7929
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
7931
7930
|
const isBoundary = n === firstPending;
|
|
7932
|
-
return /* @__PURE__ */ jsxs58(
|
|
7931
|
+
return /* @__PURE__ */ jsxs58(React40.Fragment, { children: [
|
|
7933
7932
|
showPhase ? /* @__PURE__ */ jsxs58("div", { className: "fd-rm-era", children: [
|
|
7934
7933
|
/* @__PURE__ */ jsxs58("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
7935
7934
|
/* @__PURE__ */ jsx62("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
@@ -7973,7 +7972,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7973
7972
|
}
|
|
7974
7973
|
|
|
7975
7974
|
// src/components/platform/ComingSoon.tsx
|
|
7976
|
-
import * as
|
|
7975
|
+
import * as React41 from "react";
|
|
7977
7976
|
import { createPortal as createPortal5 } from "react-dom";
|
|
7978
7977
|
import { Fragment as Fragment18, jsx as jsx63, jsxs as jsxs59 } from "react/jsx-runtime";
|
|
7979
7978
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
@@ -7991,8 +7990,8 @@ function writeBypassed(list) {
|
|
|
7991
7990
|
}
|
|
7992
7991
|
}
|
|
7993
7992
|
function useBypass(key) {
|
|
7994
|
-
const [on, setOn] =
|
|
7995
|
-
|
|
7993
|
+
const [on, setOn] = React41.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
7994
|
+
React41.useEffect(() => {
|
|
7996
7995
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
7997
7996
|
}, [key]);
|
|
7998
7997
|
const set = (next) => {
|
|
@@ -8039,9 +8038,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
|
|
|
8039
8038
|
] });
|
|
8040
8039
|
}
|
|
8041
8040
|
function useHoverCard(open) {
|
|
8042
|
-
const anchor =
|
|
8043
|
-
const [pos, setPos] =
|
|
8044
|
-
|
|
8041
|
+
const anchor = React41.useRef(null);
|
|
8042
|
+
const [pos, setPos] = React41.useState(null);
|
|
8043
|
+
React41.useLayoutEffect(() => {
|
|
8045
8044
|
if (!open || !anchor.current) {
|
|
8046
8045
|
setPos(null);
|
|
8047
8046
|
return;
|
|
@@ -8168,10 +8167,10 @@ function ComingSoon({
|
|
|
8168
8167
|
] });
|
|
8169
8168
|
}
|
|
8170
8169
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
8171
|
-
const [open, setOpen] =
|
|
8170
|
+
const [open, setOpen] = React41.useState(false);
|
|
8172
8171
|
const [anchor, pos] = useHoverCard(open);
|
|
8173
8172
|
const zIndex = useOverlayLayer(open);
|
|
8174
|
-
const close =
|
|
8173
|
+
const close = React41.useRef(null);
|
|
8175
8174
|
const show = () => {
|
|
8176
8175
|
if (close.current) {
|
|
8177
8176
|
clearTimeout(close.current);
|
|
@@ -8187,7 +8186,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
8187
8186
|
setOpen(false);
|
|
8188
8187
|
}, 140);
|
|
8189
8188
|
};
|
|
8190
|
-
|
|
8189
|
+
React41.useEffect(() => () => {
|
|
8191
8190
|
if (close.current) clearTimeout(close.current);
|
|
8192
8191
|
}, []);
|
|
8193
8192
|
return /* @__PURE__ */ jsxs59(
|
|
@@ -8358,14 +8357,14 @@ function PermissionHint({ perm, children }) {
|
|
|
8358
8357
|
}
|
|
8359
8358
|
|
|
8360
8359
|
// src/components/platform/ModeSwitch.tsx
|
|
8361
|
-
import * as
|
|
8360
|
+
import * as React42 from "react";
|
|
8362
8361
|
import { Fragment as Fragment19, jsx as jsx65, jsxs as jsxs61 } from "react/jsx-runtime";
|
|
8363
8362
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
8364
8363
|
const mode2 = useRuntimeMode();
|
|
8365
|
-
const [open, setOpen] =
|
|
8364
|
+
const [open, setOpen] = React42.useState(false);
|
|
8366
8365
|
const zIndex = useOverlayLayer(open);
|
|
8367
|
-
const ref =
|
|
8368
|
-
|
|
8366
|
+
const ref = React42.useRef(null);
|
|
8367
|
+
React42.useEffect(() => {
|
|
8369
8368
|
if (!open) return;
|
|
8370
8369
|
const away = (e) => {
|
|
8371
8370
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -8621,7 +8620,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8621
8620
|
}
|
|
8622
8621
|
|
|
8623
8622
|
// src/components/planner/MixGap.tsx
|
|
8624
|
-
import * as
|
|
8623
|
+
import * as React43 from "react";
|
|
8625
8624
|
import { Fragment as Fragment20, jsx as jsx68, jsxs as jsxs64 } from "react/jsx-runtime";
|
|
8626
8625
|
var MIX_GAP_LAYOUT = {
|
|
8627
8626
|
trackHeight: 30,
|
|
@@ -8636,7 +8635,7 @@ function mixGapOffset(value, max) {
|
|
|
8636
8635
|
}
|
|
8637
8636
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
8638
8637
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
8639
|
-
const [hover, setHover] =
|
|
8638
|
+
const [hover, setHover] = React43.useState(null);
|
|
8640
8639
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
8641
8640
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
8642
8641
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
@@ -8779,7 +8778,7 @@ function ChannelContribution({
|
|
|
8779
8778
|
}
|
|
8780
8779
|
|
|
8781
8780
|
// src/components/planner/BudgetReallocator.tsx
|
|
8782
|
-
import * as
|
|
8781
|
+
import * as React44 from "react";
|
|
8783
8782
|
import { Fragment as Fragment21, jsx as jsx70, jsxs as jsxs66 } from "react/jsx-runtime";
|
|
8784
8783
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
8785
8784
|
function BudgetReallocator({
|
|
@@ -8795,8 +8794,8 @@ function BudgetReallocator({
|
|
|
8795
8794
|
onCancel,
|
|
8796
8795
|
className = ""
|
|
8797
8796
|
}) {
|
|
8798
|
-
const [draft, setDraft] =
|
|
8799
|
-
|
|
8797
|
+
const [draft, setDraft] = React44.useState(spend);
|
|
8798
|
+
React44.useEffect(() => setDraft(spend), [spend]);
|
|
8800
8799
|
const dirty = draft !== spend;
|
|
8801
8800
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
8802
8801
|
const nextBand = bandFor(nextCrp);
|
|
@@ -8811,10 +8810,10 @@ function BudgetReallocator({
|
|
|
8811
8810
|
setDraft(spend);
|
|
8812
8811
|
if (onCancel) onCancel();
|
|
8813
8812
|
};
|
|
8814
|
-
const trackRef =
|
|
8815
|
-
const chipRef =
|
|
8816
|
-
const [chipLeft, setChipLeft] =
|
|
8817
|
-
|
|
8813
|
+
const trackRef = React44.useRef(null);
|
|
8814
|
+
const chipRef = React44.useRef(null);
|
|
8815
|
+
const [chipLeft, setChipLeft] = React44.useState(null);
|
|
8816
|
+
React44.useLayoutEffect(() => {
|
|
8818
8817
|
const track = trackRef.current;
|
|
8819
8818
|
if (!dirty || !track) {
|
|
8820
8819
|
setChipLeft(null);
|
|
@@ -9001,7 +9000,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "" })
|
|
|
9001
9000
|
}
|
|
9002
9001
|
|
|
9003
9002
|
// src/components/planner/PreferenceMeter.tsx
|
|
9004
|
-
import * as
|
|
9003
|
+
import * as React45 from "react";
|
|
9005
9004
|
import { jsx as jsx73, jsxs as jsxs69 } from "react/jsx-runtime";
|
|
9006
9005
|
function preferenceScore(criteria) {
|
|
9007
9006
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
@@ -9031,7 +9030,7 @@ function PreferenceMeter({
|
|
|
9031
9030
|
className = ""
|
|
9032
9031
|
}) {
|
|
9033
9032
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
9034
|
-
const segments =
|
|
9033
|
+
const segments = React45.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
9035
9034
|
return /* @__PURE__ */ jsx73(
|
|
9036
9035
|
ScoreMeter,
|
|
9037
9036
|
{
|
|
@@ -9070,10 +9069,10 @@ function PreferenceMeter({
|
|
|
9070
9069
|
}
|
|
9071
9070
|
|
|
9072
9071
|
// src/components/chat/AgentChatPanel.tsx
|
|
9073
|
-
import * as
|
|
9072
|
+
import * as React51 from "react";
|
|
9074
9073
|
|
|
9075
9074
|
// src/components/chat/chatEngine.ts
|
|
9076
|
-
import * as
|
|
9075
|
+
import * as React46 from "react";
|
|
9077
9076
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
9078
9077
|
var JOB_PENDING = ["queued", "running"];
|
|
9079
9078
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -9127,22 +9126,22 @@ function useChatEngine(opts) {
|
|
|
9127
9126
|
onClear,
|
|
9128
9127
|
onFeedback
|
|
9129
9128
|
} = opts || {};
|
|
9130
|
-
const [status, setStatus] =
|
|
9131
|
-
const [threadId, setThreadId] =
|
|
9132
|
-
const [messages, setMessages] =
|
|
9133
|
-
const [queue, setQueue] =
|
|
9134
|
-
const [fatal, setFatal] =
|
|
9135
|
-
const [busy, setBusy] =
|
|
9136
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
9137
|
-
const listRef =
|
|
9138
|
-
const queueRef =
|
|
9139
|
-
const busyRef =
|
|
9140
|
-
const stoppedRef =
|
|
9141
|
-
const abortRef =
|
|
9142
|
-
const serverCount =
|
|
9143
|
-
const threadRef =
|
|
9144
|
-
const mounted =
|
|
9145
|
-
|
|
9129
|
+
const [status, setStatus] = React46.useState("idle");
|
|
9130
|
+
const [threadId, setThreadId] = React46.useState(null);
|
|
9131
|
+
const [messages, setMessages] = React46.useState([]);
|
|
9132
|
+
const [queue, setQueue] = React46.useState([]);
|
|
9133
|
+
const [fatal, setFatal] = React46.useState(null);
|
|
9134
|
+
const [busy, setBusy] = React46.useState(false);
|
|
9135
|
+
const [turnStartedAt, setTurnStartedAt] = React46.useState(null);
|
|
9136
|
+
const listRef = React46.useRef([]);
|
|
9137
|
+
const queueRef = React46.useRef([]);
|
|
9138
|
+
const busyRef = React46.useRef(false);
|
|
9139
|
+
const stoppedRef = React46.useRef(false);
|
|
9140
|
+
const abortRef = React46.useRef(null);
|
|
9141
|
+
const serverCount = React46.useRef(0);
|
|
9142
|
+
const threadRef = React46.useRef(null);
|
|
9143
|
+
const mounted = React46.useRef(true);
|
|
9144
|
+
React46.useEffect(() => {
|
|
9146
9145
|
mounted.current = true;
|
|
9147
9146
|
return () => {
|
|
9148
9147
|
mounted.current = false;
|
|
@@ -9164,14 +9163,14 @@ function useChatEngine(opts) {
|
|
|
9164
9163
|
}
|
|
9165
9164
|
return false;
|
|
9166
9165
|
};
|
|
9167
|
-
const loadThread =
|
|
9166
|
+
const loadThread = React46.useCallback(async (id) => {
|
|
9168
9167
|
const data = await apiAdapter.getThread(id);
|
|
9169
9168
|
const list = [...data && data.messages || []];
|
|
9170
9169
|
serverCount.current = list.length;
|
|
9171
9170
|
commit(list);
|
|
9172
9171
|
return list;
|
|
9173
9172
|
}, [apiAdapter]);
|
|
9174
|
-
|
|
9173
|
+
React46.useEffect(() => {
|
|
9175
9174
|
if (!apiAdapter) {
|
|
9176
9175
|
setStatus("idle");
|
|
9177
9176
|
setFatal(null);
|
|
@@ -9384,7 +9383,7 @@ function useChatEngine(opts) {
|
|
|
9384
9383
|
await dispatchTurn(turn);
|
|
9385
9384
|
}
|
|
9386
9385
|
}
|
|
9387
|
-
const send =
|
|
9386
|
+
const send = React46.useCallback((text, attachments) => {
|
|
9388
9387
|
const body = (text || "").trim();
|
|
9389
9388
|
if (!body && !(attachments && attachments.length)) return;
|
|
9390
9389
|
if (status === "disconnected") return;
|
|
@@ -9394,7 +9393,7 @@ function useChatEngine(opts) {
|
|
|
9394
9393
|
stoppedRef.current = false;
|
|
9395
9394
|
drain();
|
|
9396
9395
|
}, [status]);
|
|
9397
|
-
const stop =
|
|
9396
|
+
const stop = React46.useCallback(() => {
|
|
9398
9397
|
stoppedRef.current = true;
|
|
9399
9398
|
const ac = abortRef.current;
|
|
9400
9399
|
if (ac) {
|
|
@@ -9413,11 +9412,11 @@ function useChatEngine(opts) {
|
|
|
9413
9412
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
9414
9413
|
}
|
|
9415
9414
|
}, [apiAdapter]);
|
|
9416
|
-
const removeQueued =
|
|
9415
|
+
const removeQueued = React46.useCallback((id) => {
|
|
9417
9416
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
9418
9417
|
setQueue(queueRef.current.slice());
|
|
9419
9418
|
}, []);
|
|
9420
|
-
const retry =
|
|
9419
|
+
const retry = React46.useCallback(() => {
|
|
9421
9420
|
const list = listRef.current;
|
|
9422
9421
|
let at = -1;
|
|
9423
9422
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -9433,19 +9432,19 @@ function useChatEngine(opts) {
|
|
|
9433
9432
|
setQueue(queueRef.current.slice());
|
|
9434
9433
|
drain();
|
|
9435
9434
|
}, []);
|
|
9436
|
-
const clear =
|
|
9435
|
+
const clear = React46.useCallback(() => {
|
|
9437
9436
|
commit([]);
|
|
9438
9437
|
serverCount.current = 0;
|
|
9439
9438
|
queueRef.current = [];
|
|
9440
9439
|
setQueue([]);
|
|
9441
9440
|
onClear && onClear();
|
|
9442
9441
|
}, [onClear]);
|
|
9443
|
-
const setFeedback =
|
|
9442
|
+
const setFeedback = React46.useCallback((id, value) => {
|
|
9444
9443
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
9445
9444
|
const msg = listRef.current.find((m) => m.id === id);
|
|
9446
9445
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
9447
9446
|
}, [onFeedback]);
|
|
9448
|
-
const reload =
|
|
9447
|
+
const reload = React46.useCallback(async () => {
|
|
9449
9448
|
if (!threadRef.current) return;
|
|
9450
9449
|
setStatus("loading");
|
|
9451
9450
|
try {
|
|
@@ -9483,10 +9482,10 @@ var ChatKit = {
|
|
|
9483
9482
|
};
|
|
9484
9483
|
|
|
9485
9484
|
// src/components/chat/ChatTranscript.tsx
|
|
9486
|
-
import * as
|
|
9485
|
+
import * as React48 from "react";
|
|
9487
9486
|
|
|
9488
9487
|
// src/components/chat/ChatTurn.tsx
|
|
9489
|
-
import * as
|
|
9488
|
+
import * as React47 from "react";
|
|
9490
9489
|
import { jsx as jsx74, jsxs as jsxs70 } from "react/jsx-runtime";
|
|
9491
9490
|
function JsonView({ value }) {
|
|
9492
9491
|
let text;
|
|
@@ -9523,7 +9522,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
|
9523
9522
|
] });
|
|
9524
9523
|
}
|
|
9525
9524
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
9526
|
-
const [open, setOpen] =
|
|
9525
|
+
const [open, setOpen] = React47.useState(defaultOpen);
|
|
9527
9526
|
if (!text) return null;
|
|
9528
9527
|
return /* @__PURE__ */ jsxs70("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
|
|
9529
9528
|
/* @__PURE__ */ jsxs70("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -9540,7 +9539,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
|
9540
9539
|
] });
|
|
9541
9540
|
}
|
|
9542
9541
|
function Citations({ items = [], onOpen }) {
|
|
9543
|
-
const [open, setOpen] =
|
|
9542
|
+
const [open, setOpen] = React47.useState(false);
|
|
9544
9543
|
if (!items.length) return null;
|
|
9545
9544
|
return /* @__PURE__ */ jsxs70("div", { className: "fdc-cites", children: [
|
|
9546
9545
|
/* @__PURE__ */ jsxs70("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -9566,7 +9565,7 @@ function clampText(text, max) {
|
|
|
9566
9565
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
9567
9566
|
}
|
|
9568
9567
|
function MessageBody({ message: m, ctx }) {
|
|
9569
|
-
const [expanded, setExpanded] =
|
|
9568
|
+
const [expanded, setExpanded] = React47.useState(false);
|
|
9570
9569
|
const isUser = m.role === "user";
|
|
9571
9570
|
const raw = m.text || "";
|
|
9572
9571
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
@@ -9633,9 +9632,9 @@ function MessageBody({ message: m, ctx }) {
|
|
|
9633
9632
|
] });
|
|
9634
9633
|
}
|
|
9635
9634
|
function useCopyRun() {
|
|
9636
|
-
const [done, setDone] =
|
|
9637
|
-
const t =
|
|
9638
|
-
|
|
9635
|
+
const [done, setDone] = React47.useState(false);
|
|
9636
|
+
const t = React47.useRef(null);
|
|
9637
|
+
React47.useEffect(() => () => {
|
|
9639
9638
|
if (t.current) clearTimeout(t.current);
|
|
9640
9639
|
}, []);
|
|
9641
9640
|
return [done, (text) => {
|
|
@@ -9662,7 +9661,7 @@ function RunActions({ group, ctx }) {
|
|
|
9662
9661
|
] }),
|
|
9663
9662
|
isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx74("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx74("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
9664
9663
|
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx74("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx74("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
9665
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs70(
|
|
9664
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs70(React47.Fragment, { children: [
|
|
9666
9665
|
/* @__PURE__ */ jsx74("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__ */ jsx74("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
9667
9666
|
/* @__PURE__ */ jsx74("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__ */ jsx74("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
9668
9667
|
] }) : null,
|
|
@@ -9757,10 +9756,10 @@ function ChatTranscript({
|
|
|
9757
9756
|
renderEmpty,
|
|
9758
9757
|
className = ""
|
|
9759
9758
|
}) {
|
|
9760
|
-
const scroller =
|
|
9761
|
-
const stick =
|
|
9762
|
-
const [pill, setPill] =
|
|
9763
|
-
const seen =
|
|
9759
|
+
const scroller = React48.useRef(null);
|
|
9760
|
+
const stick = React48.useRef(true);
|
|
9761
|
+
const [pill, setPill] = React48.useState(0);
|
|
9762
|
+
const seen = React48.useRef(0);
|
|
9764
9763
|
const toBottom = (smooth) => {
|
|
9765
9764
|
const el = scroller.current;
|
|
9766
9765
|
if (!el) return;
|
|
@@ -9779,7 +9778,7 @@ function ChatTranscript({
|
|
|
9779
9778
|
seen.current = messages.length;
|
|
9780
9779
|
}
|
|
9781
9780
|
};
|
|
9782
|
-
|
|
9781
|
+
React48.useLayoutEffect(() => {
|
|
9783
9782
|
const el = scroller.current;
|
|
9784
9783
|
if (!el) return;
|
|
9785
9784
|
if (stick.current) {
|
|
@@ -9787,7 +9786,7 @@ function ChatTranscript({
|
|
|
9787
9786
|
seen.current = messages.length;
|
|
9788
9787
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
9789
9788
|
}, [messages]);
|
|
9790
|
-
|
|
9789
|
+
React48.useEffect(() => {
|
|
9791
9790
|
const el = scroller.current;
|
|
9792
9791
|
const inner = el && el.firstChild;
|
|
9793
9792
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -9797,7 +9796,7 @@ function ChatTranscript({
|
|
|
9797
9796
|
ro.observe(inner);
|
|
9798
9797
|
return () => ro.disconnect();
|
|
9799
9798
|
}, []);
|
|
9800
|
-
const groups =
|
|
9799
|
+
const groups = React48.useMemo(() => groupMessages(messages), [messages]);
|
|
9801
9800
|
const empty = !messages.length && status === "ready";
|
|
9802
9801
|
return /* @__PURE__ */ jsxs71("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
9803
9802
|
/* @__PURE__ */ jsxs71("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
@@ -9821,7 +9820,7 @@ function ChatTranscript({
|
|
|
9821
9820
|
const prev = groups[i - 1];
|
|
9822
9821
|
const k = dayKey(g.messages[0].timestamp);
|
|
9823
9822
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
9824
|
-
return /* @__PURE__ */ jsxs71(
|
|
9823
|
+
return /* @__PURE__ */ jsxs71(React48.Fragment, { children: [
|
|
9825
9824
|
showDay ? /* @__PURE__ */ jsx75("div", { className: "fdc-day", children: /* @__PURE__ */ jsx75("span", { children: dayLabel(k) }) }) : null,
|
|
9826
9825
|
/* @__PURE__ */ jsx75(ChatTurn, { group: g, ctx })
|
|
9827
9826
|
] }, g.key || i);
|
|
@@ -9838,7 +9837,7 @@ function ChatTranscript({
|
|
|
9838
9837
|
var TranscriptKit = { groupMessages };
|
|
9839
9838
|
|
|
9840
9839
|
// src/components/chat/ChatComposer.tsx
|
|
9841
|
-
import * as
|
|
9840
|
+
import * as React49 from "react";
|
|
9842
9841
|
import { jsx as jsx76, jsxs as jsxs72 } from "react/jsx-runtime";
|
|
9843
9842
|
function ChatComposer({
|
|
9844
9843
|
onSubmit,
|
|
@@ -9866,17 +9865,17 @@ function ChatComposer({
|
|
|
9866
9865
|
onReject,
|
|
9867
9866
|
onOpenAttachment
|
|
9868
9867
|
}) {
|
|
9869
|
-
const [text, setText] =
|
|
9870
|
-
const [trigger, setTrigger] =
|
|
9871
|
-
const [mentionItems, setMentionItems] =
|
|
9872
|
-
const [listening, setListening] =
|
|
9873
|
-
const [notice, setNotice] =
|
|
9874
|
-
const editor =
|
|
9875
|
-
const wrap =
|
|
9876
|
-
const stopVoice =
|
|
9868
|
+
const [text, setText] = React49.useState(draft || "");
|
|
9869
|
+
const [trigger, setTrigger] = React49.useState(null);
|
|
9870
|
+
const [mentionItems, setMentionItems] = React49.useState([]);
|
|
9871
|
+
const [listening, setListening] = React49.useState(false);
|
|
9872
|
+
const [notice, setNotice] = React49.useState(null);
|
|
9873
|
+
const editor = React49.useRef(null);
|
|
9874
|
+
const wrap = React49.useRef(null);
|
|
9875
|
+
const stopVoice = React49.useRef(null);
|
|
9877
9876
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
9878
9877
|
} });
|
|
9879
|
-
|
|
9878
|
+
React49.useEffect(() => {
|
|
9880
9879
|
if (draft != null && draft !== text) setText(draft);
|
|
9881
9880
|
}, [draft]);
|
|
9882
9881
|
const change = (v) => {
|
|
@@ -9912,7 +9911,7 @@ function ChatComposer({
|
|
|
9912
9911
|
e.preventDefault();
|
|
9913
9912
|
staged.add(found.files);
|
|
9914
9913
|
};
|
|
9915
|
-
|
|
9914
|
+
React49.useEffect(() => {
|
|
9916
9915
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
9917
9916
|
setMentionItems([]);
|
|
9918
9917
|
return;
|
|
@@ -9930,7 +9929,7 @@ function ChatComposer({
|
|
|
9930
9929
|
const q = (trigger.query || "").toLowerCase();
|
|
9931
9930
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
9932
9931
|
}, [trigger, mentionSources]);
|
|
9933
|
-
const slashItems =
|
|
9932
|
+
const slashItems = React49.useMemo(() => {
|
|
9934
9933
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
9935
9934
|
const q = (trigger.query || "").toLowerCase();
|
|
9936
9935
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -10104,12 +10103,12 @@ function ChatComposer({
|
|
|
10104
10103
|
}
|
|
10105
10104
|
|
|
10106
10105
|
// src/components/chat/ChatSessionBar.tsx
|
|
10107
|
-
import * as
|
|
10106
|
+
import * as React50 from "react";
|
|
10108
10107
|
import { jsx as jsx77, jsxs as jsxs73 } from "react/jsx-runtime";
|
|
10109
10108
|
var compact2 = meterFormats.compact;
|
|
10110
10109
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
10111
|
-
const [open, setOpen] =
|
|
10112
|
-
const anchor =
|
|
10110
|
+
const [open, setOpen] = React50.useState(false);
|
|
10111
|
+
const anchor = React50.useRef(null);
|
|
10113
10112
|
const stats = sessionStats || null;
|
|
10114
10113
|
const cu = contextUsage || null;
|
|
10115
10114
|
const limits = usageLimits || null;
|
|
@@ -10124,7 +10123,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
10124
10123
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
10125
10124
|
if (cu) bits.push(pct + "% context");
|
|
10126
10125
|
const expandable = !!(cu || limits);
|
|
10127
|
-
return /* @__PURE__ */ jsxs73(
|
|
10126
|
+
return /* @__PURE__ */ jsxs73(React50.Fragment, { children: [
|
|
10128
10127
|
/* @__PURE__ */ jsxs73("div", { className: "fdc-bar", children: [
|
|
10129
10128
|
/* @__PURE__ */ jsxs73(
|
|
10130
10129
|
"button",
|
|
@@ -10265,7 +10264,7 @@ function ModelControls({
|
|
|
10265
10264
|
] })
|
|
10266
10265
|
});
|
|
10267
10266
|
}
|
|
10268
|
-
return /* @__PURE__ */ jsxs73(
|
|
10267
|
+
return /* @__PURE__ */ jsxs73(React50.Fragment, { children: [
|
|
10269
10268
|
/* @__PURE__ */ jsx77(
|
|
10270
10269
|
MenuButton,
|
|
10271
10270
|
{
|
|
@@ -10382,11 +10381,11 @@ function AgentChatPanel({
|
|
|
10382
10381
|
onFeedback,
|
|
10383
10382
|
onEditMessage
|
|
10384
10383
|
}) {
|
|
10385
|
-
const [panelWidth, setPanelWidth] =
|
|
10386
|
-
const [applied, setApplied] =
|
|
10387
|
-
const [draft, setDraft] =
|
|
10388
|
-
const dragging =
|
|
10389
|
-
|
|
10384
|
+
const [panelWidth, setPanelWidth] = React51.useState(width);
|
|
10385
|
+
const [applied, setApplied] = React51.useState({});
|
|
10386
|
+
const [draft, setDraft] = React51.useState("");
|
|
10387
|
+
const dragging = React51.useRef(null);
|
|
10388
|
+
React51.useEffect(() => setPanelWidth(width), [width]);
|
|
10390
10389
|
const engine = useChatEngine({
|
|
10391
10390
|
contextType,
|
|
10392
10391
|
contextId,
|
|
@@ -10590,7 +10589,7 @@ function AgentChatPanel({
|
|
|
10590
10589
|
}
|
|
10591
10590
|
|
|
10592
10591
|
// src/components/files/FileViewer.tsx
|
|
10593
|
-
import * as
|
|
10592
|
+
import * as React52 from "react";
|
|
10594
10593
|
import { jsx as jsx79, jsxs as jsxs75 } from "react/jsx-runtime";
|
|
10595
10594
|
function previewKindOf(file) {
|
|
10596
10595
|
const mime = (file.mime || "").toLowerCase();
|
|
@@ -10647,13 +10646,13 @@ function parseDelimited(text, delimiter) {
|
|
|
10647
10646
|
return rows;
|
|
10648
10647
|
}
|
|
10649
10648
|
function usePreview(file, kind, resolveUrl) {
|
|
10650
|
-
const [state, setState] =
|
|
10651
|
-
const [attempt, setAttempt] =
|
|
10652
|
-
const resolveRef =
|
|
10653
|
-
|
|
10649
|
+
const [state, setState] = React52.useState({ status: "loading" });
|
|
10650
|
+
const [attempt, setAttempt] = React52.useState(0);
|
|
10651
|
+
const resolveRef = React52.useRef(resolveUrl);
|
|
10652
|
+
React52.useEffect(() => {
|
|
10654
10653
|
resolveRef.current = resolveUrl;
|
|
10655
10654
|
}, [resolveUrl]);
|
|
10656
|
-
|
|
10655
|
+
React52.useEffect(() => {
|
|
10657
10656
|
if (kind === "none") {
|
|
10658
10657
|
setState({ status: "ready" });
|
|
10659
10658
|
return;
|
|
@@ -10683,7 +10682,7 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
10683
10682
|
if (ac) ac.abort();
|
|
10684
10683
|
};
|
|
10685
10684
|
}, [file.id, kind, attempt]);
|
|
10686
|
-
return { ...state, retry:
|
|
10685
|
+
return { ...state, retry: React52.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
10687
10686
|
}
|
|
10688
10687
|
function PreviewBody({ file, kind, state }) {
|
|
10689
10688
|
if (kind === "image") return /* @__PURE__ */ jsx79("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
@@ -10728,13 +10727,13 @@ function PreviewBody({ file, kind, state }) {
|
|
|
10728
10727
|
] });
|
|
10729
10728
|
}
|
|
10730
10729
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
10731
|
-
const kind =
|
|
10730
|
+
const kind = React52.useMemo(() => previewKindOf(file), [file]);
|
|
10732
10731
|
const preview = usePreview(file, kind, resolveUrl);
|
|
10733
|
-
const [tab, setTab] =
|
|
10734
|
-
const [downloading, setDownloading] =
|
|
10735
|
-
const [downloadError, setDownloadError] =
|
|
10732
|
+
const [tab, setTab] = React52.useState("preview");
|
|
10733
|
+
const [downloading, setDownloading] = React52.useState(false);
|
|
10734
|
+
const [downloadError, setDownloadError] = React52.useState(null);
|
|
10736
10735
|
const hasSide = sidePanel != null;
|
|
10737
|
-
|
|
10736
|
+
React52.useEffect(() => {
|
|
10738
10737
|
setTab("preview");
|
|
10739
10738
|
}, [file.id]);
|
|
10740
10739
|
const download = () => {
|
|
@@ -10801,7 +10800,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
10801
10800
|
}
|
|
10802
10801
|
|
|
10803
10802
|
// src/components/files/FileBrowser.tsx
|
|
10804
|
-
import * as
|
|
10803
|
+
import * as React53 from "react";
|
|
10805
10804
|
import { Fragment as Fragment25, jsx as jsx80, jsxs as jsxs76 } from "react/jsx-runtime";
|
|
10806
10805
|
function childrenOf(folders, parentId) {
|
|
10807
10806
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -10872,10 +10871,10 @@ function FolderPickerMenu({
|
|
|
10872
10871
|
destinations,
|
|
10873
10872
|
onPick
|
|
10874
10873
|
}) {
|
|
10875
|
-
const [open, setOpen] =
|
|
10874
|
+
const [open, setOpen] = React53.useState(false);
|
|
10876
10875
|
const zIndex = useOverlayLayer(open);
|
|
10877
|
-
const ref =
|
|
10878
|
-
|
|
10876
|
+
const ref = React53.useRef(null);
|
|
10877
|
+
React53.useEffect(() => {
|
|
10879
10878
|
if (!open) return;
|
|
10880
10879
|
const away = (e) => {
|
|
10881
10880
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -10927,8 +10926,8 @@ function FolderPickerMenu({
|
|
|
10927
10926
|
] });
|
|
10928
10927
|
}
|
|
10929
10928
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
10930
|
-
const [over, setOver] =
|
|
10931
|
-
const dragCounter =
|
|
10929
|
+
const [over, setOver] = React53.useState(false);
|
|
10930
|
+
const dragCounter = React53.useRef(0);
|
|
10932
10931
|
const dropHandlers = isDropTarget ? {
|
|
10933
10932
|
onDragEnter: (e) => {
|
|
10934
10933
|
if (!hasInternalPayload(e)) return;
|
|
@@ -10976,8 +10975,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
10976
10975
|
}
|
|
10977
10976
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
10978
10977
|
const kids = childrenOf(folders, folder.id);
|
|
10979
|
-
const [expanded, setExpanded] =
|
|
10980
|
-
|
|
10978
|
+
const [expanded, setExpanded] = React53.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
10979
|
+
React53.useEffect(() => {
|
|
10981
10980
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
10982
10981
|
}, [currentFolderId, folder.id, folders]);
|
|
10983
10982
|
const isCurrent = folder.id === currentFolderId;
|
|
@@ -11043,15 +11042,15 @@ function FileBrowser({
|
|
|
11043
11042
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
11044
11043
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
11045
11044
|
const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
|
|
11046
|
-
const [createOpen, setCreateOpen] =
|
|
11047
|
-
const [createName, setCreateName] =
|
|
11048
|
-
const [renameTarget, setRenameTarget] =
|
|
11049
|
-
const [renameValue, setRenameValue] =
|
|
11050
|
-
const [deleteTarget, setDeleteTarget] =
|
|
11051
|
-
const uploadInputRef =
|
|
11052
|
-
const crumbFolders =
|
|
11053
|
-
const subfolders =
|
|
11054
|
-
const currentFiles =
|
|
11045
|
+
const [createOpen, setCreateOpen] = React53.useState(false);
|
|
11046
|
+
const [createName, setCreateName] = React53.useState("");
|
|
11047
|
+
const [renameTarget, setRenameTarget] = React53.useState(null);
|
|
11048
|
+
const [renameValue, setRenameValue] = React53.useState("");
|
|
11049
|
+
const [deleteTarget, setDeleteTarget] = React53.useState(null);
|
|
11050
|
+
const uploadInputRef = React53.useRef(null);
|
|
11051
|
+
const crumbFolders = React53.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
11052
|
+
const subfolders = React53.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
11053
|
+
const currentFiles = React53.useMemo(
|
|
11055
11054
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
11056
11055
|
[files, currentFolderId]
|
|
11057
11056
|
);
|
|
@@ -11283,8 +11282,8 @@ function BreadcrumbCrumb({
|
|
|
11283
11282
|
isDropTarget,
|
|
11284
11283
|
onDropPayload
|
|
11285
11284
|
}) {
|
|
11286
|
-
const [over, setOver] =
|
|
11287
|
-
const dragCounter =
|
|
11285
|
+
const [over, setOver] = React53.useState(false);
|
|
11286
|
+
const dragCounter = React53.useRef(0);
|
|
11288
11287
|
const dropHandlers = isDropTarget ? {
|
|
11289
11288
|
onDragEnter: (e) => {
|
|
11290
11289
|
if (!hasInternalPayload(e)) return;
|
|
@@ -11313,7 +11312,7 @@ function BreadcrumbCrumb({
|
|
|
11313
11312
|
}
|
|
11314
11313
|
|
|
11315
11314
|
// src/kits/query.ts
|
|
11316
|
-
import * as
|
|
11315
|
+
import * as React54 from "react";
|
|
11317
11316
|
function eqFilter(get2) {
|
|
11318
11317
|
return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
|
|
11319
11318
|
}
|
|
@@ -11345,22 +11344,22 @@ function compare(a, b, dir) {
|
|
|
11345
11344
|
var API = null;
|
|
11346
11345
|
var PREFS = null;
|
|
11347
11346
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
11348
|
-
const [query, setQuery] =
|
|
11347
|
+
const [query, setQuery] = React54.useState(() => {
|
|
11349
11348
|
const store = PREFS || window.PlannerPrefs;
|
|
11350
11349
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
11351
11350
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
11352
11351
|
});
|
|
11353
|
-
const savePref =
|
|
11352
|
+
const savePref = React54.useCallback((patch2) => {
|
|
11354
11353
|
const store = PREFS || window.PlannerPrefs;
|
|
11355
11354
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
11356
11355
|
}, [prefsKey]);
|
|
11357
|
-
const [res, setRes] =
|
|
11358
|
-
const [loading, setLoading] =
|
|
11359
|
-
const seq2 =
|
|
11356
|
+
const [res, setRes] = React54.useState(null);
|
|
11357
|
+
const [loading, setLoading] = React54.useState(true);
|
|
11358
|
+
const seq2 = React54.useRef(0);
|
|
11360
11359
|
const depKey = (deps || []).join("|");
|
|
11361
11360
|
const paramKey = JSON.stringify(params || {});
|
|
11362
11361
|
const queryKey = JSON.stringify(query);
|
|
11363
|
-
|
|
11362
|
+
React54.useEffect(() => {
|
|
11364
11363
|
const id = ++seq2.current;
|
|
11365
11364
|
setLoading(true);
|
|
11366
11365
|
const t = setTimeout(() => {
|
|
@@ -11657,6 +11656,95 @@ function createVersionStore(initialState, options) {
|
|
|
11657
11656
|
}
|
|
11658
11657
|
};
|
|
11659
11658
|
}
|
|
11659
|
+
|
|
11660
|
+
// src/kits/useResponsiveRail.ts
|
|
11661
|
+
import * as React55 from "react";
|
|
11662
|
+
function matchesBreakpoint(breakpoint) {
|
|
11663
|
+
return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches;
|
|
11664
|
+
}
|
|
11665
|
+
var FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
11666
|
+
function getFocusable(container) {
|
|
11667
|
+
return Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR));
|
|
11668
|
+
}
|
|
11669
|
+
function useFocusTrap(navRef, active) {
|
|
11670
|
+
React55.useEffect(() => {
|
|
11671
|
+
if (!active) return;
|
|
11672
|
+
const container = navRef.current;
|
|
11673
|
+
if (!container) return;
|
|
11674
|
+
const previouslyFocused = document.activeElement;
|
|
11675
|
+
const focusable = getFocusable(container);
|
|
11676
|
+
(focusable[0] ?? container).focus();
|
|
11677
|
+
const handler = (e) => {
|
|
11678
|
+
if (e.key !== "Tab") return;
|
|
11679
|
+
const items = getFocusable(container);
|
|
11680
|
+
if (items.length === 0) {
|
|
11681
|
+
e.preventDefault();
|
|
11682
|
+
return;
|
|
11683
|
+
}
|
|
11684
|
+
const first = items[0];
|
|
11685
|
+
const last = items[items.length - 1];
|
|
11686
|
+
const activeElement = document.activeElement;
|
|
11687
|
+
const outside = !(activeElement instanceof Node) || !container.contains(activeElement);
|
|
11688
|
+
if (e.shiftKey) {
|
|
11689
|
+
if (outside || activeElement === first) {
|
|
11690
|
+
e.preventDefault();
|
|
11691
|
+
last.focus();
|
|
11692
|
+
}
|
|
11693
|
+
} else if (outside || activeElement === last) {
|
|
11694
|
+
e.preventDefault();
|
|
11695
|
+
first.focus();
|
|
11696
|
+
}
|
|
11697
|
+
};
|
|
11698
|
+
document.addEventListener("keydown", handler);
|
|
11699
|
+
return () => {
|
|
11700
|
+
document.removeEventListener("keydown", handler);
|
|
11701
|
+
previouslyFocused?.focus?.();
|
|
11702
|
+
};
|
|
11703
|
+
}, [active, navRef]);
|
|
11704
|
+
}
|
|
11705
|
+
function useResponsiveRail(options = {}) {
|
|
11706
|
+
const { breakpoint = 1024, initialOpen = true, onPersist } = options;
|
|
11707
|
+
const navRef = React55.useRef(null);
|
|
11708
|
+
const [overlay, setOverlay] = React55.useState(() => matchesBreakpoint(breakpoint));
|
|
11709
|
+
const [open, setOpenRaw] = React55.useState(() => matchesBreakpoint(breakpoint) ? false : initialOpen);
|
|
11710
|
+
const setOpen = React55.useCallback(
|
|
11711
|
+
(value) => {
|
|
11712
|
+
setOpenRaw(value);
|
|
11713
|
+
if (!matchesBreakpoint(breakpoint)) onPersist?.(value);
|
|
11714
|
+
},
|
|
11715
|
+
[breakpoint, onPersist]
|
|
11716
|
+
);
|
|
11717
|
+
const toggle = React55.useCallback(() => setOpen(!open), [open, setOpen]);
|
|
11718
|
+
const close = React55.useCallback(() => setOpenRaw(false), []);
|
|
11719
|
+
React55.useEffect(() => {
|
|
11720
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
11721
|
+
const mq = window.matchMedia(`(max-width: ${breakpoint}px)`);
|
|
11722
|
+
const handler = (e) => {
|
|
11723
|
+
setOverlay(e.matches);
|
|
11724
|
+
setOpenRaw(!e.matches);
|
|
11725
|
+
};
|
|
11726
|
+
mq.addEventListener("change", handler);
|
|
11727
|
+
return () => mq.removeEventListener("change", handler);
|
|
11728
|
+
}, [breakpoint]);
|
|
11729
|
+
React55.useEffect(() => {
|
|
11730
|
+
if (!overlay || !open) return;
|
|
11731
|
+
const handler = (e) => {
|
|
11732
|
+
if (e.key === "Escape") close();
|
|
11733
|
+
};
|
|
11734
|
+
document.addEventListener("keydown", handler);
|
|
11735
|
+
return () => document.removeEventListener("keydown", handler);
|
|
11736
|
+
}, [overlay, open, close]);
|
|
11737
|
+
React55.useEffect(() => {
|
|
11738
|
+
if (!overlay || !open) return;
|
|
11739
|
+
const previousOverflow = document.body.style.overflow;
|
|
11740
|
+
document.body.style.overflow = "hidden";
|
|
11741
|
+
return () => {
|
|
11742
|
+
document.body.style.overflow = previousOverflow;
|
|
11743
|
+
};
|
|
11744
|
+
}, [overlay, open]);
|
|
11745
|
+
useFocusTrap(navRef, overlay && open);
|
|
11746
|
+
return { open, overlay, navRef, toggle, close, setOpen };
|
|
11747
|
+
}
|
|
11660
11748
|
export {
|
|
11661
11749
|
AccountMenu,
|
|
11662
11750
|
AgentChatPanel,
|
|
@@ -11840,6 +11928,7 @@ export {
|
|
|
11840
11928
|
useChatEngine,
|
|
11841
11929
|
useFeatureStatus,
|
|
11842
11930
|
usePopoverPosition,
|
|
11931
|
+
useResponsiveRail,
|
|
11843
11932
|
useRuntimeMode,
|
|
11844
11933
|
useServerTable,
|
|
11845
11934
|
useSessionContext,
|