@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.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hideEscapes,
|
|
3
|
+
markdownToText,
|
|
4
|
+
showEscapes,
|
|
5
|
+
showEscapesRaw
|
|
6
|
+
} from "./chunk-476HCG2A.js";
|
|
1
7
|
import {
|
|
2
8
|
US_STATES,
|
|
3
9
|
US_STATE_CODES,
|
|
@@ -5224,7 +5230,8 @@ var INLINE = [
|
|
|
5224
5230
|
];
|
|
5225
5231
|
function inlineNodes(src, ctx, keyBase) {
|
|
5226
5232
|
const out = [];
|
|
5227
|
-
let rest = String(src == null ? "" : src), guard = 0;
|
|
5233
|
+
let rest = hideEscapes(String(src == null ? "" : src)), guard = 0;
|
|
5234
|
+
const d = showEscapes;
|
|
5228
5235
|
const key = () => keyBase + "-" + out.length;
|
|
5229
5236
|
while (rest && guard++ < 800) {
|
|
5230
5237
|
let best = null;
|
|
@@ -5235,28 +5242,28 @@ function inlineNodes(src, ctx, keyBase) {
|
|
|
5235
5242
|
}
|
|
5236
5243
|
if (!best) break;
|
|
5237
5244
|
const { kind, m } = best;
|
|
5238
|
-
if (m.index > 0) out.push(rest.slice(0, m.index));
|
|
5245
|
+
if (m.index > 0) out.push(d(rest.slice(0, m.index)));
|
|
5239
5246
|
const g = (i) => m[i];
|
|
5240
|
-
if (kind === "code") out.push(/* @__PURE__ */ jsx54("code", { className: "fd-md-code", children: g(1) }, key()));
|
|
5247
|
+
if (kind === "code") out.push(/* @__PURE__ */ jsx54("code", { className: "fd-md-code", children: showEscapesRaw(g(1)) }, key()));
|
|
5241
5248
|
else if (kind === "image") {
|
|
5242
|
-
const src2 = safeHref(g(2));
|
|
5243
|
-
out.push(ctx.allowImages && src2 ? /* @__PURE__ */ jsx54("img", { className: "fd-md-img", src: src2, alt: g(1) || "", title: g(3)
|
|
5249
|
+
const src2 = safeHref(d(g(2)));
|
|
5250
|
+
out.push(ctx.allowImages && src2 ? /* @__PURE__ */ jsx54("img", { className: "fd-md-img", src: src2, alt: d(g(1) || ""), title: g(3) ? d(g(3)) : void 0, loading: "lazy" }, key()) : /* @__PURE__ */ jsx54("span", { className: "fd-md-imgalt", children: d(g(1) || "image") }, key()));
|
|
5244
5251
|
} else if (kind === "link") {
|
|
5245
|
-
const href = safeHref(g(2));
|
|
5246
|
-
out.push(href ? /* @__PURE__ */ jsx54("a", { href, title: g(3)
|
|
5252
|
+
const href = safeHref(d(g(2)));
|
|
5253
|
+
out.push(href ? /* @__PURE__ */ jsx54("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__ */ jsx54("span", { children: d(g(1)) }, key()));
|
|
5247
5254
|
} else if (kind === "cite") {
|
|
5248
|
-
out.push(ctx.renderCitation ? /* @__PURE__ */ jsx54(React35.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ jsx54("sup", { className: "fd-md-cite", children: g(1) }, key()));
|
|
5255
|
+
out.push(ctx.renderCitation ? /* @__PURE__ */ jsx54(React35.Fragment, { children: ctx.renderCitation(d(g(1))) }, key()) : /* @__PURE__ */ jsx54("sup", { className: "fd-md-cite", children: d(g(1)) }, key()));
|
|
5249
5256
|
} else if (kind === "strongem") out.push(/* @__PURE__ */ jsx54("strong", { children: /* @__PURE__ */ jsx54("em", { children: inlineNodes(g(1), ctx, key()) }) }, key()));
|
|
5250
5257
|
else if (kind === "strong") out.push(/* @__PURE__ */ jsx54("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
5251
5258
|
else if (kind === "em") out.push(/* @__PURE__ */ jsx54("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
5252
5259
|
else if (kind === "del") out.push(/* @__PURE__ */ jsx54("del", { children: inlineNodes(g(1), ctx, key()) }, key()));
|
|
5253
5260
|
else if (kind === "autolink" || kind === "bare") {
|
|
5254
|
-
const href = safeHref(g(1));
|
|
5255
|
-
out.push(href ? /* @__PURE__ */ jsx54("a", { href, target: "_blank", rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: g(1).replace(/^mailto:/, "") }, key()) : g(1));
|
|
5261
|
+
const href = safeHref(d(g(1)));
|
|
5262
|
+
out.push(href ? /* @__PURE__ */ jsx54("a", { href, target: "_blank", rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: d(g(1)).replace(/^mailto:/, "") }, key()) : d(g(1)));
|
|
5256
5263
|
}
|
|
5257
5264
|
rest = rest.slice(m.index + m[0].length);
|
|
5258
5265
|
}
|
|
5259
|
-
if (rest) out.push(rest);
|
|
5266
|
+
if (rest) out.push(d(rest));
|
|
5260
5267
|
return out;
|
|
5261
5268
|
}
|
|
5262
5269
|
var RE = {
|
|
@@ -5268,7 +5275,26 @@ var RE = {
|
|
|
5268
5275
|
task: /^\[([ xX])\]\s+(.*)$/,
|
|
5269
5276
|
tableSep: /^\s*\|?[\s:|-]*-[\s:|-]*\|?\s*$/
|
|
5270
5277
|
};
|
|
5271
|
-
var splitRow = (line) =>
|
|
5278
|
+
var splitRow = (line) => {
|
|
5279
|
+
const t = line.trim();
|
|
5280
|
+
const cells = [];
|
|
5281
|
+
let cur = "";
|
|
5282
|
+
for (let i = t.startsWith("|") ? 1 : 0; i < t.length; i++) {
|
|
5283
|
+
const c = t[i];
|
|
5284
|
+
if (c === "\\" && i + 1 < t.length) {
|
|
5285
|
+
cur += c + t[++i];
|
|
5286
|
+
continue;
|
|
5287
|
+
}
|
|
5288
|
+
if (c === "|") {
|
|
5289
|
+
cells.push(cur.trim());
|
|
5290
|
+
cur = "";
|
|
5291
|
+
continue;
|
|
5292
|
+
}
|
|
5293
|
+
cur += c;
|
|
5294
|
+
}
|
|
5295
|
+
if (cur.trim() || !t.endsWith("|")) cells.push(cur.trim());
|
|
5296
|
+
return cells;
|
|
5297
|
+
};
|
|
5272
5298
|
function parseBlocks(src) {
|
|
5273
5299
|
const lines = String(src == null ? "" : src).replace(/\r\n?/g, "\n").split("\n");
|
|
5274
5300
|
const blocks = [];
|
|
@@ -5400,6 +5426,7 @@ function renderBlocks(blocks, ctx, path) {
|
|
|
5400
5426
|
}
|
|
5401
5427
|
});
|
|
5402
5428
|
}
|
|
5429
|
+
var mdClass = (base, size, tone, className) => [base, size && `${base}--${size}`, tone === "muted" && `${base}--muted`, className].filter(Boolean).join(" ");
|
|
5403
5430
|
function Markdown({
|
|
5404
5431
|
source = "",
|
|
5405
5432
|
className = "",
|
|
@@ -5407,17 +5434,16 @@ function Markdown({
|
|
|
5407
5434
|
allowImages = true,
|
|
5408
5435
|
headingOffset = 0,
|
|
5409
5436
|
renderCitation,
|
|
5410
|
-
onLinkClick
|
|
5437
|
+
onLinkClick,
|
|
5438
|
+
size = "body",
|
|
5439
|
+
tone = "default"
|
|
5411
5440
|
}) {
|
|
5412
5441
|
const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
|
|
5413
5442
|
const blocks = React35.useMemo(() => parseBlocks(source), [source]);
|
|
5414
|
-
return /* @__PURE__ */ jsx54("div", { className:
|
|
5443
|
+
return /* @__PURE__ */ jsx54("div", { className: mdClass("fd-md", size, tone, className), children: renderBlocks(blocks, ctx, "b") });
|
|
5415
5444
|
}
|
|
5416
|
-
function MarkdownInline({ source = "", className = "", onLinkClick }) {
|
|
5417
|
-
return /* @__PURE__ */ jsx54("span", { className:
|
|
5418
|
-
}
|
|
5419
|
-
function markdownToText(src) {
|
|
5420
|
-
return String(src == null ? "" : src).replace(/```[\w+#-]*\n?([\s\S]*?)```/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").replace(/^\s{0,3}#{1,6}\s+/gm, "").replace(/\*\*\*([^*]+)\*\*\*|\*\*([^*]+)\*\*|__([^_]+)__/g, "$1$2$3").replace(/(^|\W)[*_]([^*_\n]+)[*_](\W|$)/g, "$1$2$3").replace(/~~([^~]+)~~/g, "$1").replace(/^\s*>\s?/gm, "").trim();
|
|
5445
|
+
function MarkdownInline({ source = "", className = "", onLinkClick, size, tone }) {
|
|
5446
|
+
return /* @__PURE__ */ jsx54("span", { className: mdClass("fd-md-inline", size, tone, className), children: inlineNodes(source, { allowImages: false, onLinkClick }, "i") });
|
|
5421
5447
|
}
|
|
5422
5448
|
|
|
5423
5449
|
// src/components/data/Meter.tsx
|
|
@@ -6678,14 +6704,17 @@ function Checkbox({ label, description, card = false, indeterminate = false, cla
|
|
|
6678
6704
|
|
|
6679
6705
|
// src/components/forms/Radio.tsx
|
|
6680
6706
|
import { jsx as jsx69, jsxs as jsxs58 } from "react/jsx-runtime";
|
|
6681
|
-
function Radio({ label, description, card = false, className = "", ...rest }) {
|
|
6707
|
+
function Radio({ label, description, badge, card = false, className = "", ...rest }) {
|
|
6682
6708
|
return /* @__PURE__ */ jsxs58("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
6683
6709
|
/* @__PURE__ */ jsxs58("span", { className: "fd-choice-input", children: [
|
|
6684
6710
|
/* @__PURE__ */ jsx69("input", { type: "radio", ...rest }),
|
|
6685
6711
|
/* @__PURE__ */ jsx69("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ jsx69("span", { className: "fd-choice-dot" }) })
|
|
6686
6712
|
] }),
|
|
6687
6713
|
/* @__PURE__ */ jsxs58("span", { className: "fd-choice-text", children: [
|
|
6688
|
-
/* @__PURE__ */
|
|
6714
|
+
/* @__PURE__ */ jsxs58("span", { className: "fd-choice-title", children: [
|
|
6715
|
+
label,
|
|
6716
|
+
badge ? /* @__PURE__ */ jsx69("span", { className: "fd-choice-badge", children: badge }) : null
|
|
6717
|
+
] }),
|
|
6689
6718
|
description ? /* @__PURE__ */ jsx69("span", { className: "fd-choice-desc", children: description }) : null
|
|
6690
6719
|
] })
|
|
6691
6720
|
] });
|
|
@@ -8277,17 +8306,49 @@ function CodeEditor({
|
|
|
8277
8306
|
] });
|
|
8278
8307
|
}
|
|
8279
8308
|
|
|
8309
|
+
// src/components/forms/RadioGroup.tsx
|
|
8310
|
+
import * as React53 from "react";
|
|
8311
|
+
import { jsx as jsx79, jsxs as jsxs68 } from "react/jsx-runtime";
|
|
8312
|
+
function RadioGroup({ label, labelledBy, options, value, onChange, card = false, disabled = false, name, className = "" }) {
|
|
8313
|
+
const autoName = React53.useId();
|
|
8314
|
+
const labelId = React53.useId();
|
|
8315
|
+
return /* @__PURE__ */ jsxs68("div", { role: "radiogroup", "aria-labelledby": labelledBy ?? labelId, "aria-disabled": disabled || void 0, className: ["fd-radiogroup", className].filter(Boolean).join(" "), children: [
|
|
8316
|
+
labelledBy === void 0 && /* @__PURE__ */ jsx79("span", { id: labelId, className: "fd-radiogroup-label", children: label }),
|
|
8317
|
+
options.map((o) => /* @__PURE__ */ jsx79(
|
|
8318
|
+
Radio,
|
|
8319
|
+
{
|
|
8320
|
+
card,
|
|
8321
|
+
name: name ?? autoName,
|
|
8322
|
+
value: o.value,
|
|
8323
|
+
label: o.label,
|
|
8324
|
+
description: o.description,
|
|
8325
|
+
badge: o.badge,
|
|
8326
|
+
checked: o.value === value,
|
|
8327
|
+
disabled: disabled || o.disabled,
|
|
8328
|
+
onChange: () => onChange(o.value)
|
|
8329
|
+
},
|
|
8330
|
+
o.value
|
|
8331
|
+
))
|
|
8332
|
+
] });
|
|
8333
|
+
}
|
|
8334
|
+
|
|
8335
|
+
// src/components/forms/Fieldset.tsx
|
|
8336
|
+
import { jsx as jsx80 } from "react/jsx-runtime";
|
|
8337
|
+
function Fieldset({ busy = false, className = "", ...rest }) {
|
|
8338
|
+
return /* @__PURE__ */ jsx80("fieldset", { disabled: busy, "aria-busy": busy || void 0, className: ["fd-fieldset", className].filter(Boolean).join(" "), ...rest });
|
|
8339
|
+
}
|
|
8340
|
+
|
|
8280
8341
|
// src/components/platform/AccountMenu.tsx
|
|
8281
|
-
import * as
|
|
8342
|
+
import * as React55 from "react";
|
|
8282
8343
|
|
|
8283
8344
|
// src/kits/sessionContext.tsx
|
|
8284
|
-
import * as
|
|
8285
|
-
var SessionContext =
|
|
8345
|
+
import * as React54 from "react";
|
|
8346
|
+
var SessionContext = React54.createContext(null);
|
|
8286
8347
|
function SessionProvider({ value, children }) {
|
|
8287
|
-
return
|
|
8348
|
+
return React54.createElement(SessionContext.Provider, { value }, children);
|
|
8288
8349
|
}
|
|
8289
8350
|
function useSessionContext() {
|
|
8290
|
-
const ctx =
|
|
8351
|
+
const ctx = React54.useContext(SessionContext);
|
|
8291
8352
|
if (!ctx) {
|
|
8292
8353
|
throw new Error(
|
|
8293
8354
|
"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."
|
|
@@ -8297,11 +8358,11 @@ function useSessionContext() {
|
|
|
8297
8358
|
}
|
|
8298
8359
|
|
|
8299
8360
|
// src/components/platform/AccountMenu.tsx
|
|
8300
|
-
import { Fragment as Fragment19, jsx as
|
|
8361
|
+
import { Fragment as Fragment19, jsx as jsx81, jsxs as jsxs69 } from "react/jsx-runtime";
|
|
8301
8362
|
var DEFAULT_LINKS = [];
|
|
8302
8363
|
var DEFAULT_GROUPS = [];
|
|
8303
8364
|
function Item({ item, onPick }) {
|
|
8304
|
-
return /* @__PURE__ */
|
|
8365
|
+
return /* @__PURE__ */ jsxs69(
|
|
8305
8366
|
"button",
|
|
8306
8367
|
{
|
|
8307
8368
|
type: "button",
|
|
@@ -8309,9 +8370,9 @@ function Item({ item, onPick }) {
|
|
|
8309
8370
|
className: "fd-acct-item",
|
|
8310
8371
|
onClick: () => onPick(item),
|
|
8311
8372
|
children: [
|
|
8312
|
-
item.icon ? /* @__PURE__ */
|
|
8313
|
-
/* @__PURE__ */
|
|
8314
|
-
item.badge ? /* @__PURE__ */
|
|
8373
|
+
item.icon ? /* @__PURE__ */ jsx81("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
|
|
8374
|
+
/* @__PURE__ */ jsx81("span", { style: { flex: 1 }, children: item.label }),
|
|
8375
|
+
item.badge ? /* @__PURE__ */ jsx81(Badge, { tone: "neutral", children: item.badge }) : null
|
|
8315
8376
|
]
|
|
8316
8377
|
}
|
|
8317
8378
|
);
|
|
@@ -8327,11 +8388,11 @@ function AccountMenu({
|
|
|
8327
8388
|
...rest
|
|
8328
8389
|
}) {
|
|
8329
8390
|
const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
|
|
8330
|
-
const [open2, setOpen] =
|
|
8331
|
-
const [switching, setSwitching] =
|
|
8332
|
-
const [signingOut, setSigningOut] =
|
|
8333
|
-
const [signOutError, setSignOutError] =
|
|
8334
|
-
const ref =
|
|
8391
|
+
const [open2, setOpen] = React55.useState(false);
|
|
8392
|
+
const [switching, setSwitching] = React55.useState(false);
|
|
8393
|
+
const [signingOut, setSigningOut] = React55.useState(false);
|
|
8394
|
+
const [signOutError, setSignOutError] = React55.useState(null);
|
|
8395
|
+
const ref = React55.useRef(null);
|
|
8335
8396
|
const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
|
|
8336
8397
|
const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || !pending && can2(l.perm)) })).filter((g) => g.links.length);
|
|
8337
8398
|
const closeMenu = () => {
|
|
@@ -8359,8 +8420,8 @@ function AccountMenu({
|
|
|
8359
8420
|
}
|
|
8360
8421
|
};
|
|
8361
8422
|
const showSwitcher = allowUserSwitch && !!demo;
|
|
8362
|
-
return /* @__PURE__ */
|
|
8363
|
-
/* @__PURE__ */
|
|
8423
|
+
return /* @__PURE__ */ jsxs69(Fragment19, { children: [
|
|
8424
|
+
/* @__PURE__ */ jsxs69(
|
|
8364
8425
|
"button",
|
|
8365
8426
|
{
|
|
8366
8427
|
type: "button",
|
|
@@ -8372,12 +8433,12 @@ function AccountMenu({
|
|
|
8372
8433
|
onClick: () => open2 ? closeMenu() : setOpen(true),
|
|
8373
8434
|
...rest,
|
|
8374
8435
|
children: [
|
|
8375
|
-
/* @__PURE__ */
|
|
8376
|
-
/* @__PURE__ */
|
|
8436
|
+
/* @__PURE__ */ jsx81(Avatar, { name: user.name, size: "sm" }),
|
|
8437
|
+
/* @__PURE__ */ jsx81("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
|
|
8377
8438
|
]
|
|
8378
8439
|
}
|
|
8379
8440
|
),
|
|
8380
|
-
/* @__PURE__ */
|
|
8441
|
+
/* @__PURE__ */ jsx81(
|
|
8381
8442
|
Popover,
|
|
8382
8443
|
{
|
|
8383
8444
|
open: open2,
|
|
@@ -8385,27 +8446,27 @@ function AccountMenu({
|
|
|
8385
8446
|
onClose: closeMenu,
|
|
8386
8447
|
placement: "bottom-end",
|
|
8387
8448
|
width: 272,
|
|
8388
|
-
children: /* @__PURE__ */
|
|
8389
|
-
/* @__PURE__ */
|
|
8390
|
-
/* @__PURE__ */
|
|
8391
|
-
/* @__PURE__ */
|
|
8392
|
-
/* @__PURE__ */
|
|
8393
|
-
/* @__PURE__ */
|
|
8449
|
+
children: /* @__PURE__ */ jsxs69("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
|
|
8450
|
+
/* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
8451
|
+
/* @__PURE__ */ jsx81(Avatar, { name: user.name }),
|
|
8452
|
+
/* @__PURE__ */ jsxs69("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
|
|
8453
|
+
/* @__PURE__ */ jsx81("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
|
|
8454
|
+
/* @__PURE__ */ jsx81("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
|
|
8394
8455
|
] })
|
|
8395
8456
|
] }),
|
|
8396
|
-
showRoles && roles.length ? /* @__PURE__ */
|
|
8397
|
-
visibleLinks.length ? /* @__PURE__ */
|
|
8398
|
-
visibleGroups.map((g) => /* @__PURE__ */
|
|
8399
|
-
/* @__PURE__ */
|
|
8400
|
-
g.links.map((l) => /* @__PURE__ */
|
|
8457
|
+
showRoles && roles.length ? /* @__PURE__ */ jsx81("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ jsx81(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
|
|
8458
|
+
visibleLinks.length ? /* @__PURE__ */ jsx81("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ jsx81(Item, { item: l, onPick: pick }, l.id)) }) : null,
|
|
8459
|
+
visibleGroups.map((g) => /* @__PURE__ */ jsxs69("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
8460
|
+
/* @__PURE__ */ jsx81("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
|
|
8461
|
+
g.links.map((l) => /* @__PURE__ */ jsx81(Item, { item: l, onPick: pick }, l.id))
|
|
8401
8462
|
] }, g.label)),
|
|
8402
|
-
showSwitcher && demo ? /* @__PURE__ */
|
|
8403
|
-
/* @__PURE__ */
|
|
8404
|
-
/* @__PURE__ */
|
|
8405
|
-
/* @__PURE__ */
|
|
8406
|
-
/* @__PURE__ */
|
|
8463
|
+
showSwitcher && demo ? /* @__PURE__ */ jsxs69("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
8464
|
+
/* @__PURE__ */ jsxs69("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
|
|
8465
|
+
/* @__PURE__ */ jsx81("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
|
|
8466
|
+
/* @__PURE__ */ jsx81("span", { style: { flex: 1 }, children: "View as another member" }),
|
|
8467
|
+
/* @__PURE__ */ jsx81("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
|
|
8407
8468
|
] }),
|
|
8408
|
-
switching ? /* @__PURE__ */
|
|
8469
|
+
switching ? /* @__PURE__ */ jsx81("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ jsxs69(
|
|
8409
8470
|
"button",
|
|
8410
8471
|
{
|
|
8411
8472
|
type: "button",
|
|
@@ -8417,19 +8478,19 @@ function AccountMenu({
|
|
|
8417
8478
|
setSwitching(false);
|
|
8418
8479
|
},
|
|
8419
8480
|
children: [
|
|
8420
|
-
/* @__PURE__ */
|
|
8421
|
-
/* @__PURE__ */
|
|
8422
|
-
/* @__PURE__ */
|
|
8423
|
-
u.roles ? /* @__PURE__ */
|
|
8481
|
+
/* @__PURE__ */ jsx81(Avatar, { name: u.name, size: "sm" }),
|
|
8482
|
+
/* @__PURE__ */ jsxs69("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
|
|
8483
|
+
/* @__PURE__ */ jsx81("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
|
|
8484
|
+
u.roles ? /* @__PURE__ */ jsx81("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
|
|
8424
8485
|
] }),
|
|
8425
|
-
u.id === user.id ? /* @__PURE__ */
|
|
8486
|
+
u.id === user.id ? /* @__PURE__ */ jsx81("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
|
|
8426
8487
|
]
|
|
8427
8488
|
},
|
|
8428
8489
|
u.id
|
|
8429
8490
|
)) }) : null
|
|
8430
8491
|
] }) : null,
|
|
8431
|
-
/* @__PURE__ */
|
|
8432
|
-
/* @__PURE__ */
|
|
8492
|
+
/* @__PURE__ */ jsxs69("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
8493
|
+
/* @__PURE__ */ jsxs69(
|
|
8433
8494
|
"button",
|
|
8434
8495
|
{
|
|
8435
8496
|
type: "button",
|
|
@@ -8439,14 +8500,14 @@ function AccountMenu({
|
|
|
8439
8500
|
disabled: signingOut,
|
|
8440
8501
|
onClick: signOut,
|
|
8441
8502
|
children: [
|
|
8442
|
-
signingOut ? /* @__PURE__ */
|
|
8443
|
-
/* @__PURE__ */
|
|
8503
|
+
signingOut ? /* @__PURE__ */ jsx81(Spinner, { size: "sm" }) : /* @__PURE__ */ jsx81("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
|
|
8504
|
+
/* @__PURE__ */ jsx81("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
|
|
8444
8505
|
]
|
|
8445
8506
|
}
|
|
8446
8507
|
),
|
|
8447
|
-
signOutError ? /* @__PURE__ */
|
|
8448
|
-
/* @__PURE__ */
|
|
8449
|
-
/* @__PURE__ */
|
|
8508
|
+
signOutError ? /* @__PURE__ */ jsxs69("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
|
|
8509
|
+
/* @__PURE__ */ jsx81("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
|
|
8510
|
+
/* @__PURE__ */ jsx81("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
|
|
8450
8511
|
] }) : null
|
|
8451
8512
|
] })
|
|
8452
8513
|
] })
|
|
@@ -8456,13 +8517,13 @@ function AccountMenu({
|
|
|
8456
8517
|
}
|
|
8457
8518
|
|
|
8458
8519
|
// src/components/platform/AppSwitcher.tsx
|
|
8459
|
-
import * as
|
|
8460
|
-
import { jsx as
|
|
8520
|
+
import * as React56 from "react";
|
|
8521
|
+
import { jsx as jsx82, jsxs as jsxs70 } from "react/jsx-runtime";
|
|
8461
8522
|
function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
8462
8523
|
const { apps: contextApps } = useSessionContext();
|
|
8463
8524
|
const apps = appsProp ?? contextApps ?? [];
|
|
8464
|
-
const [open2, setOpen] =
|
|
8465
|
-
const anchorRef =
|
|
8525
|
+
const [open2, setOpen] = React56.useState(false);
|
|
8526
|
+
const anchorRef = React56.useRef(null);
|
|
8466
8527
|
if (!apps.length) return null;
|
|
8467
8528
|
const items = apps.map((app) => ({
|
|
8468
8529
|
id: app.key,
|
|
@@ -8476,8 +8537,8 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
8476
8537
|
window.location.href = app.url;
|
|
8477
8538
|
}
|
|
8478
8539
|
}));
|
|
8479
|
-
return /* @__PURE__ */
|
|
8480
|
-
/* @__PURE__ */
|
|
8540
|
+
return /* @__PURE__ */ jsxs70(React56.Fragment, { children: [
|
|
8541
|
+
/* @__PURE__ */ jsx82("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx82(
|
|
8481
8542
|
IconButton,
|
|
8482
8543
|
{
|
|
8483
8544
|
icon: "squares-four",
|
|
@@ -8487,7 +8548,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
8487
8548
|
onClick: () => setOpen((v) => !v)
|
|
8488
8549
|
}
|
|
8489
8550
|
) }),
|
|
8490
|
-
/* @__PURE__ */
|
|
8551
|
+
/* @__PURE__ */ jsx82(
|
|
8491
8552
|
Popover,
|
|
8492
8553
|
{
|
|
8493
8554
|
open: open2,
|
|
@@ -8498,17 +8559,17 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
8498
8559
|
label: "All flytedesk apps",
|
|
8499
8560
|
width: 240,
|
|
8500
8561
|
maxHeight: 360,
|
|
8501
|
-
children: /* @__PURE__ */
|
|
8562
|
+
children: /* @__PURE__ */ jsx82(Menu, { items, onClose: () => setOpen(false) })
|
|
8502
8563
|
}
|
|
8503
8564
|
)
|
|
8504
8565
|
] });
|
|
8505
8566
|
}
|
|
8506
8567
|
|
|
8507
8568
|
// src/components/platform/AppearanceMenu.tsx
|
|
8508
|
-
import * as
|
|
8569
|
+
import * as React59 from "react";
|
|
8509
8570
|
|
|
8510
8571
|
// src/kits/appearance.ts
|
|
8511
|
-
import * as
|
|
8572
|
+
import * as React57 from "react";
|
|
8512
8573
|
var DEFAULT_STORAGE_KEY = "fd-appearance";
|
|
8513
8574
|
var DEFAULT_PREFS = {
|
|
8514
8575
|
theme: "system",
|
|
@@ -8620,8 +8681,8 @@ function watchAppearance(store, root = document.documentElement) {
|
|
|
8620
8681
|
};
|
|
8621
8682
|
}
|
|
8622
8683
|
function useAppearancePrefs(store) {
|
|
8623
|
-
const prefs =
|
|
8624
|
-
const update =
|
|
8684
|
+
const prefs = React57.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
8685
|
+
const update = React57.useCallback(
|
|
8625
8686
|
(patch) => {
|
|
8626
8687
|
store.write({ ...store.getSnapshot(), ...patch });
|
|
8627
8688
|
},
|
|
@@ -8631,21 +8692,21 @@ function useAppearancePrefs(store) {
|
|
|
8631
8692
|
}
|
|
8632
8693
|
|
|
8633
8694
|
// src/components/platform/AppearanceProvider.tsx
|
|
8634
|
-
import * as
|
|
8635
|
-
import { jsx as
|
|
8636
|
-
var AppearanceStoreContext =
|
|
8695
|
+
import * as React58 from "react";
|
|
8696
|
+
import { jsx as jsx83 } from "react/jsx-runtime";
|
|
8697
|
+
var AppearanceStoreContext = React58.createContext(null);
|
|
8637
8698
|
function AppearanceProvider({ store, children }) {
|
|
8638
|
-
|
|
8639
|
-
return /* @__PURE__ */
|
|
8699
|
+
React58.useLayoutEffect(() => watchAppearance(store), [store]);
|
|
8700
|
+
return /* @__PURE__ */ jsx83(AppearanceStoreContext.Provider, { value: store, children });
|
|
8640
8701
|
}
|
|
8641
8702
|
function useAppearanceStore() {
|
|
8642
|
-
const store =
|
|
8703
|
+
const store = React58.useContext(AppearanceStoreContext);
|
|
8643
8704
|
if (!store) throw new Error("AppearanceMenu and useAppearanceStore must be rendered inside an <AppearanceProvider>.");
|
|
8644
8705
|
return store;
|
|
8645
8706
|
}
|
|
8646
8707
|
|
|
8647
8708
|
// src/components/platform/AppearanceMenu.tsx
|
|
8648
|
-
import { jsx as
|
|
8709
|
+
import { jsx as jsx84, jsxs as jsxs71 } from "react/jsx-runtime";
|
|
8649
8710
|
var THEME_OPTIONS = [
|
|
8650
8711
|
{ value: "light", label: "Light" },
|
|
8651
8712
|
{ value: "dark", label: "Dark" },
|
|
@@ -8659,11 +8720,11 @@ var TEXT_SCALE_OPTIONS = [
|
|
|
8659
8720
|
];
|
|
8660
8721
|
function AppearanceMenu({ className = "" }) {
|
|
8661
8722
|
const [prefs, update] = useAppearancePrefs(useAppearanceStore());
|
|
8662
|
-
const [open2, setOpen] =
|
|
8663
|
-
const anchorRef =
|
|
8723
|
+
const [open2, setOpen] = React59.useState(false);
|
|
8724
|
+
const anchorRef = React59.useRef(null);
|
|
8664
8725
|
const patch = (p) => update(p);
|
|
8665
|
-
return /* @__PURE__ */
|
|
8666
|
-
/* @__PURE__ */
|
|
8726
|
+
return /* @__PURE__ */ jsxs71(React59.Fragment, { children: [
|
|
8727
|
+
/* @__PURE__ */ jsx84("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx84(
|
|
8667
8728
|
IconButton,
|
|
8668
8729
|
{
|
|
8669
8730
|
icon: "circle-half",
|
|
@@ -8671,7 +8732,7 @@ function AppearanceMenu({ className = "" }) {
|
|
|
8671
8732
|
onClick: () => setOpen((v) => !v)
|
|
8672
8733
|
}
|
|
8673
8734
|
) }),
|
|
8674
|
-
/* @__PURE__ */
|
|
8735
|
+
/* @__PURE__ */ jsx84(
|
|
8675
8736
|
Popover,
|
|
8676
8737
|
{
|
|
8677
8738
|
open: open2,
|
|
@@ -8681,10 +8742,10 @@ function AppearanceMenu({ className = "" }) {
|
|
|
8681
8742
|
padded: true,
|
|
8682
8743
|
width: 260,
|
|
8683
8744
|
label: "Appearance settings",
|
|
8684
|
-
children: /* @__PURE__ */
|
|
8685
|
-
/* @__PURE__ */
|
|
8686
|
-
/* @__PURE__ */
|
|
8687
|
-
/* @__PURE__ */
|
|
8745
|
+
children: /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
|
|
8746
|
+
/* @__PURE__ */ jsxs71("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
8747
|
+
/* @__PURE__ */ jsx84("span", { className: "fd-field-label", children: "Theme" }),
|
|
8748
|
+
/* @__PURE__ */ jsx84(
|
|
8688
8749
|
SegmentedControl,
|
|
8689
8750
|
{
|
|
8690
8751
|
options: THEME_OPTIONS,
|
|
@@ -8694,9 +8755,9 @@ function AppearanceMenu({ className = "" }) {
|
|
|
8694
8755
|
}
|
|
8695
8756
|
)
|
|
8696
8757
|
] }),
|
|
8697
|
-
/* @__PURE__ */
|
|
8698
|
-
/* @__PURE__ */
|
|
8699
|
-
/* @__PURE__ */
|
|
8758
|
+
/* @__PURE__ */ jsxs71("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
8759
|
+
/* @__PURE__ */ jsx84("span", { className: "fd-field-label", children: "Text size" }),
|
|
8760
|
+
/* @__PURE__ */ jsx84(
|
|
8700
8761
|
SegmentedControl,
|
|
8701
8762
|
{
|
|
8702
8763
|
options: TEXT_SCALE_OPTIONS,
|
|
@@ -8706,7 +8767,7 @@ function AppearanceMenu({ className = "" }) {
|
|
|
8706
8767
|
}
|
|
8707
8768
|
)
|
|
8708
8769
|
] }),
|
|
8709
|
-
/* @__PURE__ */
|
|
8770
|
+
/* @__PURE__ */ jsx84(
|
|
8710
8771
|
Switch,
|
|
8711
8772
|
{
|
|
8712
8773
|
label: "High contrast",
|
|
@@ -8715,7 +8776,7 @@ function AppearanceMenu({ className = "" }) {
|
|
|
8715
8776
|
onChange: (e) => patch({ highContrast: e.target.checked })
|
|
8716
8777
|
}
|
|
8717
8778
|
),
|
|
8718
|
-
/* @__PURE__ */
|
|
8779
|
+
/* @__PURE__ */ jsx84(
|
|
8719
8780
|
Switch,
|
|
8720
8781
|
{
|
|
8721
8782
|
label: "Reduce motion",
|
|
@@ -8731,14 +8792,14 @@ function AppearanceMenu({ className = "" }) {
|
|
|
8731
8792
|
}
|
|
8732
8793
|
|
|
8733
8794
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
8734
|
-
import * as
|
|
8735
|
-
import { jsx as
|
|
8795
|
+
import * as React60 from "react";
|
|
8796
|
+
import { jsx as jsx85, jsxs as jsxs72 } from "react/jsx-runtime";
|
|
8736
8797
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
8737
8798
|
function Json({ obj }) {
|
|
8738
|
-
return /* @__PURE__ */
|
|
8799
|
+
return /* @__PURE__ */ jsx85("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
8739
8800
|
}
|
|
8740
8801
|
function Endpoint({ s, onRequest }) {
|
|
8741
|
-
const [tried, setTried] =
|
|
8802
|
+
const [tried, setTried] = React60.useState(null);
|
|
8742
8803
|
const run = async () => {
|
|
8743
8804
|
setTried("busy");
|
|
8744
8805
|
const t0 = (window.performance || Date).now();
|
|
@@ -8749,50 +8810,50 @@ function Endpoint({ s, onRequest }) {
|
|
|
8749
8810
|
setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
|
|
8750
8811
|
}
|
|
8751
8812
|
};
|
|
8752
|
-
return /* @__PURE__ */
|
|
8753
|
-
/* @__PURE__ */
|
|
8754
|
-
/* @__PURE__ */
|
|
8755
|
-
/* @__PURE__ */
|
|
8756
|
-
s.isList ? /* @__PURE__ */
|
|
8757
|
-
/* @__PURE__ */
|
|
8758
|
-
/* @__PURE__ */
|
|
8813
|
+
return /* @__PURE__ */ jsx85(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
8814
|
+
/* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
|
|
8815
|
+
/* @__PURE__ */ jsx85(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
|
|
8816
|
+
/* @__PURE__ */ jsx85("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
|
|
8817
|
+
s.isList ? /* @__PURE__ */ jsx85(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
|
|
8818
|
+
/* @__PURE__ */ jsx85("span", { style: { flex: 1 } }),
|
|
8819
|
+
/* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
8759
8820
|
s.latency[0],
|
|
8760
8821
|
"\u2013",
|
|
8761
8822
|
s.latency[1],
|
|
8762
8823
|
"ms"
|
|
8763
8824
|
] }),
|
|
8764
|
-
/* @__PURE__ */
|
|
8825
|
+
/* @__PURE__ */ jsx85(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
|
|
8765
8826
|
] }),
|
|
8766
|
-
/* @__PURE__ */
|
|
8767
|
-
/* @__PURE__ */
|
|
8768
|
-
/* @__PURE__ */
|
|
8769
|
-
/* @__PURE__ */
|
|
8770
|
-
s.usedBy && s.usedBy.length ? /* @__PURE__ */
|
|
8827
|
+
/* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
|
|
8828
|
+
/* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8829
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
|
|
8830
|
+
/* @__PURE__ */ jsx85("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
|
|
8831
|
+
s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx85("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx85(Tag, { children: u }, u)) }) : null
|
|
8771
8832
|
] }),
|
|
8772
|
-
/* @__PURE__ */
|
|
8773
|
-
s.request ? /* @__PURE__ */
|
|
8774
|
-
/* @__PURE__ */
|
|
8775
|
-
/* @__PURE__ */
|
|
8833
|
+
/* @__PURE__ */ jsxs72("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
|
|
8834
|
+
s.request ? /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8835
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Request body" }),
|
|
8836
|
+
/* @__PURE__ */ jsx85(Json, { obj: s.request })
|
|
8776
8837
|
] }) : null,
|
|
8777
|
-
s.query ? /* @__PURE__ */
|
|
8778
|
-
/* @__PURE__ */
|
|
8779
|
-
/* @__PURE__ */
|
|
8838
|
+
s.query ? /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8839
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Query" }),
|
|
8840
|
+
/* @__PURE__ */ jsx85(Json, { obj: s.query })
|
|
8780
8841
|
] }) : null,
|
|
8781
|
-
/* @__PURE__ */
|
|
8782
|
-
/* @__PURE__ */
|
|
8783
|
-
/* @__PURE__ */
|
|
8842
|
+
/* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8843
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Response 200" }),
|
|
8844
|
+
/* @__PURE__ */ jsx85(Json, { obj: s.response })
|
|
8784
8845
|
] })
|
|
8785
8846
|
] }),
|
|
8786
|
-
s.notes ? /* @__PURE__ */
|
|
8787
|
-
tried && tried !== "busy" ? /* @__PURE__ */
|
|
8788
|
-
/* @__PURE__ */
|
|
8789
|
-
/* @__PURE__ */
|
|
8790
|
-
/* @__PURE__ */
|
|
8847
|
+
s.notes ? /* @__PURE__ */ jsx85(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
|
|
8848
|
+
tried && tried !== "busy" ? /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8849
|
+
/* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
8850
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
|
|
8851
|
+
/* @__PURE__ */ jsxs72(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
|
|
8791
8852
|
tried.ms,
|
|
8792
8853
|
"ms"
|
|
8793
8854
|
] })
|
|
8794
8855
|
] }),
|
|
8795
|
-
/* @__PURE__ */
|
|
8856
|
+
/* @__PURE__ */ jsx85(Json, { obj: tried.error ? { error: tried.error } : tried.data })
|
|
8796
8857
|
] }) : null
|
|
8797
8858
|
] })
|
|
8798
8859
|
] }) });
|
|
@@ -8811,58 +8872,58 @@ function ApiSpecBrowser({
|
|
|
8811
8872
|
className = "",
|
|
8812
8873
|
...rest
|
|
8813
8874
|
}) {
|
|
8814
|
-
const [q, setQ] =
|
|
8815
|
-
const [method, setMethod] =
|
|
8816
|
-
const [mod, setMod] =
|
|
8817
|
-
const [listOnly, setListOnly] =
|
|
8875
|
+
const [q, setQ] = React60.useState("");
|
|
8876
|
+
const [method, setMethod] = React60.useState(null);
|
|
8877
|
+
const [mod, setMod] = React60.useState(null);
|
|
8878
|
+
const [listOnly, setListOnly] = React60.useState(false);
|
|
8818
8879
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
8819
8880
|
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())));
|
|
8820
8881
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
8821
8882
|
const methods = [...new Set(spec.map((s) => s.method))];
|
|
8822
8883
|
const listCount = spec.filter((s) => s.isList).length;
|
|
8823
|
-
return /* @__PURE__ */
|
|
8824
|
-
/* @__PURE__ */
|
|
8825
|
-
kicker ? /* @__PURE__ */
|
|
8826
|
-
/* @__PURE__ */
|
|
8827
|
-
lede ? /* @__PURE__ */
|
|
8884
|
+
return /* @__PURE__ */ jsxs72("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
|
|
8885
|
+
/* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
8886
|
+
kicker ? /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: kicker }) : null,
|
|
8887
|
+
/* @__PURE__ */ jsx85("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
8888
|
+
lede ? /* @__PURE__ */ jsx85("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
|
|
8828
8889
|
] }),
|
|
8829
|
-
modules && modules.length ? /* @__PURE__ */
|
|
8830
|
-
/* @__PURE__ */
|
|
8831
|
-
/* @__PURE__ */
|
|
8832
|
-
/* @__PURE__ */
|
|
8890
|
+
modules && modules.length ? /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
8891
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
|
|
8892
|
+
/* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
8893
|
+
/* @__PURE__ */ jsxs72(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
|
|
8833
8894
|
"All screens ",
|
|
8834
|
-
/* @__PURE__ */
|
|
8895
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-mono", children: spec.length })
|
|
8835
8896
|
] }),
|
|
8836
|
-
modules.map((m) => /* @__PURE__ */
|
|
8897
|
+
modules.map((m) => /* @__PURE__ */ jsxs72(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
|
|
8837
8898
|
m.label,
|
|
8838
8899
|
" ",
|
|
8839
|
-
/* @__PURE__ */
|
|
8900
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-mono", children: m.endpoints.length })
|
|
8840
8901
|
] }, m.id))
|
|
8841
8902
|
] }),
|
|
8842
|
-
activeModule ? /* @__PURE__ */
|
|
8903
|
+
activeModule ? /* @__PURE__ */ jsx85(
|
|
8843
8904
|
Flag,
|
|
8844
8905
|
{
|
|
8845
8906
|
tone: "info",
|
|
8846
8907
|
statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
|
|
8847
8908
|
cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
|
|
8848
|
-
actions: /* @__PURE__ */
|
|
8909
|
+
actions: /* @__PURE__ */ jsx85(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
|
|
8849
8910
|
}
|
|
8850
8911
|
) : null
|
|
8851
8912
|
] }) : null,
|
|
8852
|
-
sourceNote ? /* @__PURE__ */
|
|
8853
|
-
/* @__PURE__ */
|
|
8854
|
-
/* @__PURE__ */
|
|
8855
|
-
methods.map((m) => /* @__PURE__ */
|
|
8913
|
+
sourceNote ? /* @__PURE__ */ jsx85(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
|
|
8914
|
+
/* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
8915
|
+
/* @__PURE__ */ jsx85(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
|
|
8916
|
+
methods.map((m) => /* @__PURE__ */ jsxs72(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
|
|
8856
8917
|
m,
|
|
8857
8918
|
" ",
|
|
8858
|
-
/* @__PURE__ */
|
|
8919
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
|
|
8859
8920
|
] }, m)),
|
|
8860
|
-
listCount ? /* @__PURE__ */
|
|
8921
|
+
listCount ? /* @__PURE__ */ jsxs72(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
|
|
8861
8922
|
"Paged lists ",
|
|
8862
|
-
/* @__PURE__ */
|
|
8923
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-mono", children: listCount })
|
|
8863
8924
|
] }) : null,
|
|
8864
|
-
/* @__PURE__ */
|
|
8865
|
-
/* @__PURE__ */
|
|
8925
|
+
/* @__PURE__ */ jsx85("span", { style: { flex: 1 } }),
|
|
8926
|
+
/* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted", children: [
|
|
8866
8927
|
hits.length,
|
|
8867
8928
|
" of ",
|
|
8868
8929
|
spec.length,
|
|
@@ -8870,31 +8931,31 @@ function ApiSpecBrowser({
|
|
|
8870
8931
|
listCount ? " \xB7 " + listCount + " paged" : ""
|
|
8871
8932
|
] })
|
|
8872
8933
|
] }),
|
|
8873
|
-
hits.length === 0 ? /* @__PURE__ */
|
|
8934
|
+
hits.length === 0 ? /* @__PURE__ */ jsx85(Card, { elevation: "flat", children: /* @__PURE__ */ jsx85("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
|
|
8874
8935
|
const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
|
|
8875
8936
|
if (!items.length) return null;
|
|
8876
|
-
return /* @__PURE__ */
|
|
8877
|
-
/* @__PURE__ */
|
|
8878
|
-
items.map((s) => /* @__PURE__ */
|
|
8937
|
+
return /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 12 }, children: [
|
|
8938
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-label-lg", children: g }),
|
|
8939
|
+
items.map((s) => /* @__PURE__ */ jsx85(Endpoint, { s, onRequest }, s.id))
|
|
8879
8940
|
] }, g);
|
|
8880
8941
|
}),
|
|
8881
|
-
conventions && conventions.length ? /* @__PURE__ */
|
|
8882
|
-
/* @__PURE__ */
|
|
8883
|
-
/* @__PURE__ */
|
|
8942
|
+
conventions && conventions.length ? /* @__PURE__ */ jsx85(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx85("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
|
|
8943
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
|
|
8944
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
|
|
8884
8945
|
] }, k)) }) }) : null,
|
|
8885
|
-
openQuestions && openQuestions.length ? /* @__PURE__ */
|
|
8886
|
-
/* @__PURE__ */
|
|
8887
|
-
/* @__PURE__ */
|
|
8888
|
-
/* @__PURE__ */
|
|
8889
|
-
/* @__PURE__ */
|
|
8946
|
+
openQuestions && openQuestions.length ? /* @__PURE__ */ jsx85(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx85("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
|
|
8947
|
+
/* @__PURE__ */ jsx85(Badge, { tone: "danger", children: id }),
|
|
8948
|
+
/* @__PURE__ */ jsxs72("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
|
|
8949
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
|
|
8950
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-body-sm fd-muted", children: why })
|
|
8890
8951
|
] })
|
|
8891
8952
|
] }, id)) }) }) : null
|
|
8892
8953
|
] });
|
|
8893
8954
|
}
|
|
8894
8955
|
|
|
8895
8956
|
// src/components/platform/ProfilePage.tsx
|
|
8896
|
-
import * as
|
|
8897
|
-
import { jsx as
|
|
8957
|
+
import * as React61 from "react";
|
|
8958
|
+
import { jsx as jsx86, jsxs as jsxs73 } from "react/jsx-runtime";
|
|
8898
8959
|
function fieldInitialValue(field, user) {
|
|
8899
8960
|
if (field.value) return field.value(user);
|
|
8900
8961
|
const raw = user[field.key];
|
|
@@ -8929,21 +8990,21 @@ function ProfilePage({
|
|
|
8929
8990
|
}) {
|
|
8930
8991
|
const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
|
|
8931
8992
|
const user = userProp || sessionUser;
|
|
8932
|
-
const initialFieldValues =
|
|
8993
|
+
const initialFieldValues = React61.useMemo(() => {
|
|
8933
8994
|
const values2 = {};
|
|
8934
8995
|
for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
|
|
8935
8996
|
return values2;
|
|
8936
8997
|
}, [user.id, fields]);
|
|
8937
|
-
const initialNotify =
|
|
8998
|
+
const initialNotify = React61.useMemo(() => {
|
|
8938
8999
|
const values2 = {};
|
|
8939
9000
|
for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
|
|
8940
9001
|
return values2;
|
|
8941
9002
|
}, [user.id, notifications]);
|
|
8942
|
-
const [values, setValues] =
|
|
8943
|
-
const [notify, setNotify] =
|
|
8944
|
-
const [saving, setSaving] =
|
|
8945
|
-
const [saved, setSaved] =
|
|
8946
|
-
const [prevUserId, setPrevUserId] =
|
|
9003
|
+
const [values, setValues] = React61.useState(initialFieldValues);
|
|
9004
|
+
const [notify, setNotify] = React61.useState(initialNotify);
|
|
9005
|
+
const [saving, setSaving] = React61.useState(false);
|
|
9006
|
+
const [saved, setSaved] = React61.useState(false);
|
|
9007
|
+
const [prevUserId, setPrevUserId] = React61.useState(user.id);
|
|
8947
9008
|
if (user.id !== prevUserId) {
|
|
8948
9009
|
setPrevUserId(user.id);
|
|
8949
9010
|
setValues(initialFieldValues);
|
|
@@ -8980,37 +9041,37 @@ function ProfilePage({
|
|
|
8980
9041
|
};
|
|
8981
9042
|
const displayName = fields.some((f) => f.key === "name") ? values.name || user.name : user.name;
|
|
8982
9043
|
const fieldGroups = groupFields(fields);
|
|
8983
|
-
return /* @__PURE__ */
|
|
8984
|
-
/* @__PURE__ */
|
|
8985
|
-
/* @__PURE__ */
|
|
8986
|
-
/* @__PURE__ */
|
|
8987
|
-
/* @__PURE__ */
|
|
9044
|
+
return /* @__PURE__ */ jsxs73("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
|
|
9045
|
+
/* @__PURE__ */ jsxs73("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
9046
|
+
/* @__PURE__ */ jsx86("span", { className: "fd-overline fd-muted", children: "Account" }),
|
|
9047
|
+
/* @__PURE__ */ jsx86("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
|
|
9048
|
+
/* @__PURE__ */ jsx86("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." })
|
|
8988
9049
|
] }),
|
|
8989
|
-
/* @__PURE__ */
|
|
8990
|
-
/* @__PURE__ */
|
|
8991
|
-
/* @__PURE__ */
|
|
8992
|
-
/* @__PURE__ */
|
|
8993
|
-
/* @__PURE__ */
|
|
8994
|
-
roles.map((r) => /* @__PURE__ */
|
|
8995
|
-
user.sso ? /* @__PURE__ */
|
|
9050
|
+
/* @__PURE__ */ jsx86(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs73("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
|
|
9051
|
+
/* @__PURE__ */ jsx86(Avatar, { name: displayName, size: "lg" }),
|
|
9052
|
+
/* @__PURE__ */ jsxs73("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
|
|
9053
|
+
/* @__PURE__ */ jsx86("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
|
|
9054
|
+
/* @__PURE__ */ jsxs73("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
|
|
9055
|
+
roles.map((r) => /* @__PURE__ */ jsx86(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
|
|
9056
|
+
user.sso ? /* @__PURE__ */ jsx86(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
|
|
8996
9057
|
] })
|
|
8997
9058
|
] }),
|
|
8998
|
-
onChangePhoto ? /* @__PURE__ */
|
|
9059
|
+
onChangePhoto ? /* @__PURE__ */ jsx86(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
|
|
8999
9060
|
] }) }),
|
|
9000
|
-
fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */
|
|
9061
|
+
fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ jsx86(
|
|
9001
9062
|
Card,
|
|
9002
9063
|
{
|
|
9003
|
-
title: description ? /* @__PURE__ */
|
|
9004
|
-
/* @__PURE__ */
|
|
9005
|
-
/* @__PURE__ */
|
|
9064
|
+
title: description ? /* @__PURE__ */ jsxs73("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
9065
|
+
/* @__PURE__ */ jsx86("span", { children: group }),
|
|
9066
|
+
/* @__PURE__ */ jsx86("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
|
|
9006
9067
|
] }) : group,
|
|
9007
9068
|
elevation: "flat",
|
|
9008
|
-
children: /* @__PURE__ */
|
|
9009
|
-
/* @__PURE__ */
|
|
9069
|
+
children: /* @__PURE__ */ jsxs73("div", { className: "fd-stack", style: { gap: 14 }, children: [
|
|
9070
|
+
/* @__PURE__ */ jsx86("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
|
|
9010
9071
|
const help = typeof field.help === "function" ? field.help(user) : field.help;
|
|
9011
9072
|
const readOnly = field.readOnly || field.type === "readonly";
|
|
9012
9073
|
if (field.type === "select") {
|
|
9013
|
-
return /* @__PURE__ */
|
|
9074
|
+
return /* @__PURE__ */ jsx86(
|
|
9014
9075
|
Select,
|
|
9015
9076
|
{
|
|
9016
9077
|
label: field.label,
|
|
@@ -9024,7 +9085,7 @@ function ProfilePage({
|
|
|
9024
9085
|
field.key
|
|
9025
9086
|
);
|
|
9026
9087
|
}
|
|
9027
|
-
return /* @__PURE__ */
|
|
9088
|
+
return /* @__PURE__ */ jsx86(
|
|
9028
9089
|
Input,
|
|
9029
9090
|
{
|
|
9030
9091
|
label: field.label,
|
|
@@ -9040,7 +9101,7 @@ function ProfilePage({
|
|
|
9040
9101
|
}) }),
|
|
9041
9102
|
groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
|
|
9042
9103
|
const help = typeof field.help === "function" ? field.help(user) : field.help;
|
|
9043
|
-
return /* @__PURE__ */
|
|
9104
|
+
return /* @__PURE__ */ jsx86(
|
|
9044
9105
|
Textarea,
|
|
9045
9106
|
{
|
|
9046
9107
|
label: field.label,
|
|
@@ -9060,16 +9121,16 @@ function ProfilePage({
|
|
|
9060
9121
|
group
|
|
9061
9122
|
)),
|
|
9062
9123
|
extra,
|
|
9063
|
-
notifications.length > 0 ? /* @__PURE__ */
|
|
9064
|
-
/* @__PURE__ */
|
|
9124
|
+
notifications.length > 0 ? /* @__PURE__ */ jsx86(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ jsx86("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ jsx86(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
|
|
9125
|
+
/* @__PURE__ */ jsxs73(
|
|
9065
9126
|
Card,
|
|
9066
9127
|
{
|
|
9067
|
-
title: /* @__PURE__ */
|
|
9068
|
-
/* @__PURE__ */
|
|
9069
|
-
/* @__PURE__ */
|
|
9128
|
+
title: /* @__PURE__ */ jsxs73("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
9129
|
+
/* @__PURE__ */ jsx86("span", { children: "Access" }),
|
|
9130
|
+
/* @__PURE__ */ jsx86("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
|
|
9070
9131
|
] }),
|
|
9071
9132
|
elevation: "flat",
|
|
9072
|
-
action: /* @__PURE__ */
|
|
9133
|
+
action: /* @__PURE__ */ jsx86(
|
|
9073
9134
|
Button,
|
|
9074
9135
|
{
|
|
9075
9136
|
size: "sm",
|
|
@@ -9080,39 +9141,39 @@ function ProfilePage({
|
|
|
9080
9141
|
}
|
|
9081
9142
|
),
|
|
9082
9143
|
children: [
|
|
9083
|
-
/* @__PURE__ */
|
|
9084
|
-
/* @__PURE__ */
|
|
9085
|
-
/* @__PURE__ */
|
|
9144
|
+
/* @__PURE__ */ jsxs73("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
9145
|
+
/* @__PURE__ */ jsx86(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
|
|
9146
|
+
/* @__PURE__ */ jsxs73(CardRow, { label: "Permissions", children: [
|
|
9086
9147
|
permissions.length,
|
|
9087
9148
|
" granted"
|
|
9088
9149
|
] }),
|
|
9089
|
-
/* @__PURE__ */
|
|
9150
|
+
/* @__PURE__ */ jsx86(CardRow, { label: "Member since", children: user.joined || "\u2014" })
|
|
9090
9151
|
] }),
|
|
9091
|
-
/* @__PURE__ */
|
|
9152
|
+
/* @__PURE__ */ jsx86("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." })
|
|
9092
9153
|
]
|
|
9093
9154
|
}
|
|
9094
9155
|
),
|
|
9095
|
-
sessions ? /* @__PURE__ */
|
|
9156
|
+
sessions ? /* @__PURE__ */ jsx86(
|
|
9096
9157
|
Card,
|
|
9097
9158
|
{
|
|
9098
9159
|
title: "Signed-in devices",
|
|
9099
9160
|
elevation: "flat",
|
|
9100
|
-
action: /* @__PURE__ */
|
|
9101
|
-
children: /* @__PURE__ */
|
|
9102
|
-
/* @__PURE__ */
|
|
9103
|
-
/* @__PURE__ */
|
|
9104
|
-
/* @__PURE__ */
|
|
9105
|
-
/* @__PURE__ */
|
|
9161
|
+
action: /* @__PURE__ */ jsx86(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
|
|
9162
|
+
children: /* @__PURE__ */ jsx86("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ jsx86("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ jsxs73("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
|
|
9163
|
+
/* @__PURE__ */ jsx86("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
9164
|
+
/* @__PURE__ */ jsxs73("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
|
|
9165
|
+
/* @__PURE__ */ jsx86("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
|
|
9166
|
+
/* @__PURE__ */ jsxs73("span", { className: "fd-body-sm fd-muted", children: [
|
|
9106
9167
|
s.where,
|
|
9107
9168
|
" \xB7 ",
|
|
9108
9169
|
s.when
|
|
9109
9170
|
] })
|
|
9110
9171
|
] }),
|
|
9111
|
-
s.current ? /* @__PURE__ */
|
|
9172
|
+
s.current ? /* @__PURE__ */ jsx86(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx86(Button, { size: "sm", variant: "ghost", children: "Revoke" })
|
|
9112
9173
|
] }, s.id)) })
|
|
9113
9174
|
}
|
|
9114
9175
|
) : null,
|
|
9115
|
-
/* @__PURE__ */
|
|
9176
|
+
/* @__PURE__ */ jsxs73("div", { className: "fd-row", style: {
|
|
9116
9177
|
gap: 10,
|
|
9117
9178
|
flexWrap: "wrap",
|
|
9118
9179
|
position: "sticky",
|
|
@@ -9123,16 +9184,16 @@ function ProfilePage({
|
|
|
9123
9184
|
border: "1px solid var(--border)",
|
|
9124
9185
|
boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
|
|
9125
9186
|
}, children: [
|
|
9126
|
-
/* @__PURE__ */
|
|
9127
|
-
/* @__PURE__ */
|
|
9128
|
-
/* @__PURE__ */
|
|
9187
|
+
/* @__PURE__ */ jsx86("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
|
|
9188
|
+
/* @__PURE__ */ jsx86(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
|
|
9189
|
+
/* @__PURE__ */ jsx86(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
|
|
9129
9190
|
] })
|
|
9130
9191
|
] });
|
|
9131
9192
|
}
|
|
9132
9193
|
|
|
9133
9194
|
// src/components/platform/SessionScreen.tsx
|
|
9134
|
-
import * as
|
|
9135
|
-
import { Fragment as Fragment22, jsx as
|
|
9195
|
+
import * as React62 from "react";
|
|
9196
|
+
import { Fragment as Fragment22, jsx as jsx87, jsxs as jsxs74 } from "react/jsx-runtime";
|
|
9136
9197
|
var COPY = {
|
|
9137
9198
|
"signing-in": { busy: "Signing you in\u2026" },
|
|
9138
9199
|
"session-expired": { busy: "Your session expired \u2014 signing you back in\u2026" },
|
|
@@ -9145,28 +9206,28 @@ function SessionScreen({ kind, error, onRetry, productName }) {
|
|
|
9145
9206
|
const copy = COPY[kind];
|
|
9146
9207
|
const busyMessage = "busy" in copy ? copy.busy : null;
|
|
9147
9208
|
const failureTitle = "failure" in copy ? copy.failure : null;
|
|
9148
|
-
const [announced, setAnnounced] =
|
|
9149
|
-
|
|
9209
|
+
const [announced, setAnnounced] = React62.useState("");
|
|
9210
|
+
React62.useEffect(() => {
|
|
9150
9211
|
setAnnounced(busyMessage ?? "");
|
|
9151
9212
|
}, [busyMessage]);
|
|
9152
|
-
const titleRef =
|
|
9213
|
+
const titleRef = React62.useRef(null);
|
|
9153
9214
|
const failed = failureTitle !== null;
|
|
9154
|
-
|
|
9215
|
+
React62.useEffect(() => {
|
|
9155
9216
|
titleRef.current?.focus({ preventScroll: true });
|
|
9156
9217
|
}, [failed]);
|
|
9157
|
-
return /* @__PURE__ */
|
|
9158
|
-
/* @__PURE__ */
|
|
9159
|
-
/* @__PURE__ */
|
|
9160
|
-
/* @__PURE__ */
|
|
9161
|
-
/* @__PURE__ */
|
|
9162
|
-
/* @__PURE__ */
|
|
9163
|
-
/* @__PURE__ */
|
|
9164
|
-
/* @__PURE__ */
|
|
9165
|
-
/* @__PURE__ */
|
|
9218
|
+
return /* @__PURE__ */ jsx87("main", { className: "fd-session-screen", children: /* @__PURE__ */ jsxs74("div", { className: "fd-session-screen-inner", children: [
|
|
9219
|
+
/* @__PURE__ */ jsx87("div", { className: "fd-session-screen-mark", "data-theme": "dark", children: /* @__PURE__ */ jsx87(FlytedeskMark, { size: "lg" }) }),
|
|
9220
|
+
/* @__PURE__ */ jsxs74("div", { className: "fd-session-screen-frame", children: [
|
|
9221
|
+
/* @__PURE__ */ jsx87("div", { className: "fd-session-screen-stripe" }),
|
|
9222
|
+
/* @__PURE__ */ jsx87(Card, { children: /* @__PURE__ */ jsxs74("div", { className: "fd-session-screen-body", children: [
|
|
9223
|
+
/* @__PURE__ */ jsx87("h1", { ref: titleRef, tabIndex: -1, className: "fd-h3 fd-session-screen-title", children: productName }),
|
|
9224
|
+
/* @__PURE__ */ jsx87("div", { role: "status", "aria-live": "polite", className: "fd-session-screen-status", children: busyMessage !== null ? /* @__PURE__ */ jsxs74(Fragment22, { children: [
|
|
9225
|
+
/* @__PURE__ */ jsx87("span", { className: "fd-spinner fd-spinner-lg fd-session-screen-spinner", "aria-hidden": "true" }),
|
|
9226
|
+
/* @__PURE__ */ jsx87("p", { className: "fd-body fd-session-screen-message", children: announced })
|
|
9166
9227
|
] }) : null }),
|
|
9167
|
-
failureTitle !== null ? /* @__PURE__ */
|
|
9168
|
-
/* @__PURE__ */
|
|
9169
|
-
onRetry !== null ? /* @__PURE__ */
|
|
9228
|
+
failureTitle !== null ? /* @__PURE__ */ jsxs74("div", { className: "fd-session-screen-failure", children: [
|
|
9229
|
+
/* @__PURE__ */ jsx87(Banner, { tone: "danger", title: failureTitle, detail: error ?? void 0 }),
|
|
9230
|
+
onRetry !== null ? /* @__PURE__ */ jsx87(Button, { variant: "primary", block: true, onClick: onRetry, children: "Try again" }) : null
|
|
9170
9231
|
] }) : null
|
|
9171
9232
|
] }) })
|
|
9172
9233
|
] })
|
|
@@ -9174,10 +9235,10 @@ function SessionScreen({ kind, error, onRetry, productName }) {
|
|
|
9174
9235
|
}
|
|
9175
9236
|
|
|
9176
9237
|
// src/components/platform/RoadmapTimeline.tsx
|
|
9177
|
-
import * as
|
|
9238
|
+
import * as React65 from "react";
|
|
9178
9239
|
|
|
9179
9240
|
// src/kits/session.ts
|
|
9180
|
-
import * as
|
|
9241
|
+
import * as React63 from "react";
|
|
9181
9242
|
var PERMISSION_CATALOG = [
|
|
9182
9243
|
{ group: "Plans", items: [
|
|
9183
9244
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -10744,8 +10805,8 @@ function roadmap(overrides) {
|
|
|
10744
10805
|
};
|
|
10745
10806
|
}
|
|
10746
10807
|
function useSession() {
|
|
10747
|
-
const [s, setS] =
|
|
10748
|
-
|
|
10808
|
+
const [s, setS] = React63.useState(getSession);
|
|
10809
|
+
React63.useEffect(() => subscribe(setS), []);
|
|
10749
10810
|
return s;
|
|
10750
10811
|
}
|
|
10751
10812
|
var SessionKit = {
|
|
@@ -10778,7 +10839,7 @@ var SessionKit = {
|
|
|
10778
10839
|
};
|
|
10779
10840
|
function DemoSessionProvider({ children }) {
|
|
10780
10841
|
const session = useSession();
|
|
10781
|
-
const value =
|
|
10842
|
+
const value = React63.useMemo(
|
|
10782
10843
|
() => ({
|
|
10783
10844
|
user: session.user,
|
|
10784
10845
|
roles: session.roles,
|
|
@@ -10794,11 +10855,11 @@ function DemoSessionProvider({ children }) {
|
|
|
10794
10855
|
}),
|
|
10795
10856
|
[session]
|
|
10796
10857
|
);
|
|
10797
|
-
return
|
|
10858
|
+
return React63.createElement(SessionProvider, { value }, children);
|
|
10798
10859
|
}
|
|
10799
10860
|
|
|
10800
10861
|
// src/kits/runtime.ts
|
|
10801
|
-
import * as
|
|
10862
|
+
import * as React64 from "react";
|
|
10802
10863
|
var WIRED_ENDPOINTS = [
|
|
10803
10864
|
// Nothing yet. Every id below would come from a real service:
|
|
10804
10865
|
// "plan.get", "placements.list", …
|
|
@@ -10969,8 +11030,8 @@ var RuntimeKit = {
|
|
|
10969
11030
|
};
|
|
10970
11031
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
10971
11032
|
function useRuntimeMode() {
|
|
10972
|
-
const [m, setM] =
|
|
10973
|
-
|
|
11033
|
+
const [m, setM] = React64.useState(RuntimeKit.getMode());
|
|
11034
|
+
React64.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
10974
11035
|
return m;
|
|
10975
11036
|
}
|
|
10976
11037
|
function useFeatureStatus(key) {
|
|
@@ -10989,7 +11050,7 @@ var UseRuntimeMode = useRuntimeMode;
|
|
|
10989
11050
|
var UseFeatureStatus = useFeatureStatus;
|
|
10990
11051
|
|
|
10991
11052
|
// src/components/platform/RoadmapTimeline.tsx
|
|
10992
|
-
import { jsx as
|
|
11053
|
+
import { jsx as jsx88, jsxs as jsxs75 } from "react/jsx-runtime";
|
|
10993
11054
|
var STATUS = {
|
|
10994
11055
|
shipped: { tone: "success", icon: "check-circle", label: "Wired" },
|
|
10995
11056
|
next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
|
|
@@ -11004,45 +11065,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
11004
11065
|
const s = STATUS[item.status] || STATUS.planned;
|
|
11005
11066
|
const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
|
|
11006
11067
|
const blocking = deps.filter((d) => !d.implemented);
|
|
11007
|
-
return /* @__PURE__ */
|
|
11008
|
-
/* @__PURE__ */
|
|
11009
|
-
/* @__PURE__ */
|
|
11010
|
-
/* @__PURE__ */
|
|
11011
|
-
/* @__PURE__ */
|
|
11068
|
+
return /* @__PURE__ */ jsx88(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs75("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
11069
|
+
/* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
11070
|
+
/* @__PURE__ */ jsx88("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
|
|
11071
|
+
/* @__PURE__ */ jsx88(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
|
|
11072
|
+
/* @__PURE__ */ jsx88(Badge, { tone: s.tone, icon: s.icon, children: s.label })
|
|
11012
11073
|
] }),
|
|
11013
|
-
/* @__PURE__ */
|
|
11014
|
-
item.backend ? /* @__PURE__ */
|
|
11015
|
-
/* @__PURE__ */
|
|
11016
|
-
/* @__PURE__ */
|
|
11074
|
+
/* @__PURE__ */ jsx88("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
|
|
11075
|
+
item.backend ? /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
|
|
11076
|
+
/* @__PURE__ */ jsx88("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
|
|
11077
|
+
/* @__PURE__ */ jsx88("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
|
|
11017
11078
|
] }) : null,
|
|
11018
|
-
/* @__PURE__ */
|
|
11019
|
-
item.effort ? /* @__PURE__ */
|
|
11020
|
-
/* @__PURE__ */
|
|
11079
|
+
/* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
11080
|
+
item.effort ? /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted", children: [
|
|
11081
|
+
/* @__PURE__ */ jsx88("i", { className: "ph ph-hourglass-medium" }),
|
|
11021
11082
|
" ",
|
|
11022
11083
|
item.effort
|
|
11023
11084
|
] }) : null,
|
|
11024
|
-
/* @__PURE__ */
|
|
11025
|
-
/* @__PURE__ */
|
|
11085
|
+
/* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted", children: [
|
|
11086
|
+
/* @__PURE__ */ jsx88("i", { className: "ph ph-user" }),
|
|
11026
11087
|
" ",
|
|
11027
11088
|
item.owner
|
|
11028
11089
|
] }),
|
|
11029
|
-
item.screen ? /* @__PURE__ */
|
|
11030
|
-
/* @__PURE__ */
|
|
11031
|
-
/* @__PURE__ */
|
|
11090
|
+
item.screen ? /* @__PURE__ */ jsx88(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
|
|
11091
|
+
/* @__PURE__ */ jsx88("span", { style: { flex: 1 } }),
|
|
11092
|
+
/* @__PURE__ */ jsx88(
|
|
11032
11093
|
"button",
|
|
11033
11094
|
{
|
|
11034
11095
|
type: "button",
|
|
11035
11096
|
onClick: () => onOpenFlag && onOpenFlag(item.key),
|
|
11036
11097
|
style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
|
|
11037
|
-
children: /* @__PURE__ */
|
|
11098
|
+
children: /* @__PURE__ */ jsx88("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
|
|
11038
11099
|
}
|
|
11039
11100
|
)
|
|
11040
11101
|
] }),
|
|
11041
|
-
deps.length ? /* @__PURE__ */
|
|
11042
|
-
/* @__PURE__ */
|
|
11043
|
-
deps.map((d) => /* @__PURE__ */
|
|
11102
|
+
deps.length ? /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
|
|
11103
|
+
/* @__PURE__ */ jsx88("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
|
|
11104
|
+
deps.map((d) => /* @__PURE__ */ jsx88(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
|
|
11044
11105
|
] }) : null,
|
|
11045
|
-
blocking.length && !item.implemented ? /* @__PURE__ */
|
|
11106
|
+
blocking.length && !item.implemented ? /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
|
|
11046
11107
|
"Blocked until ",
|
|
11047
11108
|
blocking.map((d) => d.label).join(" and "),
|
|
11048
11109
|
" ",
|
|
@@ -11053,12 +11114,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
11053
11114
|
}
|
|
11054
11115
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
11055
11116
|
const session = SessionKit.useSession();
|
|
11056
|
-
const [project, setProject] =
|
|
11057
|
-
const [q, setQ] =
|
|
11058
|
-
const scrollRef =
|
|
11059
|
-
const nowRef =
|
|
11060
|
-
const rm =
|
|
11061
|
-
const byKey =
|
|
11117
|
+
const [project, setProject] = React65.useState("");
|
|
11118
|
+
const [q, setQ] = React65.useState("");
|
|
11119
|
+
const scrollRef = React65.useRef(null);
|
|
11120
|
+
const nowRef = React65.useRef(null);
|
|
11121
|
+
const rm = React65.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
11122
|
+
const byKey = React65.useMemo(() => {
|
|
11062
11123
|
const m = {};
|
|
11063
11124
|
rm.items.forEach((i) => {
|
|
11064
11125
|
m[i.key] = i;
|
|
@@ -11067,7 +11128,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
11067
11128
|
}, [rm]);
|
|
11068
11129
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
11069
11130
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
11070
|
-
|
|
11131
|
+
React65.useEffect(() => {
|
|
11071
11132
|
let raf1 = 0, raf2 = 0;
|
|
11072
11133
|
const place = () => {
|
|
11073
11134
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -11095,23 +11156,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
11095
11156
|
}, 0);
|
|
11096
11157
|
const nextPhase = items.find((i) => !i.implemented);
|
|
11097
11158
|
let lastPhase = null;
|
|
11098
|
-
return /* @__PURE__ */
|
|
11099
|
-
/* @__PURE__ */
|
|
11100
|
-
/* @__PURE__ */
|
|
11101
|
-
/* @__PURE__ */
|
|
11102
|
-
/* @__PURE__ */
|
|
11159
|
+
return /* @__PURE__ */ jsxs75("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
|
|
11160
|
+
/* @__PURE__ */ jsxs75("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
11161
|
+
/* @__PURE__ */ jsx88("span", { className: "fd-overline fd-muted", children: "Architecture" }),
|
|
11162
|
+
/* @__PURE__ */ jsx88("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
11163
|
+
/* @__PURE__ */ jsx88("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." })
|
|
11103
11164
|
] }),
|
|
11104
|
-
/* @__PURE__ */
|
|
11105
|
-
/* @__PURE__ */
|
|
11106
|
-
/* @__PURE__ */
|
|
11107
|
-
/* @__PURE__ */
|
|
11108
|
-
/* @__PURE__ */
|
|
11165
|
+
/* @__PURE__ */ jsxs75("div", { className: "fd-grid-stats is-thin", children: [
|
|
11166
|
+
/* @__PURE__ */ jsx88(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
|
|
11167
|
+
/* @__PURE__ */ jsx88(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
|
|
11168
|
+
/* @__PURE__ */ jsx88(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
|
|
11169
|
+
/* @__PURE__ */ jsx88(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
|
|
11109
11170
|
] }),
|
|
11110
|
-
/* @__PURE__ */
|
|
11111
|
-
/* @__PURE__ */
|
|
11112
|
-
/* @__PURE__ */
|
|
11113
|
-
/* @__PURE__ */
|
|
11114
|
-
/* @__PURE__ */
|
|
11171
|
+
/* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
11172
|
+
/* @__PURE__ */ jsx88(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 } }),
|
|
11173
|
+
/* @__PURE__ */ jsx88(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
|
|
11174
|
+
/* @__PURE__ */ jsx88("span", { style: { flex: 1 } }),
|
|
11175
|
+
/* @__PURE__ */ jsx88(
|
|
11115
11176
|
Button,
|
|
11116
11177
|
{
|
|
11117
11178
|
size: "sm",
|
|
@@ -11125,7 +11186,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
11125
11186
|
}
|
|
11126
11187
|
)
|
|
11127
11188
|
] }),
|
|
11128
|
-
/* @__PURE__ */
|
|
11189
|
+
/* @__PURE__ */ jsx88(
|
|
11129
11190
|
Flag,
|
|
11130
11191
|
{
|
|
11131
11192
|
tone: "info",
|
|
@@ -11134,60 +11195,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
11134
11195
|
actions: null
|
|
11135
11196
|
}
|
|
11136
11197
|
),
|
|
11137
|
-
/* @__PURE__ */
|
|
11138
|
-
/* @__PURE__ */
|
|
11198
|
+
/* @__PURE__ */ jsx88("div", { className: "fd-rm", children: /* @__PURE__ */ jsx88("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs75("div", { className: "fd-rm-track", children: [
|
|
11199
|
+
/* @__PURE__ */ jsx88("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx88("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
|
|
11139
11200
|
items.map((item, n) => {
|
|
11140
11201
|
const showPhase = item.phase !== lastPhase;
|
|
11141
11202
|
lastPhase = item.phase;
|
|
11142
11203
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
11143
11204
|
const isBoundary = n === firstPending;
|
|
11144
|
-
return /* @__PURE__ */
|
|
11145
|
-
showPhase ? /* @__PURE__ */
|
|
11146
|
-
/* @__PURE__ */
|
|
11147
|
-
/* @__PURE__ */
|
|
11148
|
-
item.phase === 0 ? null : /* @__PURE__ */
|
|
11205
|
+
return /* @__PURE__ */ jsxs75(React65.Fragment, { children: [
|
|
11206
|
+
showPhase ? /* @__PURE__ */ jsxs75("div", { className: "fd-rm-era", children: [
|
|
11207
|
+
/* @__PURE__ */ jsxs75("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
11208
|
+
/* @__PURE__ */ jsx88("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
11209
|
+
item.phase === 0 ? null : /* @__PURE__ */ jsxs75("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
11149
11210
|
fmtDate(item.phaseStart),
|
|
11150
11211
|
" \u2013 ",
|
|
11151
11212
|
fmtDate(item.date)
|
|
11152
11213
|
] }),
|
|
11153
|
-
/* @__PURE__ */
|
|
11214
|
+
/* @__PURE__ */ jsxs75("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
11154
11215
|
"\xB7 ",
|
|
11155
11216
|
inPhase,
|
|
11156
11217
|
" feature",
|
|
11157
11218
|
inPhase === 1 ? "" : "s"
|
|
11158
11219
|
] })
|
|
11159
11220
|
] }),
|
|
11160
|
-
item.phaseWhy ? /* @__PURE__ */
|
|
11221
|
+
item.phaseWhy ? /* @__PURE__ */ jsx88("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
|
|
11161
11222
|
] }) : null,
|
|
11162
|
-
isBoundary ? /* @__PURE__ */
|
|
11163
|
-
/* @__PURE__ */
|
|
11223
|
+
isBoundary ? /* @__PURE__ */ jsx88("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs75("span", { className: "fd-rm-now-pill", children: [
|
|
11224
|
+
/* @__PURE__ */ jsx88("i", { className: "ph ph-map-pin" }),
|
|
11164
11225
|
" You are here \u2014 everything above is wired"
|
|
11165
11226
|
] }) }) : null,
|
|
11166
|
-
/* @__PURE__ */
|
|
11167
|
-
/* @__PURE__ */
|
|
11168
|
-
/* @__PURE__ */
|
|
11227
|
+
/* @__PURE__ */ jsxs75("div", { className: "fd-rm-row", children: [
|
|
11228
|
+
/* @__PURE__ */ jsx88("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
|
|
11229
|
+
/* @__PURE__ */ jsxs75("div", { className: "fd-rm-date", children: [
|
|
11169
11230
|
fmtDate(item.date),
|
|
11170
|
-
/* @__PURE__ */
|
|
11171
|
-
/* @__PURE__ */
|
|
11231
|
+
/* @__PURE__ */ jsx88("br", {}),
|
|
11232
|
+
/* @__PURE__ */ jsx88("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
|
|
11172
11233
|
] }),
|
|
11173
|
-
/* @__PURE__ */
|
|
11234
|
+
/* @__PURE__ */ jsx88(RoadmapCard, { item, byKey, onOpenFlag })
|
|
11174
11235
|
] })
|
|
11175
11236
|
] }, item.key);
|
|
11176
11237
|
}),
|
|
11177
|
-
!items.length ? /* @__PURE__ */
|
|
11238
|
+
!items.length ? /* @__PURE__ */ jsx88("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
|
|
11178
11239
|
] }) }) }),
|
|
11179
|
-
/* @__PURE__ */
|
|
11240
|
+
/* @__PURE__ */ jsxs75("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
|
|
11180
11241
|
"Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
|
|
11181
|
-
/* @__PURE__ */
|
|
11242
|
+
/* @__PURE__ */ jsx88("code", { className: "fd-mono", children: "implemented" }),
|
|
11182
11243
|
" field, so this page cannot drift from what the apps actually do."
|
|
11183
11244
|
] })
|
|
11184
11245
|
] });
|
|
11185
11246
|
}
|
|
11186
11247
|
|
|
11187
11248
|
// src/components/platform/ComingSoon.tsx
|
|
11188
|
-
import * as
|
|
11249
|
+
import * as React66 from "react";
|
|
11189
11250
|
import { createPortal as createPortal6 } from "react-dom";
|
|
11190
|
-
import { Fragment as Fragment24, jsx as
|
|
11251
|
+
import { Fragment as Fragment24, jsx as jsx89, jsxs as jsxs76 } from "react/jsx-runtime";
|
|
11191
11252
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
11192
11253
|
function readBypassed() {
|
|
11193
11254
|
try {
|
|
@@ -11203,8 +11264,8 @@ function writeBypassed(list) {
|
|
|
11203
11264
|
}
|
|
11204
11265
|
}
|
|
11205
11266
|
function useBypass(key) {
|
|
11206
|
-
const [on, setOn] =
|
|
11207
|
-
|
|
11267
|
+
const [on, setOn] = React66.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
11268
|
+
React66.useEffect(() => {
|
|
11208
11269
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
11209
11270
|
}, [key]);
|
|
11210
11271
|
const set = (next) => {
|
|
@@ -11217,43 +11278,43 @@ function useBypass(key) {
|
|
|
11217
11278
|
return [on, set];
|
|
11218
11279
|
}
|
|
11219
11280
|
function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
|
|
11220
|
-
return /* @__PURE__ */
|
|
11221
|
-
/* @__PURE__ */
|
|
11222
|
-
/* @__PURE__ */
|
|
11281
|
+
return /* @__PURE__ */ jsxs76(Fragment24, { children: [
|
|
11282
|
+
/* @__PURE__ */ jsxs76("span", { className: "fd-soon-badge", children: [
|
|
11283
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
11223
11284
|
label
|
|
11224
11285
|
] }),
|
|
11225
|
-
detail ? /* @__PURE__ */
|
|
11226
|
-
backend ? /* @__PURE__ */
|
|
11227
|
-
/* @__PURE__ */
|
|
11286
|
+
detail ? /* @__PURE__ */ jsx89("span", { className: "fd-soon-detail", children: detail }) : null,
|
|
11287
|
+
backend ? /* @__PURE__ */ jsxs76("span", { className: "fd-soon-backend", children: [
|
|
11288
|
+
/* @__PURE__ */ jsx89("span", { className: "fd-overline", children: "Needs" }),
|
|
11228
11289
|
" ",
|
|
11229
11290
|
backend
|
|
11230
11291
|
] }) : null,
|
|
11231
|
-
eta || effort || onRoadmap ? /* @__PURE__ */
|
|
11232
|
-
eta ? /* @__PURE__ */
|
|
11233
|
-
/* @__PURE__ */
|
|
11292
|
+
eta || effort || onRoadmap ? /* @__PURE__ */ jsxs76("span", { className: "fd-soon-meta", children: [
|
|
11293
|
+
eta ? /* @__PURE__ */ jsxs76("span", { children: [
|
|
11294
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
|
|
11234
11295
|
" ",
|
|
11235
11296
|
eta
|
|
11236
11297
|
] }) : null,
|
|
11237
|
-
effort ? /* @__PURE__ */
|
|
11238
|
-
/* @__PURE__ */
|
|
11298
|
+
effort ? /* @__PURE__ */ jsxs76("span", { children: [
|
|
11299
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
|
|
11239
11300
|
" ",
|
|
11240
11301
|
effort
|
|
11241
11302
|
] }) : null,
|
|
11242
|
-
onRoadmap ? /* @__PURE__ */
|
|
11303
|
+
onRoadmap ? /* @__PURE__ */ jsxs76("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
11243
11304
|
"See the roadmap ",
|
|
11244
|
-
/* @__PURE__ */
|
|
11305
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
11245
11306
|
] }) : null
|
|
11246
11307
|
] }) : null,
|
|
11247
|
-
allowed ? /* @__PURE__ */
|
|
11248
|
-
/* @__PURE__ */
|
|
11308
|
+
allowed ? /* @__PURE__ */ jsxs76("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
|
|
11309
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-eye", "aria-hidden": "true" }),
|
|
11249
11310
|
" View and use it anyway"
|
|
11250
11311
|
] }) : null
|
|
11251
11312
|
] });
|
|
11252
11313
|
}
|
|
11253
11314
|
function useHoverCard(open2) {
|
|
11254
|
-
const anchor =
|
|
11255
|
-
const [pos, setPos] =
|
|
11256
|
-
|
|
11315
|
+
const anchor = React66.useRef(null);
|
|
11316
|
+
const [pos, setPos] = React66.useState(null);
|
|
11317
|
+
React66.useLayoutEffect(() => {
|
|
11257
11318
|
if (!open2 || !anchor.current) {
|
|
11258
11319
|
setPos(null);
|
|
11259
11320
|
return;
|
|
@@ -11305,9 +11366,9 @@ function ComingSoon({
|
|
|
11305
11366
|
const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
|
|
11306
11367
|
if (inline) {
|
|
11307
11368
|
if (allowed && bypassed) {
|
|
11308
|
-
return /* @__PURE__ */
|
|
11369
|
+
return /* @__PURE__ */ jsxs76("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
|
|
11309
11370
|
children,
|
|
11310
|
-
/* @__PURE__ */
|
|
11371
|
+
/* @__PURE__ */ jsx89(
|
|
11311
11372
|
"button",
|
|
11312
11373
|
{
|
|
11313
11374
|
type: "button",
|
|
@@ -11315,12 +11376,12 @@ function ComingSoon({
|
|
|
11315
11376
|
title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
|
|
11316
11377
|
onClick: () => setBypassed(false),
|
|
11317
11378
|
"aria-label": "Re-blur this unwired feature",
|
|
11318
|
-
children: /* @__PURE__ */
|
|
11379
|
+
children: /* @__PURE__ */ jsx89("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
11319
11380
|
}
|
|
11320
11381
|
)
|
|
11321
11382
|
] });
|
|
11322
11383
|
}
|
|
11323
|
-
return /* @__PURE__ */
|
|
11384
|
+
return /* @__PURE__ */ jsx89(
|
|
11324
11385
|
InlineSoon,
|
|
11325
11386
|
{
|
|
11326
11387
|
label,
|
|
@@ -11340,20 +11401,20 @@ function ComingSoon({
|
|
|
11340
11401
|
);
|
|
11341
11402
|
}
|
|
11342
11403
|
if (allowed && bypassed) {
|
|
11343
|
-
return /* @__PURE__ */
|
|
11344
|
-
/* @__PURE__ */
|
|
11345
|
-
/* @__PURE__ */
|
|
11346
|
-
/* @__PURE__ */
|
|
11404
|
+
return /* @__PURE__ */ jsxs76("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
|
|
11405
|
+
/* @__PURE__ */ jsxs76("div", { className: "fd-soon-bar", role: "status", children: [
|
|
11406
|
+
/* @__PURE__ */ jsxs76("span", { className: "fd-soon-badge", children: [
|
|
11407
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
11347
11408
|
"Unwired feature \u2014 you are using it anyway"
|
|
11348
11409
|
] }),
|
|
11349
|
-
/* @__PURE__ */
|
|
11350
|
-
/* @__PURE__ */
|
|
11351
|
-
onRoadmap ? /* @__PURE__ */
|
|
11410
|
+
/* @__PURE__ */ jsx89("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
|
|
11411
|
+
/* @__PURE__ */ jsxs76("span", { className: "fd-soon-bar-actions", children: [
|
|
11412
|
+
onRoadmap ? /* @__PURE__ */ jsxs76("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
11352
11413
|
"Roadmap ",
|
|
11353
|
-
/* @__PURE__ */
|
|
11414
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
11354
11415
|
] }) : null,
|
|
11355
|
-
/* @__PURE__ */
|
|
11356
|
-
/* @__PURE__ */
|
|
11416
|
+
/* @__PURE__ */ jsxs76("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
|
|
11417
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
|
|
11357
11418
|
" Re-blur"
|
|
11358
11419
|
] })
|
|
11359
11420
|
] })
|
|
@@ -11361,10 +11422,10 @@ function ComingSoon({
|
|
|
11361
11422
|
children
|
|
11362
11423
|
] });
|
|
11363
11424
|
}
|
|
11364
|
-
return /* @__PURE__ */
|
|
11365
|
-
/* @__PURE__ */
|
|
11366
|
-
/* @__PURE__ */
|
|
11367
|
-
/* @__PURE__ */
|
|
11425
|
+
return /* @__PURE__ */ jsxs76("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
|
|
11426
|
+
/* @__PURE__ */ jsx89("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
11427
|
+
/* @__PURE__ */ jsx89("div", { className: "fd-soon-veil" }),
|
|
11428
|
+
/* @__PURE__ */ jsx89("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx89(
|
|
11368
11429
|
SoonCard,
|
|
11369
11430
|
{
|
|
11370
11431
|
label,
|
|
@@ -11380,12 +11441,12 @@ function ComingSoon({
|
|
|
11380
11441
|
] });
|
|
11381
11442
|
}
|
|
11382
11443
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
11383
|
-
const [open2, setOpen] =
|
|
11444
|
+
const [open2, setOpen] = React66.useState(false);
|
|
11384
11445
|
const [anchor, pos] = useHoverCard(open2);
|
|
11385
|
-
const hoverCardRef =
|
|
11446
|
+
const hoverCardRef = React66.useRef(null);
|
|
11386
11447
|
const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
|
|
11387
11448
|
const zIndex = useLayerZIndex(hoverLayer);
|
|
11388
|
-
const close2 =
|
|
11449
|
+
const close2 = React66.useRef(null);
|
|
11389
11450
|
const show = () => {
|
|
11390
11451
|
if (close2.current) {
|
|
11391
11452
|
clearTimeout(close2.current);
|
|
@@ -11401,10 +11462,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
11401
11462
|
setOpen(false);
|
|
11402
11463
|
}, 140);
|
|
11403
11464
|
};
|
|
11404
|
-
|
|
11465
|
+
React66.useEffect(() => () => {
|
|
11405
11466
|
if (close2.current) clearTimeout(close2.current);
|
|
11406
11467
|
}, []);
|
|
11407
|
-
return /* @__PURE__ */
|
|
11468
|
+
return /* @__PURE__ */ jsxs76(
|
|
11408
11469
|
"span",
|
|
11409
11470
|
{
|
|
11410
11471
|
ref: anchor,
|
|
@@ -11415,8 +11476,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
11415
11476
|
onBlur: hide,
|
|
11416
11477
|
...rest,
|
|
11417
11478
|
children: [
|
|
11418
|
-
/* @__PURE__ */
|
|
11419
|
-
/* @__PURE__ */
|
|
11479
|
+
/* @__PURE__ */ jsx89("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
11480
|
+
/* @__PURE__ */ jsx89(
|
|
11420
11481
|
"button",
|
|
11421
11482
|
{
|
|
11422
11483
|
type: "button",
|
|
@@ -11427,11 +11488,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
11427
11488
|
onFocus: show,
|
|
11428
11489
|
onBlur: hide,
|
|
11429
11490
|
onClick: () => open2 ? setOpen(false) : show(),
|
|
11430
|
-
children: /* @__PURE__ */
|
|
11491
|
+
children: /* @__PURE__ */ jsx89("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
11431
11492
|
}
|
|
11432
11493
|
),
|
|
11433
11494
|
open2 && pos ? createPortal6(
|
|
11434
|
-
/* @__PURE__ */
|
|
11495
|
+
/* @__PURE__ */ jsx89(
|
|
11435
11496
|
"div",
|
|
11436
11497
|
{
|
|
11437
11498
|
ref: hoverCardRef,
|
|
@@ -11440,7 +11501,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
11440
11501
|
style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
|
|
11441
11502
|
onMouseEnter: show,
|
|
11442
11503
|
onMouseLeave: hide,
|
|
11443
|
-
children: /* @__PURE__ */
|
|
11504
|
+
children: /* @__PURE__ */ jsx89(
|
|
11444
11505
|
SoonCard,
|
|
11445
11506
|
{
|
|
11446
11507
|
label,
|
|
@@ -11470,10 +11531,10 @@ function formatEta(iso2) {
|
|
|
11470
11531
|
var FormatEta = formatEta;
|
|
11471
11532
|
|
|
11472
11533
|
// src/components/platform/Gate.tsx
|
|
11473
|
-
import { jsx as
|
|
11534
|
+
import { jsx as jsx90, jsxs as jsxs77 } from "react/jsx-runtime";
|
|
11474
11535
|
function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
|
|
11475
11536
|
const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
|
|
11476
|
-
return /* @__PURE__ */
|
|
11537
|
+
return /* @__PURE__ */ jsxs77(
|
|
11477
11538
|
"div",
|
|
11478
11539
|
{
|
|
11479
11540
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -11489,14 +11550,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
11489
11550
|
},
|
|
11490
11551
|
...rest,
|
|
11491
11552
|
children: [
|
|
11492
|
-
/* @__PURE__ */
|
|
11493
|
-
/* @__PURE__ */
|
|
11494
|
-
/* @__PURE__ */
|
|
11553
|
+
/* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
11554
|
+
/* @__PURE__ */ jsx90("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
11555
|
+
/* @__PURE__ */ jsx90("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
|
|
11495
11556
|
] }),
|
|
11496
|
-
/* @__PURE__ */
|
|
11497
|
-
need.length ? /* @__PURE__ */
|
|
11498
|
-
/* @__PURE__ */
|
|
11499
|
-
need.map((p) => /* @__PURE__ */
|
|
11557
|
+
/* @__PURE__ */ jsx90("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." }),
|
|
11558
|
+
need.length ? /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
|
|
11559
|
+
/* @__PURE__ */ jsx90("span", { className: "fd-overline fd-muted", children: "Requires" }),
|
|
11560
|
+
need.map((p) => /* @__PURE__ */ jsx90("code", { className: "fd-mono", style: {
|
|
11500
11561
|
fontSize: 11.5,
|
|
11501
11562
|
padding: "2px 7px",
|
|
11502
11563
|
borderRadius: 5,
|
|
@@ -11509,7 +11570,7 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
11509
11570
|
);
|
|
11510
11571
|
}
|
|
11511
11572
|
function GatePending({ compact: compact3 = false, className = "" }) {
|
|
11512
|
-
return /* @__PURE__ */
|
|
11573
|
+
return /* @__PURE__ */ jsxs77(
|
|
11513
11574
|
"div",
|
|
11514
11575
|
{
|
|
11515
11576
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -11525,11 +11586,11 @@ function GatePending({ compact: compact3 = false, className = "" }) {
|
|
|
11525
11586
|
textAlign: "left"
|
|
11526
11587
|
},
|
|
11527
11588
|
children: [
|
|
11528
|
-
/* @__PURE__ */
|
|
11529
|
-
/* @__PURE__ */
|
|
11530
|
-
/* @__PURE__ */
|
|
11589
|
+
/* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
11590
|
+
/* @__PURE__ */ jsx90("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
11591
|
+
/* @__PURE__ */ jsx90("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
|
|
11531
11592
|
] }),
|
|
11532
|
-
/* @__PURE__ */
|
|
11593
|
+
/* @__PURE__ */ jsx90("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." })
|
|
11533
11594
|
]
|
|
11534
11595
|
}
|
|
11535
11596
|
);
|
|
@@ -11539,7 +11600,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
|
|
|
11539
11600
|
if (pending) {
|
|
11540
11601
|
if (pendingFallback !== void 0) return pendingFallback;
|
|
11541
11602
|
if (silent) return null;
|
|
11542
|
-
return /* @__PURE__ */
|
|
11603
|
+
return /* @__PURE__ */ jsx90(GatePending, { compact: compact3 });
|
|
11543
11604
|
}
|
|
11544
11605
|
let ok = true;
|
|
11545
11606
|
if (perm) ok = ok && can2(perm);
|
|
@@ -11548,7 +11609,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
|
|
|
11548
11609
|
if (ok) return children;
|
|
11549
11610
|
if (fallback !== void 0) return fallback;
|
|
11550
11611
|
if (silent) return null;
|
|
11551
|
-
return /* @__PURE__ */
|
|
11612
|
+
return /* @__PURE__ */ jsx90(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
|
|
11552
11613
|
}
|
|
11553
11614
|
function FeatureGate({
|
|
11554
11615
|
flag,
|
|
@@ -11571,7 +11632,7 @@ function FeatureGate({
|
|
|
11571
11632
|
const f = SessionKit.findFlag(flag) || {};
|
|
11572
11633
|
const missing = rt.missing || [];
|
|
11573
11634
|
const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
|
|
11574
|
-
return /* @__PURE__ */
|
|
11635
|
+
return /* @__PURE__ */ jsx90(
|
|
11575
11636
|
ComingSoon,
|
|
11576
11637
|
{
|
|
11577
11638
|
label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
|
|
@@ -11592,22 +11653,22 @@ function FeatureGate({
|
|
|
11592
11653
|
function PermissionHint({ perm, children }) {
|
|
11593
11654
|
const { can: can2, pending } = useSessionContext();
|
|
11594
11655
|
if (pending) {
|
|
11595
|
-
return /* @__PURE__ */
|
|
11656
|
+
return /* @__PURE__ */ jsx90("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ jsx90("span", { style: { pointerEvents: "none" }, children }) });
|
|
11596
11657
|
}
|
|
11597
11658
|
if (can2(perm)) return children;
|
|
11598
|
-
return /* @__PURE__ */
|
|
11659
|
+
return /* @__PURE__ */ jsx90(
|
|
11599
11660
|
"span",
|
|
11600
11661
|
{
|
|
11601
11662
|
title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
|
|
11602
11663
|
style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
|
|
11603
11664
|
"aria-disabled": "true",
|
|
11604
|
-
children: /* @__PURE__ */
|
|
11665
|
+
children: /* @__PURE__ */ jsx90("span", { style: { pointerEvents: "none" }, children })
|
|
11605
11666
|
}
|
|
11606
11667
|
);
|
|
11607
11668
|
}
|
|
11608
11669
|
|
|
11609
11670
|
// src/components/platform/ModeSwitch.tsx
|
|
11610
|
-
import { Fragment as Fragment25, jsx as
|
|
11671
|
+
import { Fragment as Fragment25, jsx as jsx91, jsxs as jsxs78 } from "react/jsx-runtime";
|
|
11611
11672
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
11612
11673
|
const mode2 = useRuntimeMode();
|
|
11613
11674
|
const panel = useInlinePanel();
|
|
@@ -11619,8 +11680,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
11619
11680
|
RuntimeKit.setMode(next);
|
|
11620
11681
|
setOpen(false);
|
|
11621
11682
|
};
|
|
11622
|
-
return /* @__PURE__ */
|
|
11623
|
-
/* @__PURE__ */
|
|
11683
|
+
return /* @__PURE__ */ jsxs78("span", { style: { display: "inline-flex" }, ref, children: [
|
|
11684
|
+
/* @__PURE__ */ jsxs78(
|
|
11624
11685
|
"button",
|
|
11625
11686
|
{
|
|
11626
11687
|
type: "button",
|
|
@@ -11630,29 +11691,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
11630
11691
|
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.",
|
|
11631
11692
|
className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
|
|
11632
11693
|
children: [
|
|
11633
|
-
/* @__PURE__ */
|
|
11634
|
-
test && requestCount ? /* @__PURE__ */
|
|
11694
|
+
/* @__PURE__ */ jsx91("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
|
|
11695
|
+
test && requestCount ? /* @__PURE__ */ jsx91("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
|
|
11635
11696
|
]
|
|
11636
11697
|
}
|
|
11637
11698
|
),
|
|
11638
|
-
/* @__PURE__ */
|
|
11639
|
-
/* @__PURE__ */
|
|
11640
|
-
/* @__PURE__ */
|
|
11641
|
-
/* @__PURE__ */
|
|
11699
|
+
/* @__PURE__ */ jsxs78(InlinePanelSurface, { panel, align: "right", offset: 8, width: 400, className: "fd-mode-pop", label: test ? "Test mode" : "Live mode", children: [
|
|
11700
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
11701
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
|
|
11702
|
+
/* @__PURE__ */ jsx91("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
|
|
11642
11703
|
test ? "Test mode" : "Live mode"
|
|
11643
11704
|
] }),
|
|
11644
|
-
test ? /* @__PURE__ */
|
|
11705
|
+
test ? /* @__PURE__ */ jsxs78("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
11645
11706
|
requestCount,
|
|
11646
11707
|
" simulated request",
|
|
11647
11708
|
requestCount === 1 ? "" : "s"
|
|
11648
11709
|
] }) : null,
|
|
11649
|
-
/* @__PURE__ */
|
|
11650
|
-
test && onClearLog ? /* @__PURE__ */
|
|
11710
|
+
/* @__PURE__ */ jsx91("span", { style: { flex: 1 } }),
|
|
11711
|
+
test && onClearLog ? /* @__PURE__ */ jsx91("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
|
|
11651
11712
|
] }),
|
|
11652
|
-
/* @__PURE__ */
|
|
11653
|
-
/* @__PURE__ */
|
|
11654
|
-
/* @__PURE__ */
|
|
11655
|
-
/* @__PURE__ */
|
|
11713
|
+
/* @__PURE__ */ jsxs78("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
11714
|
+
/* @__PURE__ */ jsx91("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." }),
|
|
11715
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
|
|
11716
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
11656
11717
|
s.endpointsWired,
|
|
11657
11718
|
" endpoint",
|
|
11658
11719
|
s.endpointsWired === 1 ? "" : "s",
|
|
@@ -11662,58 +11723,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
11662
11723
|
s.total,
|
|
11663
11724
|
" features complete"
|
|
11664
11725
|
] }),
|
|
11665
|
-
onOpenSpec ? /* @__PURE__ */
|
|
11666
|
-
/* @__PURE__ */
|
|
11667
|
-
/* @__PURE__ */
|
|
11726
|
+
onOpenSpec ? /* @__PURE__ */ jsxs78(Fragment25, { children: [
|
|
11727
|
+
/* @__PURE__ */ jsx91("span", { style: { flex: 1 } }),
|
|
11728
|
+
/* @__PURE__ */ jsxs78("button", { type: "button", className: "fd-soon-link", onClick: () => {
|
|
11668
11729
|
setOpen(false);
|
|
11669
11730
|
onOpenSpec();
|
|
11670
11731
|
}, children: [
|
|
11671
11732
|
"API spec ",
|
|
11672
|
-
/* @__PURE__ */
|
|
11733
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
11673
11734
|
] })
|
|
11674
11735
|
] }) : null
|
|
11675
11736
|
] })
|
|
11676
11737
|
] }),
|
|
11677
|
-
/* @__PURE__ */
|
|
11678
|
-
/* @__PURE__ */
|
|
11679
|
-
/* @__PURE__ */
|
|
11680
|
-
/* @__PURE__ */
|
|
11681
|
-
/* @__PURE__ */
|
|
11682
|
-
/* @__PURE__ */
|
|
11738
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-mode-choice", children: [
|
|
11739
|
+
/* @__PURE__ */ jsxs78("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
|
|
11740
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
11741
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-mode-opt-text", children: [
|
|
11742
|
+
/* @__PURE__ */ jsx91("span", { className: "fd-mode-opt-title", children: "Live mode" }),
|
|
11743
|
+
/* @__PURE__ */ jsx91("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
|
|
11683
11744
|
] }),
|
|
11684
|
-
!test ? /* @__PURE__ */
|
|
11745
|
+
!test ? /* @__PURE__ */ jsx91("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
11685
11746
|
] }),
|
|
11686
|
-
/* @__PURE__ */
|
|
11687
|
-
/* @__PURE__ */
|
|
11688
|
-
/* @__PURE__ */
|
|
11689
|
-
/* @__PURE__ */
|
|
11690
|
-
/* @__PURE__ */
|
|
11747
|
+
/* @__PURE__ */ jsxs78("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
|
|
11748
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
11749
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-mode-opt-text", children: [
|
|
11750
|
+
/* @__PURE__ */ jsx91("span", { className: "fd-mode-opt-title", children: "Test mode" }),
|
|
11751
|
+
/* @__PURE__ */ jsx91("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
|
|
11691
11752
|
] }),
|
|
11692
|
-
test ? /* @__PURE__ */
|
|
11753
|
+
test ? /* @__PURE__ */ jsx91("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
11693
11754
|
] })
|
|
11694
11755
|
] }),
|
|
11695
|
-
test && renderLog ? /* @__PURE__ */
|
|
11756
|
+
test && renderLog ? /* @__PURE__ */ jsx91("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
|
|
11696
11757
|
] })
|
|
11697
11758
|
] });
|
|
11698
11759
|
}
|
|
11699
11760
|
function TestModeBar({ onExit }) {
|
|
11700
11761
|
const mode2 = useRuntimeMode();
|
|
11701
11762
|
if (mode2 !== "test") return null;
|
|
11702
|
-
return /* @__PURE__ */
|
|
11703
|
-
/* @__PURE__ */
|
|
11704
|
-
/* @__PURE__ */
|
|
11763
|
+
return /* @__PURE__ */ jsxs78("div", { className: "fd-testbar", role: "status", children: [
|
|
11764
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-badge fd-badge-warning", children: [
|
|
11765
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
11705
11766
|
"Test mode"
|
|
11706
11767
|
] }),
|
|
11707
|
-
/* @__PURE__ */
|
|
11708
|
-
/* @__PURE__ */
|
|
11709
|
-
/* @__PURE__ */
|
|
11768
|
+
/* @__PURE__ */ jsx91("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
|
|
11769
|
+
/* @__PURE__ */ jsxs78("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
|
|
11770
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
11710
11771
|
" Back to live mode"
|
|
11711
11772
|
] })
|
|
11712
11773
|
] });
|
|
11713
11774
|
}
|
|
11714
11775
|
|
|
11715
11776
|
// src/components/planner/ChannelMeta.tsx
|
|
11716
|
-
import { jsx as
|
|
11777
|
+
import { jsx as jsx92, jsxs as jsxs79 } from "react/jsx-runtime";
|
|
11717
11778
|
var CHANNEL_WEIGHTS = {
|
|
11718
11779
|
"OOH": 50,
|
|
11719
11780
|
"DOOH": 50,
|
|
@@ -11766,9 +11827,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
11766
11827
|
const m = ChannelMeta(channel);
|
|
11767
11828
|
const wt = channelWeightOf(channel || "");
|
|
11768
11829
|
if (dot) {
|
|
11769
|
-
return /* @__PURE__ */
|
|
11830
|
+
return /* @__PURE__ */ jsx92("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
|
|
11770
11831
|
}
|
|
11771
|
-
return /* @__PURE__ */
|
|
11832
|
+
return /* @__PURE__ */ jsxs79(
|
|
11772
11833
|
"span",
|
|
11773
11834
|
{
|
|
11774
11835
|
className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
|
|
@@ -11776,16 +11837,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
11776
11837
|
style: { "--chan": m.color },
|
|
11777
11838
|
...rest,
|
|
11778
11839
|
children: [
|
|
11779
|
-
/* @__PURE__ */
|
|
11780
|
-
showLabel ? /* @__PURE__ */
|
|
11781
|
-
weight ? /* @__PURE__ */
|
|
11840
|
+
/* @__PURE__ */ jsx92("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
|
|
11841
|
+
showLabel ? /* @__PURE__ */ jsx92("span", { className: "fd-chan-label", children: m.label }) : null,
|
|
11842
|
+
weight ? /* @__PURE__ */ jsx92("span", { className: "fd-chan-weight", children: wt || 0 }) : null
|
|
11782
11843
|
]
|
|
11783
11844
|
}
|
|
11784
11845
|
);
|
|
11785
11846
|
}
|
|
11786
11847
|
|
|
11787
11848
|
// src/components/planner/SaturationDistribution.tsx
|
|
11788
|
-
import { jsx as
|
|
11849
|
+
import { jsx as jsx93, jsxs as jsxs80 } from "react/jsx-runtime";
|
|
11789
11850
|
var BANDS2 = [
|
|
11790
11851
|
{ key: "weak", label: "Weak", n: 1, range: "< 50" },
|
|
11791
11852
|
{ key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
|
|
@@ -11796,24 +11857,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11796
11857
|
const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
|
|
11797
11858
|
const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
|
|
11798
11859
|
const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
|
|
11799
|
-
return /* @__PURE__ */
|
|
11800
|
-
/* @__PURE__ */
|
|
11860
|
+
return /* @__PURE__ */ jsxs80("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
11861
|
+
/* @__PURE__ */ jsx93("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
|
|
11801
11862
|
const mark = "var(--csi-" + g.n + "-mark)";
|
|
11802
11863
|
const active = selectedBand === g.key;
|
|
11803
|
-
return /* @__PURE__ */
|
|
11864
|
+
return /* @__PURE__ */ jsxs80(
|
|
11804
11865
|
"button",
|
|
11805
11866
|
{
|
|
11806
11867
|
type: "button",
|
|
11807
11868
|
onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
|
|
11808
11869
|
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)" },
|
|
11809
11870
|
children: [
|
|
11810
|
-
/* @__PURE__ */
|
|
11871
|
+
/* @__PURE__ */ jsx93("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx93("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
|
|
11811
11872
|
// `overflow: hidden` + `white-space: nowrap` only clips once the span
|
|
11812
11873
|
// actually HAS a bounded width to clip against (see the grid/flex
|
|
11813
11874
|
// `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
|
|
11814
11875
|
// that clip readable instead of a hard cut mid-letter; the full name
|
|
11815
11876
|
// is still one hover away via `title`.
|
|
11816
|
-
/* @__PURE__ */
|
|
11877
|
+
/* @__PURE__ */ jsx93(
|
|
11817
11878
|
"span",
|
|
11818
11879
|
{
|
|
11819
11880
|
title: c.name + " \xB7 " + c.crp,
|
|
@@ -11823,13 +11884,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11823
11884
|
c.name
|
|
11824
11885
|
)
|
|
11825
11886
|
)) }),
|
|
11826
|
-
/* @__PURE__ */
|
|
11827
|
-
/* @__PURE__ */
|
|
11828
|
-
/* @__PURE__ */
|
|
11887
|
+
/* @__PURE__ */ jsxs80("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
|
|
11888
|
+
/* @__PURE__ */ jsx93("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
|
|
11889
|
+
/* @__PURE__ */ jsx93("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx93("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
|
|
11829
11890
|
] }),
|
|
11830
|
-
/* @__PURE__ */
|
|
11831
|
-
/* @__PURE__ */
|
|
11832
|
-
/* @__PURE__ */
|
|
11891
|
+
/* @__PURE__ */ jsxs80("span", { className: "fd-stack", style: { gap: 1 }, children: [
|
|
11892
|
+
/* @__PURE__ */ jsx93("span", { className: "fd-label-lg", children: g.label }),
|
|
11893
|
+
/* @__PURE__ */ jsxs80("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
|
|
11833
11894
|
"CRP ",
|
|
11834
11895
|
g.range
|
|
11835
11896
|
] })
|
|
@@ -11839,10 +11900,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11839
11900
|
g.key
|
|
11840
11901
|
);
|
|
11841
11902
|
}) }),
|
|
11842
|
-
floorBand ? /* @__PURE__ */
|
|
11843
|
-
/* @__PURE__ */
|
|
11844
|
-
/* @__PURE__ */
|
|
11845
|
-
/* @__PURE__ */
|
|
11903
|
+
floorBand ? /* @__PURE__ */ jsxs80("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: [
|
|
11904
|
+
/* @__PURE__ */ jsx93("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx93("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
|
|
11905
|
+
/* @__PURE__ */ jsxs80("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
|
|
11906
|
+
/* @__PURE__ */ jsxs80("strong", { style: { color: "var(--text)" }, children: [
|
|
11846
11907
|
"Plan floor ",
|
|
11847
11908
|
floorScore
|
|
11848
11909
|
] }),
|
|
@@ -11853,8 +11914,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11853
11914
|
}
|
|
11854
11915
|
|
|
11855
11916
|
// src/components/planner/MixGap.tsx
|
|
11856
|
-
import * as
|
|
11857
|
-
import { Fragment as Fragment26, jsx as
|
|
11917
|
+
import * as React67 from "react";
|
|
11918
|
+
import { Fragment as Fragment26, jsx as jsx94, jsxs as jsxs81 } from "react/jsx-runtime";
|
|
11858
11919
|
var MIX_GAP_LAYOUT = {
|
|
11859
11920
|
trackHeight: 30,
|
|
11860
11921
|
barHeight: 20,
|
|
@@ -11868,19 +11929,19 @@ function mixGapOffset(value, max) {
|
|
|
11868
11929
|
}
|
|
11869
11930
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
11870
11931
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
11871
|
-
const [hover, setHover] =
|
|
11932
|
+
const [hover, setHover] = React67.useState(null);
|
|
11872
11933
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
11873
11934
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
11874
11935
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
11875
11936
|
const barTop = (trackHeight - barHeight) / 2;
|
|
11876
|
-
return /* @__PURE__ */
|
|
11877
|
-
/* @__PURE__ */
|
|
11878
|
-
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */
|
|
11879
|
-
/* @__PURE__ */
|
|
11937
|
+
return /* @__PURE__ */ jsxs81("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
|
|
11938
|
+
/* @__PURE__ */ jsxs81("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
|
|
11939
|
+
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs81("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
11940
|
+
/* @__PURE__ */ jsx94("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
|
|
11880
11941
|
l
|
|
11881
11942
|
] }, l)),
|
|
11882
|
-
/* @__PURE__ */
|
|
11883
|
-
/* @__PURE__ */
|
|
11943
|
+
/* @__PURE__ */ jsxs81("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
11944
|
+
/* @__PURE__ */ jsx94("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
|
|
11884
11945
|
"Target"
|
|
11885
11946
|
] })
|
|
11886
11947
|
] }),
|
|
@@ -11889,7 +11950,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11889
11950
|
const tone = toneOf(gap);
|
|
11890
11951
|
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 : "");
|
|
11891
11952
|
const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
|
|
11892
|
-
return /* @__PURE__ */
|
|
11953
|
+
return /* @__PURE__ */ jsxs81(
|
|
11893
11954
|
"div",
|
|
11894
11955
|
{
|
|
11895
11956
|
className: "fd-row",
|
|
@@ -11897,15 +11958,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11897
11958
|
onMouseEnter: () => setHover(r.channel),
|
|
11898
11959
|
onMouseLeave: () => setHover(null),
|
|
11899
11960
|
children: [
|
|
11900
|
-
/* @__PURE__ */
|
|
11901
|
-
/* @__PURE__ */
|
|
11902
|
-
/* @__PURE__ */
|
|
11903
|
-
/* @__PURE__ */
|
|
11904
|
-
/* @__PURE__ */
|
|
11961
|
+
/* @__PURE__ */ jsx94("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx94(ChannelTag, { channel: r.channel, size: "sm" }) }),
|
|
11962
|
+
/* @__PURE__ */ jsx94("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx94("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs81(Fragment26, { children: [
|
|
11963
|
+
/* @__PURE__ */ jsx94("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)" } }),
|
|
11964
|
+
/* @__PURE__ */ jsx94("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 } }),
|
|
11965
|
+
/* @__PURE__ */ jsxs81("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: [
|
|
11905
11966
|
r.realized,
|
|
11906
11967
|
"%"
|
|
11907
11968
|
] }),
|
|
11908
|
-
hover === r.channel ? /* @__PURE__ */
|
|
11969
|
+
hover === r.channel ? /* @__PURE__ */ jsx94("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
|
|
11909
11970
|
] }) })
|
|
11910
11971
|
]
|
|
11911
11972
|
},
|
|
@@ -11916,7 +11977,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11916
11977
|
}
|
|
11917
11978
|
|
|
11918
11979
|
// src/components/planner/ChannelContribution.tsx
|
|
11919
|
-
import { jsx as
|
|
11980
|
+
import { jsx as jsx95, jsxs as jsxs82 } from "react/jsx-runtime";
|
|
11920
11981
|
var money = (n) => "$" + Math.round(n).toLocaleString();
|
|
11921
11982
|
function ChannelContribution({
|
|
11922
11983
|
channels = [],
|
|
@@ -11932,9 +11993,9 @@ function ChannelContribution({
|
|
|
11932
11993
|
const grand = total !== void 0 ? total : base + bonus;
|
|
11933
11994
|
const pct = (v) => grand ? v / grand * 100 : 0;
|
|
11934
11995
|
const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
|
|
11935
|
-
return /* @__PURE__ */
|
|
11936
|
-
loading ? /* @__PURE__ */
|
|
11937
|
-
channels.map((c) => /* @__PURE__ */
|
|
11996
|
+
return /* @__PURE__ */ jsxs82("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
11997
|
+
loading ? /* @__PURE__ */ jsx95("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs82("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
|
|
11998
|
+
channels.map((c) => /* @__PURE__ */ jsx95(
|
|
11938
11999
|
"span",
|
|
11939
12000
|
{
|
|
11940
12001
|
title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
|
|
@@ -11943,7 +12004,7 @@ function ChannelContribution({
|
|
|
11943
12004
|
},
|
|
11944
12005
|
c.name
|
|
11945
12006
|
)),
|
|
11946
|
-
bonus > 0 ? /* @__PURE__ */
|
|
12007
|
+
bonus > 0 ? /* @__PURE__ */ jsx95(
|
|
11947
12008
|
"span",
|
|
11948
12009
|
{
|
|
11949
12010
|
title: "Surround-sound bonus +" + bonusPct + "%",
|
|
@@ -11952,18 +12013,18 @@ function ChannelContribution({
|
|
|
11952
12013
|
}
|
|
11953
12014
|
) : null
|
|
11954
12015
|
] }),
|
|
11955
|
-
showTable ? /* @__PURE__ */
|
|
11956
|
-
/* @__PURE__ */
|
|
11957
|
-
/* @__PURE__ */
|
|
11958
|
-
/* @__PURE__ */
|
|
11959
|
-
/* @__PURE__ */
|
|
11960
|
-
/* @__PURE__ */
|
|
11961
|
-
/* @__PURE__ */
|
|
12016
|
+
showTable ? /* @__PURE__ */ jsxs82("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
|
|
12017
|
+
/* @__PURE__ */ jsx95("thead", { children: /* @__PURE__ */ jsxs82("tr", { children: [
|
|
12018
|
+
/* @__PURE__ */ jsx95("th", { style: { width: "34%" }, children: "Channel" }),
|
|
12019
|
+
/* @__PURE__ */ jsx95("th", { style: { width: "16%" }, children: "Weight" }),
|
|
12020
|
+
/* @__PURE__ */ jsx95("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
|
|
12021
|
+
/* @__PURE__ */ jsx95("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
|
|
12022
|
+
/* @__PURE__ */ jsx95("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
|
|
11962
12023
|
] }) }),
|
|
11963
|
-
/* @__PURE__ */
|
|
11964
|
-
channels.map((c) => /* @__PURE__ */
|
|
11965
|
-
/* @__PURE__ */
|
|
11966
|
-
/* @__PURE__ */
|
|
12024
|
+
/* @__PURE__ */ jsxs82("tbody", { children: [
|
|
12025
|
+
channels.map((c) => /* @__PURE__ */ jsxs82("tr", { children: [
|
|
12026
|
+
/* @__PURE__ */ jsx95("td", { children: /* @__PURE__ */ jsx95(ChannelTag, { channel: c.name, size: "sm" }) }),
|
|
12027
|
+
/* @__PURE__ */ jsx95("td", { children: /* @__PURE__ */ jsx95(
|
|
11967
12028
|
"span",
|
|
11968
12029
|
{
|
|
11969
12030
|
className: "fd-badge fd-badge-neutral",
|
|
@@ -11972,38 +12033,38 @@ function ChannelContribution({
|
|
|
11972
12033
|
children: "weight " + (channelWeightOf(c.name) || 0)
|
|
11973
12034
|
}
|
|
11974
12035
|
) }),
|
|
11975
|
-
/* @__PURE__ */
|
|
11976
|
-
/* @__PURE__ */
|
|
11977
|
-
/* @__PURE__ */
|
|
12036
|
+
/* @__PURE__ */ jsx95("td", { className: "is-num", children: c.spend }),
|
|
12037
|
+
/* @__PURE__ */ jsx95("td", { className: "is-num", children: c.crp.toFixed(1) }),
|
|
12038
|
+
/* @__PURE__ */ jsxs82("td", { className: "is-num", children: [
|
|
11978
12039
|
pct(c.crp).toFixed(0),
|
|
11979
12040
|
"%"
|
|
11980
12041
|
] })
|
|
11981
12042
|
] }, c.name)),
|
|
11982
|
-
bonus > 0 ? /* @__PURE__ */
|
|
11983
|
-
/* @__PURE__ */
|
|
11984
|
-
/* @__PURE__ */
|
|
12043
|
+
bonus > 0 ? /* @__PURE__ */ jsxs82("tr", { children: [
|
|
12044
|
+
/* @__PURE__ */ jsx95("td", { children: /* @__PURE__ */ jsxs82("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
|
|
12045
|
+
/* @__PURE__ */ jsx95("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" } }),
|
|
11985
12046
|
"Surround-sound bonus"
|
|
11986
12047
|
] }) }),
|
|
11987
|
-
/* @__PURE__ */
|
|
12048
|
+
/* @__PURE__ */ jsx95("td", { children: /* @__PURE__ */ jsxs82("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
|
|
11988
12049
|
"+",
|
|
11989
12050
|
bonusPct,
|
|
11990
12051
|
"% of +",
|
|
11991
12052
|
bonusMax,
|
|
11992
12053
|
"%"
|
|
11993
12054
|
] }) }),
|
|
11994
|
-
/* @__PURE__ */
|
|
11995
|
-
/* @__PURE__ */
|
|
11996
|
-
/* @__PURE__ */
|
|
12055
|
+
/* @__PURE__ */ jsx95("td", { className: "is-num fd-muted", children: "\u2014" }),
|
|
12056
|
+
/* @__PURE__ */ jsx95("td", { className: "is-num", children: bonus.toFixed(1) }),
|
|
12057
|
+
/* @__PURE__ */ jsxs82("td", { className: "is-num", children: [
|
|
11997
12058
|
pct(bonus).toFixed(0),
|
|
11998
12059
|
"%"
|
|
11999
12060
|
] })
|
|
12000
12061
|
] }) : null,
|
|
12001
|
-
/* @__PURE__ */
|
|
12002
|
-
/* @__PURE__ */
|
|
12003
|
-
/* @__PURE__ */
|
|
12004
|
-
/* @__PURE__ */
|
|
12005
|
-
/* @__PURE__ */
|
|
12006
|
-
/* @__PURE__ */
|
|
12062
|
+
/* @__PURE__ */ jsxs82("tr", { style: { background: "var(--surface-2)" }, children: [
|
|
12063
|
+
/* @__PURE__ */ jsx95("td", { style: { fontWeight: 700 }, children: "Campus total" }),
|
|
12064
|
+
/* @__PURE__ */ jsx95("td", {}),
|
|
12065
|
+
/* @__PURE__ */ jsx95("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
|
|
12066
|
+
/* @__PURE__ */ jsx95("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
|
|
12067
|
+
/* @__PURE__ */ jsx95("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
|
|
12007
12068
|
] })
|
|
12008
12069
|
] })
|
|
12009
12070
|
] }) : null
|
|
@@ -12011,8 +12072,8 @@ function ChannelContribution({
|
|
|
12011
12072
|
}
|
|
12012
12073
|
|
|
12013
12074
|
// src/components/planner/BudgetReallocator.tsx
|
|
12014
|
-
import * as
|
|
12015
|
-
import { Fragment as Fragment27, jsx as
|
|
12075
|
+
import * as React68 from "react";
|
|
12076
|
+
import { Fragment as Fragment27, jsx as jsx96, jsxs as jsxs83 } from "react/jsx-runtime";
|
|
12016
12077
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
12017
12078
|
function BudgetReallocator({
|
|
12018
12079
|
campus,
|
|
@@ -12027,8 +12088,8 @@ function BudgetReallocator({
|
|
|
12027
12088
|
onCancel,
|
|
12028
12089
|
className = ""
|
|
12029
12090
|
}) {
|
|
12030
|
-
const [draft, setDraft] =
|
|
12031
|
-
|
|
12091
|
+
const [draft, setDraft] = React68.useState(spend);
|
|
12092
|
+
React68.useEffect(() => setDraft(spend), [spend]);
|
|
12032
12093
|
const dirty = draft !== spend;
|
|
12033
12094
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
12034
12095
|
const nextBand = bandFor(nextCrp);
|
|
@@ -12043,10 +12104,10 @@ function BudgetReallocator({
|
|
|
12043
12104
|
setDraft(spend);
|
|
12044
12105
|
if (onCancel) onCancel();
|
|
12045
12106
|
};
|
|
12046
|
-
const trackRef =
|
|
12047
|
-
const chipRef =
|
|
12048
|
-
const [chipLeft, setChipLeft] =
|
|
12049
|
-
|
|
12107
|
+
const trackRef = React68.useRef(null);
|
|
12108
|
+
const chipRef = React68.useRef(null);
|
|
12109
|
+
const [chipLeft, setChipLeft] = React68.useState(null);
|
|
12110
|
+
React68.useLayoutEffect(() => {
|
|
12050
12111
|
const track = trackRef.current;
|
|
12051
12112
|
if (!dirty || !track) {
|
|
12052
12113
|
setChipLeft(null);
|
|
@@ -12067,23 +12128,23 @@ function BudgetReallocator({
|
|
|
12067
12128
|
ro.observe(track);
|
|
12068
12129
|
return () => ro.disconnect();
|
|
12069
12130
|
}, [dirty, pct]);
|
|
12070
|
-
return /* @__PURE__ */
|
|
12131
|
+
return /* @__PURE__ */ jsxs83(
|
|
12071
12132
|
"div",
|
|
12072
12133
|
{
|
|
12073
12134
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
12074
12135
|
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)" },
|
|
12075
12136
|
children: [
|
|
12076
|
-
/* @__PURE__ */
|
|
12077
|
-
/* @__PURE__ */
|
|
12078
|
-
/* @__PURE__ */
|
|
12079
|
-
dirty ? /* @__PURE__ */
|
|
12080
|
-
/* @__PURE__ */
|
|
12081
|
-
/* @__PURE__ */
|
|
12137
|
+
/* @__PURE__ */ jsxs83("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
12138
|
+
/* @__PURE__ */ jsx96("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
|
|
12139
|
+
/* @__PURE__ */ jsx96(CsiBadge, { band: nowBand, crp, size: "medium" }),
|
|
12140
|
+
dirty ? /* @__PURE__ */ jsxs83(Fragment27, { children: [
|
|
12141
|
+
/* @__PURE__ */ jsx96("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
|
|
12142
|
+
/* @__PURE__ */ jsx96(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
|
|
12082
12143
|
] }) : null
|
|
12083
12144
|
] }),
|
|
12084
|
-
/* @__PURE__ */
|
|
12085
|
-
/* @__PURE__ */
|
|
12086
|
-
dirty ? /* @__PURE__ */
|
|
12145
|
+
/* @__PURE__ */ jsxs83("div", { className: "fd-slider", ref: trackRef, children: [
|
|
12146
|
+
/* @__PURE__ */ jsx96("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
12147
|
+
dirty ? /* @__PURE__ */ jsx96(
|
|
12087
12148
|
"span",
|
|
12088
12149
|
{
|
|
12089
12150
|
ref: chipRef,
|
|
@@ -12095,7 +12156,7 @@ function BudgetReallocator({
|
|
|
12095
12156
|
children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
|
|
12096
12157
|
}
|
|
12097
12158
|
) : null,
|
|
12098
|
-
/* @__PURE__ */
|
|
12159
|
+
/* @__PURE__ */ jsx96(
|
|
12099
12160
|
"input",
|
|
12100
12161
|
{
|
|
12101
12162
|
type: "range",
|
|
@@ -12111,13 +12172,13 @@ function BudgetReallocator({
|
|
|
12111
12172
|
}
|
|
12112
12173
|
)
|
|
12113
12174
|
] }),
|
|
12114
|
-
/* @__PURE__ */
|
|
12115
|
-
/* @__PURE__ */
|
|
12116
|
-
/* @__PURE__ */
|
|
12117
|
-
/* @__PURE__ */
|
|
12175
|
+
/* @__PURE__ */ jsxs83("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
12176
|
+
/* @__PURE__ */ jsxs83("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
|
|
12177
|
+
/* @__PURE__ */ jsx96("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
|
|
12178
|
+
/* @__PURE__ */ jsx96("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
|
|
12118
12179
|
] }),
|
|
12119
|
-
/* @__PURE__ */
|
|
12120
|
-
/* @__PURE__ */
|
|
12180
|
+
/* @__PURE__ */ jsx96("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
|
|
12181
|
+
/* @__PURE__ */ jsx96(
|
|
12121
12182
|
"button",
|
|
12122
12183
|
{
|
|
12123
12184
|
type: "button",
|
|
@@ -12136,7 +12197,7 @@ function BudgetReallocator({
|
|
|
12136
12197
|
}
|
|
12137
12198
|
|
|
12138
12199
|
// src/components/planner/SurroundSound.tsx
|
|
12139
|
-
import { jsx as
|
|
12200
|
+
import { jsx as jsx97, jsxs as jsxs84 } from "react/jsx-runtime";
|
|
12140
12201
|
var CATEGORIES = [
|
|
12141
12202
|
{ key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
|
|
12142
12203
|
{ key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
|
|
@@ -12148,26 +12209,26 @@ var CATEGORIES = [
|
|
|
12148
12209
|
function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
|
|
12149
12210
|
const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
|
|
12150
12211
|
const single = present.length <= 2;
|
|
12151
|
-
return /* @__PURE__ */
|
|
12152
|
-
/* @__PURE__ */
|
|
12212
|
+
return /* @__PURE__ */ jsxs84("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
|
|
12213
|
+
/* @__PURE__ */ jsx97("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
|
|
12153
12214
|
const on = present.includes(c.key);
|
|
12154
|
-
return /* @__PURE__ */
|
|
12215
|
+
return /* @__PURE__ */ jsxs84(
|
|
12155
12216
|
"span",
|
|
12156
12217
|
{
|
|
12157
12218
|
title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
|
|
12158
12219
|
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)" },
|
|
12159
12220
|
children: [
|
|
12160
|
-
/* @__PURE__ */
|
|
12161
|
-
/* @__PURE__ */
|
|
12221
|
+
/* @__PURE__ */ jsx97("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
12222
|
+
/* @__PURE__ */ jsx97("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
|
|
12162
12223
|
]
|
|
12163
12224
|
},
|
|
12164
12225
|
c.key
|
|
12165
12226
|
);
|
|
12166
12227
|
}) }),
|
|
12167
|
-
/* @__PURE__ */
|
|
12168
|
-
/* @__PURE__ */
|
|
12169
|
-
/* @__PURE__ */
|
|
12170
|
-
/* @__PURE__ */
|
|
12228
|
+
/* @__PURE__ */ jsxs84("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
12229
|
+
/* @__PURE__ */ jsxs84("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
12230
|
+
/* @__PURE__ */ jsx97("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
|
|
12231
|
+
/* @__PURE__ */ jsxs84("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
|
|
12171
12232
|
"+",
|
|
12172
12233
|
bonusPct,
|
|
12173
12234
|
"% of +",
|
|
@@ -12175,8 +12236,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
12175
12236
|
"%"
|
|
12176
12237
|
] })
|
|
12177
12238
|
] }),
|
|
12178
|
-
/* @__PURE__ */
|
|
12179
|
-
/* @__PURE__ */
|
|
12239
|
+
/* @__PURE__ */ jsx97("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx97("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
|
|
12240
|
+
/* @__PURE__ */ jsxs84("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
|
|
12180
12241
|
present.length,
|
|
12181
12242
|
" of 6 channel categories present.",
|
|
12182
12243
|
" ",
|
|
@@ -12188,7 +12249,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
12188
12249
|
}
|
|
12189
12250
|
|
|
12190
12251
|
// src/components/planner/Importance.tsx
|
|
12191
|
-
import { jsx as
|
|
12252
|
+
import { jsx as jsx98, jsxs as jsxs85 } from "react/jsx-runtime";
|
|
12192
12253
|
var IMPORTANCE_LEVELS = [
|
|
12193
12254
|
{ id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
|
|
12194
12255
|
{ id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
|
|
@@ -12218,7 +12279,7 @@ function importanceTokens(id) {
|
|
|
12218
12279
|
function ImportanceTag({ level, showLabel = true, size = "sm", className = "", disabled = false }) {
|
|
12219
12280
|
const lvl = importanceLevel(level);
|
|
12220
12281
|
const t = importanceTokens(level);
|
|
12221
|
-
return /* @__PURE__ */
|
|
12282
|
+
return /* @__PURE__ */ jsxs85(
|
|
12222
12283
|
"span",
|
|
12223
12284
|
{
|
|
12224
12285
|
className: ["fd-imp-tag", size === "md" ? "is-md" : "", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "),
|
|
@@ -12226,16 +12287,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
|
|
|
12226
12287
|
title: lvl.label + " \u2014 " + lvl.description,
|
|
12227
12288
|
"aria-disabled": disabled ? "true" : void 0,
|
|
12228
12289
|
children: [
|
|
12229
|
-
/* @__PURE__ */
|
|
12230
|
-
showLabel ? lvl.label : /* @__PURE__ */
|
|
12290
|
+
/* @__PURE__ */ jsx98("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
|
|
12291
|
+
showLabel ? lvl.label : /* @__PURE__ */ jsx98("span", { className: "fd-sr", children: lvl.label })
|
|
12231
12292
|
]
|
|
12232
12293
|
}
|
|
12233
12294
|
);
|
|
12234
12295
|
}
|
|
12235
12296
|
|
|
12236
12297
|
// src/components/planner/PreferenceMeter.tsx
|
|
12237
|
-
import * as
|
|
12238
|
-
import { jsx as
|
|
12298
|
+
import * as React69 from "react";
|
|
12299
|
+
import { jsx as jsx99, jsxs as jsxs86 } from "react/jsx-runtime";
|
|
12239
12300
|
function preferenceScore(criteria) {
|
|
12240
12301
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
12241
12302
|
const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
|
|
@@ -12264,8 +12325,8 @@ function PreferenceMeter({
|
|
|
12264
12325
|
className = ""
|
|
12265
12326
|
}) {
|
|
12266
12327
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
12267
|
-
const segments =
|
|
12268
|
-
return /* @__PURE__ */
|
|
12328
|
+
const segments = React69.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
12329
|
+
return /* @__PURE__ */ jsx99(
|
|
12269
12330
|
ScoreMeter,
|
|
12270
12331
|
{
|
|
12271
12332
|
score: value,
|
|
@@ -12277,22 +12338,22 @@ function PreferenceMeter({
|
|
|
12277
12338
|
placement,
|
|
12278
12339
|
className,
|
|
12279
12340
|
breakdownLabel: breakdownTitle,
|
|
12280
|
-
breakdown: /* @__PURE__ */
|
|
12281
|
-
/* @__PURE__ */
|
|
12282
|
-
/* @__PURE__ */
|
|
12283
|
-
/* @__PURE__ */
|
|
12341
|
+
breakdown: /* @__PURE__ */ jsxs86("div", { className: "fd-prefbreak", children: [
|
|
12342
|
+
/* @__PURE__ */ jsxs86("div", { className: "fd-prefbreak-head", children: [
|
|
12343
|
+
/* @__PURE__ */ jsx99("span", { className: "fd-label-lg", children: breakdownTitle }),
|
|
12344
|
+
/* @__PURE__ */ jsx99("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
|
|
12284
12345
|
] }),
|
|
12285
|
-
/* @__PURE__ */
|
|
12346
|
+
/* @__PURE__ */ jsx99("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
|
|
12286
12347
|
const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
|
|
12287
|
-
return /* @__PURE__ */
|
|
12288
|
-
/* @__PURE__ */
|
|
12289
|
-
/* @__PURE__ */
|
|
12290
|
-
/* @__PURE__ */
|
|
12291
|
-
c.note ? /* @__PURE__ */
|
|
12348
|
+
return /* @__PURE__ */ jsxs86("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
|
|
12349
|
+
/* @__PURE__ */ jsx99(ImportanceTag, { level: c.importance }),
|
|
12350
|
+
/* @__PURE__ */ jsxs86("span", { className: "fd-prefbreak-text", children: [
|
|
12351
|
+
/* @__PURE__ */ jsx99("span", { className: "fd-prefbreak-label", children: c.label }),
|
|
12352
|
+
c.note ? /* @__PURE__ */ jsx99("span", { className: "fd-prefbreak-note", children: c.note }) : null
|
|
12292
12353
|
] }),
|
|
12293
|
-
/* @__PURE__ */
|
|
12354
|
+
/* @__PURE__ */ jsxs86("span", { className: "fd-prefbreak-val fd-tabular", children: [
|
|
12294
12355
|
Math.round(Number(c.earned) || 0),
|
|
12295
|
-
/* @__PURE__ */
|
|
12356
|
+
/* @__PURE__ */ jsx99("span", { className: "fd-prefbreak-sep", children: "/" }),
|
|
12296
12357
|
Math.round(c.weight)
|
|
12297
12358
|
] })
|
|
12298
12359
|
] }, c.id);
|
|
@@ -12303,10 +12364,10 @@ function PreferenceMeter({
|
|
|
12303
12364
|
}
|
|
12304
12365
|
|
|
12305
12366
|
// src/components/chat/AgentChatPanel.tsx
|
|
12306
|
-
import * as
|
|
12367
|
+
import * as React75 from "react";
|
|
12307
12368
|
|
|
12308
12369
|
// src/components/chat/chatEngine.ts
|
|
12309
|
-
import * as
|
|
12370
|
+
import * as React70 from "react";
|
|
12310
12371
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
12311
12372
|
var JOB_PENDING = ["queued", "running"];
|
|
12312
12373
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -12351,7 +12412,7 @@ function useChatEngine(opts) {
|
|
|
12351
12412
|
initialMessage,
|
|
12352
12413
|
threadId: threadIdProp,
|
|
12353
12414
|
pollIntervalMs = 1500,
|
|
12354
|
-
|
|
12415
|
+
pendingTimeoutMs = 18e4,
|
|
12355
12416
|
store = safeStore,
|
|
12356
12417
|
onPacket,
|
|
12357
12418
|
onThreadReady,
|
|
@@ -12360,22 +12421,22 @@ function useChatEngine(opts) {
|
|
|
12360
12421
|
onClear,
|
|
12361
12422
|
onFeedback
|
|
12362
12423
|
} = opts || {};
|
|
12363
|
-
const [status, setStatus] =
|
|
12364
|
-
const [threadId, setThreadId] =
|
|
12365
|
-
const [messages, setMessages] =
|
|
12366
|
-
const [queue, setQueue] =
|
|
12367
|
-
const [fatal, setFatal] =
|
|
12368
|
-
const [busy, setBusy] =
|
|
12369
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
12370
|
-
const listRef =
|
|
12371
|
-
const queueRef =
|
|
12372
|
-
const busyRef =
|
|
12373
|
-
const stoppedRef =
|
|
12374
|
-
const abortRef =
|
|
12375
|
-
const serverCount =
|
|
12376
|
-
const threadRef =
|
|
12377
|
-
const mounted =
|
|
12378
|
-
|
|
12424
|
+
const [status, setStatus] = React70.useState("idle");
|
|
12425
|
+
const [threadId, setThreadId] = React70.useState(null);
|
|
12426
|
+
const [messages, setMessages] = React70.useState([]);
|
|
12427
|
+
const [queue, setQueue] = React70.useState([]);
|
|
12428
|
+
const [fatal, setFatal] = React70.useState(null);
|
|
12429
|
+
const [busy, setBusy] = React70.useState(false);
|
|
12430
|
+
const [turnStartedAt, setTurnStartedAt] = React70.useState(null);
|
|
12431
|
+
const listRef = React70.useRef([]);
|
|
12432
|
+
const queueRef = React70.useRef([]);
|
|
12433
|
+
const busyRef = React70.useRef(false);
|
|
12434
|
+
const stoppedRef = React70.useRef(false);
|
|
12435
|
+
const abortRef = React70.useRef(null);
|
|
12436
|
+
const serverCount = React70.useRef(0);
|
|
12437
|
+
const threadRef = React70.useRef(null);
|
|
12438
|
+
const mounted = React70.useRef(true);
|
|
12439
|
+
React70.useEffect(() => {
|
|
12379
12440
|
mounted.current = true;
|
|
12380
12441
|
return () => {
|
|
12381
12442
|
mounted.current = false;
|
|
@@ -12397,14 +12458,21 @@ function useChatEngine(opts) {
|
|
|
12397
12458
|
}
|
|
12398
12459
|
return false;
|
|
12399
12460
|
};
|
|
12400
|
-
const loadThread =
|
|
12461
|
+
const loadThread = React70.useCallback(async (id) => {
|
|
12401
12462
|
const data = await apiAdapter.getThread(id);
|
|
12402
12463
|
const list = [...data && data.messages || []];
|
|
12403
12464
|
serverCount.current = list.length;
|
|
12404
12465
|
commit(list);
|
|
12405
12466
|
return list;
|
|
12406
12467
|
}, [apiAdapter]);
|
|
12407
|
-
|
|
12468
|
+
async function mergeThread() {
|
|
12469
|
+
const data = await apiAdapter.getThread(threadRef.current);
|
|
12470
|
+
const server = data && data.messages || [];
|
|
12471
|
+
const ids = new Set(server.map((m) => m.id));
|
|
12472
|
+
serverCount.current = server.length;
|
|
12473
|
+
commit([...server, ...listRef.current.filter((m) => !ids.has(m.id))]);
|
|
12474
|
+
}
|
|
12475
|
+
React70.useEffect(() => {
|
|
12408
12476
|
if (!apiAdapter) {
|
|
12409
12477
|
setStatus("idle");
|
|
12410
12478
|
setFatal(null);
|
|
@@ -12450,7 +12518,9 @@ function useChatEngine(opts) {
|
|
|
12450
12518
|
setStatus("ready");
|
|
12451
12519
|
onThreadReady && onThreadReady(id);
|
|
12452
12520
|
const stored = store.get(STORAGE_PREFIX + id);
|
|
12521
|
+
const last = [...visibleMessages(listRef.current)].reverse().find((m) => m.role === "assistant");
|
|
12453
12522
|
if (stored) resumeJob(stored);
|
|
12523
|
+
else if (last && last.working && last.jobId) resumeJob(last.jobId, last.id);
|
|
12454
12524
|
else if (initialMessage) send(initialMessage);
|
|
12455
12525
|
} catch (err) {
|
|
12456
12526
|
if (dead) return;
|
|
@@ -12466,8 +12536,8 @@ function useChatEngine(opts) {
|
|
|
12466
12536
|
}, [apiAdapter, contextType, contextId, threadIdProp]);
|
|
12467
12537
|
async function pollJob(jobId, placeholderId) {
|
|
12468
12538
|
store.set(STORAGE_PREFIX + threadRef.current, jobId);
|
|
12469
|
-
|
|
12470
|
-
while (
|
|
12539
|
+
const deadline = Date.now() + pendingTimeoutMs;
|
|
12540
|
+
while (true) {
|
|
12471
12541
|
if (stoppedRef.current) break;
|
|
12472
12542
|
await sleep(pollIntervalMs);
|
|
12473
12543
|
if (!mounted.current) return;
|
|
@@ -12485,7 +12555,15 @@ function useChatEngine(opts) {
|
|
|
12485
12555
|
}
|
|
12486
12556
|
patch(placeholderId, { job });
|
|
12487
12557
|
const bucket2 = jobBucket(job && job.status);
|
|
12488
|
-
if (bucket2 === "pending")
|
|
12558
|
+
if (bucket2 === "pending") {
|
|
12559
|
+
try {
|
|
12560
|
+
await mergeThread();
|
|
12561
|
+
} catch (err) {
|
|
12562
|
+
fail(err);
|
|
12563
|
+
}
|
|
12564
|
+
if (Date.now() >= deadline) break;
|
|
12565
|
+
continue;
|
|
12566
|
+
}
|
|
12489
12567
|
if (bucket2 === "success") {
|
|
12490
12568
|
finishJob(jobId, job);
|
|
12491
12569
|
return;
|
|
@@ -12522,9 +12600,10 @@ function useChatEngine(opts) {
|
|
|
12522
12600
|
patch(placeholderId, { working: false, streaming: false, error: code, retryable: !!retryable, job: job || void 0 });
|
|
12523
12601
|
onError && onError(new Error(code));
|
|
12524
12602
|
}
|
|
12525
|
-
function resumeJob(jobId) {
|
|
12526
|
-
const id = uid("a");
|
|
12527
|
-
|
|
12603
|
+
function resumeJob(jobId, existingId) {
|
|
12604
|
+
const id = existingId || uid("a");
|
|
12605
|
+
if (existingId) patch(id, { working: true, resumed: true });
|
|
12606
|
+
else push({ id, role: "assistant", working: true, jobId, resumed: true });
|
|
12528
12607
|
setBusy(true);
|
|
12529
12608
|
busyRef.current = true;
|
|
12530
12609
|
setTurnStartedAt(Date.now());
|
|
@@ -12617,7 +12696,7 @@ function useChatEngine(opts) {
|
|
|
12617
12696
|
await dispatchTurn(turn);
|
|
12618
12697
|
}
|
|
12619
12698
|
}
|
|
12620
|
-
const send =
|
|
12699
|
+
const send = React70.useCallback((text, attachments) => {
|
|
12621
12700
|
const body = (text || "").trim();
|
|
12622
12701
|
if (!body && !(attachments && attachments.length)) return;
|
|
12623
12702
|
if (status === "disconnected") return;
|
|
@@ -12627,7 +12706,7 @@ function useChatEngine(opts) {
|
|
|
12627
12706
|
stoppedRef.current = false;
|
|
12628
12707
|
drain();
|
|
12629
12708
|
}, [status]);
|
|
12630
|
-
const stop =
|
|
12709
|
+
const stop = React70.useCallback(() => {
|
|
12631
12710
|
stoppedRef.current = true;
|
|
12632
12711
|
const ac = abortRef.current;
|
|
12633
12712
|
if (ac) {
|
|
@@ -12646,11 +12725,11 @@ function useChatEngine(opts) {
|
|
|
12646
12725
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
12647
12726
|
}
|
|
12648
12727
|
}, [apiAdapter]);
|
|
12649
|
-
const removeQueued =
|
|
12728
|
+
const removeQueued = React70.useCallback((id) => {
|
|
12650
12729
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
12651
12730
|
setQueue(queueRef.current.slice());
|
|
12652
12731
|
}, []);
|
|
12653
|
-
const retry =
|
|
12732
|
+
const retry = React70.useCallback(() => {
|
|
12654
12733
|
const list = listRef.current;
|
|
12655
12734
|
let at = -1;
|
|
12656
12735
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -12666,19 +12745,19 @@ function useChatEngine(opts) {
|
|
|
12666
12745
|
setQueue(queueRef.current.slice());
|
|
12667
12746
|
drain();
|
|
12668
12747
|
}, []);
|
|
12669
|
-
const clear =
|
|
12748
|
+
const clear = React70.useCallback(() => {
|
|
12670
12749
|
commit([]);
|
|
12671
12750
|
serverCount.current = 0;
|
|
12672
12751
|
queueRef.current = [];
|
|
12673
12752
|
setQueue([]);
|
|
12674
12753
|
onClear && onClear();
|
|
12675
12754
|
}, [onClear]);
|
|
12676
|
-
const setFeedback =
|
|
12755
|
+
const setFeedback = React70.useCallback((id, value) => {
|
|
12677
12756
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
12678
12757
|
const msg = listRef.current.find((m) => m.id === id);
|
|
12679
12758
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
12680
12759
|
}, [onFeedback]);
|
|
12681
|
-
const reload =
|
|
12760
|
+
const reload = React70.useCallback(async () => {
|
|
12682
12761
|
if (!threadRef.current) return;
|
|
12683
12762
|
setStatus("loading");
|
|
12684
12763
|
try {
|
|
@@ -12716,11 +12795,11 @@ var ChatKit = {
|
|
|
12716
12795
|
};
|
|
12717
12796
|
|
|
12718
12797
|
// src/components/chat/ChatTranscript.tsx
|
|
12719
|
-
import * as
|
|
12798
|
+
import * as React72 from "react";
|
|
12720
12799
|
|
|
12721
12800
|
// src/components/chat/ChatTurn.tsx
|
|
12722
|
-
import * as
|
|
12723
|
-
import { jsx as
|
|
12801
|
+
import * as React71 from "react";
|
|
12802
|
+
import { jsx as jsx100, jsxs as jsxs87 } from "react/jsx-runtime";
|
|
12724
12803
|
function JsonView({ value }) {
|
|
12725
12804
|
let text;
|
|
12726
12805
|
try {
|
|
@@ -12728,67 +12807,67 @@ function JsonView({ value }) {
|
|
|
12728
12807
|
} catch (e) {
|
|
12729
12808
|
text = String(value);
|
|
12730
12809
|
}
|
|
12731
|
-
return /* @__PURE__ */
|
|
12810
|
+
return /* @__PURE__ */ jsx100(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
|
|
12732
12811
|
}
|
|
12733
12812
|
function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
12734
12813
|
if (!packet) return null;
|
|
12735
12814
|
const s = schema || {};
|
|
12736
12815
|
const invalid = packet.valid === false;
|
|
12737
12816
|
const title = s.heading || packet.type;
|
|
12738
|
-
return /* @__PURE__ */
|
|
12739
|
-
/* @__PURE__ */
|
|
12740
|
-
/* @__PURE__ */
|
|
12741
|
-
/* @__PURE__ */
|
|
12742
|
-
packet.repaired ? /* @__PURE__ */
|
|
12743
|
-
invalid ? /* @__PURE__ */
|
|
12817
|
+
return /* @__PURE__ */ jsxs87("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
|
|
12818
|
+
/* @__PURE__ */ jsxs87("header", { className: "fdc-packet-head", children: [
|
|
12819
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
|
|
12820
|
+
/* @__PURE__ */ jsx100("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
|
|
12821
|
+
packet.repaired ? /* @__PURE__ */ jsx100("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
|
|
12822
|
+
invalid ? /* @__PURE__ */ jsx100("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
|
|
12744
12823
|
] }),
|
|
12745
|
-
invalid ? /* @__PURE__ */
|
|
12746
|
-
/* @__PURE__ */
|
|
12747
|
-
/* @__PURE__ */
|
|
12748
|
-
] }) : /* @__PURE__ */
|
|
12749
|
-
!invalid && onApply ? /* @__PURE__ */
|
|
12750
|
-
packet.repaired ? /* @__PURE__ */
|
|
12751
|
-
/* @__PURE__ */
|
|
12752
|
-
/* @__PURE__ */
|
|
12824
|
+
invalid ? /* @__PURE__ */ jsxs87("div", { className: "fdc-packet-alert", role: "alert", children: [
|
|
12825
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
12826
|
+
/* @__PURE__ */ jsx100("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
|
|
12827
|
+
] }) : /* @__PURE__ */ jsx100("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx100(JsonView, { value: packet.payload }) }),
|
|
12828
|
+
!invalid && onApply && s.apply !== false ? /* @__PURE__ */ jsxs87("footer", { className: "fdc-packet-foot", children: [
|
|
12829
|
+
packet.repaired ? /* @__PURE__ */ jsx100("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx100("span", {}),
|
|
12830
|
+
/* @__PURE__ */ jsxs87("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
|
|
12831
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
|
|
12753
12832
|
applied ? "Applied" : s.applyLabel || "Apply"
|
|
12754
12833
|
] })
|
|
12755
12834
|
] }) : null
|
|
12756
12835
|
] });
|
|
12757
12836
|
}
|
|
12758
12837
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
12759
|
-
const [open2, setOpen] =
|
|
12838
|
+
const [open2, setOpen] = React71.useState(defaultOpen);
|
|
12760
12839
|
if (!text) return null;
|
|
12761
|
-
return /* @__PURE__ */
|
|
12762
|
-
/* @__PURE__ */
|
|
12763
|
-
/* @__PURE__ */
|
|
12764
|
-
/* @__PURE__ */
|
|
12765
|
-
streaming ? /* @__PURE__ */
|
|
12766
|
-
/* @__PURE__ */
|
|
12767
|
-
/* @__PURE__ */
|
|
12768
|
-
/* @__PURE__ */
|
|
12840
|
+
return /* @__PURE__ */ jsxs87("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
|
|
12841
|
+
/* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
12842
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-brain", "aria-hidden": "true" }),
|
|
12843
|
+
/* @__PURE__ */ jsx100("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
|
|
12844
|
+
streaming ? /* @__PURE__ */ jsxs87("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
12845
|
+
/* @__PURE__ */ jsx100("span", {}),
|
|
12846
|
+
/* @__PURE__ */ jsx100("span", {}),
|
|
12847
|
+
/* @__PURE__ */ jsx100("span", {})
|
|
12769
12848
|
] }) : null,
|
|
12770
|
-
/* @__PURE__ */
|
|
12849
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
|
|
12771
12850
|
] }),
|
|
12772
|
-
open2 ? /* @__PURE__ */
|
|
12851
|
+
open2 ? /* @__PURE__ */ jsx100("div", { className: "fdc-think-body", children: text }) : null
|
|
12773
12852
|
] });
|
|
12774
12853
|
}
|
|
12775
12854
|
function Citations({ items = [], onOpen }) {
|
|
12776
|
-
const [open2, setOpen] =
|
|
12855
|
+
const [open2, setOpen] = React71.useState(false);
|
|
12777
12856
|
if (!items.length) return null;
|
|
12778
|
-
return /* @__PURE__ */
|
|
12779
|
-
/* @__PURE__ */
|
|
12780
|
-
/* @__PURE__ */
|
|
12781
|
-
/* @__PURE__ */
|
|
12857
|
+
return /* @__PURE__ */ jsxs87("div", { className: "fdc-cites", children: [
|
|
12858
|
+
/* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
12859
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
|
|
12860
|
+
/* @__PURE__ */ jsxs87("span", { children: [
|
|
12782
12861
|
items.length,
|
|
12783
12862
|
" source",
|
|
12784
12863
|
items.length === 1 ? "" : "s"
|
|
12785
12864
|
] }),
|
|
12786
|
-
/* @__PURE__ */
|
|
12865
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
|
|
12787
12866
|
] }),
|
|
12788
|
-
open2 ? /* @__PURE__ */
|
|
12789
|
-
/* @__PURE__ */
|
|
12790
|
-
c.url ? /* @__PURE__ */
|
|
12791
|
-
c.detail ? /* @__PURE__ */
|
|
12867
|
+
open2 ? /* @__PURE__ */ jsx100("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs87("li", { children: [
|
|
12868
|
+
/* @__PURE__ */ jsx100("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
|
|
12869
|
+
c.url ? /* @__PURE__ */ jsx100("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx100("span", { children: c.title || "Source" }),
|
|
12870
|
+
c.detail ? /* @__PURE__ */ jsx100("span", { className: "fdc-cite-detail", children: c.detail }) : null
|
|
12792
12871
|
] }, c.id || i)) }) : null
|
|
12793
12872
|
] });
|
|
12794
12873
|
}
|
|
@@ -12799,29 +12878,29 @@ function clampText(text, max) {
|
|
|
12799
12878
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
12800
12879
|
}
|
|
12801
12880
|
function MessageBody({ message: m, ctx }) {
|
|
12802
|
-
const [expanded, setExpanded] =
|
|
12881
|
+
const [expanded, setExpanded] = React71.useState(false);
|
|
12803
12882
|
const isUser = m.role === "user";
|
|
12804
12883
|
const raw = m.text || "";
|
|
12805
12884
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
12806
12885
|
const body = clamped != null ? clamped : raw;
|
|
12807
12886
|
const showMd = ctx.markdown && !isUser;
|
|
12808
|
-
return /* @__PURE__ */
|
|
12809
|
-
m.thinking && ctx.showThinking ? /* @__PURE__ */
|
|
12810
|
-
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */
|
|
12811
|
-
body ? /* @__PURE__ */
|
|
12812
|
-
showMd ? /* @__PURE__ */
|
|
12813
|
-
m.streaming ? /* @__PURE__ */
|
|
12887
|
+
return /* @__PURE__ */ jsxs87("div", { className: "fdc-body", children: [
|
|
12888
|
+
m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx100(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
|
|
12889
|
+
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx100(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
|
|
12890
|
+
body ? /* @__PURE__ */ jsxs87("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
|
|
12891
|
+
showMd ? /* @__PURE__ */ jsx100(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx100("div", { className: "fdc-plain", children: body }),
|
|
12892
|
+
m.streaming ? /* @__PURE__ */ jsx100("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
|
|
12814
12893
|
] }) : null,
|
|
12815
|
-
clamped != null ? /* @__PURE__ */
|
|
12816
|
-
/* @__PURE__ */
|
|
12894
|
+
clamped != null ? /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
|
|
12895
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
|
|
12817
12896
|
"Show more",
|
|
12818
|
-
/* @__PURE__ */
|
|
12819
|
-
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */
|
|
12820
|
-
/* @__PURE__ */
|
|
12897
|
+
/* @__PURE__ */ jsx100("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
|
|
12898
|
+
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
|
|
12899
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
|
|
12821
12900
|
"Show less"
|
|
12822
12901
|
] }) : null,
|
|
12823
|
-
m.attachments && m.attachments.length ? /* @__PURE__ */
|
|
12824
|
-
m.packet ? /* @__PURE__ */
|
|
12902
|
+
m.attachments && m.attachments.length ? /* @__PURE__ */ jsx100(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
|
|
12903
|
+
m.packet ? /* @__PURE__ */ jsx100(
|
|
12825
12904
|
PacketCard,
|
|
12826
12905
|
{
|
|
12827
12906
|
packet: m.packet,
|
|
@@ -12831,35 +12910,35 @@ function MessageBody({ message: m, ctx }) {
|
|
|
12831
12910
|
applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
|
|
12832
12911
|
}
|
|
12833
12912
|
) : null,
|
|
12834
|
-
m.citations && m.citations.length ? /* @__PURE__ */
|
|
12835
|
-
m.working ? /* @__PURE__ */
|
|
12836
|
-
/* @__PURE__ */
|
|
12837
|
-
/* @__PURE__ */
|
|
12838
|
-
/* @__PURE__ */
|
|
12839
|
-
/* @__PURE__ */
|
|
12913
|
+
m.citations && m.citations.length ? /* @__PURE__ */ jsx100(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
|
|
12914
|
+
m.working ? /* @__PURE__ */ jsxs87("div", { className: "fdc-working", role: "status", children: [
|
|
12915
|
+
/* @__PURE__ */ jsxs87("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
12916
|
+
/* @__PURE__ */ jsx100("span", {}),
|
|
12917
|
+
/* @__PURE__ */ jsx100("span", {}),
|
|
12918
|
+
/* @__PURE__ */ jsx100("span", {})
|
|
12840
12919
|
] }),
|
|
12841
|
-
/* @__PURE__ */
|
|
12920
|
+
/* @__PURE__ */ jsxs87("span", { className: "fdc-working-label", children: [
|
|
12842
12921
|
m.resumed ? "Resuming" : "Working",
|
|
12843
|
-
m.job && m.job.status ? /* @__PURE__ */
|
|
12922
|
+
m.job && m.job.status ? /* @__PURE__ */ jsxs87("span", { className: "fdc-working-job", children: [
|
|
12844
12923
|
" \xB7 ",
|
|
12845
12924
|
m.job.status
|
|
12846
12925
|
] }) : null,
|
|
12847
|
-
m.job && m.job.detail ? /* @__PURE__ */
|
|
12926
|
+
m.job && m.job.detail ? /* @__PURE__ */ jsxs87("span", { className: "fdc-working-job", children: [
|
|
12848
12927
|
" \xB7 ",
|
|
12849
12928
|
m.job.detail
|
|
12850
12929
|
] }) : null
|
|
12851
12930
|
] }),
|
|
12852
|
-
m.jobId ? /* @__PURE__ */
|
|
12931
|
+
m.jobId ? /* @__PURE__ */ jsx100("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
|
|
12853
12932
|
] }) : null,
|
|
12854
|
-
m.stopped ? /* @__PURE__ */
|
|
12855
|
-
/* @__PURE__ */
|
|
12933
|
+
m.stopped ? /* @__PURE__ */ jsxs87("div", { className: "fdc-stopped", children: [
|
|
12934
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
12856
12935
|
"Stopped"
|
|
12857
12936
|
] }) : null,
|
|
12858
|
-
m.error ? /* @__PURE__ */
|
|
12859
|
-
/* @__PURE__ */
|
|
12860
|
-
/* @__PURE__ */
|
|
12861
|
-
m.retryable && ctx.onRetry ? /* @__PURE__ */
|
|
12862
|
-
/* @__PURE__ */
|
|
12937
|
+
m.error ? /* @__PURE__ */ jsxs87("div", { className: "fdc-error", role: "alert", children: [
|
|
12938
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
12939
|
+
/* @__PURE__ */ jsx100("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
|
|
12940
|
+
m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
|
|
12941
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
12863
12942
|
"Retry"
|
|
12864
12943
|
] }) : null
|
|
12865
12944
|
] }) : null
|
|
@@ -12872,16 +12951,16 @@ function RunActions({ group, ctx }) {
|
|
|
12872
12951
|
const isAssistant = group.role === "assistant";
|
|
12873
12952
|
const fb = last.feedback;
|
|
12874
12953
|
if (!ctx.messageActions) return null;
|
|
12875
|
-
return /* @__PURE__ */
|
|
12876
|
-
/* @__PURE__ */
|
|
12877
|
-
/* @__PURE__ */
|
|
12878
|
-
/* @__PURE__ */
|
|
12954
|
+
return /* @__PURE__ */ jsxs87("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
|
|
12955
|
+
/* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
|
|
12956
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
|
|
12957
|
+
/* @__PURE__ */ jsx100("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
|
|
12879
12958
|
] }),
|
|
12880
|
-
isAssistant && ctx.onRetry ? /* @__PURE__ */
|
|
12881
|
-
group.role === "user" && ctx.onEdit ? /* @__PURE__ */
|
|
12882
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */
|
|
12883
|
-
/* @__PURE__ */
|
|
12884
|
-
/* @__PURE__ */
|
|
12959
|
+
isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx100("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx100("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
12960
|
+
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx100("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx100("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
12961
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs87(React71.Fragment, { children: [
|
|
12962
|
+
/* @__PURE__ */ jsx100("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__ */ jsx100("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
12963
|
+
/* @__PURE__ */ jsx100("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__ */ jsx100("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
12885
12964
|
] }) : null,
|
|
12886
12965
|
ctx.extraActions ? ctx.extraActions(group) : null
|
|
12887
12966
|
] });
|
|
@@ -12891,22 +12970,22 @@ function ChatTurn({ group, ctx }) {
|
|
|
12891
12970
|
const name = isUser ? ctx.userName : group.author || ctx.assistantName;
|
|
12892
12971
|
const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
|
|
12893
12972
|
const stamp = group.messages[0].timestamp;
|
|
12894
|
-
return /* @__PURE__ */
|
|
12895
|
-
/* @__PURE__ */
|
|
12896
|
-
ctx.showAvatars ? /* @__PURE__ */
|
|
12897
|
-
/* @__PURE__ */
|
|
12898
|
-
stamp ? /* @__PURE__ */
|
|
12899
|
-
group.messages.some((m) => m.model) ? /* @__PURE__ */
|
|
12973
|
+
return /* @__PURE__ */ jsxs87("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
|
|
12974
|
+
/* @__PURE__ */ jsxs87("div", { className: "fdc-turn-head", children: [
|
|
12975
|
+
ctx.showAvatars ? /* @__PURE__ */ jsx100("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx100("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx100("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx100("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
|
|
12976
|
+
/* @__PURE__ */ jsx100("span", { className: "fdc-who", children: name }),
|
|
12977
|
+
stamp ? /* @__PURE__ */ jsx100(RelativeTime, { className: "fdc-when", value: stamp }) : null,
|
|
12978
|
+
group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx100("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
|
|
12900
12979
|
] }),
|
|
12901
|
-
/* @__PURE__ */
|
|
12902
|
-
group.messages.map((m) => /* @__PURE__ */
|
|
12903
|
-
/* @__PURE__ */
|
|
12980
|
+
/* @__PURE__ */ jsxs87("div", { className: "fdc-turn-body", children: [
|
|
12981
|
+
group.messages.map((m) => /* @__PURE__ */ jsx100("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx100(MessageBody, { message: m, ctx }) }, m.id)),
|
|
12982
|
+
/* @__PURE__ */ jsx100(RunActions, { group, ctx })
|
|
12904
12983
|
] })
|
|
12905
12984
|
] });
|
|
12906
12985
|
}
|
|
12907
12986
|
|
|
12908
12987
|
// src/components/chat/ChatTranscript.tsx
|
|
12909
|
-
import { jsx as
|
|
12988
|
+
import { jsx as jsx101, jsxs as jsxs88 } from "react/jsx-runtime";
|
|
12910
12989
|
var GROUP_WINDOW = 6e4;
|
|
12911
12990
|
var STICK_PX = 100;
|
|
12912
12991
|
function groupMessages(list) {
|
|
@@ -12939,25 +13018,25 @@ function dayLabel(key) {
|
|
|
12939
13018
|
}
|
|
12940
13019
|
function Suggestions({ items = [], onPick }) {
|
|
12941
13020
|
if (!items.length) return null;
|
|
12942
|
-
return /* @__PURE__ */
|
|
13021
|
+
return /* @__PURE__ */ jsx101("div", { className: "fdc-suggest", children: items.map((s, i) => {
|
|
12943
13022
|
const it = typeof s === "string" ? { label: s, text: s } : s;
|
|
12944
|
-
return /* @__PURE__ */
|
|
12945
|
-
it.icon ? /* @__PURE__ */
|
|
12946
|
-
/* @__PURE__ */
|
|
12947
|
-
/* @__PURE__ */
|
|
12948
|
-
it.description ? /* @__PURE__ */
|
|
13023
|
+
return /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
|
|
13024
|
+
it.icon ? /* @__PURE__ */ jsx101("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
|
|
13025
|
+
/* @__PURE__ */ jsxs88("span", { className: "fdc-suggest-text", children: [
|
|
13026
|
+
/* @__PURE__ */ jsx101("span", { className: "fdc-suggest-label", children: it.label }),
|
|
13027
|
+
it.description ? /* @__PURE__ */ jsx101("span", { className: "fdc-suggest-desc", children: it.description }) : null
|
|
12949
13028
|
] }),
|
|
12950
|
-
/* @__PURE__ */
|
|
13029
|
+
/* @__PURE__ */ jsx101("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
|
|
12951
13030
|
] }, it.id || i);
|
|
12952
13031
|
}) });
|
|
12953
13032
|
}
|
|
12954
13033
|
function LoadingTurns() {
|
|
12955
|
-
return /* @__PURE__ */
|
|
12956
|
-
/* @__PURE__ */
|
|
12957
|
-
/* @__PURE__ */
|
|
12958
|
-
/* @__PURE__ */
|
|
12959
|
-
/* @__PURE__ */
|
|
12960
|
-
/* @__PURE__ */
|
|
13034
|
+
return /* @__PURE__ */ jsx101("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs88("div", { className: "fdc-skel-turn", children: [
|
|
13035
|
+
/* @__PURE__ */ jsx101("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
|
|
13036
|
+
/* @__PURE__ */ jsxs88("div", { className: "fdc-skel-lines", children: [
|
|
13037
|
+
/* @__PURE__ */ jsx101("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
|
|
13038
|
+
/* @__PURE__ */ jsx101("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
|
|
13039
|
+
/* @__PURE__ */ jsx101("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
|
|
12961
13040
|
] })
|
|
12962
13041
|
] }, i)) });
|
|
12963
13042
|
}
|
|
@@ -12974,10 +13053,10 @@ function ChatTranscript({
|
|
|
12974
13053
|
renderEmpty,
|
|
12975
13054
|
className = ""
|
|
12976
13055
|
}) {
|
|
12977
|
-
const scroller =
|
|
12978
|
-
const stick =
|
|
12979
|
-
const [pill, setPill] =
|
|
12980
|
-
const seen =
|
|
13056
|
+
const scroller = React72.useRef(null);
|
|
13057
|
+
const stick = React72.useRef(true);
|
|
13058
|
+
const [pill, setPill] = React72.useState(0);
|
|
13059
|
+
const seen = React72.useRef(0);
|
|
12981
13060
|
const toBottom = (smooth) => {
|
|
12982
13061
|
const el = scroller.current;
|
|
12983
13062
|
if (!el) return;
|
|
@@ -12996,7 +13075,7 @@ function ChatTranscript({
|
|
|
12996
13075
|
seen.current = messages.length;
|
|
12997
13076
|
}
|
|
12998
13077
|
};
|
|
12999
|
-
|
|
13078
|
+
React72.useLayoutEffect(() => {
|
|
13000
13079
|
const el = scroller.current;
|
|
13001
13080
|
if (!el) return;
|
|
13002
13081
|
if (stick.current) {
|
|
@@ -13004,7 +13083,7 @@ function ChatTranscript({
|
|
|
13004
13083
|
seen.current = messages.length;
|
|
13005
13084
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
13006
13085
|
}, [messages]);
|
|
13007
|
-
|
|
13086
|
+
React72.useEffect(() => {
|
|
13008
13087
|
const el = scroller.current;
|
|
13009
13088
|
const inner = el && el.firstChild;
|
|
13010
13089
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -13014,38 +13093,38 @@ function ChatTranscript({
|
|
|
13014
13093
|
ro.observe(inner);
|
|
13015
13094
|
return () => ro.disconnect();
|
|
13016
13095
|
}, []);
|
|
13017
|
-
const groups =
|
|
13096
|
+
const groups = React72.useMemo(() => groupMessages(messages), [messages]);
|
|
13018
13097
|
const empty = !messages.length && status === "ready";
|
|
13019
|
-
return /* @__PURE__ */
|
|
13020
|
-
/* @__PURE__ */
|
|
13021
|
-
status === "loading" || status === "resolving" ? /* @__PURE__ */
|
|
13022
|
-
status === "disconnected" ? /* @__PURE__ */
|
|
13023
|
-
/* @__PURE__ */
|
|
13024
|
-
/* @__PURE__ */
|
|
13025
|
-
/* @__PURE__ */
|
|
13026
|
-
ctx.onReconnect ? /* @__PURE__ */
|
|
13027
|
-
/* @__PURE__ */
|
|
13098
|
+
return /* @__PURE__ */ jsxs88("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
13099
|
+
/* @__PURE__ */ jsxs88("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
13100
|
+
status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx101(LoadingTurns, {}) : null,
|
|
13101
|
+
status === "disconnected" ? /* @__PURE__ */ jsxs88("div", { className: "fdc-dead", children: [
|
|
13102
|
+
/* @__PURE__ */ jsx101("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx101("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
|
|
13103
|
+
/* @__PURE__ */ jsx101("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
|
|
13104
|
+
/* @__PURE__ */ jsx101("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." }),
|
|
13105
|
+
ctx.onReconnect ? /* @__PURE__ */ jsxs88("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
|
|
13106
|
+
/* @__PURE__ */ jsx101("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
13028
13107
|
"Try again"
|
|
13029
13108
|
] }) : null
|
|
13030
13109
|
] }) : null,
|
|
13031
|
-
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */
|
|
13032
|
-
/* @__PURE__ */
|
|
13033
|
-
/* @__PURE__ */
|
|
13034
|
-
emptyDescription ? /* @__PURE__ */
|
|
13035
|
-
/* @__PURE__ */
|
|
13110
|
+
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs88("div", { className: "fdc-empty", children: [
|
|
13111
|
+
/* @__PURE__ */ jsx101("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx101("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
|
|
13112
|
+
/* @__PURE__ */ jsx101("h3", { className: "fdc-empty-title", children: emptyTitle }),
|
|
13113
|
+
emptyDescription ? /* @__PURE__ */ jsx101("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
|
|
13114
|
+
/* @__PURE__ */ jsx101(Suggestions, { items: suggestions, onPick })
|
|
13036
13115
|
] }) : null,
|
|
13037
13116
|
groups.map((g, i) => {
|
|
13038
13117
|
const prev = groups[i - 1];
|
|
13039
13118
|
const k = dayKey(g.messages[0].timestamp);
|
|
13040
13119
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
13041
|
-
return /* @__PURE__ */
|
|
13042
|
-
showDay ? /* @__PURE__ */
|
|
13043
|
-
/* @__PURE__ */
|
|
13120
|
+
return /* @__PURE__ */ jsxs88(React72.Fragment, { children: [
|
|
13121
|
+
showDay ? /* @__PURE__ */ jsx101("div", { className: "fdc-day", children: /* @__PURE__ */ jsx101("span", { children: dayLabel(k) }) }) : null,
|
|
13122
|
+
/* @__PURE__ */ jsx101(ChatTurn, { group: g, ctx })
|
|
13044
13123
|
] }, g.key || i);
|
|
13045
13124
|
})
|
|
13046
13125
|
] }),
|
|
13047
|
-
pill ? /* @__PURE__ */
|
|
13048
|
-
/* @__PURE__ */
|
|
13126
|
+
pill ? /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
|
|
13127
|
+
/* @__PURE__ */ jsx101("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
|
|
13049
13128
|
pill,
|
|
13050
13129
|
" new message",
|
|
13051
13130
|
pill === 1 ? "" : "s"
|
|
@@ -13055,8 +13134,8 @@ function ChatTranscript({
|
|
|
13055
13134
|
var TranscriptKit = { groupMessages };
|
|
13056
13135
|
|
|
13057
13136
|
// src/components/chat/ChatComposer.tsx
|
|
13058
|
-
import * as
|
|
13059
|
-
import { jsx as
|
|
13137
|
+
import * as React73 from "react";
|
|
13138
|
+
import { jsx as jsx102, jsxs as jsxs89 } from "react/jsx-runtime";
|
|
13060
13139
|
function ChatComposer({
|
|
13061
13140
|
onSubmit,
|
|
13062
13141
|
onStop,
|
|
@@ -13083,17 +13162,17 @@ function ChatComposer({
|
|
|
13083
13162
|
onReject,
|
|
13084
13163
|
onOpenAttachment
|
|
13085
13164
|
}) {
|
|
13086
|
-
const [text, setText] =
|
|
13087
|
-
const [trigger, setTrigger] =
|
|
13088
|
-
const [mentionItems, setMentionItems] =
|
|
13089
|
-
const [listening, setListening] =
|
|
13090
|
-
const [notice, setNotice] =
|
|
13091
|
-
const editor =
|
|
13092
|
-
const wrap =
|
|
13093
|
-
const stopVoice =
|
|
13165
|
+
const [text, setText] = React73.useState(draft || "");
|
|
13166
|
+
const [trigger, setTrigger] = React73.useState(null);
|
|
13167
|
+
const [mentionItems, setMentionItems] = React73.useState([]);
|
|
13168
|
+
const [listening, setListening] = React73.useState(false);
|
|
13169
|
+
const [notice, setNotice] = React73.useState(null);
|
|
13170
|
+
const editor = React73.useRef(null);
|
|
13171
|
+
const wrap = React73.useRef(null);
|
|
13172
|
+
const stopVoice = React73.useRef(null);
|
|
13094
13173
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
13095
13174
|
} });
|
|
13096
|
-
|
|
13175
|
+
React73.useEffect(() => {
|
|
13097
13176
|
if (draft != null && draft !== text) setText(draft);
|
|
13098
13177
|
}, [draft]);
|
|
13099
13178
|
const change = (v) => {
|
|
@@ -13129,7 +13208,7 @@ function ChatComposer({
|
|
|
13129
13208
|
e.preventDefault();
|
|
13130
13209
|
staged.add(found.files);
|
|
13131
13210
|
};
|
|
13132
|
-
|
|
13211
|
+
React73.useEffect(() => {
|
|
13133
13212
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
13134
13213
|
setMentionItems([]);
|
|
13135
13214
|
return;
|
|
@@ -13147,7 +13226,7 @@ function ChatComposer({
|
|
|
13147
13226
|
const q = (trigger.query || "").toLowerCase();
|
|
13148
13227
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
13149
13228
|
}, [trigger, mentionSources]);
|
|
13150
|
-
const slashItems =
|
|
13229
|
+
const slashItems = React73.useMemo(() => {
|
|
13151
13230
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
13152
13231
|
const q = (trigger.query || "").toLowerCase();
|
|
13153
13232
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -13161,7 +13240,7 @@ function ChatComposer({
|
|
|
13161
13240
|
description: it.description,
|
|
13162
13241
|
icon: it.icon,
|
|
13163
13242
|
meta: mention.meta,
|
|
13164
|
-
shortcut: slash.shortcut ? /* @__PURE__ */
|
|
13243
|
+
shortcut: slash.shortcut ? /* @__PURE__ */ jsx102(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
|
|
13165
13244
|
onSelect: () => {
|
|
13166
13245
|
const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
|
|
13167
13246
|
editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
|
|
@@ -13220,14 +13299,14 @@ function ChatComposer({
|
|
|
13220
13299
|
stopVoice.current = typeof res === "function" ? res : () => {
|
|
13221
13300
|
};
|
|
13222
13301
|
};
|
|
13223
|
-
return /* @__PURE__ */
|
|
13224
|
-
queue.length ? /* @__PURE__ */
|
|
13225
|
-
/* @__PURE__ */
|
|
13226
|
-
/* @__PURE__ */
|
|
13227
|
-
onRemoveQueued ? /* @__PURE__ */
|
|
13302
|
+
return /* @__PURE__ */ jsxs89("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
|
|
13303
|
+
queue.length ? /* @__PURE__ */ jsx102("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs89("div", { className: "fdc-queue-row", children: [
|
|
13304
|
+
/* @__PURE__ */ jsx102("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
|
|
13305
|
+
/* @__PURE__ */ jsx102("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)" : "") }),
|
|
13306
|
+
onRemoveQueued ? /* @__PURE__ */ jsx102("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx102("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
13228
13307
|
] }, q.id)) }) : null,
|
|
13229
13308
|
sessionBar,
|
|
13230
|
-
/* @__PURE__ */
|
|
13309
|
+
/* @__PURE__ */ jsx102(
|
|
13231
13310
|
Dropzone,
|
|
13232
13311
|
{
|
|
13233
13312
|
className: "fdc-field",
|
|
@@ -13241,9 +13320,9 @@ function ChatComposer({
|
|
|
13241
13320
|
disabled: !fileUploadHandler || disabled,
|
|
13242
13321
|
label: "Drop to attach",
|
|
13243
13322
|
hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
|
|
13244
|
-
children: /* @__PURE__ */
|
|
13245
|
-
staged.items.length ? /* @__PURE__ */
|
|
13246
|
-
/* @__PURE__ */
|
|
13323
|
+
children: /* @__PURE__ */ jsxs89("div", { ref: wrap, className: "fdc-field-inner", children: [
|
|
13324
|
+
staged.items.length ? /* @__PURE__ */ jsx102("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx102(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
|
|
13325
|
+
/* @__PURE__ */ jsx102(
|
|
13247
13326
|
MarkdownEditor,
|
|
13248
13327
|
{
|
|
13249
13328
|
ref: editor,
|
|
@@ -13262,33 +13341,33 @@ function ChatComposer({
|
|
|
13262
13341
|
ariaLabel: "Message"
|
|
13263
13342
|
}
|
|
13264
13343
|
),
|
|
13265
|
-
/* @__PURE__ */
|
|
13266
|
-
fileUploadHandler ? /* @__PURE__ */
|
|
13267
|
-
voiceHandler ? /* @__PURE__ */
|
|
13344
|
+
/* @__PURE__ */ jsxs89("div", { className: "fdc-tools", children: [
|
|
13345
|
+
fileUploadHandler ? /* @__PURE__ */ jsx102(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
|
|
13346
|
+
voiceHandler ? /* @__PURE__ */ jsx102("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx102("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
|
|
13268
13347
|
toolbarExtras,
|
|
13269
|
-
/* @__PURE__ */
|
|
13270
|
-
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */
|
|
13348
|
+
/* @__PURE__ */ jsx102("span", { className: "fdc-tools-gap" }),
|
|
13349
|
+
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs89("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
|
|
13271
13350
|
text.length,
|
|
13272
13351
|
"/",
|
|
13273
13352
|
maxLength
|
|
13274
13353
|
] }) : null,
|
|
13275
|
-
busy ? /* @__PURE__ */
|
|
13276
|
-
/* @__PURE__ */
|
|
13277
|
-
/* @__PURE__ */
|
|
13278
|
-
] }) : /* @__PURE__ */
|
|
13279
|
-
/* @__PURE__ */
|
|
13280
|
-
/* @__PURE__ */
|
|
13354
|
+
busy ? /* @__PURE__ */ jsxs89("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
|
|
13355
|
+
/* @__PURE__ */ jsx102("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
13356
|
+
/* @__PURE__ */ jsx102("span", { children: "Stop" })
|
|
13357
|
+
] }) : /* @__PURE__ */ jsxs89("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
|
|
13358
|
+
/* @__PURE__ */ jsx102("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
|
|
13359
|
+
/* @__PURE__ */ jsx102("span", { className: "fdc-send-label", children: "Send" })
|
|
13281
13360
|
] })
|
|
13282
13361
|
] })
|
|
13283
13362
|
] })
|
|
13284
13363
|
}
|
|
13285
13364
|
),
|
|
13286
|
-
notice ? /* @__PURE__ */
|
|
13287
|
-
/* @__PURE__ */
|
|
13365
|
+
notice ? /* @__PURE__ */ jsxs89("div", { className: "fdc-notice", role: "status", children: [
|
|
13366
|
+
/* @__PURE__ */ jsx102("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
13288
13367
|
notice
|
|
13289
13368
|
] }) : null,
|
|
13290
|
-
hint && !notice ? /* @__PURE__ */
|
|
13291
|
-
/* @__PURE__ */
|
|
13369
|
+
hint && !notice ? /* @__PURE__ */ jsx102("div", { className: "fdc-hint", children: hint }) : null,
|
|
13370
|
+
/* @__PURE__ */ jsx102(
|
|
13292
13371
|
Popover,
|
|
13293
13372
|
{
|
|
13294
13373
|
open: menuOpen,
|
|
@@ -13302,12 +13381,12 @@ function ChatComposer({
|
|
|
13302
13381
|
returnFocus: false,
|
|
13303
13382
|
closeOnOutside: true,
|
|
13304
13383
|
label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
|
|
13305
|
-
children: /* @__PURE__ */
|
|
13384
|
+
children: /* @__PURE__ */ jsx102(
|
|
13306
13385
|
Menu,
|
|
13307
13386
|
{
|
|
13308
13387
|
items: menuItems,
|
|
13309
13388
|
autoFocus: false,
|
|
13310
|
-
header: /* @__PURE__ */
|
|
13389
|
+
header: /* @__PURE__ */ jsx102("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
|
|
13311
13390
|
onClose: () => setTrigger(null)
|
|
13312
13391
|
}
|
|
13313
13392
|
)
|
|
@@ -13317,12 +13396,12 @@ function ChatComposer({
|
|
|
13317
13396
|
}
|
|
13318
13397
|
|
|
13319
13398
|
// src/components/chat/ChatSessionBar.tsx
|
|
13320
|
-
import * as
|
|
13321
|
-
import { jsx as
|
|
13399
|
+
import * as React74 from "react";
|
|
13400
|
+
import { jsx as jsx103, jsxs as jsxs90 } from "react/jsx-runtime";
|
|
13322
13401
|
var compact2 = meterFormats.compact;
|
|
13323
13402
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
13324
|
-
const [open2, setOpen] =
|
|
13325
|
-
const anchor =
|
|
13403
|
+
const [open2, setOpen] = React74.useState(false);
|
|
13404
|
+
const anchor = React74.useRef(null);
|
|
13326
13405
|
const stats = sessionStats || null;
|
|
13327
13406
|
const cu = contextUsage || null;
|
|
13328
13407
|
const limits = usageLimits || null;
|
|
@@ -13337,9 +13416,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
13337
13416
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
13338
13417
|
if (cu) bits.push(pct + "% context");
|
|
13339
13418
|
const expandable = !!(cu || limits);
|
|
13340
|
-
return /* @__PURE__ */
|
|
13341
|
-
/* @__PURE__ */
|
|
13342
|
-
/* @__PURE__ */
|
|
13419
|
+
return /* @__PURE__ */ jsxs90(React74.Fragment, { children: [
|
|
13420
|
+
/* @__PURE__ */ jsxs90("div", { className: "fdc-bar", children: [
|
|
13421
|
+
/* @__PURE__ */ jsxs90(
|
|
13343
13422
|
"button",
|
|
13344
13423
|
{
|
|
13345
13424
|
type: "button",
|
|
@@ -13350,15 +13429,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
13350
13429
|
"aria-expanded": expandable ? open2 : void 0,
|
|
13351
13430
|
"aria-label": expandable ? "Usage details" : void 0,
|
|
13352
13431
|
children: [
|
|
13353
|
-
cu ? /* @__PURE__ */
|
|
13354
|
-
/* @__PURE__ */
|
|
13355
|
-
expandable ? /* @__PURE__ */
|
|
13432
|
+
cu ? /* @__PURE__ */ jsx103("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx103(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
|
|
13433
|
+
/* @__PURE__ */ jsx103("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
|
|
13434
|
+
expandable ? /* @__PURE__ */ jsx103("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
|
|
13356
13435
|
]
|
|
13357
13436
|
}
|
|
13358
13437
|
),
|
|
13359
13438
|
extras
|
|
13360
13439
|
] }),
|
|
13361
|
-
/* @__PURE__ */
|
|
13440
|
+
/* @__PURE__ */ jsx103(
|
|
13362
13441
|
Popover,
|
|
13363
13442
|
{
|
|
13364
13443
|
open: open2,
|
|
@@ -13369,15 +13448,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
13369
13448
|
maxHeight: 460,
|
|
13370
13449
|
padded: true,
|
|
13371
13450
|
label: "Usage",
|
|
13372
|
-
footer: onClear ? /* @__PURE__ */
|
|
13451
|
+
footer: onClear ? /* @__PURE__ */ jsxs90("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
|
|
13373
13452
|
setOpen(false);
|
|
13374
13453
|
onClear();
|
|
13375
13454
|
}, children: [
|
|
13376
|
-
/* @__PURE__ */
|
|
13455
|
+
/* @__PURE__ */ jsx103("i", { className: "ph ph-trash", "aria-hidden": "true" }),
|
|
13377
13456
|
"Clear conversation"
|
|
13378
13457
|
] }) : void 0,
|
|
13379
|
-
children: /* @__PURE__ */
|
|
13380
|
-
cu ? /* @__PURE__ */
|
|
13458
|
+
children: /* @__PURE__ */ jsxs90("div", { className: "fdc-usage", children: [
|
|
13459
|
+
cu ? /* @__PURE__ */ jsx103("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx103(
|
|
13381
13460
|
SegmentedMeter,
|
|
13382
13461
|
{
|
|
13383
13462
|
total,
|
|
@@ -13389,9 +13468,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
13389
13468
|
remainderLabel: "Free"
|
|
13390
13469
|
}
|
|
13391
13470
|
) }) : null,
|
|
13392
|
-
limits && limits.length ? /* @__PURE__ */
|
|
13393
|
-
/* @__PURE__ */
|
|
13394
|
-
/* @__PURE__ */
|
|
13471
|
+
limits && limits.length ? /* @__PURE__ */ jsxs90("section", { className: "fdc-usage-sec", children: [
|
|
13472
|
+
/* @__PURE__ */ jsx103("h4", { className: "fdc-usage-h", children: "Usage limits" }),
|
|
13473
|
+
/* @__PURE__ */ jsx103("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx103(
|
|
13395
13474
|
QuotaRow,
|
|
13396
13475
|
{
|
|
13397
13476
|
label: l.label,
|
|
@@ -13401,25 +13480,25 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
13401
13480
|
l.id
|
|
13402
13481
|
)) })
|
|
13403
13482
|
] }) : null,
|
|
13404
|
-
stats ? /* @__PURE__ */
|
|
13405
|
-
stats.elapsedMs ? /* @__PURE__ */
|
|
13406
|
-
/* @__PURE__ */
|
|
13407
|
-
/* @__PURE__ */
|
|
13483
|
+
stats ? /* @__PURE__ */ jsxs90("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
|
|
13484
|
+
stats.elapsedMs ? /* @__PURE__ */ jsxs90("div", { children: [
|
|
13485
|
+
/* @__PURE__ */ jsx103("span", { children: "Session" }),
|
|
13486
|
+
/* @__PURE__ */ jsx103("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
|
|
13408
13487
|
] }) : null,
|
|
13409
|
-
stats.tokens ? /* @__PURE__ */
|
|
13410
|
-
/* @__PURE__ */
|
|
13411
|
-
/* @__PURE__ */
|
|
13488
|
+
stats.tokens ? /* @__PURE__ */ jsxs90("div", { children: [
|
|
13489
|
+
/* @__PURE__ */ jsx103("span", { children: "Tokens" }),
|
|
13490
|
+
/* @__PURE__ */ jsx103("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
|
|
13412
13491
|
] }) : null,
|
|
13413
|
-
stats.costUsd != null ? /* @__PURE__ */
|
|
13414
|
-
/* @__PURE__ */
|
|
13415
|
-
/* @__PURE__ */
|
|
13492
|
+
stats.costUsd != null ? /* @__PURE__ */ jsxs90("div", { children: [
|
|
13493
|
+
/* @__PURE__ */ jsx103("span", { children: "Cost" }),
|
|
13494
|
+
/* @__PURE__ */ jsxs90("b", { className: "fd-tabular", children: [
|
|
13416
13495
|
"$",
|
|
13417
13496
|
Number(stats.costUsd).toFixed(3)
|
|
13418
13497
|
] })
|
|
13419
13498
|
] }) : null,
|
|
13420
|
-
stats.turns ? /* @__PURE__ */
|
|
13421
|
-
/* @__PURE__ */
|
|
13422
|
-
/* @__PURE__ */
|
|
13499
|
+
stats.turns ? /* @__PURE__ */ jsxs90("div", { children: [
|
|
13500
|
+
/* @__PURE__ */ jsx103("span", { children: "Turns" }),
|
|
13501
|
+
/* @__PURE__ */ jsx103("b", { className: "fd-tabular", children: stats.turns })
|
|
13423
13502
|
] }) : null
|
|
13424
13503
|
] }) : null
|
|
13425
13504
|
] })
|
|
@@ -13458,7 +13537,7 @@ function ModelControls({
|
|
|
13458
13537
|
disabled: m.disabled,
|
|
13459
13538
|
checked: m.id === (current2 && current2.id),
|
|
13460
13539
|
meta: m.meta,
|
|
13461
|
-
shortcut: m.shortcut ? /* @__PURE__ */
|
|
13540
|
+
shortcut: m.shortcut ? /* @__PURE__ */ jsx103(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
|
|
13462
13541
|
onSelect: () => onModelChange && onModelChange(m.id)
|
|
13463
13542
|
});
|
|
13464
13543
|
const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
|
|
@@ -13471,15 +13550,15 @@ function ModelControls({
|
|
|
13471
13550
|
items.push({ kind: "section", label: "Fast mode" });
|
|
13472
13551
|
items.push({
|
|
13473
13552
|
kind: "custom",
|
|
13474
|
-
render: () => /* @__PURE__ */
|
|
13475
|
-
/* @__PURE__ */
|
|
13476
|
-
/* @__PURE__ */
|
|
13477
|
-
/* @__PURE__ */
|
|
13553
|
+
render: () => /* @__PURE__ */ jsxs90("label", { className: "fdc-switchrow", children: [
|
|
13554
|
+
/* @__PURE__ */ jsx103("span", { children: fastModeLabel }),
|
|
13555
|
+
/* @__PURE__ */ jsx103("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
|
|
13556
|
+
/* @__PURE__ */ jsx103("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx103("span", { className: "fd-switch-thumb" }) })
|
|
13478
13557
|
] })
|
|
13479
13558
|
});
|
|
13480
13559
|
}
|
|
13481
|
-
return /* @__PURE__ */
|
|
13482
|
-
/* @__PURE__ */
|
|
13560
|
+
return /* @__PURE__ */ jsxs90(React74.Fragment, { children: [
|
|
13561
|
+
/* @__PURE__ */ jsx103(
|
|
13483
13562
|
MenuButton,
|
|
13484
13563
|
{
|
|
13485
13564
|
items,
|
|
@@ -13490,7 +13569,7 @@ function ModelControls({
|
|
|
13490
13569
|
title: "Choose a model"
|
|
13491
13570
|
}
|
|
13492
13571
|
),
|
|
13493
|
-
effortLevels && effortLevels.length ? /* @__PURE__ */
|
|
13572
|
+
effortLevels && effortLevels.length ? /* @__PURE__ */ jsx103(
|
|
13494
13573
|
MenuButton,
|
|
13495
13574
|
{
|
|
13496
13575
|
placement: "top-end",
|
|
@@ -13511,7 +13590,7 @@ function ModelControls({
|
|
|
13511
13590
|
}
|
|
13512
13591
|
|
|
13513
13592
|
// src/components/chat/AgentChatPanel.tsx
|
|
13514
|
-
import { jsx as
|
|
13593
|
+
import { jsx as jsx104, jsxs as jsxs91 } from "react/jsx-runtime";
|
|
13515
13594
|
var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
|
|
13516
13595
|
function AgentChatPanel({
|
|
13517
13596
|
/* required */
|
|
@@ -13545,6 +13624,7 @@ function AgentChatPanel({
|
|
|
13545
13624
|
packetSchemas,
|
|
13546
13625
|
packetRenderers,
|
|
13547
13626
|
onApplyPacket,
|
|
13627
|
+
pendingTimeoutMs,
|
|
13548
13628
|
onOpenAttachment,
|
|
13549
13629
|
errorCopy,
|
|
13550
13630
|
/* composer */
|
|
@@ -13595,17 +13675,18 @@ function AgentChatPanel({
|
|
|
13595
13675
|
onFeedback,
|
|
13596
13676
|
onEditMessage
|
|
13597
13677
|
}) {
|
|
13598
|
-
const [panelWidth, setPanelWidth] =
|
|
13599
|
-
const [applied, setApplied] =
|
|
13600
|
-
const [draft, setDraft] =
|
|
13601
|
-
const dragging =
|
|
13602
|
-
|
|
13678
|
+
const [panelWidth, setPanelWidth] = React75.useState(width);
|
|
13679
|
+
const [applied, setApplied] = React75.useState({});
|
|
13680
|
+
const [draft, setDraft] = React75.useState("");
|
|
13681
|
+
const dragging = React75.useRef(null);
|
|
13682
|
+
React75.useEffect(() => setPanelWidth(width), [width]);
|
|
13603
13683
|
const engine = useChatEngine({
|
|
13604
13684
|
contextType,
|
|
13605
13685
|
contextId,
|
|
13606
13686
|
apiAdapter,
|
|
13607
13687
|
initialMessage,
|
|
13608
13688
|
threadId,
|
|
13689
|
+
pendingTimeoutMs,
|
|
13609
13690
|
onPacket,
|
|
13610
13691
|
onThreadReady,
|
|
13611
13692
|
onError,
|
|
@@ -13665,7 +13746,7 @@ function AgentChatPanel({
|
|
|
13665
13746
|
onReconnect: engine.reload,
|
|
13666
13747
|
deadTitle: "The assistant isn\u2019t reachable"
|
|
13667
13748
|
};
|
|
13668
|
-
const sessionBar = /* @__PURE__ */
|
|
13749
|
+
const sessionBar = /* @__PURE__ */ jsx104(
|
|
13669
13750
|
ChatSessionBar,
|
|
13670
13751
|
{
|
|
13671
13752
|
sessionStats,
|
|
@@ -13674,7 +13755,7 @@ function AgentChatPanel({
|
|
|
13674
13755
|
onClear: engine.visible.length ? engine.clear : void 0
|
|
13675
13756
|
}
|
|
13676
13757
|
);
|
|
13677
|
-
const modelControls = /* @__PURE__ */
|
|
13758
|
+
const modelControls = /* @__PURE__ */ jsx104(
|
|
13678
13759
|
ModelControls,
|
|
13679
13760
|
{
|
|
13680
13761
|
models,
|
|
@@ -13689,7 +13770,7 @@ function AgentChatPanel({
|
|
|
13689
13770
|
narrow
|
|
13690
13771
|
}
|
|
13691
13772
|
);
|
|
13692
|
-
const threadMenu = threads && threads.length ? /* @__PURE__ */
|
|
13773
|
+
const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx104(
|
|
13693
13774
|
MenuButton,
|
|
13694
13775
|
{
|
|
13695
13776
|
variant: "ghost",
|
|
@@ -13716,7 +13797,7 @@ function AgentChatPanel({
|
|
|
13716
13797
|
})))
|
|
13717
13798
|
}
|
|
13718
13799
|
) : null;
|
|
13719
|
-
return /* @__PURE__ */
|
|
13800
|
+
return /* @__PURE__ */ jsxs91(
|
|
13720
13801
|
"aside",
|
|
13721
13802
|
{
|
|
13722
13803
|
className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
|
|
@@ -13727,7 +13808,7 @@ function AgentChatPanel({
|
|
|
13727
13808
|
},
|
|
13728
13809
|
"aria-label": title,
|
|
13729
13810
|
children: [
|
|
13730
|
-
surface === "sidebar" && resizable ? /* @__PURE__ */
|
|
13811
|
+
surface === "sidebar" && resizable ? /* @__PURE__ */ jsx104(
|
|
13731
13812
|
"div",
|
|
13732
13813
|
{
|
|
13733
13814
|
className: "fdc-grip",
|
|
@@ -13742,20 +13823,20 @@ function AgentChatPanel({
|
|
|
13742
13823
|
}
|
|
13743
13824
|
}
|
|
13744
13825
|
) : null,
|
|
13745
|
-
showHeader ? /* @__PURE__ */
|
|
13746
|
-
/* @__PURE__ */
|
|
13747
|
-
/* @__PURE__ */
|
|
13748
|
-
/* @__PURE__ */
|
|
13749
|
-
subtitle ? /* @__PURE__ */
|
|
13826
|
+
showHeader ? /* @__PURE__ */ jsxs91("header", { className: "fdc-head", children: [
|
|
13827
|
+
/* @__PURE__ */ jsx104("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx104("i", { className: "ph ph-" + assistantIcon }) }),
|
|
13828
|
+
/* @__PURE__ */ jsxs91("span", { className: "fdc-head-titles", children: [
|
|
13829
|
+
/* @__PURE__ */ jsx104("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
|
|
13830
|
+
subtitle ? /* @__PURE__ */ jsx104("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
|
|
13750
13831
|
] }),
|
|
13751
|
-
/* @__PURE__ */
|
|
13832
|
+
/* @__PURE__ */ jsxs91("span", { className: "fdc-head-acts", children: [
|
|
13752
13833
|
headerActions,
|
|
13753
13834
|
threadMenu,
|
|
13754
|
-
onNewThread ? /* @__PURE__ */
|
|
13755
|
-
onClose ? /* @__PURE__ */
|
|
13835
|
+
onNewThread ? /* @__PURE__ */ jsx104("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx104("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
|
|
13836
|
+
onClose ? /* @__PURE__ */ jsx104("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx104("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
13756
13837
|
] })
|
|
13757
13838
|
] }) : null,
|
|
13758
|
-
/* @__PURE__ */
|
|
13839
|
+
/* @__PURE__ */ jsx104(
|
|
13759
13840
|
ChatTranscript,
|
|
13760
13841
|
{
|
|
13761
13842
|
messages: engine.visible,
|
|
@@ -13770,7 +13851,7 @@ function AgentChatPanel({
|
|
|
13770
13851
|
renderEmpty
|
|
13771
13852
|
}
|
|
13772
13853
|
),
|
|
13773
|
-
/* @__PURE__ */
|
|
13854
|
+
/* @__PURE__ */ jsx104(
|
|
13774
13855
|
ChatComposer,
|
|
13775
13856
|
{
|
|
13776
13857
|
onSubmit: (text, atts) => engine.send(text, atts),
|
|
@@ -13803,8 +13884,8 @@ function AgentChatPanel({
|
|
|
13803
13884
|
}
|
|
13804
13885
|
|
|
13805
13886
|
// src/components/files/FileViewer.tsx
|
|
13806
|
-
import * as
|
|
13807
|
-
import { jsx as
|
|
13887
|
+
import * as React76 from "react";
|
|
13888
|
+
import { jsx as jsx105, jsxs as jsxs92 } from "react/jsx-runtime";
|
|
13808
13889
|
function previewKindOf(file) {
|
|
13809
13890
|
const mime = (file.mime || "").toLowerCase();
|
|
13810
13891
|
const ext = extensionOf(file.name || "");
|
|
@@ -13860,13 +13941,13 @@ function parseDelimited(text, delimiter) {
|
|
|
13860
13941
|
return rows;
|
|
13861
13942
|
}
|
|
13862
13943
|
function usePreview(file, kind, resolveUrl) {
|
|
13863
|
-
const [state, setState] =
|
|
13864
|
-
const [attempt, setAttempt] =
|
|
13865
|
-
const resolveRef =
|
|
13866
|
-
|
|
13944
|
+
const [state, setState] = React76.useState({ status: "loading" });
|
|
13945
|
+
const [attempt, setAttempt] = React76.useState(0);
|
|
13946
|
+
const resolveRef = React76.useRef(resolveUrl);
|
|
13947
|
+
React76.useEffect(() => {
|
|
13867
13948
|
resolveRef.current = resolveUrl;
|
|
13868
13949
|
}, [resolveUrl]);
|
|
13869
|
-
|
|
13950
|
+
React76.useEffect(() => {
|
|
13870
13951
|
if (kind === "none") {
|
|
13871
13952
|
setState({ status: "ready" });
|
|
13872
13953
|
return;
|
|
@@ -13896,19 +13977,19 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
13896
13977
|
if (ac) ac.abort();
|
|
13897
13978
|
};
|
|
13898
13979
|
}, [file.id, kind, attempt]);
|
|
13899
|
-
return { ...state, retry:
|
|
13980
|
+
return { ...state, retry: React76.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
13900
13981
|
}
|
|
13901
13982
|
function PreviewBody({ file, kind, state }) {
|
|
13902
|
-
if (kind === "image") return /* @__PURE__ */
|
|
13903
|
-
if (kind === "pdf") return /* @__PURE__ */
|
|
13904
|
-
if (kind === "markdown") return /* @__PURE__ */
|
|
13983
|
+
if (kind === "image") return /* @__PURE__ */ jsx105("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
13984
|
+
if (kind === "pdf") return /* @__PURE__ */ jsx105("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
|
|
13985
|
+
if (kind === "markdown") return /* @__PURE__ */ jsx105(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
|
|
13905
13986
|
if (kind === "json") {
|
|
13906
13987
|
let pretty = state.text || "";
|
|
13907
13988
|
try {
|
|
13908
13989
|
pretty = JSON.stringify(JSON.parse(pretty), null, 2);
|
|
13909
13990
|
} catch {
|
|
13910
13991
|
}
|
|
13911
|
-
return /* @__PURE__ */
|
|
13992
|
+
return /* @__PURE__ */ jsx105(CodeBlock, { code: pretty, language: "json" });
|
|
13912
13993
|
}
|
|
13913
13994
|
if (kind === "csv") {
|
|
13914
13995
|
const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
|
|
@@ -13916,12 +13997,12 @@ function PreviewBody({ file, kind, state }) {
|
|
|
13916
13997
|
const head = rows[0] || [];
|
|
13917
13998
|
const dataRows = rows.slice(1);
|
|
13918
13999
|
const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
|
|
13919
|
-
return /* @__PURE__ */
|
|
13920
|
-
/* @__PURE__ */
|
|
13921
|
-
/* @__PURE__ */
|
|
13922
|
-
/* @__PURE__ */
|
|
14000
|
+
return /* @__PURE__ */ jsxs92("div", { className: "fd-fv-csv", children: [
|
|
14001
|
+
/* @__PURE__ */ jsxs92("table", { className: "fd-fv-csv-table", children: [
|
|
14002
|
+
/* @__PURE__ */ jsx105("thead", { children: /* @__PURE__ */ jsx105("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx105("th", { children: c }, i)) }) }),
|
|
14003
|
+
/* @__PURE__ */ jsx105("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx105("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx105("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
|
|
13923
14004
|
] }),
|
|
13924
|
-
dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */
|
|
14005
|
+
dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs92("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
|
|
13925
14006
|
"Showing the first ",
|
|
13926
14007
|
FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
|
|
13927
14008
|
" of ",
|
|
@@ -13930,24 +14011,24 @@ function PreviewBody({ file, kind, state }) {
|
|
|
13930
14011
|
] }) : null
|
|
13931
14012
|
] });
|
|
13932
14013
|
}
|
|
13933
|
-
if (kind === "text") return /* @__PURE__ */
|
|
13934
|
-
return /* @__PURE__ */
|
|
13935
|
-
/* @__PURE__ */
|
|
13936
|
-
/* @__PURE__ */
|
|
13937
|
-
/* @__PURE__ */
|
|
14014
|
+
if (kind === "text") return /* @__PURE__ */ jsx105(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
|
|
14015
|
+
return /* @__PURE__ */ jsxs92("div", { className: "fd-fv-fallback", children: [
|
|
14016
|
+
/* @__PURE__ */ jsx105("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx105("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
|
|
14017
|
+
/* @__PURE__ */ jsx105("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
|
|
14018
|
+
/* @__PURE__ */ jsxs92("span", { className: "fd-fv-fallback-meta", children: [
|
|
13938
14019
|
file.mime || "Unknown type",
|
|
13939
14020
|
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
13940
14021
|
] })
|
|
13941
14022
|
] });
|
|
13942
14023
|
}
|
|
13943
14024
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
13944
|
-
const kind =
|
|
14025
|
+
const kind = React76.useMemo(() => previewKindOf(file), [file]);
|
|
13945
14026
|
const preview = usePreview(file, kind, resolveUrl);
|
|
13946
|
-
const [tab, setTab] =
|
|
13947
|
-
const [downloading, setDownloading] =
|
|
13948
|
-
const [downloadError, setDownloadError] =
|
|
14027
|
+
const [tab, setTab] = React76.useState("preview");
|
|
14028
|
+
const [downloading, setDownloading] = React76.useState(false);
|
|
14029
|
+
const [downloadError, setDownloadError] = React76.useState(null);
|
|
13949
14030
|
const hasSide = sidePanel != null;
|
|
13950
|
-
|
|
14031
|
+
React76.useEffect(() => {
|
|
13951
14032
|
setTab("preview");
|
|
13952
14033
|
}, [file.id]);
|
|
13953
14034
|
const download = () => {
|
|
@@ -13963,29 +14044,29 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13963
14044
|
a.remove();
|
|
13964
14045
|
}).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
|
|
13965
14046
|
};
|
|
13966
|
-
return /* @__PURE__ */
|
|
14047
|
+
return /* @__PURE__ */ jsxs92(
|
|
13967
14048
|
"section",
|
|
13968
14049
|
{
|
|
13969
14050
|
className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
|
|
13970
14051
|
"aria-label": file.name || "File",
|
|
13971
14052
|
children: [
|
|
13972
|
-
/* @__PURE__ */
|
|
13973
|
-
/* @__PURE__ */
|
|
13974
|
-
/* @__PURE__ */
|
|
13975
|
-
/* @__PURE__ */
|
|
13976
|
-
/* @__PURE__ */
|
|
14053
|
+
/* @__PURE__ */ jsxs92("header", { className: "fd-fv-head", children: [
|
|
14054
|
+
/* @__PURE__ */ jsx105("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx105("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
|
|
14055
|
+
/* @__PURE__ */ jsxs92("span", { className: "fd-fv-head-titles", children: [
|
|
14056
|
+
/* @__PURE__ */ jsx105("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
|
|
14057
|
+
/* @__PURE__ */ jsxs92("span", { className: "fd-fv-head-meta", children: [
|
|
13977
14058
|
file.mime || "Unknown type",
|
|
13978
14059
|
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
13979
14060
|
] })
|
|
13980
14061
|
] }),
|
|
13981
|
-
/* @__PURE__ */
|
|
14062
|
+
/* @__PURE__ */ jsxs92("span", { className: "fd-fv-head-actions", children: [
|
|
13982
14063
|
actions,
|
|
13983
|
-
/* @__PURE__ */
|
|
13984
|
-
onClose ? /* @__PURE__ */
|
|
14064
|
+
/* @__PURE__ */ jsx105(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
|
|
14065
|
+
onClose ? /* @__PURE__ */ jsx105(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
|
|
13985
14066
|
] })
|
|
13986
14067
|
] }),
|
|
13987
|
-
downloadError ? /* @__PURE__ */
|
|
13988
|
-
hasSide ? /* @__PURE__ */
|
|
14068
|
+
downloadError ? /* @__PURE__ */ jsx105("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
|
|
14069
|
+
hasSide ? /* @__PURE__ */ jsx105(
|
|
13989
14070
|
Tabs,
|
|
13990
14071
|
{
|
|
13991
14072
|
className: "fd-fv-tabs",
|
|
@@ -13994,19 +14075,19 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13994
14075
|
onChange: (v) => setTab(v)
|
|
13995
14076
|
}
|
|
13996
14077
|
) : null,
|
|
13997
|
-
/* @__PURE__ */
|
|
13998
|
-
/* @__PURE__ */
|
|
14078
|
+
/* @__PURE__ */ jsxs92("div", { className: "fd-fv-body", children: [
|
|
14079
|
+
/* @__PURE__ */ jsx105("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx105(
|
|
13999
14080
|
LoadingRegion,
|
|
14000
14081
|
{
|
|
14001
14082
|
state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
|
|
14002
14083
|
error: preview.error,
|
|
14003
14084
|
label: "Loading preview of " + (file.name || "file"),
|
|
14004
14085
|
onRetry: preview.status === "error" ? preview.retry : void 0,
|
|
14005
|
-
skeleton: /* @__PURE__ */
|
|
14006
|
-
children: /* @__PURE__ */
|
|
14086
|
+
skeleton: /* @__PURE__ */ jsx105(Skeleton, { shape: "card", h: 220 }),
|
|
14087
|
+
children: /* @__PURE__ */ jsx105(PreviewBody, { file, kind, state: preview })
|
|
14007
14088
|
}
|
|
14008
14089
|
) }),
|
|
14009
|
-
hasSide ? /* @__PURE__ */
|
|
14090
|
+
hasSide ? /* @__PURE__ */ jsx105("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
|
|
14010
14091
|
] })
|
|
14011
14092
|
]
|
|
14012
14093
|
}
|
|
@@ -14014,8 +14095,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
14014
14095
|
}
|
|
14015
14096
|
|
|
14016
14097
|
// src/components/files/FileBrowser.tsx
|
|
14017
|
-
import * as
|
|
14018
|
-
import { Fragment as Fragment31, jsx as
|
|
14098
|
+
import * as React77 from "react";
|
|
14099
|
+
import { Fragment as Fragment31, jsx as jsx106, jsxs as jsxs93 } from "react/jsx-runtime";
|
|
14019
14100
|
function childrenOf(folders, parentId) {
|
|
14020
14101
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
14021
14102
|
}
|
|
@@ -14087,8 +14168,8 @@ function FolderPickerMenu({
|
|
|
14087
14168
|
}) {
|
|
14088
14169
|
const panel = useInlinePanel();
|
|
14089
14170
|
const { open: open2, setOpen, ref } = panel;
|
|
14090
|
-
return /* @__PURE__ */
|
|
14091
|
-
/* @__PURE__ */
|
|
14171
|
+
return /* @__PURE__ */ jsxs93("span", { className: "fd-fb-menu-anchor", ref, children: [
|
|
14172
|
+
/* @__PURE__ */ jsx106(
|
|
14092
14173
|
IconButton,
|
|
14093
14174
|
{
|
|
14094
14175
|
icon: "arrows-out-cardinal",
|
|
@@ -14100,9 +14181,9 @@ function FolderPickerMenu({
|
|
|
14100
14181
|
onClick: () => setOpen((v) => !v)
|
|
14101
14182
|
}
|
|
14102
14183
|
),
|
|
14103
|
-
/* @__PURE__ */
|
|
14104
|
-
/* @__PURE__ */
|
|
14105
|
-
destinations.map((d) => /* @__PURE__ */
|
|
14184
|
+
/* @__PURE__ */ jsx106(InlinePanelSurface, { panel, align: "right", offset: 4, width: 220, maxHeight: 280, role: "menu", label, children: /* @__PURE__ */ jsxs93("div", { className: "fd-fb-menu", children: [
|
|
14185
|
+
/* @__PURE__ */ jsx106("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
|
|
14186
|
+
destinations.map((d) => /* @__PURE__ */ jsxs93(
|
|
14106
14187
|
"button",
|
|
14107
14188
|
{
|
|
14108
14189
|
type: "button",
|
|
@@ -14114,7 +14195,7 @@ function FolderPickerMenu({
|
|
|
14114
14195
|
setOpen(false);
|
|
14115
14196
|
},
|
|
14116
14197
|
children: [
|
|
14117
|
-
/* @__PURE__ */
|
|
14198
|
+
/* @__PURE__ */ jsx106("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
|
|
14118
14199
|
d.name
|
|
14119
14200
|
]
|
|
14120
14201
|
},
|
|
@@ -14124,8 +14205,8 @@ function FolderPickerMenu({
|
|
|
14124
14205
|
] });
|
|
14125
14206
|
}
|
|
14126
14207
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
14127
|
-
const [over, setOver] =
|
|
14128
|
-
const dragCounter =
|
|
14208
|
+
const [over, setOver] = React77.useState(false);
|
|
14209
|
+
const dragCounter = React77.useRef(0);
|
|
14129
14210
|
const dropHandlers = isDropTarget ? {
|
|
14130
14211
|
onDragEnter: (e) => {
|
|
14131
14212
|
if (!hasInternalPayload(e)) return;
|
|
@@ -14150,8 +14231,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
14150
14231
|
if (payload && onDropPayload) onDropPayload(payload);
|
|
14151
14232
|
}
|
|
14152
14233
|
} : {};
|
|
14153
|
-
return /* @__PURE__ */
|
|
14154
|
-
/* @__PURE__ */
|
|
14234
|
+
return /* @__PURE__ */ jsxs93("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
|
|
14235
|
+
/* @__PURE__ */ jsxs93(
|
|
14155
14236
|
"button",
|
|
14156
14237
|
{
|
|
14157
14238
|
type: "button",
|
|
@@ -14160,26 +14241,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
14160
14241
|
draggable: !!draggableId,
|
|
14161
14242
|
onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
|
|
14162
14243
|
children: [
|
|
14163
|
-
/* @__PURE__ */
|
|
14164
|
-
/* @__PURE__ */
|
|
14165
|
-
/* @__PURE__ */
|
|
14166
|
-
meta ? /* @__PURE__ */
|
|
14244
|
+
/* @__PURE__ */ jsx106("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx106("i", { className: "ph ph-" + icon }) }),
|
|
14245
|
+
/* @__PURE__ */ jsxs93("span", { className: "fd-fb-row-text", children: [
|
|
14246
|
+
/* @__PURE__ */ jsx106("span", { className: "fd-fb-row-name", title: name, children: name }),
|
|
14247
|
+
meta ? /* @__PURE__ */ jsx106("span", { className: "fd-fb-row-meta", children: meta }) : null
|
|
14167
14248
|
] })
|
|
14168
14249
|
]
|
|
14169
14250
|
}
|
|
14170
14251
|
),
|
|
14171
|
-
actions ? /* @__PURE__ */
|
|
14252
|
+
actions ? /* @__PURE__ */ jsx106("span", { className: "fd-fb-row-actions", children: actions }) : null
|
|
14172
14253
|
] });
|
|
14173
14254
|
}
|
|
14174
14255
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
14175
14256
|
const kids = childrenOf(folders, folder.id);
|
|
14176
|
-
const [expanded, setExpanded] =
|
|
14177
|
-
|
|
14257
|
+
const [expanded, setExpanded] = React77.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
14258
|
+
React77.useEffect(() => {
|
|
14178
14259
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
14179
14260
|
}, [currentFolderId, folder.id, folders]);
|
|
14180
14261
|
const isCurrent = folder.id === currentFolderId;
|
|
14181
|
-
return /* @__PURE__ */
|
|
14182
|
-
/* @__PURE__ */
|
|
14262
|
+
return /* @__PURE__ */ jsxs93("div", { className: "fd-fb-tree-node", children: [
|
|
14263
|
+
/* @__PURE__ */ jsx106(
|
|
14183
14264
|
RowShell,
|
|
14184
14265
|
{
|
|
14185
14266
|
icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
|
|
@@ -14189,7 +14270,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
|
|
|
14189
14270
|
isDropTarget: canMove,
|
|
14190
14271
|
onDropPayload: (payload) => onMoveInto(payload, folder.id),
|
|
14191
14272
|
className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
|
|
14192
|
-
actions: kids.length ? /* @__PURE__ */
|
|
14273
|
+
actions: kids.length ? /* @__PURE__ */ jsx106(
|
|
14193
14274
|
IconButton,
|
|
14194
14275
|
{
|
|
14195
14276
|
icon: expanded ? "caret-down" : "caret-right",
|
|
@@ -14201,7 +14282,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
|
|
|
14201
14282
|
) : void 0
|
|
14202
14283
|
}
|
|
14203
14284
|
),
|
|
14204
|
-
expanded && kids.length ? /* @__PURE__ */
|
|
14285
|
+
expanded && kids.length ? /* @__PURE__ */ jsx106("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx106(
|
|
14205
14286
|
TreeNode,
|
|
14206
14287
|
{
|
|
14207
14288
|
folder: k,
|
|
@@ -14240,15 +14321,15 @@ function FileBrowser({
|
|
|
14240
14321
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
14241
14322
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
14242
14323
|
const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
|
|
14243
|
-
const [createOpen, setCreateOpen] =
|
|
14244
|
-
const [createName, setCreateName] =
|
|
14245
|
-
const [renameTarget, setRenameTarget] =
|
|
14246
|
-
const [renameValue, setRenameValue] =
|
|
14247
|
-
const [deleteTarget, setDeleteTarget] =
|
|
14248
|
-
const uploadInputRef =
|
|
14249
|
-
const crumbFolders =
|
|
14250
|
-
const subfolders =
|
|
14251
|
-
const currentFiles =
|
|
14324
|
+
const [createOpen, setCreateOpen] = React77.useState(false);
|
|
14325
|
+
const [createName, setCreateName] = React77.useState("");
|
|
14326
|
+
const [renameTarget, setRenameTarget] = React77.useState(null);
|
|
14327
|
+
const [renameValue, setRenameValue] = React77.useState("");
|
|
14328
|
+
const [deleteTarget, setDeleteTarget] = React77.useState(null);
|
|
14329
|
+
const uploadInputRef = React77.useRef(null);
|
|
14330
|
+
const crumbFolders = React77.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
14331
|
+
const subfolders = React77.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
14332
|
+
const currentFiles = React77.useMemo(
|
|
14252
14333
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
14253
14334
|
[files, currentFolderId]
|
|
14254
14335
|
);
|
|
@@ -14287,10 +14368,10 @@ function FileBrowser({
|
|
|
14287
14368
|
if (deleteTarget && onDeleteFolder) onDeleteFolder(deleteTarget);
|
|
14288
14369
|
setDeleteTarget(null);
|
|
14289
14370
|
};
|
|
14290
|
-
const content = /* @__PURE__ */
|
|
14291
|
-
/* @__PURE__ */
|
|
14292
|
-
/* @__PURE__ */
|
|
14293
|
-
/* @__PURE__ */
|
|
14371
|
+
const content = /* @__PURE__ */ jsxs93("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
|
|
14372
|
+
/* @__PURE__ */ jsxs93("div", { className: "fd-fb-head", children: [
|
|
14373
|
+
/* @__PURE__ */ jsxs93("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
|
|
14374
|
+
/* @__PURE__ */ jsx106(
|
|
14294
14375
|
BreadcrumbCrumb,
|
|
14295
14376
|
{
|
|
14296
14377
|
label: "Home",
|
|
@@ -14300,7 +14381,7 @@ function FileBrowser({
|
|
|
14300
14381
|
onDropPayload: (p) => moveIntoFolder(p, null)
|
|
14301
14382
|
}
|
|
14302
14383
|
),
|
|
14303
|
-
crumbFolders.map((f, i) => /* @__PURE__ */
|
|
14384
|
+
crumbFolders.map((f, i) => /* @__PURE__ */ jsx106(
|
|
14304
14385
|
BreadcrumbCrumb,
|
|
14305
14386
|
{
|
|
14306
14387
|
label: f.name,
|
|
@@ -14312,11 +14393,11 @@ function FileBrowser({
|
|
|
14312
14393
|
f.id
|
|
14313
14394
|
))
|
|
14314
14395
|
] }),
|
|
14315
|
-
/* @__PURE__ */
|
|
14316
|
-
canCreateFolder ? /* @__PURE__ */
|
|
14317
|
-
canUpload ? /* @__PURE__ */
|
|
14318
|
-
/* @__PURE__ */
|
|
14319
|
-
/* @__PURE__ */
|
|
14396
|
+
/* @__PURE__ */ jsxs93("span", { className: "fd-fb-actions", children: [
|
|
14397
|
+
canCreateFolder ? /* @__PURE__ */ jsx106(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
|
|
14398
|
+
canUpload ? /* @__PURE__ */ jsxs93(Fragment31, { children: [
|
|
14399
|
+
/* @__PURE__ */ jsx106(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
|
|
14400
|
+
/* @__PURE__ */ jsx106(
|
|
14320
14401
|
"input",
|
|
14321
14402
|
{
|
|
14322
14403
|
ref: uploadInputRef,
|
|
@@ -14334,9 +14415,9 @@ function FileBrowser({
|
|
|
14334
14415
|
] }) : null
|
|
14335
14416
|
] })
|
|
14336
14417
|
] }),
|
|
14337
|
-
/* @__PURE__ */
|
|
14338
|
-
/* @__PURE__ */
|
|
14339
|
-
/* @__PURE__ */
|
|
14418
|
+
/* @__PURE__ */ jsxs93("div", { className: "fd-fb-body", children: [
|
|
14419
|
+
/* @__PURE__ */ jsxs93("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
|
|
14420
|
+
/* @__PURE__ */ jsx106(
|
|
14340
14421
|
RowShell,
|
|
14341
14422
|
{
|
|
14342
14423
|
icon: "house-simple",
|
|
@@ -14347,7 +14428,7 @@ function FileBrowser({
|
|
|
14347
14428
|
className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
|
|
14348
14429
|
}
|
|
14349
14430
|
),
|
|
14350
|
-
childrenOf(folders, null).map((f) => /* @__PURE__ */
|
|
14431
|
+
childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx106(
|
|
14351
14432
|
TreeNode,
|
|
14352
14433
|
{
|
|
14353
14434
|
folder: f,
|
|
@@ -14361,18 +14442,18 @@ function FileBrowser({
|
|
|
14361
14442
|
f.id
|
|
14362
14443
|
))
|
|
14363
14444
|
] }),
|
|
14364
|
-
/* @__PURE__ */
|
|
14445
|
+
/* @__PURE__ */ jsx106("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx106(
|
|
14365
14446
|
LoadingRegion,
|
|
14366
14447
|
{
|
|
14367
14448
|
state: loading ? "loading" : "ready",
|
|
14368
14449
|
label: "Loading folder contents",
|
|
14369
|
-
skeleton: /* @__PURE__ */
|
|
14370
|
-
/* @__PURE__ */
|
|
14371
|
-
/* @__PURE__ */
|
|
14372
|
-
/* @__PURE__ */
|
|
14450
|
+
skeleton: /* @__PURE__ */ jsxs93("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
|
|
14451
|
+
/* @__PURE__ */ jsx106(Skeleton, { h: 44, radius: "10px" }),
|
|
14452
|
+
/* @__PURE__ */ jsx106(Skeleton, { h: 44, radius: "10px" }),
|
|
14453
|
+
/* @__PURE__ */ jsx106(Skeleton, { h: 44, radius: "10px" })
|
|
14373
14454
|
] }),
|
|
14374
|
-
children: isEmpty ? /* @__PURE__ */
|
|
14375
|
-
subfolders.map((f) => /* @__PURE__ */
|
|
14455
|
+
children: isEmpty ? /* @__PURE__ */ jsx106(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__ */ jsxs93("div", { className: "fd-fb-list", children: [
|
|
14456
|
+
subfolders.map((f) => /* @__PURE__ */ jsx106(
|
|
14376
14457
|
RowShell,
|
|
14377
14458
|
{
|
|
14378
14459
|
icon: "folder-simple",
|
|
@@ -14381,9 +14462,9 @@ function FileBrowser({
|
|
|
14381
14462
|
draggableId: canMove ? { kind: "folder", id: f.id } : void 0,
|
|
14382
14463
|
isDropTarget: canMove,
|
|
14383
14464
|
onDropPayload: (p) => moveIntoFolder(p, f.id),
|
|
14384
|
-
actions: /* @__PURE__ */
|
|
14385
|
-
canRenameFolder ? /* @__PURE__ */
|
|
14386
|
-
canMove ? /* @__PURE__ */
|
|
14465
|
+
actions: /* @__PURE__ */ jsxs93(Fragment31, { children: [
|
|
14466
|
+
canRenameFolder ? /* @__PURE__ */ jsx106(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
|
|
14467
|
+
canMove ? /* @__PURE__ */ jsx106(
|
|
14387
14468
|
FolderPickerMenu,
|
|
14388
14469
|
{
|
|
14389
14470
|
label: "Move " + f.name,
|
|
@@ -14391,12 +14472,12 @@ function FileBrowser({
|
|
|
14391
14472
|
onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
|
|
14392
14473
|
}
|
|
14393
14474
|
) : null,
|
|
14394
|
-
canDeleteFolder ? /* @__PURE__ */
|
|
14475
|
+
canDeleteFolder ? /* @__PURE__ */ jsx106(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
|
|
14395
14476
|
] })
|
|
14396
14477
|
},
|
|
14397
14478
|
f.id
|
|
14398
14479
|
)),
|
|
14399
|
-
currentFiles.map((file) => /* @__PURE__ */
|
|
14480
|
+
currentFiles.map((file) => /* @__PURE__ */ jsx106(
|
|
14400
14481
|
RowShell,
|
|
14401
14482
|
{
|
|
14402
14483
|
icon: iconForMime(file.mime, file.name),
|
|
@@ -14404,8 +14485,8 @@ function FileBrowser({
|
|
|
14404
14485
|
meta: file.size ? formatBytes(file.size) : void 0,
|
|
14405
14486
|
onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
|
|
14406
14487
|
draggableId: canMove ? { kind: "file", id: file.id } : void 0,
|
|
14407
|
-
actions: /* @__PURE__ */
|
|
14408
|
-
canMove ? /* @__PURE__ */
|
|
14488
|
+
actions: /* @__PURE__ */ jsxs93(Fragment31, { children: [
|
|
14489
|
+
canMove ? /* @__PURE__ */ jsx106(
|
|
14409
14490
|
FolderPickerMenu,
|
|
14410
14491
|
{
|
|
14411
14492
|
label: "Move " + file.name,
|
|
@@ -14413,7 +14494,7 @@ function FileBrowser({
|
|
|
14413
14494
|
onPick: (target) => onMoveFile && onMoveFile(file.id, target)
|
|
14414
14495
|
}
|
|
14415
14496
|
) : null,
|
|
14416
|
-
canRemoveFile ? /* @__PURE__ */
|
|
14497
|
+
canRemoveFile ? /* @__PURE__ */ jsx106(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
|
|
14417
14498
|
] })
|
|
14418
14499
|
},
|
|
14419
14500
|
file.id
|
|
@@ -14422,10 +14503,10 @@ function FileBrowser({
|
|
|
14422
14503
|
}
|
|
14423
14504
|
) })
|
|
14424
14505
|
] }),
|
|
14425
|
-
/* @__PURE__ */
|
|
14426
|
-
/* @__PURE__ */
|
|
14427
|
-
/* @__PURE__ */
|
|
14428
|
-
] }), children: /* @__PURE__ */
|
|
14506
|
+
/* @__PURE__ */ jsx106(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs93(Fragment31, { children: [
|
|
14507
|
+
/* @__PURE__ */ jsx106(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
|
|
14508
|
+
/* @__PURE__ */ jsx106(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
|
|
14509
|
+
] }), children: /* @__PURE__ */ jsx106(
|
|
14429
14510
|
"input",
|
|
14430
14511
|
{
|
|
14431
14512
|
className: "fd-fb-input",
|
|
@@ -14439,10 +14520,10 @@ function FileBrowser({
|
|
|
14439
14520
|
autoFocus: true
|
|
14440
14521
|
}
|
|
14441
14522
|
) }),
|
|
14442
|
-
/* @__PURE__ */
|
|
14443
|
-
/* @__PURE__ */
|
|
14444
|
-
/* @__PURE__ */
|
|
14445
|
-
] }), children: /* @__PURE__ */
|
|
14523
|
+
/* @__PURE__ */ jsx106(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs93(Fragment31, { children: [
|
|
14524
|
+
/* @__PURE__ */ jsx106(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
|
|
14525
|
+
/* @__PURE__ */ jsx106(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
|
|
14526
|
+
] }), children: /* @__PURE__ */ jsx106(
|
|
14446
14527
|
"input",
|
|
14447
14528
|
{
|
|
14448
14529
|
className: "fd-fb-input",
|
|
@@ -14456,22 +14537,22 @@ function FileBrowser({
|
|
|
14456
14537
|
autoFocus: true
|
|
14457
14538
|
}
|
|
14458
14539
|
) }),
|
|
14459
|
-
/* @__PURE__ */
|
|
14540
|
+
/* @__PURE__ */ jsx106(
|
|
14460
14541
|
Modal,
|
|
14461
14542
|
{
|
|
14462
14543
|
open: deleteTarget != null,
|
|
14463
14544
|
title: deleteTarget ? "Delete \u201C" + deleteTarget.name + "\u201D?" : "Delete folder?",
|
|
14464
14545
|
description: "This can't be undone. The folder must be empty.",
|
|
14465
14546
|
onClose: () => setDeleteTarget(null),
|
|
14466
|
-
footer: /* @__PURE__ */
|
|
14467
|
-
/* @__PURE__ */
|
|
14468
|
-
/* @__PURE__ */
|
|
14547
|
+
footer: /* @__PURE__ */ jsxs93(Fragment31, { children: [
|
|
14548
|
+
/* @__PURE__ */ jsx106(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
|
|
14549
|
+
/* @__PURE__ */ jsx106(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
|
|
14469
14550
|
] })
|
|
14470
14551
|
}
|
|
14471
14552
|
)
|
|
14472
14553
|
] });
|
|
14473
14554
|
if (!canUpload) return content;
|
|
14474
|
-
return /* @__PURE__ */
|
|
14555
|
+
return /* @__PURE__ */ jsx106(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
|
|
14475
14556
|
}
|
|
14476
14557
|
function BreadcrumbCrumb({
|
|
14477
14558
|
label,
|
|
@@ -14480,8 +14561,8 @@ function BreadcrumbCrumb({
|
|
|
14480
14561
|
isDropTarget,
|
|
14481
14562
|
onDropPayload
|
|
14482
14563
|
}) {
|
|
14483
|
-
const [over, setOver] =
|
|
14484
|
-
const dragCounter =
|
|
14564
|
+
const [over, setOver] = React77.useState(false);
|
|
14565
|
+
const dragCounter = React77.useRef(0);
|
|
14485
14566
|
const dropHandlers = isDropTarget ? {
|
|
14486
14567
|
onDragEnter: (e) => {
|
|
14487
14568
|
if (!hasInternalPayload(e)) return;
|
|
@@ -14506,11 +14587,11 @@ function BreadcrumbCrumb({
|
|
|
14506
14587
|
if (payload && onDropPayload) onDropPayload(payload);
|
|
14507
14588
|
}
|
|
14508
14589
|
} : {};
|
|
14509
|
-
return /* @__PURE__ */
|
|
14590
|
+
return /* @__PURE__ */ jsx106("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx106("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx106("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
|
|
14510
14591
|
}
|
|
14511
14592
|
|
|
14512
14593
|
// src/kits/query.ts
|
|
14513
|
-
import * as
|
|
14594
|
+
import * as React78 from "react";
|
|
14514
14595
|
|
|
14515
14596
|
// src/kits/queryUrl.ts
|
|
14516
14597
|
var historyUrlAdapter = {
|
|
@@ -14648,38 +14729,38 @@ function requestFor(params, query, paging, after) {
|
|
|
14648
14729
|
}
|
|
14649
14730
|
var toError = (e) => e instanceof Error ? e : new Error(String(e));
|
|
14650
14731
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "page", url }) {
|
|
14651
|
-
const [base] =
|
|
14732
|
+
const [base] = React78.useState(() => {
|
|
14652
14733
|
const store = PREFS || window.PlannerPrefs;
|
|
14653
14734
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
14654
14735
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
14655
14736
|
});
|
|
14656
|
-
const [mountParams] =
|
|
14657
|
-
const address =
|
|
14658
|
-
const [query, setQuery] =
|
|
14659
|
-
const savePref =
|
|
14737
|
+
const [mountParams] = React78.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
|
|
14738
|
+
const address = React78.useRef(mountParams);
|
|
14739
|
+
const [query, setQuery] = React78.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
|
|
14740
|
+
const savePref = React78.useCallback((patch2) => {
|
|
14660
14741
|
const store = PREFS || window.PlannerPrefs;
|
|
14661
14742
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
14662
14743
|
}, [prefsKey]);
|
|
14663
|
-
const [res, setRes] =
|
|
14664
|
-
const [loading, setLoading] =
|
|
14665
|
-
const [loadingMore, setLoadingMore] =
|
|
14666
|
-
const [failure, setFailure] =
|
|
14667
|
-
const [reloadToken, setReloadToken] =
|
|
14668
|
-
const moreController =
|
|
14744
|
+
const [res, setRes] = React78.useState(null);
|
|
14745
|
+
const [loading, setLoading] = React78.useState(true);
|
|
14746
|
+
const [loadingMore, setLoadingMore] = React78.useState(false);
|
|
14747
|
+
const [failure, setFailure] = React78.useState(null);
|
|
14748
|
+
const [reloadToken, setReloadToken] = React78.useState(0);
|
|
14749
|
+
const moreController = React78.useRef(null);
|
|
14669
14750
|
const depKey = (deps || []).join("|");
|
|
14670
14751
|
const paramKey = JSON.stringify(params || {});
|
|
14671
14752
|
const queryKey = JSON.stringify(query);
|
|
14672
|
-
const lifetime =
|
|
14673
|
-
|
|
14753
|
+
const lifetime = React78.useRef(null);
|
|
14754
|
+
React78.useEffect(() => {
|
|
14674
14755
|
const controller = new AbortController();
|
|
14675
14756
|
lifetime.current = controller;
|
|
14676
14757
|
return () => controller.abort();
|
|
14677
14758
|
}, []);
|
|
14678
|
-
const latest =
|
|
14679
|
-
|
|
14759
|
+
const latest = React78.useRef({ res, loading, query, params, endpoint, url, base });
|
|
14760
|
+
React78.useLayoutEffect(() => {
|
|
14680
14761
|
latest.current = { res, loading, query, params, endpoint, url, base };
|
|
14681
14762
|
});
|
|
14682
|
-
|
|
14763
|
+
React78.useEffect(() => {
|
|
14683
14764
|
const controller = new AbortController();
|
|
14684
14765
|
const { signal } = controller;
|
|
14685
14766
|
setLoading(true);
|
|
@@ -14715,7 +14796,7 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "
|
|
|
14715
14796
|
};
|
|
14716
14797
|
}, [endpoint, queryKey, paramKey, depKey, paging, reloadToken]);
|
|
14717
14798
|
const adapter = url ? url.adapter ?? historyUrlAdapter : null;
|
|
14718
|
-
|
|
14799
|
+
React78.useEffect(() => {
|
|
14719
14800
|
if (!adapter) return;
|
|
14720
14801
|
return adapter.subscribe((params2) => {
|
|
14721
14802
|
const { url: u, base: b } = latest.current;
|
|
@@ -15065,12 +15146,12 @@ function createVersionStore(initialState, options) {
|
|
|
15065
15146
|
}
|
|
15066
15147
|
|
|
15067
15148
|
// src/kits/documentTitle.ts
|
|
15068
|
-
import * as
|
|
15149
|
+
import * as React79 from "react";
|
|
15069
15150
|
function formatDocumentTitle(routeTitle, appName) {
|
|
15070
15151
|
return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
|
|
15071
15152
|
}
|
|
15072
15153
|
function useDocumentTitle(routeTitle, appName) {
|
|
15073
|
-
|
|
15154
|
+
React79.useEffect(() => {
|
|
15074
15155
|
if (typeof document === "undefined") return;
|
|
15075
15156
|
document.title = formatDocumentTitle(routeTitle, appName);
|
|
15076
15157
|
}, [routeTitle, appName]);
|
|
@@ -15141,6 +15222,7 @@ export {
|
|
|
15141
15222
|
FILE_VIEWER_TEXT_LIMIT,
|
|
15142
15223
|
FactList,
|
|
15143
15224
|
FeatureGate,
|
|
15225
|
+
Fieldset,
|
|
15144
15226
|
FileBrowser,
|
|
15145
15227
|
FileChip,
|
|
15146
15228
|
FileGrid,
|
|
@@ -15194,6 +15276,7 @@ export {
|
|
|
15194
15276
|
QuotaRow,
|
|
15195
15277
|
ROOT_STEP,
|
|
15196
15278
|
Radio,
|
|
15279
|
+
RadioGroup,
|
|
15197
15280
|
RangeSlider,
|
|
15198
15281
|
RelativeTime,
|
|
15199
15282
|
RoadmapTimeline,
|