@flytedan/flytebot-design-system 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +641 -486
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +160 -20
- package/dist/index.d.ts +160 -20
- package/dist/index.js +639 -486
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -172,6 +172,7 @@ __export(index_exports, {
|
|
|
172
172
|
channelWeightOf: () => channelWeightOf,
|
|
173
173
|
computeNeedMore: () => computeNeedMore,
|
|
174
174
|
computeVirtualWindow: () => computeVirtualWindow,
|
|
175
|
+
createLocalStorageAppearanceStore: () => createLocalStorageAppearanceStore,
|
|
175
176
|
createVersionStore: () => createVersionStore,
|
|
176
177
|
eqFilter: () => eqFilter,
|
|
177
178
|
extensionOf: () => extensionOf,
|
|
@@ -211,6 +212,7 @@ __export(index_exports, {
|
|
|
211
212
|
useChatEngine: () => useChatEngine,
|
|
212
213
|
useFeatureStatus: () => useFeatureStatus,
|
|
213
214
|
usePopoverPosition: () => usePopoverPosition,
|
|
215
|
+
useResponsiveRail: () => useResponsiveRail,
|
|
214
216
|
useRuntimeMode: () => useRuntimeMode,
|
|
215
217
|
useServerTable: () => useServerTable,
|
|
216
218
|
useSessionContext: () => useSessionContext,
|
|
@@ -1106,37 +1108,48 @@ function Spinner({ size = "md", label = "Loading", className = "", style, ...res
|
|
|
1106
1108
|
}
|
|
1107
1109
|
|
|
1108
1110
|
// src/components/navigation/SidebarNav.tsx
|
|
1111
|
+
var React6 = __toESM(require("react"), 1);
|
|
1109
1112
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1110
1113
|
function Tip({ label, children }) {
|
|
1111
1114
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { title: label, style: { display: "inline-flex", flex: "none" }, children });
|
|
1112
1115
|
}
|
|
1113
|
-
|
|
1114
|
-
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
children:
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
}
|
|
1116
|
+
var SidebarNav = React6.forwardRef(function SidebarNav2({ brand, groups = [], current: current2, onNavigate, footer, open = false, className = "", ...rest }, ref) {
|
|
1117
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1118
|
+
"nav",
|
|
1119
|
+
{
|
|
1120
|
+
ref,
|
|
1121
|
+
tabIndex: -1,
|
|
1122
|
+
className: ["fd-side", className].filter(Boolean).join(" "),
|
|
1123
|
+
"data-open": open ? "true" : "false",
|
|
1124
|
+
...rest,
|
|
1125
|
+
children: [
|
|
1126
|
+
brand ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("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,
|
|
1127
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { flex: 1, overflow: "auto", padding: "4px 10px 18px" }, children: groups.map((g, gi) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
|
|
1128
|
+
g.label ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "fd-side-group", children: g.label }) : null,
|
|
1129
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "fd-stack", style: { gap: 2 }, children: g.items.map((it) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1130
|
+
"button",
|
|
1131
|
+
{
|
|
1132
|
+
type: "button",
|
|
1133
|
+
className: "fd-side-item",
|
|
1134
|
+
"aria-current": current2 === it.value ? "page" : void 0,
|
|
1135
|
+
onClick: onNavigate ? () => onNavigate(it.value) : void 0,
|
|
1136
|
+
children: [
|
|
1137
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "fd-side-item-icon", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) }),
|
|
1138
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, title: truncationTitle(it.label), children: it.label }),
|
|
1139
|
+
it.preview ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Tip, { label: "Designed, backend not wired yet", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("i", { className: "ph ph-traffic-cone", style: { fontSize: 13, color: "var(--warn-solid)", flex: "none" } }) }) : null,
|
|
1140
|
+
it.locked ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Tip, { label: "You do not have permission for this", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 13, color: "var(--text-muted)", flex: "none" } }) }) : null,
|
|
1141
|
+
it.count !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "fd-side-item-count", children: it.count }) : null,
|
|
1142
|
+
it.loading ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "fd-skel fd-skel-text", style: { width: 22, height: 11, marginLeft: "auto" } }) : null
|
|
1143
|
+
]
|
|
1144
|
+
},
|
|
1145
|
+
it.value
|
|
1146
|
+
)) })
|
|
1147
|
+
] }, gi)) }),
|
|
1148
|
+
footer ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { borderTop: "1px solid var(--border)", padding: 14, flex: "none" }, children: footer }) : null
|
|
1149
|
+
]
|
|
1150
|
+
}
|
|
1151
|
+
);
|
|
1152
|
+
});
|
|
1140
1153
|
|
|
1141
1154
|
// src/components/navigation/FlytedeskBrand.tsx
|
|
1142
1155
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
@@ -1177,13 +1190,13 @@ function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
|
|
|
1177
1190
|
}
|
|
1178
1191
|
|
|
1179
1192
|
// src/components/navigation/Topbar.tsx
|
|
1180
|
-
var
|
|
1193
|
+
var React7 = __toESM(require("react"), 1);
|
|
1181
1194
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1182
1195
|
function useIsNarrow(breakpoint) {
|
|
1183
|
-
const [narrow, setNarrow] =
|
|
1196
|
+
const [narrow, setNarrow] = React7.useState(
|
|
1184
1197
|
() => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
|
|
1185
1198
|
);
|
|
1186
|
-
|
|
1199
|
+
React7.useEffect(() => {
|
|
1187
1200
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
1188
1201
|
const mq = window.matchMedia(`(max-width: ${breakpoint}px)`);
|
|
1189
1202
|
const apply = () => setNarrow(mq.matches);
|
|
@@ -1204,11 +1217,11 @@ function Topbar({
|
|
|
1204
1217
|
...rest
|
|
1205
1218
|
}) {
|
|
1206
1219
|
const narrow = useIsNarrow(overflowBreakpoint);
|
|
1207
|
-
const [moreOpen, setMoreOpen] =
|
|
1208
|
-
const moreRef =
|
|
1220
|
+
const [moreOpen, setMoreOpen] = React7.useState(false);
|
|
1221
|
+
const moreRef = React7.useRef(null);
|
|
1209
1222
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("header", { className: ["fd-topbar", narrow ? "is-narrow" : "", className].filter(Boolean).join(" "), ...rest, children: [
|
|
1210
1223
|
onMenu ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Menu", onClick: onMenu, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("i", { className: "ph ph-list" }) }) : null,
|
|
1211
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
1224
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(React7.Fragment, { children: [
|
|
1212
1225
|
i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("i", { className: "ph ph-caret-right", style: { fontSize: 11, opacity: 0.6 }, "aria-hidden": "true" }) : null,
|
|
1213
1226
|
i === crumbs.length - 1 ? (
|
|
1214
1227
|
// MP-141: the current crumb mixes a static route label with (usually) a
|
|
@@ -1417,18 +1430,18 @@ function Toast({ title, children, tone = "success", onUndo, onDismiss, className
|
|
|
1417
1430
|
}
|
|
1418
1431
|
|
|
1419
1432
|
// src/components/feedback/Tooltip.tsx
|
|
1420
|
-
var
|
|
1433
|
+
var React8 = __toESM(require("react"), 1);
|
|
1421
1434
|
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1422
1435
|
var CLOSE_DELAY_MS = 120;
|
|
1423
1436
|
function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
1424
|
-
const anchorRef =
|
|
1425
|
-
const bubbleRef =
|
|
1426
|
-
const [reason, setReason] =
|
|
1427
|
-
const closeTimer =
|
|
1428
|
-
const id =
|
|
1437
|
+
const anchorRef = React8.useRef(null);
|
|
1438
|
+
const bubbleRef = React8.useRef(null);
|
|
1439
|
+
const [reason, setReason] = React8.useState(null);
|
|
1440
|
+
const closeTimer = React8.useRef(null);
|
|
1441
|
+
const id = React8.useId();
|
|
1429
1442
|
const descId = id + "-desc";
|
|
1430
1443
|
const open = reason != null;
|
|
1431
|
-
const cancelClose =
|
|
1444
|
+
const cancelClose = React8.useCallback(() => {
|
|
1432
1445
|
if (closeTimer.current) {
|
|
1433
1446
|
clearTimeout(closeTimer.current);
|
|
1434
1447
|
closeTimer.current = null;
|
|
@@ -1438,7 +1451,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1438
1451
|
cancelClose();
|
|
1439
1452
|
setReason(why);
|
|
1440
1453
|
};
|
|
1441
|
-
const hide =
|
|
1454
|
+
const hide = React8.useCallback(() => {
|
|
1442
1455
|
cancelClose();
|
|
1443
1456
|
setReason(null);
|
|
1444
1457
|
}, [cancelClose]);
|
|
@@ -1453,7 +1466,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1453
1466
|
setReason((r) => r === "hover" ? null : r);
|
|
1454
1467
|
}, CLOSE_DELAY_MS);
|
|
1455
1468
|
};
|
|
1456
|
-
|
|
1469
|
+
React8.useEffect(() => cancelClose, [cancelClose]);
|
|
1457
1470
|
const pos = usePopoverPosition(open, anchorRef, {
|
|
1458
1471
|
placement: placement === "bottom" ? "bottom-center" : "top-center",
|
|
1459
1472
|
offset: 8,
|
|
@@ -1463,7 +1476,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1463
1476
|
onDetach: hide
|
|
1464
1477
|
});
|
|
1465
1478
|
const zIndex = useOverlayLayer(open);
|
|
1466
|
-
|
|
1479
|
+
React8.useEffect(() => {
|
|
1467
1480
|
if (!open) return;
|
|
1468
1481
|
const key = (e) => {
|
|
1469
1482
|
if (e.key === "Escape") hide();
|
|
@@ -1491,7 +1504,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1491
1504
|
}
|
|
1492
1505
|
if (keyboard) show("focus");
|
|
1493
1506
|
};
|
|
1494
|
-
const described =
|
|
1507
|
+
const described = React8.isValidElement(children) ? React8.cloneElement(children, {
|
|
1495
1508
|
"aria-describedby": [children.props["aria-describedby"], descId].filter(Boolean).join(" ")
|
|
1496
1509
|
}) : children;
|
|
1497
1510
|
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
@@ -1499,7 +1512,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1499
1512
|
{
|
|
1500
1513
|
ref: anchorRef,
|
|
1501
1514
|
className: "fd-tooltip-anchor",
|
|
1502
|
-
"aria-describedby":
|
|
1515
|
+
"aria-describedby": React8.isValidElement(children) ? void 0 : descId,
|
|
1503
1516
|
onPointerEnter: (e) => {
|
|
1504
1517
|
if (isMouse(e)) hover();
|
|
1505
1518
|
},
|
|
@@ -1543,7 +1556,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1543
1556
|
}
|
|
1544
1557
|
|
|
1545
1558
|
// src/components/data/Clamp.tsx
|
|
1546
|
-
var
|
|
1559
|
+
var React9 = __toESM(require("react"), 1);
|
|
1547
1560
|
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1548
1561
|
function Clamp({
|
|
1549
1562
|
children,
|
|
@@ -1555,16 +1568,16 @@ function Clamp({
|
|
|
1555
1568
|
onToggle,
|
|
1556
1569
|
className = ""
|
|
1557
1570
|
}) {
|
|
1558
|
-
const [open, setOpen] =
|
|
1559
|
-
const [overflows, setOverflows] =
|
|
1560
|
-
const bodyRef =
|
|
1561
|
-
const charClamped =
|
|
1571
|
+
const [open, setOpen] = React9.useState(false);
|
|
1572
|
+
const [overflows, setOverflows] = React9.useState(false);
|
|
1573
|
+
const bodyRef = React9.useRef(null);
|
|
1574
|
+
const charClamped = React9.useMemo(() => {
|
|
1562
1575
|
if (open || !maxChars || typeof text !== "string" || text.length <= maxChars) return null;
|
|
1563
1576
|
const cut = text.slice(0, maxChars);
|
|
1564
1577
|
const at = cut.lastIndexOf(" ");
|
|
1565
1578
|
return (at > maxChars * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
1566
1579
|
}, [text, maxChars, open]);
|
|
1567
|
-
|
|
1580
|
+
React9.useLayoutEffect(() => {
|
|
1568
1581
|
const node = bodyRef.current;
|
|
1569
1582
|
if (maxChars || !node || !maxHeight) return;
|
|
1570
1583
|
const measure = () => {
|
|
@@ -1703,18 +1716,18 @@ function DataTable({
|
|
|
1703
1716
|
}
|
|
1704
1717
|
|
|
1705
1718
|
// src/components/data/FilterBar.tsx
|
|
1706
|
-
var
|
|
1719
|
+
var React10 = __toESM(require("react"), 1);
|
|
1707
1720
|
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1708
1721
|
var isSet = (v) => !(v == null || v === "" || v === false);
|
|
1709
1722
|
function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align = "left", className = "", ...rest }) {
|
|
1710
|
-
const [panel, setPanel] =
|
|
1723
|
+
const [panel, setPanel] = React10.useState(null);
|
|
1711
1724
|
const zIndex = useOverlayLayer(!!panel);
|
|
1712
|
-
const rootRef =
|
|
1713
|
-
const textInputRef =
|
|
1714
|
-
const optionsRef =
|
|
1725
|
+
const rootRef = React10.useRef(null);
|
|
1726
|
+
const textInputRef = React10.useRef(null);
|
|
1727
|
+
const optionsRef = React10.useRef(null);
|
|
1715
1728
|
const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
|
|
1716
1729
|
const dismissible = !!panel && (panel.kind === "add" || panel.kind === "edit" && editingField?.type === "select");
|
|
1717
|
-
|
|
1730
|
+
React10.useEffect(() => {
|
|
1718
1731
|
if (!dismissible) return;
|
|
1719
1732
|
const away = (e) => {
|
|
1720
1733
|
if (rootRef.current && !rootRef.current.contains(e.target)) setPanel(null);
|
|
@@ -1729,7 +1742,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
1729
1742
|
document.removeEventListener("keydown", esc);
|
|
1730
1743
|
};
|
|
1731
1744
|
}, [dismissible]);
|
|
1732
|
-
|
|
1745
|
+
React10.useEffect(() => {
|
|
1733
1746
|
if (!panel || panel.kind !== "edit") return;
|
|
1734
1747
|
if (editingField?.type === "text") {
|
|
1735
1748
|
textInputRef.current?.focus();
|
|
@@ -1895,7 +1908,7 @@ function StatTile({ label, value, sub, delta, loading = false, compact: compact3
|
|
|
1895
1908
|
}
|
|
1896
1909
|
|
|
1897
1910
|
// src/components/data/CodeBlock.tsx
|
|
1898
|
-
var
|
|
1911
|
+
var React11 = __toESM(require("react"), 1);
|
|
1899
1912
|
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1900
1913
|
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)$/;
|
|
1901
1914
|
var RULES = {
|
|
@@ -2051,13 +2064,13 @@ function tokenize(src, lang) {
|
|
|
2051
2064
|
return out;
|
|
2052
2065
|
}
|
|
2053
2066
|
function Highlighted({ code, lang }) {
|
|
2054
|
-
const toks =
|
|
2067
|
+
const toks = React11.useMemo(() => tokenize(code, lang), [code, lang]);
|
|
2055
2068
|
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_jsx_runtime30.Fragment, { children: toks.map((tk, i) => tk.c ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "tok-" + tk.c, children: tk.t }, i) : tk.t) });
|
|
2056
2069
|
}
|
|
2057
2070
|
function useCopy() {
|
|
2058
|
-
const [done, setDone] =
|
|
2059
|
-
const timer =
|
|
2060
|
-
|
|
2071
|
+
const [done, setDone] = React11.useState(false);
|
|
2072
|
+
const timer = React11.useRef(null);
|
|
2073
|
+
React11.useEffect(() => () => {
|
|
2061
2074
|
if (timer.current) clearTimeout(timer.current);
|
|
2062
2075
|
}, []);
|
|
2063
2076
|
const copy = (text) => {
|
|
@@ -2093,8 +2106,8 @@ function CodeBlock({
|
|
|
2093
2106
|
actions,
|
|
2094
2107
|
className = ""
|
|
2095
2108
|
}) {
|
|
2096
|
-
const [wrap, setWrap] =
|
|
2097
|
-
const [open, setOpen] =
|
|
2109
|
+
const [wrap, setWrap] = React11.useState(!!wrapDefault);
|
|
2110
|
+
const [open, setOpen] = React11.useState(false);
|
|
2098
2111
|
const [copied, copy] = useCopy();
|
|
2099
2112
|
const body = String(code).replace(/\n$/, "");
|
|
2100
2113
|
const lines = body.split("\n");
|
|
@@ -2123,7 +2136,7 @@ function CodeBlock({
|
|
|
2123
2136
|
] });
|
|
2124
2137
|
}
|
|
2125
2138
|
function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
|
|
2126
|
-
const [open, setOpen] =
|
|
2139
|
+
const [open, setOpen] = React11.useState(false);
|
|
2127
2140
|
const [copied, copy] = useCopy();
|
|
2128
2141
|
const raw = String(diff).replace(/\n$/, "");
|
|
2129
2142
|
const all = raw.split("\n").map((line) => {
|
|
@@ -2169,7 +2182,7 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
|
|
|
2169
2182
|
}
|
|
2170
2183
|
|
|
2171
2184
|
// src/components/data/Markdown.tsx
|
|
2172
|
-
var
|
|
2185
|
+
var React12 = __toESM(require("react"), 1);
|
|
2173
2186
|
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
2174
2187
|
var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
|
|
2175
2188
|
var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
|
|
@@ -2208,7 +2221,7 @@ function inlineNodes(src, ctx, keyBase) {
|
|
|
2208
2221
|
const href = safeHref(g(2));
|
|
2209
2222
|
out.push(href ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("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__ */ (0, import_jsx_runtime31.jsx)("span", { children: g(1) }, key()));
|
|
2210
2223
|
} else if (kind === "cite") {
|
|
2211
|
-
out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2224
|
+
out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(React12.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("sup", { className: "fd-md-cite", children: g(1) }, key()));
|
|
2212
2225
|
} else if (kind === "strongem") out.push(/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("strong", { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("em", { children: inlineNodes(g(1), ctx, key()) }) }, key()));
|
|
2213
2226
|
else if (kind === "strong") out.push(/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
2214
2227
|
else if (kind === "em") out.push(/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
@@ -2373,7 +2386,7 @@ function Markdown({
|
|
|
2373
2386
|
onLinkClick
|
|
2374
2387
|
}) {
|
|
2375
2388
|
const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
|
|
2376
|
-
const blocks =
|
|
2389
|
+
const blocks = React12.useMemo(() => parseBlocks(source), [source]);
|
|
2377
2390
|
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: ["fd-md", className].filter(Boolean).join(" "), children: renderBlocks(blocks, ctx, "b") });
|
|
2378
2391
|
}
|
|
2379
2392
|
function MarkdownInline({ source = "", className = "", onLinkClick }) {
|
|
@@ -2487,7 +2500,7 @@ function Pagination({
|
|
|
2487
2500
|
}
|
|
2488
2501
|
|
|
2489
2502
|
// src/components/data/RelativeTime.tsx
|
|
2490
|
-
var
|
|
2503
|
+
var React13 = __toESM(require("react"), 1);
|
|
2491
2504
|
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
2492
2505
|
var MIN = 6e4;
|
|
2493
2506
|
var HOUR = 36e5;
|
|
@@ -2539,9 +2552,9 @@ function formatDuration(ms) {
|
|
|
2539
2552
|
return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
|
|
2540
2553
|
}
|
|
2541
2554
|
function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
|
|
2542
|
-
const [, force] =
|
|
2555
|
+
const [, force] = React13.useState(0);
|
|
2543
2556
|
const t = value instanceof Date ? value.getTime() : Date.parse(value);
|
|
2544
|
-
|
|
2557
|
+
React13.useEffect(() => {
|
|
2545
2558
|
if (!refresh2 || !t || isNaN(t)) return;
|
|
2546
2559
|
const abs = Math.abs(t - Date.now());
|
|
2547
2560
|
if (abs > DAY) return;
|
|
@@ -2557,10 +2570,10 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
|
|
|
2557
2570
|
}
|
|
2558
2571
|
|
|
2559
2572
|
// src/components/data/ScoreMeter.tsx
|
|
2560
|
-
var
|
|
2573
|
+
var React15 = __toESM(require("react"), 1);
|
|
2561
2574
|
|
|
2562
2575
|
// src/components/data/SegmentedMeter.tsx
|
|
2563
|
-
var
|
|
2576
|
+
var React14 = __toESM(require("react"), 1);
|
|
2564
2577
|
|
|
2565
2578
|
// src/kits/files.ts
|
|
2566
2579
|
function formatBytes(n) {
|
|
@@ -2765,7 +2778,7 @@ function SegmentedMeter({
|
|
|
2765
2778
|
const pct = safeTotal ? Math.min(100, Math.round(used / safeTotal * 100)) : 0;
|
|
2766
2779
|
const w = (v) => safeTotal ? Math.max(0, Math.min(100, Number(v) / safeTotal * 100)) : 0;
|
|
2767
2780
|
const fill = (s, i) => s.color || (s.variant ? VARIANT_FILL[s.variant] : void 0) || CHART[i % CHART.length];
|
|
2768
|
-
const generatedId =
|
|
2781
|
+
const generatedId = React14.useId();
|
|
2769
2782
|
const uid2 = id || generatedId;
|
|
2770
2783
|
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: ["fd-segmeter", className].filter(Boolean).join(" "), onClick, children: [
|
|
2771
2784
|
label || showTotal ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "fd-segmeter-head", children: [
|
|
@@ -2849,10 +2862,10 @@ function ScoreMeter({
|
|
|
2849
2862
|
breakdownWidth = 280,
|
|
2850
2863
|
className = ""
|
|
2851
2864
|
}) {
|
|
2852
|
-
const [open, setOpen] =
|
|
2853
|
-
const ref =
|
|
2865
|
+
const [open, setOpen] = React15.useState(false);
|
|
2866
|
+
const ref = React15.useRef(null);
|
|
2854
2867
|
const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
|
|
2855
|
-
const body = /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
2868
|
+
const body = /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(React15.Fragment, { children: [
|
|
2856
2869
|
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "fd-scoremeter-rail", style: { width }, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(SegmentedMeter, { total: 100, segments, height, showTotal: false, showPercent: false, legend: false }) }),
|
|
2857
2870
|
showScore ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
|
|
2858
2871
|
] });
|
|
@@ -2871,7 +2884,7 @@ function ScoreMeter({
|
|
|
2871
2884
|
}
|
|
2872
2885
|
);
|
|
2873
2886
|
}
|
|
2874
|
-
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
2887
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(React15.Fragment, { children: [
|
|
2875
2888
|
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2876
2889
|
"button",
|
|
2877
2890
|
{
|
|
@@ -2902,13 +2915,13 @@ function ScoreMeter({
|
|
|
2902
2915
|
}
|
|
2903
2916
|
|
|
2904
2917
|
// src/components/data/SortMenu.tsx
|
|
2905
|
-
var
|
|
2918
|
+
var React16 = __toESM(require("react"), 1);
|
|
2906
2919
|
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
2907
2920
|
function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", className = "", ...rest }) {
|
|
2908
|
-
const [open, setOpen] =
|
|
2921
|
+
const [open, setOpen] = React16.useState(false);
|
|
2909
2922
|
const zIndex = useOverlayLayer(open);
|
|
2910
|
-
const ref =
|
|
2911
|
-
|
|
2923
|
+
const ref = React16.useRef(null);
|
|
2924
|
+
React16.useEffect(() => {
|
|
2912
2925
|
if (!open) return;
|
|
2913
2926
|
const away = (e) => {
|
|
2914
2927
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -2970,7 +2983,7 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
|
|
|
2970
2983
|
}
|
|
2971
2984
|
|
|
2972
2985
|
// src/components/data/StepList.tsx
|
|
2973
|
-
var
|
|
2986
|
+
var React17 = __toESM(require("react"), 1);
|
|
2974
2987
|
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
2975
2988
|
var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
|
|
2976
2989
|
function StepList({
|
|
@@ -2983,9 +2996,9 @@ function StepList({
|
|
|
2983
2996
|
dense = false,
|
|
2984
2997
|
className = ""
|
|
2985
2998
|
}) {
|
|
2986
|
-
const [openState, setOpenState] =
|
|
2999
|
+
const [openState, setOpenState] = React17.useState(defaultOpen);
|
|
2987
3000
|
const open = openProp == null ? openState : openProp;
|
|
2988
|
-
const [expanded, setExpanded] =
|
|
3001
|
+
const [expanded, setExpanded] = React17.useState({});
|
|
2989
3002
|
if (!steps.length) return null;
|
|
2990
3003
|
const running = steps.some((s) => s.status === "running");
|
|
2991
3004
|
const failed = steps.filter((s) => s.status === "error").length;
|
|
@@ -3043,7 +3056,7 @@ function StepList({
|
|
|
3043
3056
|
}
|
|
3044
3057
|
|
|
3045
3058
|
// src/components/data/VirtualList.tsx
|
|
3046
|
-
var
|
|
3059
|
+
var React18 = __toESM(require("react"), 1);
|
|
3047
3060
|
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
3048
3061
|
var VIRTUAL_LIST_BUFFER_ROWS = 20;
|
|
3049
3062
|
var VIRTUAL_LIST_ROW_GAP = 6;
|
|
@@ -3095,35 +3108,35 @@ function VirtualList({
|
|
|
3095
3108
|
className = "",
|
|
3096
3109
|
style
|
|
3097
3110
|
}) {
|
|
3098
|
-
const [scrollTop, setScrollTop] =
|
|
3099
|
-
const loaded =
|
|
3111
|
+
const [scrollTop, setScrollTop] = React18.useState(0);
|
|
3112
|
+
const loaded = React18.useMemo(
|
|
3100
3113
|
() => ({ firstItemIndex, count: items.length }),
|
|
3101
3114
|
[firstItemIndex, items.length]
|
|
3102
3115
|
);
|
|
3103
3116
|
const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
|
|
3104
3117
|
const bandKey = firstItemIndex + ":" + items.length;
|
|
3105
|
-
const win =
|
|
3118
|
+
const win = React18.useMemo(
|
|
3106
3119
|
() => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
|
|
3107
3120
|
[scrollTop, height, itemHeight, total, loaded]
|
|
3108
3121
|
);
|
|
3109
|
-
const need =
|
|
3122
|
+
const need = React18.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
|
|
3110
3123
|
const wantStart = need.start && hasMore?.start !== false;
|
|
3111
3124
|
const wantEnd = need.end && hasMore?.end !== false;
|
|
3112
3125
|
const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
|
|
3113
3126
|
const askKey = bandKey + "@" + bucket2;
|
|
3114
|
-
const asked =
|
|
3115
|
-
|
|
3127
|
+
const asked = React18.useRef({ start: null, end: null });
|
|
3128
|
+
React18.useEffect(() => {
|
|
3116
3129
|
if (loading || !wantStart || asked.current.start === askKey) return;
|
|
3117
3130
|
asked.current.start = askKey;
|
|
3118
3131
|
onNeedMore("start", win);
|
|
3119
3132
|
}, [wantStart, loading, askKey, onNeedMore, win]);
|
|
3120
|
-
|
|
3133
|
+
React18.useEffect(() => {
|
|
3121
3134
|
if (loading || !wantEnd || asked.current.end === askKey) return;
|
|
3122
3135
|
asked.current.end = askKey;
|
|
3123
3136
|
onNeedMore("end", win);
|
|
3124
3137
|
}, [wantEnd, loading, askKey, onNeedMore, win]);
|
|
3125
|
-
const lastKeysRef =
|
|
3126
|
-
const newKeys =
|
|
3138
|
+
const lastKeysRef = React18.useRef(null);
|
|
3139
|
+
const newKeys = React18.useMemo(() => {
|
|
3127
3140
|
const prev = lastKeysRef.current;
|
|
3128
3141
|
if (!prev) return /* @__PURE__ */ new Set();
|
|
3129
3142
|
const fresh = /* @__PURE__ */ new Set();
|
|
@@ -3133,7 +3146,7 @@ function VirtualList({
|
|
|
3133
3146
|
}
|
|
3134
3147
|
return fresh;
|
|
3135
3148
|
}, [items]);
|
|
3136
|
-
|
|
3149
|
+
React18.useEffect(() => {
|
|
3137
3150
|
lastKeysRef.current = new Set(items.map(keyOf));
|
|
3138
3151
|
}, [items]);
|
|
3139
3152
|
const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
|
|
@@ -3178,7 +3191,7 @@ function VirtualList({
|
|
|
3178
3191
|
}
|
|
3179
3192
|
|
|
3180
3193
|
// src/components/data/EntityRow.tsx
|
|
3181
|
-
var
|
|
3194
|
+
var React19 = __toESM(require("react"), 1);
|
|
3182
3195
|
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
3183
3196
|
var ENTITY_ROW_METRIC_WIDTH = 74;
|
|
3184
3197
|
var METRIC_TONE_COLOR = {
|
|
@@ -3191,7 +3204,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
|
|
|
3191
3204
|
const key = m.id || m.label || i;
|
|
3192
3205
|
const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
|
|
3193
3206
|
const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
|
|
3194
|
-
const content = /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
3207
|
+
const content = /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(React19.Fragment, { children: [
|
|
3195
3208
|
m.icon ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
|
|
3196
3209
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
|
|
3197
3210
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-sr", children: " " + m.label })
|
|
@@ -3283,14 +3296,14 @@ function EntityRow({
|
|
|
3283
3296
|
}
|
|
3284
3297
|
|
|
3285
3298
|
// src/components/data/TransferList.tsx
|
|
3286
|
-
var
|
|
3299
|
+
var React21 = __toESM(require("react"), 1);
|
|
3287
3300
|
var import_react_dom4 = require("react-dom");
|
|
3288
3301
|
|
|
3289
3302
|
// src/components/forms/field.tsx
|
|
3290
|
-
var
|
|
3303
|
+
var React20 = __toESM(require("react"), 1);
|
|
3291
3304
|
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
3292
3305
|
function useFieldId(id) {
|
|
3293
|
-
const generated =
|
|
3306
|
+
const generated = React20.useId();
|
|
3294
3307
|
return id || generated;
|
|
3295
3308
|
}
|
|
3296
3309
|
function FieldLabel({ htmlFor, id, required = false, onClick, children }) {
|
|
@@ -3408,12 +3421,12 @@ function TransferList({
|
|
|
3408
3421
|
listHeight = 440,
|
|
3409
3422
|
className = ""
|
|
3410
3423
|
}) {
|
|
3411
|
-
const [drag, setDrag] =
|
|
3412
|
-
const [dragOverSide, setDragOverSide] =
|
|
3413
|
-
const dragRef =
|
|
3414
|
-
const armedRef =
|
|
3415
|
-
const sideRefs =
|
|
3416
|
-
const hitTestSide =
|
|
3424
|
+
const [drag, setDrag] = React21.useState(null);
|
|
3425
|
+
const [dragOverSide, setDragOverSide] = React21.useState(null);
|
|
3426
|
+
const dragRef = React21.useRef(null);
|
|
3427
|
+
const armedRef = React21.useRef(null);
|
|
3428
|
+
const sideRefs = React21.useRef({ left: null, right: null });
|
|
3429
|
+
const hitTestSide = React21.useCallback((x, y) => {
|
|
3417
3430
|
for (const side of ["left", "right"]) {
|
|
3418
3431
|
const el = sideRefs.current[side];
|
|
3419
3432
|
if (!el) continue;
|
|
@@ -3422,7 +3435,7 @@ function TransferList({
|
|
|
3422
3435
|
}
|
|
3423
3436
|
return null;
|
|
3424
3437
|
}, []);
|
|
3425
|
-
const findItem =
|
|
3438
|
+
const findItem = React21.useCallback(
|
|
3426
3439
|
(side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
|
|
3427
3440
|
[left.items, right.items, keyOf]
|
|
3428
3441
|
);
|
|
@@ -3444,7 +3457,7 @@ function TransferList({
|
|
|
3444
3457
|
height: rect.height
|
|
3445
3458
|
};
|
|
3446
3459
|
};
|
|
3447
|
-
|
|
3460
|
+
React21.useEffect(() => {
|
|
3448
3461
|
const onMovePointer = (e) => {
|
|
3449
3462
|
const armed = armedRef.current;
|
|
3450
3463
|
if (!armed || e.pointerId !== armed.pointerId) return;
|
|
@@ -3497,7 +3510,7 @@ function TransferList({
|
|
|
3497
3510
|
window.removeEventListener("pointercancel", endDrag);
|
|
3498
3511
|
};
|
|
3499
3512
|
}, [hitTestSide, findItem, onMove]);
|
|
3500
|
-
|
|
3513
|
+
React21.useEffect(() => {
|
|
3501
3514
|
if (!drag || typeof document === "undefined") return;
|
|
3502
3515
|
const prev = document.body.style.userSelect;
|
|
3503
3516
|
document.body.style.userSelect = "none";
|
|
@@ -3605,11 +3618,11 @@ function TransferList({
|
|
|
3605
3618
|
}
|
|
3606
3619
|
|
|
3607
3620
|
// src/components/forms/Checkbox.tsx
|
|
3608
|
-
var
|
|
3621
|
+
var React22 = __toESM(require("react"), 1);
|
|
3609
3622
|
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
3610
3623
|
function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
|
|
3611
|
-
const ref =
|
|
3612
|
-
|
|
3624
|
+
const ref = React22.useRef(null);
|
|
3625
|
+
React22.useEffect(() => {
|
|
3613
3626
|
if (ref.current) ref.current.indeterminate = indeterminate;
|
|
3614
3627
|
}, [indeterminate]);
|
|
3615
3628
|
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
@@ -3668,7 +3681,7 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
|
|
|
3668
3681
|
}
|
|
3669
3682
|
|
|
3670
3683
|
// src/components/forms/NumberInput.tsx
|
|
3671
|
-
var
|
|
3684
|
+
var React23 = __toESM(require("react"), 1);
|
|
3672
3685
|
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
3673
3686
|
function NumberInput({
|
|
3674
3687
|
label,
|
|
@@ -3696,10 +3709,10 @@ function NumberInput({
|
|
|
3696
3709
|
const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
|
|
3697
3710
|
return isNaN(n) ? null : n;
|
|
3698
3711
|
};
|
|
3699
|
-
const [text, setText] =
|
|
3700
|
-
const [editing, setEditing] =
|
|
3701
|
-
const timer =
|
|
3702
|
-
|
|
3712
|
+
const [text, setText] = React23.useState(value == null || value === "" ? "" : String(value));
|
|
3713
|
+
const [editing, setEditing] = React23.useState(false);
|
|
3714
|
+
const timer = React23.useRef(null);
|
|
3715
|
+
React23.useEffect(() => {
|
|
3703
3716
|
if (!editing) setText(value == null || value === "" ? "" : String(value));
|
|
3704
3717
|
}, [value, editing]);
|
|
3705
3718
|
const clamp = (n) => Math.min(max, Math.max(min, n));
|
|
@@ -3723,7 +3736,7 @@ function NumberInput({
|
|
|
3723
3736
|
const release = () => {
|
|
3724
3737
|
if (timer.current) clearTimeout(timer.current);
|
|
3725
3738
|
};
|
|
3726
|
-
|
|
3739
|
+
React23.useEffect(() => () => {
|
|
3727
3740
|
if (timer.current) clearTimeout(timer.current);
|
|
3728
3741
|
}, []);
|
|
3729
3742
|
const shown = editing ? text : (() => {
|
|
@@ -3810,7 +3823,7 @@ function NumberInput({
|
|
|
3810
3823
|
}
|
|
3811
3824
|
|
|
3812
3825
|
// src/components/forms/Select.tsx
|
|
3813
|
-
var
|
|
3826
|
+
var React24 = __toESM(require("react"), 1);
|
|
3814
3827
|
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
3815
3828
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
3816
3829
|
function Select({
|
|
@@ -3837,13 +3850,13 @@ function Select({
|
|
|
3837
3850
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
3838
3851
|
const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
|
|
3839
3852
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
3840
|
-
const [open, setOpen] =
|
|
3841
|
-
const [q, setQ] =
|
|
3842
|
-
const [active, setActive] =
|
|
3843
|
-
const rootRef =
|
|
3844
|
-
const boxRef =
|
|
3845
|
-
const listRef =
|
|
3846
|
-
const typeBuf =
|
|
3853
|
+
const [open, setOpen] = React24.useState(false);
|
|
3854
|
+
const [q, setQ] = React24.useState("");
|
|
3855
|
+
const [active, setActive] = React24.useState(-1);
|
|
3856
|
+
const rootRef = React24.useRef(null);
|
|
3857
|
+
const boxRef = React24.useRef(null);
|
|
3858
|
+
const listRef = React24.useRef(null);
|
|
3859
|
+
const typeBuf = React24.useRef({ s: "", t: 0 });
|
|
3847
3860
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
3848
3861
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
3849
3862
|
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;
|
|
@@ -3868,7 +3881,7 @@ function Select({
|
|
|
3868
3881
|
}
|
|
3869
3882
|
setOpen(!open);
|
|
3870
3883
|
};
|
|
3871
|
-
|
|
3884
|
+
React24.useEffect(() => {
|
|
3872
3885
|
if (!open || active < 0 || !listRef.current) return;
|
|
3873
3886
|
const el = listRef.current.querySelector('[data-i="' + active + '"]');
|
|
3874
3887
|
if (el) {
|
|
@@ -3989,7 +4002,7 @@ function Select({
|
|
|
3989
4002
|
),
|
|
3990
4003
|
q ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
3991
4004
|
] }) : void 0,
|
|
3992
|
-
footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
4005
|
+
footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(React24.Fragment, { children: [
|
|
3993
4006
|
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3994
4007
|
"button",
|
|
3995
4008
|
{
|
|
@@ -4020,7 +4033,7 @@ function Select({
|
|
|
4020
4033
|
'Nothing matches "',
|
|
4021
4034
|
q,
|
|
4022
4035
|
'".'
|
|
4023
|
-
] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
4036
|
+
] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(React24.Fragment, { children: [
|
|
4024
4037
|
grp.g ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
|
|
4025
4038
|
grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
4026
4039
|
"button",
|
|
@@ -4057,7 +4070,7 @@ function Select({
|
|
|
4057
4070
|
}
|
|
4058
4071
|
|
|
4059
4072
|
// src/components/forms/DatePicker.tsx
|
|
4060
|
-
var
|
|
4073
|
+
var React25 = __toESM(require("react"), 1);
|
|
4061
4074
|
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
4062
4075
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
4063
4076
|
var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
@@ -4075,10 +4088,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
4075
4088
|
const today = /* @__PURE__ */ new Date();
|
|
4076
4089
|
const sel = range ? value || {} : { start: value, end: value };
|
|
4077
4090
|
const anchor = parse(sel.start) || parse(initialMonth) || today;
|
|
4078
|
-
const [vy, setVy] =
|
|
4079
|
-
const [vm, setVm] =
|
|
4080
|
-
const [mode2, setMode] =
|
|
4081
|
-
const [hover, setHover] =
|
|
4091
|
+
const [vy, setVy] = React25.useState(anchor.getFullYear());
|
|
4092
|
+
const [vm, setVm] = React25.useState(anchor.getMonth());
|
|
4093
|
+
const [mode2, setMode] = React25.useState("days");
|
|
4094
|
+
const [hover, setHover] = React25.useState(null);
|
|
4082
4095
|
const s = parse(sel.start), e = parse(sel.end);
|
|
4083
4096
|
const hoverEnd = range && s && !e && hover ? parse(hover) : null;
|
|
4084
4097
|
const inRange = (d) => {
|
|
@@ -4194,9 +4207,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
4194
4207
|
}
|
|
4195
4208
|
function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, ...rest }) {
|
|
4196
4209
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
4197
|
-
const [open, setOpen] =
|
|
4198
|
-
const rootRef =
|
|
4199
|
-
const boxRef =
|
|
4210
|
+
const [open, setOpen] = React25.useState(false);
|
|
4211
|
+
const rootRef = React25.useRef(null);
|
|
4212
|
+
const boxRef = React25.useRef(null);
|
|
4200
4213
|
const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
|
|
4201
4214
|
const toggle = () => {
|
|
4202
4215
|
if (!disabled) setOpen(!open);
|
|
@@ -4259,7 +4272,7 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
4259
4272
|
}
|
|
4260
4273
|
|
|
4261
4274
|
// src/components/forms/TimePicker.tsx
|
|
4262
|
-
var
|
|
4275
|
+
var React26 = __toESM(require("react"), 1);
|
|
4263
4276
|
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
4264
4277
|
var pad = (n) => String(n).padStart(2, "0");
|
|
4265
4278
|
function ClockFace({ value = "09:00", onChange }) {
|
|
@@ -4268,9 +4281,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
4268
4281
|
if (isNaN(m)) m = 0;
|
|
4269
4282
|
const pm = h24 >= 12;
|
|
4270
4283
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
4271
|
-
const [mode2, setMode] =
|
|
4272
|
-
const faceRef =
|
|
4273
|
-
const dragging =
|
|
4284
|
+
const [mode2, setMode] = React26.useState("h");
|
|
4285
|
+
const faceRef = React26.useRef(null);
|
|
4286
|
+
const dragging = React26.useRef(false);
|
|
4274
4287
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
4275
4288
|
const R = 108, NR = 80;
|
|
4276
4289
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -4343,9 +4356,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
4343
4356
|
}
|
|
4344
4357
|
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
|
|
4345
4358
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
4346
|
-
const [open, setOpen] =
|
|
4347
|
-
const rootRef =
|
|
4348
|
-
const boxRef =
|
|
4359
|
+
const [open, setOpen] = React26.useState(false);
|
|
4360
|
+
const rootRef = React26.useRef(null);
|
|
4361
|
+
const boxRef = React26.useRef(null);
|
|
4349
4362
|
const disp = () => {
|
|
4350
4363
|
if (!value) return "";
|
|
4351
4364
|
const [h, m] = value.split(":").map(Number);
|
|
@@ -4388,7 +4401,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4388
4401
|
offset: 6,
|
|
4389
4402
|
width: 262,
|
|
4390
4403
|
role: "presentation",
|
|
4391
|
-
footer: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
4404
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React26.Fragment, { children: [
|
|
4392
4405
|
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
4393
4406
|
"button",
|
|
4394
4407
|
{
|
|
@@ -4416,7 +4429,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4416
4429
|
}
|
|
4417
4430
|
|
|
4418
4431
|
// src/components/forms/Slider.tsx
|
|
4419
|
-
var
|
|
4432
|
+
var React27 = __toESM(require("react"), 1);
|
|
4420
4433
|
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
4421
4434
|
function Slider({
|
|
4422
4435
|
label,
|
|
@@ -4434,7 +4447,7 @@ function Slider({
|
|
|
4434
4447
|
...rest
|
|
4435
4448
|
}) {
|
|
4436
4449
|
const fieldId = useFieldId(id);
|
|
4437
|
-
const [dragging, setDragging] =
|
|
4450
|
+
const [dragging, setDragging] = React27.useState(false);
|
|
4438
4451
|
const v = value === void 0 ? min : Number(value);
|
|
4439
4452
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
4440
4453
|
return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
|
|
@@ -4468,7 +4481,7 @@ function Slider({
|
|
|
4468
4481
|
}
|
|
4469
4482
|
|
|
4470
4483
|
// src/components/forms/RangeSlider.tsx
|
|
4471
|
-
var
|
|
4484
|
+
var React28 = __toESM(require("react"), 1);
|
|
4472
4485
|
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
4473
4486
|
function RangeSlider({
|
|
4474
4487
|
label,
|
|
@@ -4488,9 +4501,9 @@ function RangeSlider({
|
|
|
4488
4501
|
}) {
|
|
4489
4502
|
const fmt2 = format || ((v) => String(v));
|
|
4490
4503
|
const [a, b] = value || [min, max];
|
|
4491
|
-
const [drag, setDrag] =
|
|
4492
|
-
const [focus, setFocus] =
|
|
4493
|
-
const railRef =
|
|
4504
|
+
const [drag, setDrag] = React28.useState(null);
|
|
4505
|
+
const [focus, setFocus] = React28.useState(null);
|
|
4506
|
+
const railRef = React28.useRef(null);
|
|
4494
4507
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
4495
4508
|
const clampPair = (i, v) => {
|
|
4496
4509
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -4505,7 +4518,7 @@ function RangeSlider({
|
|
|
4505
4518
|
const r = railRef.current.getBoundingClientRect();
|
|
4506
4519
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
4507
4520
|
};
|
|
4508
|
-
|
|
4521
|
+
React28.useEffect(() => {
|
|
4509
4522
|
if (drag === null) return;
|
|
4510
4523
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
4511
4524
|
const upH = () => setDrag(null);
|
|
@@ -4586,7 +4599,7 @@ function RangeSlider({
|
|
|
4586
4599
|
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
|
|
4587
4600
|
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-rail", ref: railRef }),
|
|
4588
4601
|
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
|
|
4589
|
-
marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
4602
|
+
marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(React28.Fragment, { children: [
|
|
4590
4603
|
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
|
|
4591
4604
|
m.label ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
|
|
4592
4605
|
] }, m.value)),
|
|
@@ -4615,7 +4628,7 @@ function RangeSlider({
|
|
|
4615
4628
|
}
|
|
4616
4629
|
|
|
4617
4630
|
// src/components/forms/Dropzone.tsx
|
|
4618
|
-
var
|
|
4631
|
+
var React29 = __toESM(require("react"), 1);
|
|
4619
4632
|
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
4620
4633
|
function Dropzone({
|
|
4621
4634
|
onFiles,
|
|
@@ -4630,8 +4643,8 @@ function Dropzone({
|
|
|
4630
4643
|
className = "",
|
|
4631
4644
|
style
|
|
4632
4645
|
}) {
|
|
4633
|
-
const [over, setOver] =
|
|
4634
|
-
const depth =
|
|
4646
|
+
const [over, setOver] = React29.useState(false);
|
|
4647
|
+
const depth = React29.useRef(0);
|
|
4635
4648
|
const has = (e) => {
|
|
4636
4649
|
const dt = e.dataTransfer;
|
|
4637
4650
|
if (!dt) return false;
|
|
@@ -4693,8 +4706,8 @@ function FilePickButton({
|
|
|
4693
4706
|
className = "",
|
|
4694
4707
|
children
|
|
4695
4708
|
}) {
|
|
4696
|
-
const ref =
|
|
4697
|
-
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
|
|
4709
|
+
const ref = React29.useRef(null);
|
|
4710
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(React29.Fragment, { children: [
|
|
4698
4711
|
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4699
4712
|
"button",
|
|
4700
4713
|
{
|
|
@@ -4727,10 +4740,10 @@ function FilePickButton({
|
|
|
4727
4740
|
}
|
|
4728
4741
|
function useStagedFiles(upload, opts) {
|
|
4729
4742
|
const o = opts || {};
|
|
4730
|
-
const [items, setItems] =
|
|
4731
|
-
const controllers =
|
|
4743
|
+
const [items, setItems] = React29.useState([]);
|
|
4744
|
+
const controllers = React29.useRef({});
|
|
4732
4745
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
4733
|
-
const run =
|
|
4746
|
+
const run = React29.useCallback((att) => {
|
|
4734
4747
|
if (!upload) return;
|
|
4735
4748
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
4736
4749
|
controllers.current[att.id] = ac;
|
|
@@ -4747,14 +4760,14 @@ function useStagedFiles(upload, opts) {
|
|
|
4747
4760
|
delete controllers.current[att.id];
|
|
4748
4761
|
});
|
|
4749
4762
|
}, [upload]);
|
|
4750
|
-
const add =
|
|
4763
|
+
const add = React29.useCallback((files) => {
|
|
4751
4764
|
if (!upload) return [];
|
|
4752
4765
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
4753
4766
|
setItems((list) => list.concat(atts));
|
|
4754
4767
|
atts.forEach(run);
|
|
4755
4768
|
return atts;
|
|
4756
4769
|
}, [upload, run]);
|
|
4757
|
-
const remove =
|
|
4770
|
+
const remove = React29.useCallback((att) => {
|
|
4758
4771
|
const ac = controllers.current[att.id];
|
|
4759
4772
|
if (ac) {
|
|
4760
4773
|
try {
|
|
@@ -4765,10 +4778,10 @@ function useStagedFiles(upload, opts) {
|
|
|
4765
4778
|
}
|
|
4766
4779
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
4767
4780
|
}, []);
|
|
4768
|
-
const retry =
|
|
4781
|
+
const retry = React29.useCallback((att) => {
|
|
4769
4782
|
run(att);
|
|
4770
4783
|
}, [run]);
|
|
4771
|
-
const clear =
|
|
4784
|
+
const clear = React29.useCallback(() => {
|
|
4772
4785
|
Object.values(controllers.current).forEach((ac) => {
|
|
4773
4786
|
try {
|
|
4774
4787
|
ac && ac.abort();
|
|
@@ -4892,7 +4905,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
4892
4905
|
}
|
|
4893
4906
|
|
|
4894
4907
|
// src/components/forms/MarkdownEditor.tsx
|
|
4895
|
-
var
|
|
4908
|
+
var React30 = __toESM(require("react"), 1);
|
|
4896
4909
|
var import_jsx_runtime57 = require("react/jsx-runtime");
|
|
4897
4910
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
4898
4911
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
@@ -5106,7 +5119,7 @@ function syncDom(root, value) {
|
|
|
5106
5119
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
5107
5120
|
}
|
|
5108
5121
|
var LIST_CONT = RE_LI;
|
|
5109
|
-
var MarkdownEditor =
|
|
5122
|
+
var MarkdownEditor = React30.forwardRef(function MarkdownEditor2({
|
|
5110
5123
|
value = "",
|
|
5111
5124
|
onChange,
|
|
5112
5125
|
onSubmit,
|
|
@@ -5125,10 +5138,10 @@ var MarkdownEditor = React29.forwardRef(function MarkdownEditor2({
|
|
|
5125
5138
|
className = "",
|
|
5126
5139
|
id
|
|
5127
5140
|
}, ref) {
|
|
5128
|
-
const boxRef =
|
|
5129
|
-
const composing =
|
|
5130
|
-
const pendingCaret =
|
|
5131
|
-
|
|
5141
|
+
const boxRef = React30.useRef(null);
|
|
5142
|
+
const composing = React30.useRef(false);
|
|
5143
|
+
const pendingCaret = React30.useRef(null);
|
|
5144
|
+
React30.useLayoutEffect(() => {
|
|
5132
5145
|
const root = boxRef.current;
|
|
5133
5146
|
if (!root || composing.current) return;
|
|
5134
5147
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -5137,7 +5150,7 @@ var MarkdownEditor = React29.forwardRef(function MarkdownEditor2({
|
|
|
5137
5150
|
pendingCaret.current = null;
|
|
5138
5151
|
if (active && caret != null) placeCaret(root, caret);
|
|
5139
5152
|
}, [value]);
|
|
5140
|
-
|
|
5153
|
+
React30.useEffect(() => {
|
|
5141
5154
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
5142
5155
|
}, [autoFocus]);
|
|
5143
5156
|
const caretNow = () => {
|
|
@@ -5204,7 +5217,7 @@ var MarkdownEditor = React29.forwardRef(function MarkdownEditor2({
|
|
|
5204
5217
|
api.replaceRange(from, to, next, from + next.length);
|
|
5205
5218
|
}
|
|
5206
5219
|
};
|
|
5207
|
-
|
|
5220
|
+
React30.useImperativeHandle(ref, () => api);
|
|
5208
5221
|
function detect(text, caret) {
|
|
5209
5222
|
if (!onTrigger) return;
|
|
5210
5223
|
const upto = text.slice(0, caret);
|
|
@@ -5356,16 +5369,16 @@ var MarkdownEditor = React29.forwardRef(function MarkdownEditor2({
|
|
|
5356
5369
|
});
|
|
5357
5370
|
|
|
5358
5371
|
// src/components/platform/AccountMenu.tsx
|
|
5359
|
-
var
|
|
5372
|
+
var React32 = __toESM(require("react"), 1);
|
|
5360
5373
|
|
|
5361
5374
|
// src/kits/sessionContext.tsx
|
|
5362
|
-
var
|
|
5363
|
-
var SessionContext =
|
|
5375
|
+
var React31 = __toESM(require("react"), 1);
|
|
5376
|
+
var SessionContext = React31.createContext(null);
|
|
5364
5377
|
function SessionProvider({ value, children }) {
|
|
5365
|
-
return
|
|
5378
|
+
return React31.createElement(SessionContext.Provider, { value }, children);
|
|
5366
5379
|
}
|
|
5367
5380
|
function useSessionContext() {
|
|
5368
|
-
const ctx =
|
|
5381
|
+
const ctx = React31.useContext(SessionContext);
|
|
5369
5382
|
if (!ctx) {
|
|
5370
5383
|
throw new Error(
|
|
5371
5384
|
"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."
|
|
@@ -5376,20 +5389,8 @@ function useSessionContext() {
|
|
|
5376
5389
|
|
|
5377
5390
|
// src/components/platform/AccountMenu.tsx
|
|
5378
5391
|
var import_jsx_runtime58 = require("react/jsx-runtime");
|
|
5379
|
-
var DEFAULT_LINKS = [
|
|
5380
|
-
|
|
5381
|
-
{ id: "preferences", label: "Preferences", icon: "sliders-horizontal", href: "../admin/index.html#preferences" }
|
|
5382
|
-
];
|
|
5383
|
-
var DEFAULT_GROUPS = [
|
|
5384
|
-
{
|
|
5385
|
-
label: "Administration",
|
|
5386
|
-
links: [
|
|
5387
|
-
{ id: "users", label: "Users", icon: "users-three", href: "../admin/index.html#users", perm: "users.view" },
|
|
5388
|
-
{ id: "roles", label: "Roles & permissions", icon: "shield-check", href: "../admin/index.html#roles", perm: "roles.manage" },
|
|
5389
|
-
{ id: "flags", label: "Feature flags", icon: "toggle-right", href: "../admin/index.html#flags", perm: "flags.manage" }
|
|
5390
|
-
]
|
|
5391
|
-
}
|
|
5392
|
-
];
|
|
5392
|
+
var DEFAULT_LINKS = [];
|
|
5393
|
+
var DEFAULT_GROUPS = [];
|
|
5393
5394
|
function Item({ item, onPick }) {
|
|
5394
5395
|
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
|
|
5395
5396
|
"button",
|
|
@@ -5417,10 +5418,10 @@ function AccountMenu({
|
|
|
5417
5418
|
...rest
|
|
5418
5419
|
}) {
|
|
5419
5420
|
const { user, roles, can: can2, signOut: ctxSignOut, demo } = useSessionContext();
|
|
5420
|
-
const [open, setOpen] =
|
|
5421
|
-
const [switching, setSwitching] =
|
|
5422
|
-
const [signingOut, setSigningOut] =
|
|
5423
|
-
const ref =
|
|
5421
|
+
const [open, setOpen] = React32.useState(false);
|
|
5422
|
+
const [switching, setSwitching] = React32.useState(false);
|
|
5423
|
+
const [signingOut, setSigningOut] = React32.useState(false);
|
|
5424
|
+
const ref = React32.useRef(null);
|
|
5424
5425
|
const visibleLinks = links.filter((l) => !l.perm || can2(l.perm));
|
|
5425
5426
|
const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || can2(l.perm)) })).filter((g) => g.links.length);
|
|
5426
5427
|
const pick = (item) => {
|
|
@@ -5523,13 +5524,13 @@ function AccountMenu({
|
|
|
5523
5524
|
}
|
|
5524
5525
|
|
|
5525
5526
|
// src/components/platform/AppSwitcher.tsx
|
|
5526
|
-
var
|
|
5527
|
+
var React33 = __toESM(require("react"), 1);
|
|
5527
5528
|
var import_jsx_runtime59 = require("react/jsx-runtime");
|
|
5528
5529
|
function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
5529
5530
|
const { apps: contextApps } = useSessionContext();
|
|
5530
5531
|
const apps = appsProp ?? contextApps ?? [];
|
|
5531
|
-
const [open, setOpen] =
|
|
5532
|
-
const anchorRef =
|
|
5532
|
+
const [open, setOpen] = React33.useState(false);
|
|
5533
|
+
const anchorRef = React33.useRef(null);
|
|
5533
5534
|
if (!apps.length) return null;
|
|
5534
5535
|
const items = apps.map((app) => ({
|
|
5535
5536
|
id: app.key,
|
|
@@ -5543,7 +5544,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
5543
5544
|
window.location.href = app.url;
|
|
5544
5545
|
}
|
|
5545
5546
|
}));
|
|
5546
|
-
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
|
|
5547
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React33.Fragment, { children: [
|
|
5547
5548
|
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
5548
5549
|
IconButton,
|
|
5549
5550
|
{
|
|
@@ -5572,10 +5573,10 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
5572
5573
|
}
|
|
5573
5574
|
|
|
5574
5575
|
// src/components/platform/AppearanceMenu.tsx
|
|
5575
|
-
var
|
|
5576
|
+
var React35 = __toESM(require("react"), 1);
|
|
5576
5577
|
|
|
5577
5578
|
// src/kits/appearance.ts
|
|
5578
|
-
var
|
|
5579
|
+
var React34 = __toESM(require("react"), 1);
|
|
5579
5580
|
var DEFAULT_STORAGE_KEY = "fd-appearance";
|
|
5580
5581
|
var DEFAULT_PREFS = {
|
|
5581
5582
|
theme: "system",
|
|
@@ -5624,6 +5625,43 @@ function savePrefs(prefs, opts) {
|
|
|
5624
5625
|
} catch {
|
|
5625
5626
|
}
|
|
5626
5627
|
}
|
|
5628
|
+
function createLocalStorageAppearanceStore(opts) {
|
|
5629
|
+
const key = opts?.storageKey ?? DEFAULT_STORAGE_KEY;
|
|
5630
|
+
const storage = resolveStorage(opts);
|
|
5631
|
+
let snapshot = loadPrefs(opts);
|
|
5632
|
+
const listeners3 = /* @__PURE__ */ new Set();
|
|
5633
|
+
const notify = () => listeners3.forEach((l) => l());
|
|
5634
|
+
const onStorageEvent = (e) => {
|
|
5635
|
+
if (e.key !== null && e.key !== key) return;
|
|
5636
|
+
snapshot = loadPrefs(opts);
|
|
5637
|
+
notify();
|
|
5638
|
+
};
|
|
5639
|
+
return {
|
|
5640
|
+
getSnapshot: () => snapshot,
|
|
5641
|
+
write(prefs) {
|
|
5642
|
+
snapshot = prefs;
|
|
5643
|
+
if (storage) {
|
|
5644
|
+
try {
|
|
5645
|
+
storage.setItem(key, JSON.stringify(prefs));
|
|
5646
|
+
} catch {
|
|
5647
|
+
}
|
|
5648
|
+
}
|
|
5649
|
+
notify();
|
|
5650
|
+
},
|
|
5651
|
+
subscribe(onChange) {
|
|
5652
|
+
listeners3.add(onChange);
|
|
5653
|
+
if (listeners3.size === 1 && typeof window !== "undefined") {
|
|
5654
|
+
window.addEventListener("storage", onStorageEvent);
|
|
5655
|
+
}
|
|
5656
|
+
return () => {
|
|
5657
|
+
listeners3.delete(onChange);
|
|
5658
|
+
if (listeners3.size === 0 && typeof window !== "undefined") {
|
|
5659
|
+
window.removeEventListener("storage", onStorageEvent);
|
|
5660
|
+
}
|
|
5661
|
+
};
|
|
5662
|
+
}
|
|
5663
|
+
};
|
|
5664
|
+
}
|
|
5627
5665
|
function applyPrefs(prefs, root = document.documentElement) {
|
|
5628
5666
|
root.setAttribute("data-theme", resolveTheme(prefs.theme));
|
|
5629
5667
|
root.setAttribute("data-text-scale", prefs.textScale);
|
|
@@ -5632,13 +5670,12 @@ function applyPrefs(prefs, root = document.documentElement) {
|
|
|
5632
5670
|
if (prefs.reduceMotion) root.setAttribute("data-motion", "reduce");
|
|
5633
5671
|
else root.removeAttribute("data-motion");
|
|
5634
5672
|
}
|
|
5635
|
-
function useAppearancePrefs(
|
|
5636
|
-
const
|
|
5637
|
-
|
|
5673
|
+
function useAppearancePrefs(store) {
|
|
5674
|
+
const prefs = React34.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
5675
|
+
React34.useEffect(() => {
|
|
5638
5676
|
applyPrefs(prefs);
|
|
5639
|
-
savePrefs(prefs, opts);
|
|
5640
5677
|
}, [prefs]);
|
|
5641
|
-
|
|
5678
|
+
React34.useEffect(() => {
|
|
5642
5679
|
if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
5643
5680
|
return;
|
|
5644
5681
|
}
|
|
@@ -5647,9 +5684,12 @@ function useAppearancePrefs(opts) {
|
|
|
5647
5684
|
mq.addEventListener("change", onChange);
|
|
5648
5685
|
return () => mq.removeEventListener("change", onChange);
|
|
5649
5686
|
}, [prefs]);
|
|
5650
|
-
const update =
|
|
5651
|
-
|
|
5652
|
-
|
|
5687
|
+
const update = React34.useCallback(
|
|
5688
|
+
(patch) => {
|
|
5689
|
+
store.write({ ...store.getSnapshot(), ...patch });
|
|
5690
|
+
},
|
|
5691
|
+
[store]
|
|
5692
|
+
);
|
|
5653
5693
|
return [prefs, update];
|
|
5654
5694
|
}
|
|
5655
5695
|
|
|
@@ -5666,12 +5706,16 @@ var TEXT_SCALE_OPTIONS = [
|
|
|
5666
5706
|
{ value: "lg", label: "L" },
|
|
5667
5707
|
{ value: "xl", label: "XL" }
|
|
5668
5708
|
];
|
|
5669
|
-
function AppearanceMenu({ className = "",
|
|
5670
|
-
const
|
|
5671
|
-
|
|
5672
|
-
|
|
5709
|
+
function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
|
|
5710
|
+
const store = React35.useMemo(
|
|
5711
|
+
() => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
|
|
5712
|
+
[storeProp, storageKey, storage, defaults]
|
|
5713
|
+
);
|
|
5714
|
+
const [prefs, update] = useAppearancePrefs(store);
|
|
5715
|
+
const [open, setOpen] = React35.useState(false);
|
|
5716
|
+
const anchorRef = React35.useRef(null);
|
|
5673
5717
|
const patch = (p) => update(p);
|
|
5674
|
-
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
|
|
5718
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(React35.Fragment, { children: [
|
|
5675
5719
|
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
5676
5720
|
IconButton,
|
|
5677
5721
|
{
|
|
@@ -5740,14 +5784,14 @@ function AppearanceMenu({ className = "", ...storeOptions }) {
|
|
|
5740
5784
|
}
|
|
5741
5785
|
|
|
5742
5786
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
5743
|
-
var
|
|
5787
|
+
var React36 = __toESM(require("react"), 1);
|
|
5744
5788
|
var import_jsx_runtime61 = require("react/jsx-runtime");
|
|
5745
5789
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
5746
5790
|
function Json({ obj }) {
|
|
5747
5791
|
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
5748
5792
|
}
|
|
5749
5793
|
function Endpoint({ s, onRequest }) {
|
|
5750
|
-
const [tried, setTried] =
|
|
5794
|
+
const [tried, setTried] = React36.useState(null);
|
|
5751
5795
|
const run = async () => {
|
|
5752
5796
|
setTried("busy");
|
|
5753
5797
|
const t0 = (window.performance || Date).now();
|
|
@@ -5820,10 +5864,10 @@ function ApiSpecBrowser({
|
|
|
5820
5864
|
className = "",
|
|
5821
5865
|
...rest
|
|
5822
5866
|
}) {
|
|
5823
|
-
const [q, setQ] =
|
|
5824
|
-
const [method, setMethod] =
|
|
5825
|
-
const [mod, setMod] =
|
|
5826
|
-
const [listOnly, setListOnly] =
|
|
5867
|
+
const [q, setQ] = React36.useState("");
|
|
5868
|
+
const [method, setMethod] = React36.useState(null);
|
|
5869
|
+
const [mod, setMod] = React36.useState(null);
|
|
5870
|
+
const [listOnly, setListOnly] = React36.useState(false);
|
|
5827
5871
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
5828
5872
|
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())));
|
|
5829
5873
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
@@ -5902,139 +5946,174 @@ function ApiSpecBrowser({
|
|
|
5902
5946
|
}
|
|
5903
5947
|
|
|
5904
5948
|
// src/components/platform/ProfilePage.tsx
|
|
5905
|
-
var
|
|
5949
|
+
var React37 = __toESM(require("react"), 1);
|
|
5906
5950
|
var import_jsx_runtime62 = require("react/jsx-runtime");
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5951
|
+
function fieldInitialValue(field, user) {
|
|
5952
|
+
if (field.value) return field.value(user);
|
|
5953
|
+
const raw = user[field.key];
|
|
5954
|
+
return raw == null ? "" : String(raw);
|
|
5955
|
+
}
|
|
5956
|
+
function groupFields(fields) {
|
|
5957
|
+
const order = [];
|
|
5958
|
+
const byGroup = /* @__PURE__ */ new Map();
|
|
5959
|
+
for (const field of fields) {
|
|
5960
|
+
const group = field.group ?? "Identity";
|
|
5961
|
+
if (!byGroup.has(group)) {
|
|
5962
|
+
byGroup.set(group, { group, description: field.groupDescription, fields: [] });
|
|
5963
|
+
order.push(group);
|
|
5964
|
+
}
|
|
5965
|
+
const entry = byGroup.get(group);
|
|
5966
|
+
if (entry.description === void 0) entry.description = field.groupDescription;
|
|
5967
|
+
entry.fields.push(field);
|
|
5968
|
+
}
|
|
5969
|
+
return order.map((g) => byGroup.get(g));
|
|
5970
|
+
}
|
|
5971
|
+
function ProfilePage({
|
|
5972
|
+
user: userProp,
|
|
5973
|
+
fields = [],
|
|
5974
|
+
notifications = [],
|
|
5975
|
+
extra,
|
|
5976
|
+
onChangePhoto,
|
|
5977
|
+
onSave,
|
|
5978
|
+
onNavigate,
|
|
5979
|
+
sessions,
|
|
5980
|
+
onSignOutEverywhere,
|
|
5981
|
+
className = ""
|
|
5982
|
+
}) {
|
|
5916
5983
|
const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
|
|
5917
5984
|
const user = userProp || sessionUser;
|
|
5918
|
-
const
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
const [
|
|
5929
|
-
const
|
|
5930
|
-
|
|
5985
|
+
const initialFieldValues = React37.useMemo(() => {
|
|
5986
|
+
const values2 = {};
|
|
5987
|
+
for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
|
|
5988
|
+
return values2;
|
|
5989
|
+
}, [user.id, fields]);
|
|
5990
|
+
const initialNotify = React37.useMemo(() => {
|
|
5991
|
+
const values2 = {};
|
|
5992
|
+
for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
|
|
5993
|
+
return values2;
|
|
5994
|
+
}, [user.id, notifications]);
|
|
5995
|
+
const [values, setValues] = React37.useState(initialFieldValues);
|
|
5996
|
+
const [notify, setNotify] = React37.useState(initialNotify);
|
|
5997
|
+
const [saving, setSaving] = React37.useState(false);
|
|
5998
|
+
const [saved, setSaved] = React37.useState(false);
|
|
5999
|
+
const [prevUserId, setPrevUserId] = React37.useState(user.id);
|
|
6000
|
+
if (user.id !== prevUserId) {
|
|
6001
|
+
setPrevUserId(user.id);
|
|
6002
|
+
setValues(initialFieldValues);
|
|
6003
|
+
setNotify(initialNotify);
|
|
6004
|
+
setSaved(false);
|
|
6005
|
+
}
|
|
6006
|
+
const setField = (key, v) => {
|
|
6007
|
+
setValues((d) => ({ ...d, [key]: v }));
|
|
5931
6008
|
setSaved(false);
|
|
5932
6009
|
};
|
|
5933
|
-
const
|
|
5934
|
-
|
|
6010
|
+
const toggleNotify = (key) => {
|
|
6011
|
+
setNotify((d) => ({ ...d, [key]: !d[key] }));
|
|
5935
6012
|
setSaved(false);
|
|
5936
6013
|
};
|
|
5937
|
-
const dirty =
|
|
5938
|
-
const canSave = !!(onSave || saveProfile2);
|
|
6014
|
+
const dirty = fields.some((f) => values[f.key] !== initialFieldValues[f.key]) || notifications.some((n) => notify[n.key] !== initialNotify[n.key]);
|
|
6015
|
+
const canSave = !!(onSave || saveProfile2) && (fields.length > 0 || notifications.length > 0);
|
|
5939
6016
|
const save = async () => {
|
|
5940
6017
|
if (!canSave) return;
|
|
5941
6018
|
setSaving(true);
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
6019
|
+
const draft = { ...values };
|
|
6020
|
+
if (notifications.length > 0) draft.notify = notify;
|
|
6021
|
+
try {
|
|
6022
|
+
if (onSave) await onSave(draft);
|
|
6023
|
+
else await saveProfile2(draft);
|
|
6024
|
+
setSaved(true);
|
|
6025
|
+
} finally {
|
|
6026
|
+
setSaving(false);
|
|
6027
|
+
}
|
|
5946
6028
|
};
|
|
5947
|
-
const
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
6029
|
+
const discard = () => {
|
|
6030
|
+
setValues(initialFieldValues);
|
|
6031
|
+
setNotify(initialNotify);
|
|
6032
|
+
setSaved(false);
|
|
6033
|
+
};
|
|
6034
|
+
const displayName = fields.some((f) => f.key === "name") ? values.name || user.name : user.name;
|
|
6035
|
+
const fieldGroups = groupFields(fields);
|
|
6036
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
|
|
5953
6037
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
5954
6038
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
|
|
5955
6039
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
|
|
5956
6040
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
|
|
5957
6041
|
] }),
|
|
5958
6042
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
|
|
5959
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Avatar, { name:
|
|
6043
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Avatar, { name: displayName, size: "lg" }),
|
|
5960
6044
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
|
|
5961
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children:
|
|
5962
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
5963
|
-
draft.title || "No title set",
|
|
5964
|
-
" \xB7 ",
|
|
5965
|
-
user.team || "No team"
|
|
5966
|
-
] }),
|
|
6045
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
|
|
5967
6046
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
|
|
5968
6047
|
roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
|
|
5969
6048
|
user.sso ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
|
|
5970
6049
|
] })
|
|
5971
6050
|
] }),
|
|
5972
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", children: "Change photo" })
|
|
6051
|
+
onChangePhoto ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
|
|
5973
6052
|
] }) }),
|
|
5974
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6053
|
+
fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
5975
6054
|
Card,
|
|
5976
6055
|
{
|
|
5977
|
-
title: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
5978
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { children:
|
|
5979
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children:
|
|
5980
|
-
] }),
|
|
6056
|
+
title: description ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
6057
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { children: group }),
|
|
6058
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
|
|
6059
|
+
] }) : group,
|
|
5981
6060
|
elevation: "flat",
|
|
5982
6061
|
children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
|
|
5983
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
6062
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
|
|
6063
|
+
const help = typeof field.help === "function" ? field.help(user) : field.help;
|
|
6064
|
+
const readOnly = field.readOnly || field.type === "readonly";
|
|
6065
|
+
if (field.type === "select") {
|
|
6066
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6067
|
+
Select,
|
|
6068
|
+
{
|
|
6069
|
+
label: field.label,
|
|
6070
|
+
value: values[field.key],
|
|
6071
|
+
onChange: readOnly ? void 0 : (e) => setField(field.key, e.target.value),
|
|
6072
|
+
options: field.options ?? [],
|
|
6073
|
+
placeholder: field.placeholder,
|
|
6074
|
+
help,
|
|
6075
|
+
disabled: readOnly
|
|
6076
|
+
},
|
|
6077
|
+
field.key
|
|
6078
|
+
);
|
|
6079
|
+
}
|
|
6080
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
5989
6081
|
Input,
|
|
5990
6082
|
{
|
|
5991
|
-
label:
|
|
5992
|
-
value:
|
|
5993
|
-
readOnly:
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6083
|
+
label: field.label,
|
|
6084
|
+
value: values[field.key],
|
|
6085
|
+
onChange: readOnly ? void 0 : (e) => setField(field.key, e.target.value),
|
|
6086
|
+
readOnly,
|
|
6087
|
+
disabled: readOnly,
|
|
6088
|
+
placeholder: field.placeholder,
|
|
6089
|
+
help
|
|
6090
|
+
},
|
|
6091
|
+
field.key
|
|
6092
|
+
);
|
|
6093
|
+
}) }),
|
|
6094
|
+
groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
|
|
6095
|
+
const help = typeof field.help === "function" ? field.help(user) : field.help;
|
|
6096
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6097
|
+
Textarea,
|
|
6098
|
+
{
|
|
6099
|
+
label: field.label,
|
|
6100
|
+
value: values[field.key],
|
|
6101
|
+
onChange: field.readOnly ? void 0 : (e) => setField(field.key, e.target.value),
|
|
6102
|
+
readOnly: field.readOnly,
|
|
6103
|
+
disabled: field.readOnly,
|
|
6104
|
+
rows: field.rows ?? 3,
|
|
6105
|
+
placeholder: field.placeholder,
|
|
6106
|
+
help
|
|
6107
|
+
},
|
|
6108
|
+
field.key
|
|
6109
|
+
);
|
|
6110
|
+
})
|
|
6011
6111
|
] })
|
|
6012
|
-
}
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
{
|
|
6018
|
-
label: "Time zone",
|
|
6019
|
-
value: draft.timezone,
|
|
6020
|
-
onChange: (e) => set("timezone", e.target.value),
|
|
6021
|
-
options: TIMEZONES,
|
|
6022
|
-
help: "Flight dates and schedules render in this zone."
|
|
6023
|
-
}
|
|
6024
|
-
),
|
|
6025
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Select, { label: "Start of week", options: ["Monday", "Sunday"], placeholder: "Monday" })
|
|
6026
|
-
] }) }),
|
|
6027
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6028
|
-
Card,
|
|
6029
|
-
{
|
|
6030
|
-
title: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
6031
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { children: "Notifications" }),
|
|
6032
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Email only for now \u2014 in-app notifications are on the roadmap" })
|
|
6033
|
-
] }),
|
|
6034
|
-
elevation: "flat",
|
|
6035
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "fd-stack", style: { gap: 14 }, children: NOTIFY.map((n) => /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Switch, { checked: !!draft.notify[n.key], onChange: () => setNotify(n.key), label: n.label, description: n.detail }, n.key)) })
|
|
6036
|
-
}
|
|
6037
|
-
),
|
|
6112
|
+
},
|
|
6113
|
+
group
|
|
6114
|
+
)),
|
|
6115
|
+
extra,
|
|
6116
|
+
notifications.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
|
|
6038
6117
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
|
|
6039
6118
|
Card,
|
|
6040
6119
|
{
|
|
@@ -6066,13 +6145,13 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6066
6145
|
]
|
|
6067
6146
|
}
|
|
6068
6147
|
),
|
|
6069
|
-
|
|
6148
|
+
sessions ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6070
6149
|
Card,
|
|
6071
6150
|
{
|
|
6072
6151
|
title: "Signed-in devices",
|
|
6073
6152
|
elevation: "flat",
|
|
6074
|
-
action: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", children: "Sign out everywhere" }),
|
|
6075
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children:
|
|
6153
|
+
action: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
|
|
6154
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
|
|
6076
6155
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
6077
6156
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
|
|
6078
6157
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
|
|
@@ -6098,29 +6177,17 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6098
6177
|
boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
|
|
6099
6178
|
}, children: [
|
|
6100
6179
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
|
|
6101
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6102
|
-
Button,
|
|
6103
|
-
{
|
|
6104
|
-
size: "sm",
|
|
6105
|
-
variant: "ghost",
|
|
6106
|
-
disabled: !dirty || saving,
|
|
6107
|
-
onClick: () => {
|
|
6108
|
-
setDraft({ name: user.name || "", title: user.title || "", email: user.email || "", phone: user.phone || "", timezone: user.timezone || TIMEZONES[2], bio: user.bio || "", notify: user.notify || { planShared: true, planChanged: true, goalMissed: true, flagChanged: false, weekly: true } });
|
|
6109
|
-
setSaved(false);
|
|
6110
|
-
},
|
|
6111
|
-
children: "Discard"
|
|
6112
|
-
}
|
|
6113
|
-
),
|
|
6180
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
|
|
6114
6181
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
|
|
6115
6182
|
] })
|
|
6116
6183
|
] });
|
|
6117
6184
|
}
|
|
6118
6185
|
|
|
6119
6186
|
// src/components/platform/RoadmapTimeline.tsx
|
|
6120
|
-
var
|
|
6187
|
+
var React40 = __toESM(require("react"), 1);
|
|
6121
6188
|
|
|
6122
6189
|
// src/kits/session.ts
|
|
6123
|
-
var
|
|
6190
|
+
var React38 = __toESM(require("react"), 1);
|
|
6124
6191
|
var PERMISSION_CATALOG = [
|
|
6125
6192
|
{ group: "Plans", items: [
|
|
6126
6193
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -7687,8 +7754,8 @@ function roadmap(overrides) {
|
|
|
7687
7754
|
};
|
|
7688
7755
|
}
|
|
7689
7756
|
function useSession() {
|
|
7690
|
-
const [s, setS] =
|
|
7691
|
-
|
|
7757
|
+
const [s, setS] = React38.useState(getSession);
|
|
7758
|
+
React38.useEffect(() => subscribe(setS), []);
|
|
7692
7759
|
return s;
|
|
7693
7760
|
}
|
|
7694
7761
|
var SessionKit = {
|
|
@@ -7721,7 +7788,7 @@ var SessionKit = {
|
|
|
7721
7788
|
};
|
|
7722
7789
|
function DemoSessionProvider({ children }) {
|
|
7723
7790
|
const session = useSession();
|
|
7724
|
-
const value =
|
|
7791
|
+
const value = React38.useMemo(
|
|
7725
7792
|
() => ({
|
|
7726
7793
|
user: session.user,
|
|
7727
7794
|
roles: session.roles,
|
|
@@ -7737,11 +7804,11 @@ function DemoSessionProvider({ children }) {
|
|
|
7737
7804
|
}),
|
|
7738
7805
|
[session]
|
|
7739
7806
|
);
|
|
7740
|
-
return
|
|
7807
|
+
return React38.createElement(SessionProvider, { value }, children);
|
|
7741
7808
|
}
|
|
7742
7809
|
|
|
7743
7810
|
// src/kits/runtime.ts
|
|
7744
|
-
var
|
|
7811
|
+
var React39 = __toESM(require("react"), 1);
|
|
7745
7812
|
var WIRED_ENDPOINTS = [
|
|
7746
7813
|
// Nothing yet. Every id below would come from a real service:
|
|
7747
7814
|
// "plan.get", "placements.list", …
|
|
@@ -7912,8 +7979,8 @@ var RuntimeKit = {
|
|
|
7912
7979
|
};
|
|
7913
7980
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
7914
7981
|
function useRuntimeMode() {
|
|
7915
|
-
const [m, setM] =
|
|
7916
|
-
|
|
7982
|
+
const [m, setM] = React39.useState(RuntimeKit.getMode());
|
|
7983
|
+
React39.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
7917
7984
|
return m;
|
|
7918
7985
|
}
|
|
7919
7986
|
function useFeatureStatus(key) {
|
|
@@ -7996,12 +8063,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
7996
8063
|
}
|
|
7997
8064
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
7998
8065
|
const session = SessionKit.useSession();
|
|
7999
|
-
const [project, setProject] =
|
|
8000
|
-
const [q, setQ] =
|
|
8001
|
-
const scrollRef =
|
|
8002
|
-
const nowRef =
|
|
8003
|
-
const rm =
|
|
8004
|
-
const byKey =
|
|
8066
|
+
const [project, setProject] = React40.useState("");
|
|
8067
|
+
const [q, setQ] = React40.useState("");
|
|
8068
|
+
const scrollRef = React40.useRef(null);
|
|
8069
|
+
const nowRef = React40.useRef(null);
|
|
8070
|
+
const rm = React40.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
8071
|
+
const byKey = React40.useMemo(() => {
|
|
8005
8072
|
const m = {};
|
|
8006
8073
|
rm.items.forEach((i) => {
|
|
8007
8074
|
m[i.key] = i;
|
|
@@ -8010,7 +8077,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
8010
8077
|
}, [rm]);
|
|
8011
8078
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
8012
8079
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
8013
|
-
|
|
8080
|
+
React40.useEffect(() => {
|
|
8014
8081
|
let raf1 = 0, raf2 = 0;
|
|
8015
8082
|
const place = () => {
|
|
8016
8083
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -8084,7 +8151,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
8084
8151
|
lastPhase = item.phase;
|
|
8085
8152
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
8086
8153
|
const isBoundary = n === firstPending;
|
|
8087
|
-
return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
|
|
8154
|
+
return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(React40.Fragment, { children: [
|
|
8088
8155
|
showPhase ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "fd-rm-era", children: [
|
|
8089
8156
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
8090
8157
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
@@ -8128,7 +8195,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
8128
8195
|
}
|
|
8129
8196
|
|
|
8130
8197
|
// src/components/platform/ComingSoon.tsx
|
|
8131
|
-
var
|
|
8198
|
+
var React41 = __toESM(require("react"), 1);
|
|
8132
8199
|
var import_react_dom5 = require("react-dom");
|
|
8133
8200
|
var import_jsx_runtime64 = require("react/jsx-runtime");
|
|
8134
8201
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
@@ -8146,8 +8213,8 @@ function writeBypassed(list) {
|
|
|
8146
8213
|
}
|
|
8147
8214
|
}
|
|
8148
8215
|
function useBypass(key) {
|
|
8149
|
-
const [on, setOn] =
|
|
8150
|
-
|
|
8216
|
+
const [on, setOn] = React41.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
8217
|
+
React41.useEffect(() => {
|
|
8151
8218
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
8152
8219
|
}, [key]);
|
|
8153
8220
|
const set = (next) => {
|
|
@@ -8194,9 +8261,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
|
|
|
8194
8261
|
] });
|
|
8195
8262
|
}
|
|
8196
8263
|
function useHoverCard(open) {
|
|
8197
|
-
const anchor =
|
|
8198
|
-
const [pos, setPos] =
|
|
8199
|
-
|
|
8264
|
+
const anchor = React41.useRef(null);
|
|
8265
|
+
const [pos, setPos] = React41.useState(null);
|
|
8266
|
+
React41.useLayoutEffect(() => {
|
|
8200
8267
|
if (!open || !anchor.current) {
|
|
8201
8268
|
setPos(null);
|
|
8202
8269
|
return;
|
|
@@ -8323,10 +8390,10 @@ function ComingSoon({
|
|
|
8323
8390
|
] });
|
|
8324
8391
|
}
|
|
8325
8392
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
8326
|
-
const [open, setOpen] =
|
|
8393
|
+
const [open, setOpen] = React41.useState(false);
|
|
8327
8394
|
const [anchor, pos] = useHoverCard(open);
|
|
8328
8395
|
const zIndex = useOverlayLayer(open);
|
|
8329
|
-
const close =
|
|
8396
|
+
const close = React41.useRef(null);
|
|
8330
8397
|
const show = () => {
|
|
8331
8398
|
if (close.current) {
|
|
8332
8399
|
clearTimeout(close.current);
|
|
@@ -8342,7 +8409,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
8342
8409
|
setOpen(false);
|
|
8343
8410
|
}, 140);
|
|
8344
8411
|
};
|
|
8345
|
-
|
|
8412
|
+
React41.useEffect(() => () => {
|
|
8346
8413
|
if (close.current) clearTimeout(close.current);
|
|
8347
8414
|
}, []);
|
|
8348
8415
|
return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
|
|
@@ -8513,14 +8580,14 @@ function PermissionHint({ perm, children }) {
|
|
|
8513
8580
|
}
|
|
8514
8581
|
|
|
8515
8582
|
// src/components/platform/ModeSwitch.tsx
|
|
8516
|
-
var
|
|
8583
|
+
var React42 = __toESM(require("react"), 1);
|
|
8517
8584
|
var import_jsx_runtime66 = require("react/jsx-runtime");
|
|
8518
8585
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
8519
8586
|
const mode2 = useRuntimeMode();
|
|
8520
|
-
const [open, setOpen] =
|
|
8587
|
+
const [open, setOpen] = React42.useState(false);
|
|
8521
8588
|
const zIndex = useOverlayLayer(open);
|
|
8522
|
-
const ref =
|
|
8523
|
-
|
|
8589
|
+
const ref = React42.useRef(null);
|
|
8590
|
+
React42.useEffect(() => {
|
|
8524
8591
|
if (!open) return;
|
|
8525
8592
|
const away = (e) => {
|
|
8526
8593
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -8776,7 +8843,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8776
8843
|
}
|
|
8777
8844
|
|
|
8778
8845
|
// src/components/planner/MixGap.tsx
|
|
8779
|
-
var
|
|
8846
|
+
var React43 = __toESM(require("react"), 1);
|
|
8780
8847
|
var import_jsx_runtime69 = require("react/jsx-runtime");
|
|
8781
8848
|
var MIX_GAP_LAYOUT = {
|
|
8782
8849
|
trackHeight: 30,
|
|
@@ -8791,7 +8858,7 @@ function mixGapOffset(value, max) {
|
|
|
8791
8858
|
}
|
|
8792
8859
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
8793
8860
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
8794
|
-
const [hover, setHover] =
|
|
8861
|
+
const [hover, setHover] = React43.useState(null);
|
|
8795
8862
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
8796
8863
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
8797
8864
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
@@ -8934,7 +9001,7 @@ function ChannelContribution({
|
|
|
8934
9001
|
}
|
|
8935
9002
|
|
|
8936
9003
|
// src/components/planner/BudgetReallocator.tsx
|
|
8937
|
-
var
|
|
9004
|
+
var React44 = __toESM(require("react"), 1);
|
|
8938
9005
|
var import_jsx_runtime71 = require("react/jsx-runtime");
|
|
8939
9006
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
8940
9007
|
function BudgetReallocator({
|
|
@@ -8950,8 +9017,8 @@ function BudgetReallocator({
|
|
|
8950
9017
|
onCancel,
|
|
8951
9018
|
className = ""
|
|
8952
9019
|
}) {
|
|
8953
|
-
const [draft, setDraft] =
|
|
8954
|
-
|
|
9020
|
+
const [draft, setDraft] = React44.useState(spend);
|
|
9021
|
+
React44.useEffect(() => setDraft(spend), [spend]);
|
|
8955
9022
|
const dirty = draft !== spend;
|
|
8956
9023
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
8957
9024
|
const nextBand = bandFor(nextCrp);
|
|
@@ -8966,10 +9033,10 @@ function BudgetReallocator({
|
|
|
8966
9033
|
setDraft(spend);
|
|
8967
9034
|
if (onCancel) onCancel();
|
|
8968
9035
|
};
|
|
8969
|
-
const trackRef =
|
|
8970
|
-
const chipRef =
|
|
8971
|
-
const [chipLeft, setChipLeft] =
|
|
8972
|
-
|
|
9036
|
+
const trackRef = React44.useRef(null);
|
|
9037
|
+
const chipRef = React44.useRef(null);
|
|
9038
|
+
const [chipLeft, setChipLeft] = React44.useState(null);
|
|
9039
|
+
React44.useLayoutEffect(() => {
|
|
8973
9040
|
const track = trackRef.current;
|
|
8974
9041
|
if (!dirty || !track) {
|
|
8975
9042
|
setChipLeft(null);
|
|
@@ -9156,7 +9223,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "" })
|
|
|
9156
9223
|
}
|
|
9157
9224
|
|
|
9158
9225
|
// src/components/planner/PreferenceMeter.tsx
|
|
9159
|
-
var
|
|
9226
|
+
var React45 = __toESM(require("react"), 1);
|
|
9160
9227
|
var import_jsx_runtime74 = require("react/jsx-runtime");
|
|
9161
9228
|
function preferenceScore(criteria) {
|
|
9162
9229
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
@@ -9186,7 +9253,7 @@ function PreferenceMeter({
|
|
|
9186
9253
|
className = ""
|
|
9187
9254
|
}) {
|
|
9188
9255
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
9189
|
-
const segments =
|
|
9256
|
+
const segments = React45.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
9190
9257
|
return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
|
|
9191
9258
|
ScoreMeter,
|
|
9192
9259
|
{
|
|
@@ -9225,10 +9292,10 @@ function PreferenceMeter({
|
|
|
9225
9292
|
}
|
|
9226
9293
|
|
|
9227
9294
|
// src/components/chat/AgentChatPanel.tsx
|
|
9228
|
-
var
|
|
9295
|
+
var React51 = __toESM(require("react"), 1);
|
|
9229
9296
|
|
|
9230
9297
|
// src/components/chat/chatEngine.ts
|
|
9231
|
-
var
|
|
9298
|
+
var React46 = __toESM(require("react"), 1);
|
|
9232
9299
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
9233
9300
|
var JOB_PENDING = ["queued", "running"];
|
|
9234
9301
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -9282,22 +9349,22 @@ function useChatEngine(opts) {
|
|
|
9282
9349
|
onClear,
|
|
9283
9350
|
onFeedback
|
|
9284
9351
|
} = opts || {};
|
|
9285
|
-
const [status, setStatus] =
|
|
9286
|
-
const [threadId, setThreadId] =
|
|
9287
|
-
const [messages, setMessages] =
|
|
9288
|
-
const [queue, setQueue] =
|
|
9289
|
-
const [fatal, setFatal] =
|
|
9290
|
-
const [busy, setBusy] =
|
|
9291
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
9292
|
-
const listRef =
|
|
9293
|
-
const queueRef =
|
|
9294
|
-
const busyRef =
|
|
9295
|
-
const stoppedRef =
|
|
9296
|
-
const abortRef =
|
|
9297
|
-
const serverCount =
|
|
9298
|
-
const threadRef =
|
|
9299
|
-
const mounted =
|
|
9300
|
-
|
|
9352
|
+
const [status, setStatus] = React46.useState("idle");
|
|
9353
|
+
const [threadId, setThreadId] = React46.useState(null);
|
|
9354
|
+
const [messages, setMessages] = React46.useState([]);
|
|
9355
|
+
const [queue, setQueue] = React46.useState([]);
|
|
9356
|
+
const [fatal, setFatal] = React46.useState(null);
|
|
9357
|
+
const [busy, setBusy] = React46.useState(false);
|
|
9358
|
+
const [turnStartedAt, setTurnStartedAt] = React46.useState(null);
|
|
9359
|
+
const listRef = React46.useRef([]);
|
|
9360
|
+
const queueRef = React46.useRef([]);
|
|
9361
|
+
const busyRef = React46.useRef(false);
|
|
9362
|
+
const stoppedRef = React46.useRef(false);
|
|
9363
|
+
const abortRef = React46.useRef(null);
|
|
9364
|
+
const serverCount = React46.useRef(0);
|
|
9365
|
+
const threadRef = React46.useRef(null);
|
|
9366
|
+
const mounted = React46.useRef(true);
|
|
9367
|
+
React46.useEffect(() => {
|
|
9301
9368
|
mounted.current = true;
|
|
9302
9369
|
return () => {
|
|
9303
9370
|
mounted.current = false;
|
|
@@ -9319,14 +9386,14 @@ function useChatEngine(opts) {
|
|
|
9319
9386
|
}
|
|
9320
9387
|
return false;
|
|
9321
9388
|
};
|
|
9322
|
-
const loadThread =
|
|
9389
|
+
const loadThread = React46.useCallback(async (id) => {
|
|
9323
9390
|
const data = await apiAdapter.getThread(id);
|
|
9324
9391
|
const list = [...data && data.messages || []];
|
|
9325
9392
|
serverCount.current = list.length;
|
|
9326
9393
|
commit(list);
|
|
9327
9394
|
return list;
|
|
9328
9395
|
}, [apiAdapter]);
|
|
9329
|
-
|
|
9396
|
+
React46.useEffect(() => {
|
|
9330
9397
|
if (!apiAdapter) {
|
|
9331
9398
|
setStatus("idle");
|
|
9332
9399
|
setFatal(null);
|
|
@@ -9539,7 +9606,7 @@ function useChatEngine(opts) {
|
|
|
9539
9606
|
await dispatchTurn(turn);
|
|
9540
9607
|
}
|
|
9541
9608
|
}
|
|
9542
|
-
const send =
|
|
9609
|
+
const send = React46.useCallback((text, attachments) => {
|
|
9543
9610
|
const body = (text || "").trim();
|
|
9544
9611
|
if (!body && !(attachments && attachments.length)) return;
|
|
9545
9612
|
if (status === "disconnected") return;
|
|
@@ -9549,7 +9616,7 @@ function useChatEngine(opts) {
|
|
|
9549
9616
|
stoppedRef.current = false;
|
|
9550
9617
|
drain();
|
|
9551
9618
|
}, [status]);
|
|
9552
|
-
const stop =
|
|
9619
|
+
const stop = React46.useCallback(() => {
|
|
9553
9620
|
stoppedRef.current = true;
|
|
9554
9621
|
const ac = abortRef.current;
|
|
9555
9622
|
if (ac) {
|
|
@@ -9568,11 +9635,11 @@ function useChatEngine(opts) {
|
|
|
9568
9635
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
9569
9636
|
}
|
|
9570
9637
|
}, [apiAdapter]);
|
|
9571
|
-
const removeQueued =
|
|
9638
|
+
const removeQueued = React46.useCallback((id) => {
|
|
9572
9639
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
9573
9640
|
setQueue(queueRef.current.slice());
|
|
9574
9641
|
}, []);
|
|
9575
|
-
const retry =
|
|
9642
|
+
const retry = React46.useCallback(() => {
|
|
9576
9643
|
const list = listRef.current;
|
|
9577
9644
|
let at = -1;
|
|
9578
9645
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -9588,19 +9655,19 @@ function useChatEngine(opts) {
|
|
|
9588
9655
|
setQueue(queueRef.current.slice());
|
|
9589
9656
|
drain();
|
|
9590
9657
|
}, []);
|
|
9591
|
-
const clear =
|
|
9658
|
+
const clear = React46.useCallback(() => {
|
|
9592
9659
|
commit([]);
|
|
9593
9660
|
serverCount.current = 0;
|
|
9594
9661
|
queueRef.current = [];
|
|
9595
9662
|
setQueue([]);
|
|
9596
9663
|
onClear && onClear();
|
|
9597
9664
|
}, [onClear]);
|
|
9598
|
-
const setFeedback =
|
|
9665
|
+
const setFeedback = React46.useCallback((id, value) => {
|
|
9599
9666
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
9600
9667
|
const msg = listRef.current.find((m) => m.id === id);
|
|
9601
9668
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
9602
9669
|
}, [onFeedback]);
|
|
9603
|
-
const reload =
|
|
9670
|
+
const reload = React46.useCallback(async () => {
|
|
9604
9671
|
if (!threadRef.current) return;
|
|
9605
9672
|
setStatus("loading");
|
|
9606
9673
|
try {
|
|
@@ -9638,10 +9705,10 @@ var ChatKit = {
|
|
|
9638
9705
|
};
|
|
9639
9706
|
|
|
9640
9707
|
// src/components/chat/ChatTranscript.tsx
|
|
9641
|
-
var
|
|
9708
|
+
var React48 = __toESM(require("react"), 1);
|
|
9642
9709
|
|
|
9643
9710
|
// src/components/chat/ChatTurn.tsx
|
|
9644
|
-
var
|
|
9711
|
+
var React47 = __toESM(require("react"), 1);
|
|
9645
9712
|
var import_jsx_runtime75 = require("react/jsx-runtime");
|
|
9646
9713
|
function JsonView({ value }) {
|
|
9647
9714
|
let text;
|
|
@@ -9678,7 +9745,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
|
9678
9745
|
] });
|
|
9679
9746
|
}
|
|
9680
9747
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
9681
|
-
const [open, setOpen] =
|
|
9748
|
+
const [open, setOpen] = React47.useState(defaultOpen);
|
|
9682
9749
|
if (!text) return null;
|
|
9683
9750
|
return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
|
|
9684
9751
|
/* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -9695,7 +9762,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
|
9695
9762
|
] });
|
|
9696
9763
|
}
|
|
9697
9764
|
function Citations({ items = [], onOpen }) {
|
|
9698
|
-
const [open, setOpen] =
|
|
9765
|
+
const [open, setOpen] = React47.useState(false);
|
|
9699
9766
|
if (!items.length) return null;
|
|
9700
9767
|
return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "fdc-cites", children: [
|
|
9701
9768
|
/* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -9721,7 +9788,7 @@ function clampText(text, max) {
|
|
|
9721
9788
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
9722
9789
|
}
|
|
9723
9790
|
function MessageBody({ message: m, ctx }) {
|
|
9724
|
-
const [expanded, setExpanded] =
|
|
9791
|
+
const [expanded, setExpanded] = React47.useState(false);
|
|
9725
9792
|
const isUser = m.role === "user";
|
|
9726
9793
|
const raw = m.text || "";
|
|
9727
9794
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
@@ -9788,9 +9855,9 @@ function MessageBody({ message: m, ctx }) {
|
|
|
9788
9855
|
] });
|
|
9789
9856
|
}
|
|
9790
9857
|
function useCopyRun() {
|
|
9791
|
-
const [done, setDone] =
|
|
9792
|
-
const t =
|
|
9793
|
-
|
|
9858
|
+
const [done, setDone] = React47.useState(false);
|
|
9859
|
+
const t = React47.useRef(null);
|
|
9860
|
+
React47.useEffect(() => () => {
|
|
9794
9861
|
if (t.current) clearTimeout(t.current);
|
|
9795
9862
|
}, []);
|
|
9796
9863
|
return [done, (text) => {
|
|
@@ -9817,7 +9884,7 @@ function RunActions({ group, ctx }) {
|
|
|
9817
9884
|
] }),
|
|
9818
9885
|
isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
9819
9886
|
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
9820
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(
|
|
9887
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(React47.Fragment, { children: [
|
|
9821
9888
|
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
9822
9889
|
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
9823
9890
|
] }) : null,
|
|
@@ -9912,10 +9979,10 @@ function ChatTranscript({
|
|
|
9912
9979
|
renderEmpty,
|
|
9913
9980
|
className = ""
|
|
9914
9981
|
}) {
|
|
9915
|
-
const scroller =
|
|
9916
|
-
const stick =
|
|
9917
|
-
const [pill, setPill] =
|
|
9918
|
-
const seen =
|
|
9982
|
+
const scroller = React48.useRef(null);
|
|
9983
|
+
const stick = React48.useRef(true);
|
|
9984
|
+
const [pill, setPill] = React48.useState(0);
|
|
9985
|
+
const seen = React48.useRef(0);
|
|
9919
9986
|
const toBottom = (smooth) => {
|
|
9920
9987
|
const el = scroller.current;
|
|
9921
9988
|
if (!el) return;
|
|
@@ -9934,7 +10001,7 @@ function ChatTranscript({
|
|
|
9934
10001
|
seen.current = messages.length;
|
|
9935
10002
|
}
|
|
9936
10003
|
};
|
|
9937
|
-
|
|
10004
|
+
React48.useLayoutEffect(() => {
|
|
9938
10005
|
const el = scroller.current;
|
|
9939
10006
|
if (!el) return;
|
|
9940
10007
|
if (stick.current) {
|
|
@@ -9942,7 +10009,7 @@ function ChatTranscript({
|
|
|
9942
10009
|
seen.current = messages.length;
|
|
9943
10010
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
9944
10011
|
}, [messages]);
|
|
9945
|
-
|
|
10012
|
+
React48.useEffect(() => {
|
|
9946
10013
|
const el = scroller.current;
|
|
9947
10014
|
const inner = el && el.firstChild;
|
|
9948
10015
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -9952,7 +10019,7 @@ function ChatTranscript({
|
|
|
9952
10019
|
ro.observe(inner);
|
|
9953
10020
|
return () => ro.disconnect();
|
|
9954
10021
|
}, []);
|
|
9955
|
-
const groups =
|
|
10022
|
+
const groups = React48.useMemo(() => groupMessages(messages), [messages]);
|
|
9956
10023
|
const empty = !messages.length && status === "ready";
|
|
9957
10024
|
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
9958
10025
|
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
@@ -9976,7 +10043,7 @@ function ChatTranscript({
|
|
|
9976
10043
|
const prev = groups[i - 1];
|
|
9977
10044
|
const k = dayKey(g.messages[0].timestamp);
|
|
9978
10045
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
9979
|
-
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
|
|
10046
|
+
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React48.Fragment, { children: [
|
|
9980
10047
|
showDay ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { children: dayLabel(k) }) }) : null,
|
|
9981
10048
|
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)(ChatTurn, { group: g, ctx })
|
|
9982
10049
|
] }, g.key || i);
|
|
@@ -9993,7 +10060,7 @@ function ChatTranscript({
|
|
|
9993
10060
|
var TranscriptKit = { groupMessages };
|
|
9994
10061
|
|
|
9995
10062
|
// src/components/chat/ChatComposer.tsx
|
|
9996
|
-
var
|
|
10063
|
+
var React49 = __toESM(require("react"), 1);
|
|
9997
10064
|
var import_jsx_runtime77 = require("react/jsx-runtime");
|
|
9998
10065
|
function ChatComposer({
|
|
9999
10066
|
onSubmit,
|
|
@@ -10021,17 +10088,17 @@ function ChatComposer({
|
|
|
10021
10088
|
onReject,
|
|
10022
10089
|
onOpenAttachment
|
|
10023
10090
|
}) {
|
|
10024
|
-
const [text, setText] =
|
|
10025
|
-
const [trigger, setTrigger] =
|
|
10026
|
-
const [mentionItems, setMentionItems] =
|
|
10027
|
-
const [listening, setListening] =
|
|
10028
|
-
const [notice, setNotice] =
|
|
10029
|
-
const editor =
|
|
10030
|
-
const wrap =
|
|
10031
|
-
const stopVoice =
|
|
10091
|
+
const [text, setText] = React49.useState(draft || "");
|
|
10092
|
+
const [trigger, setTrigger] = React49.useState(null);
|
|
10093
|
+
const [mentionItems, setMentionItems] = React49.useState([]);
|
|
10094
|
+
const [listening, setListening] = React49.useState(false);
|
|
10095
|
+
const [notice, setNotice] = React49.useState(null);
|
|
10096
|
+
const editor = React49.useRef(null);
|
|
10097
|
+
const wrap = React49.useRef(null);
|
|
10098
|
+
const stopVoice = React49.useRef(null);
|
|
10032
10099
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
10033
10100
|
} });
|
|
10034
|
-
|
|
10101
|
+
React49.useEffect(() => {
|
|
10035
10102
|
if (draft != null && draft !== text) setText(draft);
|
|
10036
10103
|
}, [draft]);
|
|
10037
10104
|
const change = (v) => {
|
|
@@ -10067,7 +10134,7 @@ function ChatComposer({
|
|
|
10067
10134
|
e.preventDefault();
|
|
10068
10135
|
staged.add(found.files);
|
|
10069
10136
|
};
|
|
10070
|
-
|
|
10137
|
+
React49.useEffect(() => {
|
|
10071
10138
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
10072
10139
|
setMentionItems([]);
|
|
10073
10140
|
return;
|
|
@@ -10085,7 +10152,7 @@ function ChatComposer({
|
|
|
10085
10152
|
const q = (trigger.query || "").toLowerCase();
|
|
10086
10153
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
10087
10154
|
}, [trigger, mentionSources]);
|
|
10088
|
-
const slashItems =
|
|
10155
|
+
const slashItems = React49.useMemo(() => {
|
|
10089
10156
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
10090
10157
|
const q = (trigger.query || "").toLowerCase();
|
|
10091
10158
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -10259,12 +10326,12 @@ function ChatComposer({
|
|
|
10259
10326
|
}
|
|
10260
10327
|
|
|
10261
10328
|
// src/components/chat/ChatSessionBar.tsx
|
|
10262
|
-
var
|
|
10329
|
+
var React50 = __toESM(require("react"), 1);
|
|
10263
10330
|
var import_jsx_runtime78 = require("react/jsx-runtime");
|
|
10264
10331
|
var compact2 = meterFormats.compact;
|
|
10265
10332
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
10266
|
-
const [open, setOpen] =
|
|
10267
|
-
const anchor =
|
|
10333
|
+
const [open, setOpen] = React50.useState(false);
|
|
10334
|
+
const anchor = React50.useRef(null);
|
|
10268
10335
|
const stats = sessionStats || null;
|
|
10269
10336
|
const cu = contextUsage || null;
|
|
10270
10337
|
const limits = usageLimits || null;
|
|
@@ -10279,7 +10346,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
10279
10346
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
10280
10347
|
if (cu) bits.push(pct + "% context");
|
|
10281
10348
|
const expandable = !!(cu || limits);
|
|
10282
|
-
return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
|
|
10349
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(React50.Fragment, { children: [
|
|
10283
10350
|
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fdc-bar", children: [
|
|
10284
10351
|
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
|
|
10285
10352
|
"button",
|
|
@@ -10420,7 +10487,7 @@ function ModelControls({
|
|
|
10420
10487
|
] })
|
|
10421
10488
|
});
|
|
10422
10489
|
}
|
|
10423
|
-
return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
|
|
10490
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(React50.Fragment, { children: [
|
|
10424
10491
|
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
10425
10492
|
MenuButton,
|
|
10426
10493
|
{
|
|
@@ -10537,11 +10604,11 @@ function AgentChatPanel({
|
|
|
10537
10604
|
onFeedback,
|
|
10538
10605
|
onEditMessage
|
|
10539
10606
|
}) {
|
|
10540
|
-
const [panelWidth, setPanelWidth] =
|
|
10541
|
-
const [applied, setApplied] =
|
|
10542
|
-
const [draft, setDraft] =
|
|
10543
|
-
const dragging =
|
|
10544
|
-
|
|
10607
|
+
const [panelWidth, setPanelWidth] = React51.useState(width);
|
|
10608
|
+
const [applied, setApplied] = React51.useState({});
|
|
10609
|
+
const [draft, setDraft] = React51.useState("");
|
|
10610
|
+
const dragging = React51.useRef(null);
|
|
10611
|
+
React51.useEffect(() => setPanelWidth(width), [width]);
|
|
10545
10612
|
const engine = useChatEngine({
|
|
10546
10613
|
contextType,
|
|
10547
10614
|
contextId,
|
|
@@ -10745,7 +10812,7 @@ function AgentChatPanel({
|
|
|
10745
10812
|
}
|
|
10746
10813
|
|
|
10747
10814
|
// src/components/files/FileViewer.tsx
|
|
10748
|
-
var
|
|
10815
|
+
var React52 = __toESM(require("react"), 1);
|
|
10749
10816
|
var import_jsx_runtime80 = require("react/jsx-runtime");
|
|
10750
10817
|
function previewKindOf(file) {
|
|
10751
10818
|
const mime = (file.mime || "").toLowerCase();
|
|
@@ -10802,13 +10869,13 @@ function parseDelimited(text, delimiter) {
|
|
|
10802
10869
|
return rows;
|
|
10803
10870
|
}
|
|
10804
10871
|
function usePreview(file, kind, resolveUrl) {
|
|
10805
|
-
const [state, setState] =
|
|
10806
|
-
const [attempt, setAttempt] =
|
|
10807
|
-
const resolveRef =
|
|
10808
|
-
|
|
10872
|
+
const [state, setState] = React52.useState({ status: "loading" });
|
|
10873
|
+
const [attempt, setAttempt] = React52.useState(0);
|
|
10874
|
+
const resolveRef = React52.useRef(resolveUrl);
|
|
10875
|
+
React52.useEffect(() => {
|
|
10809
10876
|
resolveRef.current = resolveUrl;
|
|
10810
10877
|
}, [resolveUrl]);
|
|
10811
|
-
|
|
10878
|
+
React52.useEffect(() => {
|
|
10812
10879
|
if (kind === "none") {
|
|
10813
10880
|
setState({ status: "ready" });
|
|
10814
10881
|
return;
|
|
@@ -10838,7 +10905,7 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
10838
10905
|
if (ac) ac.abort();
|
|
10839
10906
|
};
|
|
10840
10907
|
}, [file.id, kind, attempt]);
|
|
10841
|
-
return { ...state, retry:
|
|
10908
|
+
return { ...state, retry: React52.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
10842
10909
|
}
|
|
10843
10910
|
function PreviewBody({ file, kind, state }) {
|
|
10844
10911
|
if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
@@ -10883,13 +10950,13 @@ function PreviewBody({ file, kind, state }) {
|
|
|
10883
10950
|
] });
|
|
10884
10951
|
}
|
|
10885
10952
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
10886
|
-
const kind =
|
|
10953
|
+
const kind = React52.useMemo(() => previewKindOf(file), [file]);
|
|
10887
10954
|
const preview = usePreview(file, kind, resolveUrl);
|
|
10888
|
-
const [tab, setTab] =
|
|
10889
|
-
const [downloading, setDownloading] =
|
|
10890
|
-
const [downloadError, setDownloadError] =
|
|
10955
|
+
const [tab, setTab] = React52.useState("preview");
|
|
10956
|
+
const [downloading, setDownloading] = React52.useState(false);
|
|
10957
|
+
const [downloadError, setDownloadError] = React52.useState(null);
|
|
10891
10958
|
const hasSide = sidePanel != null;
|
|
10892
|
-
|
|
10959
|
+
React52.useEffect(() => {
|
|
10893
10960
|
setTab("preview");
|
|
10894
10961
|
}, [file.id]);
|
|
10895
10962
|
const download = () => {
|
|
@@ -10956,7 +11023,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
10956
11023
|
}
|
|
10957
11024
|
|
|
10958
11025
|
// src/components/files/FileBrowser.tsx
|
|
10959
|
-
var
|
|
11026
|
+
var React53 = __toESM(require("react"), 1);
|
|
10960
11027
|
var import_jsx_runtime81 = require("react/jsx-runtime");
|
|
10961
11028
|
function childrenOf(folders, parentId) {
|
|
10962
11029
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -11027,10 +11094,10 @@ function FolderPickerMenu({
|
|
|
11027
11094
|
destinations,
|
|
11028
11095
|
onPick
|
|
11029
11096
|
}) {
|
|
11030
|
-
const [open, setOpen] =
|
|
11097
|
+
const [open, setOpen] = React53.useState(false);
|
|
11031
11098
|
const zIndex = useOverlayLayer(open);
|
|
11032
|
-
const ref =
|
|
11033
|
-
|
|
11099
|
+
const ref = React53.useRef(null);
|
|
11100
|
+
React53.useEffect(() => {
|
|
11034
11101
|
if (!open) return;
|
|
11035
11102
|
const away = (e) => {
|
|
11036
11103
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -11082,8 +11149,8 @@ function FolderPickerMenu({
|
|
|
11082
11149
|
] });
|
|
11083
11150
|
}
|
|
11084
11151
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
11085
|
-
const [over, setOver] =
|
|
11086
|
-
const dragCounter =
|
|
11152
|
+
const [over, setOver] = React53.useState(false);
|
|
11153
|
+
const dragCounter = React53.useRef(0);
|
|
11087
11154
|
const dropHandlers = isDropTarget ? {
|
|
11088
11155
|
onDragEnter: (e) => {
|
|
11089
11156
|
if (!hasInternalPayload(e)) return;
|
|
@@ -11131,8 +11198,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
11131
11198
|
}
|
|
11132
11199
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
11133
11200
|
const kids = childrenOf(folders, folder.id);
|
|
11134
|
-
const [expanded, setExpanded] =
|
|
11135
|
-
|
|
11201
|
+
const [expanded, setExpanded] = React53.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
11202
|
+
React53.useEffect(() => {
|
|
11136
11203
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
11137
11204
|
}, [currentFolderId, folder.id, folders]);
|
|
11138
11205
|
const isCurrent = folder.id === currentFolderId;
|
|
@@ -11198,15 +11265,15 @@ function FileBrowser({
|
|
|
11198
11265
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
11199
11266
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
11200
11267
|
const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
|
|
11201
|
-
const [createOpen, setCreateOpen] =
|
|
11202
|
-
const [createName, setCreateName] =
|
|
11203
|
-
const [renameTarget, setRenameTarget] =
|
|
11204
|
-
const [renameValue, setRenameValue] =
|
|
11205
|
-
const [deleteTarget, setDeleteTarget] =
|
|
11206
|
-
const uploadInputRef =
|
|
11207
|
-
const crumbFolders =
|
|
11208
|
-
const subfolders =
|
|
11209
|
-
const currentFiles =
|
|
11268
|
+
const [createOpen, setCreateOpen] = React53.useState(false);
|
|
11269
|
+
const [createName, setCreateName] = React53.useState("");
|
|
11270
|
+
const [renameTarget, setRenameTarget] = React53.useState(null);
|
|
11271
|
+
const [renameValue, setRenameValue] = React53.useState("");
|
|
11272
|
+
const [deleteTarget, setDeleteTarget] = React53.useState(null);
|
|
11273
|
+
const uploadInputRef = React53.useRef(null);
|
|
11274
|
+
const crumbFolders = React53.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
11275
|
+
const subfolders = React53.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
11276
|
+
const currentFiles = React53.useMemo(
|
|
11210
11277
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
11211
11278
|
[files, currentFolderId]
|
|
11212
11279
|
);
|
|
@@ -11438,8 +11505,8 @@ function BreadcrumbCrumb({
|
|
|
11438
11505
|
isDropTarget,
|
|
11439
11506
|
onDropPayload
|
|
11440
11507
|
}) {
|
|
11441
|
-
const [over, setOver] =
|
|
11442
|
-
const dragCounter =
|
|
11508
|
+
const [over, setOver] = React53.useState(false);
|
|
11509
|
+
const dragCounter = React53.useRef(0);
|
|
11443
11510
|
const dropHandlers = isDropTarget ? {
|
|
11444
11511
|
onDragEnter: (e) => {
|
|
11445
11512
|
if (!hasInternalPayload(e)) return;
|
|
@@ -11468,7 +11535,7 @@ function BreadcrumbCrumb({
|
|
|
11468
11535
|
}
|
|
11469
11536
|
|
|
11470
11537
|
// src/kits/query.ts
|
|
11471
|
-
var
|
|
11538
|
+
var React54 = __toESM(require("react"), 1);
|
|
11472
11539
|
function eqFilter(get2) {
|
|
11473
11540
|
return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
|
|
11474
11541
|
}
|
|
@@ -11500,22 +11567,22 @@ function compare(a, b, dir) {
|
|
|
11500
11567
|
var API = null;
|
|
11501
11568
|
var PREFS = null;
|
|
11502
11569
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
11503
|
-
const [query, setQuery] =
|
|
11570
|
+
const [query, setQuery] = React54.useState(() => {
|
|
11504
11571
|
const store = PREFS || window.PlannerPrefs;
|
|
11505
11572
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
11506
11573
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
11507
11574
|
});
|
|
11508
|
-
const savePref =
|
|
11575
|
+
const savePref = React54.useCallback((patch2) => {
|
|
11509
11576
|
const store = PREFS || window.PlannerPrefs;
|
|
11510
11577
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
11511
11578
|
}, [prefsKey]);
|
|
11512
|
-
const [res, setRes] =
|
|
11513
|
-
const [loading, setLoading] =
|
|
11514
|
-
const seq2 =
|
|
11579
|
+
const [res, setRes] = React54.useState(null);
|
|
11580
|
+
const [loading, setLoading] = React54.useState(true);
|
|
11581
|
+
const seq2 = React54.useRef(0);
|
|
11515
11582
|
const depKey = (deps || []).join("|");
|
|
11516
11583
|
const paramKey = JSON.stringify(params || {});
|
|
11517
11584
|
const queryKey = JSON.stringify(query);
|
|
11518
|
-
|
|
11585
|
+
React54.useEffect(() => {
|
|
11519
11586
|
const id = ++seq2.current;
|
|
11520
11587
|
setLoading(true);
|
|
11521
11588
|
const t = setTimeout(() => {
|
|
@@ -11812,6 +11879,92 @@ function createVersionStore(initialState, options) {
|
|
|
11812
11879
|
}
|
|
11813
11880
|
};
|
|
11814
11881
|
}
|
|
11882
|
+
|
|
11883
|
+
// src/kits/useResponsiveRail.ts
|
|
11884
|
+
var React55 = __toESM(require("react"), 1);
|
|
11885
|
+
function matchesBreakpoint(breakpoint) {
|
|
11886
|
+
return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches;
|
|
11887
|
+
}
|
|
11888
|
+
var FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
11889
|
+
function getFocusable(container) {
|
|
11890
|
+
return Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR));
|
|
11891
|
+
}
|
|
11892
|
+
function useResponsiveRail(options = {}) {
|
|
11893
|
+
const { breakpoint = 1024, initialOpen = true, onPersist } = options;
|
|
11894
|
+
const navRef = React55.useRef(null);
|
|
11895
|
+
const [overlay, setOverlay] = React55.useState(() => matchesBreakpoint(breakpoint));
|
|
11896
|
+
const [open, setOpenRaw] = React55.useState(() => matchesBreakpoint(breakpoint) ? false : initialOpen);
|
|
11897
|
+
const setOpen = React55.useCallback(
|
|
11898
|
+
(value) => {
|
|
11899
|
+
setOpenRaw(value);
|
|
11900
|
+
if (!matchesBreakpoint(breakpoint)) onPersist?.(value);
|
|
11901
|
+
},
|
|
11902
|
+
[breakpoint, onPersist]
|
|
11903
|
+
);
|
|
11904
|
+
const toggle = React55.useCallback(() => setOpen(!open), [open, setOpen]);
|
|
11905
|
+
const close = React55.useCallback(() => setOpenRaw(false), []);
|
|
11906
|
+
React55.useEffect(() => {
|
|
11907
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
11908
|
+
const mq = window.matchMedia(`(max-width: ${breakpoint}px)`);
|
|
11909
|
+
const handler = (e) => {
|
|
11910
|
+
setOverlay(e.matches);
|
|
11911
|
+
setOpenRaw(!e.matches);
|
|
11912
|
+
};
|
|
11913
|
+
mq.addEventListener("change", handler);
|
|
11914
|
+
return () => mq.removeEventListener("change", handler);
|
|
11915
|
+
}, [breakpoint]);
|
|
11916
|
+
React55.useEffect(() => {
|
|
11917
|
+
if (!overlay || !open) return;
|
|
11918
|
+
const handler = (e) => {
|
|
11919
|
+
if (e.key === "Escape") close();
|
|
11920
|
+
};
|
|
11921
|
+
document.addEventListener("keydown", handler);
|
|
11922
|
+
return () => document.removeEventListener("keydown", handler);
|
|
11923
|
+
}, [overlay, open, close]);
|
|
11924
|
+
React55.useEffect(() => {
|
|
11925
|
+
if (!overlay || !open) return;
|
|
11926
|
+
const previousOverflow = document.body.style.overflow;
|
|
11927
|
+
document.body.style.overflow = "hidden";
|
|
11928
|
+
return () => {
|
|
11929
|
+
document.body.style.overflow = previousOverflow;
|
|
11930
|
+
};
|
|
11931
|
+
}, [overlay, open]);
|
|
11932
|
+
React55.useEffect(() => {
|
|
11933
|
+
if (!overlay || !open) return;
|
|
11934
|
+
const container = navRef.current;
|
|
11935
|
+
if (!container) return;
|
|
11936
|
+
const previouslyFocused = document.activeElement;
|
|
11937
|
+
const focusable = getFocusable(container);
|
|
11938
|
+
(focusable[0] ?? container).focus();
|
|
11939
|
+
const handler = (e) => {
|
|
11940
|
+
if (e.key !== "Tab") return;
|
|
11941
|
+
const items = getFocusable(container);
|
|
11942
|
+
if (items.length === 0) {
|
|
11943
|
+
e.preventDefault();
|
|
11944
|
+
return;
|
|
11945
|
+
}
|
|
11946
|
+
const first = items[0];
|
|
11947
|
+
const last = items[items.length - 1];
|
|
11948
|
+
const active = document.activeElement;
|
|
11949
|
+
const outside = !(active instanceof Node) || !container.contains(active);
|
|
11950
|
+
if (e.shiftKey) {
|
|
11951
|
+
if (outside || active === first) {
|
|
11952
|
+
e.preventDefault();
|
|
11953
|
+
last.focus();
|
|
11954
|
+
}
|
|
11955
|
+
} else if (outside || active === last) {
|
|
11956
|
+
e.preventDefault();
|
|
11957
|
+
first.focus();
|
|
11958
|
+
}
|
|
11959
|
+
};
|
|
11960
|
+
document.addEventListener("keydown", handler);
|
|
11961
|
+
return () => {
|
|
11962
|
+
document.removeEventListener("keydown", handler);
|
|
11963
|
+
previouslyFocused?.focus?.();
|
|
11964
|
+
};
|
|
11965
|
+
}, [overlay, open]);
|
|
11966
|
+
return { open, overlay, navRef, toggle, close, setOpen };
|
|
11967
|
+
}
|
|
11815
11968
|
// Annotate the CommonJS export names for ESM import in node:
|
|
11816
11969
|
0 && (module.exports = {
|
|
11817
11970
|
AccountMenu,
|
|
@@ -11956,6 +12109,7 @@ function createVersionStore(initialState, options) {
|
|
|
11956
12109
|
channelWeightOf,
|
|
11957
12110
|
computeNeedMore,
|
|
11958
12111
|
computeVirtualWindow,
|
|
12112
|
+
createLocalStorageAppearanceStore,
|
|
11959
12113
|
createVersionStore,
|
|
11960
12114
|
eqFilter,
|
|
11961
12115
|
extensionOf,
|
|
@@ -11995,6 +12149,7 @@ function createVersionStore(initialState, options) {
|
|
|
11995
12149
|
useChatEngine,
|
|
11996
12150
|
useFeatureStatus,
|
|
11997
12151
|
usePopoverPosition,
|
|
12152
|
+
useResponsiveRail,
|
|
11998
12153
|
useRuntimeMode,
|
|
11999
12154
|
useServerTable,
|
|
12000
12155
|
useSessionContext,
|