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