@flytedan/flytebot-design-system 0.68.0 → 0.70.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/chunk-OVTWSE43.js +21 -0
- package/dist/chunk-OVTWSE43.js.map +1 -0
- package/dist/index.cjs +1050 -958
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +68 -8
- package/dist/index.d.ts +68 -8
- package/dist/index.js +1043 -958
- package/dist/index.js.map +1 -1
- package/dist/markdown.cjs +38 -0
- package/dist/markdown.cjs.map +1 -0
- package/dist/markdown.d.cts +9 -0
- package/dist/markdown.d.ts +9 -0
- package/dist/markdown.js +7 -0
- package/dist/markdown.js.map +1 -0
- package/package.json +6 -1
- package/styles/components.css +24 -2
package/dist/index.cjs
CHANGED
|
@@ -974,6 +974,7 @@ __export(index_exports, {
|
|
|
974
974
|
FILE_VIEWER_TEXT_LIMIT: () => FILE_VIEWER_TEXT_LIMIT,
|
|
975
975
|
FactList: () => FactList,
|
|
976
976
|
FeatureGate: () => FeatureGate,
|
|
977
|
+
Fieldset: () => Fieldset,
|
|
977
978
|
FileBrowser: () => FileBrowser,
|
|
978
979
|
FileChip: () => FileChip,
|
|
979
980
|
FileGrid: () => FileGrid,
|
|
@@ -1027,6 +1028,7 @@ __export(index_exports, {
|
|
|
1027
1028
|
QuotaRow: () => QuotaRow,
|
|
1028
1029
|
ROOT_STEP: () => ROOT_STEP,
|
|
1029
1030
|
Radio: () => Radio,
|
|
1031
|
+
RadioGroup: () => RadioGroup,
|
|
1030
1032
|
RangeSlider: () => RangeSlider,
|
|
1031
1033
|
RelativeTime: () => RelativeTime,
|
|
1032
1034
|
RoadmapTimeline: () => RoadmapTimeline,
|
|
@@ -6353,6 +6355,16 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
|
|
|
6353
6355
|
|
|
6354
6356
|
// src/components/data/Markdown.tsx
|
|
6355
6357
|
var React35 = __toESM(require("react"), 1);
|
|
6358
|
+
|
|
6359
|
+
// src/components/data/markdownEscape.ts
|
|
6360
|
+
var ESCAPABLE = /\\([!-/:-@[-`{-~])/g;
|
|
6361
|
+
var STAND_IN_BASE = 57344;
|
|
6362
|
+
var STAND_IN = /[-]/g;
|
|
6363
|
+
var hideEscapes = (s) => s.replace(STAND_IN, "\uFFFD").replace(ESCAPABLE, (_, c) => String.fromCharCode(STAND_IN_BASE + c.charCodeAt(0)));
|
|
6364
|
+
var showEscapes = (s) => s.replace(STAND_IN, (c) => String.fromCharCode(c.charCodeAt(0) - STAND_IN_BASE));
|
|
6365
|
+
var showEscapesRaw = (s) => s.replace(STAND_IN, (c) => "\\" + String.fromCharCode(c.charCodeAt(0) - STAND_IN_BASE));
|
|
6366
|
+
|
|
6367
|
+
// src/components/data/Markdown.tsx
|
|
6356
6368
|
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
6357
6369
|
var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
|
|
6358
6370
|
var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
|
|
@@ -6370,7 +6382,8 @@ var INLINE = [
|
|
|
6370
6382
|
];
|
|
6371
6383
|
function inlineNodes(src, ctx, keyBase) {
|
|
6372
6384
|
const out = [];
|
|
6373
|
-
let rest = String(src == null ? "" : src), guard = 0;
|
|
6385
|
+
let rest = hideEscapes(String(src == null ? "" : src)), guard = 0;
|
|
6386
|
+
const d = showEscapes;
|
|
6374
6387
|
const key = () => keyBase + "-" + out.length;
|
|
6375
6388
|
while (rest && guard++ < 800) {
|
|
6376
6389
|
let best = null;
|
|
@@ -6381,28 +6394,28 @@ function inlineNodes(src, ctx, keyBase) {
|
|
|
6381
6394
|
}
|
|
6382
6395
|
if (!best) break;
|
|
6383
6396
|
const { kind, m } = best;
|
|
6384
|
-
if (m.index > 0) out.push(rest.slice(0, m.index));
|
|
6397
|
+
if (m.index > 0) out.push(d(rest.slice(0, m.index)));
|
|
6385
6398
|
const g = (i) => m[i];
|
|
6386
|
-
if (kind === "code") out.push(/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("code", { className: "fd-md-code", children: g(1) }, key()));
|
|
6399
|
+
if (kind === "code") out.push(/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("code", { className: "fd-md-code", children: showEscapesRaw(g(1)) }, key()));
|
|
6387
6400
|
else if (kind === "image") {
|
|
6388
|
-
const src2 = safeHref(g(2));
|
|
6389
|
-
out.push(ctx.allowImages && src2 ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("img", { className: "fd-md-img", src: src2, alt: g(1) || "", title: g(3)
|
|
6401
|
+
const src2 = safeHref(d(g(2)));
|
|
6402
|
+
out.push(ctx.allowImages && src2 ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("img", { className: "fd-md-img", src: src2, alt: d(g(1) || ""), title: g(3) ? d(g(3)) : void 0, loading: "lazy" }, key()) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-md-imgalt", children: d(g(1) || "image") }, key()));
|
|
6390
6403
|
} else if (kind === "link") {
|
|
6391
|
-
const href = safeHref(g(2));
|
|
6392
|
-
out.push(href ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("a", { href, title: g(3)
|
|
6404
|
+
const href = safeHref(d(g(2)));
|
|
6405
|
+
out.push(href ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("a", { href, title: g(3) ? d(g(3)) : void 0, target: /^https?:/i.test(href) ? "_blank" : void 0, rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: inlineNodes(g(1), ctx, key()) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { children: d(g(1)) }, key()));
|
|
6393
6406
|
} else if (kind === "cite") {
|
|
6394
|
-
out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(React35.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("sup", { className: "fd-md-cite", children: g(1) }, key()));
|
|
6407
|
+
out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(React35.Fragment, { children: ctx.renderCitation(d(g(1))) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("sup", { className: "fd-md-cite", children: d(g(1)) }, key()));
|
|
6395
6408
|
} else if (kind === "strongem") out.push(/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("strong", { children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("em", { children: inlineNodes(g(1), ctx, key()) }) }, key()));
|
|
6396
6409
|
else if (kind === "strong") out.push(/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
6397
6410
|
else if (kind === "em") out.push(/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
6398
6411
|
else if (kind === "del") out.push(/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("del", { children: inlineNodes(g(1), ctx, key()) }, key()));
|
|
6399
6412
|
else if (kind === "autolink" || kind === "bare") {
|
|
6400
|
-
const href = safeHref(g(1));
|
|
6401
|
-
out.push(href ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: g(1).replace(/^mailto:/, "") }, key()) : g(1));
|
|
6413
|
+
const href = safeHref(d(g(1)));
|
|
6414
|
+
out.push(href ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: d(g(1)).replace(/^mailto:/, "") }, key()) : d(g(1)));
|
|
6402
6415
|
}
|
|
6403
6416
|
rest = rest.slice(m.index + m[0].length);
|
|
6404
6417
|
}
|
|
6405
|
-
if (rest) out.push(rest);
|
|
6418
|
+
if (rest) out.push(d(rest));
|
|
6406
6419
|
return out;
|
|
6407
6420
|
}
|
|
6408
6421
|
var RE = {
|
|
@@ -6414,7 +6427,26 @@ var RE = {
|
|
|
6414
6427
|
task: /^\[([ xX])\]\s+(.*)$/,
|
|
6415
6428
|
tableSep: /^\s*\|?[\s:|-]*-[\s:|-]*\|?\s*$/
|
|
6416
6429
|
};
|
|
6417
|
-
var splitRow = (line) =>
|
|
6430
|
+
var splitRow = (line) => {
|
|
6431
|
+
const t = line.trim();
|
|
6432
|
+
const cells = [];
|
|
6433
|
+
let cur = "";
|
|
6434
|
+
for (let i = t.startsWith("|") ? 1 : 0; i < t.length; i++) {
|
|
6435
|
+
const c = t[i];
|
|
6436
|
+
if (c === "\\" && i + 1 < t.length) {
|
|
6437
|
+
cur += c + t[++i];
|
|
6438
|
+
continue;
|
|
6439
|
+
}
|
|
6440
|
+
if (c === "|") {
|
|
6441
|
+
cells.push(cur.trim());
|
|
6442
|
+
cur = "";
|
|
6443
|
+
continue;
|
|
6444
|
+
}
|
|
6445
|
+
cur += c;
|
|
6446
|
+
}
|
|
6447
|
+
if (cur.trim() || !t.endsWith("|")) cells.push(cur.trim());
|
|
6448
|
+
return cells;
|
|
6449
|
+
};
|
|
6418
6450
|
function parseBlocks(src) {
|
|
6419
6451
|
const lines = String(src == null ? "" : src).replace(/\r\n?/g, "\n").split("\n");
|
|
6420
6452
|
const blocks = [];
|
|
@@ -6546,6 +6578,7 @@ function renderBlocks(blocks, ctx, path) {
|
|
|
6546
6578
|
}
|
|
6547
6579
|
});
|
|
6548
6580
|
}
|
|
6581
|
+
var mdClass = (base, size, tone, className) => [base, size && `${base}--${size}`, tone === "muted" && `${base}--muted`, className].filter(Boolean).join(" ");
|
|
6549
6582
|
function Markdown({
|
|
6550
6583
|
source = "",
|
|
6551
6584
|
className = "",
|
|
@@ -6553,14 +6586,16 @@ function Markdown({
|
|
|
6553
6586
|
allowImages = true,
|
|
6554
6587
|
headingOffset = 0,
|
|
6555
6588
|
renderCitation,
|
|
6556
|
-
onLinkClick
|
|
6589
|
+
onLinkClick,
|
|
6590
|
+
size = "body",
|
|
6591
|
+
tone = "default"
|
|
6557
6592
|
}) {
|
|
6558
6593
|
const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
|
|
6559
6594
|
const blocks = React35.useMemo(() => parseBlocks(source), [source]);
|
|
6560
|
-
return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className:
|
|
6595
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: mdClass("fd-md", size, tone, className), children: renderBlocks(blocks, ctx, "b") });
|
|
6561
6596
|
}
|
|
6562
|
-
function MarkdownInline({ source = "", className = "", onLinkClick }) {
|
|
6563
|
-
return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className:
|
|
6597
|
+
function MarkdownInline({ source = "", className = "", onLinkClick, size, tone }) {
|
|
6598
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: mdClass("fd-md-inline", size, tone, className), children: inlineNodes(source, { allowImages: false, onLinkClick }, "i") });
|
|
6564
6599
|
}
|
|
6565
6600
|
function markdownToText(src) {
|
|
6566
6601
|
return String(src == null ? "" : src).replace(/```[\w+#-]*\n?([\s\S]*?)```/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").replace(/^\s{0,3}#{1,6}\s+/gm, "").replace(/\*\*\*([^*]+)\*\*\*|\*\*([^*]+)\*\*|__([^_]+)__/g, "$1$2$3").replace(/(^|\W)[*_]([^*_\n]+)[*_](\W|$)/g, "$1$2$3").replace(/~~([^~]+)~~/g, "$1").replace(/^\s*>\s?/gm, "").trim();
|
|
@@ -7829,14 +7864,17 @@ function Checkbox({ label, description, card = false, indeterminate = false, cla
|
|
|
7829
7864
|
|
|
7830
7865
|
// src/components/forms/Radio.tsx
|
|
7831
7866
|
var import_jsx_runtime70 = require("react/jsx-runtime");
|
|
7832
|
-
function Radio({ label, description, card = false, className = "", ...rest }) {
|
|
7867
|
+
function Radio({ label, description, badge, card = false, className = "", ...rest }) {
|
|
7833
7868
|
return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
7834
7869
|
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "fd-choice-input", children: [
|
|
7835
7870
|
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("input", { type: "radio", ...rest }),
|
|
7836
7871
|
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fd-choice-dot" }) })
|
|
7837
7872
|
] }),
|
|
7838
7873
|
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "fd-choice-text", children: [
|
|
7839
|
-
/* @__PURE__ */ (0, import_jsx_runtime70.
|
|
7874
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "fd-choice-title", children: [
|
|
7875
|
+
label,
|
|
7876
|
+
badge ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fd-choice-badge", children: badge }) : null
|
|
7877
|
+
] }),
|
|
7840
7878
|
description ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fd-choice-desc", children: description }) : null
|
|
7841
7879
|
] })
|
|
7842
7880
|
] });
|
|
@@ -9428,17 +9466,49 @@ function CodeEditor({
|
|
|
9428
9466
|
] });
|
|
9429
9467
|
}
|
|
9430
9468
|
|
|
9469
|
+
// src/components/forms/RadioGroup.tsx
|
|
9470
|
+
var React53 = __toESM(require("react"), 1);
|
|
9471
|
+
var import_jsx_runtime80 = require("react/jsx-runtime");
|
|
9472
|
+
function RadioGroup({ label, options, value, onChange, card = false, disabled = false, name, className = "" }) {
|
|
9473
|
+
const autoName = React53.useId();
|
|
9474
|
+
const labelId = React53.useId();
|
|
9475
|
+
return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { role: "radiogroup", "aria-labelledby": labelId, "aria-disabled": disabled || void 0, className: ["fd-radiogroup", className].filter(Boolean).join(" "), children: [
|
|
9476
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { id: labelId, className: "fd-radiogroup-label", children: label }),
|
|
9477
|
+
options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
|
|
9478
|
+
Radio,
|
|
9479
|
+
{
|
|
9480
|
+
card,
|
|
9481
|
+
name: name ?? autoName,
|
|
9482
|
+
value: o.value,
|
|
9483
|
+
label: o.label,
|
|
9484
|
+
description: o.description,
|
|
9485
|
+
badge: o.badge,
|
|
9486
|
+
checked: o.value === value,
|
|
9487
|
+
disabled: disabled || o.disabled,
|
|
9488
|
+
onChange: () => onChange(o.value)
|
|
9489
|
+
},
|
|
9490
|
+
o.value
|
|
9491
|
+
))
|
|
9492
|
+
] });
|
|
9493
|
+
}
|
|
9494
|
+
|
|
9495
|
+
// src/components/forms/Fieldset.tsx
|
|
9496
|
+
var import_jsx_runtime81 = require("react/jsx-runtime");
|
|
9497
|
+
function Fieldset({ busy = false, className = "", ...rest }) {
|
|
9498
|
+
return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("fieldset", { disabled: busy, "aria-busy": busy || void 0, className: ["fd-fieldset", className].filter(Boolean).join(" "), ...rest });
|
|
9499
|
+
}
|
|
9500
|
+
|
|
9431
9501
|
// src/components/platform/AccountMenu.tsx
|
|
9432
|
-
var
|
|
9502
|
+
var React55 = __toESM(require("react"), 1);
|
|
9433
9503
|
|
|
9434
9504
|
// src/kits/sessionContext.tsx
|
|
9435
|
-
var
|
|
9436
|
-
var SessionContext =
|
|
9505
|
+
var React54 = __toESM(require("react"), 1);
|
|
9506
|
+
var SessionContext = React54.createContext(null);
|
|
9437
9507
|
function SessionProvider({ value, children }) {
|
|
9438
|
-
return
|
|
9508
|
+
return React54.createElement(SessionContext.Provider, { value }, children);
|
|
9439
9509
|
}
|
|
9440
9510
|
function useSessionContext() {
|
|
9441
|
-
const ctx =
|
|
9511
|
+
const ctx = React54.useContext(SessionContext);
|
|
9442
9512
|
if (!ctx) {
|
|
9443
9513
|
throw new Error(
|
|
9444
9514
|
"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."
|
|
@@ -9448,11 +9518,11 @@ function useSessionContext() {
|
|
|
9448
9518
|
}
|
|
9449
9519
|
|
|
9450
9520
|
// src/components/platform/AccountMenu.tsx
|
|
9451
|
-
var
|
|
9521
|
+
var import_jsx_runtime82 = require("react/jsx-runtime");
|
|
9452
9522
|
var DEFAULT_LINKS = [];
|
|
9453
9523
|
var DEFAULT_GROUPS = [];
|
|
9454
9524
|
function Item({ item, onPick }) {
|
|
9455
|
-
return /* @__PURE__ */ (0,
|
|
9525
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
|
|
9456
9526
|
"button",
|
|
9457
9527
|
{
|
|
9458
9528
|
type: "button",
|
|
@@ -9460,9 +9530,9 @@ function Item({ item, onPick }) {
|
|
|
9460
9530
|
className: "fd-acct-item",
|
|
9461
9531
|
onClick: () => onPick(item),
|
|
9462
9532
|
children: [
|
|
9463
|
-
item.icon ? /* @__PURE__ */ (0,
|
|
9464
|
-
/* @__PURE__ */ (0,
|
|
9465
|
-
item.badge ? /* @__PURE__ */ (0,
|
|
9533
|
+
item.icon ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
|
|
9534
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { flex: 1 }, children: item.label }),
|
|
9535
|
+
item.badge ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Badge, { tone: "neutral", children: item.badge }) : null
|
|
9466
9536
|
]
|
|
9467
9537
|
}
|
|
9468
9538
|
);
|
|
@@ -9478,11 +9548,11 @@ function AccountMenu({
|
|
|
9478
9548
|
...rest
|
|
9479
9549
|
}) {
|
|
9480
9550
|
const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
|
|
9481
|
-
const [open2, setOpen] =
|
|
9482
|
-
const [switching, setSwitching] =
|
|
9483
|
-
const [signingOut, setSigningOut] =
|
|
9484
|
-
const [signOutError, setSignOutError] =
|
|
9485
|
-
const ref =
|
|
9551
|
+
const [open2, setOpen] = React55.useState(false);
|
|
9552
|
+
const [switching, setSwitching] = React55.useState(false);
|
|
9553
|
+
const [signingOut, setSigningOut] = React55.useState(false);
|
|
9554
|
+
const [signOutError, setSignOutError] = React55.useState(null);
|
|
9555
|
+
const ref = React55.useRef(null);
|
|
9486
9556
|
const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
|
|
9487
9557
|
const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || !pending && can2(l.perm)) })).filter((g) => g.links.length);
|
|
9488
9558
|
const closeMenu = () => {
|
|
@@ -9510,8 +9580,8 @@ function AccountMenu({
|
|
|
9510
9580
|
}
|
|
9511
9581
|
};
|
|
9512
9582
|
const showSwitcher = allowUserSwitch && !!demo;
|
|
9513
|
-
return /* @__PURE__ */ (0,
|
|
9514
|
-
/* @__PURE__ */ (0,
|
|
9583
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(import_jsx_runtime82.Fragment, { children: [
|
|
9584
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
|
|
9515
9585
|
"button",
|
|
9516
9586
|
{
|
|
9517
9587
|
type: "button",
|
|
@@ -9523,12 +9593,12 @@ function AccountMenu({
|
|
|
9523
9593
|
onClick: () => open2 ? closeMenu() : setOpen(true),
|
|
9524
9594
|
...rest,
|
|
9525
9595
|
children: [
|
|
9526
|
-
/* @__PURE__ */ (0,
|
|
9527
|
-
/* @__PURE__ */ (0,
|
|
9596
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Avatar, { name: user.name, size: "sm" }),
|
|
9597
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
|
|
9528
9598
|
]
|
|
9529
9599
|
}
|
|
9530
9600
|
),
|
|
9531
|
-
/* @__PURE__ */ (0,
|
|
9601
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
9532
9602
|
Popover,
|
|
9533
9603
|
{
|
|
9534
9604
|
open: open2,
|
|
@@ -9536,27 +9606,27 @@ function AccountMenu({
|
|
|
9536
9606
|
onClose: closeMenu,
|
|
9537
9607
|
placement: "bottom-end",
|
|
9538
9608
|
width: 272,
|
|
9539
|
-
children: /* @__PURE__ */ (0,
|
|
9540
|
-
/* @__PURE__ */ (0,
|
|
9541
|
-
/* @__PURE__ */ (0,
|
|
9542
|
-
/* @__PURE__ */ (0,
|
|
9543
|
-
/* @__PURE__ */ (0,
|
|
9544
|
-
/* @__PURE__ */ (0,
|
|
9609
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
|
|
9610
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
9611
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Avatar, { name: user.name }),
|
|
9612
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
|
|
9613
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
|
|
9614
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
|
|
9545
9615
|
] })
|
|
9546
9616
|
] }),
|
|
9547
|
-
showRoles && roles.length ? /* @__PURE__ */ (0,
|
|
9548
|
-
visibleLinks.length ? /* @__PURE__ */ (0,
|
|
9549
|
-
visibleGroups.map((g) => /* @__PURE__ */ (0,
|
|
9550
|
-
/* @__PURE__ */ (0,
|
|
9551
|
-
g.links.map((l) => /* @__PURE__ */ (0,
|
|
9617
|
+
showRoles && roles.length ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
|
|
9618
|
+
visibleLinks.length ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Item, { item: l, onPick: pick }, l.id)) }) : null,
|
|
9619
|
+
visibleGroups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
9620
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
|
|
9621
|
+
g.links.map((l) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Item, { item: l, onPick: pick }, l.id))
|
|
9552
9622
|
] }, g.label)),
|
|
9553
|
-
showSwitcher && demo ? /* @__PURE__ */ (0,
|
|
9554
|
-
/* @__PURE__ */ (0,
|
|
9555
|
-
/* @__PURE__ */ (0,
|
|
9556
|
-
/* @__PURE__ */ (0,
|
|
9557
|
-
/* @__PURE__ */ (0,
|
|
9623
|
+
showSwitcher && demo ? /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
9624
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
|
|
9625
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
|
|
9626
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
|
|
9627
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
|
|
9558
9628
|
] }),
|
|
9559
|
-
switching ? /* @__PURE__ */ (0,
|
|
9629
|
+
switching ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
|
|
9560
9630
|
"button",
|
|
9561
9631
|
{
|
|
9562
9632
|
type: "button",
|
|
@@ -9568,19 +9638,19 @@ function AccountMenu({
|
|
|
9568
9638
|
setSwitching(false);
|
|
9569
9639
|
},
|
|
9570
9640
|
children: [
|
|
9571
|
-
/* @__PURE__ */ (0,
|
|
9572
|
-
/* @__PURE__ */ (0,
|
|
9573
|
-
/* @__PURE__ */ (0,
|
|
9574
|
-
u.roles ? /* @__PURE__ */ (0,
|
|
9641
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Avatar, { name: u.name, size: "sm" }),
|
|
9642
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
|
|
9643
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
|
|
9644
|
+
u.roles ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
|
|
9575
9645
|
] }),
|
|
9576
|
-
u.id === user.id ? /* @__PURE__ */ (0,
|
|
9646
|
+
u.id === user.id ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
|
|
9577
9647
|
]
|
|
9578
9648
|
},
|
|
9579
9649
|
u.id
|
|
9580
9650
|
)) }) : null
|
|
9581
9651
|
] }) : null,
|
|
9582
|
-
/* @__PURE__ */ (0,
|
|
9583
|
-
/* @__PURE__ */ (0,
|
|
9652
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
9653
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
|
|
9584
9654
|
"button",
|
|
9585
9655
|
{
|
|
9586
9656
|
type: "button",
|
|
@@ -9590,14 +9660,14 @@ function AccountMenu({
|
|
|
9590
9660
|
disabled: signingOut,
|
|
9591
9661
|
onClick: signOut,
|
|
9592
9662
|
children: [
|
|
9593
|
-
signingOut ? /* @__PURE__ */ (0,
|
|
9594
|
-
/* @__PURE__ */ (0,
|
|
9663
|
+
signingOut ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Spinner, { size: "sm" }) : /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
|
|
9664
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
|
|
9595
9665
|
]
|
|
9596
9666
|
}
|
|
9597
9667
|
),
|
|
9598
|
-
signOutError ? /* @__PURE__ */ (0,
|
|
9599
|
-
/* @__PURE__ */ (0,
|
|
9600
|
-
/* @__PURE__ */ (0,
|
|
9668
|
+
signOutError ? /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
|
|
9669
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
|
|
9670
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
|
|
9601
9671
|
] }) : null
|
|
9602
9672
|
] })
|
|
9603
9673
|
] })
|
|
@@ -9607,13 +9677,13 @@ function AccountMenu({
|
|
|
9607
9677
|
}
|
|
9608
9678
|
|
|
9609
9679
|
// src/components/platform/AppSwitcher.tsx
|
|
9610
|
-
var
|
|
9611
|
-
var
|
|
9680
|
+
var React56 = __toESM(require("react"), 1);
|
|
9681
|
+
var import_jsx_runtime83 = require("react/jsx-runtime");
|
|
9612
9682
|
function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
9613
9683
|
const { apps: contextApps } = useSessionContext();
|
|
9614
9684
|
const apps = appsProp ?? contextApps ?? [];
|
|
9615
|
-
const [open2, setOpen] =
|
|
9616
|
-
const anchorRef =
|
|
9685
|
+
const [open2, setOpen] = React56.useState(false);
|
|
9686
|
+
const anchorRef = React56.useRef(null);
|
|
9617
9687
|
if (!apps.length) return null;
|
|
9618
9688
|
const items = apps.map((app) => ({
|
|
9619
9689
|
id: app.key,
|
|
@@ -9627,8 +9697,8 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
9627
9697
|
window.location.href = app.url;
|
|
9628
9698
|
}
|
|
9629
9699
|
}));
|
|
9630
|
-
return /* @__PURE__ */ (0,
|
|
9631
|
-
/* @__PURE__ */ (0,
|
|
9700
|
+
return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(React56.Fragment, { children: [
|
|
9701
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
|
|
9632
9702
|
IconButton,
|
|
9633
9703
|
{
|
|
9634
9704
|
icon: "squares-four",
|
|
@@ -9638,7 +9708,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
9638
9708
|
onClick: () => setOpen((v) => !v)
|
|
9639
9709
|
}
|
|
9640
9710
|
) }),
|
|
9641
|
-
/* @__PURE__ */ (0,
|
|
9711
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
|
|
9642
9712
|
Popover,
|
|
9643
9713
|
{
|
|
9644
9714
|
open: open2,
|
|
@@ -9649,17 +9719,17 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
9649
9719
|
label: "All flytedesk apps",
|
|
9650
9720
|
width: 240,
|
|
9651
9721
|
maxHeight: 360,
|
|
9652
|
-
children: /* @__PURE__ */ (0,
|
|
9722
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(Menu, { items, onClose: () => setOpen(false) })
|
|
9653
9723
|
}
|
|
9654
9724
|
)
|
|
9655
9725
|
] });
|
|
9656
9726
|
}
|
|
9657
9727
|
|
|
9658
9728
|
// src/components/platform/AppearanceMenu.tsx
|
|
9659
|
-
var
|
|
9729
|
+
var React59 = __toESM(require("react"), 1);
|
|
9660
9730
|
|
|
9661
9731
|
// src/kits/appearance.ts
|
|
9662
|
-
var
|
|
9732
|
+
var React57 = __toESM(require("react"), 1);
|
|
9663
9733
|
var DEFAULT_STORAGE_KEY = "fd-appearance";
|
|
9664
9734
|
var DEFAULT_PREFS = {
|
|
9665
9735
|
theme: "system",
|
|
@@ -9771,8 +9841,8 @@ function watchAppearance(store, root = document.documentElement) {
|
|
|
9771
9841
|
};
|
|
9772
9842
|
}
|
|
9773
9843
|
function useAppearancePrefs(store) {
|
|
9774
|
-
const prefs =
|
|
9775
|
-
const update =
|
|
9844
|
+
const prefs = React57.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
9845
|
+
const update = React57.useCallback(
|
|
9776
9846
|
(patch) => {
|
|
9777
9847
|
store.write({ ...store.getSnapshot(), ...patch });
|
|
9778
9848
|
},
|
|
@@ -9782,21 +9852,21 @@ function useAppearancePrefs(store) {
|
|
|
9782
9852
|
}
|
|
9783
9853
|
|
|
9784
9854
|
// src/components/platform/AppearanceProvider.tsx
|
|
9785
|
-
var
|
|
9786
|
-
var
|
|
9787
|
-
var AppearanceStoreContext =
|
|
9855
|
+
var React58 = __toESM(require("react"), 1);
|
|
9856
|
+
var import_jsx_runtime84 = require("react/jsx-runtime");
|
|
9857
|
+
var AppearanceStoreContext = React58.createContext(null);
|
|
9788
9858
|
function AppearanceProvider({ store, children }) {
|
|
9789
|
-
|
|
9790
|
-
return /* @__PURE__ */ (0,
|
|
9859
|
+
React58.useLayoutEffect(() => watchAppearance(store), [store]);
|
|
9860
|
+
return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(AppearanceStoreContext.Provider, { value: store, children });
|
|
9791
9861
|
}
|
|
9792
9862
|
function useAppearanceStore() {
|
|
9793
|
-
const store =
|
|
9863
|
+
const store = React58.useContext(AppearanceStoreContext);
|
|
9794
9864
|
if (!store) throw new Error("AppearanceMenu and useAppearanceStore must be rendered inside an <AppearanceProvider>.");
|
|
9795
9865
|
return store;
|
|
9796
9866
|
}
|
|
9797
9867
|
|
|
9798
9868
|
// src/components/platform/AppearanceMenu.tsx
|
|
9799
|
-
var
|
|
9869
|
+
var import_jsx_runtime85 = require("react/jsx-runtime");
|
|
9800
9870
|
var THEME_OPTIONS = [
|
|
9801
9871
|
{ value: "light", label: "Light" },
|
|
9802
9872
|
{ value: "dark", label: "Dark" },
|
|
@@ -9810,11 +9880,11 @@ var TEXT_SCALE_OPTIONS = [
|
|
|
9810
9880
|
];
|
|
9811
9881
|
function AppearanceMenu({ className = "" }) {
|
|
9812
9882
|
const [prefs, update] = useAppearancePrefs(useAppearanceStore());
|
|
9813
|
-
const [open2, setOpen] =
|
|
9814
|
-
const anchorRef =
|
|
9883
|
+
const [open2, setOpen] = React59.useState(false);
|
|
9884
|
+
const anchorRef = React59.useRef(null);
|
|
9815
9885
|
const patch = (p) => update(p);
|
|
9816
|
-
return /* @__PURE__ */ (0,
|
|
9817
|
-
/* @__PURE__ */ (0,
|
|
9886
|
+
return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(React59.Fragment, { children: [
|
|
9887
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
|
|
9818
9888
|
IconButton,
|
|
9819
9889
|
{
|
|
9820
9890
|
icon: "circle-half",
|
|
@@ -9822,7 +9892,7 @@ function AppearanceMenu({ className = "" }) {
|
|
|
9822
9892
|
onClick: () => setOpen((v) => !v)
|
|
9823
9893
|
}
|
|
9824
9894
|
) }),
|
|
9825
|
-
/* @__PURE__ */ (0,
|
|
9895
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
|
|
9826
9896
|
Popover,
|
|
9827
9897
|
{
|
|
9828
9898
|
open: open2,
|
|
@@ -9832,10 +9902,10 @@ function AppearanceMenu({ className = "" }) {
|
|
|
9832
9902
|
padded: true,
|
|
9833
9903
|
width: 260,
|
|
9834
9904
|
label: "Appearance settings",
|
|
9835
|
-
children: /* @__PURE__ */ (0,
|
|
9836
|
-
/* @__PURE__ */ (0,
|
|
9837
|
-
/* @__PURE__ */ (0,
|
|
9838
|
-
/* @__PURE__ */ (0,
|
|
9905
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
|
|
9906
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
9907
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-field-label", children: "Theme" }),
|
|
9908
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
|
|
9839
9909
|
SegmentedControl,
|
|
9840
9910
|
{
|
|
9841
9911
|
options: THEME_OPTIONS,
|
|
@@ -9845,9 +9915,9 @@ function AppearanceMenu({ className = "" }) {
|
|
|
9845
9915
|
}
|
|
9846
9916
|
)
|
|
9847
9917
|
] }),
|
|
9848
|
-
/* @__PURE__ */ (0,
|
|
9849
|
-
/* @__PURE__ */ (0,
|
|
9850
|
-
/* @__PURE__ */ (0,
|
|
9918
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
9919
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-field-label", children: "Text size" }),
|
|
9920
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
|
|
9851
9921
|
SegmentedControl,
|
|
9852
9922
|
{
|
|
9853
9923
|
options: TEXT_SCALE_OPTIONS,
|
|
@@ -9857,7 +9927,7 @@ function AppearanceMenu({ className = "" }) {
|
|
|
9857
9927
|
}
|
|
9858
9928
|
)
|
|
9859
9929
|
] }),
|
|
9860
|
-
/* @__PURE__ */ (0,
|
|
9930
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
|
|
9861
9931
|
Switch,
|
|
9862
9932
|
{
|
|
9863
9933
|
label: "High contrast",
|
|
@@ -9866,7 +9936,7 @@ function AppearanceMenu({ className = "" }) {
|
|
|
9866
9936
|
onChange: (e) => patch({ highContrast: e.target.checked })
|
|
9867
9937
|
}
|
|
9868
9938
|
),
|
|
9869
|
-
/* @__PURE__ */ (0,
|
|
9939
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
|
|
9870
9940
|
Switch,
|
|
9871
9941
|
{
|
|
9872
9942
|
label: "Reduce motion",
|
|
@@ -9882,14 +9952,14 @@ function AppearanceMenu({ className = "" }) {
|
|
|
9882
9952
|
}
|
|
9883
9953
|
|
|
9884
9954
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
9885
|
-
var
|
|
9886
|
-
var
|
|
9955
|
+
var React60 = __toESM(require("react"), 1);
|
|
9956
|
+
var import_jsx_runtime86 = require("react/jsx-runtime");
|
|
9887
9957
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
9888
9958
|
function Json({ obj }) {
|
|
9889
|
-
return /* @__PURE__ */ (0,
|
|
9959
|
+
return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
9890
9960
|
}
|
|
9891
9961
|
function Endpoint({ s, onRequest }) {
|
|
9892
|
-
const [tried, setTried] =
|
|
9962
|
+
const [tried, setTried] = React60.useState(null);
|
|
9893
9963
|
const run = async () => {
|
|
9894
9964
|
setTried("busy");
|
|
9895
9965
|
const t0 = (window.performance || Date).now();
|
|
@@ -9900,50 +9970,50 @@ function Endpoint({ s, onRequest }) {
|
|
|
9900
9970
|
setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
|
|
9901
9971
|
}
|
|
9902
9972
|
};
|
|
9903
|
-
return /* @__PURE__ */ (0,
|
|
9904
|
-
/* @__PURE__ */ (0,
|
|
9905
|
-
/* @__PURE__ */ (0,
|
|
9906
|
-
/* @__PURE__ */ (0,
|
|
9907
|
-
s.isList ? /* @__PURE__ */ (0,
|
|
9908
|
-
/* @__PURE__ */ (0,
|
|
9909
|
-
/* @__PURE__ */ (0,
|
|
9973
|
+
return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
9974
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
|
|
9975
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
|
|
9976
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
|
|
9977
|
+
s.isList ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
|
|
9978
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { style: { flex: 1 } }),
|
|
9979
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
9910
9980
|
s.latency[0],
|
|
9911
9981
|
"\u2013",
|
|
9912
9982
|
s.latency[1],
|
|
9913
9983
|
"ms"
|
|
9914
9984
|
] }),
|
|
9915
|
-
/* @__PURE__ */ (0,
|
|
9985
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
|
|
9916
9986
|
] }),
|
|
9917
|
-
/* @__PURE__ */ (0,
|
|
9918
|
-
/* @__PURE__ */ (0,
|
|
9919
|
-
/* @__PURE__ */ (0,
|
|
9920
|
-
/* @__PURE__ */ (0,
|
|
9921
|
-
s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0,
|
|
9987
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
|
|
9988
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
9989
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
|
|
9990
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
|
|
9991
|
+
s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Tag, { children: u }, u)) }) : null
|
|
9922
9992
|
] }),
|
|
9923
|
-
/* @__PURE__ */ (0,
|
|
9924
|
-
s.request ? /* @__PURE__ */ (0,
|
|
9925
|
-
/* @__PURE__ */ (0,
|
|
9926
|
-
/* @__PURE__ */ (0,
|
|
9993
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
|
|
9994
|
+
s.request ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
9995
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-overline fd-muted", children: "Request body" }),
|
|
9996
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Json, { obj: s.request })
|
|
9927
9997
|
] }) : null,
|
|
9928
|
-
s.query ? /* @__PURE__ */ (0,
|
|
9929
|
-
/* @__PURE__ */ (0,
|
|
9930
|
-
/* @__PURE__ */ (0,
|
|
9998
|
+
s.query ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
9999
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-overline fd-muted", children: "Query" }),
|
|
10000
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Json, { obj: s.query })
|
|
9931
10001
|
] }) : null,
|
|
9932
|
-
/* @__PURE__ */ (0,
|
|
9933
|
-
/* @__PURE__ */ (0,
|
|
9934
|
-
/* @__PURE__ */ (0,
|
|
10002
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
10003
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-overline fd-muted", children: "Response 200" }),
|
|
10004
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Json, { obj: s.response })
|
|
9935
10005
|
] })
|
|
9936
10006
|
] }),
|
|
9937
|
-
s.notes ? /* @__PURE__ */ (0,
|
|
9938
|
-
tried && tried !== "busy" ? /* @__PURE__ */ (0,
|
|
9939
|
-
/* @__PURE__ */ (0,
|
|
9940
|
-
/* @__PURE__ */ (0,
|
|
9941
|
-
/* @__PURE__ */ (0,
|
|
10007
|
+
s.notes ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
|
|
10008
|
+
tried && tried !== "busy" ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
10009
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
10010
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
|
|
10011
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
|
|
9942
10012
|
tried.ms,
|
|
9943
10013
|
"ms"
|
|
9944
10014
|
] })
|
|
9945
10015
|
] }),
|
|
9946
|
-
/* @__PURE__ */ (0,
|
|
10016
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
|
|
9947
10017
|
] }) : null
|
|
9948
10018
|
] })
|
|
9949
10019
|
] }) });
|
|
@@ -9962,58 +10032,58 @@ function ApiSpecBrowser({
|
|
|
9962
10032
|
className = "",
|
|
9963
10033
|
...rest
|
|
9964
10034
|
}) {
|
|
9965
|
-
const [q, setQ] =
|
|
9966
|
-
const [method, setMethod] =
|
|
9967
|
-
const [mod, setMod] =
|
|
9968
|
-
const [listOnly, setListOnly] =
|
|
10035
|
+
const [q, setQ] = React60.useState("");
|
|
10036
|
+
const [method, setMethod] = React60.useState(null);
|
|
10037
|
+
const [mod, setMod] = React60.useState(null);
|
|
10038
|
+
const [listOnly, setListOnly] = React60.useState(false);
|
|
9969
10039
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
9970
10040
|
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())));
|
|
9971
10041
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
9972
10042
|
const methods = [...new Set(spec.map((s) => s.method))];
|
|
9973
10043
|
const listCount = spec.filter((s) => s.isList).length;
|
|
9974
|
-
return /* @__PURE__ */ (0,
|
|
9975
|
-
/* @__PURE__ */ (0,
|
|
9976
|
-
kicker ? /* @__PURE__ */ (0,
|
|
9977
|
-
/* @__PURE__ */ (0,
|
|
9978
|
-
lede ? /* @__PURE__ */ (0,
|
|
10044
|
+
return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
|
|
10045
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
10046
|
+
kicker ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-overline fd-muted", children: kicker }) : null,
|
|
10047
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
10048
|
+
lede ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
|
|
9979
10049
|
] }),
|
|
9980
|
-
modules && modules.length ? /* @__PURE__ */ (0,
|
|
9981
|
-
/* @__PURE__ */ (0,
|
|
9982
|
-
/* @__PURE__ */ (0,
|
|
9983
|
-
/* @__PURE__ */ (0,
|
|
10050
|
+
modules && modules.length ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
10051
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
|
|
10052
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
10053
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
|
|
9984
10054
|
"All screens ",
|
|
9985
|
-
/* @__PURE__ */ (0,
|
|
10055
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-mono", children: spec.length })
|
|
9986
10056
|
] }),
|
|
9987
|
-
modules.map((m) => /* @__PURE__ */ (0,
|
|
10057
|
+
modules.map((m) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
|
|
9988
10058
|
m.label,
|
|
9989
10059
|
" ",
|
|
9990
|
-
/* @__PURE__ */ (0,
|
|
10060
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
|
|
9991
10061
|
] }, m.id))
|
|
9992
10062
|
] }),
|
|
9993
|
-
activeModule ? /* @__PURE__ */ (0,
|
|
10063
|
+
activeModule ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
|
|
9994
10064
|
Flag,
|
|
9995
10065
|
{
|
|
9996
10066
|
tone: "info",
|
|
9997
10067
|
statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
|
|
9998
10068
|
cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
|
|
9999
|
-
actions: /* @__PURE__ */ (0,
|
|
10069
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
|
|
10000
10070
|
}
|
|
10001
10071
|
) : null
|
|
10002
10072
|
] }) : null,
|
|
10003
|
-
sourceNote ? /* @__PURE__ */ (0,
|
|
10004
|
-
/* @__PURE__ */ (0,
|
|
10005
|
-
/* @__PURE__ */ (0,
|
|
10006
|
-
methods.map((m) => /* @__PURE__ */ (0,
|
|
10073
|
+
sourceNote ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
|
|
10074
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
10075
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
|
|
10076
|
+
methods.map((m) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
|
|
10007
10077
|
m,
|
|
10008
10078
|
" ",
|
|
10009
|
-
/* @__PURE__ */ (0,
|
|
10079
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
|
|
10010
10080
|
] }, m)),
|
|
10011
|
-
listCount ? /* @__PURE__ */ (0,
|
|
10081
|
+
listCount ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
|
|
10012
10082
|
"Paged lists ",
|
|
10013
|
-
/* @__PURE__ */ (0,
|
|
10083
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-mono", children: listCount })
|
|
10014
10084
|
] }) : null,
|
|
10015
|
-
/* @__PURE__ */ (0,
|
|
10016
|
-
/* @__PURE__ */ (0,
|
|
10085
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { style: { flex: 1 } }),
|
|
10086
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
10017
10087
|
hits.length,
|
|
10018
10088
|
" of ",
|
|
10019
10089
|
spec.length,
|
|
@@ -10021,31 +10091,31 @@ function ApiSpecBrowser({
|
|
|
10021
10091
|
listCount ? " \xB7 " + listCount + " paged" : ""
|
|
10022
10092
|
] })
|
|
10023
10093
|
] }),
|
|
10024
|
-
hits.length === 0 ? /* @__PURE__ */ (0,
|
|
10094
|
+
hits.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
|
|
10025
10095
|
const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
|
|
10026
10096
|
if (!items.length) return null;
|
|
10027
|
-
return /* @__PURE__ */ (0,
|
|
10028
|
-
/* @__PURE__ */ (0,
|
|
10029
|
-
items.map((s) => /* @__PURE__ */ (0,
|
|
10097
|
+
return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 12 }, children: [
|
|
10098
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-label-lg", children: g }),
|
|
10099
|
+
items.map((s) => /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Endpoint, { s, onRequest }, s.id))
|
|
10030
10100
|
] }, g);
|
|
10031
10101
|
}),
|
|
10032
|
-
conventions && conventions.length ? /* @__PURE__ */ (0,
|
|
10033
|
-
/* @__PURE__ */ (0,
|
|
10034
|
-
/* @__PURE__ */ (0,
|
|
10102
|
+
conventions && conventions.length ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
|
|
10103
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
|
|
10104
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
|
|
10035
10105
|
] }, k)) }) }) : null,
|
|
10036
|
-
openQuestions && openQuestions.length ? /* @__PURE__ */ (0,
|
|
10037
|
-
/* @__PURE__ */ (0,
|
|
10038
|
-
/* @__PURE__ */ (0,
|
|
10039
|
-
/* @__PURE__ */ (0,
|
|
10040
|
-
/* @__PURE__ */ (0,
|
|
10106
|
+
openQuestions && openQuestions.length ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
|
|
10107
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Badge, { tone: "danger", children: id }),
|
|
10108
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
|
|
10109
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
|
|
10110
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-body-sm fd-muted", children: why })
|
|
10041
10111
|
] })
|
|
10042
10112
|
] }, id)) }) }) : null
|
|
10043
10113
|
] });
|
|
10044
10114
|
}
|
|
10045
10115
|
|
|
10046
10116
|
// src/components/platform/ProfilePage.tsx
|
|
10047
|
-
var
|
|
10048
|
-
var
|
|
10117
|
+
var React61 = __toESM(require("react"), 1);
|
|
10118
|
+
var import_jsx_runtime87 = require("react/jsx-runtime");
|
|
10049
10119
|
function fieldInitialValue(field, user) {
|
|
10050
10120
|
if (field.value) return field.value(user);
|
|
10051
10121
|
const raw = user[field.key];
|
|
@@ -10080,21 +10150,21 @@ function ProfilePage({
|
|
|
10080
10150
|
}) {
|
|
10081
10151
|
const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
|
|
10082
10152
|
const user = userProp || sessionUser;
|
|
10083
|
-
const initialFieldValues =
|
|
10153
|
+
const initialFieldValues = React61.useMemo(() => {
|
|
10084
10154
|
const values2 = {};
|
|
10085
10155
|
for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
|
|
10086
10156
|
return values2;
|
|
10087
10157
|
}, [user.id, fields]);
|
|
10088
|
-
const initialNotify =
|
|
10158
|
+
const initialNotify = React61.useMemo(() => {
|
|
10089
10159
|
const values2 = {};
|
|
10090
10160
|
for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
|
|
10091
10161
|
return values2;
|
|
10092
10162
|
}, [user.id, notifications]);
|
|
10093
|
-
const [values, setValues] =
|
|
10094
|
-
const [notify, setNotify] =
|
|
10095
|
-
const [saving, setSaving] =
|
|
10096
|
-
const [saved, setSaved] =
|
|
10097
|
-
const [prevUserId, setPrevUserId] =
|
|
10163
|
+
const [values, setValues] = React61.useState(initialFieldValues);
|
|
10164
|
+
const [notify, setNotify] = React61.useState(initialNotify);
|
|
10165
|
+
const [saving, setSaving] = React61.useState(false);
|
|
10166
|
+
const [saved, setSaved] = React61.useState(false);
|
|
10167
|
+
const [prevUserId, setPrevUserId] = React61.useState(user.id);
|
|
10098
10168
|
if (user.id !== prevUserId) {
|
|
10099
10169
|
setPrevUserId(user.id);
|
|
10100
10170
|
setValues(initialFieldValues);
|
|
@@ -10131,37 +10201,37 @@ function ProfilePage({
|
|
|
10131
10201
|
};
|
|
10132
10202
|
const displayName = fields.some((f) => f.key === "name") ? values.name || user.name : user.name;
|
|
10133
10203
|
const fieldGroups = groupFields(fields);
|
|
10134
|
-
return /* @__PURE__ */ (0,
|
|
10135
|
-
/* @__PURE__ */ (0,
|
|
10136
|
-
/* @__PURE__ */ (0,
|
|
10137
|
-
/* @__PURE__ */ (0,
|
|
10138
|
-
/* @__PURE__ */ (0,
|
|
10204
|
+
return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
|
|
10205
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
10206
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
|
|
10207
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
|
|
10208
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.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." })
|
|
10139
10209
|
] }),
|
|
10140
|
-
/* @__PURE__ */ (0,
|
|
10141
|
-
/* @__PURE__ */ (0,
|
|
10142
|
-
/* @__PURE__ */ (0,
|
|
10143
|
-
/* @__PURE__ */ (0,
|
|
10144
|
-
/* @__PURE__ */ (0,
|
|
10145
|
-
roles.map((r) => /* @__PURE__ */ (0,
|
|
10146
|
-
user.sso ? /* @__PURE__ */ (0,
|
|
10210
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
|
|
10211
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Avatar, { name: displayName, size: "lg" }),
|
|
10212
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
|
|
10213
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
|
|
10214
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
|
|
10215
|
+
roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
|
|
10216
|
+
user.sso ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
|
|
10147
10217
|
] })
|
|
10148
10218
|
] }),
|
|
10149
|
-
onChangePhoto ? /* @__PURE__ */ (0,
|
|
10219
|
+
onChangePhoto ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
|
|
10150
10220
|
] }) }),
|
|
10151
|
-
fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ (0,
|
|
10221
|
+
fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
|
|
10152
10222
|
Card,
|
|
10153
10223
|
{
|
|
10154
|
-
title: description ? /* @__PURE__ */ (0,
|
|
10155
|
-
/* @__PURE__ */ (0,
|
|
10156
|
-
/* @__PURE__ */ (0,
|
|
10224
|
+
title: description ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
10225
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { children: group }),
|
|
10226
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
|
|
10157
10227
|
] }) : group,
|
|
10158
10228
|
elevation: "flat",
|
|
10159
|
-
children: /* @__PURE__ */ (0,
|
|
10160
|
-
/* @__PURE__ */ (0,
|
|
10229
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
|
|
10230
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
|
|
10161
10231
|
const help = typeof field.help === "function" ? field.help(user) : field.help;
|
|
10162
10232
|
const readOnly = field.readOnly || field.type === "readonly";
|
|
10163
10233
|
if (field.type === "select") {
|
|
10164
|
-
return /* @__PURE__ */ (0,
|
|
10234
|
+
return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
|
|
10165
10235
|
Select,
|
|
10166
10236
|
{
|
|
10167
10237
|
label: field.label,
|
|
@@ -10175,7 +10245,7 @@ function ProfilePage({
|
|
|
10175
10245
|
field.key
|
|
10176
10246
|
);
|
|
10177
10247
|
}
|
|
10178
|
-
return /* @__PURE__ */ (0,
|
|
10248
|
+
return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
|
|
10179
10249
|
Input,
|
|
10180
10250
|
{
|
|
10181
10251
|
label: field.label,
|
|
@@ -10191,7 +10261,7 @@ function ProfilePage({
|
|
|
10191
10261
|
}) }),
|
|
10192
10262
|
groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
|
|
10193
10263
|
const help = typeof field.help === "function" ? field.help(user) : field.help;
|
|
10194
|
-
return /* @__PURE__ */ (0,
|
|
10264
|
+
return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
|
|
10195
10265
|
Textarea,
|
|
10196
10266
|
{
|
|
10197
10267
|
label: field.label,
|
|
@@ -10211,16 +10281,16 @@ function ProfilePage({
|
|
|
10211
10281
|
group
|
|
10212
10282
|
)),
|
|
10213
10283
|
extra,
|
|
10214
|
-
notifications.length > 0 ? /* @__PURE__ */ (0,
|
|
10215
|
-
/* @__PURE__ */ (0,
|
|
10284
|
+
notifications.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
|
|
10285
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(
|
|
10216
10286
|
Card,
|
|
10217
10287
|
{
|
|
10218
|
-
title: /* @__PURE__ */ (0,
|
|
10219
|
-
/* @__PURE__ */ (0,
|
|
10220
|
-
/* @__PURE__ */ (0,
|
|
10288
|
+
title: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
10289
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { children: "Access" }),
|
|
10290
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
|
|
10221
10291
|
] }),
|
|
10222
10292
|
elevation: "flat",
|
|
10223
|
-
action: /* @__PURE__ */ (0,
|
|
10293
|
+
action: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
|
|
10224
10294
|
Button,
|
|
10225
10295
|
{
|
|
10226
10296
|
size: "sm",
|
|
@@ -10231,39 +10301,39 @@ function ProfilePage({
|
|
|
10231
10301
|
}
|
|
10232
10302
|
),
|
|
10233
10303
|
children: [
|
|
10234
|
-
/* @__PURE__ */ (0,
|
|
10235
|
-
/* @__PURE__ */ (0,
|
|
10236
|
-
/* @__PURE__ */ (0,
|
|
10304
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
10305
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
|
|
10306
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(CardRow, { label: "Permissions", children: [
|
|
10237
10307
|
permissions.length,
|
|
10238
10308
|
" granted"
|
|
10239
10309
|
] }),
|
|
10240
|
-
/* @__PURE__ */ (0,
|
|
10310
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
|
|
10241
10311
|
] }),
|
|
10242
|
-
/* @__PURE__ */ (0,
|
|
10312
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
|
|
10243
10313
|
]
|
|
10244
10314
|
}
|
|
10245
10315
|
),
|
|
10246
|
-
sessions ? /* @__PURE__ */ (0,
|
|
10316
|
+
sessions ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
|
|
10247
10317
|
Card,
|
|
10248
10318
|
{
|
|
10249
10319
|
title: "Signed-in devices",
|
|
10250
10320
|
elevation: "flat",
|
|
10251
|
-
action: /* @__PURE__ */ (0,
|
|
10252
|
-
children: /* @__PURE__ */ (0,
|
|
10253
|
-
/* @__PURE__ */ (0,
|
|
10254
|
-
/* @__PURE__ */ (0,
|
|
10255
|
-
/* @__PURE__ */ (0,
|
|
10256
|
-
/* @__PURE__ */ (0,
|
|
10321
|
+
action: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
|
|
10322
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
|
|
10323
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
10324
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
|
|
10325
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
|
|
10326
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
10257
10327
|
s.where,
|
|
10258
10328
|
" \xB7 ",
|
|
10259
10329
|
s.when
|
|
10260
10330
|
] })
|
|
10261
10331
|
] }),
|
|
10262
|
-
s.current ? /* @__PURE__ */ (0,
|
|
10332
|
+
s.current ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Button, { size: "sm", variant: "ghost", children: "Revoke" })
|
|
10263
10333
|
] }, s.id)) })
|
|
10264
10334
|
}
|
|
10265
10335
|
) : null,
|
|
10266
|
-
/* @__PURE__ */ (0,
|
|
10336
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: {
|
|
10267
10337
|
gap: 10,
|
|
10268
10338
|
flexWrap: "wrap",
|
|
10269
10339
|
position: "sticky",
|
|
@@ -10274,16 +10344,16 @@ function ProfilePage({
|
|
|
10274
10344
|
border: "1px solid var(--border)",
|
|
10275
10345
|
boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
|
|
10276
10346
|
}, children: [
|
|
10277
|
-
/* @__PURE__ */ (0,
|
|
10278
|
-
/* @__PURE__ */ (0,
|
|
10279
|
-
/* @__PURE__ */ (0,
|
|
10347
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
|
|
10348
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
|
|
10349
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
|
|
10280
10350
|
] })
|
|
10281
10351
|
] });
|
|
10282
10352
|
}
|
|
10283
10353
|
|
|
10284
10354
|
// src/components/platform/SessionScreen.tsx
|
|
10285
|
-
var
|
|
10286
|
-
var
|
|
10355
|
+
var React62 = __toESM(require("react"), 1);
|
|
10356
|
+
var import_jsx_runtime88 = require("react/jsx-runtime");
|
|
10287
10357
|
var COPY = {
|
|
10288
10358
|
"signing-in": { busy: "Signing you in\u2026" },
|
|
10289
10359
|
"session-expired": { busy: "Your session expired \u2014 signing you back in\u2026" },
|
|
@@ -10296,28 +10366,28 @@ function SessionScreen({ kind, error, onRetry, productName }) {
|
|
|
10296
10366
|
const copy = COPY[kind];
|
|
10297
10367
|
const busyMessage = "busy" in copy ? copy.busy : null;
|
|
10298
10368
|
const failureTitle = "failure" in copy ? copy.failure : null;
|
|
10299
|
-
const [announced, setAnnounced] =
|
|
10300
|
-
|
|
10369
|
+
const [announced, setAnnounced] = React62.useState("");
|
|
10370
|
+
React62.useEffect(() => {
|
|
10301
10371
|
setAnnounced(busyMessage ?? "");
|
|
10302
10372
|
}, [busyMessage]);
|
|
10303
|
-
const titleRef =
|
|
10373
|
+
const titleRef = React62.useRef(null);
|
|
10304
10374
|
const failed = failureTitle !== null;
|
|
10305
|
-
|
|
10375
|
+
React62.useEffect(() => {
|
|
10306
10376
|
titleRef.current?.focus({ preventScroll: true });
|
|
10307
10377
|
}, [failed]);
|
|
10308
|
-
return /* @__PURE__ */ (0,
|
|
10309
|
-
/* @__PURE__ */ (0,
|
|
10310
|
-
/* @__PURE__ */ (0,
|
|
10311
|
-
/* @__PURE__ */ (0,
|
|
10312
|
-
/* @__PURE__ */ (0,
|
|
10313
|
-
/* @__PURE__ */ (0,
|
|
10314
|
-
/* @__PURE__ */ (0,
|
|
10315
|
-
/* @__PURE__ */ (0,
|
|
10316
|
-
/* @__PURE__ */ (0,
|
|
10378
|
+
return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("main", { className: "fd-session-screen", children: /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-session-screen-inner", children: [
|
|
10379
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { className: "fd-session-screen-mark", "data-theme": "dark", children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(FlytedeskMark, { size: "lg" }) }),
|
|
10380
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-session-screen-frame", children: [
|
|
10381
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { className: "fd-session-screen-stripe" }),
|
|
10382
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-session-screen-body", children: [
|
|
10383
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)("h1", { ref: titleRef, tabIndex: -1, className: "fd-h3 fd-session-screen-title", children: productName }),
|
|
10384
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { role: "status", "aria-live": "polite", className: "fd-session-screen-status", children: busyMessage !== null ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(import_jsx_runtime88.Fragment, { children: [
|
|
10385
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-spinner fd-spinner-lg fd-session-screen-spinner", "aria-hidden": "true" }),
|
|
10386
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)("p", { className: "fd-body fd-session-screen-message", children: announced })
|
|
10317
10387
|
] }) : null }),
|
|
10318
|
-
failureTitle !== null ? /* @__PURE__ */ (0,
|
|
10319
|
-
/* @__PURE__ */ (0,
|
|
10320
|
-
onRetry !== null ? /* @__PURE__ */ (0,
|
|
10388
|
+
failureTitle !== null ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-session-screen-failure", children: [
|
|
10389
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)(Banner, { tone: "danger", title: failureTitle, detail: error ?? void 0 }),
|
|
10390
|
+
onRetry !== null ? /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(Button, { variant: "primary", block: true, onClick: onRetry, children: "Try again" }) : null
|
|
10321
10391
|
] }) : null
|
|
10322
10392
|
] }) })
|
|
10323
10393
|
] })
|
|
@@ -10325,10 +10395,10 @@ function SessionScreen({ kind, error, onRetry, productName }) {
|
|
|
10325
10395
|
}
|
|
10326
10396
|
|
|
10327
10397
|
// src/components/platform/RoadmapTimeline.tsx
|
|
10328
|
-
var
|
|
10398
|
+
var React65 = __toESM(require("react"), 1);
|
|
10329
10399
|
|
|
10330
10400
|
// src/kits/session.ts
|
|
10331
|
-
var
|
|
10401
|
+
var React63 = __toESM(require("react"), 1);
|
|
10332
10402
|
var PERMISSION_CATALOG = [
|
|
10333
10403
|
{ group: "Plans", items: [
|
|
10334
10404
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -11895,8 +11965,8 @@ function roadmap(overrides) {
|
|
|
11895
11965
|
};
|
|
11896
11966
|
}
|
|
11897
11967
|
function useSession() {
|
|
11898
|
-
const [s, setS] =
|
|
11899
|
-
|
|
11968
|
+
const [s, setS] = React63.useState(getSession);
|
|
11969
|
+
React63.useEffect(() => subscribe(setS), []);
|
|
11900
11970
|
return s;
|
|
11901
11971
|
}
|
|
11902
11972
|
var SessionKit = {
|
|
@@ -11929,7 +11999,7 @@ var SessionKit = {
|
|
|
11929
11999
|
};
|
|
11930
12000
|
function DemoSessionProvider({ children }) {
|
|
11931
12001
|
const session = useSession();
|
|
11932
|
-
const value =
|
|
12002
|
+
const value = React63.useMemo(
|
|
11933
12003
|
() => ({
|
|
11934
12004
|
user: session.user,
|
|
11935
12005
|
roles: session.roles,
|
|
@@ -11945,11 +12015,11 @@ function DemoSessionProvider({ children }) {
|
|
|
11945
12015
|
}),
|
|
11946
12016
|
[session]
|
|
11947
12017
|
);
|
|
11948
|
-
return
|
|
12018
|
+
return React63.createElement(SessionProvider, { value }, children);
|
|
11949
12019
|
}
|
|
11950
12020
|
|
|
11951
12021
|
// src/kits/runtime.ts
|
|
11952
|
-
var
|
|
12022
|
+
var React64 = __toESM(require("react"), 1);
|
|
11953
12023
|
var WIRED_ENDPOINTS = [
|
|
11954
12024
|
// Nothing yet. Every id below would come from a real service:
|
|
11955
12025
|
// "plan.get", "placements.list", …
|
|
@@ -12120,8 +12190,8 @@ var RuntimeKit = {
|
|
|
12120
12190
|
};
|
|
12121
12191
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
12122
12192
|
function useRuntimeMode() {
|
|
12123
|
-
const [m, setM] =
|
|
12124
|
-
|
|
12193
|
+
const [m, setM] = React64.useState(RuntimeKit.getMode());
|
|
12194
|
+
React64.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
12125
12195
|
return m;
|
|
12126
12196
|
}
|
|
12127
12197
|
function useFeatureStatus(key) {
|
|
@@ -12140,7 +12210,7 @@ var UseRuntimeMode = useRuntimeMode;
|
|
|
12140
12210
|
var UseFeatureStatus = useFeatureStatus;
|
|
12141
12211
|
|
|
12142
12212
|
// src/components/platform/RoadmapTimeline.tsx
|
|
12143
|
-
var
|
|
12213
|
+
var import_jsx_runtime89 = require("react/jsx-runtime");
|
|
12144
12214
|
var STATUS = {
|
|
12145
12215
|
shipped: { tone: "success", icon: "check-circle", label: "Wired" },
|
|
12146
12216
|
next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
|
|
@@ -12155,45 +12225,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
12155
12225
|
const s = STATUS[item.status] || STATUS.planned;
|
|
12156
12226
|
const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
|
|
12157
12227
|
const blocking = deps.filter((d) => !d.implemented);
|
|
12158
|
-
return /* @__PURE__ */ (0,
|
|
12159
|
-
/* @__PURE__ */ (0,
|
|
12160
|
-
/* @__PURE__ */ (0,
|
|
12161
|
-
/* @__PURE__ */ (0,
|
|
12162
|
-
/* @__PURE__ */ (0,
|
|
12228
|
+
return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
12229
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
12230
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
|
|
12231
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
|
|
12232
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(Badge, { tone: s.tone, icon: s.icon, children: s.label })
|
|
12163
12233
|
] }),
|
|
12164
|
-
/* @__PURE__ */ (0,
|
|
12165
|
-
item.backend ? /* @__PURE__ */ (0,
|
|
12166
|
-
/* @__PURE__ */ (0,
|
|
12167
|
-
/* @__PURE__ */ (0,
|
|
12234
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
|
|
12235
|
+
item.backend ? /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
|
|
12236
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
|
|
12237
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
|
|
12168
12238
|
] }) : null,
|
|
12169
|
-
/* @__PURE__ */ (0,
|
|
12170
|
-
item.effort ? /* @__PURE__ */ (0,
|
|
12171
|
-
/* @__PURE__ */ (0,
|
|
12239
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
12240
|
+
item.effort ? /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
12241
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("i", { className: "ph ph-hourglass-medium" }),
|
|
12172
12242
|
" ",
|
|
12173
12243
|
item.effort
|
|
12174
12244
|
] }) : null,
|
|
12175
|
-
/* @__PURE__ */ (0,
|
|
12176
|
-
/* @__PURE__ */ (0,
|
|
12245
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
12246
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("i", { className: "ph ph-user" }),
|
|
12177
12247
|
" ",
|
|
12178
12248
|
item.owner
|
|
12179
12249
|
] }),
|
|
12180
|
-
item.screen ? /* @__PURE__ */ (0,
|
|
12181
|
-
/* @__PURE__ */ (0,
|
|
12182
|
-
/* @__PURE__ */ (0,
|
|
12250
|
+
item.screen ? /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
|
|
12251
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { style: { flex: 1 } }),
|
|
12252
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
|
|
12183
12253
|
"button",
|
|
12184
12254
|
{
|
|
12185
12255
|
type: "button",
|
|
12186
12256
|
onClick: () => onOpenFlag && onOpenFlag(item.key),
|
|
12187
12257
|
style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
|
|
12188
|
-
children: /* @__PURE__ */ (0,
|
|
12258
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
|
|
12189
12259
|
}
|
|
12190
12260
|
)
|
|
12191
12261
|
] }),
|
|
12192
|
-
deps.length ? /* @__PURE__ */ (0,
|
|
12193
|
-
/* @__PURE__ */ (0,
|
|
12194
|
-
deps.map((d) => /* @__PURE__ */ (0,
|
|
12262
|
+
deps.length ? /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
|
|
12263
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
|
|
12264
|
+
deps.map((d) => /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
|
|
12195
12265
|
] }) : null,
|
|
12196
|
-
blocking.length && !item.implemented ? /* @__PURE__ */ (0,
|
|
12266
|
+
blocking.length && !item.implemented ? /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
|
|
12197
12267
|
"Blocked until ",
|
|
12198
12268
|
blocking.map((d) => d.label).join(" and "),
|
|
12199
12269
|
" ",
|
|
@@ -12204,12 +12274,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
12204
12274
|
}
|
|
12205
12275
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
12206
12276
|
const session = SessionKit.useSession();
|
|
12207
|
-
const [project, setProject] =
|
|
12208
|
-
const [q, setQ] =
|
|
12209
|
-
const scrollRef =
|
|
12210
|
-
const nowRef =
|
|
12211
|
-
const rm =
|
|
12212
|
-
const byKey =
|
|
12277
|
+
const [project, setProject] = React65.useState("");
|
|
12278
|
+
const [q, setQ] = React65.useState("");
|
|
12279
|
+
const scrollRef = React65.useRef(null);
|
|
12280
|
+
const nowRef = React65.useRef(null);
|
|
12281
|
+
const rm = React65.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
12282
|
+
const byKey = React65.useMemo(() => {
|
|
12213
12283
|
const m = {};
|
|
12214
12284
|
rm.items.forEach((i) => {
|
|
12215
12285
|
m[i.key] = i;
|
|
@@ -12218,7 +12288,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
12218
12288
|
}, [rm]);
|
|
12219
12289
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
12220
12290
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
12221
|
-
|
|
12291
|
+
React65.useEffect(() => {
|
|
12222
12292
|
let raf1 = 0, raf2 = 0;
|
|
12223
12293
|
const place = () => {
|
|
12224
12294
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -12246,23 +12316,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
12246
12316
|
}, 0);
|
|
12247
12317
|
const nextPhase = items.find((i) => !i.implemented);
|
|
12248
12318
|
let lastPhase = null;
|
|
12249
|
-
return /* @__PURE__ */ (0,
|
|
12250
|
-
/* @__PURE__ */ (0,
|
|
12251
|
-
/* @__PURE__ */ (0,
|
|
12252
|
-
/* @__PURE__ */ (0,
|
|
12253
|
-
/* @__PURE__ */ (0,
|
|
12319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
|
|
12320
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
12321
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-overline fd-muted", children: "Architecture" }),
|
|
12322
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
12323
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede || "Every screen and feature in these tools is already designed and working against a simulated backend. This is the plan for connecting them to the real one \u2014 so the only work described here is server work." })
|
|
12254
12324
|
] }),
|
|
12255
|
-
/* @__PURE__ */ (0,
|
|
12256
|
-
/* @__PURE__ */ (0,
|
|
12257
|
-
/* @__PURE__ */ (0,
|
|
12258
|
-
/* @__PURE__ */ (0,
|
|
12259
|
-
/* @__PURE__ */ (0,
|
|
12325
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-grid-stats is-thin", children: [
|
|
12326
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
|
|
12327
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
|
|
12328
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
|
|
12329
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
|
|
12260
12330
|
] }),
|
|
12261
|
-
/* @__PURE__ */ (0,
|
|
12262
|
-
/* @__PURE__ */ (0,
|
|
12263
|
-
/* @__PURE__ */ (0,
|
|
12264
|
-
/* @__PURE__ */ (0,
|
|
12265
|
-
/* @__PURE__ */ (0,
|
|
12331
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
12332
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find a feature or a piece of backend work", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
|
|
12333
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
|
|
12334
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { style: { flex: 1 } }),
|
|
12335
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
|
|
12266
12336
|
Button,
|
|
12267
12337
|
{
|
|
12268
12338
|
size: "sm",
|
|
@@ -12276,7 +12346,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
12276
12346
|
}
|
|
12277
12347
|
)
|
|
12278
12348
|
] }),
|
|
12279
|
-
/* @__PURE__ */ (0,
|
|
12349
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
|
|
12280
12350
|
Flag,
|
|
12281
12351
|
{
|
|
12282
12352
|
tone: "info",
|
|
@@ -12285,60 +12355,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
12285
12355
|
actions: null
|
|
12286
12356
|
}
|
|
12287
12357
|
),
|
|
12288
|
-
/* @__PURE__ */ (0,
|
|
12289
|
-
/* @__PURE__ */ (0,
|
|
12358
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "fd-rm", children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-rm-track", children: [
|
|
12359
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-rm-spine", children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
|
|
12290
12360
|
items.map((item, n) => {
|
|
12291
12361
|
const showPhase = item.phase !== lastPhase;
|
|
12292
12362
|
lastPhase = item.phase;
|
|
12293
12363
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
12294
12364
|
const isBoundary = n === firstPending;
|
|
12295
|
-
return /* @__PURE__ */ (0,
|
|
12296
|
-
showPhase ? /* @__PURE__ */ (0,
|
|
12297
|
-
/* @__PURE__ */ (0,
|
|
12298
|
-
/* @__PURE__ */ (0,
|
|
12299
|
-
item.phase === 0 ? null : /* @__PURE__ */ (0,
|
|
12365
|
+
return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(React65.Fragment, { children: [
|
|
12366
|
+
showPhase ? /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-rm-era", children: [
|
|
12367
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
12368
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
12369
|
+
item.phase === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
12300
12370
|
fmtDate(item.phaseStart),
|
|
12301
12371
|
" \u2013 ",
|
|
12302
12372
|
fmtDate(item.date)
|
|
12303
12373
|
] }),
|
|
12304
|
-
/* @__PURE__ */ (0,
|
|
12374
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
12305
12375
|
"\xB7 ",
|
|
12306
12376
|
inPhase,
|
|
12307
12377
|
" feature",
|
|
12308
12378
|
inPhase === 1 ? "" : "s"
|
|
12309
12379
|
] })
|
|
12310
12380
|
] }),
|
|
12311
|
-
item.phaseWhy ? /* @__PURE__ */ (0,
|
|
12381
|
+
item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
|
|
12312
12382
|
] }) : null,
|
|
12313
|
-
isBoundary ? /* @__PURE__ */ (0,
|
|
12314
|
-
/* @__PURE__ */ (0,
|
|
12383
|
+
isBoundary ? /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-rm-now-pill", children: [
|
|
12384
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("i", { className: "ph ph-map-pin" }),
|
|
12315
12385
|
" You are here \u2014 everything above is wired"
|
|
12316
12386
|
] }) }) : null,
|
|
12317
|
-
/* @__PURE__ */ (0,
|
|
12318
|
-
/* @__PURE__ */ (0,
|
|
12319
|
-
/* @__PURE__ */ (0,
|
|
12387
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-rm-row", children: [
|
|
12388
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
|
|
12389
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-rm-date", children: [
|
|
12320
12390
|
fmtDate(item.date),
|
|
12321
|
-
/* @__PURE__ */ (0,
|
|
12322
|
-
/* @__PURE__ */ (0,
|
|
12391
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("br", {}),
|
|
12392
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
|
|
12323
12393
|
] }),
|
|
12324
|
-
/* @__PURE__ */ (0,
|
|
12394
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
|
|
12325
12395
|
] })
|
|
12326
12396
|
] }, item.key);
|
|
12327
12397
|
}),
|
|
12328
|
-
!items.length ? /* @__PURE__ */ (0,
|
|
12398
|
+
!items.length ? /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
|
|
12329
12399
|
] }) }) }),
|
|
12330
|
-
/* @__PURE__ */ (0,
|
|
12400
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
|
|
12331
12401
|
"Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
|
|
12332
|
-
/* @__PURE__ */ (0,
|
|
12402
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("code", { className: "fd-mono", children: "implemented" }),
|
|
12333
12403
|
" field, so this page cannot drift from what the apps actually do."
|
|
12334
12404
|
] })
|
|
12335
12405
|
] });
|
|
12336
12406
|
}
|
|
12337
12407
|
|
|
12338
12408
|
// src/components/platform/ComingSoon.tsx
|
|
12339
|
-
var
|
|
12409
|
+
var React66 = __toESM(require("react"), 1);
|
|
12340
12410
|
var import_react_dom7 = require("react-dom");
|
|
12341
|
-
var
|
|
12411
|
+
var import_jsx_runtime90 = require("react/jsx-runtime");
|
|
12342
12412
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
12343
12413
|
function readBypassed() {
|
|
12344
12414
|
try {
|
|
@@ -12354,8 +12424,8 @@ function writeBypassed(list) {
|
|
|
12354
12424
|
}
|
|
12355
12425
|
}
|
|
12356
12426
|
function useBypass(key) {
|
|
12357
|
-
const [on, setOn] =
|
|
12358
|
-
|
|
12427
|
+
const [on, setOn] = React66.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
12428
|
+
React66.useEffect(() => {
|
|
12359
12429
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
12360
12430
|
}, [key]);
|
|
12361
12431
|
const set = (next) => {
|
|
@@ -12368,43 +12438,43 @@ function useBypass(key) {
|
|
|
12368
12438
|
return [on, set];
|
|
12369
12439
|
}
|
|
12370
12440
|
function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
|
|
12371
|
-
return /* @__PURE__ */ (0,
|
|
12372
|
-
/* @__PURE__ */ (0,
|
|
12373
|
-
/* @__PURE__ */ (0,
|
|
12441
|
+
return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(import_jsx_runtime90.Fragment, { children: [
|
|
12442
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-soon-badge", children: [
|
|
12443
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
12374
12444
|
label
|
|
12375
12445
|
] }),
|
|
12376
|
-
detail ? /* @__PURE__ */ (0,
|
|
12377
|
-
backend ? /* @__PURE__ */ (0,
|
|
12378
|
-
/* @__PURE__ */ (0,
|
|
12446
|
+
detail ? /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-soon-detail", children: detail }) : null,
|
|
12447
|
+
backend ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-soon-backend", children: [
|
|
12448
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-overline", children: "Needs" }),
|
|
12379
12449
|
" ",
|
|
12380
12450
|
backend
|
|
12381
12451
|
] }) : null,
|
|
12382
|
-
eta || effort || onRoadmap ? /* @__PURE__ */ (0,
|
|
12383
|
-
eta ? /* @__PURE__ */ (0,
|
|
12384
|
-
/* @__PURE__ */ (0,
|
|
12452
|
+
eta || effort || onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-soon-meta", children: [
|
|
12453
|
+
eta ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { children: [
|
|
12454
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
|
|
12385
12455
|
" ",
|
|
12386
12456
|
eta
|
|
12387
12457
|
] }) : null,
|
|
12388
|
-
effort ? /* @__PURE__ */ (0,
|
|
12389
|
-
/* @__PURE__ */ (0,
|
|
12458
|
+
effort ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { children: [
|
|
12459
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
|
|
12390
12460
|
" ",
|
|
12391
12461
|
effort
|
|
12392
12462
|
] }) : null,
|
|
12393
|
-
onRoadmap ? /* @__PURE__ */ (0,
|
|
12463
|
+
onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
12394
12464
|
"See the roadmap ",
|
|
12395
|
-
/* @__PURE__ */ (0,
|
|
12465
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
12396
12466
|
] }) : null
|
|
12397
12467
|
] }) : null,
|
|
12398
|
-
allowed ? /* @__PURE__ */ (0,
|
|
12399
|
-
/* @__PURE__ */ (0,
|
|
12468
|
+
allowed ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
|
|
12469
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-eye", "aria-hidden": "true" }),
|
|
12400
12470
|
" View and use it anyway"
|
|
12401
12471
|
] }) : null
|
|
12402
12472
|
] });
|
|
12403
12473
|
}
|
|
12404
12474
|
function useHoverCard(open2) {
|
|
12405
|
-
const anchor =
|
|
12406
|
-
const [pos, setPos] =
|
|
12407
|
-
|
|
12475
|
+
const anchor = React66.useRef(null);
|
|
12476
|
+
const [pos, setPos] = React66.useState(null);
|
|
12477
|
+
React66.useLayoutEffect(() => {
|
|
12408
12478
|
if (!open2 || !anchor.current) {
|
|
12409
12479
|
setPos(null);
|
|
12410
12480
|
return;
|
|
@@ -12456,9 +12526,9 @@ function ComingSoon({
|
|
|
12456
12526
|
const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
|
|
12457
12527
|
if (inline) {
|
|
12458
12528
|
if (allowed && bypassed) {
|
|
12459
|
-
return /* @__PURE__ */ (0,
|
|
12529
|
+
return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
|
|
12460
12530
|
children,
|
|
12461
|
-
/* @__PURE__ */ (0,
|
|
12531
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
|
|
12462
12532
|
"button",
|
|
12463
12533
|
{
|
|
12464
12534
|
type: "button",
|
|
@@ -12466,12 +12536,12 @@ function ComingSoon({
|
|
|
12466
12536
|
title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
|
|
12467
12537
|
onClick: () => setBypassed(false),
|
|
12468
12538
|
"aria-label": "Re-blur this unwired feature",
|
|
12469
|
-
children: /* @__PURE__ */ (0,
|
|
12539
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
12470
12540
|
}
|
|
12471
12541
|
)
|
|
12472
12542
|
] });
|
|
12473
12543
|
}
|
|
12474
|
-
return /* @__PURE__ */ (0,
|
|
12544
|
+
return /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
|
|
12475
12545
|
InlineSoon,
|
|
12476
12546
|
{
|
|
12477
12547
|
label,
|
|
@@ -12491,20 +12561,20 @@ function ComingSoon({
|
|
|
12491
12561
|
);
|
|
12492
12562
|
}
|
|
12493
12563
|
if (allowed && bypassed) {
|
|
12494
|
-
return /* @__PURE__ */ (0,
|
|
12495
|
-
/* @__PURE__ */ (0,
|
|
12496
|
-
/* @__PURE__ */ (0,
|
|
12497
|
-
/* @__PURE__ */ (0,
|
|
12564
|
+
return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
|
|
12565
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "fd-soon-bar", role: "status", children: [
|
|
12566
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-soon-badge", children: [
|
|
12567
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
12498
12568
|
"Unwired feature \u2014 you are using it anyway"
|
|
12499
12569
|
] }),
|
|
12500
|
-
/* @__PURE__ */ (0,
|
|
12501
|
-
/* @__PURE__ */ (0,
|
|
12502
|
-
onRoadmap ? /* @__PURE__ */ (0,
|
|
12570
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
|
|
12571
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-soon-bar-actions", children: [
|
|
12572
|
+
onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
12503
12573
|
"Roadmap ",
|
|
12504
|
-
/* @__PURE__ */ (0,
|
|
12574
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
12505
12575
|
] }) : null,
|
|
12506
|
-
/* @__PURE__ */ (0,
|
|
12507
|
-
/* @__PURE__ */ (0,
|
|
12576
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
|
|
12577
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
|
|
12508
12578
|
" Re-blur"
|
|
12509
12579
|
] })
|
|
12510
12580
|
] })
|
|
@@ -12512,10 +12582,10 @@ function ComingSoon({
|
|
|
12512
12582
|
children
|
|
12513
12583
|
] });
|
|
12514
12584
|
}
|
|
12515
|
-
return /* @__PURE__ */ (0,
|
|
12516
|
-
/* @__PURE__ */ (0,
|
|
12517
|
-
/* @__PURE__ */ (0,
|
|
12518
|
-
/* @__PURE__ */ (0,
|
|
12585
|
+
return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
|
|
12586
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
12587
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)("div", { className: "fd-soon-veil" }),
|
|
12588
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
|
|
12519
12589
|
SoonCard,
|
|
12520
12590
|
{
|
|
12521
12591
|
label,
|
|
@@ -12531,12 +12601,12 @@ function ComingSoon({
|
|
|
12531
12601
|
] });
|
|
12532
12602
|
}
|
|
12533
12603
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
12534
|
-
const [open2, setOpen] =
|
|
12604
|
+
const [open2, setOpen] = React66.useState(false);
|
|
12535
12605
|
const [anchor, pos] = useHoverCard(open2);
|
|
12536
|
-
const hoverCardRef =
|
|
12606
|
+
const hoverCardRef = React66.useRef(null);
|
|
12537
12607
|
const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
|
|
12538
12608
|
const zIndex = useLayerZIndex(hoverLayer);
|
|
12539
|
-
const close2 =
|
|
12609
|
+
const close2 = React66.useRef(null);
|
|
12540
12610
|
const show = () => {
|
|
12541
12611
|
if (close2.current) {
|
|
12542
12612
|
clearTimeout(close2.current);
|
|
@@ -12552,10 +12622,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
12552
12622
|
setOpen(false);
|
|
12553
12623
|
}, 140);
|
|
12554
12624
|
};
|
|
12555
|
-
|
|
12625
|
+
React66.useEffect(() => () => {
|
|
12556
12626
|
if (close2.current) clearTimeout(close2.current);
|
|
12557
12627
|
}, []);
|
|
12558
|
-
return /* @__PURE__ */ (0,
|
|
12628
|
+
return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(
|
|
12559
12629
|
"span",
|
|
12560
12630
|
{
|
|
12561
12631
|
ref: anchor,
|
|
@@ -12566,8 +12636,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
12566
12636
|
onBlur: hide,
|
|
12567
12637
|
...rest,
|
|
12568
12638
|
children: [
|
|
12569
|
-
/* @__PURE__ */ (0,
|
|
12570
|
-
/* @__PURE__ */ (0,
|
|
12639
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
12640
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
|
|
12571
12641
|
"button",
|
|
12572
12642
|
{
|
|
12573
12643
|
type: "button",
|
|
@@ -12578,11 +12648,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
12578
12648
|
onFocus: show,
|
|
12579
12649
|
onBlur: hide,
|
|
12580
12650
|
onClick: () => open2 ? setOpen(false) : show(),
|
|
12581
|
-
children: /* @__PURE__ */ (0,
|
|
12651
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
12582
12652
|
}
|
|
12583
12653
|
),
|
|
12584
12654
|
open2 && pos ? (0, import_react_dom7.createPortal)(
|
|
12585
|
-
/* @__PURE__ */ (0,
|
|
12655
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
|
|
12586
12656
|
"div",
|
|
12587
12657
|
{
|
|
12588
12658
|
ref: hoverCardRef,
|
|
@@ -12591,7 +12661,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
12591
12661
|
style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
|
|
12592
12662
|
onMouseEnter: show,
|
|
12593
12663
|
onMouseLeave: hide,
|
|
12594
|
-
children: /* @__PURE__ */ (0,
|
|
12664
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
|
|
12595
12665
|
SoonCard,
|
|
12596
12666
|
{
|
|
12597
12667
|
label,
|
|
@@ -12621,10 +12691,10 @@ function formatEta(iso2) {
|
|
|
12621
12691
|
var FormatEta = formatEta;
|
|
12622
12692
|
|
|
12623
12693
|
// src/components/platform/Gate.tsx
|
|
12624
|
-
var
|
|
12694
|
+
var import_jsx_runtime91 = require("react/jsx-runtime");
|
|
12625
12695
|
function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
|
|
12626
12696
|
const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
|
|
12627
|
-
return /* @__PURE__ */ (0,
|
|
12697
|
+
return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
|
|
12628
12698
|
"div",
|
|
12629
12699
|
{
|
|
12630
12700
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -12640,14 +12710,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
12640
12710
|
},
|
|
12641
12711
|
...rest,
|
|
12642
12712
|
children: [
|
|
12643
|
-
/* @__PURE__ */ (0,
|
|
12644
|
-
/* @__PURE__ */ (0,
|
|
12645
|
-
/* @__PURE__ */ (0,
|
|
12713
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
12714
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
12715
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
|
|
12646
12716
|
] }),
|
|
12647
|
-
/* @__PURE__ */ (0,
|
|
12648
|
-
need.length ? /* @__PURE__ */ (0,
|
|
12649
|
-
/* @__PURE__ */ (0,
|
|
12650
|
-
need.map((p) => /* @__PURE__ */ (0,
|
|
12717
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: detail || "Your roles do not grant this. An administrator can change that from Admin \u2192 Users." }),
|
|
12718
|
+
need.length ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
|
|
12719
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-overline fd-muted", children: "Requires" }),
|
|
12720
|
+
need.map((p) => /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("code", { className: "fd-mono", style: {
|
|
12651
12721
|
fontSize: 11.5,
|
|
12652
12722
|
padding: "2px 7px",
|
|
12653
12723
|
borderRadius: 5,
|
|
@@ -12660,7 +12730,7 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
12660
12730
|
);
|
|
12661
12731
|
}
|
|
12662
12732
|
function GatePending({ compact: compact3 = false, className = "" }) {
|
|
12663
|
-
return /* @__PURE__ */ (0,
|
|
12733
|
+
return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
|
|
12664
12734
|
"div",
|
|
12665
12735
|
{
|
|
12666
12736
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -12676,11 +12746,11 @@ function GatePending({ compact: compact3 = false, className = "" }) {
|
|
|
12676
12746
|
textAlign: "left"
|
|
12677
12747
|
},
|
|
12678
12748
|
children: [
|
|
12679
|
-
/* @__PURE__ */ (0,
|
|
12680
|
-
/* @__PURE__ */ (0,
|
|
12681
|
-
/* @__PURE__ */ (0,
|
|
12749
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
12750
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
12751
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
|
|
12682
12752
|
] }),
|
|
12683
|
-
/* @__PURE__ */ (0,
|
|
12753
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: "Your access can't be verified right now. This will resolve on its own once the connection is back." })
|
|
12684
12754
|
]
|
|
12685
12755
|
}
|
|
12686
12756
|
);
|
|
@@ -12690,7 +12760,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
|
|
|
12690
12760
|
if (pending) {
|
|
12691
12761
|
if (pendingFallback !== void 0) return pendingFallback;
|
|
12692
12762
|
if (silent) return null;
|
|
12693
|
-
return /* @__PURE__ */ (0,
|
|
12763
|
+
return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(GatePending, { compact: compact3 });
|
|
12694
12764
|
}
|
|
12695
12765
|
let ok = true;
|
|
12696
12766
|
if (perm) ok = ok && can2(perm);
|
|
@@ -12699,7 +12769,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
|
|
|
12699
12769
|
if (ok) return children;
|
|
12700
12770
|
if (fallback !== void 0) return fallback;
|
|
12701
12771
|
if (silent) return null;
|
|
12702
|
-
return /* @__PURE__ */ (0,
|
|
12772
|
+
return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
|
|
12703
12773
|
}
|
|
12704
12774
|
function FeatureGate({
|
|
12705
12775
|
flag,
|
|
@@ -12722,7 +12792,7 @@ function FeatureGate({
|
|
|
12722
12792
|
const f = SessionKit.findFlag(flag) || {};
|
|
12723
12793
|
const missing = rt.missing || [];
|
|
12724
12794
|
const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
|
|
12725
|
-
return /* @__PURE__ */ (0,
|
|
12795
|
+
return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
|
|
12726
12796
|
ComingSoon,
|
|
12727
12797
|
{
|
|
12728
12798
|
label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
|
|
@@ -12743,22 +12813,22 @@ function FeatureGate({
|
|
|
12743
12813
|
function PermissionHint({ perm, children }) {
|
|
12744
12814
|
const { can: can2, pending } = useSessionContext();
|
|
12745
12815
|
if (pending) {
|
|
12746
|
-
return /* @__PURE__ */ (0,
|
|
12816
|
+
return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { style: { pointerEvents: "none" }, children }) });
|
|
12747
12817
|
}
|
|
12748
12818
|
if (can2(perm)) return children;
|
|
12749
|
-
return /* @__PURE__ */ (0,
|
|
12819
|
+
return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
|
|
12750
12820
|
"span",
|
|
12751
12821
|
{
|
|
12752
12822
|
title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
|
|
12753
12823
|
style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
|
|
12754
12824
|
"aria-disabled": "true",
|
|
12755
|
-
children: /* @__PURE__ */ (0,
|
|
12825
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { style: { pointerEvents: "none" }, children })
|
|
12756
12826
|
}
|
|
12757
12827
|
);
|
|
12758
12828
|
}
|
|
12759
12829
|
|
|
12760
12830
|
// src/components/platform/ModeSwitch.tsx
|
|
12761
|
-
var
|
|
12831
|
+
var import_jsx_runtime92 = require("react/jsx-runtime");
|
|
12762
12832
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
12763
12833
|
const mode2 = useRuntimeMode();
|
|
12764
12834
|
const panel = useInlinePanel();
|
|
@@ -12770,8 +12840,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
12770
12840
|
RuntimeKit.setMode(next);
|
|
12771
12841
|
setOpen(false);
|
|
12772
12842
|
};
|
|
12773
|
-
return /* @__PURE__ */ (0,
|
|
12774
|
-
/* @__PURE__ */ (0,
|
|
12843
|
+
return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { style: { display: "inline-flex" }, ref, children: [
|
|
12844
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)(
|
|
12775
12845
|
"button",
|
|
12776
12846
|
{
|
|
12777
12847
|
type: "button",
|
|
@@ -12781,29 +12851,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
12781
12851
|
title: test ? "Test mode \u2014 every response is simulated. Click to inspect requests or return to live mode." : "Live mode \u2014 incomplete features are shown under construction. Click for test mode.",
|
|
12782
12852
|
className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
|
|
12783
12853
|
children: [
|
|
12784
|
-
/* @__PURE__ */ (0,
|
|
12785
|
-
test && requestCount ? /* @__PURE__ */ (0,
|
|
12854
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
|
|
12855
|
+
test && requestCount ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
|
|
12786
12856
|
]
|
|
12787
12857
|
}
|
|
12788
12858
|
),
|
|
12789
|
-
/* @__PURE__ */ (0,
|
|
12790
|
-
/* @__PURE__ */ (0,
|
|
12791
|
-
/* @__PURE__ */ (0,
|
|
12792
|
-
/* @__PURE__ */ (0,
|
|
12859
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)(InlinePanelSurface, { panel, align: "right", offset: 8, width: 400, className: "fd-mode-pop", label: test ? "Test mode" : "Live mode", children: [
|
|
12860
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
12861
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
|
|
12862
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
|
|
12793
12863
|
test ? "Test mode" : "Live mode"
|
|
12794
12864
|
] }),
|
|
12795
|
-
test ? /* @__PURE__ */ (0,
|
|
12865
|
+
test ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
12796
12866
|
requestCount,
|
|
12797
12867
|
" simulated request",
|
|
12798
12868
|
requestCount === 1 ? "" : "s"
|
|
12799
12869
|
] }) : null,
|
|
12800
|
-
/* @__PURE__ */ (0,
|
|
12801
|
-
test && onClearLog ? /* @__PURE__ */ (0,
|
|
12870
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { style: { flex: 1 } }),
|
|
12871
|
+
test && onClearLog ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
|
|
12802
12872
|
] }),
|
|
12803
|
-
/* @__PURE__ */ (0,
|
|
12804
|
-
/* @__PURE__ */ (0,
|
|
12805
|
-
/* @__PURE__ */ (0,
|
|
12806
|
-
/* @__PURE__ */ (0,
|
|
12873
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
12874
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-body-sm fd-secondary", style: { display: "block", textWrap: "pretty" }, children: test ? "Every feature is usable and nothing is obstructed, but no response comes from a real service \u2014 nothing you do here persists. Use this to review and demo the design." : "This is what a user would see today. " + s.incomplete + " of " + s.total + " features depend on backend work that is not wired yet, so they render under construction." }),
|
|
12875
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
|
|
12876
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
12807
12877
|
s.endpointsWired,
|
|
12808
12878
|
" endpoint",
|
|
12809
12879
|
s.endpointsWired === 1 ? "" : "s",
|
|
@@ -12813,58 +12883,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
12813
12883
|
s.total,
|
|
12814
12884
|
" features complete"
|
|
12815
12885
|
] }),
|
|
12816
|
-
onOpenSpec ? /* @__PURE__ */ (0,
|
|
12817
|
-
/* @__PURE__ */ (0,
|
|
12818
|
-
/* @__PURE__ */ (0,
|
|
12886
|
+
onOpenSpec ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)(import_jsx_runtime92.Fragment, { children: [
|
|
12887
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { style: { flex: 1 } }),
|
|
12888
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => {
|
|
12819
12889
|
setOpen(false);
|
|
12820
12890
|
onOpenSpec();
|
|
12821
12891
|
}, children: [
|
|
12822
12892
|
"API spec ",
|
|
12823
|
-
/* @__PURE__ */ (0,
|
|
12893
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
12824
12894
|
] })
|
|
12825
12895
|
] }) : null
|
|
12826
12896
|
] })
|
|
12827
12897
|
] }),
|
|
12828
|
-
/* @__PURE__ */ (0,
|
|
12829
|
-
/* @__PURE__ */ (0,
|
|
12830
|
-
/* @__PURE__ */ (0,
|
|
12831
|
-
/* @__PURE__ */ (0,
|
|
12832
|
-
/* @__PURE__ */ (0,
|
|
12833
|
-
/* @__PURE__ */ (0,
|
|
12898
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-mode-choice", children: [
|
|
12899
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
|
|
12900
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
12901
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-mode-opt-text", children: [
|
|
12902
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-mode-opt-title", children: "Live mode" }),
|
|
12903
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
|
|
12834
12904
|
] }),
|
|
12835
|
-
!test ? /* @__PURE__ */ (0,
|
|
12905
|
+
!test ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
12836
12906
|
] }),
|
|
12837
|
-
/* @__PURE__ */ (0,
|
|
12838
|
-
/* @__PURE__ */ (0,
|
|
12839
|
-
/* @__PURE__ */ (0,
|
|
12840
|
-
/* @__PURE__ */ (0,
|
|
12841
|
-
/* @__PURE__ */ (0,
|
|
12907
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
|
|
12908
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
12909
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-mode-opt-text", children: [
|
|
12910
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-mode-opt-title", children: "Test mode" }),
|
|
12911
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
|
|
12842
12912
|
] }),
|
|
12843
|
-
test ? /* @__PURE__ */ (0,
|
|
12913
|
+
test ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
12844
12914
|
] })
|
|
12845
12915
|
] }),
|
|
12846
|
-
test && renderLog ? /* @__PURE__ */ (0,
|
|
12916
|
+
test && renderLog ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
|
|
12847
12917
|
] })
|
|
12848
12918
|
] });
|
|
12849
12919
|
}
|
|
12850
12920
|
function TestModeBar({ onExit }) {
|
|
12851
12921
|
const mode2 = useRuntimeMode();
|
|
12852
12922
|
if (mode2 !== "test") return null;
|
|
12853
|
-
return /* @__PURE__ */ (0,
|
|
12854
|
-
/* @__PURE__ */ (0,
|
|
12855
|
-
/* @__PURE__ */ (0,
|
|
12923
|
+
return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fd-testbar", role: "status", children: [
|
|
12924
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-badge fd-badge-warning", children: [
|
|
12925
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
12856
12926
|
"Test mode"
|
|
12857
12927
|
] }),
|
|
12858
|
-
/* @__PURE__ */ (0,
|
|
12859
|
-
/* @__PURE__ */ (0,
|
|
12860
|
-
/* @__PURE__ */ (0,
|
|
12928
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
|
|
12929
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
|
|
12930
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
12861
12931
|
" Back to live mode"
|
|
12862
12932
|
] })
|
|
12863
12933
|
] });
|
|
12864
12934
|
}
|
|
12865
12935
|
|
|
12866
12936
|
// src/components/planner/ChannelMeta.tsx
|
|
12867
|
-
var
|
|
12937
|
+
var import_jsx_runtime93 = require("react/jsx-runtime");
|
|
12868
12938
|
var CHANNEL_WEIGHTS = {
|
|
12869
12939
|
"OOH": 50,
|
|
12870
12940
|
"DOOH": 50,
|
|
@@ -12917,9 +12987,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
12917
12987
|
const m = ChannelMeta(channel);
|
|
12918
12988
|
const wt = channelWeightOf(channel || "");
|
|
12919
12989
|
if (dot) {
|
|
12920
|
-
return /* @__PURE__ */ (0,
|
|
12990
|
+
return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
|
|
12921
12991
|
}
|
|
12922
|
-
return /* @__PURE__ */ (0,
|
|
12992
|
+
return /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)(
|
|
12923
12993
|
"span",
|
|
12924
12994
|
{
|
|
12925
12995
|
className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
|
|
@@ -12927,16 +12997,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
12927
12997
|
style: { "--chan": m.color },
|
|
12928
12998
|
...rest,
|
|
12929
12999
|
children: [
|
|
12930
|
-
/* @__PURE__ */ (0,
|
|
12931
|
-
showLabel ? /* @__PURE__ */ (0,
|
|
12932
|
-
weight ? /* @__PURE__ */ (0,
|
|
13000
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
|
|
13001
|
+
showLabel ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fd-chan-label", children: m.label }) : null,
|
|
13002
|
+
weight ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fd-chan-weight", children: wt || 0 }) : null
|
|
12933
13003
|
]
|
|
12934
13004
|
}
|
|
12935
13005
|
);
|
|
12936
13006
|
}
|
|
12937
13007
|
|
|
12938
13008
|
// src/components/planner/SaturationDistribution.tsx
|
|
12939
|
-
var
|
|
13009
|
+
var import_jsx_runtime94 = require("react/jsx-runtime");
|
|
12940
13010
|
var BANDS2 = [
|
|
12941
13011
|
{ key: "weak", label: "Weak", n: 1, range: "< 50" },
|
|
12942
13012
|
{ key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
|
|
@@ -12947,24 +13017,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
12947
13017
|
const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
|
|
12948
13018
|
const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
|
|
12949
13019
|
const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
|
|
12950
|
-
return /* @__PURE__ */ (0,
|
|
12951
|
-
/* @__PURE__ */ (0,
|
|
13020
|
+
return /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
13021
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
|
|
12952
13022
|
const mark = "var(--csi-" + g.n + "-mark)";
|
|
12953
13023
|
const active = selectedBand === g.key;
|
|
12954
|
-
return /* @__PURE__ */ (0,
|
|
13024
|
+
return /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)(
|
|
12955
13025
|
"button",
|
|
12956
13026
|
{
|
|
12957
13027
|
type: "button",
|
|
12958
13028
|
onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
|
|
12959
13029
|
style: { display: "flex", flexDirection: "column", justifyContent: "flex-end", gap: 10, padding: 12, border: "1px solid " + (active ? "var(--border-strong)" : "var(--border)"), borderRadius: "var(--r-lg)", background: active ? "var(--surface-2)" : "var(--surface)", cursor: onSelectBand ? "pointer" : "default", textAlign: "left", minHeight: 190, minWidth: 0, transition: "background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease)" },
|
|
12960
13030
|
children: [
|
|
12961
|
-
/* @__PURE__ */ (0,
|
|
13031
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
|
|
12962
13032
|
// `overflow: hidden` + `white-space: nowrap` only clips once the span
|
|
12963
13033
|
// actually HAS a bounded width to clip against (see the grid/flex
|
|
12964
13034
|
// `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
|
|
12965
13035
|
// that clip readable instead of a hard cut mid-letter; the full name
|
|
12966
13036
|
// is still one hover away via `title`.
|
|
12967
|
-
/* @__PURE__ */ (0,
|
|
13037
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
|
|
12968
13038
|
"span",
|
|
12969
13039
|
{
|
|
12970
13040
|
title: c.name + " \xB7 " + c.crp,
|
|
@@ -12974,13 +13044,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
12974
13044
|
c.name
|
|
12975
13045
|
)
|
|
12976
13046
|
)) }),
|
|
12977
|
-
/* @__PURE__ */ (0,
|
|
12978
|
-
/* @__PURE__ */ (0,
|
|
12979
|
-
/* @__PURE__ */ (0,
|
|
13047
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
|
|
13048
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
|
|
13049
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
|
|
12980
13050
|
] }),
|
|
12981
|
-
/* @__PURE__ */ (0,
|
|
12982
|
-
/* @__PURE__ */ (0,
|
|
12983
|
-
/* @__PURE__ */ (0,
|
|
13051
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("span", { className: "fd-stack", style: { gap: 1 }, children: [
|
|
13052
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-label-lg", children: g.label }),
|
|
13053
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
|
|
12984
13054
|
"CRP ",
|
|
12985
13055
|
g.range
|
|
12986
13056
|
] })
|
|
@@ -12990,10 +13060,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
12990
13060
|
g.key
|
|
12991
13061
|
);
|
|
12992
13062
|
}) }),
|
|
12993
|
-
floorBand ? /* @__PURE__ */ (0,
|
|
12994
|
-
/* @__PURE__ */ (0,
|
|
12995
|
-
/* @__PURE__ */ (0,
|
|
12996
|
-
/* @__PURE__ */ (0,
|
|
13063
|
+
floorBand ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderRadius: "var(--r-md)", background: "var(--surface-2)", border: "1px solid var(--border)", flexWrap: "wrap" }, children: [
|
|
13064
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
|
|
13065
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
|
|
13066
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("strong", { style: { color: "var(--text)" }, children: [
|
|
12997
13067
|
"Plan floor ",
|
|
12998
13068
|
floorScore
|
|
12999
13069
|
] }),
|
|
@@ -13004,8 +13074,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
13004
13074
|
}
|
|
13005
13075
|
|
|
13006
13076
|
// src/components/planner/MixGap.tsx
|
|
13007
|
-
var
|
|
13008
|
-
var
|
|
13077
|
+
var React67 = __toESM(require("react"), 1);
|
|
13078
|
+
var import_jsx_runtime95 = require("react/jsx-runtime");
|
|
13009
13079
|
var MIX_GAP_LAYOUT = {
|
|
13010
13080
|
trackHeight: 30,
|
|
13011
13081
|
barHeight: 20,
|
|
@@ -13019,19 +13089,19 @@ function mixGapOffset(value, max) {
|
|
|
13019
13089
|
}
|
|
13020
13090
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
13021
13091
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
13022
|
-
const [hover, setHover] =
|
|
13092
|
+
const [hover, setHover] = React67.useState(null);
|
|
13023
13093
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
13024
13094
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
13025
13095
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
13026
13096
|
const barTop = (trackHeight - barHeight) / 2;
|
|
13027
|
-
return /* @__PURE__ */ (0,
|
|
13028
|
-
/* @__PURE__ */ (0,
|
|
13029
|
-
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0,
|
|
13030
|
-
/* @__PURE__ */ (0,
|
|
13097
|
+
return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
|
|
13098
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
|
|
13099
|
+
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
13100
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
|
|
13031
13101
|
l
|
|
13032
13102
|
] }, l)),
|
|
13033
|
-
/* @__PURE__ */ (0,
|
|
13034
|
-
/* @__PURE__ */ (0,
|
|
13103
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
13104
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
|
|
13035
13105
|
"Target"
|
|
13036
13106
|
] })
|
|
13037
13107
|
] }),
|
|
@@ -13040,7 +13110,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
13040
13110
|
const tone = toneOf(gap);
|
|
13041
13111
|
const tip = "Realized " + r.realized + "% vs " + r.target + "% target" + (gap < -1 ? " \xB7 " + Math.abs(gap).toFixed(0) + " pts short" : gap > 1 ? " \xB7 " + gap.toFixed(0) + " pts over" : " \xB7 on target") + (r.note ? " \u2014 " + r.note : "");
|
|
13042
13112
|
const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
|
|
13043
|
-
return /* @__PURE__ */ (0,
|
|
13113
|
+
return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(
|
|
13044
13114
|
"div",
|
|
13045
13115
|
{
|
|
13046
13116
|
className: "fd-row",
|
|
@@ -13048,15 +13118,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
13048
13118
|
onMouseEnter: () => setHover(r.channel),
|
|
13049
13119
|
onMouseLeave: () => setHover(null),
|
|
13050
13120
|
children: [
|
|
13051
|
-
/* @__PURE__ */ (0,
|
|
13052
|
-
/* @__PURE__ */ (0,
|
|
13053
|
-
/* @__PURE__ */ (0,
|
|
13054
|
-
/* @__PURE__ */ (0,
|
|
13055
|
-
/* @__PURE__ */ (0,
|
|
13121
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(ChannelTag, { channel: r.channel, size: "sm" }) }),
|
|
13122
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(import_jsx_runtime95.Fragment, { children: [
|
|
13123
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { "data-mixgap-bar": "", style: { position: "absolute", left: 0, top: barTop, height: barHeight, width: mixGapOffset(r.realized, max), background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
|
|
13124
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { "data-mixgap-target": "", style: { position: "absolute", left: `calc(${mixGapOffset(r.target, max)} - ${targetWidth / 2}px)`, top: 0, width: targetWidth, height: trackHeight, background: MIX_GAP_TARGET_STRIPE, borderRadius: 1 } }),
|
|
13125
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("span", { "data-mixgap-label": "", className: "fd-num", style: { position: "absolute", left: labelLeft, top: "50%", transform: "translateY(-50%)", fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap" }, children: [
|
|
13056
13126
|
r.realized,
|
|
13057
13127
|
"%"
|
|
13058
13128
|
] }),
|
|
13059
|
-
hover === r.channel ? /* @__PURE__ */ (0,
|
|
13129
|
+
hover === r.channel ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: trackHeight + 4, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
|
|
13060
13130
|
] }) })
|
|
13061
13131
|
]
|
|
13062
13132
|
},
|
|
@@ -13067,7 +13137,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
13067
13137
|
}
|
|
13068
13138
|
|
|
13069
13139
|
// src/components/planner/ChannelContribution.tsx
|
|
13070
|
-
var
|
|
13140
|
+
var import_jsx_runtime96 = require("react/jsx-runtime");
|
|
13071
13141
|
var money = (n) => "$" + Math.round(n).toLocaleString();
|
|
13072
13142
|
function ChannelContribution({
|
|
13073
13143
|
channels = [],
|
|
@@ -13083,9 +13153,9 @@ function ChannelContribution({
|
|
|
13083
13153
|
const grand = total !== void 0 ? total : base + bonus;
|
|
13084
13154
|
const pct = (v) => grand ? v / grand * 100 : 0;
|
|
13085
13155
|
const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
|
|
13086
|
-
return /* @__PURE__ */ (0,
|
|
13087
|
-
loading ? /* @__PURE__ */ (0,
|
|
13088
|
-
channels.map((c) => /* @__PURE__ */ (0,
|
|
13156
|
+
return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
13157
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
|
|
13158
|
+
channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
|
|
13089
13159
|
"span",
|
|
13090
13160
|
{
|
|
13091
13161
|
title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
|
|
@@ -13094,7 +13164,7 @@ function ChannelContribution({
|
|
|
13094
13164
|
},
|
|
13095
13165
|
c.name
|
|
13096
13166
|
)),
|
|
13097
|
-
bonus > 0 ? /* @__PURE__ */ (0,
|
|
13167
|
+
bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
|
|
13098
13168
|
"span",
|
|
13099
13169
|
{
|
|
13100
13170
|
title: "Surround-sound bonus +" + bonusPct + "%",
|
|
@@ -13103,18 +13173,18 @@ function ChannelContribution({
|
|
|
13103
13173
|
}
|
|
13104
13174
|
) : null
|
|
13105
13175
|
] }),
|
|
13106
|
-
showTable ? /* @__PURE__ */ (0,
|
|
13107
|
-
/* @__PURE__ */ (0,
|
|
13108
|
-
/* @__PURE__ */ (0,
|
|
13109
|
-
/* @__PURE__ */ (0,
|
|
13110
|
-
/* @__PURE__ */ (0,
|
|
13111
|
-
/* @__PURE__ */ (0,
|
|
13112
|
-
/* @__PURE__ */ (0,
|
|
13176
|
+
showTable ? /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
|
|
13177
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("tr", { children: [
|
|
13178
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("th", { style: { width: "34%" }, children: "Channel" }),
|
|
13179
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("th", { style: { width: "16%" }, children: "Weight" }),
|
|
13180
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
|
|
13181
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
|
|
13182
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
|
|
13113
13183
|
] }) }),
|
|
13114
|
-
/* @__PURE__ */ (0,
|
|
13115
|
-
channels.map((c) => /* @__PURE__ */ (0,
|
|
13116
|
-
/* @__PURE__ */ (0,
|
|
13117
|
-
/* @__PURE__ */ (0,
|
|
13184
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("tbody", { children: [
|
|
13185
|
+
channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("tr", { children: [
|
|
13186
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(ChannelTag, { channel: c.name, size: "sm" }) }),
|
|
13187
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
|
|
13118
13188
|
"span",
|
|
13119
13189
|
{
|
|
13120
13190
|
className: "fd-badge fd-badge-neutral",
|
|
@@ -13123,38 +13193,38 @@ function ChannelContribution({
|
|
|
13123
13193
|
children: "weight " + (channelWeightOf(c.name) || 0)
|
|
13124
13194
|
}
|
|
13125
13195
|
) }),
|
|
13126
|
-
/* @__PURE__ */ (0,
|
|
13127
|
-
/* @__PURE__ */ (0,
|
|
13128
|
-
/* @__PURE__ */ (0,
|
|
13196
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { className: "is-num", children: c.spend }),
|
|
13197
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { className: "is-num", children: c.crp.toFixed(1) }),
|
|
13198
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("td", { className: "is-num", children: [
|
|
13129
13199
|
pct(c.crp).toFixed(0),
|
|
13130
13200
|
"%"
|
|
13131
13201
|
] })
|
|
13132
13202
|
] }, c.name)),
|
|
13133
|
-
bonus > 0 ? /* @__PURE__ */ (0,
|
|
13134
|
-
/* @__PURE__ */ (0,
|
|
13135
|
-
/* @__PURE__ */ (0,
|
|
13203
|
+
bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("tr", { children: [
|
|
13204
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
|
|
13205
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { style: { width: 9, height: 9, borderRadius: 2, background: "repeating-linear-gradient(135deg,var(--csi-3-mark) 0 3px,var(--csi-2-mark) 3px 6px)", flex: "none" } }),
|
|
13136
13206
|
"Surround-sound bonus"
|
|
13137
13207
|
] }) }),
|
|
13138
|
-
/* @__PURE__ */ (0,
|
|
13208
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
|
|
13139
13209
|
"+",
|
|
13140
13210
|
bonusPct,
|
|
13141
13211
|
"% of +",
|
|
13142
13212
|
bonusMax,
|
|
13143
13213
|
"%"
|
|
13144
13214
|
] }) }),
|
|
13145
|
-
/* @__PURE__ */ (0,
|
|
13146
|
-
/* @__PURE__ */ (0,
|
|
13147
|
-
/* @__PURE__ */ (0,
|
|
13215
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { className: "is-num fd-muted", children: "\u2014" }),
|
|
13216
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { className: "is-num", children: bonus.toFixed(1) }),
|
|
13217
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("td", { className: "is-num", children: [
|
|
13148
13218
|
pct(bonus).toFixed(0),
|
|
13149
13219
|
"%"
|
|
13150
13220
|
] })
|
|
13151
13221
|
] }) : null,
|
|
13152
|
-
/* @__PURE__ */ (0,
|
|
13153
|
-
/* @__PURE__ */ (0,
|
|
13154
|
-
/* @__PURE__ */ (0,
|
|
13155
|
-
/* @__PURE__ */ (0,
|
|
13156
|
-
/* @__PURE__ */ (0,
|
|
13157
|
-
/* @__PURE__ */ (0,
|
|
13222
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("tr", { style: { background: "var(--surface-2)" }, children: [
|
|
13223
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { style: { fontWeight: 700 }, children: "Campus total" }),
|
|
13224
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", {}),
|
|
13225
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
|
|
13226
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
|
|
13227
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
|
|
13158
13228
|
] })
|
|
13159
13229
|
] })
|
|
13160
13230
|
] }) : null
|
|
@@ -13162,8 +13232,8 @@ function ChannelContribution({
|
|
|
13162
13232
|
}
|
|
13163
13233
|
|
|
13164
13234
|
// src/components/planner/BudgetReallocator.tsx
|
|
13165
|
-
var
|
|
13166
|
-
var
|
|
13235
|
+
var React68 = __toESM(require("react"), 1);
|
|
13236
|
+
var import_jsx_runtime97 = require("react/jsx-runtime");
|
|
13167
13237
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
13168
13238
|
function BudgetReallocator({
|
|
13169
13239
|
campus,
|
|
@@ -13178,8 +13248,8 @@ function BudgetReallocator({
|
|
|
13178
13248
|
onCancel,
|
|
13179
13249
|
className = ""
|
|
13180
13250
|
}) {
|
|
13181
|
-
const [draft, setDraft] =
|
|
13182
|
-
|
|
13251
|
+
const [draft, setDraft] = React68.useState(spend);
|
|
13252
|
+
React68.useEffect(() => setDraft(spend), [spend]);
|
|
13183
13253
|
const dirty = draft !== spend;
|
|
13184
13254
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
13185
13255
|
const nextBand = bandFor(nextCrp);
|
|
@@ -13194,10 +13264,10 @@ function BudgetReallocator({
|
|
|
13194
13264
|
setDraft(spend);
|
|
13195
13265
|
if (onCancel) onCancel();
|
|
13196
13266
|
};
|
|
13197
|
-
const trackRef =
|
|
13198
|
-
const chipRef =
|
|
13199
|
-
const [chipLeft, setChipLeft] =
|
|
13200
|
-
|
|
13267
|
+
const trackRef = React68.useRef(null);
|
|
13268
|
+
const chipRef = React68.useRef(null);
|
|
13269
|
+
const [chipLeft, setChipLeft] = React68.useState(null);
|
|
13270
|
+
React68.useLayoutEffect(() => {
|
|
13201
13271
|
const track = trackRef.current;
|
|
13202
13272
|
if (!dirty || !track) {
|
|
13203
13273
|
setChipLeft(null);
|
|
@@ -13218,23 +13288,23 @@ function BudgetReallocator({
|
|
|
13218
13288
|
ro.observe(track);
|
|
13219
13289
|
return () => ro.disconnect();
|
|
13220
13290
|
}, [dirty, pct]);
|
|
13221
|
-
return /* @__PURE__ */ (0,
|
|
13291
|
+
return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(
|
|
13222
13292
|
"div",
|
|
13223
13293
|
{
|
|
13224
13294
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
13225
13295
|
style: { gap: 14, padding: 18, border: "1px solid " + (dirty ? "var(--border-brand)" : "var(--border)"), borderRadius: "var(--r-lg)", background: dirty ? "var(--surface-brand)" : "var(--surface)", color: "var(--text)", transition: "background var(--dur-base) var(--ease),border-color var(--dur-base) var(--ease)" },
|
|
13226
13296
|
children: [
|
|
13227
|
-
/* @__PURE__ */ (0,
|
|
13228
|
-
/* @__PURE__ */ (0,
|
|
13229
|
-
/* @__PURE__ */ (0,
|
|
13230
|
-
dirty ? /* @__PURE__ */ (0,
|
|
13231
|
-
/* @__PURE__ */ (0,
|
|
13232
|
-
/* @__PURE__ */ (0,
|
|
13297
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
13298
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
|
|
13299
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)(CsiBadge, { band: nowBand, crp, size: "medium" }),
|
|
13300
|
+
dirty ? /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
|
|
13301
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
|
|
13302
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
|
|
13233
13303
|
] }) : null
|
|
13234
13304
|
] }),
|
|
13235
|
-
/* @__PURE__ */ (0,
|
|
13236
|
-
/* @__PURE__ */ (0,
|
|
13237
|
-
dirty ? /* @__PURE__ */ (0,
|
|
13305
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-slider", ref: trackRef, children: [
|
|
13306
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
13307
|
+
dirty ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
|
|
13238
13308
|
"span",
|
|
13239
13309
|
{
|
|
13240
13310
|
ref: chipRef,
|
|
@@ -13246,7 +13316,7 @@ function BudgetReallocator({
|
|
|
13246
13316
|
children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
|
|
13247
13317
|
}
|
|
13248
13318
|
) : null,
|
|
13249
|
-
/* @__PURE__ */ (0,
|
|
13319
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
|
|
13250
13320
|
"input",
|
|
13251
13321
|
{
|
|
13252
13322
|
type: "range",
|
|
@@ -13262,13 +13332,13 @@ function BudgetReallocator({
|
|
|
13262
13332
|
}
|
|
13263
13333
|
)
|
|
13264
13334
|
] }),
|
|
13265
|
-
/* @__PURE__ */ (0,
|
|
13266
|
-
/* @__PURE__ */ (0,
|
|
13267
|
-
/* @__PURE__ */ (0,
|
|
13268
|
-
/* @__PURE__ */ (0,
|
|
13335
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
13336
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
|
|
13337
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
|
|
13338
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
|
|
13269
13339
|
] }),
|
|
13270
|
-
/* @__PURE__ */ (0,
|
|
13271
|
-
/* @__PURE__ */ (0,
|
|
13340
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
|
|
13341
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
|
|
13272
13342
|
"button",
|
|
13273
13343
|
{
|
|
13274
13344
|
type: "button",
|
|
@@ -13287,7 +13357,7 @@ function BudgetReallocator({
|
|
|
13287
13357
|
}
|
|
13288
13358
|
|
|
13289
13359
|
// src/components/planner/SurroundSound.tsx
|
|
13290
|
-
var
|
|
13360
|
+
var import_jsx_runtime98 = require("react/jsx-runtime");
|
|
13291
13361
|
var CATEGORIES = [
|
|
13292
13362
|
{ key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
|
|
13293
13363
|
{ key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
|
|
@@ -13299,26 +13369,26 @@ var CATEGORIES = [
|
|
|
13299
13369
|
function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
|
|
13300
13370
|
const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
|
|
13301
13371
|
const single = present.length <= 2;
|
|
13302
|
-
return /* @__PURE__ */ (0,
|
|
13303
|
-
/* @__PURE__ */ (0,
|
|
13372
|
+
return /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
|
|
13373
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
|
|
13304
13374
|
const on = present.includes(c.key);
|
|
13305
|
-
return /* @__PURE__ */ (0,
|
|
13375
|
+
return /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(
|
|
13306
13376
|
"span",
|
|
13307
13377
|
{
|
|
13308
13378
|
title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
|
|
13309
13379
|
style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 5, width: 62, padding: "10px 0", borderRadius: "var(--r-md)", border: "1px solid " + (on ? "var(--csi-2-edge)" : "var(--border)"), background: on ? "var(--csi-2-fill)" : "var(--surface-2)", color: on ? "var(--csi-2-text)" : "var(--text-disabled)" },
|
|
13310
13380
|
children: [
|
|
13311
|
-
/* @__PURE__ */ (0,
|
|
13312
|
-
/* @__PURE__ */ (0,
|
|
13381
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
13382
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
|
|
13313
13383
|
]
|
|
13314
13384
|
},
|
|
13315
13385
|
c.key
|
|
13316
13386
|
);
|
|
13317
13387
|
}) }),
|
|
13318
|
-
/* @__PURE__ */ (0,
|
|
13319
|
-
/* @__PURE__ */ (0,
|
|
13320
|
-
/* @__PURE__ */ (0,
|
|
13321
|
-
/* @__PURE__ */ (0,
|
|
13388
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
13389
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
13390
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
|
|
13391
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
|
|
13322
13392
|
"+",
|
|
13323
13393
|
bonusPct,
|
|
13324
13394
|
"% of +",
|
|
@@ -13326,8 +13396,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
13326
13396
|
"%"
|
|
13327
13397
|
] })
|
|
13328
13398
|
] }),
|
|
13329
|
-
/* @__PURE__ */ (0,
|
|
13330
|
-
/* @__PURE__ */ (0,
|
|
13399
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
|
|
13400
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
|
|
13331
13401
|
present.length,
|
|
13332
13402
|
" of 6 channel categories present.",
|
|
13333
13403
|
" ",
|
|
@@ -13339,7 +13409,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
13339
13409
|
}
|
|
13340
13410
|
|
|
13341
13411
|
// src/components/planner/Importance.tsx
|
|
13342
|
-
var
|
|
13412
|
+
var import_jsx_runtime99 = require("react/jsx-runtime");
|
|
13343
13413
|
var IMPORTANCE_LEVELS = [
|
|
13344
13414
|
{ id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
|
|
13345
13415
|
{ id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
|
|
@@ -13369,7 +13439,7 @@ function importanceTokens(id) {
|
|
|
13369
13439
|
function ImportanceTag({ level, showLabel = true, size = "sm", className = "", disabled = false }) {
|
|
13370
13440
|
const lvl = importanceLevel(level);
|
|
13371
13441
|
const t = importanceTokens(level);
|
|
13372
|
-
return /* @__PURE__ */ (0,
|
|
13442
|
+
return /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)(
|
|
13373
13443
|
"span",
|
|
13374
13444
|
{
|
|
13375
13445
|
className: ["fd-imp-tag", size === "md" ? "is-md" : "", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "),
|
|
@@ -13377,16 +13447,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
|
|
|
13377
13447
|
title: lvl.label + " \u2014 " + lvl.description,
|
|
13378
13448
|
"aria-disabled": disabled ? "true" : void 0,
|
|
13379
13449
|
children: [
|
|
13380
|
-
/* @__PURE__ */ (0,
|
|
13381
|
-
showLabel ? lvl.label : /* @__PURE__ */ (0,
|
|
13450
|
+
/* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
|
|
13451
|
+
showLabel ? lvl.label : /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fd-sr", children: lvl.label })
|
|
13382
13452
|
]
|
|
13383
13453
|
}
|
|
13384
13454
|
);
|
|
13385
13455
|
}
|
|
13386
13456
|
|
|
13387
13457
|
// src/components/planner/PreferenceMeter.tsx
|
|
13388
|
-
var
|
|
13389
|
-
var
|
|
13458
|
+
var React69 = __toESM(require("react"), 1);
|
|
13459
|
+
var import_jsx_runtime100 = require("react/jsx-runtime");
|
|
13390
13460
|
function preferenceScore(criteria) {
|
|
13391
13461
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
13392
13462
|
const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
|
|
@@ -13415,8 +13485,8 @@ function PreferenceMeter({
|
|
|
13415
13485
|
className = ""
|
|
13416
13486
|
}) {
|
|
13417
13487
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
13418
|
-
const segments =
|
|
13419
|
-
return /* @__PURE__ */ (0,
|
|
13488
|
+
const segments = React69.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
13489
|
+
return /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
|
|
13420
13490
|
ScoreMeter,
|
|
13421
13491
|
{
|
|
13422
13492
|
score: value,
|
|
@@ -13428,22 +13498,22 @@ function PreferenceMeter({
|
|
|
13428
13498
|
placement,
|
|
13429
13499
|
className,
|
|
13430
13500
|
breakdownLabel: breakdownTitle,
|
|
13431
|
-
breakdown: /* @__PURE__ */ (0,
|
|
13432
|
-
/* @__PURE__ */ (0,
|
|
13433
|
-
/* @__PURE__ */ (0,
|
|
13434
|
-
/* @__PURE__ */ (0,
|
|
13501
|
+
breakdown: /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("div", { className: "fd-prefbreak", children: [
|
|
13502
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("div", { className: "fd-prefbreak-head", children: [
|
|
13503
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)("span", { className: "fd-label-lg", children: breakdownTitle }),
|
|
13504
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
|
|
13435
13505
|
] }),
|
|
13436
|
-
/* @__PURE__ */ (0,
|
|
13506
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
|
|
13437
13507
|
const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
|
|
13438
|
-
return /* @__PURE__ */ (0,
|
|
13439
|
-
/* @__PURE__ */ (0,
|
|
13440
|
-
/* @__PURE__ */ (0,
|
|
13441
|
-
/* @__PURE__ */ (0,
|
|
13442
|
-
c.note ? /* @__PURE__ */ (0,
|
|
13508
|
+
return /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
|
|
13509
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(ImportanceTag, { level: c.importance }),
|
|
13510
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("span", { className: "fd-prefbreak-text", children: [
|
|
13511
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)("span", { className: "fd-prefbreak-label", children: c.label }),
|
|
13512
|
+
c.note ? /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("span", { className: "fd-prefbreak-note", children: c.note }) : null
|
|
13443
13513
|
] }),
|
|
13444
|
-
/* @__PURE__ */ (0,
|
|
13514
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("span", { className: "fd-prefbreak-val fd-tabular", children: [
|
|
13445
13515
|
Math.round(Number(c.earned) || 0),
|
|
13446
|
-
/* @__PURE__ */ (0,
|
|
13516
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)("span", { className: "fd-prefbreak-sep", children: "/" }),
|
|
13447
13517
|
Math.round(c.weight)
|
|
13448
13518
|
] })
|
|
13449
13519
|
] }, c.id);
|
|
@@ -13454,10 +13524,10 @@ function PreferenceMeter({
|
|
|
13454
13524
|
}
|
|
13455
13525
|
|
|
13456
13526
|
// src/components/chat/AgentChatPanel.tsx
|
|
13457
|
-
var
|
|
13527
|
+
var React75 = __toESM(require("react"), 1);
|
|
13458
13528
|
|
|
13459
13529
|
// src/components/chat/chatEngine.ts
|
|
13460
|
-
var
|
|
13530
|
+
var React70 = __toESM(require("react"), 1);
|
|
13461
13531
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
13462
13532
|
var JOB_PENDING = ["queued", "running"];
|
|
13463
13533
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -13502,7 +13572,7 @@ function useChatEngine(opts) {
|
|
|
13502
13572
|
initialMessage,
|
|
13503
13573
|
threadId: threadIdProp,
|
|
13504
13574
|
pollIntervalMs = 1500,
|
|
13505
|
-
|
|
13575
|
+
pendingTimeoutMs = 18e4,
|
|
13506
13576
|
store = safeStore,
|
|
13507
13577
|
onPacket,
|
|
13508
13578
|
onThreadReady,
|
|
@@ -13511,22 +13581,22 @@ function useChatEngine(opts) {
|
|
|
13511
13581
|
onClear,
|
|
13512
13582
|
onFeedback
|
|
13513
13583
|
} = opts || {};
|
|
13514
|
-
const [status, setStatus] =
|
|
13515
|
-
const [threadId, setThreadId] =
|
|
13516
|
-
const [messages, setMessages] =
|
|
13517
|
-
const [queue, setQueue] =
|
|
13518
|
-
const [fatal, setFatal] =
|
|
13519
|
-
const [busy, setBusy] =
|
|
13520
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
13521
|
-
const listRef =
|
|
13522
|
-
const queueRef =
|
|
13523
|
-
const busyRef =
|
|
13524
|
-
const stoppedRef =
|
|
13525
|
-
const abortRef =
|
|
13526
|
-
const serverCount =
|
|
13527
|
-
const threadRef =
|
|
13528
|
-
const mounted =
|
|
13529
|
-
|
|
13584
|
+
const [status, setStatus] = React70.useState("idle");
|
|
13585
|
+
const [threadId, setThreadId] = React70.useState(null);
|
|
13586
|
+
const [messages, setMessages] = React70.useState([]);
|
|
13587
|
+
const [queue, setQueue] = React70.useState([]);
|
|
13588
|
+
const [fatal, setFatal] = React70.useState(null);
|
|
13589
|
+
const [busy, setBusy] = React70.useState(false);
|
|
13590
|
+
const [turnStartedAt, setTurnStartedAt] = React70.useState(null);
|
|
13591
|
+
const listRef = React70.useRef([]);
|
|
13592
|
+
const queueRef = React70.useRef([]);
|
|
13593
|
+
const busyRef = React70.useRef(false);
|
|
13594
|
+
const stoppedRef = React70.useRef(false);
|
|
13595
|
+
const abortRef = React70.useRef(null);
|
|
13596
|
+
const serverCount = React70.useRef(0);
|
|
13597
|
+
const threadRef = React70.useRef(null);
|
|
13598
|
+
const mounted = React70.useRef(true);
|
|
13599
|
+
React70.useEffect(() => {
|
|
13530
13600
|
mounted.current = true;
|
|
13531
13601
|
return () => {
|
|
13532
13602
|
mounted.current = false;
|
|
@@ -13548,14 +13618,21 @@ function useChatEngine(opts) {
|
|
|
13548
13618
|
}
|
|
13549
13619
|
return false;
|
|
13550
13620
|
};
|
|
13551
|
-
const loadThread =
|
|
13621
|
+
const loadThread = React70.useCallback(async (id) => {
|
|
13552
13622
|
const data = await apiAdapter.getThread(id);
|
|
13553
13623
|
const list = [...data && data.messages || []];
|
|
13554
13624
|
serverCount.current = list.length;
|
|
13555
13625
|
commit(list);
|
|
13556
13626
|
return list;
|
|
13557
13627
|
}, [apiAdapter]);
|
|
13558
|
-
|
|
13628
|
+
async function mergeThread() {
|
|
13629
|
+
const data = await apiAdapter.getThread(threadRef.current);
|
|
13630
|
+
const server = data && data.messages || [];
|
|
13631
|
+
const ids = new Set(server.map((m) => m.id));
|
|
13632
|
+
serverCount.current = server.length;
|
|
13633
|
+
commit([...server, ...listRef.current.filter((m) => !ids.has(m.id))]);
|
|
13634
|
+
}
|
|
13635
|
+
React70.useEffect(() => {
|
|
13559
13636
|
if (!apiAdapter) {
|
|
13560
13637
|
setStatus("idle");
|
|
13561
13638
|
setFatal(null);
|
|
@@ -13601,7 +13678,9 @@ function useChatEngine(opts) {
|
|
|
13601
13678
|
setStatus("ready");
|
|
13602
13679
|
onThreadReady && onThreadReady(id);
|
|
13603
13680
|
const stored = store.get(STORAGE_PREFIX + id);
|
|
13681
|
+
const last = [...visibleMessages(listRef.current)].reverse().find((m) => m.role === "assistant");
|
|
13604
13682
|
if (stored) resumeJob(stored);
|
|
13683
|
+
else if (last && last.working && last.jobId) resumeJob(last.jobId, last.id);
|
|
13605
13684
|
else if (initialMessage) send(initialMessage);
|
|
13606
13685
|
} catch (err) {
|
|
13607
13686
|
if (dead) return;
|
|
@@ -13617,8 +13696,8 @@ function useChatEngine(opts) {
|
|
|
13617
13696
|
}, [apiAdapter, contextType, contextId, threadIdProp]);
|
|
13618
13697
|
async function pollJob(jobId, placeholderId) {
|
|
13619
13698
|
store.set(STORAGE_PREFIX + threadRef.current, jobId);
|
|
13620
|
-
|
|
13621
|
-
while (
|
|
13699
|
+
const deadline = Date.now() + pendingTimeoutMs;
|
|
13700
|
+
while (true) {
|
|
13622
13701
|
if (stoppedRef.current) break;
|
|
13623
13702
|
await sleep(pollIntervalMs);
|
|
13624
13703
|
if (!mounted.current) return;
|
|
@@ -13636,7 +13715,15 @@ function useChatEngine(opts) {
|
|
|
13636
13715
|
}
|
|
13637
13716
|
patch(placeholderId, { job });
|
|
13638
13717
|
const bucket2 = jobBucket(job && job.status);
|
|
13639
|
-
if (bucket2 === "pending")
|
|
13718
|
+
if (bucket2 === "pending") {
|
|
13719
|
+
try {
|
|
13720
|
+
await mergeThread();
|
|
13721
|
+
} catch (err) {
|
|
13722
|
+
fail(err);
|
|
13723
|
+
}
|
|
13724
|
+
if (Date.now() >= deadline) break;
|
|
13725
|
+
continue;
|
|
13726
|
+
}
|
|
13640
13727
|
if (bucket2 === "success") {
|
|
13641
13728
|
finishJob(jobId, job);
|
|
13642
13729
|
return;
|
|
@@ -13673,9 +13760,10 @@ function useChatEngine(opts) {
|
|
|
13673
13760
|
patch(placeholderId, { working: false, streaming: false, error: code, retryable: !!retryable, job: job || void 0 });
|
|
13674
13761
|
onError && onError(new Error(code));
|
|
13675
13762
|
}
|
|
13676
|
-
function resumeJob(jobId) {
|
|
13677
|
-
const id = uid("a");
|
|
13678
|
-
|
|
13763
|
+
function resumeJob(jobId, existingId) {
|
|
13764
|
+
const id = existingId || uid("a");
|
|
13765
|
+
if (existingId) patch(id, { working: true, resumed: true });
|
|
13766
|
+
else push({ id, role: "assistant", working: true, jobId, resumed: true });
|
|
13679
13767
|
setBusy(true);
|
|
13680
13768
|
busyRef.current = true;
|
|
13681
13769
|
setTurnStartedAt(Date.now());
|
|
@@ -13768,7 +13856,7 @@ function useChatEngine(opts) {
|
|
|
13768
13856
|
await dispatchTurn(turn);
|
|
13769
13857
|
}
|
|
13770
13858
|
}
|
|
13771
|
-
const send =
|
|
13859
|
+
const send = React70.useCallback((text, attachments) => {
|
|
13772
13860
|
const body = (text || "").trim();
|
|
13773
13861
|
if (!body && !(attachments && attachments.length)) return;
|
|
13774
13862
|
if (status === "disconnected") return;
|
|
@@ -13778,7 +13866,7 @@ function useChatEngine(opts) {
|
|
|
13778
13866
|
stoppedRef.current = false;
|
|
13779
13867
|
drain();
|
|
13780
13868
|
}, [status]);
|
|
13781
|
-
const stop =
|
|
13869
|
+
const stop = React70.useCallback(() => {
|
|
13782
13870
|
stoppedRef.current = true;
|
|
13783
13871
|
const ac = abortRef.current;
|
|
13784
13872
|
if (ac) {
|
|
@@ -13797,11 +13885,11 @@ function useChatEngine(opts) {
|
|
|
13797
13885
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
13798
13886
|
}
|
|
13799
13887
|
}, [apiAdapter]);
|
|
13800
|
-
const removeQueued =
|
|
13888
|
+
const removeQueued = React70.useCallback((id) => {
|
|
13801
13889
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
13802
13890
|
setQueue(queueRef.current.slice());
|
|
13803
13891
|
}, []);
|
|
13804
|
-
const retry =
|
|
13892
|
+
const retry = React70.useCallback(() => {
|
|
13805
13893
|
const list = listRef.current;
|
|
13806
13894
|
let at = -1;
|
|
13807
13895
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -13817,19 +13905,19 @@ function useChatEngine(opts) {
|
|
|
13817
13905
|
setQueue(queueRef.current.slice());
|
|
13818
13906
|
drain();
|
|
13819
13907
|
}, []);
|
|
13820
|
-
const clear =
|
|
13908
|
+
const clear = React70.useCallback(() => {
|
|
13821
13909
|
commit([]);
|
|
13822
13910
|
serverCount.current = 0;
|
|
13823
13911
|
queueRef.current = [];
|
|
13824
13912
|
setQueue([]);
|
|
13825
13913
|
onClear && onClear();
|
|
13826
13914
|
}, [onClear]);
|
|
13827
|
-
const setFeedback =
|
|
13915
|
+
const setFeedback = React70.useCallback((id, value) => {
|
|
13828
13916
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
13829
13917
|
const msg = listRef.current.find((m) => m.id === id);
|
|
13830
13918
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
13831
13919
|
}, [onFeedback]);
|
|
13832
|
-
const reload =
|
|
13920
|
+
const reload = React70.useCallback(async () => {
|
|
13833
13921
|
if (!threadRef.current) return;
|
|
13834
13922
|
setStatus("loading");
|
|
13835
13923
|
try {
|
|
@@ -13867,11 +13955,11 @@ var ChatKit = {
|
|
|
13867
13955
|
};
|
|
13868
13956
|
|
|
13869
13957
|
// src/components/chat/ChatTranscript.tsx
|
|
13870
|
-
var
|
|
13958
|
+
var React72 = __toESM(require("react"), 1);
|
|
13871
13959
|
|
|
13872
13960
|
// src/components/chat/ChatTurn.tsx
|
|
13873
|
-
var
|
|
13874
|
-
var
|
|
13961
|
+
var React71 = __toESM(require("react"), 1);
|
|
13962
|
+
var import_jsx_runtime101 = require("react/jsx-runtime");
|
|
13875
13963
|
function JsonView({ value }) {
|
|
13876
13964
|
let text;
|
|
13877
13965
|
try {
|
|
@@ -13879,67 +13967,67 @@ function JsonView({ value }) {
|
|
|
13879
13967
|
} catch (e) {
|
|
13880
13968
|
text = String(value);
|
|
13881
13969
|
}
|
|
13882
|
-
return /* @__PURE__ */ (0,
|
|
13970
|
+
return /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
|
|
13883
13971
|
}
|
|
13884
13972
|
function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
13885
13973
|
if (!packet) return null;
|
|
13886
13974
|
const s = schema || {};
|
|
13887
13975
|
const invalid = packet.valid === false;
|
|
13888
13976
|
const title = s.heading || packet.type;
|
|
13889
|
-
return /* @__PURE__ */ (0,
|
|
13890
|
-
/* @__PURE__ */ (0,
|
|
13891
|
-
/* @__PURE__ */ (0,
|
|
13892
|
-
/* @__PURE__ */ (0,
|
|
13893
|
-
packet.repaired ? /* @__PURE__ */ (0,
|
|
13894
|
-
invalid ? /* @__PURE__ */ (0,
|
|
13977
|
+
return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
|
|
13978
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("header", { className: "fdc-packet-head", children: [
|
|
13979
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
|
|
13980
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
|
|
13981
|
+
packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
|
|
13982
|
+
invalid ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
|
|
13895
13983
|
] }),
|
|
13896
|
-
invalid ? /* @__PURE__ */ (0,
|
|
13897
|
-
/* @__PURE__ */ (0,
|
|
13898
|
-
/* @__PURE__ */ (0,
|
|
13899
|
-
] }) : /* @__PURE__ */ (0,
|
|
13900
|
-
!invalid && onApply ? /* @__PURE__ */ (0,
|
|
13901
|
-
packet.repaired ? /* @__PURE__ */ (0,
|
|
13902
|
-
/* @__PURE__ */ (0,
|
|
13903
|
-
/* @__PURE__ */ (0,
|
|
13984
|
+
invalid ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-packet-alert", role: "alert", children: [
|
|
13985
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
13986
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
|
|
13987
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(JsonView, { value: packet.payload }) }),
|
|
13988
|
+
!invalid && onApply && s.apply !== false ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("footer", { className: "fdc-packet-foot", children: [
|
|
13989
|
+
packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", {}),
|
|
13990
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
|
|
13991
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
|
|
13904
13992
|
applied ? "Applied" : s.applyLabel || "Apply"
|
|
13905
13993
|
] })
|
|
13906
13994
|
] }) : null
|
|
13907
13995
|
] });
|
|
13908
13996
|
}
|
|
13909
13997
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
13910
|
-
const [open2, setOpen] =
|
|
13998
|
+
const [open2, setOpen] = React71.useState(defaultOpen);
|
|
13911
13999
|
if (!text) return null;
|
|
13912
|
-
return /* @__PURE__ */ (0,
|
|
13913
|
-
/* @__PURE__ */ (0,
|
|
13914
|
-
/* @__PURE__ */ (0,
|
|
13915
|
-
/* @__PURE__ */ (0,
|
|
13916
|
-
streaming ? /* @__PURE__ */ (0,
|
|
13917
|
-
/* @__PURE__ */ (0,
|
|
13918
|
-
/* @__PURE__ */ (0,
|
|
13919
|
-
/* @__PURE__ */ (0,
|
|
14000
|
+
return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
|
|
14001
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
14002
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-brain", "aria-hidden": "true" }),
|
|
14003
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
|
|
14004
|
+
streaming ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
14005
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", {}),
|
|
14006
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", {}),
|
|
14007
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", {})
|
|
13920
14008
|
] }) : null,
|
|
13921
|
-
/* @__PURE__ */ (0,
|
|
14009
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
|
|
13922
14010
|
] }),
|
|
13923
|
-
open2 ? /* @__PURE__ */ (0,
|
|
14011
|
+
open2 ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "fdc-think-body", children: text }) : null
|
|
13924
14012
|
] });
|
|
13925
14013
|
}
|
|
13926
14014
|
function Citations({ items = [], onOpen }) {
|
|
13927
|
-
const [open2, setOpen] =
|
|
14015
|
+
const [open2, setOpen] = React71.useState(false);
|
|
13928
14016
|
if (!items.length) return null;
|
|
13929
|
-
return /* @__PURE__ */ (0,
|
|
13930
|
-
/* @__PURE__ */ (0,
|
|
13931
|
-
/* @__PURE__ */ (0,
|
|
13932
|
-
/* @__PURE__ */ (0,
|
|
14017
|
+
return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-cites", children: [
|
|
14018
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
14019
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
|
|
14020
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("span", { children: [
|
|
13933
14021
|
items.length,
|
|
13934
14022
|
" source",
|
|
13935
14023
|
items.length === 1 ? "" : "s"
|
|
13936
14024
|
] }),
|
|
13937
|
-
/* @__PURE__ */ (0,
|
|
14025
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
|
|
13938
14026
|
] }),
|
|
13939
|
-
open2 ? /* @__PURE__ */ (0,
|
|
13940
|
-
/* @__PURE__ */ (0,
|
|
13941
|
-
c.url ? /* @__PURE__ */ (0,
|
|
13942
|
-
c.detail ? /* @__PURE__ */ (0,
|
|
14027
|
+
open2 ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("li", { children: [
|
|
14028
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
|
|
14029
|
+
c.url ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { children: c.title || "Source" }),
|
|
14030
|
+
c.detail ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-cite-detail", children: c.detail }) : null
|
|
13943
14031
|
] }, c.id || i)) }) : null
|
|
13944
14032
|
] });
|
|
13945
14033
|
}
|
|
@@ -13950,29 +14038,29 @@ function clampText(text, max) {
|
|
|
13950
14038
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
13951
14039
|
}
|
|
13952
14040
|
function MessageBody({ message: m, ctx }) {
|
|
13953
|
-
const [expanded, setExpanded] =
|
|
14041
|
+
const [expanded, setExpanded] = React71.useState(false);
|
|
13954
14042
|
const isUser = m.role === "user";
|
|
13955
14043
|
const raw = m.text || "";
|
|
13956
14044
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
13957
14045
|
const body = clamped != null ? clamped : raw;
|
|
13958
14046
|
const showMd = ctx.markdown && !isUser;
|
|
13959
|
-
return /* @__PURE__ */ (0,
|
|
13960
|
-
m.thinking && ctx.showThinking ? /* @__PURE__ */ (0,
|
|
13961
|
-
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0,
|
|
13962
|
-
body ? /* @__PURE__ */ (0,
|
|
13963
|
-
showMd ? /* @__PURE__ */ (0,
|
|
13964
|
-
m.streaming ? /* @__PURE__ */ (0,
|
|
14047
|
+
return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-body", children: [
|
|
14048
|
+
m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
|
|
14049
|
+
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
|
|
14050
|
+
body ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
|
|
14051
|
+
showMd ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "fdc-plain", children: body }),
|
|
14052
|
+
m.streaming ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
|
|
13965
14053
|
] }) : null,
|
|
13966
|
-
clamped != null ? /* @__PURE__ */ (0,
|
|
13967
|
-
/* @__PURE__ */ (0,
|
|
14054
|
+
clamped != null ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
|
|
14055
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
|
|
13968
14056
|
"Show more",
|
|
13969
|
-
/* @__PURE__ */ (0,
|
|
13970
|
-
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0,
|
|
13971
|
-
/* @__PURE__ */ (0,
|
|
14057
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
|
|
14058
|
+
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
|
|
14059
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
|
|
13972
14060
|
"Show less"
|
|
13973
14061
|
] }) : null,
|
|
13974
|
-
m.attachments && m.attachments.length ? /* @__PURE__ */ (0,
|
|
13975
|
-
m.packet ? /* @__PURE__ */ (0,
|
|
14062
|
+
m.attachments && m.attachments.length ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
|
|
14063
|
+
m.packet ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
13976
14064
|
PacketCard,
|
|
13977
14065
|
{
|
|
13978
14066
|
packet: m.packet,
|
|
@@ -13982,35 +14070,35 @@ function MessageBody({ message: m, ctx }) {
|
|
|
13982
14070
|
applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
|
|
13983
14071
|
}
|
|
13984
14072
|
) : null,
|
|
13985
|
-
m.citations && m.citations.length ? /* @__PURE__ */ (0,
|
|
13986
|
-
m.working ? /* @__PURE__ */ (0,
|
|
13987
|
-
/* @__PURE__ */ (0,
|
|
13988
|
-
/* @__PURE__ */ (0,
|
|
13989
|
-
/* @__PURE__ */ (0,
|
|
13990
|
-
/* @__PURE__ */ (0,
|
|
14073
|
+
m.citations && m.citations.length ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
|
|
14074
|
+
m.working ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-working", role: "status", children: [
|
|
14075
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
14076
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", {}),
|
|
14077
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", {}),
|
|
14078
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", {})
|
|
13991
14079
|
] }),
|
|
13992
|
-
/* @__PURE__ */ (0,
|
|
14080
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("span", { className: "fdc-working-label", children: [
|
|
13993
14081
|
m.resumed ? "Resuming" : "Working",
|
|
13994
|
-
m.job && m.job.status ? /* @__PURE__ */ (0,
|
|
14082
|
+
m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("span", { className: "fdc-working-job", children: [
|
|
13995
14083
|
" \xB7 ",
|
|
13996
14084
|
m.job.status
|
|
13997
14085
|
] }) : null,
|
|
13998
|
-
m.job && m.job.detail ? /* @__PURE__ */ (0,
|
|
14086
|
+
m.job && m.job.detail ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("span", { className: "fdc-working-job", children: [
|
|
13999
14087
|
" \xB7 ",
|
|
14000
14088
|
m.job.detail
|
|
14001
14089
|
] }) : null
|
|
14002
14090
|
] }),
|
|
14003
|
-
m.jobId ? /* @__PURE__ */ (0,
|
|
14091
|
+
m.jobId ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
|
|
14004
14092
|
] }) : null,
|
|
14005
|
-
m.stopped ? /* @__PURE__ */ (0,
|
|
14006
|
-
/* @__PURE__ */ (0,
|
|
14093
|
+
m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-stopped", children: [
|
|
14094
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
14007
14095
|
"Stopped"
|
|
14008
14096
|
] }) : null,
|
|
14009
|
-
m.error ? /* @__PURE__ */ (0,
|
|
14010
|
-
/* @__PURE__ */ (0,
|
|
14011
|
-
/* @__PURE__ */ (0,
|
|
14012
|
-
m.retryable && ctx.onRetry ? /* @__PURE__ */ (0,
|
|
14013
|
-
/* @__PURE__ */ (0,
|
|
14097
|
+
m.error ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-error", role: "alert", children: [
|
|
14098
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
14099
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
|
|
14100
|
+
m.retryable && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
|
|
14101
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
14014
14102
|
"Retry"
|
|
14015
14103
|
] }) : null
|
|
14016
14104
|
] }) : null
|
|
@@ -14023,16 +14111,16 @@ function RunActions({ group, ctx }) {
|
|
|
14023
14111
|
const isAssistant = group.role === "assistant";
|
|
14024
14112
|
const fb = last.feedback;
|
|
14025
14113
|
if (!ctx.messageActions) return null;
|
|
14026
|
-
return /* @__PURE__ */ (0,
|
|
14027
|
-
/* @__PURE__ */ (0,
|
|
14028
|
-
/* @__PURE__ */ (0,
|
|
14029
|
-
/* @__PURE__ */ (0,
|
|
14114
|
+
return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
|
|
14115
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
|
|
14116
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
|
|
14117
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
|
|
14030
14118
|
] }),
|
|
14031
|
-
isAssistant && ctx.onRetry ? /* @__PURE__ */ (0,
|
|
14032
|
-
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0,
|
|
14033
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0,
|
|
14034
|
-
/* @__PURE__ */ (0,
|
|
14035
|
-
/* @__PURE__ */ (0,
|
|
14119
|
+
isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
14120
|
+
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
14121
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)(React71.Fragment, { children: [
|
|
14122
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.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_runtime101.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
14123
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.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_runtime101.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
14036
14124
|
] }) : null,
|
|
14037
14125
|
ctx.extraActions ? ctx.extraActions(group) : null
|
|
14038
14126
|
] });
|
|
@@ -14042,22 +14130,22 @@ function ChatTurn({ group, ctx }) {
|
|
|
14042
14130
|
const name = isUser ? ctx.userName : group.author || ctx.assistantName;
|
|
14043
14131
|
const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
|
|
14044
14132
|
const stamp = group.messages[0].timestamp;
|
|
14045
|
-
return /* @__PURE__ */ (0,
|
|
14046
|
-
/* @__PURE__ */ (0,
|
|
14047
|
-
ctx.showAvatars ? /* @__PURE__ */ (0,
|
|
14048
|
-
/* @__PURE__ */ (0,
|
|
14049
|
-
stamp ? /* @__PURE__ */ (0,
|
|
14050
|
-
group.messages.some((m) => m.model) ? /* @__PURE__ */ (0,
|
|
14133
|
+
return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
|
|
14134
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-turn-head", children: [
|
|
14135
|
+
ctx.showAvatars ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
|
|
14136
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-who", children: name }),
|
|
14137
|
+
stamp ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(RelativeTime, { className: "fdc-when", value: stamp }) : null,
|
|
14138
|
+
group.messages.some((m) => m.model) ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
|
|
14051
14139
|
] }),
|
|
14052
|
-
/* @__PURE__ */ (0,
|
|
14053
|
-
group.messages.map((m) => /* @__PURE__ */ (0,
|
|
14054
|
-
/* @__PURE__ */ (0,
|
|
14140
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-turn-body", children: [
|
|
14141
|
+
group.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(MessageBody, { message: m, ctx }) }, m.id)),
|
|
14142
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)(RunActions, { group, ctx })
|
|
14055
14143
|
] })
|
|
14056
14144
|
] });
|
|
14057
14145
|
}
|
|
14058
14146
|
|
|
14059
14147
|
// src/components/chat/ChatTranscript.tsx
|
|
14060
|
-
var
|
|
14148
|
+
var import_jsx_runtime102 = require("react/jsx-runtime");
|
|
14061
14149
|
var GROUP_WINDOW = 6e4;
|
|
14062
14150
|
var STICK_PX = 100;
|
|
14063
14151
|
function groupMessages(list) {
|
|
@@ -14090,25 +14178,25 @@ function dayLabel(key) {
|
|
|
14090
14178
|
}
|
|
14091
14179
|
function Suggestions({ items = [], onPick }) {
|
|
14092
14180
|
if (!items.length) return null;
|
|
14093
|
-
return /* @__PURE__ */ (0,
|
|
14181
|
+
return /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
|
|
14094
14182
|
const it = typeof s === "string" ? { label: s, text: s } : s;
|
|
14095
|
-
return /* @__PURE__ */ (0,
|
|
14096
|
-
it.icon ? /* @__PURE__ */ (0,
|
|
14097
|
-
/* @__PURE__ */ (0,
|
|
14098
|
-
/* @__PURE__ */ (0,
|
|
14099
|
-
it.description ? /* @__PURE__ */ (0,
|
|
14183
|
+
return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
|
|
14184
|
+
it.icon ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
|
|
14185
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("span", { className: "fdc-suggest-text", children: [
|
|
14186
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { className: "fdc-suggest-label", children: it.label }),
|
|
14187
|
+
it.description ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { className: "fdc-suggest-desc", children: it.description }) : null
|
|
14100
14188
|
] }),
|
|
14101
|
-
/* @__PURE__ */ (0,
|
|
14189
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
|
|
14102
14190
|
] }, it.id || i);
|
|
14103
14191
|
}) });
|
|
14104
14192
|
}
|
|
14105
14193
|
function LoadingTurns() {
|
|
14106
|
-
return /* @__PURE__ */ (0,
|
|
14107
|
-
/* @__PURE__ */ (0,
|
|
14108
|
-
/* @__PURE__ */ (0,
|
|
14109
|
-
/* @__PURE__ */ (0,
|
|
14110
|
-
/* @__PURE__ */ (0,
|
|
14111
|
-
/* @__PURE__ */ (0,
|
|
14194
|
+
return /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-skel-turn", children: [
|
|
14195
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
|
|
14196
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-skel-lines", children: [
|
|
14197
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
|
|
14198
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
|
|
14199
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
|
|
14112
14200
|
] })
|
|
14113
14201
|
] }, i)) });
|
|
14114
14202
|
}
|
|
@@ -14125,10 +14213,10 @@ function ChatTranscript({
|
|
|
14125
14213
|
renderEmpty,
|
|
14126
14214
|
className = ""
|
|
14127
14215
|
}) {
|
|
14128
|
-
const scroller =
|
|
14129
|
-
const stick =
|
|
14130
|
-
const [pill, setPill] =
|
|
14131
|
-
const seen =
|
|
14216
|
+
const scroller = React72.useRef(null);
|
|
14217
|
+
const stick = React72.useRef(true);
|
|
14218
|
+
const [pill, setPill] = React72.useState(0);
|
|
14219
|
+
const seen = React72.useRef(0);
|
|
14132
14220
|
const toBottom = (smooth) => {
|
|
14133
14221
|
const el = scroller.current;
|
|
14134
14222
|
if (!el) return;
|
|
@@ -14147,7 +14235,7 @@ function ChatTranscript({
|
|
|
14147
14235
|
seen.current = messages.length;
|
|
14148
14236
|
}
|
|
14149
14237
|
};
|
|
14150
|
-
|
|
14238
|
+
React72.useLayoutEffect(() => {
|
|
14151
14239
|
const el = scroller.current;
|
|
14152
14240
|
if (!el) return;
|
|
14153
14241
|
if (stick.current) {
|
|
@@ -14155,7 +14243,7 @@ function ChatTranscript({
|
|
|
14155
14243
|
seen.current = messages.length;
|
|
14156
14244
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
14157
14245
|
}, [messages]);
|
|
14158
|
-
|
|
14246
|
+
React72.useEffect(() => {
|
|
14159
14247
|
const el = scroller.current;
|
|
14160
14248
|
const inner = el && el.firstChild;
|
|
14161
14249
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -14165,38 +14253,38 @@ function ChatTranscript({
|
|
|
14165
14253
|
ro.observe(inner);
|
|
14166
14254
|
return () => ro.disconnect();
|
|
14167
14255
|
}, []);
|
|
14168
|
-
const groups =
|
|
14256
|
+
const groups = React72.useMemo(() => groupMessages(messages), [messages]);
|
|
14169
14257
|
const empty = !messages.length && status === "ready";
|
|
14170
|
-
return /* @__PURE__ */ (0,
|
|
14171
|
-
/* @__PURE__ */ (0,
|
|
14172
|
-
status === "loading" || status === "resolving" ? /* @__PURE__ */ (0,
|
|
14173
|
-
status === "disconnected" ? /* @__PURE__ */ (0,
|
|
14174
|
-
/* @__PURE__ */ (0,
|
|
14175
|
-
/* @__PURE__ */ (0,
|
|
14176
|
-
/* @__PURE__ */ (0,
|
|
14177
|
-
ctx.onReconnect ? /* @__PURE__ */ (0,
|
|
14178
|
-
/* @__PURE__ */ (0,
|
|
14258
|
+
return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
14259
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
14260
|
+
status === "loading" || status === "resolving" ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(LoadingTurns, {}) : null,
|
|
14261
|
+
status === "disconnected" ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-dead", children: [
|
|
14262
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
|
|
14263
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
|
|
14264
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("p", { className: "fdc-dead-body", children: fatal === "chat_unavailable" ? "The service reported chat_unavailable. Nothing you type will be lost \u2014 reopen the panel once it\u2019s back." : "The thread couldn\u2019t be resolved" + (fatal ? " (" + fatal + ")" : "") + ". The composer stays disabled until it resolves." }),
|
|
14265
|
+
ctx.onReconnect ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
|
|
14266
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
14179
14267
|
"Try again"
|
|
14180
14268
|
] }) : null
|
|
14181
14269
|
] }) : null,
|
|
14182
|
-
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0,
|
|
14183
|
-
/* @__PURE__ */ (0,
|
|
14184
|
-
/* @__PURE__ */ (0,
|
|
14185
|
-
emptyDescription ? /* @__PURE__ */ (0,
|
|
14186
|
-
/* @__PURE__ */ (0,
|
|
14270
|
+
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-empty", children: [
|
|
14271
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
|
|
14272
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("h3", { className: "fdc-empty-title", children: emptyTitle }),
|
|
14273
|
+
emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
|
|
14274
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)(Suggestions, { items: suggestions, onPick })
|
|
14187
14275
|
] }) : null,
|
|
14188
14276
|
groups.map((g, i) => {
|
|
14189
14277
|
const prev = groups[i - 1];
|
|
14190
14278
|
const k = dayKey(g.messages[0].timestamp);
|
|
14191
14279
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
14192
|
-
return /* @__PURE__ */ (0,
|
|
14193
|
-
showDay ? /* @__PURE__ */ (0,
|
|
14194
|
-
/* @__PURE__ */ (0,
|
|
14280
|
+
return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)(React72.Fragment, { children: [
|
|
14281
|
+
showDay ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { children: dayLabel(k) }) }) : null,
|
|
14282
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)(ChatTurn, { group: g, ctx })
|
|
14195
14283
|
] }, g.key || i);
|
|
14196
14284
|
})
|
|
14197
14285
|
] }),
|
|
14198
|
-
pill ? /* @__PURE__ */ (0,
|
|
14199
|
-
/* @__PURE__ */ (0,
|
|
14286
|
+
pill ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
|
|
14287
|
+
/* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
|
|
14200
14288
|
pill,
|
|
14201
14289
|
" new message",
|
|
14202
14290
|
pill === 1 ? "" : "s"
|
|
@@ -14206,8 +14294,8 @@ function ChatTranscript({
|
|
|
14206
14294
|
var TranscriptKit = { groupMessages };
|
|
14207
14295
|
|
|
14208
14296
|
// src/components/chat/ChatComposer.tsx
|
|
14209
|
-
var
|
|
14210
|
-
var
|
|
14297
|
+
var React73 = __toESM(require("react"), 1);
|
|
14298
|
+
var import_jsx_runtime103 = require("react/jsx-runtime");
|
|
14211
14299
|
function ChatComposer({
|
|
14212
14300
|
onSubmit,
|
|
14213
14301
|
onStop,
|
|
@@ -14234,17 +14322,17 @@ function ChatComposer({
|
|
|
14234
14322
|
onReject,
|
|
14235
14323
|
onOpenAttachment
|
|
14236
14324
|
}) {
|
|
14237
|
-
const [text, setText] =
|
|
14238
|
-
const [trigger, setTrigger] =
|
|
14239
|
-
const [mentionItems, setMentionItems] =
|
|
14240
|
-
const [listening, setListening] =
|
|
14241
|
-
const [notice, setNotice] =
|
|
14242
|
-
const editor =
|
|
14243
|
-
const wrap =
|
|
14244
|
-
const stopVoice =
|
|
14325
|
+
const [text, setText] = React73.useState(draft || "");
|
|
14326
|
+
const [trigger, setTrigger] = React73.useState(null);
|
|
14327
|
+
const [mentionItems, setMentionItems] = React73.useState([]);
|
|
14328
|
+
const [listening, setListening] = React73.useState(false);
|
|
14329
|
+
const [notice, setNotice] = React73.useState(null);
|
|
14330
|
+
const editor = React73.useRef(null);
|
|
14331
|
+
const wrap = React73.useRef(null);
|
|
14332
|
+
const stopVoice = React73.useRef(null);
|
|
14245
14333
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
14246
14334
|
} });
|
|
14247
|
-
|
|
14335
|
+
React73.useEffect(() => {
|
|
14248
14336
|
if (draft != null && draft !== text) setText(draft);
|
|
14249
14337
|
}, [draft]);
|
|
14250
14338
|
const change = (v) => {
|
|
@@ -14280,7 +14368,7 @@ function ChatComposer({
|
|
|
14280
14368
|
e.preventDefault();
|
|
14281
14369
|
staged.add(found.files);
|
|
14282
14370
|
};
|
|
14283
|
-
|
|
14371
|
+
React73.useEffect(() => {
|
|
14284
14372
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
14285
14373
|
setMentionItems([]);
|
|
14286
14374
|
return;
|
|
@@ -14298,7 +14386,7 @@ function ChatComposer({
|
|
|
14298
14386
|
const q = (trigger.query || "").toLowerCase();
|
|
14299
14387
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
14300
14388
|
}, [trigger, mentionSources]);
|
|
14301
|
-
const slashItems =
|
|
14389
|
+
const slashItems = React73.useMemo(() => {
|
|
14302
14390
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
14303
14391
|
const q = (trigger.query || "").toLowerCase();
|
|
14304
14392
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -14312,7 +14400,7 @@ function ChatComposer({
|
|
|
14312
14400
|
description: it.description,
|
|
14313
14401
|
icon: it.icon,
|
|
14314
14402
|
meta: mention.meta,
|
|
14315
|
-
shortcut: slash.shortcut ? /* @__PURE__ */ (0,
|
|
14403
|
+
shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
|
|
14316
14404
|
onSelect: () => {
|
|
14317
14405
|
const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
|
|
14318
14406
|
editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
|
|
@@ -14371,14 +14459,14 @@ function ChatComposer({
|
|
|
14371
14459
|
stopVoice.current = typeof res === "function" ? res : () => {
|
|
14372
14460
|
};
|
|
14373
14461
|
};
|
|
14374
|
-
return /* @__PURE__ */ (0,
|
|
14375
|
-
queue.length ? /* @__PURE__ */ (0,
|
|
14376
|
-
/* @__PURE__ */ (0,
|
|
14377
|
-
/* @__PURE__ */ (0,
|
|
14378
|
-
onRemoveQueued ? /* @__PURE__ */ (0,
|
|
14462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
|
|
14463
|
+
queue.length ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: "fdc-queue-row", children: [
|
|
14464
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
|
|
14465
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { className: "fdc-queue-text", title: truncationTitle(q.text || (q.attachments ? q.attachments.length + " file(s)" : "")), children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
|
|
14466
|
+
onRemoveQueued ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
14379
14467
|
] }, q.id)) }) : null,
|
|
14380
14468
|
sessionBar,
|
|
14381
|
-
/* @__PURE__ */ (0,
|
|
14469
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)(
|
|
14382
14470
|
Dropzone,
|
|
14383
14471
|
{
|
|
14384
14472
|
className: "fdc-field",
|
|
@@ -14392,9 +14480,9 @@ function ChatComposer({
|
|
|
14392
14480
|
disabled: !fileUploadHandler || disabled,
|
|
14393
14481
|
label: "Drop to attach",
|
|
14394
14482
|
hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
|
|
14395
|
-
children: /* @__PURE__ */ (0,
|
|
14396
|
-
staged.items.length ? /* @__PURE__ */ (0,
|
|
14397
|
-
/* @__PURE__ */ (0,
|
|
14483
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { ref: wrap, className: "fdc-field-inner", children: [
|
|
14484
|
+
staged.items.length ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("div", { className: "fdc-staged", children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
|
|
14485
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)(
|
|
14398
14486
|
MarkdownEditor,
|
|
14399
14487
|
{
|
|
14400
14488
|
ref: editor,
|
|
@@ -14413,33 +14501,33 @@ function ChatComposer({
|
|
|
14413
14501
|
ariaLabel: "Message"
|
|
14414
14502
|
}
|
|
14415
14503
|
),
|
|
14416
|
-
/* @__PURE__ */ (0,
|
|
14417
|
-
fileUploadHandler ? /* @__PURE__ */ (0,
|
|
14418
|
-
voiceHandler ? /* @__PURE__ */ (0,
|
|
14504
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: "fdc-tools", children: [
|
|
14505
|
+
fileUploadHandler ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
|
|
14506
|
+
voiceHandler ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
|
|
14419
14507
|
toolbarExtras,
|
|
14420
|
-
/* @__PURE__ */ (0,
|
|
14421
|
-
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0,
|
|
14508
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { className: "fdc-tools-gap" }),
|
|
14509
|
+
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
|
|
14422
14510
|
text.length,
|
|
14423
14511
|
"/",
|
|
14424
14512
|
maxLength
|
|
14425
14513
|
] }) : null,
|
|
14426
|
-
busy ? /* @__PURE__ */ (0,
|
|
14427
|
-
/* @__PURE__ */ (0,
|
|
14428
|
-
/* @__PURE__ */ (0,
|
|
14429
|
-
] }) : /* @__PURE__ */ (0,
|
|
14430
|
-
/* @__PURE__ */ (0,
|
|
14431
|
-
/* @__PURE__ */ (0,
|
|
14514
|
+
busy ? /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
|
|
14515
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
14516
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { children: "Stop" })
|
|
14517
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
|
|
14518
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
|
|
14519
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { className: "fdc-send-label", children: "Send" })
|
|
14432
14520
|
] })
|
|
14433
14521
|
] })
|
|
14434
14522
|
] })
|
|
14435
14523
|
}
|
|
14436
14524
|
),
|
|
14437
|
-
notice ? /* @__PURE__ */ (0,
|
|
14438
|
-
/* @__PURE__ */ (0,
|
|
14525
|
+
notice ? /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: "fdc-notice", role: "status", children: [
|
|
14526
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
14439
14527
|
notice
|
|
14440
14528
|
] }) : null,
|
|
14441
|
-
hint && !notice ? /* @__PURE__ */ (0,
|
|
14442
|
-
/* @__PURE__ */ (0,
|
|
14529
|
+
hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("div", { className: "fdc-hint", children: hint }) : null,
|
|
14530
|
+
/* @__PURE__ */ (0, import_jsx_runtime103.jsx)(
|
|
14443
14531
|
Popover,
|
|
14444
14532
|
{
|
|
14445
14533
|
open: menuOpen,
|
|
@@ -14453,12 +14541,12 @@ function ChatComposer({
|
|
|
14453
14541
|
returnFocus: false,
|
|
14454
14542
|
closeOnOutside: true,
|
|
14455
14543
|
label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
|
|
14456
|
-
children: /* @__PURE__ */ (0,
|
|
14544
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(
|
|
14457
14545
|
Menu,
|
|
14458
14546
|
{
|
|
14459
14547
|
items: menuItems,
|
|
14460
14548
|
autoFocus: false,
|
|
14461
|
-
header: /* @__PURE__ */ (0,
|
|
14549
|
+
header: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
|
|
14462
14550
|
onClose: () => setTrigger(null)
|
|
14463
14551
|
}
|
|
14464
14552
|
)
|
|
@@ -14468,12 +14556,12 @@ function ChatComposer({
|
|
|
14468
14556
|
}
|
|
14469
14557
|
|
|
14470
14558
|
// src/components/chat/ChatSessionBar.tsx
|
|
14471
|
-
var
|
|
14472
|
-
var
|
|
14559
|
+
var React74 = __toESM(require("react"), 1);
|
|
14560
|
+
var import_jsx_runtime104 = require("react/jsx-runtime");
|
|
14473
14561
|
var compact2 = meterFormats.compact;
|
|
14474
14562
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
14475
|
-
const [open2, setOpen] =
|
|
14476
|
-
const anchor =
|
|
14563
|
+
const [open2, setOpen] = React74.useState(false);
|
|
14564
|
+
const anchor = React74.useRef(null);
|
|
14477
14565
|
const stats = sessionStats || null;
|
|
14478
14566
|
const cu = contextUsage || null;
|
|
14479
14567
|
const limits = usageLimits || null;
|
|
@@ -14488,9 +14576,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
14488
14576
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
14489
14577
|
if (cu) bits.push(pct + "% context");
|
|
14490
14578
|
const expandable = !!(cu || limits);
|
|
14491
|
-
return /* @__PURE__ */ (0,
|
|
14492
|
-
/* @__PURE__ */ (0,
|
|
14493
|
-
/* @__PURE__ */ (0,
|
|
14579
|
+
return /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)(React74.Fragment, { children: [
|
|
14580
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { className: "fdc-bar", children: [
|
|
14581
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsxs)(
|
|
14494
14582
|
"button",
|
|
14495
14583
|
{
|
|
14496
14584
|
type: "button",
|
|
@@ -14501,15 +14589,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
14501
14589
|
"aria-expanded": expandable ? open2 : void 0,
|
|
14502
14590
|
"aria-label": expandable ? "Usage details" : void 0,
|
|
14503
14591
|
children: [
|
|
14504
|
-
cu ? /* @__PURE__ */ (0,
|
|
14505
|
-
/* @__PURE__ */ (0,
|
|
14506
|
-
expandable ? /* @__PURE__ */ (0,
|
|
14592
|
+
cu ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
|
|
14593
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
|
|
14594
|
+
expandable ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
|
|
14507
14595
|
]
|
|
14508
14596
|
}
|
|
14509
14597
|
),
|
|
14510
14598
|
extras
|
|
14511
14599
|
] }),
|
|
14512
|
-
/* @__PURE__ */ (0,
|
|
14600
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
|
|
14513
14601
|
Popover,
|
|
14514
14602
|
{
|
|
14515
14603
|
open: open2,
|
|
@@ -14520,15 +14608,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
14520
14608
|
maxHeight: 460,
|
|
14521
14609
|
padded: true,
|
|
14522
14610
|
label: "Usage",
|
|
14523
|
-
footer: onClear ? /* @__PURE__ */ (0,
|
|
14611
|
+
footer: onClear ? /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
|
|
14524
14612
|
setOpen(false);
|
|
14525
14613
|
onClear();
|
|
14526
14614
|
}, children: [
|
|
14527
|
-
/* @__PURE__ */ (0,
|
|
14615
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
|
|
14528
14616
|
"Clear conversation"
|
|
14529
14617
|
] }) : void 0,
|
|
14530
|
-
children: /* @__PURE__ */ (0,
|
|
14531
|
-
cu ? /* @__PURE__ */ (0,
|
|
14618
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { className: "fdc-usage", children: [
|
|
14619
|
+
cu ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
|
|
14532
14620
|
SegmentedMeter,
|
|
14533
14621
|
{
|
|
14534
14622
|
total,
|
|
@@ -14540,9 +14628,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
14540
14628
|
remainderLabel: "Free"
|
|
14541
14629
|
}
|
|
14542
14630
|
) }) : null,
|
|
14543
|
-
limits && limits.length ? /* @__PURE__ */ (0,
|
|
14544
|
-
/* @__PURE__ */ (0,
|
|
14545
|
-
/* @__PURE__ */ (0,
|
|
14631
|
+
limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("section", { className: "fdc-usage-sec", children: [
|
|
14632
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
|
|
14633
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
|
|
14546
14634
|
QuotaRow,
|
|
14547
14635
|
{
|
|
14548
14636
|
label: l.label,
|
|
@@ -14552,25 +14640,25 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
14552
14640
|
l.id
|
|
14553
14641
|
)) })
|
|
14554
14642
|
] }) : null,
|
|
14555
|
-
stats ? /* @__PURE__ */ (0,
|
|
14556
|
-
stats.elapsedMs ? /* @__PURE__ */ (0,
|
|
14557
|
-
/* @__PURE__ */ (0,
|
|
14558
|
-
/* @__PURE__ */ (0,
|
|
14643
|
+
stats ? /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
|
|
14644
|
+
stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { children: [
|
|
14645
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { children: "Session" }),
|
|
14646
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
|
|
14559
14647
|
] }) : null,
|
|
14560
|
-
stats.tokens ? /* @__PURE__ */ (0,
|
|
14561
|
-
/* @__PURE__ */ (0,
|
|
14562
|
-
/* @__PURE__ */ (0,
|
|
14648
|
+
stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { children: [
|
|
14649
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { children: "Tokens" }),
|
|
14650
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
|
|
14563
14651
|
] }) : null,
|
|
14564
|
-
stats.costUsd != null ? /* @__PURE__ */ (0,
|
|
14565
|
-
/* @__PURE__ */ (0,
|
|
14566
|
-
/* @__PURE__ */ (0,
|
|
14652
|
+
stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { children: [
|
|
14653
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { children: "Cost" }),
|
|
14654
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("b", { className: "fd-tabular", children: [
|
|
14567
14655
|
"$",
|
|
14568
14656
|
Number(stats.costUsd).toFixed(3)
|
|
14569
14657
|
] })
|
|
14570
14658
|
] }) : null,
|
|
14571
|
-
stats.turns ? /* @__PURE__ */ (0,
|
|
14572
|
-
/* @__PURE__ */ (0,
|
|
14573
|
-
/* @__PURE__ */ (0,
|
|
14659
|
+
stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { children: [
|
|
14660
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { children: "Turns" }),
|
|
14661
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("b", { className: "fd-tabular", children: stats.turns })
|
|
14574
14662
|
] }) : null
|
|
14575
14663
|
] }) : null
|
|
14576
14664
|
] })
|
|
@@ -14609,7 +14697,7 @@ function ModelControls({
|
|
|
14609
14697
|
disabled: m.disabled,
|
|
14610
14698
|
checked: m.id === (current2 && current2.id),
|
|
14611
14699
|
meta: m.meta,
|
|
14612
|
-
shortcut: m.shortcut ? /* @__PURE__ */ (0,
|
|
14700
|
+
shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
|
|
14613
14701
|
onSelect: () => onModelChange && onModelChange(m.id)
|
|
14614
14702
|
});
|
|
14615
14703
|
const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
|
|
@@ -14622,15 +14710,15 @@ function ModelControls({
|
|
|
14622
14710
|
items.push({ kind: "section", label: "Fast mode" });
|
|
14623
14711
|
items.push({
|
|
14624
14712
|
kind: "custom",
|
|
14625
|
-
render: () => /* @__PURE__ */ (0,
|
|
14626
|
-
/* @__PURE__ */ (0,
|
|
14627
|
-
/* @__PURE__ */ (0,
|
|
14628
|
-
/* @__PURE__ */ (0,
|
|
14713
|
+
render: () => /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("label", { className: "fdc-switchrow", children: [
|
|
14714
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { children: fastModeLabel }),
|
|
14715
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
|
|
14716
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "fd-switch-thumb" }) })
|
|
14629
14717
|
] })
|
|
14630
14718
|
});
|
|
14631
14719
|
}
|
|
14632
|
-
return /* @__PURE__ */ (0,
|
|
14633
|
-
/* @__PURE__ */ (0,
|
|
14720
|
+
return /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)(React74.Fragment, { children: [
|
|
14721
|
+
/* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
|
|
14634
14722
|
MenuButton,
|
|
14635
14723
|
{
|
|
14636
14724
|
items,
|
|
@@ -14641,7 +14729,7 @@ function ModelControls({
|
|
|
14641
14729
|
title: "Choose a model"
|
|
14642
14730
|
}
|
|
14643
14731
|
),
|
|
14644
|
-
effortLevels && effortLevels.length ? /* @__PURE__ */ (0,
|
|
14732
|
+
effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
|
|
14645
14733
|
MenuButton,
|
|
14646
14734
|
{
|
|
14647
14735
|
placement: "top-end",
|
|
@@ -14662,7 +14750,7 @@ function ModelControls({
|
|
|
14662
14750
|
}
|
|
14663
14751
|
|
|
14664
14752
|
// src/components/chat/AgentChatPanel.tsx
|
|
14665
|
-
var
|
|
14753
|
+
var import_jsx_runtime105 = require("react/jsx-runtime");
|
|
14666
14754
|
var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
|
|
14667
14755
|
function AgentChatPanel({
|
|
14668
14756
|
/* required */
|
|
@@ -14696,6 +14784,7 @@ function AgentChatPanel({
|
|
|
14696
14784
|
packetSchemas,
|
|
14697
14785
|
packetRenderers,
|
|
14698
14786
|
onApplyPacket,
|
|
14787
|
+
pendingTimeoutMs,
|
|
14699
14788
|
onOpenAttachment,
|
|
14700
14789
|
errorCopy,
|
|
14701
14790
|
/* composer */
|
|
@@ -14746,17 +14835,18 @@ function AgentChatPanel({
|
|
|
14746
14835
|
onFeedback,
|
|
14747
14836
|
onEditMessage
|
|
14748
14837
|
}) {
|
|
14749
|
-
const [panelWidth, setPanelWidth] =
|
|
14750
|
-
const [applied, setApplied] =
|
|
14751
|
-
const [draft, setDraft] =
|
|
14752
|
-
const dragging =
|
|
14753
|
-
|
|
14838
|
+
const [panelWidth, setPanelWidth] = React75.useState(width);
|
|
14839
|
+
const [applied, setApplied] = React75.useState({});
|
|
14840
|
+
const [draft, setDraft] = React75.useState("");
|
|
14841
|
+
const dragging = React75.useRef(null);
|
|
14842
|
+
React75.useEffect(() => setPanelWidth(width), [width]);
|
|
14754
14843
|
const engine = useChatEngine({
|
|
14755
14844
|
contextType,
|
|
14756
14845
|
contextId,
|
|
14757
14846
|
apiAdapter,
|
|
14758
14847
|
initialMessage,
|
|
14759
14848
|
threadId,
|
|
14849
|
+
pendingTimeoutMs,
|
|
14760
14850
|
onPacket,
|
|
14761
14851
|
onThreadReady,
|
|
14762
14852
|
onError,
|
|
@@ -14816,7 +14906,7 @@ function AgentChatPanel({
|
|
|
14816
14906
|
onReconnect: engine.reload,
|
|
14817
14907
|
deadTitle: "The assistant isn\u2019t reachable"
|
|
14818
14908
|
};
|
|
14819
|
-
const sessionBar = /* @__PURE__ */ (0,
|
|
14909
|
+
const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
14820
14910
|
ChatSessionBar,
|
|
14821
14911
|
{
|
|
14822
14912
|
sessionStats,
|
|
@@ -14825,7 +14915,7 @@ function AgentChatPanel({
|
|
|
14825
14915
|
onClear: engine.visible.length ? engine.clear : void 0
|
|
14826
14916
|
}
|
|
14827
14917
|
);
|
|
14828
|
-
const modelControls = /* @__PURE__ */ (0,
|
|
14918
|
+
const modelControls = /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
14829
14919
|
ModelControls,
|
|
14830
14920
|
{
|
|
14831
14921
|
models,
|
|
@@ -14840,7 +14930,7 @@ function AgentChatPanel({
|
|
|
14840
14930
|
narrow
|
|
14841
14931
|
}
|
|
14842
14932
|
);
|
|
14843
|
-
const threadMenu = threads && threads.length ? /* @__PURE__ */ (0,
|
|
14933
|
+
const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
14844
14934
|
MenuButton,
|
|
14845
14935
|
{
|
|
14846
14936
|
variant: "ghost",
|
|
@@ -14867,7 +14957,7 @@ function AgentChatPanel({
|
|
|
14867
14957
|
})))
|
|
14868
14958
|
}
|
|
14869
14959
|
) : null;
|
|
14870
|
-
return /* @__PURE__ */ (0,
|
|
14960
|
+
return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(
|
|
14871
14961
|
"aside",
|
|
14872
14962
|
{
|
|
14873
14963
|
className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
|
|
@@ -14878,7 +14968,7 @@ function AgentChatPanel({
|
|
|
14878
14968
|
},
|
|
14879
14969
|
"aria-label": title,
|
|
14880
14970
|
children: [
|
|
14881
|
-
surface === "sidebar" && resizable ? /* @__PURE__ */ (0,
|
|
14971
|
+
surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
14882
14972
|
"div",
|
|
14883
14973
|
{
|
|
14884
14974
|
className: "fdc-grip",
|
|
@@ -14893,20 +14983,20 @@ function AgentChatPanel({
|
|
|
14893
14983
|
}
|
|
14894
14984
|
}
|
|
14895
14985
|
) : null,
|
|
14896
|
-
showHeader ? /* @__PURE__ */ (0,
|
|
14897
|
-
/* @__PURE__ */ (0,
|
|
14898
|
-
/* @__PURE__ */ (0,
|
|
14899
|
-
/* @__PURE__ */ (0,
|
|
14900
|
-
subtitle ? /* @__PURE__ */ (0,
|
|
14986
|
+
showHeader ? /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("header", { className: "fdc-head", children: [
|
|
14987
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsx)("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("i", { className: "ph ph-" + assistantIcon }) }),
|
|
14988
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("span", { className: "fdc-head-titles", children: [
|
|
14989
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsx)("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
|
|
14990
|
+
subtitle ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
|
|
14901
14991
|
] }),
|
|
14902
|
-
/* @__PURE__ */ (0,
|
|
14992
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("span", { className: "fdc-head-acts", children: [
|
|
14903
14993
|
headerActions,
|
|
14904
14994
|
threadMenu,
|
|
14905
|
-
onNewThread ? /* @__PURE__ */ (0,
|
|
14906
|
-
onClose ? /* @__PURE__ */ (0,
|
|
14995
|
+
onNewThread ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
|
|
14996
|
+
onClose ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
14907
14997
|
] })
|
|
14908
14998
|
] }) : null,
|
|
14909
|
-
/* @__PURE__ */ (0,
|
|
14999
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
14910
15000
|
ChatTranscript,
|
|
14911
15001
|
{
|
|
14912
15002
|
messages: engine.visible,
|
|
@@ -14921,7 +15011,7 @@ function AgentChatPanel({
|
|
|
14921
15011
|
renderEmpty
|
|
14922
15012
|
}
|
|
14923
15013
|
),
|
|
14924
|
-
/* @__PURE__ */ (0,
|
|
15014
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
14925
15015
|
ChatComposer,
|
|
14926
15016
|
{
|
|
14927
15017
|
onSubmit: (text, atts) => engine.send(text, atts),
|
|
@@ -14954,8 +15044,8 @@ function AgentChatPanel({
|
|
|
14954
15044
|
}
|
|
14955
15045
|
|
|
14956
15046
|
// src/components/files/FileViewer.tsx
|
|
14957
|
-
var
|
|
14958
|
-
var
|
|
15047
|
+
var React76 = __toESM(require("react"), 1);
|
|
15048
|
+
var import_jsx_runtime106 = require("react/jsx-runtime");
|
|
14959
15049
|
function previewKindOf(file) {
|
|
14960
15050
|
const mime = (file.mime || "").toLowerCase();
|
|
14961
15051
|
const ext = extensionOf(file.name || "");
|
|
@@ -15011,13 +15101,13 @@ function parseDelimited(text, delimiter) {
|
|
|
15011
15101
|
return rows;
|
|
15012
15102
|
}
|
|
15013
15103
|
function usePreview(file, kind, resolveUrl) {
|
|
15014
|
-
const [state, setState] =
|
|
15015
|
-
const [attempt, setAttempt] =
|
|
15016
|
-
const resolveRef =
|
|
15017
|
-
|
|
15104
|
+
const [state, setState] = React76.useState({ status: "loading" });
|
|
15105
|
+
const [attempt, setAttempt] = React76.useState(0);
|
|
15106
|
+
const resolveRef = React76.useRef(resolveUrl);
|
|
15107
|
+
React76.useEffect(() => {
|
|
15018
15108
|
resolveRef.current = resolveUrl;
|
|
15019
15109
|
}, [resolveUrl]);
|
|
15020
|
-
|
|
15110
|
+
React76.useEffect(() => {
|
|
15021
15111
|
if (kind === "none") {
|
|
15022
15112
|
setState({ status: "ready" });
|
|
15023
15113
|
return;
|
|
@@ -15047,19 +15137,19 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
15047
15137
|
if (ac) ac.abort();
|
|
15048
15138
|
};
|
|
15049
15139
|
}, [file.id, kind, attempt]);
|
|
15050
|
-
return { ...state, retry:
|
|
15140
|
+
return { ...state, retry: React76.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
15051
15141
|
}
|
|
15052
15142
|
function PreviewBody({ file, kind, state }) {
|
|
15053
|
-
if (kind === "image") return /* @__PURE__ */ (0,
|
|
15054
|
-
if (kind === "pdf") return /* @__PURE__ */ (0,
|
|
15055
|
-
if (kind === "markdown") return /* @__PURE__ */ (0,
|
|
15143
|
+
if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
15144
|
+
if (kind === "pdf") return /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
|
|
15145
|
+
if (kind === "markdown") return /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
|
|
15056
15146
|
if (kind === "json") {
|
|
15057
15147
|
let pretty = state.text || "";
|
|
15058
15148
|
try {
|
|
15059
15149
|
pretty = JSON.stringify(JSON.parse(pretty), null, 2);
|
|
15060
15150
|
} catch {
|
|
15061
15151
|
}
|
|
15062
|
-
return /* @__PURE__ */ (0,
|
|
15152
|
+
return /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(CodeBlock, { code: pretty, language: "json" });
|
|
15063
15153
|
}
|
|
15064
15154
|
if (kind === "csv") {
|
|
15065
15155
|
const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
|
|
@@ -15067,12 +15157,12 @@ function PreviewBody({ file, kind, state }) {
|
|
|
15067
15157
|
const head = rows[0] || [];
|
|
15068
15158
|
const dataRows = rows.slice(1);
|
|
15069
15159
|
const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
|
|
15070
|
-
return /* @__PURE__ */ (0,
|
|
15071
|
-
/* @__PURE__ */ (0,
|
|
15072
|
-
/* @__PURE__ */ (0,
|
|
15073
|
-
/* @__PURE__ */ (0,
|
|
15160
|
+
return /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "fd-fv-csv", children: [
|
|
15161
|
+
/* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("table", { className: "fd-fv-csv-table", children: [
|
|
15162
|
+
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("tr", { children: head.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("th", { children: c }, i)) }) }),
|
|
15163
|
+
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("tr", { children: head.map((_, ci) => /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
|
|
15074
15164
|
] }),
|
|
15075
|
-
dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ (0,
|
|
15165
|
+
dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
|
|
15076
15166
|
"Showing the first ",
|
|
15077
15167
|
FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
|
|
15078
15168
|
" of ",
|
|
@@ -15081,24 +15171,24 @@ function PreviewBody({ file, kind, state }) {
|
|
|
15081
15171
|
] }) : null
|
|
15082
15172
|
] });
|
|
15083
15173
|
}
|
|
15084
|
-
if (kind === "text") return /* @__PURE__ */ (0,
|
|
15085
|
-
return /* @__PURE__ */ (0,
|
|
15086
|
-
/* @__PURE__ */ (0,
|
|
15087
|
-
/* @__PURE__ */ (0,
|
|
15088
|
-
/* @__PURE__ */ (0,
|
|
15174
|
+
if (kind === "text") return /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
|
|
15175
|
+
return /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "fd-fv-fallback", children: [
|
|
15176
|
+
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
|
|
15177
|
+
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
|
|
15178
|
+
/* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("span", { className: "fd-fv-fallback-meta", children: [
|
|
15089
15179
|
file.mime || "Unknown type",
|
|
15090
15180
|
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
15091
15181
|
] })
|
|
15092
15182
|
] });
|
|
15093
15183
|
}
|
|
15094
15184
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
15095
|
-
const kind =
|
|
15185
|
+
const kind = React76.useMemo(() => previewKindOf(file), [file]);
|
|
15096
15186
|
const preview = usePreview(file, kind, resolveUrl);
|
|
15097
|
-
const [tab, setTab] =
|
|
15098
|
-
const [downloading, setDownloading] =
|
|
15099
|
-
const [downloadError, setDownloadError] =
|
|
15187
|
+
const [tab, setTab] = React76.useState("preview");
|
|
15188
|
+
const [downloading, setDownloading] = React76.useState(false);
|
|
15189
|
+
const [downloadError, setDownloadError] = React76.useState(null);
|
|
15100
15190
|
const hasSide = sidePanel != null;
|
|
15101
|
-
|
|
15191
|
+
React76.useEffect(() => {
|
|
15102
15192
|
setTab("preview");
|
|
15103
15193
|
}, [file.id]);
|
|
15104
15194
|
const download = () => {
|
|
@@ -15114,29 +15204,29 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
15114
15204
|
a.remove();
|
|
15115
15205
|
}).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
|
|
15116
15206
|
};
|
|
15117
|
-
return /* @__PURE__ */ (0,
|
|
15207
|
+
return /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)(
|
|
15118
15208
|
"section",
|
|
15119
15209
|
{
|
|
15120
15210
|
className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
|
|
15121
15211
|
"aria-label": file.name || "File",
|
|
15122
15212
|
children: [
|
|
15123
|
-
/* @__PURE__ */ (0,
|
|
15124
|
-
/* @__PURE__ */ (0,
|
|
15125
|
-
/* @__PURE__ */ (0,
|
|
15126
|
-
/* @__PURE__ */ (0,
|
|
15127
|
-
/* @__PURE__ */ (0,
|
|
15213
|
+
/* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("header", { className: "fd-fv-head", children: [
|
|
15214
|
+
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
|
|
15215
|
+
/* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("span", { className: "fd-fv-head-titles", children: [
|
|
15216
|
+
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
|
|
15217
|
+
/* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("span", { className: "fd-fv-head-meta", children: [
|
|
15128
15218
|
file.mime || "Unknown type",
|
|
15129
15219
|
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
15130
15220
|
] })
|
|
15131
15221
|
] }),
|
|
15132
|
-
/* @__PURE__ */ (0,
|
|
15222
|
+
/* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("span", { className: "fd-fv-head-actions", children: [
|
|
15133
15223
|
actions,
|
|
15134
|
-
/* @__PURE__ */ (0,
|
|
15135
|
-
onClose ? /* @__PURE__ */ (0,
|
|
15224
|
+
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
|
|
15225
|
+
onClose ? /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
|
|
15136
15226
|
] })
|
|
15137
15227
|
] }),
|
|
15138
|
-
downloadError ? /* @__PURE__ */ (0,
|
|
15139
|
-
hasSide ? /* @__PURE__ */ (0,
|
|
15228
|
+
downloadError ? /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
|
|
15229
|
+
hasSide ? /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
|
|
15140
15230
|
Tabs,
|
|
15141
15231
|
{
|
|
15142
15232
|
className: "fd-fv-tabs",
|
|
@@ -15145,19 +15235,19 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
15145
15235
|
onChange: (v) => setTab(v)
|
|
15146
15236
|
}
|
|
15147
15237
|
) : null,
|
|
15148
|
-
/* @__PURE__ */ (0,
|
|
15149
|
-
/* @__PURE__ */ (0,
|
|
15238
|
+
/* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "fd-fv-body", children: [
|
|
15239
|
+
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
|
|
15150
15240
|
LoadingRegion,
|
|
15151
15241
|
{
|
|
15152
15242
|
state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
|
|
15153
15243
|
error: preview.error,
|
|
15154
15244
|
label: "Loading preview of " + (file.name || "file"),
|
|
15155
15245
|
onRetry: preview.status === "error" ? preview.retry : void 0,
|
|
15156
|
-
skeleton: /* @__PURE__ */ (0,
|
|
15157
|
-
children: /* @__PURE__ */ (0,
|
|
15246
|
+
skeleton: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(Skeleton, { shape: "card", h: 220 }),
|
|
15247
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(PreviewBody, { file, kind, state: preview })
|
|
15158
15248
|
}
|
|
15159
15249
|
) }),
|
|
15160
|
-
hasSide ? /* @__PURE__ */ (0,
|
|
15250
|
+
hasSide ? /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
|
|
15161
15251
|
] })
|
|
15162
15252
|
]
|
|
15163
15253
|
}
|
|
@@ -15165,8 +15255,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
15165
15255
|
}
|
|
15166
15256
|
|
|
15167
15257
|
// src/components/files/FileBrowser.tsx
|
|
15168
|
-
var
|
|
15169
|
-
var
|
|
15258
|
+
var React77 = __toESM(require("react"), 1);
|
|
15259
|
+
var import_jsx_runtime107 = require("react/jsx-runtime");
|
|
15170
15260
|
function childrenOf(folders, parentId) {
|
|
15171
15261
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
15172
15262
|
}
|
|
@@ -15238,8 +15328,8 @@ function FolderPickerMenu({
|
|
|
15238
15328
|
}) {
|
|
15239
15329
|
const panel = useInlinePanel();
|
|
15240
15330
|
const { open: open2, setOpen, ref } = panel;
|
|
15241
|
-
return /* @__PURE__ */ (0,
|
|
15242
|
-
/* @__PURE__ */ (0,
|
|
15331
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("span", { className: "fd-fb-menu-anchor", ref, children: [
|
|
15332
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15243
15333
|
IconButton,
|
|
15244
15334
|
{
|
|
15245
15335
|
icon: "arrows-out-cardinal",
|
|
@@ -15251,9 +15341,9 @@ function FolderPickerMenu({
|
|
|
15251
15341
|
onClick: () => setOpen((v) => !v)
|
|
15252
15342
|
}
|
|
15253
15343
|
),
|
|
15254
|
-
/* @__PURE__ */ (0,
|
|
15255
|
-
/* @__PURE__ */ (0,
|
|
15256
|
-
destinations.map((d) => /* @__PURE__ */ (0,
|
|
15344
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(InlinePanelSurface, { panel, align: "right", offset: 4, width: 220, maxHeight: 280, role: "menu", label, children: /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "fd-fb-menu", children: [
|
|
15345
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
|
|
15346
|
+
destinations.map((d) => /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(
|
|
15257
15347
|
"button",
|
|
15258
15348
|
{
|
|
15259
15349
|
type: "button",
|
|
@@ -15265,7 +15355,7 @@ function FolderPickerMenu({
|
|
|
15265
15355
|
setOpen(false);
|
|
15266
15356
|
},
|
|
15267
15357
|
children: [
|
|
15268
|
-
/* @__PURE__ */ (0,
|
|
15358
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
|
|
15269
15359
|
d.name
|
|
15270
15360
|
]
|
|
15271
15361
|
},
|
|
@@ -15275,8 +15365,8 @@ function FolderPickerMenu({
|
|
|
15275
15365
|
] });
|
|
15276
15366
|
}
|
|
15277
15367
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
15278
|
-
const [over, setOver] =
|
|
15279
|
-
const dragCounter =
|
|
15368
|
+
const [over, setOver] = React77.useState(false);
|
|
15369
|
+
const dragCounter = React77.useRef(0);
|
|
15280
15370
|
const dropHandlers = isDropTarget ? {
|
|
15281
15371
|
onDragEnter: (e) => {
|
|
15282
15372
|
if (!hasInternalPayload(e)) return;
|
|
@@ -15301,8 +15391,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
15301
15391
|
if (payload && onDropPayload) onDropPayload(payload);
|
|
15302
15392
|
}
|
|
15303
15393
|
} : {};
|
|
15304
|
-
return /* @__PURE__ */ (0,
|
|
15305
|
-
/* @__PURE__ */ (0,
|
|
15394
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
|
|
15395
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(
|
|
15306
15396
|
"button",
|
|
15307
15397
|
{
|
|
15308
15398
|
type: "button",
|
|
@@ -15311,26 +15401,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
15311
15401
|
draggable: !!draggableId,
|
|
15312
15402
|
onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
|
|
15313
15403
|
children: [
|
|
15314
|
-
/* @__PURE__ */ (0,
|
|
15315
|
-
/* @__PURE__ */ (0,
|
|
15316
|
-
/* @__PURE__ */ (0,
|
|
15317
|
-
meta ? /* @__PURE__ */ (0,
|
|
15404
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("i", { className: "ph ph-" + icon }) }),
|
|
15405
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("span", { className: "fd-fb-row-text", children: [
|
|
15406
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "fd-fb-row-name", title: name, children: name }),
|
|
15407
|
+
meta ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "fd-fb-row-meta", children: meta }) : null
|
|
15318
15408
|
] })
|
|
15319
15409
|
]
|
|
15320
15410
|
}
|
|
15321
15411
|
),
|
|
15322
|
-
actions ? /* @__PURE__ */ (0,
|
|
15412
|
+
actions ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "fd-fb-row-actions", children: actions }) : null
|
|
15323
15413
|
] });
|
|
15324
15414
|
}
|
|
15325
15415
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
15326
15416
|
const kids = childrenOf(folders, folder.id);
|
|
15327
|
-
const [expanded, setExpanded] =
|
|
15328
|
-
|
|
15417
|
+
const [expanded, setExpanded] = React77.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
15418
|
+
React77.useEffect(() => {
|
|
15329
15419
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
15330
15420
|
}, [currentFolderId, folder.id, folders]);
|
|
15331
15421
|
const isCurrent = folder.id === currentFolderId;
|
|
15332
|
-
return /* @__PURE__ */ (0,
|
|
15333
|
-
/* @__PURE__ */ (0,
|
|
15422
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "fd-fb-tree-node", children: [
|
|
15423
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15334
15424
|
RowShell,
|
|
15335
15425
|
{
|
|
15336
15426
|
icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
|
|
@@ -15340,7 +15430,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
|
|
|
15340
15430
|
isDropTarget: canMove,
|
|
15341
15431
|
onDropPayload: (payload) => onMoveInto(payload, folder.id),
|
|
15342
15432
|
className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
|
|
15343
|
-
actions: kids.length ? /* @__PURE__ */ (0,
|
|
15433
|
+
actions: kids.length ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15344
15434
|
IconButton,
|
|
15345
15435
|
{
|
|
15346
15436
|
icon: expanded ? "caret-down" : "caret-right",
|
|
@@ -15352,7 +15442,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
|
|
|
15352
15442
|
) : void 0
|
|
15353
15443
|
}
|
|
15354
15444
|
),
|
|
15355
|
-
expanded && kids.length ? /* @__PURE__ */ (0,
|
|
15445
|
+
expanded && kids.length ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15356
15446
|
TreeNode,
|
|
15357
15447
|
{
|
|
15358
15448
|
folder: k,
|
|
@@ -15391,15 +15481,15 @@ function FileBrowser({
|
|
|
15391
15481
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
15392
15482
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
15393
15483
|
const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
|
|
15394
|
-
const [createOpen, setCreateOpen] =
|
|
15395
|
-
const [createName, setCreateName] =
|
|
15396
|
-
const [renameTarget, setRenameTarget] =
|
|
15397
|
-
const [renameValue, setRenameValue] =
|
|
15398
|
-
const [deleteTarget, setDeleteTarget] =
|
|
15399
|
-
const uploadInputRef =
|
|
15400
|
-
const crumbFolders =
|
|
15401
|
-
const subfolders =
|
|
15402
|
-
const currentFiles =
|
|
15484
|
+
const [createOpen, setCreateOpen] = React77.useState(false);
|
|
15485
|
+
const [createName, setCreateName] = React77.useState("");
|
|
15486
|
+
const [renameTarget, setRenameTarget] = React77.useState(null);
|
|
15487
|
+
const [renameValue, setRenameValue] = React77.useState("");
|
|
15488
|
+
const [deleteTarget, setDeleteTarget] = React77.useState(null);
|
|
15489
|
+
const uploadInputRef = React77.useRef(null);
|
|
15490
|
+
const crumbFolders = React77.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
15491
|
+
const subfolders = React77.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
15492
|
+
const currentFiles = React77.useMemo(
|
|
15403
15493
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
15404
15494
|
[files, currentFolderId]
|
|
15405
15495
|
);
|
|
@@ -15438,10 +15528,10 @@ function FileBrowser({
|
|
|
15438
15528
|
if (deleteTarget && onDeleteFolder) onDeleteFolder(deleteTarget);
|
|
15439
15529
|
setDeleteTarget(null);
|
|
15440
15530
|
};
|
|
15441
|
-
const content = /* @__PURE__ */ (0,
|
|
15442
|
-
/* @__PURE__ */ (0,
|
|
15443
|
-
/* @__PURE__ */ (0,
|
|
15444
|
-
/* @__PURE__ */ (0,
|
|
15531
|
+
const content = /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
|
|
15532
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "fd-fb-head", children: [
|
|
15533
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
|
|
15534
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15445
15535
|
BreadcrumbCrumb,
|
|
15446
15536
|
{
|
|
15447
15537
|
label: "Home",
|
|
@@ -15451,7 +15541,7 @@ function FileBrowser({
|
|
|
15451
15541
|
onDropPayload: (p) => moveIntoFolder(p, null)
|
|
15452
15542
|
}
|
|
15453
15543
|
),
|
|
15454
|
-
crumbFolders.map((f, i) => /* @__PURE__ */ (0,
|
|
15544
|
+
crumbFolders.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15455
15545
|
BreadcrumbCrumb,
|
|
15456
15546
|
{
|
|
15457
15547
|
label: f.name,
|
|
@@ -15463,11 +15553,11 @@ function FileBrowser({
|
|
|
15463
15553
|
f.id
|
|
15464
15554
|
))
|
|
15465
15555
|
] }),
|
|
15466
|
-
/* @__PURE__ */ (0,
|
|
15467
|
-
canCreateFolder ? /* @__PURE__ */ (0,
|
|
15468
|
-
canUpload ? /* @__PURE__ */ (0,
|
|
15469
|
-
/* @__PURE__ */ (0,
|
|
15470
|
-
/* @__PURE__ */ (0,
|
|
15556
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("span", { className: "fd-fb-actions", children: [
|
|
15557
|
+
canCreateFolder ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
|
|
15558
|
+
canUpload ? /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(import_jsx_runtime107.Fragment, { children: [
|
|
15559
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
|
|
15560
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15471
15561
|
"input",
|
|
15472
15562
|
{
|
|
15473
15563
|
ref: uploadInputRef,
|
|
@@ -15485,9 +15575,9 @@ function FileBrowser({
|
|
|
15485
15575
|
] }) : null
|
|
15486
15576
|
] })
|
|
15487
15577
|
] }),
|
|
15488
|
-
/* @__PURE__ */ (0,
|
|
15489
|
-
/* @__PURE__ */ (0,
|
|
15490
|
-
/* @__PURE__ */ (0,
|
|
15578
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "fd-fb-body", children: [
|
|
15579
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
|
|
15580
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15491
15581
|
RowShell,
|
|
15492
15582
|
{
|
|
15493
15583
|
icon: "house-simple",
|
|
@@ -15498,7 +15588,7 @@ function FileBrowser({
|
|
|
15498
15588
|
className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
|
|
15499
15589
|
}
|
|
15500
15590
|
),
|
|
15501
|
-
childrenOf(folders, null).map((f) => /* @__PURE__ */ (0,
|
|
15591
|
+
childrenOf(folders, null).map((f) => /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15502
15592
|
TreeNode,
|
|
15503
15593
|
{
|
|
15504
15594
|
folder: f,
|
|
@@ -15512,18 +15602,18 @@ function FileBrowser({
|
|
|
15512
15602
|
f.id
|
|
15513
15603
|
))
|
|
15514
15604
|
] }),
|
|
15515
|
-
/* @__PURE__ */ (0,
|
|
15605
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15516
15606
|
LoadingRegion,
|
|
15517
15607
|
{
|
|
15518
15608
|
state: loading ? "loading" : "ready",
|
|
15519
15609
|
label: "Loading folder contents",
|
|
15520
|
-
skeleton: /* @__PURE__ */ (0,
|
|
15521
|
-
/* @__PURE__ */ (0,
|
|
15522
|
-
/* @__PURE__ */ (0,
|
|
15523
|
-
/* @__PURE__ */ (0,
|
|
15610
|
+
skeleton: /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
|
|
15611
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Skeleton, { h: 44, radius: "10px" }),
|
|
15612
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Skeleton, { h: 44, radius: "10px" }),
|
|
15613
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Skeleton, { h: 44, radius: "10px" })
|
|
15524
15614
|
] }),
|
|
15525
|
-
children: isEmpty ? /* @__PURE__ */ (0,
|
|
15526
|
-
subfolders.map((f) => /* @__PURE__ */ (0,
|
|
15615
|
+
children: isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(EmptyState, { icon: "folder-open", title: "This folder is empty", children: canUpload ? "Drop files here, or use Upload above." : "Nothing has been filed here yet." }) : /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "fd-fb-list", children: [
|
|
15616
|
+
subfolders.map((f) => /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15527
15617
|
RowShell,
|
|
15528
15618
|
{
|
|
15529
15619
|
icon: "folder-simple",
|
|
@@ -15532,9 +15622,9 @@ function FileBrowser({
|
|
|
15532
15622
|
draggableId: canMove ? { kind: "folder", id: f.id } : void 0,
|
|
15533
15623
|
isDropTarget: canMove,
|
|
15534
15624
|
onDropPayload: (p) => moveIntoFolder(p, f.id),
|
|
15535
|
-
actions: /* @__PURE__ */ (0,
|
|
15536
|
-
canRenameFolder ? /* @__PURE__ */ (0,
|
|
15537
|
-
canMove ? /* @__PURE__ */ (0,
|
|
15625
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(import_jsx_runtime107.Fragment, { children: [
|
|
15626
|
+
canRenameFolder ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
|
|
15627
|
+
canMove ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15538
15628
|
FolderPickerMenu,
|
|
15539
15629
|
{
|
|
15540
15630
|
label: "Move " + f.name,
|
|
@@ -15542,12 +15632,12 @@ function FileBrowser({
|
|
|
15542
15632
|
onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
|
|
15543
15633
|
}
|
|
15544
15634
|
) : null,
|
|
15545
|
-
canDeleteFolder ? /* @__PURE__ */ (0,
|
|
15635
|
+
canDeleteFolder ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
|
|
15546
15636
|
] })
|
|
15547
15637
|
},
|
|
15548
15638
|
f.id
|
|
15549
15639
|
)),
|
|
15550
|
-
currentFiles.map((file) => /* @__PURE__ */ (0,
|
|
15640
|
+
currentFiles.map((file) => /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15551
15641
|
RowShell,
|
|
15552
15642
|
{
|
|
15553
15643
|
icon: iconForMime(file.mime, file.name),
|
|
@@ -15555,8 +15645,8 @@ function FileBrowser({
|
|
|
15555
15645
|
meta: file.size ? formatBytes(file.size) : void 0,
|
|
15556
15646
|
onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
|
|
15557
15647
|
draggableId: canMove ? { kind: "file", id: file.id } : void 0,
|
|
15558
|
-
actions: /* @__PURE__ */ (0,
|
|
15559
|
-
canMove ? /* @__PURE__ */ (0,
|
|
15648
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(import_jsx_runtime107.Fragment, { children: [
|
|
15649
|
+
canMove ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15560
15650
|
FolderPickerMenu,
|
|
15561
15651
|
{
|
|
15562
15652
|
label: "Move " + file.name,
|
|
@@ -15564,7 +15654,7 @@ function FileBrowser({
|
|
|
15564
15654
|
onPick: (target) => onMoveFile && onMoveFile(file.id, target)
|
|
15565
15655
|
}
|
|
15566
15656
|
) : null,
|
|
15567
|
-
canRemoveFile ? /* @__PURE__ */ (0,
|
|
15657
|
+
canRemoveFile ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
|
|
15568
15658
|
] })
|
|
15569
15659
|
},
|
|
15570
15660
|
file.id
|
|
@@ -15573,10 +15663,10 @@ function FileBrowser({
|
|
|
15573
15663
|
}
|
|
15574
15664
|
) })
|
|
15575
15665
|
] }),
|
|
15576
|
-
/* @__PURE__ */ (0,
|
|
15577
|
-
/* @__PURE__ */ (0,
|
|
15578
|
-
/* @__PURE__ */ (0,
|
|
15579
|
-
] }), children: /* @__PURE__ */ (0,
|
|
15666
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(import_jsx_runtime107.Fragment, { children: [
|
|
15667
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
|
|
15668
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
|
|
15669
|
+
] }), children: /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15580
15670
|
"input",
|
|
15581
15671
|
{
|
|
15582
15672
|
className: "fd-fb-input",
|
|
@@ -15590,10 +15680,10 @@ function FileBrowser({
|
|
|
15590
15680
|
autoFocus: true
|
|
15591
15681
|
}
|
|
15592
15682
|
) }),
|
|
15593
|
-
/* @__PURE__ */ (0,
|
|
15594
|
-
/* @__PURE__ */ (0,
|
|
15595
|
-
/* @__PURE__ */ (0,
|
|
15596
|
-
] }), children: /* @__PURE__ */ (0,
|
|
15683
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(import_jsx_runtime107.Fragment, { children: [
|
|
15684
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
|
|
15685
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
|
|
15686
|
+
] }), children: /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15597
15687
|
"input",
|
|
15598
15688
|
{
|
|
15599
15689
|
className: "fd-fb-input",
|
|
@@ -15607,22 +15697,22 @@ function FileBrowser({
|
|
|
15607
15697
|
autoFocus: true
|
|
15608
15698
|
}
|
|
15609
15699
|
) }),
|
|
15610
|
-
/* @__PURE__ */ (0,
|
|
15700
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
15611
15701
|
Modal,
|
|
15612
15702
|
{
|
|
15613
15703
|
open: deleteTarget != null,
|
|
15614
15704
|
title: deleteTarget ? "Delete \u201C" + deleteTarget.name + "\u201D?" : "Delete folder?",
|
|
15615
15705
|
description: "This can't be undone. The folder must be empty.",
|
|
15616
15706
|
onClose: () => setDeleteTarget(null),
|
|
15617
|
-
footer: /* @__PURE__ */ (0,
|
|
15618
|
-
/* @__PURE__ */ (0,
|
|
15619
|
-
/* @__PURE__ */ (0,
|
|
15707
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(import_jsx_runtime107.Fragment, { children: [
|
|
15708
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
|
|
15709
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
|
|
15620
15710
|
] })
|
|
15621
15711
|
}
|
|
15622
15712
|
)
|
|
15623
15713
|
] });
|
|
15624
15714
|
if (!canUpload) return content;
|
|
15625
|
-
return /* @__PURE__ */ (0,
|
|
15715
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
|
|
15626
15716
|
}
|
|
15627
15717
|
function BreadcrumbCrumb({
|
|
15628
15718
|
label,
|
|
@@ -15631,8 +15721,8 @@ function BreadcrumbCrumb({
|
|
|
15631
15721
|
isDropTarget,
|
|
15632
15722
|
onDropPayload
|
|
15633
15723
|
}) {
|
|
15634
|
-
const [over, setOver] =
|
|
15635
|
-
const dragCounter =
|
|
15724
|
+
const [over, setOver] = React77.useState(false);
|
|
15725
|
+
const dragCounter = React77.useRef(0);
|
|
15636
15726
|
const dropHandlers = isDropTarget ? {
|
|
15637
15727
|
onDragEnter: (e) => {
|
|
15638
15728
|
if (!hasInternalPayload(e)) return;
|
|
@@ -15657,11 +15747,11 @@ function BreadcrumbCrumb({
|
|
|
15657
15747
|
if (payload && onDropPayload) onDropPayload(payload);
|
|
15658
15748
|
}
|
|
15659
15749
|
} : {};
|
|
15660
|
-
return /* @__PURE__ */ (0,
|
|
15750
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
|
|
15661
15751
|
}
|
|
15662
15752
|
|
|
15663
15753
|
// src/kits/query.ts
|
|
15664
|
-
var
|
|
15754
|
+
var React78 = __toESM(require("react"), 1);
|
|
15665
15755
|
|
|
15666
15756
|
// src/kits/queryUrl.ts
|
|
15667
15757
|
var historyUrlAdapter = {
|
|
@@ -15799,38 +15889,38 @@ function requestFor(params, query, paging, after) {
|
|
|
15799
15889
|
}
|
|
15800
15890
|
var toError = (e) => e instanceof Error ? e : new Error(String(e));
|
|
15801
15891
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "page", url }) {
|
|
15802
|
-
const [base] =
|
|
15892
|
+
const [base] = React78.useState(() => {
|
|
15803
15893
|
const store = PREFS || window.PlannerPrefs;
|
|
15804
15894
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
15805
15895
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
15806
15896
|
});
|
|
15807
|
-
const [mountParams] =
|
|
15808
|
-
const address =
|
|
15809
|
-
const [query, setQuery] =
|
|
15810
|
-
const savePref =
|
|
15897
|
+
const [mountParams] = React78.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
|
|
15898
|
+
const address = React78.useRef(mountParams);
|
|
15899
|
+
const [query, setQuery] = React78.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
|
|
15900
|
+
const savePref = React78.useCallback((patch2) => {
|
|
15811
15901
|
const store = PREFS || window.PlannerPrefs;
|
|
15812
15902
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
15813
15903
|
}, [prefsKey]);
|
|
15814
|
-
const [res, setRes] =
|
|
15815
|
-
const [loading, setLoading] =
|
|
15816
|
-
const [loadingMore, setLoadingMore] =
|
|
15817
|
-
const [failure, setFailure] =
|
|
15818
|
-
const [reloadToken, setReloadToken] =
|
|
15819
|
-
const moreController =
|
|
15904
|
+
const [res, setRes] = React78.useState(null);
|
|
15905
|
+
const [loading, setLoading] = React78.useState(true);
|
|
15906
|
+
const [loadingMore, setLoadingMore] = React78.useState(false);
|
|
15907
|
+
const [failure, setFailure] = React78.useState(null);
|
|
15908
|
+
const [reloadToken, setReloadToken] = React78.useState(0);
|
|
15909
|
+
const moreController = React78.useRef(null);
|
|
15820
15910
|
const depKey = (deps || []).join("|");
|
|
15821
15911
|
const paramKey = JSON.stringify(params || {});
|
|
15822
15912
|
const queryKey = JSON.stringify(query);
|
|
15823
|
-
const lifetime =
|
|
15824
|
-
|
|
15913
|
+
const lifetime = React78.useRef(null);
|
|
15914
|
+
React78.useEffect(() => {
|
|
15825
15915
|
const controller = new AbortController();
|
|
15826
15916
|
lifetime.current = controller;
|
|
15827
15917
|
return () => controller.abort();
|
|
15828
15918
|
}, []);
|
|
15829
|
-
const latest =
|
|
15830
|
-
|
|
15919
|
+
const latest = React78.useRef({ res, loading, query, params, endpoint, url, base });
|
|
15920
|
+
React78.useLayoutEffect(() => {
|
|
15831
15921
|
latest.current = { res, loading, query, params, endpoint, url, base };
|
|
15832
15922
|
});
|
|
15833
|
-
|
|
15923
|
+
React78.useEffect(() => {
|
|
15834
15924
|
const controller = new AbortController();
|
|
15835
15925
|
const { signal } = controller;
|
|
15836
15926
|
setLoading(true);
|
|
@@ -15866,7 +15956,7 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "
|
|
|
15866
15956
|
};
|
|
15867
15957
|
}, [endpoint, queryKey, paramKey, depKey, paging, reloadToken]);
|
|
15868
15958
|
const adapter = url ? url.adapter ?? historyUrlAdapter : null;
|
|
15869
|
-
|
|
15959
|
+
React78.useEffect(() => {
|
|
15870
15960
|
if (!adapter) return;
|
|
15871
15961
|
return adapter.subscribe((params2) => {
|
|
15872
15962
|
const { url: u, base: b } = latest.current;
|
|
@@ -16216,12 +16306,12 @@ function createVersionStore(initialState, options) {
|
|
|
16216
16306
|
}
|
|
16217
16307
|
|
|
16218
16308
|
// src/kits/documentTitle.ts
|
|
16219
|
-
var
|
|
16309
|
+
var React79 = __toESM(require("react"), 1);
|
|
16220
16310
|
function formatDocumentTitle(routeTitle, appName) {
|
|
16221
16311
|
return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
|
|
16222
16312
|
}
|
|
16223
16313
|
function useDocumentTitle(routeTitle, appName) {
|
|
16224
|
-
|
|
16314
|
+
React79.useEffect(() => {
|
|
16225
16315
|
if (typeof document === "undefined") return;
|
|
16226
16316
|
document.title = formatDocumentTitle(routeTitle, appName);
|
|
16227
16317
|
}, [routeTitle, appName]);
|
|
@@ -16293,6 +16383,7 @@ function useDocumentTitle(routeTitle, appName) {
|
|
|
16293
16383
|
FILE_VIEWER_TEXT_LIMIT,
|
|
16294
16384
|
FactList,
|
|
16295
16385
|
FeatureGate,
|
|
16386
|
+
Fieldset,
|
|
16296
16387
|
FileBrowser,
|
|
16297
16388
|
FileChip,
|
|
16298
16389
|
FileGrid,
|
|
@@ -16346,6 +16437,7 @@ function useDocumentTitle(routeTitle, appName) {
|
|
|
16346
16437
|
QuotaRow,
|
|
16347
16438
|
ROOT_STEP,
|
|
16348
16439
|
Radio,
|
|
16440
|
+
RadioGroup,
|
|
16349
16441
|
RangeSlider,
|
|
16350
16442
|
RelativeTime,
|
|
16351
16443
|
RoadmapTimeline,
|