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