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