@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.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hideEscapes,
|
|
3
|
+
showEscapes,
|
|
4
|
+
showEscapesRaw
|
|
5
|
+
} from "./chunk-OVTWSE43.js";
|
|
1
6
|
import {
|
|
2
7
|
US_STATES,
|
|
3
8
|
US_STATE_CODES,
|
|
@@ -3047,6 +3052,24 @@ function CsiHero({ band = "weak", crp, label, className = "" }) {
|
|
|
3047
3052
|
// src/components/data/DataTable.tsx
|
|
3048
3053
|
import { Fragment as Fragment7, jsx as jsx44, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
3049
3054
|
var STACK_MAX_WIDTH = 640;
|
|
3055
|
+
function RowActionButton({ action, size }) {
|
|
3056
|
+
return /* @__PURE__ */ jsx44(
|
|
3057
|
+
IconButton,
|
|
3058
|
+
{
|
|
3059
|
+
icon: action.icon,
|
|
3060
|
+
label: action.label,
|
|
3061
|
+
size,
|
|
3062
|
+
disabled: action.disabled,
|
|
3063
|
+
onClick: (e) => {
|
|
3064
|
+
e.stopPropagation();
|
|
3065
|
+
action.onClick();
|
|
3066
|
+
}
|
|
3067
|
+
}
|
|
3068
|
+
);
|
|
3069
|
+
}
|
|
3070
|
+
function RowActionCell({ action }) {
|
|
3071
|
+
return /* @__PURE__ */ jsx44("td", { className: "fd-table-action", children: action ? /* @__PURE__ */ jsx44(RowActionButton, { action, size: "sm" }) : null });
|
|
3072
|
+
}
|
|
3050
3073
|
var cellOf = (c, row) => c.render ? c.render(row) : row[c.key];
|
|
3051
3074
|
function rowInteraction(row, onRowClick) {
|
|
3052
3075
|
if (!onRowClick) return {};
|
|
@@ -3074,6 +3097,7 @@ function DataTable({
|
|
|
3074
3097
|
selectedIds,
|
|
3075
3098
|
rowTitle,
|
|
3076
3099
|
onRowClick,
|
|
3100
|
+
rowAction,
|
|
3077
3101
|
rowKey = "id",
|
|
3078
3102
|
loading = false,
|
|
3079
3103
|
refreshing = false,
|
|
@@ -3110,27 +3134,37 @@ function DataTable({
|
|
|
3110
3134
|
onSort,
|
|
3111
3135
|
rowTitle,
|
|
3112
3136
|
onRowClick,
|
|
3137
|
+
rowAction,
|
|
3113
3138
|
isSelected
|
|
3114
3139
|
}
|
|
3115
3140
|
) : /* @__PURE__ */ jsxs35("table", { className: ["fd-table", compact3 ? "fd-table-compact" : ""].filter(Boolean).join(" "), children: [
|
|
3116
|
-
/* @__PURE__ */ jsx44("thead", { children: /* @__PURE__ */
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3141
|
+
/* @__PURE__ */ jsx44("thead", { children: /* @__PURE__ */ jsxs35("tr", { children: [
|
|
3142
|
+
columns.map((c) => /* @__PURE__ */ jsx44(
|
|
3143
|
+
"th",
|
|
3144
|
+
{
|
|
3145
|
+
scope: "col",
|
|
3146
|
+
style: { width: c.width },
|
|
3147
|
+
className: [c.numeric ? "is-num" : "", sort && sort.key === c.key ? "is-sorted" : ""].filter(Boolean).join(" "),
|
|
3148
|
+
"aria-sort": sort && sort.key === c.key ? sort.dir === "asc" ? "ascending" : "descending" : void 0,
|
|
3149
|
+
children: c.sortable && onSort ? /* @__PURE__ */ jsx44(SortButton, { column: c, sort, onSort }) : c.label
|
|
3150
|
+
},
|
|
3151
|
+
c.key
|
|
3152
|
+
)),
|
|
3153
|
+
rowAction ? /* @__PURE__ */ jsx44("th", { scope: "col", className: "fd-table-action-head", children: /* @__PURE__ */ jsx44("span", { className: "fd-sr-only", children: "Actions" }) }) : null
|
|
3154
|
+
] }) }),
|
|
3155
|
+
/* @__PURE__ */ jsx44("tbody", { className: stale ? "fd-stale" : void 0, children: loading ? Array.from({ length: skeletonRows }).map((_, i) => /* @__PURE__ */ jsxs35("tr", { children: [
|
|
3156
|
+
columns.map((c) => /* @__PURE__ */ jsx44("td", { className: c.numeric ? "is-num" : "", children: /* @__PURE__ */ jsx44("span", { className: "fd-skel fd-skel-text", style: { display: "inline-block", height: 13, width: c.numeric ? 52 : i % 3 === 0 ? "72%" : "88%" } }) }, c.key)),
|
|
3157
|
+
rowAction ? /* @__PURE__ */ jsx44("td", { className: "fd-table-action" }) : null
|
|
3158
|
+
] }, i)) : rows.map((r) => /* @__PURE__ */ jsxs35(
|
|
3128
3159
|
"tr",
|
|
3129
3160
|
{
|
|
3130
3161
|
"aria-selected": isSelected(r) ? "true" : void 0,
|
|
3131
3162
|
title: rowTitle ? rowTitle(r) : void 0,
|
|
3132
3163
|
...rowInteraction(r, onRowClick),
|
|
3133
|
-
children:
|
|
3164
|
+
children: [
|
|
3165
|
+
columns.map((c) => /* @__PURE__ */ jsx44("td", { className: c.numeric ? "is-num" : "", children: cellOf(c, r) }, c.key)),
|
|
3166
|
+
rowAction ? /* @__PURE__ */ jsx44(RowActionCell, { action: rowAction(r) }) : null
|
|
3167
|
+
]
|
|
3134
3168
|
},
|
|
3135
3169
|
r[rowKey]
|
|
3136
3170
|
)) })
|
|
@@ -3143,7 +3177,7 @@ function DataTable({
|
|
|
3143
3177
|
] }) }) : null
|
|
3144
3178
|
] });
|
|
3145
3179
|
}
|
|
3146
|
-
function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort, onSort, rowTitle, onRowClick, isSelected }) {
|
|
3180
|
+
function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort, onSort, rowTitle, onRowClick, rowAction, isSelected }) {
|
|
3147
3181
|
const sortable = onSort ? columns.filter((c) => c.sortable) : [];
|
|
3148
3182
|
const primary = columns.filter((c) => c.phone === "primary");
|
|
3149
3183
|
const secondary = columns.filter((c) => c.phone === "secondary");
|
|
@@ -3162,31 +3196,34 @@ function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort
|
|
|
3162
3196
|
c.key
|
|
3163
3197
|
);
|
|
3164
3198
|
}) }) : null,
|
|
3165
|
-
/* @__PURE__ */ jsx44("div", { className: stale ? "fd-dt-cards fd-stale" : "fd-dt-cards", children: loading ? Array.from({ length: skeletonRows }).map((_, i) => /* @__PURE__ */ jsxs35("div", { className: "fd-dt-card", children: [
|
|
3199
|
+
/* @__PURE__ */ jsx44("div", { className: stale ? "fd-dt-cards fd-stale" : "fd-dt-cards", children: loading ? Array.from({ length: skeletonRows }).map((_, i) => /* @__PURE__ */ jsx44("div", { className: "fd-dt-item", children: /* @__PURE__ */ jsxs35("div", { className: "fd-dt-card", children: [
|
|
3166
3200
|
/* @__PURE__ */ jsx44("span", { className: "fd-skel fd-skel-text", style: { display: "block", height: 14, width: i % 3 === 0 ? "55%" : "70%" } }),
|
|
3167
3201
|
secondary.length ? /* @__PURE__ */ jsx44("span", { className: "fd-skel fd-skel-text", style: { display: "block", height: 12, width: "40%" } }) : null
|
|
3168
|
-
] }, i)) : rows.map((r) => {
|
|
3202
|
+
] }) }, i)) : rows.map((r) => {
|
|
3169
3203
|
const selected = isSelected(r);
|
|
3204
|
+
const action = rowAction ? rowAction(r) : null;
|
|
3170
3205
|
const semantics = onRowClick ? { role: "button", "aria-pressed": selected } : { "aria-current": selected ? "true" : void 0 };
|
|
3171
|
-
return /* @__PURE__ */ jsxs35(
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
/* @__PURE__ */ jsx44("
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3206
|
+
return /* @__PURE__ */ jsxs35("div", { className: "fd-dt-item", children: [
|
|
3207
|
+
/* @__PURE__ */ jsxs35(
|
|
3208
|
+
"div",
|
|
3209
|
+
{
|
|
3210
|
+
className: "fd-dt-card",
|
|
3211
|
+
title: rowTitle ? rowTitle(r) : void 0,
|
|
3212
|
+
"data-selected": selected ? "true" : void 0,
|
|
3213
|
+
...semantics,
|
|
3214
|
+
...rowInteraction(r, onRowClick),
|
|
3215
|
+
children: [
|
|
3216
|
+
/* @__PURE__ */ jsx44("div", { className: "fd-dt-card-title", children: primary.map((c) => /* @__PURE__ */ jsx44("span", { className: c.numeric ? "is-num" : void 0, children: cellOf(c, r) }, c.key)) }),
|
|
3217
|
+
secondary.length ? /* @__PURE__ */ jsx44("div", { className: "fd-dt-card-meta", children: secondary.map((c) => /* @__PURE__ */ jsxs35("span", { className: c.numeric ? "is-num" : void 0, children: [
|
|
3218
|
+
/* @__PURE__ */ jsx44("span", { className: "fd-dt-card-label", children: c.label }),
|
|
3219
|
+
" ",
|
|
3220
|
+
cellOf(c, r)
|
|
3221
|
+
] }, c.key)) }) : null
|
|
3222
|
+
]
|
|
3223
|
+
}
|
|
3224
|
+
),
|
|
3225
|
+
action ? /* @__PURE__ */ jsx44("div", { className: "fd-dt-action", children: /* @__PURE__ */ jsx44(RowActionButton, { action, size: "md" }) }) : null
|
|
3226
|
+
] }, r[rowKey]);
|
|
3190
3227
|
}) })
|
|
3191
3228
|
] });
|
|
3192
3229
|
}
|
|
@@ -5192,7 +5229,8 @@ var INLINE = [
|
|
|
5192
5229
|
];
|
|
5193
5230
|
function inlineNodes(src, ctx, keyBase) {
|
|
5194
5231
|
const out = [];
|
|
5195
|
-
let rest = String(src == null ? "" : src), guard = 0;
|
|
5232
|
+
let rest = hideEscapes(String(src == null ? "" : src)), guard = 0;
|
|
5233
|
+
const d = showEscapes;
|
|
5196
5234
|
const key = () => keyBase + "-" + out.length;
|
|
5197
5235
|
while (rest && guard++ < 800) {
|
|
5198
5236
|
let best = null;
|
|
@@ -5203,28 +5241,28 @@ function inlineNodes(src, ctx, keyBase) {
|
|
|
5203
5241
|
}
|
|
5204
5242
|
if (!best) break;
|
|
5205
5243
|
const { kind, m } = best;
|
|
5206
|
-
if (m.index > 0) out.push(rest.slice(0, m.index));
|
|
5244
|
+
if (m.index > 0) out.push(d(rest.slice(0, m.index)));
|
|
5207
5245
|
const g = (i) => m[i];
|
|
5208
|
-
if (kind === "code") out.push(/* @__PURE__ */ jsx54("code", { className: "fd-md-code", children: g(1) }, key()));
|
|
5246
|
+
if (kind === "code") out.push(/* @__PURE__ */ jsx54("code", { className: "fd-md-code", children: showEscapesRaw(g(1)) }, key()));
|
|
5209
5247
|
else if (kind === "image") {
|
|
5210
|
-
const src2 = safeHref(g(2));
|
|
5211
|
-
out.push(ctx.allowImages && src2 ? /* @__PURE__ */ jsx54("img", { className: "fd-md-img", src: src2, alt: g(1) || "", title: g(3)
|
|
5248
|
+
const src2 = safeHref(d(g(2)));
|
|
5249
|
+
out.push(ctx.allowImages && src2 ? /* @__PURE__ */ jsx54("img", { className: "fd-md-img", src: src2, alt: d(g(1) || ""), title: g(3) ? d(g(3)) : void 0, loading: "lazy" }, key()) : /* @__PURE__ */ jsx54("span", { className: "fd-md-imgalt", children: d(g(1) || "image") }, key()));
|
|
5212
5250
|
} else if (kind === "link") {
|
|
5213
|
-
const href = safeHref(g(2));
|
|
5214
|
-
out.push(href ? /* @__PURE__ */ jsx54("a", { href, title: g(3)
|
|
5251
|
+
const href = safeHref(d(g(2)));
|
|
5252
|
+
out.push(href ? /* @__PURE__ */ jsx54("a", { href, title: g(3) ? d(g(3)) : void 0, target: /^https?:/i.test(href) ? "_blank" : void 0, rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: inlineNodes(g(1), ctx, key()) }, key()) : /* @__PURE__ */ jsx54("span", { children: d(g(1)) }, key()));
|
|
5215
5253
|
} else if (kind === "cite") {
|
|
5216
|
-
out.push(ctx.renderCitation ? /* @__PURE__ */ jsx54(React35.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ jsx54("sup", { className: "fd-md-cite", children: g(1) }, key()));
|
|
5254
|
+
out.push(ctx.renderCitation ? /* @__PURE__ */ jsx54(React35.Fragment, { children: ctx.renderCitation(d(g(1))) }, key()) : /* @__PURE__ */ jsx54("sup", { className: "fd-md-cite", children: d(g(1)) }, key()));
|
|
5217
5255
|
} else if (kind === "strongem") out.push(/* @__PURE__ */ jsx54("strong", { children: /* @__PURE__ */ jsx54("em", { children: inlineNodes(g(1), ctx, key()) }) }, key()));
|
|
5218
5256
|
else if (kind === "strong") out.push(/* @__PURE__ */ jsx54("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
5219
5257
|
else if (kind === "em") out.push(/* @__PURE__ */ jsx54("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
5220
5258
|
else if (kind === "del") out.push(/* @__PURE__ */ jsx54("del", { children: inlineNodes(g(1), ctx, key()) }, key()));
|
|
5221
5259
|
else if (kind === "autolink" || kind === "bare") {
|
|
5222
|
-
const href = safeHref(g(1));
|
|
5223
|
-
out.push(href ? /* @__PURE__ */ jsx54("a", { href, target: "_blank", rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: g(1).replace(/^mailto:/, "") }, key()) : g(1));
|
|
5260
|
+
const href = safeHref(d(g(1)));
|
|
5261
|
+
out.push(href ? /* @__PURE__ */ jsx54("a", { href, target: "_blank", rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: d(g(1)).replace(/^mailto:/, "") }, key()) : d(g(1)));
|
|
5224
5262
|
}
|
|
5225
5263
|
rest = rest.slice(m.index + m[0].length);
|
|
5226
5264
|
}
|
|
5227
|
-
if (rest) out.push(rest);
|
|
5265
|
+
if (rest) out.push(d(rest));
|
|
5228
5266
|
return out;
|
|
5229
5267
|
}
|
|
5230
5268
|
var RE = {
|
|
@@ -5236,7 +5274,26 @@ var RE = {
|
|
|
5236
5274
|
task: /^\[([ xX])\]\s+(.*)$/,
|
|
5237
5275
|
tableSep: /^\s*\|?[\s:|-]*-[\s:|-]*\|?\s*$/
|
|
5238
5276
|
};
|
|
5239
|
-
var splitRow = (line) =>
|
|
5277
|
+
var splitRow = (line) => {
|
|
5278
|
+
const t = line.trim();
|
|
5279
|
+
const cells = [];
|
|
5280
|
+
let cur = "";
|
|
5281
|
+
for (let i = t.startsWith("|") ? 1 : 0; i < t.length; i++) {
|
|
5282
|
+
const c = t[i];
|
|
5283
|
+
if (c === "\\" && i + 1 < t.length) {
|
|
5284
|
+
cur += c + t[++i];
|
|
5285
|
+
continue;
|
|
5286
|
+
}
|
|
5287
|
+
if (c === "|") {
|
|
5288
|
+
cells.push(cur.trim());
|
|
5289
|
+
cur = "";
|
|
5290
|
+
continue;
|
|
5291
|
+
}
|
|
5292
|
+
cur += c;
|
|
5293
|
+
}
|
|
5294
|
+
if (cur.trim() || !t.endsWith("|")) cells.push(cur.trim());
|
|
5295
|
+
return cells;
|
|
5296
|
+
};
|
|
5240
5297
|
function parseBlocks(src) {
|
|
5241
5298
|
const lines = String(src == null ? "" : src).replace(/\r\n?/g, "\n").split("\n");
|
|
5242
5299
|
const blocks = [];
|
|
@@ -5368,6 +5425,7 @@ function renderBlocks(blocks, ctx, path) {
|
|
|
5368
5425
|
}
|
|
5369
5426
|
});
|
|
5370
5427
|
}
|
|
5428
|
+
var mdClass = (base, size, tone, className) => [base, size && `${base}--${size}`, tone === "muted" && `${base}--muted`, className].filter(Boolean).join(" ");
|
|
5371
5429
|
function Markdown({
|
|
5372
5430
|
source = "",
|
|
5373
5431
|
className = "",
|
|
@@ -5375,14 +5433,16 @@ function Markdown({
|
|
|
5375
5433
|
allowImages = true,
|
|
5376
5434
|
headingOffset = 0,
|
|
5377
5435
|
renderCitation,
|
|
5378
|
-
onLinkClick
|
|
5436
|
+
onLinkClick,
|
|
5437
|
+
size = "body",
|
|
5438
|
+
tone = "default"
|
|
5379
5439
|
}) {
|
|
5380
5440
|
const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
|
|
5381
5441
|
const blocks = React35.useMemo(() => parseBlocks(source), [source]);
|
|
5382
|
-
return /* @__PURE__ */ jsx54("div", { className:
|
|
5442
|
+
return /* @__PURE__ */ jsx54("div", { className: mdClass("fd-md", size, tone, className), children: renderBlocks(blocks, ctx, "b") });
|
|
5383
5443
|
}
|
|
5384
|
-
function MarkdownInline({ source = "", className = "", onLinkClick }) {
|
|
5385
|
-
return /* @__PURE__ */ jsx54("span", { className:
|
|
5444
|
+
function MarkdownInline({ source = "", className = "", onLinkClick, size, tone }) {
|
|
5445
|
+
return /* @__PURE__ */ jsx54("span", { className: mdClass("fd-md-inline", size, tone, className), children: inlineNodes(source, { allowImages: false, onLinkClick }, "i") });
|
|
5386
5446
|
}
|
|
5387
5447
|
function markdownToText(src) {
|
|
5388
5448
|
return String(src == null ? "" : src).replace(/```[\w+#-]*\n?([\s\S]*?)```/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").replace(/^\s{0,3}#{1,6}\s+/gm, "").replace(/\*\*\*([^*]+)\*\*\*|\*\*([^*]+)\*\*|__([^_]+)__/g, "$1$2$3").replace(/(^|\W)[*_]([^*_\n]+)[*_](\W|$)/g, "$1$2$3").replace(/~~([^~]+)~~/g, "$1").replace(/^\s*>\s?/gm, "").trim();
|
|
@@ -6646,14 +6706,17 @@ function Checkbox({ label, description, card = false, indeterminate = false, cla
|
|
|
6646
6706
|
|
|
6647
6707
|
// src/components/forms/Radio.tsx
|
|
6648
6708
|
import { jsx as jsx69, jsxs as jsxs58 } from "react/jsx-runtime";
|
|
6649
|
-
function Radio({ label, description, card = false, className = "", ...rest }) {
|
|
6709
|
+
function Radio({ label, description, badge, card = false, className = "", ...rest }) {
|
|
6650
6710
|
return /* @__PURE__ */ jsxs58("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
6651
6711
|
/* @__PURE__ */ jsxs58("span", { className: "fd-choice-input", children: [
|
|
6652
6712
|
/* @__PURE__ */ jsx69("input", { type: "radio", ...rest }),
|
|
6653
6713
|
/* @__PURE__ */ jsx69("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ jsx69("span", { className: "fd-choice-dot" }) })
|
|
6654
6714
|
] }),
|
|
6655
6715
|
/* @__PURE__ */ jsxs58("span", { className: "fd-choice-text", children: [
|
|
6656
|
-
/* @__PURE__ */
|
|
6716
|
+
/* @__PURE__ */ jsxs58("span", { className: "fd-choice-title", children: [
|
|
6717
|
+
label,
|
|
6718
|
+
badge ? /* @__PURE__ */ jsx69("span", { className: "fd-choice-badge", children: badge }) : null
|
|
6719
|
+
] }),
|
|
6657
6720
|
description ? /* @__PURE__ */ jsx69("span", { className: "fd-choice-desc", children: description }) : null
|
|
6658
6721
|
] })
|
|
6659
6722
|
] });
|
|
@@ -8245,17 +8308,49 @@ function CodeEditor({
|
|
|
8245
8308
|
] });
|
|
8246
8309
|
}
|
|
8247
8310
|
|
|
8311
|
+
// src/components/forms/RadioGroup.tsx
|
|
8312
|
+
import * as React53 from "react";
|
|
8313
|
+
import { jsx as jsx79, jsxs as jsxs68 } from "react/jsx-runtime";
|
|
8314
|
+
function RadioGroup({ label, options, value, onChange, card = false, disabled = false, name, className = "" }) {
|
|
8315
|
+
const autoName = React53.useId();
|
|
8316
|
+
const labelId = React53.useId();
|
|
8317
|
+
return /* @__PURE__ */ jsxs68("div", { role: "radiogroup", "aria-labelledby": labelId, "aria-disabled": disabled || void 0, className: ["fd-radiogroup", className].filter(Boolean).join(" "), children: [
|
|
8318
|
+
/* @__PURE__ */ jsx79("span", { id: labelId, className: "fd-radiogroup-label", children: label }),
|
|
8319
|
+
options.map((o) => /* @__PURE__ */ jsx79(
|
|
8320
|
+
Radio,
|
|
8321
|
+
{
|
|
8322
|
+
card,
|
|
8323
|
+
name: name ?? autoName,
|
|
8324
|
+
value: o.value,
|
|
8325
|
+
label: o.label,
|
|
8326
|
+
description: o.description,
|
|
8327
|
+
badge: o.badge,
|
|
8328
|
+
checked: o.value === value,
|
|
8329
|
+
disabled: disabled || o.disabled,
|
|
8330
|
+
onChange: () => onChange(o.value)
|
|
8331
|
+
},
|
|
8332
|
+
o.value
|
|
8333
|
+
))
|
|
8334
|
+
] });
|
|
8335
|
+
}
|
|
8336
|
+
|
|
8337
|
+
// src/components/forms/Fieldset.tsx
|
|
8338
|
+
import { jsx as jsx80 } from "react/jsx-runtime";
|
|
8339
|
+
function Fieldset({ busy = false, className = "", ...rest }) {
|
|
8340
|
+
return /* @__PURE__ */ jsx80("fieldset", { disabled: busy, "aria-busy": busy || void 0, className: ["fd-fieldset", className].filter(Boolean).join(" "), ...rest });
|
|
8341
|
+
}
|
|
8342
|
+
|
|
8248
8343
|
// src/components/platform/AccountMenu.tsx
|
|
8249
|
-
import * as
|
|
8344
|
+
import * as React55 from "react";
|
|
8250
8345
|
|
|
8251
8346
|
// src/kits/sessionContext.tsx
|
|
8252
|
-
import * as
|
|
8253
|
-
var SessionContext =
|
|
8347
|
+
import * as React54 from "react";
|
|
8348
|
+
var SessionContext = React54.createContext(null);
|
|
8254
8349
|
function SessionProvider({ value, children }) {
|
|
8255
|
-
return
|
|
8350
|
+
return React54.createElement(SessionContext.Provider, { value }, children);
|
|
8256
8351
|
}
|
|
8257
8352
|
function useSessionContext() {
|
|
8258
|
-
const ctx =
|
|
8353
|
+
const ctx = React54.useContext(SessionContext);
|
|
8259
8354
|
if (!ctx) {
|
|
8260
8355
|
throw new Error(
|
|
8261
8356
|
"useSessionContext() was called outside a <SessionProvider>. Wrap your app root in <SessionProvider value={...}> with your real session, or \u2014 in the docs site or a demo \u2014 in <DemoSessionProvider>, before rendering AccountMenu, Gate, ProfilePage or AppSwitcher."
|
|
@@ -8265,11 +8360,11 @@ function useSessionContext() {
|
|
|
8265
8360
|
}
|
|
8266
8361
|
|
|
8267
8362
|
// src/components/platform/AccountMenu.tsx
|
|
8268
|
-
import { Fragment as Fragment19, jsx as
|
|
8363
|
+
import { Fragment as Fragment19, jsx as jsx81, jsxs as jsxs69 } from "react/jsx-runtime";
|
|
8269
8364
|
var DEFAULT_LINKS = [];
|
|
8270
8365
|
var DEFAULT_GROUPS = [];
|
|
8271
8366
|
function Item({ item, onPick }) {
|
|
8272
|
-
return /* @__PURE__ */
|
|
8367
|
+
return /* @__PURE__ */ jsxs69(
|
|
8273
8368
|
"button",
|
|
8274
8369
|
{
|
|
8275
8370
|
type: "button",
|
|
@@ -8277,9 +8372,9 @@ function Item({ item, onPick }) {
|
|
|
8277
8372
|
className: "fd-acct-item",
|
|
8278
8373
|
onClick: () => onPick(item),
|
|
8279
8374
|
children: [
|
|
8280
|
-
item.icon ? /* @__PURE__ */
|
|
8281
|
-
/* @__PURE__ */
|
|
8282
|
-
item.badge ? /* @__PURE__ */
|
|
8375
|
+
item.icon ? /* @__PURE__ */ jsx81("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
|
|
8376
|
+
/* @__PURE__ */ jsx81("span", { style: { flex: 1 }, children: item.label }),
|
|
8377
|
+
item.badge ? /* @__PURE__ */ jsx81(Badge, { tone: "neutral", children: item.badge }) : null
|
|
8283
8378
|
]
|
|
8284
8379
|
}
|
|
8285
8380
|
);
|
|
@@ -8295,11 +8390,11 @@ function AccountMenu({
|
|
|
8295
8390
|
...rest
|
|
8296
8391
|
}) {
|
|
8297
8392
|
const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
|
|
8298
|
-
const [open2, setOpen] =
|
|
8299
|
-
const [switching, setSwitching] =
|
|
8300
|
-
const [signingOut, setSigningOut] =
|
|
8301
|
-
const [signOutError, setSignOutError] =
|
|
8302
|
-
const ref =
|
|
8393
|
+
const [open2, setOpen] = React55.useState(false);
|
|
8394
|
+
const [switching, setSwitching] = React55.useState(false);
|
|
8395
|
+
const [signingOut, setSigningOut] = React55.useState(false);
|
|
8396
|
+
const [signOutError, setSignOutError] = React55.useState(null);
|
|
8397
|
+
const ref = React55.useRef(null);
|
|
8303
8398
|
const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
|
|
8304
8399
|
const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || !pending && can2(l.perm)) })).filter((g) => g.links.length);
|
|
8305
8400
|
const closeMenu = () => {
|
|
@@ -8327,8 +8422,8 @@ function AccountMenu({
|
|
|
8327
8422
|
}
|
|
8328
8423
|
};
|
|
8329
8424
|
const showSwitcher = allowUserSwitch && !!demo;
|
|
8330
|
-
return /* @__PURE__ */
|
|
8331
|
-
/* @__PURE__ */
|
|
8425
|
+
return /* @__PURE__ */ jsxs69(Fragment19, { children: [
|
|
8426
|
+
/* @__PURE__ */ jsxs69(
|
|
8332
8427
|
"button",
|
|
8333
8428
|
{
|
|
8334
8429
|
type: "button",
|
|
@@ -8340,12 +8435,12 @@ function AccountMenu({
|
|
|
8340
8435
|
onClick: () => open2 ? closeMenu() : setOpen(true),
|
|
8341
8436
|
...rest,
|
|
8342
8437
|
children: [
|
|
8343
|
-
/* @__PURE__ */
|
|
8344
|
-
/* @__PURE__ */
|
|
8438
|
+
/* @__PURE__ */ jsx81(Avatar, { name: user.name, size: "sm" }),
|
|
8439
|
+
/* @__PURE__ */ jsx81("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
|
|
8345
8440
|
]
|
|
8346
8441
|
}
|
|
8347
8442
|
),
|
|
8348
|
-
/* @__PURE__ */
|
|
8443
|
+
/* @__PURE__ */ jsx81(
|
|
8349
8444
|
Popover,
|
|
8350
8445
|
{
|
|
8351
8446
|
open: open2,
|
|
@@ -8353,27 +8448,27 @@ function AccountMenu({
|
|
|
8353
8448
|
onClose: closeMenu,
|
|
8354
8449
|
placement: "bottom-end",
|
|
8355
8450
|
width: 272,
|
|
8356
|
-
children: /* @__PURE__ */
|
|
8357
|
-
/* @__PURE__ */
|
|
8358
|
-
/* @__PURE__ */
|
|
8359
|
-
/* @__PURE__ */
|
|
8360
|
-
/* @__PURE__ */
|
|
8361
|
-
/* @__PURE__ */
|
|
8451
|
+
children: /* @__PURE__ */ jsxs69("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
|
|
8452
|
+
/* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
8453
|
+
/* @__PURE__ */ jsx81(Avatar, { name: user.name }),
|
|
8454
|
+
/* @__PURE__ */ jsxs69("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
|
|
8455
|
+
/* @__PURE__ */ jsx81("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
|
|
8456
|
+
/* @__PURE__ */ jsx81("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
|
|
8362
8457
|
] })
|
|
8363
8458
|
] }),
|
|
8364
|
-
showRoles && roles.length ? /* @__PURE__ */
|
|
8365
|
-
visibleLinks.length ? /* @__PURE__ */
|
|
8366
|
-
visibleGroups.map((g) => /* @__PURE__ */
|
|
8367
|
-
/* @__PURE__ */
|
|
8368
|
-
g.links.map((l) => /* @__PURE__ */
|
|
8459
|
+
showRoles && roles.length ? /* @__PURE__ */ jsx81("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ jsx81(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
|
|
8460
|
+
visibleLinks.length ? /* @__PURE__ */ jsx81("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ jsx81(Item, { item: l, onPick: pick }, l.id)) }) : null,
|
|
8461
|
+
visibleGroups.map((g) => /* @__PURE__ */ jsxs69("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
8462
|
+
/* @__PURE__ */ jsx81("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
|
|
8463
|
+
g.links.map((l) => /* @__PURE__ */ jsx81(Item, { item: l, onPick: pick }, l.id))
|
|
8369
8464
|
] }, g.label)),
|
|
8370
|
-
showSwitcher && demo ? /* @__PURE__ */
|
|
8371
|
-
/* @__PURE__ */
|
|
8372
|
-
/* @__PURE__ */
|
|
8373
|
-
/* @__PURE__ */
|
|
8374
|
-
/* @__PURE__ */
|
|
8465
|
+
showSwitcher && demo ? /* @__PURE__ */ jsxs69("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
8466
|
+
/* @__PURE__ */ jsxs69("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
|
|
8467
|
+
/* @__PURE__ */ jsx81("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
|
|
8468
|
+
/* @__PURE__ */ jsx81("span", { style: { flex: 1 }, children: "View as another member" }),
|
|
8469
|
+
/* @__PURE__ */ jsx81("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
|
|
8375
8470
|
] }),
|
|
8376
|
-
switching ? /* @__PURE__ */
|
|
8471
|
+
switching ? /* @__PURE__ */ jsx81("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ jsxs69(
|
|
8377
8472
|
"button",
|
|
8378
8473
|
{
|
|
8379
8474
|
type: "button",
|
|
@@ -8385,19 +8480,19 @@ function AccountMenu({
|
|
|
8385
8480
|
setSwitching(false);
|
|
8386
8481
|
},
|
|
8387
8482
|
children: [
|
|
8388
|
-
/* @__PURE__ */
|
|
8389
|
-
/* @__PURE__ */
|
|
8390
|
-
/* @__PURE__ */
|
|
8391
|
-
u.roles ? /* @__PURE__ */
|
|
8483
|
+
/* @__PURE__ */ jsx81(Avatar, { name: u.name, size: "sm" }),
|
|
8484
|
+
/* @__PURE__ */ jsxs69("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
|
|
8485
|
+
/* @__PURE__ */ jsx81("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
|
|
8486
|
+
u.roles ? /* @__PURE__ */ jsx81("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
|
|
8392
8487
|
] }),
|
|
8393
|
-
u.id === user.id ? /* @__PURE__ */
|
|
8488
|
+
u.id === user.id ? /* @__PURE__ */ jsx81("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
|
|
8394
8489
|
]
|
|
8395
8490
|
},
|
|
8396
8491
|
u.id
|
|
8397
8492
|
)) }) : null
|
|
8398
8493
|
] }) : null,
|
|
8399
|
-
/* @__PURE__ */
|
|
8400
|
-
/* @__PURE__ */
|
|
8494
|
+
/* @__PURE__ */ jsxs69("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
8495
|
+
/* @__PURE__ */ jsxs69(
|
|
8401
8496
|
"button",
|
|
8402
8497
|
{
|
|
8403
8498
|
type: "button",
|
|
@@ -8407,14 +8502,14 @@ function AccountMenu({
|
|
|
8407
8502
|
disabled: signingOut,
|
|
8408
8503
|
onClick: signOut,
|
|
8409
8504
|
children: [
|
|
8410
|
-
signingOut ? /* @__PURE__ */
|
|
8411
|
-
/* @__PURE__ */
|
|
8505
|
+
signingOut ? /* @__PURE__ */ jsx81(Spinner, { size: "sm" }) : /* @__PURE__ */ jsx81("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
|
|
8506
|
+
/* @__PURE__ */ jsx81("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
|
|
8412
8507
|
]
|
|
8413
8508
|
}
|
|
8414
8509
|
),
|
|
8415
|
-
signOutError ? /* @__PURE__ */
|
|
8416
|
-
/* @__PURE__ */
|
|
8417
|
-
/* @__PURE__ */
|
|
8510
|
+
signOutError ? /* @__PURE__ */ jsxs69("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
|
|
8511
|
+
/* @__PURE__ */ jsx81("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
|
|
8512
|
+
/* @__PURE__ */ jsx81("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
|
|
8418
8513
|
] }) : null
|
|
8419
8514
|
] })
|
|
8420
8515
|
] })
|
|
@@ -8424,13 +8519,13 @@ function AccountMenu({
|
|
|
8424
8519
|
}
|
|
8425
8520
|
|
|
8426
8521
|
// src/components/platform/AppSwitcher.tsx
|
|
8427
|
-
import * as
|
|
8428
|
-
import { jsx as
|
|
8522
|
+
import * as React56 from "react";
|
|
8523
|
+
import { jsx as jsx82, jsxs as jsxs70 } from "react/jsx-runtime";
|
|
8429
8524
|
function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
8430
8525
|
const { apps: contextApps } = useSessionContext();
|
|
8431
8526
|
const apps = appsProp ?? contextApps ?? [];
|
|
8432
|
-
const [open2, setOpen] =
|
|
8433
|
-
const anchorRef =
|
|
8527
|
+
const [open2, setOpen] = React56.useState(false);
|
|
8528
|
+
const anchorRef = React56.useRef(null);
|
|
8434
8529
|
if (!apps.length) return null;
|
|
8435
8530
|
const items = apps.map((app) => ({
|
|
8436
8531
|
id: app.key,
|
|
@@ -8444,8 +8539,8 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
8444
8539
|
window.location.href = app.url;
|
|
8445
8540
|
}
|
|
8446
8541
|
}));
|
|
8447
|
-
return /* @__PURE__ */
|
|
8448
|
-
/* @__PURE__ */
|
|
8542
|
+
return /* @__PURE__ */ jsxs70(React56.Fragment, { children: [
|
|
8543
|
+
/* @__PURE__ */ jsx82("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx82(
|
|
8449
8544
|
IconButton,
|
|
8450
8545
|
{
|
|
8451
8546
|
icon: "squares-four",
|
|
@@ -8455,7 +8550,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
8455
8550
|
onClick: () => setOpen((v) => !v)
|
|
8456
8551
|
}
|
|
8457
8552
|
) }),
|
|
8458
|
-
/* @__PURE__ */
|
|
8553
|
+
/* @__PURE__ */ jsx82(
|
|
8459
8554
|
Popover,
|
|
8460
8555
|
{
|
|
8461
8556
|
open: open2,
|
|
@@ -8466,17 +8561,17 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
8466
8561
|
label: "All flytedesk apps",
|
|
8467
8562
|
width: 240,
|
|
8468
8563
|
maxHeight: 360,
|
|
8469
|
-
children: /* @__PURE__ */
|
|
8564
|
+
children: /* @__PURE__ */ jsx82(Menu, { items, onClose: () => setOpen(false) })
|
|
8470
8565
|
}
|
|
8471
8566
|
)
|
|
8472
8567
|
] });
|
|
8473
8568
|
}
|
|
8474
8569
|
|
|
8475
8570
|
// src/components/platform/AppearanceMenu.tsx
|
|
8476
|
-
import * as
|
|
8571
|
+
import * as React59 from "react";
|
|
8477
8572
|
|
|
8478
8573
|
// src/kits/appearance.ts
|
|
8479
|
-
import * as
|
|
8574
|
+
import * as React57 from "react";
|
|
8480
8575
|
var DEFAULT_STORAGE_KEY = "fd-appearance";
|
|
8481
8576
|
var DEFAULT_PREFS = {
|
|
8482
8577
|
theme: "system",
|
|
@@ -8588,8 +8683,8 @@ function watchAppearance(store, root = document.documentElement) {
|
|
|
8588
8683
|
};
|
|
8589
8684
|
}
|
|
8590
8685
|
function useAppearancePrefs(store) {
|
|
8591
|
-
const prefs =
|
|
8592
|
-
const update =
|
|
8686
|
+
const prefs = React57.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
8687
|
+
const update = React57.useCallback(
|
|
8593
8688
|
(patch) => {
|
|
8594
8689
|
store.write({ ...store.getSnapshot(), ...patch });
|
|
8595
8690
|
},
|
|
@@ -8599,21 +8694,21 @@ function useAppearancePrefs(store) {
|
|
|
8599
8694
|
}
|
|
8600
8695
|
|
|
8601
8696
|
// src/components/platform/AppearanceProvider.tsx
|
|
8602
|
-
import * as
|
|
8603
|
-
import { jsx as
|
|
8604
|
-
var AppearanceStoreContext =
|
|
8697
|
+
import * as React58 from "react";
|
|
8698
|
+
import { jsx as jsx83 } from "react/jsx-runtime";
|
|
8699
|
+
var AppearanceStoreContext = React58.createContext(null);
|
|
8605
8700
|
function AppearanceProvider({ store, children }) {
|
|
8606
|
-
|
|
8607
|
-
return /* @__PURE__ */
|
|
8701
|
+
React58.useLayoutEffect(() => watchAppearance(store), [store]);
|
|
8702
|
+
return /* @__PURE__ */ jsx83(AppearanceStoreContext.Provider, { value: store, children });
|
|
8608
8703
|
}
|
|
8609
8704
|
function useAppearanceStore() {
|
|
8610
|
-
const store =
|
|
8705
|
+
const store = React58.useContext(AppearanceStoreContext);
|
|
8611
8706
|
if (!store) throw new Error("AppearanceMenu and useAppearanceStore must be rendered inside an <AppearanceProvider>.");
|
|
8612
8707
|
return store;
|
|
8613
8708
|
}
|
|
8614
8709
|
|
|
8615
8710
|
// src/components/platform/AppearanceMenu.tsx
|
|
8616
|
-
import { jsx as
|
|
8711
|
+
import { jsx as jsx84, jsxs as jsxs71 } from "react/jsx-runtime";
|
|
8617
8712
|
var THEME_OPTIONS = [
|
|
8618
8713
|
{ value: "light", label: "Light" },
|
|
8619
8714
|
{ value: "dark", label: "Dark" },
|
|
@@ -8627,11 +8722,11 @@ var TEXT_SCALE_OPTIONS = [
|
|
|
8627
8722
|
];
|
|
8628
8723
|
function AppearanceMenu({ className = "" }) {
|
|
8629
8724
|
const [prefs, update] = useAppearancePrefs(useAppearanceStore());
|
|
8630
|
-
const [open2, setOpen] =
|
|
8631
|
-
const anchorRef =
|
|
8725
|
+
const [open2, setOpen] = React59.useState(false);
|
|
8726
|
+
const anchorRef = React59.useRef(null);
|
|
8632
8727
|
const patch = (p) => update(p);
|
|
8633
|
-
return /* @__PURE__ */
|
|
8634
|
-
/* @__PURE__ */
|
|
8728
|
+
return /* @__PURE__ */ jsxs71(React59.Fragment, { children: [
|
|
8729
|
+
/* @__PURE__ */ jsx84("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx84(
|
|
8635
8730
|
IconButton,
|
|
8636
8731
|
{
|
|
8637
8732
|
icon: "circle-half",
|
|
@@ -8639,7 +8734,7 @@ function AppearanceMenu({ className = "" }) {
|
|
|
8639
8734
|
onClick: () => setOpen((v) => !v)
|
|
8640
8735
|
}
|
|
8641
8736
|
) }),
|
|
8642
|
-
/* @__PURE__ */
|
|
8737
|
+
/* @__PURE__ */ jsx84(
|
|
8643
8738
|
Popover,
|
|
8644
8739
|
{
|
|
8645
8740
|
open: open2,
|
|
@@ -8649,10 +8744,10 @@ function AppearanceMenu({ className = "" }) {
|
|
|
8649
8744
|
padded: true,
|
|
8650
8745
|
width: 260,
|
|
8651
8746
|
label: "Appearance settings",
|
|
8652
|
-
children: /* @__PURE__ */
|
|
8653
|
-
/* @__PURE__ */
|
|
8654
|
-
/* @__PURE__ */
|
|
8655
|
-
/* @__PURE__ */
|
|
8747
|
+
children: /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
|
|
8748
|
+
/* @__PURE__ */ jsxs71("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
8749
|
+
/* @__PURE__ */ jsx84("span", { className: "fd-field-label", children: "Theme" }),
|
|
8750
|
+
/* @__PURE__ */ jsx84(
|
|
8656
8751
|
SegmentedControl,
|
|
8657
8752
|
{
|
|
8658
8753
|
options: THEME_OPTIONS,
|
|
@@ -8662,9 +8757,9 @@ function AppearanceMenu({ className = "" }) {
|
|
|
8662
8757
|
}
|
|
8663
8758
|
)
|
|
8664
8759
|
] }),
|
|
8665
|
-
/* @__PURE__ */
|
|
8666
|
-
/* @__PURE__ */
|
|
8667
|
-
/* @__PURE__ */
|
|
8760
|
+
/* @__PURE__ */ jsxs71("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
8761
|
+
/* @__PURE__ */ jsx84("span", { className: "fd-field-label", children: "Text size" }),
|
|
8762
|
+
/* @__PURE__ */ jsx84(
|
|
8668
8763
|
SegmentedControl,
|
|
8669
8764
|
{
|
|
8670
8765
|
options: TEXT_SCALE_OPTIONS,
|
|
@@ -8674,7 +8769,7 @@ function AppearanceMenu({ className = "" }) {
|
|
|
8674
8769
|
}
|
|
8675
8770
|
)
|
|
8676
8771
|
] }),
|
|
8677
|
-
/* @__PURE__ */
|
|
8772
|
+
/* @__PURE__ */ jsx84(
|
|
8678
8773
|
Switch,
|
|
8679
8774
|
{
|
|
8680
8775
|
label: "High contrast",
|
|
@@ -8683,7 +8778,7 @@ function AppearanceMenu({ className = "" }) {
|
|
|
8683
8778
|
onChange: (e) => patch({ highContrast: e.target.checked })
|
|
8684
8779
|
}
|
|
8685
8780
|
),
|
|
8686
|
-
/* @__PURE__ */
|
|
8781
|
+
/* @__PURE__ */ jsx84(
|
|
8687
8782
|
Switch,
|
|
8688
8783
|
{
|
|
8689
8784
|
label: "Reduce motion",
|
|
@@ -8699,14 +8794,14 @@ function AppearanceMenu({ className = "" }) {
|
|
|
8699
8794
|
}
|
|
8700
8795
|
|
|
8701
8796
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
8702
|
-
import * as
|
|
8703
|
-
import { jsx as
|
|
8797
|
+
import * as React60 from "react";
|
|
8798
|
+
import { jsx as jsx85, jsxs as jsxs72 } from "react/jsx-runtime";
|
|
8704
8799
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
8705
8800
|
function Json({ obj }) {
|
|
8706
|
-
return /* @__PURE__ */
|
|
8801
|
+
return /* @__PURE__ */ jsx85("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
8707
8802
|
}
|
|
8708
8803
|
function Endpoint({ s, onRequest }) {
|
|
8709
|
-
const [tried, setTried] =
|
|
8804
|
+
const [tried, setTried] = React60.useState(null);
|
|
8710
8805
|
const run = async () => {
|
|
8711
8806
|
setTried("busy");
|
|
8712
8807
|
const t0 = (window.performance || Date).now();
|
|
@@ -8717,50 +8812,50 @@ function Endpoint({ s, onRequest }) {
|
|
|
8717
8812
|
setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
|
|
8718
8813
|
}
|
|
8719
8814
|
};
|
|
8720
|
-
return /* @__PURE__ */
|
|
8721
|
-
/* @__PURE__ */
|
|
8722
|
-
/* @__PURE__ */
|
|
8723
|
-
/* @__PURE__ */
|
|
8724
|
-
s.isList ? /* @__PURE__ */
|
|
8725
|
-
/* @__PURE__ */
|
|
8726
|
-
/* @__PURE__ */
|
|
8815
|
+
return /* @__PURE__ */ jsx85(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
8816
|
+
/* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
|
|
8817
|
+
/* @__PURE__ */ jsx85(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
|
|
8818
|
+
/* @__PURE__ */ jsx85("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
|
|
8819
|
+
s.isList ? /* @__PURE__ */ jsx85(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
|
|
8820
|
+
/* @__PURE__ */ jsx85("span", { style: { flex: 1 } }),
|
|
8821
|
+
/* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
8727
8822
|
s.latency[0],
|
|
8728
8823
|
"\u2013",
|
|
8729
8824
|
s.latency[1],
|
|
8730
8825
|
"ms"
|
|
8731
8826
|
] }),
|
|
8732
|
-
/* @__PURE__ */
|
|
8827
|
+
/* @__PURE__ */ jsx85(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
|
|
8733
8828
|
] }),
|
|
8734
|
-
/* @__PURE__ */
|
|
8735
|
-
/* @__PURE__ */
|
|
8736
|
-
/* @__PURE__ */
|
|
8737
|
-
/* @__PURE__ */
|
|
8738
|
-
s.usedBy && s.usedBy.length ? /* @__PURE__ */
|
|
8829
|
+
/* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
|
|
8830
|
+
/* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8831
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
|
|
8832
|
+
/* @__PURE__ */ jsx85("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
|
|
8833
|
+
s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx85("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx85(Tag, { children: u }, u)) }) : null
|
|
8739
8834
|
] }),
|
|
8740
|
-
/* @__PURE__ */
|
|
8741
|
-
s.request ? /* @__PURE__ */
|
|
8742
|
-
/* @__PURE__ */
|
|
8743
|
-
/* @__PURE__ */
|
|
8835
|
+
/* @__PURE__ */ jsxs72("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
|
|
8836
|
+
s.request ? /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8837
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Request body" }),
|
|
8838
|
+
/* @__PURE__ */ jsx85(Json, { obj: s.request })
|
|
8744
8839
|
] }) : null,
|
|
8745
|
-
s.query ? /* @__PURE__ */
|
|
8746
|
-
/* @__PURE__ */
|
|
8747
|
-
/* @__PURE__ */
|
|
8840
|
+
s.query ? /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8841
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Query" }),
|
|
8842
|
+
/* @__PURE__ */ jsx85(Json, { obj: s.query })
|
|
8748
8843
|
] }) : null,
|
|
8749
|
-
/* @__PURE__ */
|
|
8750
|
-
/* @__PURE__ */
|
|
8751
|
-
/* @__PURE__ */
|
|
8844
|
+
/* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8845
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Response 200" }),
|
|
8846
|
+
/* @__PURE__ */ jsx85(Json, { obj: s.response })
|
|
8752
8847
|
] })
|
|
8753
8848
|
] }),
|
|
8754
|
-
s.notes ? /* @__PURE__ */
|
|
8755
|
-
tried && tried !== "busy" ? /* @__PURE__ */
|
|
8756
|
-
/* @__PURE__ */
|
|
8757
|
-
/* @__PURE__ */
|
|
8758
|
-
/* @__PURE__ */
|
|
8849
|
+
s.notes ? /* @__PURE__ */ jsx85(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
|
|
8850
|
+
tried && tried !== "busy" ? /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8851
|
+
/* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
8852
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
|
|
8853
|
+
/* @__PURE__ */ jsxs72(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
|
|
8759
8854
|
tried.ms,
|
|
8760
8855
|
"ms"
|
|
8761
8856
|
] })
|
|
8762
8857
|
] }),
|
|
8763
|
-
/* @__PURE__ */
|
|
8858
|
+
/* @__PURE__ */ jsx85(Json, { obj: tried.error ? { error: tried.error } : tried.data })
|
|
8764
8859
|
] }) : null
|
|
8765
8860
|
] })
|
|
8766
8861
|
] }) });
|
|
@@ -8779,58 +8874,58 @@ function ApiSpecBrowser({
|
|
|
8779
8874
|
className = "",
|
|
8780
8875
|
...rest
|
|
8781
8876
|
}) {
|
|
8782
|
-
const [q, setQ] =
|
|
8783
|
-
const [method, setMethod] =
|
|
8784
|
-
const [mod, setMod] =
|
|
8785
|
-
const [listOnly, setListOnly] =
|
|
8877
|
+
const [q, setQ] = React60.useState("");
|
|
8878
|
+
const [method, setMethod] = React60.useState(null);
|
|
8879
|
+
const [mod, setMod] = React60.useState(null);
|
|
8880
|
+
const [listOnly, setListOnly] = React60.useState(false);
|
|
8786
8881
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
8787
8882
|
const hits = spec.filter((s) => (!method || s.method === method) && (!listOnly || s.isList) && (!activeModule || activeModule.endpoints.indexOf(s.id) >= 0) && (!q || (s.path + " " + s.title + " " + s.purpose + " " + (s.usedBy || []).join(" ")).toLowerCase().includes(q.toLowerCase())));
|
|
8788
8883
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
8789
8884
|
const methods = [...new Set(spec.map((s) => s.method))];
|
|
8790
8885
|
const listCount = spec.filter((s) => s.isList).length;
|
|
8791
|
-
return /* @__PURE__ */
|
|
8792
|
-
/* @__PURE__ */
|
|
8793
|
-
kicker ? /* @__PURE__ */
|
|
8794
|
-
/* @__PURE__ */
|
|
8795
|
-
lede ? /* @__PURE__ */
|
|
8886
|
+
return /* @__PURE__ */ jsxs72("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
|
|
8887
|
+
/* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
8888
|
+
kicker ? /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: kicker }) : null,
|
|
8889
|
+
/* @__PURE__ */ jsx85("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
8890
|
+
lede ? /* @__PURE__ */ jsx85("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
|
|
8796
8891
|
] }),
|
|
8797
|
-
modules && modules.length ? /* @__PURE__ */
|
|
8798
|
-
/* @__PURE__ */
|
|
8799
|
-
/* @__PURE__ */
|
|
8800
|
-
/* @__PURE__ */
|
|
8892
|
+
modules && modules.length ? /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
8893
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
|
|
8894
|
+
/* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
8895
|
+
/* @__PURE__ */ jsxs72(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
|
|
8801
8896
|
"All screens ",
|
|
8802
|
-
/* @__PURE__ */
|
|
8897
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-mono", children: spec.length })
|
|
8803
8898
|
] }),
|
|
8804
|
-
modules.map((m) => /* @__PURE__ */
|
|
8899
|
+
modules.map((m) => /* @__PURE__ */ jsxs72(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
|
|
8805
8900
|
m.label,
|
|
8806
8901
|
" ",
|
|
8807
|
-
/* @__PURE__ */
|
|
8902
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-mono", children: m.endpoints.length })
|
|
8808
8903
|
] }, m.id))
|
|
8809
8904
|
] }),
|
|
8810
|
-
activeModule ? /* @__PURE__ */
|
|
8905
|
+
activeModule ? /* @__PURE__ */ jsx85(
|
|
8811
8906
|
Flag,
|
|
8812
8907
|
{
|
|
8813
8908
|
tone: "info",
|
|
8814
8909
|
statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
|
|
8815
8910
|
cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
|
|
8816
|
-
actions: /* @__PURE__ */
|
|
8911
|
+
actions: /* @__PURE__ */ jsx85(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
|
|
8817
8912
|
}
|
|
8818
8913
|
) : null
|
|
8819
8914
|
] }) : null,
|
|
8820
|
-
sourceNote ? /* @__PURE__ */
|
|
8821
|
-
/* @__PURE__ */
|
|
8822
|
-
/* @__PURE__ */
|
|
8823
|
-
methods.map((m) => /* @__PURE__ */
|
|
8915
|
+
sourceNote ? /* @__PURE__ */ jsx85(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
|
|
8916
|
+
/* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
8917
|
+
/* @__PURE__ */ jsx85(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
|
|
8918
|
+
methods.map((m) => /* @__PURE__ */ jsxs72(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
|
|
8824
8919
|
m,
|
|
8825
8920
|
" ",
|
|
8826
|
-
/* @__PURE__ */
|
|
8921
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
|
|
8827
8922
|
] }, m)),
|
|
8828
|
-
listCount ? /* @__PURE__ */
|
|
8923
|
+
listCount ? /* @__PURE__ */ jsxs72(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
|
|
8829
8924
|
"Paged lists ",
|
|
8830
|
-
/* @__PURE__ */
|
|
8925
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-mono", children: listCount })
|
|
8831
8926
|
] }) : null,
|
|
8832
|
-
/* @__PURE__ */
|
|
8833
|
-
/* @__PURE__ */
|
|
8927
|
+
/* @__PURE__ */ jsx85("span", { style: { flex: 1 } }),
|
|
8928
|
+
/* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted", children: [
|
|
8834
8929
|
hits.length,
|
|
8835
8930
|
" of ",
|
|
8836
8931
|
spec.length,
|
|
@@ -8838,31 +8933,31 @@ function ApiSpecBrowser({
|
|
|
8838
8933
|
listCount ? " \xB7 " + listCount + " paged" : ""
|
|
8839
8934
|
] })
|
|
8840
8935
|
] }),
|
|
8841
|
-
hits.length === 0 ? /* @__PURE__ */
|
|
8936
|
+
hits.length === 0 ? /* @__PURE__ */ jsx85(Card, { elevation: "flat", children: /* @__PURE__ */ jsx85("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
|
|
8842
8937
|
const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
|
|
8843
8938
|
if (!items.length) return null;
|
|
8844
|
-
return /* @__PURE__ */
|
|
8845
|
-
/* @__PURE__ */
|
|
8846
|
-
items.map((s) => /* @__PURE__ */
|
|
8939
|
+
return /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 12 }, children: [
|
|
8940
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-label-lg", children: g }),
|
|
8941
|
+
items.map((s) => /* @__PURE__ */ jsx85(Endpoint, { s, onRequest }, s.id))
|
|
8847
8942
|
] }, g);
|
|
8848
8943
|
}),
|
|
8849
|
-
conventions && conventions.length ? /* @__PURE__ */
|
|
8850
|
-
/* @__PURE__ */
|
|
8851
|
-
/* @__PURE__ */
|
|
8944
|
+
conventions && conventions.length ? /* @__PURE__ */ jsx85(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx85("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
|
|
8945
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
|
|
8946
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
|
|
8852
8947
|
] }, k)) }) }) : null,
|
|
8853
|
-
openQuestions && openQuestions.length ? /* @__PURE__ */
|
|
8854
|
-
/* @__PURE__ */
|
|
8855
|
-
/* @__PURE__ */
|
|
8856
|
-
/* @__PURE__ */
|
|
8857
|
-
/* @__PURE__ */
|
|
8948
|
+
openQuestions && openQuestions.length ? /* @__PURE__ */ jsx85(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx85("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
|
|
8949
|
+
/* @__PURE__ */ jsx85(Badge, { tone: "danger", children: id }),
|
|
8950
|
+
/* @__PURE__ */ jsxs72("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
|
|
8951
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
|
|
8952
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-body-sm fd-muted", children: why })
|
|
8858
8953
|
] })
|
|
8859
8954
|
] }, id)) }) }) : null
|
|
8860
8955
|
] });
|
|
8861
8956
|
}
|
|
8862
8957
|
|
|
8863
8958
|
// src/components/platform/ProfilePage.tsx
|
|
8864
|
-
import * as
|
|
8865
|
-
import { jsx as
|
|
8959
|
+
import * as React61 from "react";
|
|
8960
|
+
import { jsx as jsx86, jsxs as jsxs73 } from "react/jsx-runtime";
|
|
8866
8961
|
function fieldInitialValue(field, user) {
|
|
8867
8962
|
if (field.value) return field.value(user);
|
|
8868
8963
|
const raw = user[field.key];
|
|
@@ -8897,21 +8992,21 @@ function ProfilePage({
|
|
|
8897
8992
|
}) {
|
|
8898
8993
|
const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
|
|
8899
8994
|
const user = userProp || sessionUser;
|
|
8900
|
-
const initialFieldValues =
|
|
8995
|
+
const initialFieldValues = React61.useMemo(() => {
|
|
8901
8996
|
const values2 = {};
|
|
8902
8997
|
for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
|
|
8903
8998
|
return values2;
|
|
8904
8999
|
}, [user.id, fields]);
|
|
8905
|
-
const initialNotify =
|
|
9000
|
+
const initialNotify = React61.useMemo(() => {
|
|
8906
9001
|
const values2 = {};
|
|
8907
9002
|
for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
|
|
8908
9003
|
return values2;
|
|
8909
9004
|
}, [user.id, notifications]);
|
|
8910
|
-
const [values, setValues] =
|
|
8911
|
-
const [notify, setNotify] =
|
|
8912
|
-
const [saving, setSaving] =
|
|
8913
|
-
const [saved, setSaved] =
|
|
8914
|
-
const [prevUserId, setPrevUserId] =
|
|
9005
|
+
const [values, setValues] = React61.useState(initialFieldValues);
|
|
9006
|
+
const [notify, setNotify] = React61.useState(initialNotify);
|
|
9007
|
+
const [saving, setSaving] = React61.useState(false);
|
|
9008
|
+
const [saved, setSaved] = React61.useState(false);
|
|
9009
|
+
const [prevUserId, setPrevUserId] = React61.useState(user.id);
|
|
8915
9010
|
if (user.id !== prevUserId) {
|
|
8916
9011
|
setPrevUserId(user.id);
|
|
8917
9012
|
setValues(initialFieldValues);
|
|
@@ -8948,37 +9043,37 @@ function ProfilePage({
|
|
|
8948
9043
|
};
|
|
8949
9044
|
const displayName = fields.some((f) => f.key === "name") ? values.name || user.name : user.name;
|
|
8950
9045
|
const fieldGroups = groupFields(fields);
|
|
8951
|
-
return /* @__PURE__ */
|
|
8952
|
-
/* @__PURE__ */
|
|
8953
|
-
/* @__PURE__ */
|
|
8954
|
-
/* @__PURE__ */
|
|
8955
|
-
/* @__PURE__ */
|
|
9046
|
+
return /* @__PURE__ */ jsxs73("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
|
|
9047
|
+
/* @__PURE__ */ jsxs73("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
9048
|
+
/* @__PURE__ */ jsx86("span", { className: "fd-overline fd-muted", children: "Account" }),
|
|
9049
|
+
/* @__PURE__ */ jsx86("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
|
|
9050
|
+
/* @__PURE__ */ jsx86("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
|
|
8956
9051
|
] }),
|
|
8957
|
-
/* @__PURE__ */
|
|
8958
|
-
/* @__PURE__ */
|
|
8959
|
-
/* @__PURE__ */
|
|
8960
|
-
/* @__PURE__ */
|
|
8961
|
-
/* @__PURE__ */
|
|
8962
|
-
roles.map((r) => /* @__PURE__ */
|
|
8963
|
-
user.sso ? /* @__PURE__ */
|
|
9052
|
+
/* @__PURE__ */ jsx86(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs73("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
|
|
9053
|
+
/* @__PURE__ */ jsx86(Avatar, { name: displayName, size: "lg" }),
|
|
9054
|
+
/* @__PURE__ */ jsxs73("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
|
|
9055
|
+
/* @__PURE__ */ jsx86("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
|
|
9056
|
+
/* @__PURE__ */ jsxs73("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
|
|
9057
|
+
roles.map((r) => /* @__PURE__ */ jsx86(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
|
|
9058
|
+
user.sso ? /* @__PURE__ */ jsx86(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
|
|
8964
9059
|
] })
|
|
8965
9060
|
] }),
|
|
8966
|
-
onChangePhoto ? /* @__PURE__ */
|
|
9061
|
+
onChangePhoto ? /* @__PURE__ */ jsx86(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
|
|
8967
9062
|
] }) }),
|
|
8968
|
-
fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */
|
|
9063
|
+
fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ jsx86(
|
|
8969
9064
|
Card,
|
|
8970
9065
|
{
|
|
8971
|
-
title: description ? /* @__PURE__ */
|
|
8972
|
-
/* @__PURE__ */
|
|
8973
|
-
/* @__PURE__ */
|
|
9066
|
+
title: description ? /* @__PURE__ */ jsxs73("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
9067
|
+
/* @__PURE__ */ jsx86("span", { children: group }),
|
|
9068
|
+
/* @__PURE__ */ jsx86("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
|
|
8974
9069
|
] }) : group,
|
|
8975
9070
|
elevation: "flat",
|
|
8976
|
-
children: /* @__PURE__ */
|
|
8977
|
-
/* @__PURE__ */
|
|
9071
|
+
children: /* @__PURE__ */ jsxs73("div", { className: "fd-stack", style: { gap: 14 }, children: [
|
|
9072
|
+
/* @__PURE__ */ jsx86("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
|
|
8978
9073
|
const help = typeof field.help === "function" ? field.help(user) : field.help;
|
|
8979
9074
|
const readOnly = field.readOnly || field.type === "readonly";
|
|
8980
9075
|
if (field.type === "select") {
|
|
8981
|
-
return /* @__PURE__ */
|
|
9076
|
+
return /* @__PURE__ */ jsx86(
|
|
8982
9077
|
Select,
|
|
8983
9078
|
{
|
|
8984
9079
|
label: field.label,
|
|
@@ -8992,7 +9087,7 @@ function ProfilePage({
|
|
|
8992
9087
|
field.key
|
|
8993
9088
|
);
|
|
8994
9089
|
}
|
|
8995
|
-
return /* @__PURE__ */
|
|
9090
|
+
return /* @__PURE__ */ jsx86(
|
|
8996
9091
|
Input,
|
|
8997
9092
|
{
|
|
8998
9093
|
label: field.label,
|
|
@@ -9008,7 +9103,7 @@ function ProfilePage({
|
|
|
9008
9103
|
}) }),
|
|
9009
9104
|
groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
|
|
9010
9105
|
const help = typeof field.help === "function" ? field.help(user) : field.help;
|
|
9011
|
-
return /* @__PURE__ */
|
|
9106
|
+
return /* @__PURE__ */ jsx86(
|
|
9012
9107
|
Textarea,
|
|
9013
9108
|
{
|
|
9014
9109
|
label: field.label,
|
|
@@ -9028,16 +9123,16 @@ function ProfilePage({
|
|
|
9028
9123
|
group
|
|
9029
9124
|
)),
|
|
9030
9125
|
extra,
|
|
9031
|
-
notifications.length > 0 ? /* @__PURE__ */
|
|
9032
|
-
/* @__PURE__ */
|
|
9126
|
+
notifications.length > 0 ? /* @__PURE__ */ jsx86(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ jsx86("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ jsx86(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
|
|
9127
|
+
/* @__PURE__ */ jsxs73(
|
|
9033
9128
|
Card,
|
|
9034
9129
|
{
|
|
9035
|
-
title: /* @__PURE__ */
|
|
9036
|
-
/* @__PURE__ */
|
|
9037
|
-
/* @__PURE__ */
|
|
9130
|
+
title: /* @__PURE__ */ jsxs73("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
9131
|
+
/* @__PURE__ */ jsx86("span", { children: "Access" }),
|
|
9132
|
+
/* @__PURE__ */ jsx86("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
|
|
9038
9133
|
] }),
|
|
9039
9134
|
elevation: "flat",
|
|
9040
|
-
action: /* @__PURE__ */
|
|
9135
|
+
action: /* @__PURE__ */ jsx86(
|
|
9041
9136
|
Button,
|
|
9042
9137
|
{
|
|
9043
9138
|
size: "sm",
|
|
@@ -9048,39 +9143,39 @@ function ProfilePage({
|
|
|
9048
9143
|
}
|
|
9049
9144
|
),
|
|
9050
9145
|
children: [
|
|
9051
|
-
/* @__PURE__ */
|
|
9052
|
-
/* @__PURE__ */
|
|
9053
|
-
/* @__PURE__ */
|
|
9146
|
+
/* @__PURE__ */ jsxs73("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
9147
|
+
/* @__PURE__ */ jsx86(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
|
|
9148
|
+
/* @__PURE__ */ jsxs73(CardRow, { label: "Permissions", children: [
|
|
9054
9149
|
permissions.length,
|
|
9055
9150
|
" granted"
|
|
9056
9151
|
] }),
|
|
9057
|
-
/* @__PURE__ */
|
|
9152
|
+
/* @__PURE__ */ jsx86(CardRow, { label: "Member since", children: user.joined || "\u2014" })
|
|
9058
9153
|
] }),
|
|
9059
|
-
/* @__PURE__ */
|
|
9154
|
+
/* @__PURE__ */ jsx86("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
|
|
9060
9155
|
]
|
|
9061
9156
|
}
|
|
9062
9157
|
),
|
|
9063
|
-
sessions ? /* @__PURE__ */
|
|
9158
|
+
sessions ? /* @__PURE__ */ jsx86(
|
|
9064
9159
|
Card,
|
|
9065
9160
|
{
|
|
9066
9161
|
title: "Signed-in devices",
|
|
9067
9162
|
elevation: "flat",
|
|
9068
|
-
action: /* @__PURE__ */
|
|
9069
|
-
children: /* @__PURE__ */
|
|
9070
|
-
/* @__PURE__ */
|
|
9071
|
-
/* @__PURE__ */
|
|
9072
|
-
/* @__PURE__ */
|
|
9073
|
-
/* @__PURE__ */
|
|
9163
|
+
action: /* @__PURE__ */ jsx86(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
|
|
9164
|
+
children: /* @__PURE__ */ jsx86("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ jsx86("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ jsxs73("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
|
|
9165
|
+
/* @__PURE__ */ jsx86("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
9166
|
+
/* @__PURE__ */ jsxs73("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
|
|
9167
|
+
/* @__PURE__ */ jsx86("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
|
|
9168
|
+
/* @__PURE__ */ jsxs73("span", { className: "fd-body-sm fd-muted", children: [
|
|
9074
9169
|
s.where,
|
|
9075
9170
|
" \xB7 ",
|
|
9076
9171
|
s.when
|
|
9077
9172
|
] })
|
|
9078
9173
|
] }),
|
|
9079
|
-
s.current ? /* @__PURE__ */
|
|
9174
|
+
s.current ? /* @__PURE__ */ jsx86(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx86(Button, { size: "sm", variant: "ghost", children: "Revoke" })
|
|
9080
9175
|
] }, s.id)) })
|
|
9081
9176
|
}
|
|
9082
9177
|
) : null,
|
|
9083
|
-
/* @__PURE__ */
|
|
9178
|
+
/* @__PURE__ */ jsxs73("div", { className: "fd-row", style: {
|
|
9084
9179
|
gap: 10,
|
|
9085
9180
|
flexWrap: "wrap",
|
|
9086
9181
|
position: "sticky",
|
|
@@ -9091,16 +9186,16 @@ function ProfilePage({
|
|
|
9091
9186
|
border: "1px solid var(--border)",
|
|
9092
9187
|
boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
|
|
9093
9188
|
}, children: [
|
|
9094
|
-
/* @__PURE__ */
|
|
9095
|
-
/* @__PURE__ */
|
|
9096
|
-
/* @__PURE__ */
|
|
9189
|
+
/* @__PURE__ */ jsx86("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
|
|
9190
|
+
/* @__PURE__ */ jsx86(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
|
|
9191
|
+
/* @__PURE__ */ jsx86(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
|
|
9097
9192
|
] })
|
|
9098
9193
|
] });
|
|
9099
9194
|
}
|
|
9100
9195
|
|
|
9101
9196
|
// src/components/platform/SessionScreen.tsx
|
|
9102
|
-
import * as
|
|
9103
|
-
import { Fragment as Fragment22, jsx as
|
|
9197
|
+
import * as React62 from "react";
|
|
9198
|
+
import { Fragment as Fragment22, jsx as jsx87, jsxs as jsxs74 } from "react/jsx-runtime";
|
|
9104
9199
|
var COPY = {
|
|
9105
9200
|
"signing-in": { busy: "Signing you in\u2026" },
|
|
9106
9201
|
"session-expired": { busy: "Your session expired \u2014 signing you back in\u2026" },
|
|
@@ -9113,28 +9208,28 @@ function SessionScreen({ kind, error, onRetry, productName }) {
|
|
|
9113
9208
|
const copy = COPY[kind];
|
|
9114
9209
|
const busyMessage = "busy" in copy ? copy.busy : null;
|
|
9115
9210
|
const failureTitle = "failure" in copy ? copy.failure : null;
|
|
9116
|
-
const [announced, setAnnounced] =
|
|
9117
|
-
|
|
9211
|
+
const [announced, setAnnounced] = React62.useState("");
|
|
9212
|
+
React62.useEffect(() => {
|
|
9118
9213
|
setAnnounced(busyMessage ?? "");
|
|
9119
9214
|
}, [busyMessage]);
|
|
9120
|
-
const titleRef =
|
|
9215
|
+
const titleRef = React62.useRef(null);
|
|
9121
9216
|
const failed = failureTitle !== null;
|
|
9122
|
-
|
|
9217
|
+
React62.useEffect(() => {
|
|
9123
9218
|
titleRef.current?.focus({ preventScroll: true });
|
|
9124
9219
|
}, [failed]);
|
|
9125
|
-
return /* @__PURE__ */
|
|
9126
|
-
/* @__PURE__ */
|
|
9127
|
-
/* @__PURE__ */
|
|
9128
|
-
/* @__PURE__ */
|
|
9129
|
-
/* @__PURE__ */
|
|
9130
|
-
/* @__PURE__ */
|
|
9131
|
-
/* @__PURE__ */
|
|
9132
|
-
/* @__PURE__ */
|
|
9133
|
-
/* @__PURE__ */
|
|
9220
|
+
return /* @__PURE__ */ jsx87("main", { className: "fd-session-screen", children: /* @__PURE__ */ jsxs74("div", { className: "fd-session-screen-inner", children: [
|
|
9221
|
+
/* @__PURE__ */ jsx87("div", { className: "fd-session-screen-mark", "data-theme": "dark", children: /* @__PURE__ */ jsx87(FlytedeskMark, { size: "lg" }) }),
|
|
9222
|
+
/* @__PURE__ */ jsxs74("div", { className: "fd-session-screen-frame", children: [
|
|
9223
|
+
/* @__PURE__ */ jsx87("div", { className: "fd-session-screen-stripe" }),
|
|
9224
|
+
/* @__PURE__ */ jsx87(Card, { children: /* @__PURE__ */ jsxs74("div", { className: "fd-session-screen-body", children: [
|
|
9225
|
+
/* @__PURE__ */ jsx87("h1", { ref: titleRef, tabIndex: -1, className: "fd-h3 fd-session-screen-title", children: productName }),
|
|
9226
|
+
/* @__PURE__ */ jsx87("div", { role: "status", "aria-live": "polite", className: "fd-session-screen-status", children: busyMessage !== null ? /* @__PURE__ */ jsxs74(Fragment22, { children: [
|
|
9227
|
+
/* @__PURE__ */ jsx87("span", { className: "fd-spinner fd-spinner-lg fd-session-screen-spinner", "aria-hidden": "true" }),
|
|
9228
|
+
/* @__PURE__ */ jsx87("p", { className: "fd-body fd-session-screen-message", children: announced })
|
|
9134
9229
|
] }) : null }),
|
|
9135
|
-
failureTitle !== null ? /* @__PURE__ */
|
|
9136
|
-
/* @__PURE__ */
|
|
9137
|
-
onRetry !== null ? /* @__PURE__ */
|
|
9230
|
+
failureTitle !== null ? /* @__PURE__ */ jsxs74("div", { className: "fd-session-screen-failure", children: [
|
|
9231
|
+
/* @__PURE__ */ jsx87(Banner, { tone: "danger", title: failureTitle, detail: error ?? void 0 }),
|
|
9232
|
+
onRetry !== null ? /* @__PURE__ */ jsx87(Button, { variant: "primary", block: true, onClick: onRetry, children: "Try again" }) : null
|
|
9138
9233
|
] }) : null
|
|
9139
9234
|
] }) })
|
|
9140
9235
|
] })
|
|
@@ -9142,10 +9237,10 @@ function SessionScreen({ kind, error, onRetry, productName }) {
|
|
|
9142
9237
|
}
|
|
9143
9238
|
|
|
9144
9239
|
// src/components/platform/RoadmapTimeline.tsx
|
|
9145
|
-
import * as
|
|
9240
|
+
import * as React65 from "react";
|
|
9146
9241
|
|
|
9147
9242
|
// src/kits/session.ts
|
|
9148
|
-
import * as
|
|
9243
|
+
import * as React63 from "react";
|
|
9149
9244
|
var PERMISSION_CATALOG = [
|
|
9150
9245
|
{ group: "Plans", items: [
|
|
9151
9246
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -10712,8 +10807,8 @@ function roadmap(overrides) {
|
|
|
10712
10807
|
};
|
|
10713
10808
|
}
|
|
10714
10809
|
function useSession() {
|
|
10715
|
-
const [s, setS] =
|
|
10716
|
-
|
|
10810
|
+
const [s, setS] = React63.useState(getSession);
|
|
10811
|
+
React63.useEffect(() => subscribe(setS), []);
|
|
10717
10812
|
return s;
|
|
10718
10813
|
}
|
|
10719
10814
|
var SessionKit = {
|
|
@@ -10746,7 +10841,7 @@ var SessionKit = {
|
|
|
10746
10841
|
};
|
|
10747
10842
|
function DemoSessionProvider({ children }) {
|
|
10748
10843
|
const session = useSession();
|
|
10749
|
-
const value =
|
|
10844
|
+
const value = React63.useMemo(
|
|
10750
10845
|
() => ({
|
|
10751
10846
|
user: session.user,
|
|
10752
10847
|
roles: session.roles,
|
|
@@ -10762,11 +10857,11 @@ function DemoSessionProvider({ children }) {
|
|
|
10762
10857
|
}),
|
|
10763
10858
|
[session]
|
|
10764
10859
|
);
|
|
10765
|
-
return
|
|
10860
|
+
return React63.createElement(SessionProvider, { value }, children);
|
|
10766
10861
|
}
|
|
10767
10862
|
|
|
10768
10863
|
// src/kits/runtime.ts
|
|
10769
|
-
import * as
|
|
10864
|
+
import * as React64 from "react";
|
|
10770
10865
|
var WIRED_ENDPOINTS = [
|
|
10771
10866
|
// Nothing yet. Every id below would come from a real service:
|
|
10772
10867
|
// "plan.get", "placements.list", …
|
|
@@ -10937,8 +11032,8 @@ var RuntimeKit = {
|
|
|
10937
11032
|
};
|
|
10938
11033
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
10939
11034
|
function useRuntimeMode() {
|
|
10940
|
-
const [m, setM] =
|
|
10941
|
-
|
|
11035
|
+
const [m, setM] = React64.useState(RuntimeKit.getMode());
|
|
11036
|
+
React64.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
10942
11037
|
return m;
|
|
10943
11038
|
}
|
|
10944
11039
|
function useFeatureStatus(key) {
|
|
@@ -10957,7 +11052,7 @@ var UseRuntimeMode = useRuntimeMode;
|
|
|
10957
11052
|
var UseFeatureStatus = useFeatureStatus;
|
|
10958
11053
|
|
|
10959
11054
|
// src/components/platform/RoadmapTimeline.tsx
|
|
10960
|
-
import { jsx as
|
|
11055
|
+
import { jsx as jsx88, jsxs as jsxs75 } from "react/jsx-runtime";
|
|
10961
11056
|
var STATUS = {
|
|
10962
11057
|
shipped: { tone: "success", icon: "check-circle", label: "Wired" },
|
|
10963
11058
|
next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
|
|
@@ -10972,45 +11067,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
10972
11067
|
const s = STATUS[item.status] || STATUS.planned;
|
|
10973
11068
|
const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
|
|
10974
11069
|
const blocking = deps.filter((d) => !d.implemented);
|
|
10975
|
-
return /* @__PURE__ */
|
|
10976
|
-
/* @__PURE__ */
|
|
10977
|
-
/* @__PURE__ */
|
|
10978
|
-
/* @__PURE__ */
|
|
10979
|
-
/* @__PURE__ */
|
|
11070
|
+
return /* @__PURE__ */ jsx88(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs75("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
11071
|
+
/* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
11072
|
+
/* @__PURE__ */ jsx88("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
|
|
11073
|
+
/* @__PURE__ */ jsx88(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
|
|
11074
|
+
/* @__PURE__ */ jsx88(Badge, { tone: s.tone, icon: s.icon, children: s.label })
|
|
10980
11075
|
] }),
|
|
10981
|
-
/* @__PURE__ */
|
|
10982
|
-
item.backend ? /* @__PURE__ */
|
|
10983
|
-
/* @__PURE__ */
|
|
10984
|
-
/* @__PURE__ */
|
|
11076
|
+
/* @__PURE__ */ jsx88("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
|
|
11077
|
+
item.backend ? /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
|
|
11078
|
+
/* @__PURE__ */ jsx88("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
|
|
11079
|
+
/* @__PURE__ */ jsx88("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
|
|
10985
11080
|
] }) : null,
|
|
10986
|
-
/* @__PURE__ */
|
|
10987
|
-
item.effort ? /* @__PURE__ */
|
|
10988
|
-
/* @__PURE__ */
|
|
11081
|
+
/* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
11082
|
+
item.effort ? /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted", children: [
|
|
11083
|
+
/* @__PURE__ */ jsx88("i", { className: "ph ph-hourglass-medium" }),
|
|
10989
11084
|
" ",
|
|
10990
11085
|
item.effort
|
|
10991
11086
|
] }) : null,
|
|
10992
|
-
/* @__PURE__ */
|
|
10993
|
-
/* @__PURE__ */
|
|
11087
|
+
/* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted", children: [
|
|
11088
|
+
/* @__PURE__ */ jsx88("i", { className: "ph ph-user" }),
|
|
10994
11089
|
" ",
|
|
10995
11090
|
item.owner
|
|
10996
11091
|
] }),
|
|
10997
|
-
item.screen ? /* @__PURE__ */
|
|
10998
|
-
/* @__PURE__ */
|
|
10999
|
-
/* @__PURE__ */
|
|
11092
|
+
item.screen ? /* @__PURE__ */ jsx88(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
|
|
11093
|
+
/* @__PURE__ */ jsx88("span", { style: { flex: 1 } }),
|
|
11094
|
+
/* @__PURE__ */ jsx88(
|
|
11000
11095
|
"button",
|
|
11001
11096
|
{
|
|
11002
11097
|
type: "button",
|
|
11003
11098
|
onClick: () => onOpenFlag && onOpenFlag(item.key),
|
|
11004
11099
|
style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
|
|
11005
|
-
children: /* @__PURE__ */
|
|
11100
|
+
children: /* @__PURE__ */ jsx88("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
|
|
11006
11101
|
}
|
|
11007
11102
|
)
|
|
11008
11103
|
] }),
|
|
11009
|
-
deps.length ? /* @__PURE__ */
|
|
11010
|
-
/* @__PURE__ */
|
|
11011
|
-
deps.map((d) => /* @__PURE__ */
|
|
11104
|
+
deps.length ? /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
|
|
11105
|
+
/* @__PURE__ */ jsx88("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
|
|
11106
|
+
deps.map((d) => /* @__PURE__ */ jsx88(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
|
|
11012
11107
|
] }) : null,
|
|
11013
|
-
blocking.length && !item.implemented ? /* @__PURE__ */
|
|
11108
|
+
blocking.length && !item.implemented ? /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
|
|
11014
11109
|
"Blocked until ",
|
|
11015
11110
|
blocking.map((d) => d.label).join(" and "),
|
|
11016
11111
|
" ",
|
|
@@ -11021,12 +11116,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
11021
11116
|
}
|
|
11022
11117
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
11023
11118
|
const session = SessionKit.useSession();
|
|
11024
|
-
const [project, setProject] =
|
|
11025
|
-
const [q, setQ] =
|
|
11026
|
-
const scrollRef =
|
|
11027
|
-
const nowRef =
|
|
11028
|
-
const rm =
|
|
11029
|
-
const byKey =
|
|
11119
|
+
const [project, setProject] = React65.useState("");
|
|
11120
|
+
const [q, setQ] = React65.useState("");
|
|
11121
|
+
const scrollRef = React65.useRef(null);
|
|
11122
|
+
const nowRef = React65.useRef(null);
|
|
11123
|
+
const rm = React65.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
11124
|
+
const byKey = React65.useMemo(() => {
|
|
11030
11125
|
const m = {};
|
|
11031
11126
|
rm.items.forEach((i) => {
|
|
11032
11127
|
m[i.key] = i;
|
|
@@ -11035,7 +11130,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
11035
11130
|
}, [rm]);
|
|
11036
11131
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
11037
11132
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
11038
|
-
|
|
11133
|
+
React65.useEffect(() => {
|
|
11039
11134
|
let raf1 = 0, raf2 = 0;
|
|
11040
11135
|
const place = () => {
|
|
11041
11136
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -11063,23 +11158,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
11063
11158
|
}, 0);
|
|
11064
11159
|
const nextPhase = items.find((i) => !i.implemented);
|
|
11065
11160
|
let lastPhase = null;
|
|
11066
|
-
return /* @__PURE__ */
|
|
11067
|
-
/* @__PURE__ */
|
|
11068
|
-
/* @__PURE__ */
|
|
11069
|
-
/* @__PURE__ */
|
|
11070
|
-
/* @__PURE__ */
|
|
11161
|
+
return /* @__PURE__ */ jsxs75("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
|
|
11162
|
+
/* @__PURE__ */ jsxs75("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
11163
|
+
/* @__PURE__ */ jsx88("span", { className: "fd-overline fd-muted", children: "Architecture" }),
|
|
11164
|
+
/* @__PURE__ */ jsx88("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
11165
|
+
/* @__PURE__ */ jsx88("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede || "Every screen and feature in these tools is already designed and working against a simulated backend. This is the plan for connecting them to the real one \u2014 so the only work described here is server work." })
|
|
11071
11166
|
] }),
|
|
11072
|
-
/* @__PURE__ */
|
|
11073
|
-
/* @__PURE__ */
|
|
11074
|
-
/* @__PURE__ */
|
|
11075
|
-
/* @__PURE__ */
|
|
11076
|
-
/* @__PURE__ */
|
|
11167
|
+
/* @__PURE__ */ jsxs75("div", { className: "fd-grid-stats is-thin", children: [
|
|
11168
|
+
/* @__PURE__ */ jsx88(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
|
|
11169
|
+
/* @__PURE__ */ jsx88(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
|
|
11170
|
+
/* @__PURE__ */ jsx88(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
|
|
11171
|
+
/* @__PURE__ */ jsx88(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
|
|
11077
11172
|
] }),
|
|
11078
|
-
/* @__PURE__ */
|
|
11079
|
-
/* @__PURE__ */
|
|
11080
|
-
/* @__PURE__ */
|
|
11081
|
-
/* @__PURE__ */
|
|
11082
|
-
/* @__PURE__ */
|
|
11173
|
+
/* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
11174
|
+
/* @__PURE__ */ jsx88(Input, { icon: "magnifying-glass", placeholder: "Find a feature or a piece of backend work", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
|
|
11175
|
+
/* @__PURE__ */ jsx88(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
|
|
11176
|
+
/* @__PURE__ */ jsx88("span", { style: { flex: 1 } }),
|
|
11177
|
+
/* @__PURE__ */ jsx88(
|
|
11083
11178
|
Button,
|
|
11084
11179
|
{
|
|
11085
11180
|
size: "sm",
|
|
@@ -11093,7 +11188,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
11093
11188
|
}
|
|
11094
11189
|
)
|
|
11095
11190
|
] }),
|
|
11096
|
-
/* @__PURE__ */
|
|
11191
|
+
/* @__PURE__ */ jsx88(
|
|
11097
11192
|
Flag,
|
|
11098
11193
|
{
|
|
11099
11194
|
tone: "info",
|
|
@@ -11102,60 +11197,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
11102
11197
|
actions: null
|
|
11103
11198
|
}
|
|
11104
11199
|
),
|
|
11105
|
-
/* @__PURE__ */
|
|
11106
|
-
/* @__PURE__ */
|
|
11200
|
+
/* @__PURE__ */ jsx88("div", { className: "fd-rm", children: /* @__PURE__ */ jsx88("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs75("div", { className: "fd-rm-track", children: [
|
|
11201
|
+
/* @__PURE__ */ jsx88("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx88("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
|
|
11107
11202
|
items.map((item, n) => {
|
|
11108
11203
|
const showPhase = item.phase !== lastPhase;
|
|
11109
11204
|
lastPhase = item.phase;
|
|
11110
11205
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
11111
11206
|
const isBoundary = n === firstPending;
|
|
11112
|
-
return /* @__PURE__ */
|
|
11113
|
-
showPhase ? /* @__PURE__ */
|
|
11114
|
-
/* @__PURE__ */
|
|
11115
|
-
/* @__PURE__ */
|
|
11116
|
-
item.phase === 0 ? null : /* @__PURE__ */
|
|
11207
|
+
return /* @__PURE__ */ jsxs75(React65.Fragment, { children: [
|
|
11208
|
+
showPhase ? /* @__PURE__ */ jsxs75("div", { className: "fd-rm-era", children: [
|
|
11209
|
+
/* @__PURE__ */ jsxs75("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
11210
|
+
/* @__PURE__ */ jsx88("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
11211
|
+
item.phase === 0 ? null : /* @__PURE__ */ jsxs75("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
11117
11212
|
fmtDate(item.phaseStart),
|
|
11118
11213
|
" \u2013 ",
|
|
11119
11214
|
fmtDate(item.date)
|
|
11120
11215
|
] }),
|
|
11121
|
-
/* @__PURE__ */
|
|
11216
|
+
/* @__PURE__ */ jsxs75("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
11122
11217
|
"\xB7 ",
|
|
11123
11218
|
inPhase,
|
|
11124
11219
|
" feature",
|
|
11125
11220
|
inPhase === 1 ? "" : "s"
|
|
11126
11221
|
] })
|
|
11127
11222
|
] }),
|
|
11128
|
-
item.phaseWhy ? /* @__PURE__ */
|
|
11223
|
+
item.phaseWhy ? /* @__PURE__ */ jsx88("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
|
|
11129
11224
|
] }) : null,
|
|
11130
|
-
isBoundary ? /* @__PURE__ */
|
|
11131
|
-
/* @__PURE__ */
|
|
11225
|
+
isBoundary ? /* @__PURE__ */ jsx88("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs75("span", { className: "fd-rm-now-pill", children: [
|
|
11226
|
+
/* @__PURE__ */ jsx88("i", { className: "ph ph-map-pin" }),
|
|
11132
11227
|
" You are here \u2014 everything above is wired"
|
|
11133
11228
|
] }) }) : null,
|
|
11134
|
-
/* @__PURE__ */
|
|
11135
|
-
/* @__PURE__ */
|
|
11136
|
-
/* @__PURE__ */
|
|
11229
|
+
/* @__PURE__ */ jsxs75("div", { className: "fd-rm-row", children: [
|
|
11230
|
+
/* @__PURE__ */ jsx88("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
|
|
11231
|
+
/* @__PURE__ */ jsxs75("div", { className: "fd-rm-date", children: [
|
|
11137
11232
|
fmtDate(item.date),
|
|
11138
|
-
/* @__PURE__ */
|
|
11139
|
-
/* @__PURE__ */
|
|
11233
|
+
/* @__PURE__ */ jsx88("br", {}),
|
|
11234
|
+
/* @__PURE__ */ jsx88("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
|
|
11140
11235
|
] }),
|
|
11141
|
-
/* @__PURE__ */
|
|
11236
|
+
/* @__PURE__ */ jsx88(RoadmapCard, { item, byKey, onOpenFlag })
|
|
11142
11237
|
] })
|
|
11143
11238
|
] }, item.key);
|
|
11144
11239
|
}),
|
|
11145
|
-
!items.length ? /* @__PURE__ */
|
|
11240
|
+
!items.length ? /* @__PURE__ */ jsx88("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
|
|
11146
11241
|
] }) }) }),
|
|
11147
|
-
/* @__PURE__ */
|
|
11242
|
+
/* @__PURE__ */ jsxs75("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
|
|
11148
11243
|
"Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
|
|
11149
|
-
/* @__PURE__ */
|
|
11244
|
+
/* @__PURE__ */ jsx88("code", { className: "fd-mono", children: "implemented" }),
|
|
11150
11245
|
" field, so this page cannot drift from what the apps actually do."
|
|
11151
11246
|
] })
|
|
11152
11247
|
] });
|
|
11153
11248
|
}
|
|
11154
11249
|
|
|
11155
11250
|
// src/components/platform/ComingSoon.tsx
|
|
11156
|
-
import * as
|
|
11251
|
+
import * as React66 from "react";
|
|
11157
11252
|
import { createPortal as createPortal6 } from "react-dom";
|
|
11158
|
-
import { Fragment as Fragment24, jsx as
|
|
11253
|
+
import { Fragment as Fragment24, jsx as jsx89, jsxs as jsxs76 } from "react/jsx-runtime";
|
|
11159
11254
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
11160
11255
|
function readBypassed() {
|
|
11161
11256
|
try {
|
|
@@ -11171,8 +11266,8 @@ function writeBypassed(list) {
|
|
|
11171
11266
|
}
|
|
11172
11267
|
}
|
|
11173
11268
|
function useBypass(key) {
|
|
11174
|
-
const [on, setOn] =
|
|
11175
|
-
|
|
11269
|
+
const [on, setOn] = React66.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
11270
|
+
React66.useEffect(() => {
|
|
11176
11271
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
11177
11272
|
}, [key]);
|
|
11178
11273
|
const set = (next) => {
|
|
@@ -11185,43 +11280,43 @@ function useBypass(key) {
|
|
|
11185
11280
|
return [on, set];
|
|
11186
11281
|
}
|
|
11187
11282
|
function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
|
|
11188
|
-
return /* @__PURE__ */
|
|
11189
|
-
/* @__PURE__ */
|
|
11190
|
-
/* @__PURE__ */
|
|
11283
|
+
return /* @__PURE__ */ jsxs76(Fragment24, { children: [
|
|
11284
|
+
/* @__PURE__ */ jsxs76("span", { className: "fd-soon-badge", children: [
|
|
11285
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
11191
11286
|
label
|
|
11192
11287
|
] }),
|
|
11193
|
-
detail ? /* @__PURE__ */
|
|
11194
|
-
backend ? /* @__PURE__ */
|
|
11195
|
-
/* @__PURE__ */
|
|
11288
|
+
detail ? /* @__PURE__ */ jsx89("span", { className: "fd-soon-detail", children: detail }) : null,
|
|
11289
|
+
backend ? /* @__PURE__ */ jsxs76("span", { className: "fd-soon-backend", children: [
|
|
11290
|
+
/* @__PURE__ */ jsx89("span", { className: "fd-overline", children: "Needs" }),
|
|
11196
11291
|
" ",
|
|
11197
11292
|
backend
|
|
11198
11293
|
] }) : null,
|
|
11199
|
-
eta || effort || onRoadmap ? /* @__PURE__ */
|
|
11200
|
-
eta ? /* @__PURE__ */
|
|
11201
|
-
/* @__PURE__ */
|
|
11294
|
+
eta || effort || onRoadmap ? /* @__PURE__ */ jsxs76("span", { className: "fd-soon-meta", children: [
|
|
11295
|
+
eta ? /* @__PURE__ */ jsxs76("span", { children: [
|
|
11296
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
|
|
11202
11297
|
" ",
|
|
11203
11298
|
eta
|
|
11204
11299
|
] }) : null,
|
|
11205
|
-
effort ? /* @__PURE__ */
|
|
11206
|
-
/* @__PURE__ */
|
|
11300
|
+
effort ? /* @__PURE__ */ jsxs76("span", { children: [
|
|
11301
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
|
|
11207
11302
|
" ",
|
|
11208
11303
|
effort
|
|
11209
11304
|
] }) : null,
|
|
11210
|
-
onRoadmap ? /* @__PURE__ */
|
|
11305
|
+
onRoadmap ? /* @__PURE__ */ jsxs76("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
11211
11306
|
"See the roadmap ",
|
|
11212
|
-
/* @__PURE__ */
|
|
11307
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
11213
11308
|
] }) : null
|
|
11214
11309
|
] }) : null,
|
|
11215
|
-
allowed ? /* @__PURE__ */
|
|
11216
|
-
/* @__PURE__ */
|
|
11310
|
+
allowed ? /* @__PURE__ */ jsxs76("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
|
|
11311
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-eye", "aria-hidden": "true" }),
|
|
11217
11312
|
" View and use it anyway"
|
|
11218
11313
|
] }) : null
|
|
11219
11314
|
] });
|
|
11220
11315
|
}
|
|
11221
11316
|
function useHoverCard(open2) {
|
|
11222
|
-
const anchor =
|
|
11223
|
-
const [pos, setPos] =
|
|
11224
|
-
|
|
11317
|
+
const anchor = React66.useRef(null);
|
|
11318
|
+
const [pos, setPos] = React66.useState(null);
|
|
11319
|
+
React66.useLayoutEffect(() => {
|
|
11225
11320
|
if (!open2 || !anchor.current) {
|
|
11226
11321
|
setPos(null);
|
|
11227
11322
|
return;
|
|
@@ -11273,9 +11368,9 @@ function ComingSoon({
|
|
|
11273
11368
|
const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
|
|
11274
11369
|
if (inline) {
|
|
11275
11370
|
if (allowed && bypassed) {
|
|
11276
|
-
return /* @__PURE__ */
|
|
11371
|
+
return /* @__PURE__ */ jsxs76("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
|
|
11277
11372
|
children,
|
|
11278
|
-
/* @__PURE__ */
|
|
11373
|
+
/* @__PURE__ */ jsx89(
|
|
11279
11374
|
"button",
|
|
11280
11375
|
{
|
|
11281
11376
|
type: "button",
|
|
@@ -11283,12 +11378,12 @@ function ComingSoon({
|
|
|
11283
11378
|
title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
|
|
11284
11379
|
onClick: () => setBypassed(false),
|
|
11285
11380
|
"aria-label": "Re-blur this unwired feature",
|
|
11286
|
-
children: /* @__PURE__ */
|
|
11381
|
+
children: /* @__PURE__ */ jsx89("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
11287
11382
|
}
|
|
11288
11383
|
)
|
|
11289
11384
|
] });
|
|
11290
11385
|
}
|
|
11291
|
-
return /* @__PURE__ */
|
|
11386
|
+
return /* @__PURE__ */ jsx89(
|
|
11292
11387
|
InlineSoon,
|
|
11293
11388
|
{
|
|
11294
11389
|
label,
|
|
@@ -11308,20 +11403,20 @@ function ComingSoon({
|
|
|
11308
11403
|
);
|
|
11309
11404
|
}
|
|
11310
11405
|
if (allowed && bypassed) {
|
|
11311
|
-
return /* @__PURE__ */
|
|
11312
|
-
/* @__PURE__ */
|
|
11313
|
-
/* @__PURE__ */
|
|
11314
|
-
/* @__PURE__ */
|
|
11406
|
+
return /* @__PURE__ */ jsxs76("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
|
|
11407
|
+
/* @__PURE__ */ jsxs76("div", { className: "fd-soon-bar", role: "status", children: [
|
|
11408
|
+
/* @__PURE__ */ jsxs76("span", { className: "fd-soon-badge", children: [
|
|
11409
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
11315
11410
|
"Unwired feature \u2014 you are using it anyway"
|
|
11316
11411
|
] }),
|
|
11317
|
-
/* @__PURE__ */
|
|
11318
|
-
/* @__PURE__ */
|
|
11319
|
-
onRoadmap ? /* @__PURE__ */
|
|
11412
|
+
/* @__PURE__ */ jsx89("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
|
|
11413
|
+
/* @__PURE__ */ jsxs76("span", { className: "fd-soon-bar-actions", children: [
|
|
11414
|
+
onRoadmap ? /* @__PURE__ */ jsxs76("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
11320
11415
|
"Roadmap ",
|
|
11321
|
-
/* @__PURE__ */
|
|
11416
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
11322
11417
|
] }) : null,
|
|
11323
|
-
/* @__PURE__ */
|
|
11324
|
-
/* @__PURE__ */
|
|
11418
|
+
/* @__PURE__ */ jsxs76("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
|
|
11419
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
|
|
11325
11420
|
" Re-blur"
|
|
11326
11421
|
] })
|
|
11327
11422
|
] })
|
|
@@ -11329,10 +11424,10 @@ function ComingSoon({
|
|
|
11329
11424
|
children
|
|
11330
11425
|
] });
|
|
11331
11426
|
}
|
|
11332
|
-
return /* @__PURE__ */
|
|
11333
|
-
/* @__PURE__ */
|
|
11334
|
-
/* @__PURE__ */
|
|
11335
|
-
/* @__PURE__ */
|
|
11427
|
+
return /* @__PURE__ */ jsxs76("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
|
|
11428
|
+
/* @__PURE__ */ jsx89("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
11429
|
+
/* @__PURE__ */ jsx89("div", { className: "fd-soon-veil" }),
|
|
11430
|
+
/* @__PURE__ */ jsx89("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx89(
|
|
11336
11431
|
SoonCard,
|
|
11337
11432
|
{
|
|
11338
11433
|
label,
|
|
@@ -11348,12 +11443,12 @@ function ComingSoon({
|
|
|
11348
11443
|
] });
|
|
11349
11444
|
}
|
|
11350
11445
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
11351
|
-
const [open2, setOpen] =
|
|
11446
|
+
const [open2, setOpen] = React66.useState(false);
|
|
11352
11447
|
const [anchor, pos] = useHoverCard(open2);
|
|
11353
|
-
const hoverCardRef =
|
|
11448
|
+
const hoverCardRef = React66.useRef(null);
|
|
11354
11449
|
const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
|
|
11355
11450
|
const zIndex = useLayerZIndex(hoverLayer);
|
|
11356
|
-
const close2 =
|
|
11451
|
+
const close2 = React66.useRef(null);
|
|
11357
11452
|
const show = () => {
|
|
11358
11453
|
if (close2.current) {
|
|
11359
11454
|
clearTimeout(close2.current);
|
|
@@ -11369,10 +11464,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
11369
11464
|
setOpen(false);
|
|
11370
11465
|
}, 140);
|
|
11371
11466
|
};
|
|
11372
|
-
|
|
11467
|
+
React66.useEffect(() => () => {
|
|
11373
11468
|
if (close2.current) clearTimeout(close2.current);
|
|
11374
11469
|
}, []);
|
|
11375
|
-
return /* @__PURE__ */
|
|
11470
|
+
return /* @__PURE__ */ jsxs76(
|
|
11376
11471
|
"span",
|
|
11377
11472
|
{
|
|
11378
11473
|
ref: anchor,
|
|
@@ -11383,8 +11478,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
11383
11478
|
onBlur: hide,
|
|
11384
11479
|
...rest,
|
|
11385
11480
|
children: [
|
|
11386
|
-
/* @__PURE__ */
|
|
11387
|
-
/* @__PURE__ */
|
|
11481
|
+
/* @__PURE__ */ jsx89("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
11482
|
+
/* @__PURE__ */ jsx89(
|
|
11388
11483
|
"button",
|
|
11389
11484
|
{
|
|
11390
11485
|
type: "button",
|
|
@@ -11395,11 +11490,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
11395
11490
|
onFocus: show,
|
|
11396
11491
|
onBlur: hide,
|
|
11397
11492
|
onClick: () => open2 ? setOpen(false) : show(),
|
|
11398
|
-
children: /* @__PURE__ */
|
|
11493
|
+
children: /* @__PURE__ */ jsx89("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
11399
11494
|
}
|
|
11400
11495
|
),
|
|
11401
11496
|
open2 && pos ? createPortal6(
|
|
11402
|
-
/* @__PURE__ */
|
|
11497
|
+
/* @__PURE__ */ jsx89(
|
|
11403
11498
|
"div",
|
|
11404
11499
|
{
|
|
11405
11500
|
ref: hoverCardRef,
|
|
@@ -11408,7 +11503,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
11408
11503
|
style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
|
|
11409
11504
|
onMouseEnter: show,
|
|
11410
11505
|
onMouseLeave: hide,
|
|
11411
|
-
children: /* @__PURE__ */
|
|
11506
|
+
children: /* @__PURE__ */ jsx89(
|
|
11412
11507
|
SoonCard,
|
|
11413
11508
|
{
|
|
11414
11509
|
label,
|
|
@@ -11438,10 +11533,10 @@ function formatEta(iso2) {
|
|
|
11438
11533
|
var FormatEta = formatEta;
|
|
11439
11534
|
|
|
11440
11535
|
// src/components/platform/Gate.tsx
|
|
11441
|
-
import { jsx as
|
|
11536
|
+
import { jsx as jsx90, jsxs as jsxs77 } from "react/jsx-runtime";
|
|
11442
11537
|
function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
|
|
11443
11538
|
const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
|
|
11444
|
-
return /* @__PURE__ */
|
|
11539
|
+
return /* @__PURE__ */ jsxs77(
|
|
11445
11540
|
"div",
|
|
11446
11541
|
{
|
|
11447
11542
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -11457,14 +11552,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
11457
11552
|
},
|
|
11458
11553
|
...rest,
|
|
11459
11554
|
children: [
|
|
11460
|
-
/* @__PURE__ */
|
|
11461
|
-
/* @__PURE__ */
|
|
11462
|
-
/* @__PURE__ */
|
|
11555
|
+
/* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
11556
|
+
/* @__PURE__ */ jsx90("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
11557
|
+
/* @__PURE__ */ jsx90("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
|
|
11463
11558
|
] }),
|
|
11464
|
-
/* @__PURE__ */
|
|
11465
|
-
need.length ? /* @__PURE__ */
|
|
11466
|
-
/* @__PURE__ */
|
|
11467
|
-
need.map((p) => /* @__PURE__ */
|
|
11559
|
+
/* @__PURE__ */ jsx90("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: detail || "Your roles do not grant this. An administrator can change that from Admin \u2192 Users." }),
|
|
11560
|
+
need.length ? /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
|
|
11561
|
+
/* @__PURE__ */ jsx90("span", { className: "fd-overline fd-muted", children: "Requires" }),
|
|
11562
|
+
need.map((p) => /* @__PURE__ */ jsx90("code", { className: "fd-mono", style: {
|
|
11468
11563
|
fontSize: 11.5,
|
|
11469
11564
|
padding: "2px 7px",
|
|
11470
11565
|
borderRadius: 5,
|
|
@@ -11477,7 +11572,7 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
11477
11572
|
);
|
|
11478
11573
|
}
|
|
11479
11574
|
function GatePending({ compact: compact3 = false, className = "" }) {
|
|
11480
|
-
return /* @__PURE__ */
|
|
11575
|
+
return /* @__PURE__ */ jsxs77(
|
|
11481
11576
|
"div",
|
|
11482
11577
|
{
|
|
11483
11578
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -11493,11 +11588,11 @@ function GatePending({ compact: compact3 = false, className = "" }) {
|
|
|
11493
11588
|
textAlign: "left"
|
|
11494
11589
|
},
|
|
11495
11590
|
children: [
|
|
11496
|
-
/* @__PURE__ */
|
|
11497
|
-
/* @__PURE__ */
|
|
11498
|
-
/* @__PURE__ */
|
|
11591
|
+
/* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
11592
|
+
/* @__PURE__ */ jsx90("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
11593
|
+
/* @__PURE__ */ jsx90("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
|
|
11499
11594
|
] }),
|
|
11500
|
-
/* @__PURE__ */
|
|
11595
|
+
/* @__PURE__ */ jsx90("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: "Your access can't be verified right now. This will resolve on its own once the connection is back." })
|
|
11501
11596
|
]
|
|
11502
11597
|
}
|
|
11503
11598
|
);
|
|
@@ -11507,7 +11602,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
|
|
|
11507
11602
|
if (pending) {
|
|
11508
11603
|
if (pendingFallback !== void 0) return pendingFallback;
|
|
11509
11604
|
if (silent) return null;
|
|
11510
|
-
return /* @__PURE__ */
|
|
11605
|
+
return /* @__PURE__ */ jsx90(GatePending, { compact: compact3 });
|
|
11511
11606
|
}
|
|
11512
11607
|
let ok = true;
|
|
11513
11608
|
if (perm) ok = ok && can2(perm);
|
|
@@ -11516,7 +11611,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
|
|
|
11516
11611
|
if (ok) return children;
|
|
11517
11612
|
if (fallback !== void 0) return fallback;
|
|
11518
11613
|
if (silent) return null;
|
|
11519
|
-
return /* @__PURE__ */
|
|
11614
|
+
return /* @__PURE__ */ jsx90(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
|
|
11520
11615
|
}
|
|
11521
11616
|
function FeatureGate({
|
|
11522
11617
|
flag,
|
|
@@ -11539,7 +11634,7 @@ function FeatureGate({
|
|
|
11539
11634
|
const f = SessionKit.findFlag(flag) || {};
|
|
11540
11635
|
const missing = rt.missing || [];
|
|
11541
11636
|
const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
|
|
11542
|
-
return /* @__PURE__ */
|
|
11637
|
+
return /* @__PURE__ */ jsx90(
|
|
11543
11638
|
ComingSoon,
|
|
11544
11639
|
{
|
|
11545
11640
|
label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
|
|
@@ -11560,22 +11655,22 @@ function FeatureGate({
|
|
|
11560
11655
|
function PermissionHint({ perm, children }) {
|
|
11561
11656
|
const { can: can2, pending } = useSessionContext();
|
|
11562
11657
|
if (pending) {
|
|
11563
|
-
return /* @__PURE__ */
|
|
11658
|
+
return /* @__PURE__ */ jsx90("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ jsx90("span", { style: { pointerEvents: "none" }, children }) });
|
|
11564
11659
|
}
|
|
11565
11660
|
if (can2(perm)) return children;
|
|
11566
|
-
return /* @__PURE__ */
|
|
11661
|
+
return /* @__PURE__ */ jsx90(
|
|
11567
11662
|
"span",
|
|
11568
11663
|
{
|
|
11569
11664
|
title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
|
|
11570
11665
|
style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
|
|
11571
11666
|
"aria-disabled": "true",
|
|
11572
|
-
children: /* @__PURE__ */
|
|
11667
|
+
children: /* @__PURE__ */ jsx90("span", { style: { pointerEvents: "none" }, children })
|
|
11573
11668
|
}
|
|
11574
11669
|
);
|
|
11575
11670
|
}
|
|
11576
11671
|
|
|
11577
11672
|
// src/components/platform/ModeSwitch.tsx
|
|
11578
|
-
import { Fragment as Fragment25, jsx as
|
|
11673
|
+
import { Fragment as Fragment25, jsx as jsx91, jsxs as jsxs78 } from "react/jsx-runtime";
|
|
11579
11674
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
11580
11675
|
const mode2 = useRuntimeMode();
|
|
11581
11676
|
const panel = useInlinePanel();
|
|
@@ -11587,8 +11682,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
11587
11682
|
RuntimeKit.setMode(next);
|
|
11588
11683
|
setOpen(false);
|
|
11589
11684
|
};
|
|
11590
|
-
return /* @__PURE__ */
|
|
11591
|
-
/* @__PURE__ */
|
|
11685
|
+
return /* @__PURE__ */ jsxs78("span", { style: { display: "inline-flex" }, ref, children: [
|
|
11686
|
+
/* @__PURE__ */ jsxs78(
|
|
11592
11687
|
"button",
|
|
11593
11688
|
{
|
|
11594
11689
|
type: "button",
|
|
@@ -11598,29 +11693,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
11598
11693
|
title: test ? "Test mode \u2014 every response is simulated. Click to inspect requests or return to live mode." : "Live mode \u2014 incomplete features are shown under construction. Click for test mode.",
|
|
11599
11694
|
className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
|
|
11600
11695
|
children: [
|
|
11601
|
-
/* @__PURE__ */
|
|
11602
|
-
test && requestCount ? /* @__PURE__ */
|
|
11696
|
+
/* @__PURE__ */ jsx91("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
|
|
11697
|
+
test && requestCount ? /* @__PURE__ */ jsx91("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
|
|
11603
11698
|
]
|
|
11604
11699
|
}
|
|
11605
11700
|
),
|
|
11606
|
-
/* @__PURE__ */
|
|
11607
|
-
/* @__PURE__ */
|
|
11608
|
-
/* @__PURE__ */
|
|
11609
|
-
/* @__PURE__ */
|
|
11701
|
+
/* @__PURE__ */ jsxs78(InlinePanelSurface, { panel, align: "right", offset: 8, width: 400, className: "fd-mode-pop", label: test ? "Test mode" : "Live mode", children: [
|
|
11702
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
11703
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
|
|
11704
|
+
/* @__PURE__ */ jsx91("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
|
|
11610
11705
|
test ? "Test mode" : "Live mode"
|
|
11611
11706
|
] }),
|
|
11612
|
-
test ? /* @__PURE__ */
|
|
11707
|
+
test ? /* @__PURE__ */ jsxs78("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
11613
11708
|
requestCount,
|
|
11614
11709
|
" simulated request",
|
|
11615
11710
|
requestCount === 1 ? "" : "s"
|
|
11616
11711
|
] }) : null,
|
|
11617
|
-
/* @__PURE__ */
|
|
11618
|
-
test && onClearLog ? /* @__PURE__ */
|
|
11712
|
+
/* @__PURE__ */ jsx91("span", { style: { flex: 1 } }),
|
|
11713
|
+
test && onClearLog ? /* @__PURE__ */ jsx91("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
|
|
11619
11714
|
] }),
|
|
11620
|
-
/* @__PURE__ */
|
|
11621
|
-
/* @__PURE__ */
|
|
11622
|
-
/* @__PURE__ */
|
|
11623
|
-
/* @__PURE__ */
|
|
11715
|
+
/* @__PURE__ */ jsxs78("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
11716
|
+
/* @__PURE__ */ jsx91("span", { className: "fd-body-sm fd-secondary", style: { display: "block", textWrap: "pretty" }, children: test ? "Every feature is usable and nothing is obstructed, but no response comes from a real service \u2014 nothing you do here persists. Use this to review and demo the design." : "This is what a user would see today. " + s.incomplete + " of " + s.total + " features depend on backend work that is not wired yet, so they render under construction." }),
|
|
11717
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
|
|
11718
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
11624
11719
|
s.endpointsWired,
|
|
11625
11720
|
" endpoint",
|
|
11626
11721
|
s.endpointsWired === 1 ? "" : "s",
|
|
@@ -11630,58 +11725,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
11630
11725
|
s.total,
|
|
11631
11726
|
" features complete"
|
|
11632
11727
|
] }),
|
|
11633
|
-
onOpenSpec ? /* @__PURE__ */
|
|
11634
|
-
/* @__PURE__ */
|
|
11635
|
-
/* @__PURE__ */
|
|
11728
|
+
onOpenSpec ? /* @__PURE__ */ jsxs78(Fragment25, { children: [
|
|
11729
|
+
/* @__PURE__ */ jsx91("span", { style: { flex: 1 } }),
|
|
11730
|
+
/* @__PURE__ */ jsxs78("button", { type: "button", className: "fd-soon-link", onClick: () => {
|
|
11636
11731
|
setOpen(false);
|
|
11637
11732
|
onOpenSpec();
|
|
11638
11733
|
}, children: [
|
|
11639
11734
|
"API spec ",
|
|
11640
|
-
/* @__PURE__ */
|
|
11735
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
11641
11736
|
] })
|
|
11642
11737
|
] }) : null
|
|
11643
11738
|
] })
|
|
11644
11739
|
] }),
|
|
11645
|
-
/* @__PURE__ */
|
|
11646
|
-
/* @__PURE__ */
|
|
11647
|
-
/* @__PURE__ */
|
|
11648
|
-
/* @__PURE__ */
|
|
11649
|
-
/* @__PURE__ */
|
|
11650
|
-
/* @__PURE__ */
|
|
11740
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-mode-choice", children: [
|
|
11741
|
+
/* @__PURE__ */ jsxs78("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
|
|
11742
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
11743
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-mode-opt-text", children: [
|
|
11744
|
+
/* @__PURE__ */ jsx91("span", { className: "fd-mode-opt-title", children: "Live mode" }),
|
|
11745
|
+
/* @__PURE__ */ jsx91("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
|
|
11651
11746
|
] }),
|
|
11652
|
-
!test ? /* @__PURE__ */
|
|
11747
|
+
!test ? /* @__PURE__ */ jsx91("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
11653
11748
|
] }),
|
|
11654
|
-
/* @__PURE__ */
|
|
11655
|
-
/* @__PURE__ */
|
|
11656
|
-
/* @__PURE__ */
|
|
11657
|
-
/* @__PURE__ */
|
|
11658
|
-
/* @__PURE__ */
|
|
11749
|
+
/* @__PURE__ */ jsxs78("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
|
|
11750
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
11751
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-mode-opt-text", children: [
|
|
11752
|
+
/* @__PURE__ */ jsx91("span", { className: "fd-mode-opt-title", children: "Test mode" }),
|
|
11753
|
+
/* @__PURE__ */ jsx91("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
|
|
11659
11754
|
] }),
|
|
11660
|
-
test ? /* @__PURE__ */
|
|
11755
|
+
test ? /* @__PURE__ */ jsx91("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
11661
11756
|
] })
|
|
11662
11757
|
] }),
|
|
11663
|
-
test && renderLog ? /* @__PURE__ */
|
|
11758
|
+
test && renderLog ? /* @__PURE__ */ jsx91("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
|
|
11664
11759
|
] })
|
|
11665
11760
|
] });
|
|
11666
11761
|
}
|
|
11667
11762
|
function TestModeBar({ onExit }) {
|
|
11668
11763
|
const mode2 = useRuntimeMode();
|
|
11669
11764
|
if (mode2 !== "test") return null;
|
|
11670
|
-
return /* @__PURE__ */
|
|
11671
|
-
/* @__PURE__ */
|
|
11672
|
-
/* @__PURE__ */
|
|
11765
|
+
return /* @__PURE__ */ jsxs78("div", { className: "fd-testbar", role: "status", children: [
|
|
11766
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-badge fd-badge-warning", children: [
|
|
11767
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
11673
11768
|
"Test mode"
|
|
11674
11769
|
] }),
|
|
11675
|
-
/* @__PURE__ */
|
|
11676
|
-
/* @__PURE__ */
|
|
11677
|
-
/* @__PURE__ */
|
|
11770
|
+
/* @__PURE__ */ jsx91("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
|
|
11771
|
+
/* @__PURE__ */ jsxs78("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
|
|
11772
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
11678
11773
|
" Back to live mode"
|
|
11679
11774
|
] })
|
|
11680
11775
|
] });
|
|
11681
11776
|
}
|
|
11682
11777
|
|
|
11683
11778
|
// src/components/planner/ChannelMeta.tsx
|
|
11684
|
-
import { jsx as
|
|
11779
|
+
import { jsx as jsx92, jsxs as jsxs79 } from "react/jsx-runtime";
|
|
11685
11780
|
var CHANNEL_WEIGHTS = {
|
|
11686
11781
|
"OOH": 50,
|
|
11687
11782
|
"DOOH": 50,
|
|
@@ -11734,9 +11829,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
11734
11829
|
const m = ChannelMeta(channel);
|
|
11735
11830
|
const wt = channelWeightOf(channel || "");
|
|
11736
11831
|
if (dot) {
|
|
11737
|
-
return /* @__PURE__ */
|
|
11832
|
+
return /* @__PURE__ */ jsx92("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
|
|
11738
11833
|
}
|
|
11739
|
-
return /* @__PURE__ */
|
|
11834
|
+
return /* @__PURE__ */ jsxs79(
|
|
11740
11835
|
"span",
|
|
11741
11836
|
{
|
|
11742
11837
|
className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
|
|
@@ -11744,16 +11839,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
11744
11839
|
style: { "--chan": m.color },
|
|
11745
11840
|
...rest,
|
|
11746
11841
|
children: [
|
|
11747
|
-
/* @__PURE__ */
|
|
11748
|
-
showLabel ? /* @__PURE__ */
|
|
11749
|
-
weight ? /* @__PURE__ */
|
|
11842
|
+
/* @__PURE__ */ jsx92("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
|
|
11843
|
+
showLabel ? /* @__PURE__ */ jsx92("span", { className: "fd-chan-label", children: m.label }) : null,
|
|
11844
|
+
weight ? /* @__PURE__ */ jsx92("span", { className: "fd-chan-weight", children: wt || 0 }) : null
|
|
11750
11845
|
]
|
|
11751
11846
|
}
|
|
11752
11847
|
);
|
|
11753
11848
|
}
|
|
11754
11849
|
|
|
11755
11850
|
// src/components/planner/SaturationDistribution.tsx
|
|
11756
|
-
import { jsx as
|
|
11851
|
+
import { jsx as jsx93, jsxs as jsxs80 } from "react/jsx-runtime";
|
|
11757
11852
|
var BANDS2 = [
|
|
11758
11853
|
{ key: "weak", label: "Weak", n: 1, range: "< 50" },
|
|
11759
11854
|
{ key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
|
|
@@ -11764,24 +11859,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11764
11859
|
const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
|
|
11765
11860
|
const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
|
|
11766
11861
|
const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
|
|
11767
|
-
return /* @__PURE__ */
|
|
11768
|
-
/* @__PURE__ */
|
|
11862
|
+
return /* @__PURE__ */ jsxs80("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
11863
|
+
/* @__PURE__ */ jsx93("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
|
|
11769
11864
|
const mark = "var(--csi-" + g.n + "-mark)";
|
|
11770
11865
|
const active = selectedBand === g.key;
|
|
11771
|
-
return /* @__PURE__ */
|
|
11866
|
+
return /* @__PURE__ */ jsxs80(
|
|
11772
11867
|
"button",
|
|
11773
11868
|
{
|
|
11774
11869
|
type: "button",
|
|
11775
11870
|
onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
|
|
11776
11871
|
style: { display: "flex", flexDirection: "column", justifyContent: "flex-end", gap: 10, padding: 12, border: "1px solid " + (active ? "var(--border-strong)" : "var(--border)"), borderRadius: "var(--r-lg)", background: active ? "var(--surface-2)" : "var(--surface)", cursor: onSelectBand ? "pointer" : "default", textAlign: "left", minHeight: 190, minWidth: 0, transition: "background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease)" },
|
|
11777
11872
|
children: [
|
|
11778
|
-
/* @__PURE__ */
|
|
11873
|
+
/* @__PURE__ */ jsx93("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx93("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
|
|
11779
11874
|
// `overflow: hidden` + `white-space: nowrap` only clips once the span
|
|
11780
11875
|
// actually HAS a bounded width to clip against (see the grid/flex
|
|
11781
11876
|
// `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
|
|
11782
11877
|
// that clip readable instead of a hard cut mid-letter; the full name
|
|
11783
11878
|
// is still one hover away via `title`.
|
|
11784
|
-
/* @__PURE__ */
|
|
11879
|
+
/* @__PURE__ */ jsx93(
|
|
11785
11880
|
"span",
|
|
11786
11881
|
{
|
|
11787
11882
|
title: c.name + " \xB7 " + c.crp,
|
|
@@ -11791,13 +11886,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11791
11886
|
c.name
|
|
11792
11887
|
)
|
|
11793
11888
|
)) }),
|
|
11794
|
-
/* @__PURE__ */
|
|
11795
|
-
/* @__PURE__ */
|
|
11796
|
-
/* @__PURE__ */
|
|
11889
|
+
/* @__PURE__ */ jsxs80("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
|
|
11890
|
+
/* @__PURE__ */ jsx93("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
|
|
11891
|
+
/* @__PURE__ */ jsx93("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx93("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
|
|
11797
11892
|
] }),
|
|
11798
|
-
/* @__PURE__ */
|
|
11799
|
-
/* @__PURE__ */
|
|
11800
|
-
/* @__PURE__ */
|
|
11893
|
+
/* @__PURE__ */ jsxs80("span", { className: "fd-stack", style: { gap: 1 }, children: [
|
|
11894
|
+
/* @__PURE__ */ jsx93("span", { className: "fd-label-lg", children: g.label }),
|
|
11895
|
+
/* @__PURE__ */ jsxs80("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
|
|
11801
11896
|
"CRP ",
|
|
11802
11897
|
g.range
|
|
11803
11898
|
] })
|
|
@@ -11807,10 +11902,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11807
11902
|
g.key
|
|
11808
11903
|
);
|
|
11809
11904
|
}) }),
|
|
11810
|
-
floorBand ? /* @__PURE__ */
|
|
11811
|
-
/* @__PURE__ */
|
|
11812
|
-
/* @__PURE__ */
|
|
11813
|
-
/* @__PURE__ */
|
|
11905
|
+
floorBand ? /* @__PURE__ */ jsxs80("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderRadius: "var(--r-md)", background: "var(--surface-2)", border: "1px solid var(--border)", flexWrap: "wrap" }, children: [
|
|
11906
|
+
/* @__PURE__ */ jsx93("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx93("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
|
|
11907
|
+
/* @__PURE__ */ jsxs80("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
|
|
11908
|
+
/* @__PURE__ */ jsxs80("strong", { style: { color: "var(--text)" }, children: [
|
|
11814
11909
|
"Plan floor ",
|
|
11815
11910
|
floorScore
|
|
11816
11911
|
] }),
|
|
@@ -11821,8 +11916,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11821
11916
|
}
|
|
11822
11917
|
|
|
11823
11918
|
// src/components/planner/MixGap.tsx
|
|
11824
|
-
import * as
|
|
11825
|
-
import { Fragment as Fragment26, jsx as
|
|
11919
|
+
import * as React67 from "react";
|
|
11920
|
+
import { Fragment as Fragment26, jsx as jsx94, jsxs as jsxs81 } from "react/jsx-runtime";
|
|
11826
11921
|
var MIX_GAP_LAYOUT = {
|
|
11827
11922
|
trackHeight: 30,
|
|
11828
11923
|
barHeight: 20,
|
|
@@ -11836,19 +11931,19 @@ function mixGapOffset(value, max) {
|
|
|
11836
11931
|
}
|
|
11837
11932
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
11838
11933
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
11839
|
-
const [hover, setHover] =
|
|
11934
|
+
const [hover, setHover] = React67.useState(null);
|
|
11840
11935
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
11841
11936
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
11842
11937
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
11843
11938
|
const barTop = (trackHeight - barHeight) / 2;
|
|
11844
|
-
return /* @__PURE__ */
|
|
11845
|
-
/* @__PURE__ */
|
|
11846
|
-
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */
|
|
11847
|
-
/* @__PURE__ */
|
|
11939
|
+
return /* @__PURE__ */ jsxs81("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
|
|
11940
|
+
/* @__PURE__ */ jsxs81("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
|
|
11941
|
+
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs81("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
11942
|
+
/* @__PURE__ */ jsx94("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
|
|
11848
11943
|
l
|
|
11849
11944
|
] }, l)),
|
|
11850
|
-
/* @__PURE__ */
|
|
11851
|
-
/* @__PURE__ */
|
|
11945
|
+
/* @__PURE__ */ jsxs81("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
11946
|
+
/* @__PURE__ */ jsx94("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
|
|
11852
11947
|
"Target"
|
|
11853
11948
|
] })
|
|
11854
11949
|
] }),
|
|
@@ -11857,7 +11952,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11857
11952
|
const tone = toneOf(gap);
|
|
11858
11953
|
const tip = "Realized " + r.realized + "% vs " + r.target + "% target" + (gap < -1 ? " \xB7 " + Math.abs(gap).toFixed(0) + " pts short" : gap > 1 ? " \xB7 " + gap.toFixed(0) + " pts over" : " \xB7 on target") + (r.note ? " \u2014 " + r.note : "");
|
|
11859
11954
|
const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
|
|
11860
|
-
return /* @__PURE__ */
|
|
11955
|
+
return /* @__PURE__ */ jsxs81(
|
|
11861
11956
|
"div",
|
|
11862
11957
|
{
|
|
11863
11958
|
className: "fd-row",
|
|
@@ -11865,15 +11960,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11865
11960
|
onMouseEnter: () => setHover(r.channel),
|
|
11866
11961
|
onMouseLeave: () => setHover(null),
|
|
11867
11962
|
children: [
|
|
11868
|
-
/* @__PURE__ */
|
|
11869
|
-
/* @__PURE__ */
|
|
11870
|
-
/* @__PURE__ */
|
|
11871
|
-
/* @__PURE__ */
|
|
11872
|
-
/* @__PURE__ */
|
|
11963
|
+
/* @__PURE__ */ jsx94("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx94(ChannelTag, { channel: r.channel, size: "sm" }) }),
|
|
11964
|
+
/* @__PURE__ */ jsx94("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx94("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs81(Fragment26, { children: [
|
|
11965
|
+
/* @__PURE__ */ jsx94("span", { "data-mixgap-bar": "", style: { position: "absolute", left: 0, top: barTop, height: barHeight, width: mixGapOffset(r.realized, max), background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
|
|
11966
|
+
/* @__PURE__ */ jsx94("span", { "data-mixgap-target": "", style: { position: "absolute", left: `calc(${mixGapOffset(r.target, max)} - ${targetWidth / 2}px)`, top: 0, width: targetWidth, height: trackHeight, background: MIX_GAP_TARGET_STRIPE, borderRadius: 1 } }),
|
|
11967
|
+
/* @__PURE__ */ jsxs81("span", { "data-mixgap-label": "", className: "fd-num", style: { position: "absolute", left: labelLeft, top: "50%", transform: "translateY(-50%)", fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap" }, children: [
|
|
11873
11968
|
r.realized,
|
|
11874
11969
|
"%"
|
|
11875
11970
|
] }),
|
|
11876
|
-
hover === r.channel ? /* @__PURE__ */
|
|
11971
|
+
hover === r.channel ? /* @__PURE__ */ jsx94("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: trackHeight + 4, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
|
|
11877
11972
|
] }) })
|
|
11878
11973
|
]
|
|
11879
11974
|
},
|
|
@@ -11884,7 +11979,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11884
11979
|
}
|
|
11885
11980
|
|
|
11886
11981
|
// src/components/planner/ChannelContribution.tsx
|
|
11887
|
-
import { jsx as
|
|
11982
|
+
import { jsx as jsx95, jsxs as jsxs82 } from "react/jsx-runtime";
|
|
11888
11983
|
var money = (n) => "$" + Math.round(n).toLocaleString();
|
|
11889
11984
|
function ChannelContribution({
|
|
11890
11985
|
channels = [],
|
|
@@ -11900,9 +11995,9 @@ function ChannelContribution({
|
|
|
11900
11995
|
const grand = total !== void 0 ? total : base + bonus;
|
|
11901
11996
|
const pct = (v) => grand ? v / grand * 100 : 0;
|
|
11902
11997
|
const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
|
|
11903
|
-
return /* @__PURE__ */
|
|
11904
|
-
loading ? /* @__PURE__ */
|
|
11905
|
-
channels.map((c) => /* @__PURE__ */
|
|
11998
|
+
return /* @__PURE__ */ jsxs82("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
11999
|
+
loading ? /* @__PURE__ */ jsx95("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs82("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
|
|
12000
|
+
channels.map((c) => /* @__PURE__ */ jsx95(
|
|
11906
12001
|
"span",
|
|
11907
12002
|
{
|
|
11908
12003
|
title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
|
|
@@ -11911,7 +12006,7 @@ function ChannelContribution({
|
|
|
11911
12006
|
},
|
|
11912
12007
|
c.name
|
|
11913
12008
|
)),
|
|
11914
|
-
bonus > 0 ? /* @__PURE__ */
|
|
12009
|
+
bonus > 0 ? /* @__PURE__ */ jsx95(
|
|
11915
12010
|
"span",
|
|
11916
12011
|
{
|
|
11917
12012
|
title: "Surround-sound bonus +" + bonusPct + "%",
|
|
@@ -11920,18 +12015,18 @@ function ChannelContribution({
|
|
|
11920
12015
|
}
|
|
11921
12016
|
) : null
|
|
11922
12017
|
] }),
|
|
11923
|
-
showTable ? /* @__PURE__ */
|
|
11924
|
-
/* @__PURE__ */
|
|
11925
|
-
/* @__PURE__ */
|
|
11926
|
-
/* @__PURE__ */
|
|
11927
|
-
/* @__PURE__ */
|
|
11928
|
-
/* @__PURE__ */
|
|
11929
|
-
/* @__PURE__ */
|
|
12018
|
+
showTable ? /* @__PURE__ */ jsxs82("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
|
|
12019
|
+
/* @__PURE__ */ jsx95("thead", { children: /* @__PURE__ */ jsxs82("tr", { children: [
|
|
12020
|
+
/* @__PURE__ */ jsx95("th", { style: { width: "34%" }, children: "Channel" }),
|
|
12021
|
+
/* @__PURE__ */ jsx95("th", { style: { width: "16%" }, children: "Weight" }),
|
|
12022
|
+
/* @__PURE__ */ jsx95("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
|
|
12023
|
+
/* @__PURE__ */ jsx95("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
|
|
12024
|
+
/* @__PURE__ */ jsx95("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
|
|
11930
12025
|
] }) }),
|
|
11931
|
-
/* @__PURE__ */
|
|
11932
|
-
channels.map((c) => /* @__PURE__ */
|
|
11933
|
-
/* @__PURE__ */
|
|
11934
|
-
/* @__PURE__ */
|
|
12026
|
+
/* @__PURE__ */ jsxs82("tbody", { children: [
|
|
12027
|
+
channels.map((c) => /* @__PURE__ */ jsxs82("tr", { children: [
|
|
12028
|
+
/* @__PURE__ */ jsx95("td", { children: /* @__PURE__ */ jsx95(ChannelTag, { channel: c.name, size: "sm" }) }),
|
|
12029
|
+
/* @__PURE__ */ jsx95("td", { children: /* @__PURE__ */ jsx95(
|
|
11935
12030
|
"span",
|
|
11936
12031
|
{
|
|
11937
12032
|
className: "fd-badge fd-badge-neutral",
|
|
@@ -11940,38 +12035,38 @@ function ChannelContribution({
|
|
|
11940
12035
|
children: "weight " + (channelWeightOf(c.name) || 0)
|
|
11941
12036
|
}
|
|
11942
12037
|
) }),
|
|
11943
|
-
/* @__PURE__ */
|
|
11944
|
-
/* @__PURE__ */
|
|
11945
|
-
/* @__PURE__ */
|
|
12038
|
+
/* @__PURE__ */ jsx95("td", { className: "is-num", children: c.spend }),
|
|
12039
|
+
/* @__PURE__ */ jsx95("td", { className: "is-num", children: c.crp.toFixed(1) }),
|
|
12040
|
+
/* @__PURE__ */ jsxs82("td", { className: "is-num", children: [
|
|
11946
12041
|
pct(c.crp).toFixed(0),
|
|
11947
12042
|
"%"
|
|
11948
12043
|
] })
|
|
11949
12044
|
] }, c.name)),
|
|
11950
|
-
bonus > 0 ? /* @__PURE__ */
|
|
11951
|
-
/* @__PURE__ */
|
|
11952
|
-
/* @__PURE__ */
|
|
12045
|
+
bonus > 0 ? /* @__PURE__ */ jsxs82("tr", { children: [
|
|
12046
|
+
/* @__PURE__ */ jsx95("td", { children: /* @__PURE__ */ jsxs82("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
|
|
12047
|
+
/* @__PURE__ */ jsx95("span", { style: { width: 9, height: 9, borderRadius: 2, background: "repeating-linear-gradient(135deg,var(--csi-3-mark) 0 3px,var(--csi-2-mark) 3px 6px)", flex: "none" } }),
|
|
11953
12048
|
"Surround-sound bonus"
|
|
11954
12049
|
] }) }),
|
|
11955
|
-
/* @__PURE__ */
|
|
12050
|
+
/* @__PURE__ */ jsx95("td", { children: /* @__PURE__ */ jsxs82("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
|
|
11956
12051
|
"+",
|
|
11957
12052
|
bonusPct,
|
|
11958
12053
|
"% of +",
|
|
11959
12054
|
bonusMax,
|
|
11960
12055
|
"%"
|
|
11961
12056
|
] }) }),
|
|
11962
|
-
/* @__PURE__ */
|
|
11963
|
-
/* @__PURE__ */
|
|
11964
|
-
/* @__PURE__ */
|
|
12057
|
+
/* @__PURE__ */ jsx95("td", { className: "is-num fd-muted", children: "\u2014" }),
|
|
12058
|
+
/* @__PURE__ */ jsx95("td", { className: "is-num", children: bonus.toFixed(1) }),
|
|
12059
|
+
/* @__PURE__ */ jsxs82("td", { className: "is-num", children: [
|
|
11965
12060
|
pct(bonus).toFixed(0),
|
|
11966
12061
|
"%"
|
|
11967
12062
|
] })
|
|
11968
12063
|
] }) : null,
|
|
11969
|
-
/* @__PURE__ */
|
|
11970
|
-
/* @__PURE__ */
|
|
11971
|
-
/* @__PURE__ */
|
|
11972
|
-
/* @__PURE__ */
|
|
11973
|
-
/* @__PURE__ */
|
|
11974
|
-
/* @__PURE__ */
|
|
12064
|
+
/* @__PURE__ */ jsxs82("tr", { style: { background: "var(--surface-2)" }, children: [
|
|
12065
|
+
/* @__PURE__ */ jsx95("td", { style: { fontWeight: 700 }, children: "Campus total" }),
|
|
12066
|
+
/* @__PURE__ */ jsx95("td", {}),
|
|
12067
|
+
/* @__PURE__ */ jsx95("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
|
|
12068
|
+
/* @__PURE__ */ jsx95("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
|
|
12069
|
+
/* @__PURE__ */ jsx95("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
|
|
11975
12070
|
] })
|
|
11976
12071
|
] })
|
|
11977
12072
|
] }) : null
|
|
@@ -11979,8 +12074,8 @@ function ChannelContribution({
|
|
|
11979
12074
|
}
|
|
11980
12075
|
|
|
11981
12076
|
// src/components/planner/BudgetReallocator.tsx
|
|
11982
|
-
import * as
|
|
11983
|
-
import { Fragment as Fragment27, jsx as
|
|
12077
|
+
import * as React68 from "react";
|
|
12078
|
+
import { Fragment as Fragment27, jsx as jsx96, jsxs as jsxs83 } from "react/jsx-runtime";
|
|
11984
12079
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
11985
12080
|
function BudgetReallocator({
|
|
11986
12081
|
campus,
|
|
@@ -11995,8 +12090,8 @@ function BudgetReallocator({
|
|
|
11995
12090
|
onCancel,
|
|
11996
12091
|
className = ""
|
|
11997
12092
|
}) {
|
|
11998
|
-
const [draft, setDraft] =
|
|
11999
|
-
|
|
12093
|
+
const [draft, setDraft] = React68.useState(spend);
|
|
12094
|
+
React68.useEffect(() => setDraft(spend), [spend]);
|
|
12000
12095
|
const dirty = draft !== spend;
|
|
12001
12096
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
12002
12097
|
const nextBand = bandFor(nextCrp);
|
|
@@ -12011,10 +12106,10 @@ function BudgetReallocator({
|
|
|
12011
12106
|
setDraft(spend);
|
|
12012
12107
|
if (onCancel) onCancel();
|
|
12013
12108
|
};
|
|
12014
|
-
const trackRef =
|
|
12015
|
-
const chipRef =
|
|
12016
|
-
const [chipLeft, setChipLeft] =
|
|
12017
|
-
|
|
12109
|
+
const trackRef = React68.useRef(null);
|
|
12110
|
+
const chipRef = React68.useRef(null);
|
|
12111
|
+
const [chipLeft, setChipLeft] = React68.useState(null);
|
|
12112
|
+
React68.useLayoutEffect(() => {
|
|
12018
12113
|
const track = trackRef.current;
|
|
12019
12114
|
if (!dirty || !track) {
|
|
12020
12115
|
setChipLeft(null);
|
|
@@ -12035,23 +12130,23 @@ function BudgetReallocator({
|
|
|
12035
12130
|
ro.observe(track);
|
|
12036
12131
|
return () => ro.disconnect();
|
|
12037
12132
|
}, [dirty, pct]);
|
|
12038
|
-
return /* @__PURE__ */
|
|
12133
|
+
return /* @__PURE__ */ jsxs83(
|
|
12039
12134
|
"div",
|
|
12040
12135
|
{
|
|
12041
12136
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
12042
12137
|
style: { gap: 14, padding: 18, border: "1px solid " + (dirty ? "var(--border-brand)" : "var(--border)"), borderRadius: "var(--r-lg)", background: dirty ? "var(--surface-brand)" : "var(--surface)", color: "var(--text)", transition: "background var(--dur-base) var(--ease),border-color var(--dur-base) var(--ease)" },
|
|
12043
12138
|
children: [
|
|
12044
|
-
/* @__PURE__ */
|
|
12045
|
-
/* @__PURE__ */
|
|
12046
|
-
/* @__PURE__ */
|
|
12047
|
-
dirty ? /* @__PURE__ */
|
|
12048
|
-
/* @__PURE__ */
|
|
12049
|
-
/* @__PURE__ */
|
|
12139
|
+
/* @__PURE__ */ jsxs83("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
12140
|
+
/* @__PURE__ */ jsx96("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
|
|
12141
|
+
/* @__PURE__ */ jsx96(CsiBadge, { band: nowBand, crp, size: "medium" }),
|
|
12142
|
+
dirty ? /* @__PURE__ */ jsxs83(Fragment27, { children: [
|
|
12143
|
+
/* @__PURE__ */ jsx96("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
|
|
12144
|
+
/* @__PURE__ */ jsx96(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
|
|
12050
12145
|
] }) : null
|
|
12051
12146
|
] }),
|
|
12052
|
-
/* @__PURE__ */
|
|
12053
|
-
/* @__PURE__ */
|
|
12054
|
-
dirty ? /* @__PURE__ */
|
|
12147
|
+
/* @__PURE__ */ jsxs83("div", { className: "fd-slider", ref: trackRef, children: [
|
|
12148
|
+
/* @__PURE__ */ jsx96("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
12149
|
+
dirty ? /* @__PURE__ */ jsx96(
|
|
12055
12150
|
"span",
|
|
12056
12151
|
{
|
|
12057
12152
|
ref: chipRef,
|
|
@@ -12063,7 +12158,7 @@ function BudgetReallocator({
|
|
|
12063
12158
|
children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
|
|
12064
12159
|
}
|
|
12065
12160
|
) : null,
|
|
12066
|
-
/* @__PURE__ */
|
|
12161
|
+
/* @__PURE__ */ jsx96(
|
|
12067
12162
|
"input",
|
|
12068
12163
|
{
|
|
12069
12164
|
type: "range",
|
|
@@ -12079,13 +12174,13 @@ function BudgetReallocator({
|
|
|
12079
12174
|
}
|
|
12080
12175
|
)
|
|
12081
12176
|
] }),
|
|
12082
|
-
/* @__PURE__ */
|
|
12083
|
-
/* @__PURE__ */
|
|
12084
|
-
/* @__PURE__ */
|
|
12085
|
-
/* @__PURE__ */
|
|
12177
|
+
/* @__PURE__ */ jsxs83("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
12178
|
+
/* @__PURE__ */ jsxs83("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
|
|
12179
|
+
/* @__PURE__ */ jsx96("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
|
|
12180
|
+
/* @__PURE__ */ jsx96("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
|
|
12086
12181
|
] }),
|
|
12087
|
-
/* @__PURE__ */
|
|
12088
|
-
/* @__PURE__ */
|
|
12182
|
+
/* @__PURE__ */ jsx96("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
|
|
12183
|
+
/* @__PURE__ */ jsx96(
|
|
12089
12184
|
"button",
|
|
12090
12185
|
{
|
|
12091
12186
|
type: "button",
|
|
@@ -12104,7 +12199,7 @@ function BudgetReallocator({
|
|
|
12104
12199
|
}
|
|
12105
12200
|
|
|
12106
12201
|
// src/components/planner/SurroundSound.tsx
|
|
12107
|
-
import { jsx as
|
|
12202
|
+
import { jsx as jsx97, jsxs as jsxs84 } from "react/jsx-runtime";
|
|
12108
12203
|
var CATEGORIES = [
|
|
12109
12204
|
{ key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
|
|
12110
12205
|
{ key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
|
|
@@ -12116,26 +12211,26 @@ var CATEGORIES = [
|
|
|
12116
12211
|
function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
|
|
12117
12212
|
const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
|
|
12118
12213
|
const single = present.length <= 2;
|
|
12119
|
-
return /* @__PURE__ */
|
|
12120
|
-
/* @__PURE__ */
|
|
12214
|
+
return /* @__PURE__ */ jsxs84("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
|
|
12215
|
+
/* @__PURE__ */ jsx97("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
|
|
12121
12216
|
const on = present.includes(c.key);
|
|
12122
|
-
return /* @__PURE__ */
|
|
12217
|
+
return /* @__PURE__ */ jsxs84(
|
|
12123
12218
|
"span",
|
|
12124
12219
|
{
|
|
12125
12220
|
title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
|
|
12126
12221
|
style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 5, width: 62, padding: "10px 0", borderRadius: "var(--r-md)", border: "1px solid " + (on ? "var(--csi-2-edge)" : "var(--border)"), background: on ? "var(--csi-2-fill)" : "var(--surface-2)", color: on ? "var(--csi-2-text)" : "var(--text-disabled)" },
|
|
12127
12222
|
children: [
|
|
12128
|
-
/* @__PURE__ */
|
|
12129
|
-
/* @__PURE__ */
|
|
12223
|
+
/* @__PURE__ */ jsx97("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
12224
|
+
/* @__PURE__ */ jsx97("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
|
|
12130
12225
|
]
|
|
12131
12226
|
},
|
|
12132
12227
|
c.key
|
|
12133
12228
|
);
|
|
12134
12229
|
}) }),
|
|
12135
|
-
/* @__PURE__ */
|
|
12136
|
-
/* @__PURE__ */
|
|
12137
|
-
/* @__PURE__ */
|
|
12138
|
-
/* @__PURE__ */
|
|
12230
|
+
/* @__PURE__ */ jsxs84("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
12231
|
+
/* @__PURE__ */ jsxs84("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
12232
|
+
/* @__PURE__ */ jsx97("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
|
|
12233
|
+
/* @__PURE__ */ jsxs84("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
|
|
12139
12234
|
"+",
|
|
12140
12235
|
bonusPct,
|
|
12141
12236
|
"% of +",
|
|
@@ -12143,8 +12238,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
12143
12238
|
"%"
|
|
12144
12239
|
] })
|
|
12145
12240
|
] }),
|
|
12146
|
-
/* @__PURE__ */
|
|
12147
|
-
/* @__PURE__ */
|
|
12241
|
+
/* @__PURE__ */ jsx97("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx97("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
|
|
12242
|
+
/* @__PURE__ */ jsxs84("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
|
|
12148
12243
|
present.length,
|
|
12149
12244
|
" of 6 channel categories present.",
|
|
12150
12245
|
" ",
|
|
@@ -12156,7 +12251,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
12156
12251
|
}
|
|
12157
12252
|
|
|
12158
12253
|
// src/components/planner/Importance.tsx
|
|
12159
|
-
import { jsx as
|
|
12254
|
+
import { jsx as jsx98, jsxs as jsxs85 } from "react/jsx-runtime";
|
|
12160
12255
|
var IMPORTANCE_LEVELS = [
|
|
12161
12256
|
{ id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
|
|
12162
12257
|
{ id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
|
|
@@ -12186,7 +12281,7 @@ function importanceTokens(id) {
|
|
|
12186
12281
|
function ImportanceTag({ level, showLabel = true, size = "sm", className = "", disabled = false }) {
|
|
12187
12282
|
const lvl = importanceLevel(level);
|
|
12188
12283
|
const t = importanceTokens(level);
|
|
12189
|
-
return /* @__PURE__ */
|
|
12284
|
+
return /* @__PURE__ */ jsxs85(
|
|
12190
12285
|
"span",
|
|
12191
12286
|
{
|
|
12192
12287
|
className: ["fd-imp-tag", size === "md" ? "is-md" : "", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "),
|
|
@@ -12194,16 +12289,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
|
|
|
12194
12289
|
title: lvl.label + " \u2014 " + lvl.description,
|
|
12195
12290
|
"aria-disabled": disabled ? "true" : void 0,
|
|
12196
12291
|
children: [
|
|
12197
|
-
/* @__PURE__ */
|
|
12198
|
-
showLabel ? lvl.label : /* @__PURE__ */
|
|
12292
|
+
/* @__PURE__ */ jsx98("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
|
|
12293
|
+
showLabel ? lvl.label : /* @__PURE__ */ jsx98("span", { className: "fd-sr", children: lvl.label })
|
|
12199
12294
|
]
|
|
12200
12295
|
}
|
|
12201
12296
|
);
|
|
12202
12297
|
}
|
|
12203
12298
|
|
|
12204
12299
|
// src/components/planner/PreferenceMeter.tsx
|
|
12205
|
-
import * as
|
|
12206
|
-
import { jsx as
|
|
12300
|
+
import * as React69 from "react";
|
|
12301
|
+
import { jsx as jsx99, jsxs as jsxs86 } from "react/jsx-runtime";
|
|
12207
12302
|
function preferenceScore(criteria) {
|
|
12208
12303
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
12209
12304
|
const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
|
|
@@ -12232,8 +12327,8 @@ function PreferenceMeter({
|
|
|
12232
12327
|
className = ""
|
|
12233
12328
|
}) {
|
|
12234
12329
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
12235
|
-
const segments =
|
|
12236
|
-
return /* @__PURE__ */
|
|
12330
|
+
const segments = React69.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
12331
|
+
return /* @__PURE__ */ jsx99(
|
|
12237
12332
|
ScoreMeter,
|
|
12238
12333
|
{
|
|
12239
12334
|
score: value,
|
|
@@ -12245,22 +12340,22 @@ function PreferenceMeter({
|
|
|
12245
12340
|
placement,
|
|
12246
12341
|
className,
|
|
12247
12342
|
breakdownLabel: breakdownTitle,
|
|
12248
|
-
breakdown: /* @__PURE__ */
|
|
12249
|
-
/* @__PURE__ */
|
|
12250
|
-
/* @__PURE__ */
|
|
12251
|
-
/* @__PURE__ */
|
|
12343
|
+
breakdown: /* @__PURE__ */ jsxs86("div", { className: "fd-prefbreak", children: [
|
|
12344
|
+
/* @__PURE__ */ jsxs86("div", { className: "fd-prefbreak-head", children: [
|
|
12345
|
+
/* @__PURE__ */ jsx99("span", { className: "fd-label-lg", children: breakdownTitle }),
|
|
12346
|
+
/* @__PURE__ */ jsx99("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
|
|
12252
12347
|
] }),
|
|
12253
|
-
/* @__PURE__ */
|
|
12348
|
+
/* @__PURE__ */ jsx99("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
|
|
12254
12349
|
const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
|
|
12255
|
-
return /* @__PURE__ */
|
|
12256
|
-
/* @__PURE__ */
|
|
12257
|
-
/* @__PURE__ */
|
|
12258
|
-
/* @__PURE__ */
|
|
12259
|
-
c.note ? /* @__PURE__ */
|
|
12350
|
+
return /* @__PURE__ */ jsxs86("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
|
|
12351
|
+
/* @__PURE__ */ jsx99(ImportanceTag, { level: c.importance }),
|
|
12352
|
+
/* @__PURE__ */ jsxs86("span", { className: "fd-prefbreak-text", children: [
|
|
12353
|
+
/* @__PURE__ */ jsx99("span", { className: "fd-prefbreak-label", children: c.label }),
|
|
12354
|
+
c.note ? /* @__PURE__ */ jsx99("span", { className: "fd-prefbreak-note", children: c.note }) : null
|
|
12260
12355
|
] }),
|
|
12261
|
-
/* @__PURE__ */
|
|
12356
|
+
/* @__PURE__ */ jsxs86("span", { className: "fd-prefbreak-val fd-tabular", children: [
|
|
12262
12357
|
Math.round(Number(c.earned) || 0),
|
|
12263
|
-
/* @__PURE__ */
|
|
12358
|
+
/* @__PURE__ */ jsx99("span", { className: "fd-prefbreak-sep", children: "/" }),
|
|
12264
12359
|
Math.round(c.weight)
|
|
12265
12360
|
] })
|
|
12266
12361
|
] }, c.id);
|
|
@@ -12271,10 +12366,10 @@ function PreferenceMeter({
|
|
|
12271
12366
|
}
|
|
12272
12367
|
|
|
12273
12368
|
// src/components/chat/AgentChatPanel.tsx
|
|
12274
|
-
import * as
|
|
12369
|
+
import * as React75 from "react";
|
|
12275
12370
|
|
|
12276
12371
|
// src/components/chat/chatEngine.ts
|
|
12277
|
-
import * as
|
|
12372
|
+
import * as React70 from "react";
|
|
12278
12373
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
12279
12374
|
var JOB_PENDING = ["queued", "running"];
|
|
12280
12375
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -12319,7 +12414,7 @@ function useChatEngine(opts) {
|
|
|
12319
12414
|
initialMessage,
|
|
12320
12415
|
threadId: threadIdProp,
|
|
12321
12416
|
pollIntervalMs = 1500,
|
|
12322
|
-
|
|
12417
|
+
pendingTimeoutMs = 18e4,
|
|
12323
12418
|
store = safeStore,
|
|
12324
12419
|
onPacket,
|
|
12325
12420
|
onThreadReady,
|
|
@@ -12328,22 +12423,22 @@ function useChatEngine(opts) {
|
|
|
12328
12423
|
onClear,
|
|
12329
12424
|
onFeedback
|
|
12330
12425
|
} = opts || {};
|
|
12331
|
-
const [status, setStatus] =
|
|
12332
|
-
const [threadId, setThreadId] =
|
|
12333
|
-
const [messages, setMessages] =
|
|
12334
|
-
const [queue, setQueue] =
|
|
12335
|
-
const [fatal, setFatal] =
|
|
12336
|
-
const [busy, setBusy] =
|
|
12337
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
12338
|
-
const listRef =
|
|
12339
|
-
const queueRef =
|
|
12340
|
-
const busyRef =
|
|
12341
|
-
const stoppedRef =
|
|
12342
|
-
const abortRef =
|
|
12343
|
-
const serverCount =
|
|
12344
|
-
const threadRef =
|
|
12345
|
-
const mounted =
|
|
12346
|
-
|
|
12426
|
+
const [status, setStatus] = React70.useState("idle");
|
|
12427
|
+
const [threadId, setThreadId] = React70.useState(null);
|
|
12428
|
+
const [messages, setMessages] = React70.useState([]);
|
|
12429
|
+
const [queue, setQueue] = React70.useState([]);
|
|
12430
|
+
const [fatal, setFatal] = React70.useState(null);
|
|
12431
|
+
const [busy, setBusy] = React70.useState(false);
|
|
12432
|
+
const [turnStartedAt, setTurnStartedAt] = React70.useState(null);
|
|
12433
|
+
const listRef = React70.useRef([]);
|
|
12434
|
+
const queueRef = React70.useRef([]);
|
|
12435
|
+
const busyRef = React70.useRef(false);
|
|
12436
|
+
const stoppedRef = React70.useRef(false);
|
|
12437
|
+
const abortRef = React70.useRef(null);
|
|
12438
|
+
const serverCount = React70.useRef(0);
|
|
12439
|
+
const threadRef = React70.useRef(null);
|
|
12440
|
+
const mounted = React70.useRef(true);
|
|
12441
|
+
React70.useEffect(() => {
|
|
12347
12442
|
mounted.current = true;
|
|
12348
12443
|
return () => {
|
|
12349
12444
|
mounted.current = false;
|
|
@@ -12365,14 +12460,21 @@ function useChatEngine(opts) {
|
|
|
12365
12460
|
}
|
|
12366
12461
|
return false;
|
|
12367
12462
|
};
|
|
12368
|
-
const loadThread =
|
|
12463
|
+
const loadThread = React70.useCallback(async (id) => {
|
|
12369
12464
|
const data = await apiAdapter.getThread(id);
|
|
12370
12465
|
const list = [...data && data.messages || []];
|
|
12371
12466
|
serverCount.current = list.length;
|
|
12372
12467
|
commit(list);
|
|
12373
12468
|
return list;
|
|
12374
12469
|
}, [apiAdapter]);
|
|
12375
|
-
|
|
12470
|
+
async function mergeThread() {
|
|
12471
|
+
const data = await apiAdapter.getThread(threadRef.current);
|
|
12472
|
+
const server = data && data.messages || [];
|
|
12473
|
+
const ids = new Set(server.map((m) => m.id));
|
|
12474
|
+
serverCount.current = server.length;
|
|
12475
|
+
commit([...server, ...listRef.current.filter((m) => !ids.has(m.id))]);
|
|
12476
|
+
}
|
|
12477
|
+
React70.useEffect(() => {
|
|
12376
12478
|
if (!apiAdapter) {
|
|
12377
12479
|
setStatus("idle");
|
|
12378
12480
|
setFatal(null);
|
|
@@ -12418,7 +12520,9 @@ function useChatEngine(opts) {
|
|
|
12418
12520
|
setStatus("ready");
|
|
12419
12521
|
onThreadReady && onThreadReady(id);
|
|
12420
12522
|
const stored = store.get(STORAGE_PREFIX + id);
|
|
12523
|
+
const last = [...visibleMessages(listRef.current)].reverse().find((m) => m.role === "assistant");
|
|
12421
12524
|
if (stored) resumeJob(stored);
|
|
12525
|
+
else if (last && last.working && last.jobId) resumeJob(last.jobId, last.id);
|
|
12422
12526
|
else if (initialMessage) send(initialMessage);
|
|
12423
12527
|
} catch (err) {
|
|
12424
12528
|
if (dead) return;
|
|
@@ -12434,8 +12538,8 @@ function useChatEngine(opts) {
|
|
|
12434
12538
|
}, [apiAdapter, contextType, contextId, threadIdProp]);
|
|
12435
12539
|
async function pollJob(jobId, placeholderId) {
|
|
12436
12540
|
store.set(STORAGE_PREFIX + threadRef.current, jobId);
|
|
12437
|
-
|
|
12438
|
-
while (
|
|
12541
|
+
const deadline = Date.now() + pendingTimeoutMs;
|
|
12542
|
+
while (true) {
|
|
12439
12543
|
if (stoppedRef.current) break;
|
|
12440
12544
|
await sleep(pollIntervalMs);
|
|
12441
12545
|
if (!mounted.current) return;
|
|
@@ -12453,7 +12557,15 @@ function useChatEngine(opts) {
|
|
|
12453
12557
|
}
|
|
12454
12558
|
patch(placeholderId, { job });
|
|
12455
12559
|
const bucket2 = jobBucket(job && job.status);
|
|
12456
|
-
if (bucket2 === "pending")
|
|
12560
|
+
if (bucket2 === "pending") {
|
|
12561
|
+
try {
|
|
12562
|
+
await mergeThread();
|
|
12563
|
+
} catch (err) {
|
|
12564
|
+
fail(err);
|
|
12565
|
+
}
|
|
12566
|
+
if (Date.now() >= deadline) break;
|
|
12567
|
+
continue;
|
|
12568
|
+
}
|
|
12457
12569
|
if (bucket2 === "success") {
|
|
12458
12570
|
finishJob(jobId, job);
|
|
12459
12571
|
return;
|
|
@@ -12490,9 +12602,10 @@ function useChatEngine(opts) {
|
|
|
12490
12602
|
patch(placeholderId, { working: false, streaming: false, error: code, retryable: !!retryable, job: job || void 0 });
|
|
12491
12603
|
onError && onError(new Error(code));
|
|
12492
12604
|
}
|
|
12493
|
-
function resumeJob(jobId) {
|
|
12494
|
-
const id = uid("a");
|
|
12495
|
-
|
|
12605
|
+
function resumeJob(jobId, existingId) {
|
|
12606
|
+
const id = existingId || uid("a");
|
|
12607
|
+
if (existingId) patch(id, { working: true, resumed: true });
|
|
12608
|
+
else push({ id, role: "assistant", working: true, jobId, resumed: true });
|
|
12496
12609
|
setBusy(true);
|
|
12497
12610
|
busyRef.current = true;
|
|
12498
12611
|
setTurnStartedAt(Date.now());
|
|
@@ -12585,7 +12698,7 @@ function useChatEngine(opts) {
|
|
|
12585
12698
|
await dispatchTurn(turn);
|
|
12586
12699
|
}
|
|
12587
12700
|
}
|
|
12588
|
-
const send =
|
|
12701
|
+
const send = React70.useCallback((text, attachments) => {
|
|
12589
12702
|
const body = (text || "").trim();
|
|
12590
12703
|
if (!body && !(attachments && attachments.length)) return;
|
|
12591
12704
|
if (status === "disconnected") return;
|
|
@@ -12595,7 +12708,7 @@ function useChatEngine(opts) {
|
|
|
12595
12708
|
stoppedRef.current = false;
|
|
12596
12709
|
drain();
|
|
12597
12710
|
}, [status]);
|
|
12598
|
-
const stop =
|
|
12711
|
+
const stop = React70.useCallback(() => {
|
|
12599
12712
|
stoppedRef.current = true;
|
|
12600
12713
|
const ac = abortRef.current;
|
|
12601
12714
|
if (ac) {
|
|
@@ -12614,11 +12727,11 @@ function useChatEngine(opts) {
|
|
|
12614
12727
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
12615
12728
|
}
|
|
12616
12729
|
}, [apiAdapter]);
|
|
12617
|
-
const removeQueued =
|
|
12730
|
+
const removeQueued = React70.useCallback((id) => {
|
|
12618
12731
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
12619
12732
|
setQueue(queueRef.current.slice());
|
|
12620
12733
|
}, []);
|
|
12621
|
-
const retry =
|
|
12734
|
+
const retry = React70.useCallback(() => {
|
|
12622
12735
|
const list = listRef.current;
|
|
12623
12736
|
let at = -1;
|
|
12624
12737
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -12634,19 +12747,19 @@ function useChatEngine(opts) {
|
|
|
12634
12747
|
setQueue(queueRef.current.slice());
|
|
12635
12748
|
drain();
|
|
12636
12749
|
}, []);
|
|
12637
|
-
const clear =
|
|
12750
|
+
const clear = React70.useCallback(() => {
|
|
12638
12751
|
commit([]);
|
|
12639
12752
|
serverCount.current = 0;
|
|
12640
12753
|
queueRef.current = [];
|
|
12641
12754
|
setQueue([]);
|
|
12642
12755
|
onClear && onClear();
|
|
12643
12756
|
}, [onClear]);
|
|
12644
|
-
const setFeedback =
|
|
12757
|
+
const setFeedback = React70.useCallback((id, value) => {
|
|
12645
12758
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
12646
12759
|
const msg = listRef.current.find((m) => m.id === id);
|
|
12647
12760
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
12648
12761
|
}, [onFeedback]);
|
|
12649
|
-
const reload =
|
|
12762
|
+
const reload = React70.useCallback(async () => {
|
|
12650
12763
|
if (!threadRef.current) return;
|
|
12651
12764
|
setStatus("loading");
|
|
12652
12765
|
try {
|
|
@@ -12684,11 +12797,11 @@ var ChatKit = {
|
|
|
12684
12797
|
};
|
|
12685
12798
|
|
|
12686
12799
|
// src/components/chat/ChatTranscript.tsx
|
|
12687
|
-
import * as
|
|
12800
|
+
import * as React72 from "react";
|
|
12688
12801
|
|
|
12689
12802
|
// src/components/chat/ChatTurn.tsx
|
|
12690
|
-
import * as
|
|
12691
|
-
import { jsx as
|
|
12803
|
+
import * as React71 from "react";
|
|
12804
|
+
import { jsx as jsx100, jsxs as jsxs87 } from "react/jsx-runtime";
|
|
12692
12805
|
function JsonView({ value }) {
|
|
12693
12806
|
let text;
|
|
12694
12807
|
try {
|
|
@@ -12696,67 +12809,67 @@ function JsonView({ value }) {
|
|
|
12696
12809
|
} catch (e) {
|
|
12697
12810
|
text = String(value);
|
|
12698
12811
|
}
|
|
12699
|
-
return /* @__PURE__ */
|
|
12812
|
+
return /* @__PURE__ */ jsx100(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
|
|
12700
12813
|
}
|
|
12701
12814
|
function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
12702
12815
|
if (!packet) return null;
|
|
12703
12816
|
const s = schema || {};
|
|
12704
12817
|
const invalid = packet.valid === false;
|
|
12705
12818
|
const title = s.heading || packet.type;
|
|
12706
|
-
return /* @__PURE__ */
|
|
12707
|
-
/* @__PURE__ */
|
|
12708
|
-
/* @__PURE__ */
|
|
12709
|
-
/* @__PURE__ */
|
|
12710
|
-
packet.repaired ? /* @__PURE__ */
|
|
12711
|
-
invalid ? /* @__PURE__ */
|
|
12819
|
+
return /* @__PURE__ */ jsxs87("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
|
|
12820
|
+
/* @__PURE__ */ jsxs87("header", { className: "fdc-packet-head", children: [
|
|
12821
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
|
|
12822
|
+
/* @__PURE__ */ jsx100("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
|
|
12823
|
+
packet.repaired ? /* @__PURE__ */ jsx100("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
|
|
12824
|
+
invalid ? /* @__PURE__ */ jsx100("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
|
|
12712
12825
|
] }),
|
|
12713
|
-
invalid ? /* @__PURE__ */
|
|
12714
|
-
/* @__PURE__ */
|
|
12715
|
-
/* @__PURE__ */
|
|
12716
|
-
] }) : /* @__PURE__ */
|
|
12717
|
-
!invalid && onApply ? /* @__PURE__ */
|
|
12718
|
-
packet.repaired ? /* @__PURE__ */
|
|
12719
|
-
/* @__PURE__ */
|
|
12720
|
-
/* @__PURE__ */
|
|
12826
|
+
invalid ? /* @__PURE__ */ jsxs87("div", { className: "fdc-packet-alert", role: "alert", children: [
|
|
12827
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
12828
|
+
/* @__PURE__ */ jsx100("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
|
|
12829
|
+
] }) : /* @__PURE__ */ jsx100("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx100(JsonView, { value: packet.payload }) }),
|
|
12830
|
+
!invalid && onApply && s.apply !== false ? /* @__PURE__ */ jsxs87("footer", { className: "fdc-packet-foot", children: [
|
|
12831
|
+
packet.repaired ? /* @__PURE__ */ jsx100("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx100("span", {}),
|
|
12832
|
+
/* @__PURE__ */ jsxs87("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
|
|
12833
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
|
|
12721
12834
|
applied ? "Applied" : s.applyLabel || "Apply"
|
|
12722
12835
|
] })
|
|
12723
12836
|
] }) : null
|
|
12724
12837
|
] });
|
|
12725
12838
|
}
|
|
12726
12839
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
12727
|
-
const [open2, setOpen] =
|
|
12840
|
+
const [open2, setOpen] = React71.useState(defaultOpen);
|
|
12728
12841
|
if (!text) return null;
|
|
12729
|
-
return /* @__PURE__ */
|
|
12730
|
-
/* @__PURE__ */
|
|
12731
|
-
/* @__PURE__ */
|
|
12732
|
-
/* @__PURE__ */
|
|
12733
|
-
streaming ? /* @__PURE__ */
|
|
12734
|
-
/* @__PURE__ */
|
|
12735
|
-
/* @__PURE__ */
|
|
12736
|
-
/* @__PURE__ */
|
|
12842
|
+
return /* @__PURE__ */ jsxs87("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
|
|
12843
|
+
/* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
12844
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-brain", "aria-hidden": "true" }),
|
|
12845
|
+
/* @__PURE__ */ jsx100("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
|
|
12846
|
+
streaming ? /* @__PURE__ */ jsxs87("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
12847
|
+
/* @__PURE__ */ jsx100("span", {}),
|
|
12848
|
+
/* @__PURE__ */ jsx100("span", {}),
|
|
12849
|
+
/* @__PURE__ */ jsx100("span", {})
|
|
12737
12850
|
] }) : null,
|
|
12738
|
-
/* @__PURE__ */
|
|
12851
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
|
|
12739
12852
|
] }),
|
|
12740
|
-
open2 ? /* @__PURE__ */
|
|
12853
|
+
open2 ? /* @__PURE__ */ jsx100("div", { className: "fdc-think-body", children: text }) : null
|
|
12741
12854
|
] });
|
|
12742
12855
|
}
|
|
12743
12856
|
function Citations({ items = [], onOpen }) {
|
|
12744
|
-
const [open2, setOpen] =
|
|
12857
|
+
const [open2, setOpen] = React71.useState(false);
|
|
12745
12858
|
if (!items.length) return null;
|
|
12746
|
-
return /* @__PURE__ */
|
|
12747
|
-
/* @__PURE__ */
|
|
12748
|
-
/* @__PURE__ */
|
|
12749
|
-
/* @__PURE__ */
|
|
12859
|
+
return /* @__PURE__ */ jsxs87("div", { className: "fdc-cites", children: [
|
|
12860
|
+
/* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
12861
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
|
|
12862
|
+
/* @__PURE__ */ jsxs87("span", { children: [
|
|
12750
12863
|
items.length,
|
|
12751
12864
|
" source",
|
|
12752
12865
|
items.length === 1 ? "" : "s"
|
|
12753
12866
|
] }),
|
|
12754
|
-
/* @__PURE__ */
|
|
12867
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
|
|
12755
12868
|
] }),
|
|
12756
|
-
open2 ? /* @__PURE__ */
|
|
12757
|
-
/* @__PURE__ */
|
|
12758
|
-
c.url ? /* @__PURE__ */
|
|
12759
|
-
c.detail ? /* @__PURE__ */
|
|
12869
|
+
open2 ? /* @__PURE__ */ jsx100("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs87("li", { children: [
|
|
12870
|
+
/* @__PURE__ */ jsx100("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
|
|
12871
|
+
c.url ? /* @__PURE__ */ jsx100("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx100("span", { children: c.title || "Source" }),
|
|
12872
|
+
c.detail ? /* @__PURE__ */ jsx100("span", { className: "fdc-cite-detail", children: c.detail }) : null
|
|
12760
12873
|
] }, c.id || i)) }) : null
|
|
12761
12874
|
] });
|
|
12762
12875
|
}
|
|
@@ -12767,29 +12880,29 @@ function clampText(text, max) {
|
|
|
12767
12880
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
12768
12881
|
}
|
|
12769
12882
|
function MessageBody({ message: m, ctx }) {
|
|
12770
|
-
const [expanded, setExpanded] =
|
|
12883
|
+
const [expanded, setExpanded] = React71.useState(false);
|
|
12771
12884
|
const isUser = m.role === "user";
|
|
12772
12885
|
const raw = m.text || "";
|
|
12773
12886
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
12774
12887
|
const body = clamped != null ? clamped : raw;
|
|
12775
12888
|
const showMd = ctx.markdown && !isUser;
|
|
12776
|
-
return /* @__PURE__ */
|
|
12777
|
-
m.thinking && ctx.showThinking ? /* @__PURE__ */
|
|
12778
|
-
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */
|
|
12779
|
-
body ? /* @__PURE__ */
|
|
12780
|
-
showMd ? /* @__PURE__ */
|
|
12781
|
-
m.streaming ? /* @__PURE__ */
|
|
12889
|
+
return /* @__PURE__ */ jsxs87("div", { className: "fdc-body", children: [
|
|
12890
|
+
m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx100(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
|
|
12891
|
+
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx100(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
|
|
12892
|
+
body ? /* @__PURE__ */ jsxs87("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
|
|
12893
|
+
showMd ? /* @__PURE__ */ jsx100(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx100("div", { className: "fdc-plain", children: body }),
|
|
12894
|
+
m.streaming ? /* @__PURE__ */ jsx100("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
|
|
12782
12895
|
] }) : null,
|
|
12783
|
-
clamped != null ? /* @__PURE__ */
|
|
12784
|
-
/* @__PURE__ */
|
|
12896
|
+
clamped != null ? /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
|
|
12897
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
|
|
12785
12898
|
"Show more",
|
|
12786
|
-
/* @__PURE__ */
|
|
12787
|
-
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */
|
|
12788
|
-
/* @__PURE__ */
|
|
12899
|
+
/* @__PURE__ */ jsx100("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
|
|
12900
|
+
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
|
|
12901
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
|
|
12789
12902
|
"Show less"
|
|
12790
12903
|
] }) : null,
|
|
12791
|
-
m.attachments && m.attachments.length ? /* @__PURE__ */
|
|
12792
|
-
m.packet ? /* @__PURE__ */
|
|
12904
|
+
m.attachments && m.attachments.length ? /* @__PURE__ */ jsx100(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
|
|
12905
|
+
m.packet ? /* @__PURE__ */ jsx100(
|
|
12793
12906
|
PacketCard,
|
|
12794
12907
|
{
|
|
12795
12908
|
packet: m.packet,
|
|
@@ -12799,35 +12912,35 @@ function MessageBody({ message: m, ctx }) {
|
|
|
12799
12912
|
applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
|
|
12800
12913
|
}
|
|
12801
12914
|
) : null,
|
|
12802
|
-
m.citations && m.citations.length ? /* @__PURE__ */
|
|
12803
|
-
m.working ? /* @__PURE__ */
|
|
12804
|
-
/* @__PURE__ */
|
|
12805
|
-
/* @__PURE__ */
|
|
12806
|
-
/* @__PURE__ */
|
|
12807
|
-
/* @__PURE__ */
|
|
12915
|
+
m.citations && m.citations.length ? /* @__PURE__ */ jsx100(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
|
|
12916
|
+
m.working ? /* @__PURE__ */ jsxs87("div", { className: "fdc-working", role: "status", children: [
|
|
12917
|
+
/* @__PURE__ */ jsxs87("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
12918
|
+
/* @__PURE__ */ jsx100("span", {}),
|
|
12919
|
+
/* @__PURE__ */ jsx100("span", {}),
|
|
12920
|
+
/* @__PURE__ */ jsx100("span", {})
|
|
12808
12921
|
] }),
|
|
12809
|
-
/* @__PURE__ */
|
|
12922
|
+
/* @__PURE__ */ jsxs87("span", { className: "fdc-working-label", children: [
|
|
12810
12923
|
m.resumed ? "Resuming" : "Working",
|
|
12811
|
-
m.job && m.job.status ? /* @__PURE__ */
|
|
12924
|
+
m.job && m.job.status ? /* @__PURE__ */ jsxs87("span", { className: "fdc-working-job", children: [
|
|
12812
12925
|
" \xB7 ",
|
|
12813
12926
|
m.job.status
|
|
12814
12927
|
] }) : null,
|
|
12815
|
-
m.job && m.job.detail ? /* @__PURE__ */
|
|
12928
|
+
m.job && m.job.detail ? /* @__PURE__ */ jsxs87("span", { className: "fdc-working-job", children: [
|
|
12816
12929
|
" \xB7 ",
|
|
12817
12930
|
m.job.detail
|
|
12818
12931
|
] }) : null
|
|
12819
12932
|
] }),
|
|
12820
|
-
m.jobId ? /* @__PURE__ */
|
|
12933
|
+
m.jobId ? /* @__PURE__ */ jsx100("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
|
|
12821
12934
|
] }) : null,
|
|
12822
|
-
m.stopped ? /* @__PURE__ */
|
|
12823
|
-
/* @__PURE__ */
|
|
12935
|
+
m.stopped ? /* @__PURE__ */ jsxs87("div", { className: "fdc-stopped", children: [
|
|
12936
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
12824
12937
|
"Stopped"
|
|
12825
12938
|
] }) : null,
|
|
12826
|
-
m.error ? /* @__PURE__ */
|
|
12827
|
-
/* @__PURE__ */
|
|
12828
|
-
/* @__PURE__ */
|
|
12829
|
-
m.retryable && ctx.onRetry ? /* @__PURE__ */
|
|
12830
|
-
/* @__PURE__ */
|
|
12939
|
+
m.error ? /* @__PURE__ */ jsxs87("div", { className: "fdc-error", role: "alert", children: [
|
|
12940
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
12941
|
+
/* @__PURE__ */ jsx100("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
|
|
12942
|
+
m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
|
|
12943
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
12831
12944
|
"Retry"
|
|
12832
12945
|
] }) : null
|
|
12833
12946
|
] }) : null
|
|
@@ -12840,16 +12953,16 @@ function RunActions({ group, ctx }) {
|
|
|
12840
12953
|
const isAssistant = group.role === "assistant";
|
|
12841
12954
|
const fb = last.feedback;
|
|
12842
12955
|
if (!ctx.messageActions) return null;
|
|
12843
|
-
return /* @__PURE__ */
|
|
12844
|
-
/* @__PURE__ */
|
|
12845
|
-
/* @__PURE__ */
|
|
12846
|
-
/* @__PURE__ */
|
|
12956
|
+
return /* @__PURE__ */ jsxs87("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
|
|
12957
|
+
/* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
|
|
12958
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
|
|
12959
|
+
/* @__PURE__ */ jsx100("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
|
|
12847
12960
|
] }),
|
|
12848
|
-
isAssistant && ctx.onRetry ? /* @__PURE__ */
|
|
12849
|
-
group.role === "user" && ctx.onEdit ? /* @__PURE__ */
|
|
12850
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */
|
|
12851
|
-
/* @__PURE__ */
|
|
12852
|
-
/* @__PURE__ */
|
|
12961
|
+
isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx100("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx100("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
12962
|
+
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx100("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx100("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
12963
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs87(React71.Fragment, { children: [
|
|
12964
|
+
/* @__PURE__ */ jsx100("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ jsx100("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
12965
|
+
/* @__PURE__ */ jsx100("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ jsx100("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
12853
12966
|
] }) : null,
|
|
12854
12967
|
ctx.extraActions ? ctx.extraActions(group) : null
|
|
12855
12968
|
] });
|
|
@@ -12859,22 +12972,22 @@ function ChatTurn({ group, ctx }) {
|
|
|
12859
12972
|
const name = isUser ? ctx.userName : group.author || ctx.assistantName;
|
|
12860
12973
|
const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
|
|
12861
12974
|
const stamp = group.messages[0].timestamp;
|
|
12862
|
-
return /* @__PURE__ */
|
|
12863
|
-
/* @__PURE__ */
|
|
12864
|
-
ctx.showAvatars ? /* @__PURE__ */
|
|
12865
|
-
/* @__PURE__ */
|
|
12866
|
-
stamp ? /* @__PURE__ */
|
|
12867
|
-
group.messages.some((m) => m.model) ? /* @__PURE__ */
|
|
12975
|
+
return /* @__PURE__ */ jsxs87("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
|
|
12976
|
+
/* @__PURE__ */ jsxs87("div", { className: "fdc-turn-head", children: [
|
|
12977
|
+
ctx.showAvatars ? /* @__PURE__ */ jsx100("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx100("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx100("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx100("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
|
|
12978
|
+
/* @__PURE__ */ jsx100("span", { className: "fdc-who", children: name }),
|
|
12979
|
+
stamp ? /* @__PURE__ */ jsx100(RelativeTime, { className: "fdc-when", value: stamp }) : null,
|
|
12980
|
+
group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx100("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
|
|
12868
12981
|
] }),
|
|
12869
|
-
/* @__PURE__ */
|
|
12870
|
-
group.messages.map((m) => /* @__PURE__ */
|
|
12871
|
-
/* @__PURE__ */
|
|
12982
|
+
/* @__PURE__ */ jsxs87("div", { className: "fdc-turn-body", children: [
|
|
12983
|
+
group.messages.map((m) => /* @__PURE__ */ jsx100("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx100(MessageBody, { message: m, ctx }) }, m.id)),
|
|
12984
|
+
/* @__PURE__ */ jsx100(RunActions, { group, ctx })
|
|
12872
12985
|
] })
|
|
12873
12986
|
] });
|
|
12874
12987
|
}
|
|
12875
12988
|
|
|
12876
12989
|
// src/components/chat/ChatTranscript.tsx
|
|
12877
|
-
import { jsx as
|
|
12990
|
+
import { jsx as jsx101, jsxs as jsxs88 } from "react/jsx-runtime";
|
|
12878
12991
|
var GROUP_WINDOW = 6e4;
|
|
12879
12992
|
var STICK_PX = 100;
|
|
12880
12993
|
function groupMessages(list) {
|
|
@@ -12907,25 +13020,25 @@ function dayLabel(key) {
|
|
|
12907
13020
|
}
|
|
12908
13021
|
function Suggestions({ items = [], onPick }) {
|
|
12909
13022
|
if (!items.length) return null;
|
|
12910
|
-
return /* @__PURE__ */
|
|
13023
|
+
return /* @__PURE__ */ jsx101("div", { className: "fdc-suggest", children: items.map((s, i) => {
|
|
12911
13024
|
const it = typeof s === "string" ? { label: s, text: s } : s;
|
|
12912
|
-
return /* @__PURE__ */
|
|
12913
|
-
it.icon ? /* @__PURE__ */
|
|
12914
|
-
/* @__PURE__ */
|
|
12915
|
-
/* @__PURE__ */
|
|
12916
|
-
it.description ? /* @__PURE__ */
|
|
13025
|
+
return /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
|
|
13026
|
+
it.icon ? /* @__PURE__ */ jsx101("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
|
|
13027
|
+
/* @__PURE__ */ jsxs88("span", { className: "fdc-suggest-text", children: [
|
|
13028
|
+
/* @__PURE__ */ jsx101("span", { className: "fdc-suggest-label", children: it.label }),
|
|
13029
|
+
it.description ? /* @__PURE__ */ jsx101("span", { className: "fdc-suggest-desc", children: it.description }) : null
|
|
12917
13030
|
] }),
|
|
12918
|
-
/* @__PURE__ */
|
|
13031
|
+
/* @__PURE__ */ jsx101("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
|
|
12919
13032
|
] }, it.id || i);
|
|
12920
13033
|
}) });
|
|
12921
13034
|
}
|
|
12922
13035
|
function LoadingTurns() {
|
|
12923
|
-
return /* @__PURE__ */
|
|
12924
|
-
/* @__PURE__ */
|
|
12925
|
-
/* @__PURE__ */
|
|
12926
|
-
/* @__PURE__ */
|
|
12927
|
-
/* @__PURE__ */
|
|
12928
|
-
/* @__PURE__ */
|
|
13036
|
+
return /* @__PURE__ */ jsx101("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs88("div", { className: "fdc-skel-turn", children: [
|
|
13037
|
+
/* @__PURE__ */ jsx101("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
|
|
13038
|
+
/* @__PURE__ */ jsxs88("div", { className: "fdc-skel-lines", children: [
|
|
13039
|
+
/* @__PURE__ */ jsx101("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
|
|
13040
|
+
/* @__PURE__ */ jsx101("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
|
|
13041
|
+
/* @__PURE__ */ jsx101("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
|
|
12929
13042
|
] })
|
|
12930
13043
|
] }, i)) });
|
|
12931
13044
|
}
|
|
@@ -12942,10 +13055,10 @@ function ChatTranscript({
|
|
|
12942
13055
|
renderEmpty,
|
|
12943
13056
|
className = ""
|
|
12944
13057
|
}) {
|
|
12945
|
-
const scroller =
|
|
12946
|
-
const stick =
|
|
12947
|
-
const [pill, setPill] =
|
|
12948
|
-
const seen =
|
|
13058
|
+
const scroller = React72.useRef(null);
|
|
13059
|
+
const stick = React72.useRef(true);
|
|
13060
|
+
const [pill, setPill] = React72.useState(0);
|
|
13061
|
+
const seen = React72.useRef(0);
|
|
12949
13062
|
const toBottom = (smooth) => {
|
|
12950
13063
|
const el = scroller.current;
|
|
12951
13064
|
if (!el) return;
|
|
@@ -12964,7 +13077,7 @@ function ChatTranscript({
|
|
|
12964
13077
|
seen.current = messages.length;
|
|
12965
13078
|
}
|
|
12966
13079
|
};
|
|
12967
|
-
|
|
13080
|
+
React72.useLayoutEffect(() => {
|
|
12968
13081
|
const el = scroller.current;
|
|
12969
13082
|
if (!el) return;
|
|
12970
13083
|
if (stick.current) {
|
|
@@ -12972,7 +13085,7 @@ function ChatTranscript({
|
|
|
12972
13085
|
seen.current = messages.length;
|
|
12973
13086
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
12974
13087
|
}, [messages]);
|
|
12975
|
-
|
|
13088
|
+
React72.useEffect(() => {
|
|
12976
13089
|
const el = scroller.current;
|
|
12977
13090
|
const inner = el && el.firstChild;
|
|
12978
13091
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -12982,38 +13095,38 @@ function ChatTranscript({
|
|
|
12982
13095
|
ro.observe(inner);
|
|
12983
13096
|
return () => ro.disconnect();
|
|
12984
13097
|
}, []);
|
|
12985
|
-
const groups =
|
|
13098
|
+
const groups = React72.useMemo(() => groupMessages(messages), [messages]);
|
|
12986
13099
|
const empty = !messages.length && status === "ready";
|
|
12987
|
-
return /* @__PURE__ */
|
|
12988
|
-
/* @__PURE__ */
|
|
12989
|
-
status === "loading" || status === "resolving" ? /* @__PURE__ */
|
|
12990
|
-
status === "disconnected" ? /* @__PURE__ */
|
|
12991
|
-
/* @__PURE__ */
|
|
12992
|
-
/* @__PURE__ */
|
|
12993
|
-
/* @__PURE__ */
|
|
12994
|
-
ctx.onReconnect ? /* @__PURE__ */
|
|
12995
|
-
/* @__PURE__ */
|
|
13100
|
+
return /* @__PURE__ */ jsxs88("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
13101
|
+
/* @__PURE__ */ jsxs88("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
13102
|
+
status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx101(LoadingTurns, {}) : null,
|
|
13103
|
+
status === "disconnected" ? /* @__PURE__ */ jsxs88("div", { className: "fdc-dead", children: [
|
|
13104
|
+
/* @__PURE__ */ jsx101("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx101("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
|
|
13105
|
+
/* @__PURE__ */ jsx101("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
|
|
13106
|
+
/* @__PURE__ */ jsx101("p", { className: "fdc-dead-body", children: fatal === "chat_unavailable" ? "The service reported chat_unavailable. Nothing you type will be lost \u2014 reopen the panel once it\u2019s back." : "The thread couldn\u2019t be resolved" + (fatal ? " (" + fatal + ")" : "") + ". The composer stays disabled until it resolves." }),
|
|
13107
|
+
ctx.onReconnect ? /* @__PURE__ */ jsxs88("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
|
|
13108
|
+
/* @__PURE__ */ jsx101("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
12996
13109
|
"Try again"
|
|
12997
13110
|
] }) : null
|
|
12998
13111
|
] }) : null,
|
|
12999
|
-
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */
|
|
13000
|
-
/* @__PURE__ */
|
|
13001
|
-
/* @__PURE__ */
|
|
13002
|
-
emptyDescription ? /* @__PURE__ */
|
|
13003
|
-
/* @__PURE__ */
|
|
13112
|
+
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs88("div", { className: "fdc-empty", children: [
|
|
13113
|
+
/* @__PURE__ */ jsx101("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx101("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
|
|
13114
|
+
/* @__PURE__ */ jsx101("h3", { className: "fdc-empty-title", children: emptyTitle }),
|
|
13115
|
+
emptyDescription ? /* @__PURE__ */ jsx101("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
|
|
13116
|
+
/* @__PURE__ */ jsx101(Suggestions, { items: suggestions, onPick })
|
|
13004
13117
|
] }) : null,
|
|
13005
13118
|
groups.map((g, i) => {
|
|
13006
13119
|
const prev = groups[i - 1];
|
|
13007
13120
|
const k = dayKey(g.messages[0].timestamp);
|
|
13008
13121
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
13009
|
-
return /* @__PURE__ */
|
|
13010
|
-
showDay ? /* @__PURE__ */
|
|
13011
|
-
/* @__PURE__ */
|
|
13122
|
+
return /* @__PURE__ */ jsxs88(React72.Fragment, { children: [
|
|
13123
|
+
showDay ? /* @__PURE__ */ jsx101("div", { className: "fdc-day", children: /* @__PURE__ */ jsx101("span", { children: dayLabel(k) }) }) : null,
|
|
13124
|
+
/* @__PURE__ */ jsx101(ChatTurn, { group: g, ctx })
|
|
13012
13125
|
] }, g.key || i);
|
|
13013
13126
|
})
|
|
13014
13127
|
] }),
|
|
13015
|
-
pill ? /* @__PURE__ */
|
|
13016
|
-
/* @__PURE__ */
|
|
13128
|
+
pill ? /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
|
|
13129
|
+
/* @__PURE__ */ jsx101("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
|
|
13017
13130
|
pill,
|
|
13018
13131
|
" new message",
|
|
13019
13132
|
pill === 1 ? "" : "s"
|
|
@@ -13023,8 +13136,8 @@ function ChatTranscript({
|
|
|
13023
13136
|
var TranscriptKit = { groupMessages };
|
|
13024
13137
|
|
|
13025
13138
|
// src/components/chat/ChatComposer.tsx
|
|
13026
|
-
import * as
|
|
13027
|
-
import { jsx as
|
|
13139
|
+
import * as React73 from "react";
|
|
13140
|
+
import { jsx as jsx102, jsxs as jsxs89 } from "react/jsx-runtime";
|
|
13028
13141
|
function ChatComposer({
|
|
13029
13142
|
onSubmit,
|
|
13030
13143
|
onStop,
|
|
@@ -13051,17 +13164,17 @@ function ChatComposer({
|
|
|
13051
13164
|
onReject,
|
|
13052
13165
|
onOpenAttachment
|
|
13053
13166
|
}) {
|
|
13054
|
-
const [text, setText] =
|
|
13055
|
-
const [trigger, setTrigger] =
|
|
13056
|
-
const [mentionItems, setMentionItems] =
|
|
13057
|
-
const [listening, setListening] =
|
|
13058
|
-
const [notice, setNotice] =
|
|
13059
|
-
const editor =
|
|
13060
|
-
const wrap =
|
|
13061
|
-
const stopVoice =
|
|
13167
|
+
const [text, setText] = React73.useState(draft || "");
|
|
13168
|
+
const [trigger, setTrigger] = React73.useState(null);
|
|
13169
|
+
const [mentionItems, setMentionItems] = React73.useState([]);
|
|
13170
|
+
const [listening, setListening] = React73.useState(false);
|
|
13171
|
+
const [notice, setNotice] = React73.useState(null);
|
|
13172
|
+
const editor = React73.useRef(null);
|
|
13173
|
+
const wrap = React73.useRef(null);
|
|
13174
|
+
const stopVoice = React73.useRef(null);
|
|
13062
13175
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
13063
13176
|
} });
|
|
13064
|
-
|
|
13177
|
+
React73.useEffect(() => {
|
|
13065
13178
|
if (draft != null && draft !== text) setText(draft);
|
|
13066
13179
|
}, [draft]);
|
|
13067
13180
|
const change = (v) => {
|
|
@@ -13097,7 +13210,7 @@ function ChatComposer({
|
|
|
13097
13210
|
e.preventDefault();
|
|
13098
13211
|
staged.add(found.files);
|
|
13099
13212
|
};
|
|
13100
|
-
|
|
13213
|
+
React73.useEffect(() => {
|
|
13101
13214
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
13102
13215
|
setMentionItems([]);
|
|
13103
13216
|
return;
|
|
@@ -13115,7 +13228,7 @@ function ChatComposer({
|
|
|
13115
13228
|
const q = (trigger.query || "").toLowerCase();
|
|
13116
13229
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
13117
13230
|
}, [trigger, mentionSources]);
|
|
13118
|
-
const slashItems =
|
|
13231
|
+
const slashItems = React73.useMemo(() => {
|
|
13119
13232
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
13120
13233
|
const q = (trigger.query || "").toLowerCase();
|
|
13121
13234
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -13129,7 +13242,7 @@ function ChatComposer({
|
|
|
13129
13242
|
description: it.description,
|
|
13130
13243
|
icon: it.icon,
|
|
13131
13244
|
meta: mention.meta,
|
|
13132
|
-
shortcut: slash.shortcut ? /* @__PURE__ */
|
|
13245
|
+
shortcut: slash.shortcut ? /* @__PURE__ */ jsx102(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
|
|
13133
13246
|
onSelect: () => {
|
|
13134
13247
|
const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
|
|
13135
13248
|
editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
|
|
@@ -13188,14 +13301,14 @@ function ChatComposer({
|
|
|
13188
13301
|
stopVoice.current = typeof res === "function" ? res : () => {
|
|
13189
13302
|
};
|
|
13190
13303
|
};
|
|
13191
|
-
return /* @__PURE__ */
|
|
13192
|
-
queue.length ? /* @__PURE__ */
|
|
13193
|
-
/* @__PURE__ */
|
|
13194
|
-
/* @__PURE__ */
|
|
13195
|
-
onRemoveQueued ? /* @__PURE__ */
|
|
13304
|
+
return /* @__PURE__ */ jsxs89("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
|
|
13305
|
+
queue.length ? /* @__PURE__ */ jsx102("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs89("div", { className: "fdc-queue-row", children: [
|
|
13306
|
+
/* @__PURE__ */ jsx102("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
|
|
13307
|
+
/* @__PURE__ */ jsx102("span", { className: "fdc-queue-text", title: truncationTitle(q.text || (q.attachments ? q.attachments.length + " file(s)" : "")), children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
|
|
13308
|
+
onRemoveQueued ? /* @__PURE__ */ jsx102("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx102("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
13196
13309
|
] }, q.id)) }) : null,
|
|
13197
13310
|
sessionBar,
|
|
13198
|
-
/* @__PURE__ */
|
|
13311
|
+
/* @__PURE__ */ jsx102(
|
|
13199
13312
|
Dropzone,
|
|
13200
13313
|
{
|
|
13201
13314
|
className: "fdc-field",
|
|
@@ -13209,9 +13322,9 @@ function ChatComposer({
|
|
|
13209
13322
|
disabled: !fileUploadHandler || disabled,
|
|
13210
13323
|
label: "Drop to attach",
|
|
13211
13324
|
hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
|
|
13212
|
-
children: /* @__PURE__ */
|
|
13213
|
-
staged.items.length ? /* @__PURE__ */
|
|
13214
|
-
/* @__PURE__ */
|
|
13325
|
+
children: /* @__PURE__ */ jsxs89("div", { ref: wrap, className: "fdc-field-inner", children: [
|
|
13326
|
+
staged.items.length ? /* @__PURE__ */ jsx102("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx102(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
|
|
13327
|
+
/* @__PURE__ */ jsx102(
|
|
13215
13328
|
MarkdownEditor,
|
|
13216
13329
|
{
|
|
13217
13330
|
ref: editor,
|
|
@@ -13230,33 +13343,33 @@ function ChatComposer({
|
|
|
13230
13343
|
ariaLabel: "Message"
|
|
13231
13344
|
}
|
|
13232
13345
|
),
|
|
13233
|
-
/* @__PURE__ */
|
|
13234
|
-
fileUploadHandler ? /* @__PURE__ */
|
|
13235
|
-
voiceHandler ? /* @__PURE__ */
|
|
13346
|
+
/* @__PURE__ */ jsxs89("div", { className: "fdc-tools", children: [
|
|
13347
|
+
fileUploadHandler ? /* @__PURE__ */ jsx102(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
|
|
13348
|
+
voiceHandler ? /* @__PURE__ */ jsx102("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx102("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
|
|
13236
13349
|
toolbarExtras,
|
|
13237
|
-
/* @__PURE__ */
|
|
13238
|
-
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */
|
|
13350
|
+
/* @__PURE__ */ jsx102("span", { className: "fdc-tools-gap" }),
|
|
13351
|
+
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs89("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
|
|
13239
13352
|
text.length,
|
|
13240
13353
|
"/",
|
|
13241
13354
|
maxLength
|
|
13242
13355
|
] }) : null,
|
|
13243
|
-
busy ? /* @__PURE__ */
|
|
13244
|
-
/* @__PURE__ */
|
|
13245
|
-
/* @__PURE__ */
|
|
13246
|
-
] }) : /* @__PURE__ */
|
|
13247
|
-
/* @__PURE__ */
|
|
13248
|
-
/* @__PURE__ */
|
|
13356
|
+
busy ? /* @__PURE__ */ jsxs89("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
|
|
13357
|
+
/* @__PURE__ */ jsx102("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
13358
|
+
/* @__PURE__ */ jsx102("span", { children: "Stop" })
|
|
13359
|
+
] }) : /* @__PURE__ */ jsxs89("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
|
|
13360
|
+
/* @__PURE__ */ jsx102("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
|
|
13361
|
+
/* @__PURE__ */ jsx102("span", { className: "fdc-send-label", children: "Send" })
|
|
13249
13362
|
] })
|
|
13250
13363
|
] })
|
|
13251
13364
|
] })
|
|
13252
13365
|
}
|
|
13253
13366
|
),
|
|
13254
|
-
notice ? /* @__PURE__ */
|
|
13255
|
-
/* @__PURE__ */
|
|
13367
|
+
notice ? /* @__PURE__ */ jsxs89("div", { className: "fdc-notice", role: "status", children: [
|
|
13368
|
+
/* @__PURE__ */ jsx102("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
13256
13369
|
notice
|
|
13257
13370
|
] }) : null,
|
|
13258
|
-
hint && !notice ? /* @__PURE__ */
|
|
13259
|
-
/* @__PURE__ */
|
|
13371
|
+
hint && !notice ? /* @__PURE__ */ jsx102("div", { className: "fdc-hint", children: hint }) : null,
|
|
13372
|
+
/* @__PURE__ */ jsx102(
|
|
13260
13373
|
Popover,
|
|
13261
13374
|
{
|
|
13262
13375
|
open: menuOpen,
|
|
@@ -13270,12 +13383,12 @@ function ChatComposer({
|
|
|
13270
13383
|
returnFocus: false,
|
|
13271
13384
|
closeOnOutside: true,
|
|
13272
13385
|
label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
|
|
13273
|
-
children: /* @__PURE__ */
|
|
13386
|
+
children: /* @__PURE__ */ jsx102(
|
|
13274
13387
|
Menu,
|
|
13275
13388
|
{
|
|
13276
13389
|
items: menuItems,
|
|
13277
13390
|
autoFocus: false,
|
|
13278
|
-
header: /* @__PURE__ */
|
|
13391
|
+
header: /* @__PURE__ */ jsx102("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
|
|
13279
13392
|
onClose: () => setTrigger(null)
|
|
13280
13393
|
}
|
|
13281
13394
|
)
|
|
@@ -13285,12 +13398,12 @@ function ChatComposer({
|
|
|
13285
13398
|
}
|
|
13286
13399
|
|
|
13287
13400
|
// src/components/chat/ChatSessionBar.tsx
|
|
13288
|
-
import * as
|
|
13289
|
-
import { jsx as
|
|
13401
|
+
import * as React74 from "react";
|
|
13402
|
+
import { jsx as jsx103, jsxs as jsxs90 } from "react/jsx-runtime";
|
|
13290
13403
|
var compact2 = meterFormats.compact;
|
|
13291
13404
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
13292
|
-
const [open2, setOpen] =
|
|
13293
|
-
const anchor =
|
|
13405
|
+
const [open2, setOpen] = React74.useState(false);
|
|
13406
|
+
const anchor = React74.useRef(null);
|
|
13294
13407
|
const stats = sessionStats || null;
|
|
13295
13408
|
const cu = contextUsage || null;
|
|
13296
13409
|
const limits = usageLimits || null;
|
|
@@ -13305,9 +13418,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
13305
13418
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
13306
13419
|
if (cu) bits.push(pct + "% context");
|
|
13307
13420
|
const expandable = !!(cu || limits);
|
|
13308
|
-
return /* @__PURE__ */
|
|
13309
|
-
/* @__PURE__ */
|
|
13310
|
-
/* @__PURE__ */
|
|
13421
|
+
return /* @__PURE__ */ jsxs90(React74.Fragment, { children: [
|
|
13422
|
+
/* @__PURE__ */ jsxs90("div", { className: "fdc-bar", children: [
|
|
13423
|
+
/* @__PURE__ */ jsxs90(
|
|
13311
13424
|
"button",
|
|
13312
13425
|
{
|
|
13313
13426
|
type: "button",
|
|
@@ -13318,15 +13431,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
13318
13431
|
"aria-expanded": expandable ? open2 : void 0,
|
|
13319
13432
|
"aria-label": expandable ? "Usage details" : void 0,
|
|
13320
13433
|
children: [
|
|
13321
|
-
cu ? /* @__PURE__ */
|
|
13322
|
-
/* @__PURE__ */
|
|
13323
|
-
expandable ? /* @__PURE__ */
|
|
13434
|
+
cu ? /* @__PURE__ */ jsx103("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx103(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
|
|
13435
|
+
/* @__PURE__ */ jsx103("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
|
|
13436
|
+
expandable ? /* @__PURE__ */ jsx103("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
|
|
13324
13437
|
]
|
|
13325
13438
|
}
|
|
13326
13439
|
),
|
|
13327
13440
|
extras
|
|
13328
13441
|
] }),
|
|
13329
|
-
/* @__PURE__ */
|
|
13442
|
+
/* @__PURE__ */ jsx103(
|
|
13330
13443
|
Popover,
|
|
13331
13444
|
{
|
|
13332
13445
|
open: open2,
|
|
@@ -13337,15 +13450,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
13337
13450
|
maxHeight: 460,
|
|
13338
13451
|
padded: true,
|
|
13339
13452
|
label: "Usage",
|
|
13340
|
-
footer: onClear ? /* @__PURE__ */
|
|
13453
|
+
footer: onClear ? /* @__PURE__ */ jsxs90("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
|
|
13341
13454
|
setOpen(false);
|
|
13342
13455
|
onClear();
|
|
13343
13456
|
}, children: [
|
|
13344
|
-
/* @__PURE__ */
|
|
13457
|
+
/* @__PURE__ */ jsx103("i", { className: "ph ph-trash", "aria-hidden": "true" }),
|
|
13345
13458
|
"Clear conversation"
|
|
13346
13459
|
] }) : void 0,
|
|
13347
|
-
children: /* @__PURE__ */
|
|
13348
|
-
cu ? /* @__PURE__ */
|
|
13460
|
+
children: /* @__PURE__ */ jsxs90("div", { className: "fdc-usage", children: [
|
|
13461
|
+
cu ? /* @__PURE__ */ jsx103("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx103(
|
|
13349
13462
|
SegmentedMeter,
|
|
13350
13463
|
{
|
|
13351
13464
|
total,
|
|
@@ -13357,9 +13470,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
13357
13470
|
remainderLabel: "Free"
|
|
13358
13471
|
}
|
|
13359
13472
|
) }) : null,
|
|
13360
|
-
limits && limits.length ? /* @__PURE__ */
|
|
13361
|
-
/* @__PURE__ */
|
|
13362
|
-
/* @__PURE__ */
|
|
13473
|
+
limits && limits.length ? /* @__PURE__ */ jsxs90("section", { className: "fdc-usage-sec", children: [
|
|
13474
|
+
/* @__PURE__ */ jsx103("h4", { className: "fdc-usage-h", children: "Usage limits" }),
|
|
13475
|
+
/* @__PURE__ */ jsx103("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx103(
|
|
13363
13476
|
QuotaRow,
|
|
13364
13477
|
{
|
|
13365
13478
|
label: l.label,
|
|
@@ -13369,25 +13482,25 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
13369
13482
|
l.id
|
|
13370
13483
|
)) })
|
|
13371
13484
|
] }) : null,
|
|
13372
|
-
stats ? /* @__PURE__ */
|
|
13373
|
-
stats.elapsedMs ? /* @__PURE__ */
|
|
13374
|
-
/* @__PURE__ */
|
|
13375
|
-
/* @__PURE__ */
|
|
13485
|
+
stats ? /* @__PURE__ */ jsxs90("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
|
|
13486
|
+
stats.elapsedMs ? /* @__PURE__ */ jsxs90("div", { children: [
|
|
13487
|
+
/* @__PURE__ */ jsx103("span", { children: "Session" }),
|
|
13488
|
+
/* @__PURE__ */ jsx103("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
|
|
13376
13489
|
] }) : null,
|
|
13377
|
-
stats.tokens ? /* @__PURE__ */
|
|
13378
|
-
/* @__PURE__ */
|
|
13379
|
-
/* @__PURE__ */
|
|
13490
|
+
stats.tokens ? /* @__PURE__ */ jsxs90("div", { children: [
|
|
13491
|
+
/* @__PURE__ */ jsx103("span", { children: "Tokens" }),
|
|
13492
|
+
/* @__PURE__ */ jsx103("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
|
|
13380
13493
|
] }) : null,
|
|
13381
|
-
stats.costUsd != null ? /* @__PURE__ */
|
|
13382
|
-
/* @__PURE__ */
|
|
13383
|
-
/* @__PURE__ */
|
|
13494
|
+
stats.costUsd != null ? /* @__PURE__ */ jsxs90("div", { children: [
|
|
13495
|
+
/* @__PURE__ */ jsx103("span", { children: "Cost" }),
|
|
13496
|
+
/* @__PURE__ */ jsxs90("b", { className: "fd-tabular", children: [
|
|
13384
13497
|
"$",
|
|
13385
13498
|
Number(stats.costUsd).toFixed(3)
|
|
13386
13499
|
] })
|
|
13387
13500
|
] }) : null,
|
|
13388
|
-
stats.turns ? /* @__PURE__ */
|
|
13389
|
-
/* @__PURE__ */
|
|
13390
|
-
/* @__PURE__ */
|
|
13501
|
+
stats.turns ? /* @__PURE__ */ jsxs90("div", { children: [
|
|
13502
|
+
/* @__PURE__ */ jsx103("span", { children: "Turns" }),
|
|
13503
|
+
/* @__PURE__ */ jsx103("b", { className: "fd-tabular", children: stats.turns })
|
|
13391
13504
|
] }) : null
|
|
13392
13505
|
] }) : null
|
|
13393
13506
|
] })
|
|
@@ -13426,7 +13539,7 @@ function ModelControls({
|
|
|
13426
13539
|
disabled: m.disabled,
|
|
13427
13540
|
checked: m.id === (current2 && current2.id),
|
|
13428
13541
|
meta: m.meta,
|
|
13429
|
-
shortcut: m.shortcut ? /* @__PURE__ */
|
|
13542
|
+
shortcut: m.shortcut ? /* @__PURE__ */ jsx103(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
|
|
13430
13543
|
onSelect: () => onModelChange && onModelChange(m.id)
|
|
13431
13544
|
});
|
|
13432
13545
|
const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
|
|
@@ -13439,15 +13552,15 @@ function ModelControls({
|
|
|
13439
13552
|
items.push({ kind: "section", label: "Fast mode" });
|
|
13440
13553
|
items.push({
|
|
13441
13554
|
kind: "custom",
|
|
13442
|
-
render: () => /* @__PURE__ */
|
|
13443
|
-
/* @__PURE__ */
|
|
13444
|
-
/* @__PURE__ */
|
|
13445
|
-
/* @__PURE__ */
|
|
13555
|
+
render: () => /* @__PURE__ */ jsxs90("label", { className: "fdc-switchrow", children: [
|
|
13556
|
+
/* @__PURE__ */ jsx103("span", { children: fastModeLabel }),
|
|
13557
|
+
/* @__PURE__ */ jsx103("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
|
|
13558
|
+
/* @__PURE__ */ jsx103("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx103("span", { className: "fd-switch-thumb" }) })
|
|
13446
13559
|
] })
|
|
13447
13560
|
});
|
|
13448
13561
|
}
|
|
13449
|
-
return /* @__PURE__ */
|
|
13450
|
-
/* @__PURE__ */
|
|
13562
|
+
return /* @__PURE__ */ jsxs90(React74.Fragment, { children: [
|
|
13563
|
+
/* @__PURE__ */ jsx103(
|
|
13451
13564
|
MenuButton,
|
|
13452
13565
|
{
|
|
13453
13566
|
items,
|
|
@@ -13458,7 +13571,7 @@ function ModelControls({
|
|
|
13458
13571
|
title: "Choose a model"
|
|
13459
13572
|
}
|
|
13460
13573
|
),
|
|
13461
|
-
effortLevels && effortLevels.length ? /* @__PURE__ */
|
|
13574
|
+
effortLevels && effortLevels.length ? /* @__PURE__ */ jsx103(
|
|
13462
13575
|
MenuButton,
|
|
13463
13576
|
{
|
|
13464
13577
|
placement: "top-end",
|
|
@@ -13479,7 +13592,7 @@ function ModelControls({
|
|
|
13479
13592
|
}
|
|
13480
13593
|
|
|
13481
13594
|
// src/components/chat/AgentChatPanel.tsx
|
|
13482
|
-
import { jsx as
|
|
13595
|
+
import { jsx as jsx104, jsxs as jsxs91 } from "react/jsx-runtime";
|
|
13483
13596
|
var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
|
|
13484
13597
|
function AgentChatPanel({
|
|
13485
13598
|
/* required */
|
|
@@ -13513,6 +13626,7 @@ function AgentChatPanel({
|
|
|
13513
13626
|
packetSchemas,
|
|
13514
13627
|
packetRenderers,
|
|
13515
13628
|
onApplyPacket,
|
|
13629
|
+
pendingTimeoutMs,
|
|
13516
13630
|
onOpenAttachment,
|
|
13517
13631
|
errorCopy,
|
|
13518
13632
|
/* composer */
|
|
@@ -13563,17 +13677,18 @@ function AgentChatPanel({
|
|
|
13563
13677
|
onFeedback,
|
|
13564
13678
|
onEditMessage
|
|
13565
13679
|
}) {
|
|
13566
|
-
const [panelWidth, setPanelWidth] =
|
|
13567
|
-
const [applied, setApplied] =
|
|
13568
|
-
const [draft, setDraft] =
|
|
13569
|
-
const dragging =
|
|
13570
|
-
|
|
13680
|
+
const [panelWidth, setPanelWidth] = React75.useState(width);
|
|
13681
|
+
const [applied, setApplied] = React75.useState({});
|
|
13682
|
+
const [draft, setDraft] = React75.useState("");
|
|
13683
|
+
const dragging = React75.useRef(null);
|
|
13684
|
+
React75.useEffect(() => setPanelWidth(width), [width]);
|
|
13571
13685
|
const engine = useChatEngine({
|
|
13572
13686
|
contextType,
|
|
13573
13687
|
contextId,
|
|
13574
13688
|
apiAdapter,
|
|
13575
13689
|
initialMessage,
|
|
13576
13690
|
threadId,
|
|
13691
|
+
pendingTimeoutMs,
|
|
13577
13692
|
onPacket,
|
|
13578
13693
|
onThreadReady,
|
|
13579
13694
|
onError,
|
|
@@ -13633,7 +13748,7 @@ function AgentChatPanel({
|
|
|
13633
13748
|
onReconnect: engine.reload,
|
|
13634
13749
|
deadTitle: "The assistant isn\u2019t reachable"
|
|
13635
13750
|
};
|
|
13636
|
-
const sessionBar = /* @__PURE__ */
|
|
13751
|
+
const sessionBar = /* @__PURE__ */ jsx104(
|
|
13637
13752
|
ChatSessionBar,
|
|
13638
13753
|
{
|
|
13639
13754
|
sessionStats,
|
|
@@ -13642,7 +13757,7 @@ function AgentChatPanel({
|
|
|
13642
13757
|
onClear: engine.visible.length ? engine.clear : void 0
|
|
13643
13758
|
}
|
|
13644
13759
|
);
|
|
13645
|
-
const modelControls = /* @__PURE__ */
|
|
13760
|
+
const modelControls = /* @__PURE__ */ jsx104(
|
|
13646
13761
|
ModelControls,
|
|
13647
13762
|
{
|
|
13648
13763
|
models,
|
|
@@ -13657,7 +13772,7 @@ function AgentChatPanel({
|
|
|
13657
13772
|
narrow
|
|
13658
13773
|
}
|
|
13659
13774
|
);
|
|
13660
|
-
const threadMenu = threads && threads.length ? /* @__PURE__ */
|
|
13775
|
+
const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx104(
|
|
13661
13776
|
MenuButton,
|
|
13662
13777
|
{
|
|
13663
13778
|
variant: "ghost",
|
|
@@ -13684,7 +13799,7 @@ function AgentChatPanel({
|
|
|
13684
13799
|
})))
|
|
13685
13800
|
}
|
|
13686
13801
|
) : null;
|
|
13687
|
-
return /* @__PURE__ */
|
|
13802
|
+
return /* @__PURE__ */ jsxs91(
|
|
13688
13803
|
"aside",
|
|
13689
13804
|
{
|
|
13690
13805
|
className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
|
|
@@ -13695,7 +13810,7 @@ function AgentChatPanel({
|
|
|
13695
13810
|
},
|
|
13696
13811
|
"aria-label": title,
|
|
13697
13812
|
children: [
|
|
13698
|
-
surface === "sidebar" && resizable ? /* @__PURE__ */
|
|
13813
|
+
surface === "sidebar" && resizable ? /* @__PURE__ */ jsx104(
|
|
13699
13814
|
"div",
|
|
13700
13815
|
{
|
|
13701
13816
|
className: "fdc-grip",
|
|
@@ -13710,20 +13825,20 @@ function AgentChatPanel({
|
|
|
13710
13825
|
}
|
|
13711
13826
|
}
|
|
13712
13827
|
) : null,
|
|
13713
|
-
showHeader ? /* @__PURE__ */
|
|
13714
|
-
/* @__PURE__ */
|
|
13715
|
-
/* @__PURE__ */
|
|
13716
|
-
/* @__PURE__ */
|
|
13717
|
-
subtitle ? /* @__PURE__ */
|
|
13828
|
+
showHeader ? /* @__PURE__ */ jsxs91("header", { className: "fdc-head", children: [
|
|
13829
|
+
/* @__PURE__ */ jsx104("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx104("i", { className: "ph ph-" + assistantIcon }) }),
|
|
13830
|
+
/* @__PURE__ */ jsxs91("span", { className: "fdc-head-titles", children: [
|
|
13831
|
+
/* @__PURE__ */ jsx104("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
|
|
13832
|
+
subtitle ? /* @__PURE__ */ jsx104("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
|
|
13718
13833
|
] }),
|
|
13719
|
-
/* @__PURE__ */
|
|
13834
|
+
/* @__PURE__ */ jsxs91("span", { className: "fdc-head-acts", children: [
|
|
13720
13835
|
headerActions,
|
|
13721
13836
|
threadMenu,
|
|
13722
|
-
onNewThread ? /* @__PURE__ */
|
|
13723
|
-
onClose ? /* @__PURE__ */
|
|
13837
|
+
onNewThread ? /* @__PURE__ */ jsx104("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx104("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
|
|
13838
|
+
onClose ? /* @__PURE__ */ jsx104("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx104("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
13724
13839
|
] })
|
|
13725
13840
|
] }) : null,
|
|
13726
|
-
/* @__PURE__ */
|
|
13841
|
+
/* @__PURE__ */ jsx104(
|
|
13727
13842
|
ChatTranscript,
|
|
13728
13843
|
{
|
|
13729
13844
|
messages: engine.visible,
|
|
@@ -13738,7 +13853,7 @@ function AgentChatPanel({
|
|
|
13738
13853
|
renderEmpty
|
|
13739
13854
|
}
|
|
13740
13855
|
),
|
|
13741
|
-
/* @__PURE__ */
|
|
13856
|
+
/* @__PURE__ */ jsx104(
|
|
13742
13857
|
ChatComposer,
|
|
13743
13858
|
{
|
|
13744
13859
|
onSubmit: (text, atts) => engine.send(text, atts),
|
|
@@ -13771,8 +13886,8 @@ function AgentChatPanel({
|
|
|
13771
13886
|
}
|
|
13772
13887
|
|
|
13773
13888
|
// src/components/files/FileViewer.tsx
|
|
13774
|
-
import * as
|
|
13775
|
-
import { jsx as
|
|
13889
|
+
import * as React76 from "react";
|
|
13890
|
+
import { jsx as jsx105, jsxs as jsxs92 } from "react/jsx-runtime";
|
|
13776
13891
|
function previewKindOf(file) {
|
|
13777
13892
|
const mime = (file.mime || "").toLowerCase();
|
|
13778
13893
|
const ext = extensionOf(file.name || "");
|
|
@@ -13828,13 +13943,13 @@ function parseDelimited(text, delimiter) {
|
|
|
13828
13943
|
return rows;
|
|
13829
13944
|
}
|
|
13830
13945
|
function usePreview(file, kind, resolveUrl) {
|
|
13831
|
-
const [state, setState] =
|
|
13832
|
-
const [attempt, setAttempt] =
|
|
13833
|
-
const resolveRef =
|
|
13834
|
-
|
|
13946
|
+
const [state, setState] = React76.useState({ status: "loading" });
|
|
13947
|
+
const [attempt, setAttempt] = React76.useState(0);
|
|
13948
|
+
const resolveRef = React76.useRef(resolveUrl);
|
|
13949
|
+
React76.useEffect(() => {
|
|
13835
13950
|
resolveRef.current = resolveUrl;
|
|
13836
13951
|
}, [resolveUrl]);
|
|
13837
|
-
|
|
13952
|
+
React76.useEffect(() => {
|
|
13838
13953
|
if (kind === "none") {
|
|
13839
13954
|
setState({ status: "ready" });
|
|
13840
13955
|
return;
|
|
@@ -13864,19 +13979,19 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
13864
13979
|
if (ac) ac.abort();
|
|
13865
13980
|
};
|
|
13866
13981
|
}, [file.id, kind, attempt]);
|
|
13867
|
-
return { ...state, retry:
|
|
13982
|
+
return { ...state, retry: React76.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
13868
13983
|
}
|
|
13869
13984
|
function PreviewBody({ file, kind, state }) {
|
|
13870
|
-
if (kind === "image") return /* @__PURE__ */
|
|
13871
|
-
if (kind === "pdf") return /* @__PURE__ */
|
|
13872
|
-
if (kind === "markdown") return /* @__PURE__ */
|
|
13985
|
+
if (kind === "image") return /* @__PURE__ */ jsx105("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
13986
|
+
if (kind === "pdf") return /* @__PURE__ */ jsx105("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
|
|
13987
|
+
if (kind === "markdown") return /* @__PURE__ */ jsx105(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
|
|
13873
13988
|
if (kind === "json") {
|
|
13874
13989
|
let pretty = state.text || "";
|
|
13875
13990
|
try {
|
|
13876
13991
|
pretty = JSON.stringify(JSON.parse(pretty), null, 2);
|
|
13877
13992
|
} catch {
|
|
13878
13993
|
}
|
|
13879
|
-
return /* @__PURE__ */
|
|
13994
|
+
return /* @__PURE__ */ jsx105(CodeBlock, { code: pretty, language: "json" });
|
|
13880
13995
|
}
|
|
13881
13996
|
if (kind === "csv") {
|
|
13882
13997
|
const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
|
|
@@ -13884,12 +13999,12 @@ function PreviewBody({ file, kind, state }) {
|
|
|
13884
13999
|
const head = rows[0] || [];
|
|
13885
14000
|
const dataRows = rows.slice(1);
|
|
13886
14001
|
const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
|
|
13887
|
-
return /* @__PURE__ */
|
|
13888
|
-
/* @__PURE__ */
|
|
13889
|
-
/* @__PURE__ */
|
|
13890
|
-
/* @__PURE__ */
|
|
14002
|
+
return /* @__PURE__ */ jsxs92("div", { className: "fd-fv-csv", children: [
|
|
14003
|
+
/* @__PURE__ */ jsxs92("table", { className: "fd-fv-csv-table", children: [
|
|
14004
|
+
/* @__PURE__ */ jsx105("thead", { children: /* @__PURE__ */ jsx105("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx105("th", { children: c }, i)) }) }),
|
|
14005
|
+
/* @__PURE__ */ jsx105("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx105("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx105("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
|
|
13891
14006
|
] }),
|
|
13892
|
-
dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */
|
|
14007
|
+
dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs92("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
|
|
13893
14008
|
"Showing the first ",
|
|
13894
14009
|
FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
|
|
13895
14010
|
" of ",
|
|
@@ -13898,24 +14013,24 @@ function PreviewBody({ file, kind, state }) {
|
|
|
13898
14013
|
] }) : null
|
|
13899
14014
|
] });
|
|
13900
14015
|
}
|
|
13901
|
-
if (kind === "text") return /* @__PURE__ */
|
|
13902
|
-
return /* @__PURE__ */
|
|
13903
|
-
/* @__PURE__ */
|
|
13904
|
-
/* @__PURE__ */
|
|
13905
|
-
/* @__PURE__ */
|
|
14016
|
+
if (kind === "text") return /* @__PURE__ */ jsx105(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
|
|
14017
|
+
return /* @__PURE__ */ jsxs92("div", { className: "fd-fv-fallback", children: [
|
|
14018
|
+
/* @__PURE__ */ jsx105("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx105("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
|
|
14019
|
+
/* @__PURE__ */ jsx105("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
|
|
14020
|
+
/* @__PURE__ */ jsxs92("span", { className: "fd-fv-fallback-meta", children: [
|
|
13906
14021
|
file.mime || "Unknown type",
|
|
13907
14022
|
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
13908
14023
|
] })
|
|
13909
14024
|
] });
|
|
13910
14025
|
}
|
|
13911
14026
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
13912
|
-
const kind =
|
|
14027
|
+
const kind = React76.useMemo(() => previewKindOf(file), [file]);
|
|
13913
14028
|
const preview = usePreview(file, kind, resolveUrl);
|
|
13914
|
-
const [tab, setTab] =
|
|
13915
|
-
const [downloading, setDownloading] =
|
|
13916
|
-
const [downloadError, setDownloadError] =
|
|
14029
|
+
const [tab, setTab] = React76.useState("preview");
|
|
14030
|
+
const [downloading, setDownloading] = React76.useState(false);
|
|
14031
|
+
const [downloadError, setDownloadError] = React76.useState(null);
|
|
13917
14032
|
const hasSide = sidePanel != null;
|
|
13918
|
-
|
|
14033
|
+
React76.useEffect(() => {
|
|
13919
14034
|
setTab("preview");
|
|
13920
14035
|
}, [file.id]);
|
|
13921
14036
|
const download = () => {
|
|
@@ -13931,29 +14046,29 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13931
14046
|
a.remove();
|
|
13932
14047
|
}).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
|
|
13933
14048
|
};
|
|
13934
|
-
return /* @__PURE__ */
|
|
14049
|
+
return /* @__PURE__ */ jsxs92(
|
|
13935
14050
|
"section",
|
|
13936
14051
|
{
|
|
13937
14052
|
className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
|
|
13938
14053
|
"aria-label": file.name || "File",
|
|
13939
14054
|
children: [
|
|
13940
|
-
/* @__PURE__ */
|
|
13941
|
-
/* @__PURE__ */
|
|
13942
|
-
/* @__PURE__ */
|
|
13943
|
-
/* @__PURE__ */
|
|
13944
|
-
/* @__PURE__ */
|
|
14055
|
+
/* @__PURE__ */ jsxs92("header", { className: "fd-fv-head", children: [
|
|
14056
|
+
/* @__PURE__ */ jsx105("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx105("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
|
|
14057
|
+
/* @__PURE__ */ jsxs92("span", { className: "fd-fv-head-titles", children: [
|
|
14058
|
+
/* @__PURE__ */ jsx105("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
|
|
14059
|
+
/* @__PURE__ */ jsxs92("span", { className: "fd-fv-head-meta", children: [
|
|
13945
14060
|
file.mime || "Unknown type",
|
|
13946
14061
|
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
13947
14062
|
] })
|
|
13948
14063
|
] }),
|
|
13949
|
-
/* @__PURE__ */
|
|
14064
|
+
/* @__PURE__ */ jsxs92("span", { className: "fd-fv-head-actions", children: [
|
|
13950
14065
|
actions,
|
|
13951
|
-
/* @__PURE__ */
|
|
13952
|
-
onClose ? /* @__PURE__ */
|
|
14066
|
+
/* @__PURE__ */ jsx105(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
|
|
14067
|
+
onClose ? /* @__PURE__ */ jsx105(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
|
|
13953
14068
|
] })
|
|
13954
14069
|
] }),
|
|
13955
|
-
downloadError ? /* @__PURE__ */
|
|
13956
|
-
hasSide ? /* @__PURE__ */
|
|
14070
|
+
downloadError ? /* @__PURE__ */ jsx105("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
|
|
14071
|
+
hasSide ? /* @__PURE__ */ jsx105(
|
|
13957
14072
|
Tabs,
|
|
13958
14073
|
{
|
|
13959
14074
|
className: "fd-fv-tabs",
|
|
@@ -13962,19 +14077,19 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13962
14077
|
onChange: (v) => setTab(v)
|
|
13963
14078
|
}
|
|
13964
14079
|
) : null,
|
|
13965
|
-
/* @__PURE__ */
|
|
13966
|
-
/* @__PURE__ */
|
|
14080
|
+
/* @__PURE__ */ jsxs92("div", { className: "fd-fv-body", children: [
|
|
14081
|
+
/* @__PURE__ */ jsx105("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx105(
|
|
13967
14082
|
LoadingRegion,
|
|
13968
14083
|
{
|
|
13969
14084
|
state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
|
|
13970
14085
|
error: preview.error,
|
|
13971
14086
|
label: "Loading preview of " + (file.name || "file"),
|
|
13972
14087
|
onRetry: preview.status === "error" ? preview.retry : void 0,
|
|
13973
|
-
skeleton: /* @__PURE__ */
|
|
13974
|
-
children: /* @__PURE__ */
|
|
14088
|
+
skeleton: /* @__PURE__ */ jsx105(Skeleton, { shape: "card", h: 220 }),
|
|
14089
|
+
children: /* @__PURE__ */ jsx105(PreviewBody, { file, kind, state: preview })
|
|
13975
14090
|
}
|
|
13976
14091
|
) }),
|
|
13977
|
-
hasSide ? /* @__PURE__ */
|
|
14092
|
+
hasSide ? /* @__PURE__ */ jsx105("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
|
|
13978
14093
|
] })
|
|
13979
14094
|
]
|
|
13980
14095
|
}
|
|
@@ -13982,8 +14097,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13982
14097
|
}
|
|
13983
14098
|
|
|
13984
14099
|
// src/components/files/FileBrowser.tsx
|
|
13985
|
-
import * as
|
|
13986
|
-
import { Fragment as Fragment31, jsx as
|
|
14100
|
+
import * as React77 from "react";
|
|
14101
|
+
import { Fragment as Fragment31, jsx as jsx106, jsxs as jsxs93 } from "react/jsx-runtime";
|
|
13987
14102
|
function childrenOf(folders, parentId) {
|
|
13988
14103
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
13989
14104
|
}
|
|
@@ -14055,8 +14170,8 @@ function FolderPickerMenu({
|
|
|
14055
14170
|
}) {
|
|
14056
14171
|
const panel = useInlinePanel();
|
|
14057
14172
|
const { open: open2, setOpen, ref } = panel;
|
|
14058
|
-
return /* @__PURE__ */
|
|
14059
|
-
/* @__PURE__ */
|
|
14173
|
+
return /* @__PURE__ */ jsxs93("span", { className: "fd-fb-menu-anchor", ref, children: [
|
|
14174
|
+
/* @__PURE__ */ jsx106(
|
|
14060
14175
|
IconButton,
|
|
14061
14176
|
{
|
|
14062
14177
|
icon: "arrows-out-cardinal",
|
|
@@ -14068,9 +14183,9 @@ function FolderPickerMenu({
|
|
|
14068
14183
|
onClick: () => setOpen((v) => !v)
|
|
14069
14184
|
}
|
|
14070
14185
|
),
|
|
14071
|
-
/* @__PURE__ */
|
|
14072
|
-
/* @__PURE__ */
|
|
14073
|
-
destinations.map((d) => /* @__PURE__ */
|
|
14186
|
+
/* @__PURE__ */ jsx106(InlinePanelSurface, { panel, align: "right", offset: 4, width: 220, maxHeight: 280, role: "menu", label, children: /* @__PURE__ */ jsxs93("div", { className: "fd-fb-menu", children: [
|
|
14187
|
+
/* @__PURE__ */ jsx106("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
|
|
14188
|
+
destinations.map((d) => /* @__PURE__ */ jsxs93(
|
|
14074
14189
|
"button",
|
|
14075
14190
|
{
|
|
14076
14191
|
type: "button",
|
|
@@ -14082,7 +14197,7 @@ function FolderPickerMenu({
|
|
|
14082
14197
|
setOpen(false);
|
|
14083
14198
|
},
|
|
14084
14199
|
children: [
|
|
14085
|
-
/* @__PURE__ */
|
|
14200
|
+
/* @__PURE__ */ jsx106("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
|
|
14086
14201
|
d.name
|
|
14087
14202
|
]
|
|
14088
14203
|
},
|
|
@@ -14092,8 +14207,8 @@ function FolderPickerMenu({
|
|
|
14092
14207
|
] });
|
|
14093
14208
|
}
|
|
14094
14209
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
14095
|
-
const [over, setOver] =
|
|
14096
|
-
const dragCounter =
|
|
14210
|
+
const [over, setOver] = React77.useState(false);
|
|
14211
|
+
const dragCounter = React77.useRef(0);
|
|
14097
14212
|
const dropHandlers = isDropTarget ? {
|
|
14098
14213
|
onDragEnter: (e) => {
|
|
14099
14214
|
if (!hasInternalPayload(e)) return;
|
|
@@ -14118,8 +14233,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
14118
14233
|
if (payload && onDropPayload) onDropPayload(payload);
|
|
14119
14234
|
}
|
|
14120
14235
|
} : {};
|
|
14121
|
-
return /* @__PURE__ */
|
|
14122
|
-
/* @__PURE__ */
|
|
14236
|
+
return /* @__PURE__ */ jsxs93("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
|
|
14237
|
+
/* @__PURE__ */ jsxs93(
|
|
14123
14238
|
"button",
|
|
14124
14239
|
{
|
|
14125
14240
|
type: "button",
|
|
@@ -14128,26 +14243,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
14128
14243
|
draggable: !!draggableId,
|
|
14129
14244
|
onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
|
|
14130
14245
|
children: [
|
|
14131
|
-
/* @__PURE__ */
|
|
14132
|
-
/* @__PURE__ */
|
|
14133
|
-
/* @__PURE__ */
|
|
14134
|
-
meta ? /* @__PURE__ */
|
|
14246
|
+
/* @__PURE__ */ jsx106("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx106("i", { className: "ph ph-" + icon }) }),
|
|
14247
|
+
/* @__PURE__ */ jsxs93("span", { className: "fd-fb-row-text", children: [
|
|
14248
|
+
/* @__PURE__ */ jsx106("span", { className: "fd-fb-row-name", title: name, children: name }),
|
|
14249
|
+
meta ? /* @__PURE__ */ jsx106("span", { className: "fd-fb-row-meta", children: meta }) : null
|
|
14135
14250
|
] })
|
|
14136
14251
|
]
|
|
14137
14252
|
}
|
|
14138
14253
|
),
|
|
14139
|
-
actions ? /* @__PURE__ */
|
|
14254
|
+
actions ? /* @__PURE__ */ jsx106("span", { className: "fd-fb-row-actions", children: actions }) : null
|
|
14140
14255
|
] });
|
|
14141
14256
|
}
|
|
14142
14257
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
14143
14258
|
const kids = childrenOf(folders, folder.id);
|
|
14144
|
-
const [expanded, setExpanded] =
|
|
14145
|
-
|
|
14259
|
+
const [expanded, setExpanded] = React77.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
14260
|
+
React77.useEffect(() => {
|
|
14146
14261
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
14147
14262
|
}, [currentFolderId, folder.id, folders]);
|
|
14148
14263
|
const isCurrent = folder.id === currentFolderId;
|
|
14149
|
-
return /* @__PURE__ */
|
|
14150
|
-
/* @__PURE__ */
|
|
14264
|
+
return /* @__PURE__ */ jsxs93("div", { className: "fd-fb-tree-node", children: [
|
|
14265
|
+
/* @__PURE__ */ jsx106(
|
|
14151
14266
|
RowShell,
|
|
14152
14267
|
{
|
|
14153
14268
|
icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
|
|
@@ -14157,7 +14272,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
|
|
|
14157
14272
|
isDropTarget: canMove,
|
|
14158
14273
|
onDropPayload: (payload) => onMoveInto(payload, folder.id),
|
|
14159
14274
|
className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
|
|
14160
|
-
actions: kids.length ? /* @__PURE__ */
|
|
14275
|
+
actions: kids.length ? /* @__PURE__ */ jsx106(
|
|
14161
14276
|
IconButton,
|
|
14162
14277
|
{
|
|
14163
14278
|
icon: expanded ? "caret-down" : "caret-right",
|
|
@@ -14169,7 +14284,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
|
|
|
14169
14284
|
) : void 0
|
|
14170
14285
|
}
|
|
14171
14286
|
),
|
|
14172
|
-
expanded && kids.length ? /* @__PURE__ */
|
|
14287
|
+
expanded && kids.length ? /* @__PURE__ */ jsx106("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx106(
|
|
14173
14288
|
TreeNode,
|
|
14174
14289
|
{
|
|
14175
14290
|
folder: k,
|
|
@@ -14208,15 +14323,15 @@ function FileBrowser({
|
|
|
14208
14323
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
14209
14324
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
14210
14325
|
const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
|
|
14211
|
-
const [createOpen, setCreateOpen] =
|
|
14212
|
-
const [createName, setCreateName] =
|
|
14213
|
-
const [renameTarget, setRenameTarget] =
|
|
14214
|
-
const [renameValue, setRenameValue] =
|
|
14215
|
-
const [deleteTarget, setDeleteTarget] =
|
|
14216
|
-
const uploadInputRef =
|
|
14217
|
-
const crumbFolders =
|
|
14218
|
-
const subfolders =
|
|
14219
|
-
const currentFiles =
|
|
14326
|
+
const [createOpen, setCreateOpen] = React77.useState(false);
|
|
14327
|
+
const [createName, setCreateName] = React77.useState("");
|
|
14328
|
+
const [renameTarget, setRenameTarget] = React77.useState(null);
|
|
14329
|
+
const [renameValue, setRenameValue] = React77.useState("");
|
|
14330
|
+
const [deleteTarget, setDeleteTarget] = React77.useState(null);
|
|
14331
|
+
const uploadInputRef = React77.useRef(null);
|
|
14332
|
+
const crumbFolders = React77.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
14333
|
+
const subfolders = React77.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
14334
|
+
const currentFiles = React77.useMemo(
|
|
14220
14335
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
14221
14336
|
[files, currentFolderId]
|
|
14222
14337
|
);
|
|
@@ -14255,10 +14370,10 @@ function FileBrowser({
|
|
|
14255
14370
|
if (deleteTarget && onDeleteFolder) onDeleteFolder(deleteTarget);
|
|
14256
14371
|
setDeleteTarget(null);
|
|
14257
14372
|
};
|
|
14258
|
-
const content = /* @__PURE__ */
|
|
14259
|
-
/* @__PURE__ */
|
|
14260
|
-
/* @__PURE__ */
|
|
14261
|
-
/* @__PURE__ */
|
|
14373
|
+
const content = /* @__PURE__ */ jsxs93("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
|
|
14374
|
+
/* @__PURE__ */ jsxs93("div", { className: "fd-fb-head", children: [
|
|
14375
|
+
/* @__PURE__ */ jsxs93("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
|
|
14376
|
+
/* @__PURE__ */ jsx106(
|
|
14262
14377
|
BreadcrumbCrumb,
|
|
14263
14378
|
{
|
|
14264
14379
|
label: "Home",
|
|
@@ -14268,7 +14383,7 @@ function FileBrowser({
|
|
|
14268
14383
|
onDropPayload: (p) => moveIntoFolder(p, null)
|
|
14269
14384
|
}
|
|
14270
14385
|
),
|
|
14271
|
-
crumbFolders.map((f, i) => /* @__PURE__ */
|
|
14386
|
+
crumbFolders.map((f, i) => /* @__PURE__ */ jsx106(
|
|
14272
14387
|
BreadcrumbCrumb,
|
|
14273
14388
|
{
|
|
14274
14389
|
label: f.name,
|
|
@@ -14280,11 +14395,11 @@ function FileBrowser({
|
|
|
14280
14395
|
f.id
|
|
14281
14396
|
))
|
|
14282
14397
|
] }),
|
|
14283
|
-
/* @__PURE__ */
|
|
14284
|
-
canCreateFolder ? /* @__PURE__ */
|
|
14285
|
-
canUpload ? /* @__PURE__ */
|
|
14286
|
-
/* @__PURE__ */
|
|
14287
|
-
/* @__PURE__ */
|
|
14398
|
+
/* @__PURE__ */ jsxs93("span", { className: "fd-fb-actions", children: [
|
|
14399
|
+
canCreateFolder ? /* @__PURE__ */ jsx106(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
|
|
14400
|
+
canUpload ? /* @__PURE__ */ jsxs93(Fragment31, { children: [
|
|
14401
|
+
/* @__PURE__ */ jsx106(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
|
|
14402
|
+
/* @__PURE__ */ jsx106(
|
|
14288
14403
|
"input",
|
|
14289
14404
|
{
|
|
14290
14405
|
ref: uploadInputRef,
|
|
@@ -14302,9 +14417,9 @@ function FileBrowser({
|
|
|
14302
14417
|
] }) : null
|
|
14303
14418
|
] })
|
|
14304
14419
|
] }),
|
|
14305
|
-
/* @__PURE__ */
|
|
14306
|
-
/* @__PURE__ */
|
|
14307
|
-
/* @__PURE__ */
|
|
14420
|
+
/* @__PURE__ */ jsxs93("div", { className: "fd-fb-body", children: [
|
|
14421
|
+
/* @__PURE__ */ jsxs93("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
|
|
14422
|
+
/* @__PURE__ */ jsx106(
|
|
14308
14423
|
RowShell,
|
|
14309
14424
|
{
|
|
14310
14425
|
icon: "house-simple",
|
|
@@ -14315,7 +14430,7 @@ function FileBrowser({
|
|
|
14315
14430
|
className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
|
|
14316
14431
|
}
|
|
14317
14432
|
),
|
|
14318
|
-
childrenOf(folders, null).map((f) => /* @__PURE__ */
|
|
14433
|
+
childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx106(
|
|
14319
14434
|
TreeNode,
|
|
14320
14435
|
{
|
|
14321
14436
|
folder: f,
|
|
@@ -14329,18 +14444,18 @@ function FileBrowser({
|
|
|
14329
14444
|
f.id
|
|
14330
14445
|
))
|
|
14331
14446
|
] }),
|
|
14332
|
-
/* @__PURE__ */
|
|
14447
|
+
/* @__PURE__ */ jsx106("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx106(
|
|
14333
14448
|
LoadingRegion,
|
|
14334
14449
|
{
|
|
14335
14450
|
state: loading ? "loading" : "ready",
|
|
14336
14451
|
label: "Loading folder contents",
|
|
14337
|
-
skeleton: /* @__PURE__ */
|
|
14338
|
-
/* @__PURE__ */
|
|
14339
|
-
/* @__PURE__ */
|
|
14340
|
-
/* @__PURE__ */
|
|
14452
|
+
skeleton: /* @__PURE__ */ jsxs93("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
|
|
14453
|
+
/* @__PURE__ */ jsx106(Skeleton, { h: 44, radius: "10px" }),
|
|
14454
|
+
/* @__PURE__ */ jsx106(Skeleton, { h: 44, radius: "10px" }),
|
|
14455
|
+
/* @__PURE__ */ jsx106(Skeleton, { h: 44, radius: "10px" })
|
|
14341
14456
|
] }),
|
|
14342
|
-
children: isEmpty ? /* @__PURE__ */
|
|
14343
|
-
subfolders.map((f) => /* @__PURE__ */
|
|
14457
|
+
children: isEmpty ? /* @__PURE__ */ jsx106(EmptyState, { icon: "folder-open", title: "This folder is empty", children: canUpload ? "Drop files here, or use Upload above." : "Nothing has been filed here yet." }) : /* @__PURE__ */ jsxs93("div", { className: "fd-fb-list", children: [
|
|
14458
|
+
subfolders.map((f) => /* @__PURE__ */ jsx106(
|
|
14344
14459
|
RowShell,
|
|
14345
14460
|
{
|
|
14346
14461
|
icon: "folder-simple",
|
|
@@ -14349,9 +14464,9 @@ function FileBrowser({
|
|
|
14349
14464
|
draggableId: canMove ? { kind: "folder", id: f.id } : void 0,
|
|
14350
14465
|
isDropTarget: canMove,
|
|
14351
14466
|
onDropPayload: (p) => moveIntoFolder(p, f.id),
|
|
14352
|
-
actions: /* @__PURE__ */
|
|
14353
|
-
canRenameFolder ? /* @__PURE__ */
|
|
14354
|
-
canMove ? /* @__PURE__ */
|
|
14467
|
+
actions: /* @__PURE__ */ jsxs93(Fragment31, { children: [
|
|
14468
|
+
canRenameFolder ? /* @__PURE__ */ jsx106(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
|
|
14469
|
+
canMove ? /* @__PURE__ */ jsx106(
|
|
14355
14470
|
FolderPickerMenu,
|
|
14356
14471
|
{
|
|
14357
14472
|
label: "Move " + f.name,
|
|
@@ -14359,12 +14474,12 @@ function FileBrowser({
|
|
|
14359
14474
|
onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
|
|
14360
14475
|
}
|
|
14361
14476
|
) : null,
|
|
14362
|
-
canDeleteFolder ? /* @__PURE__ */
|
|
14477
|
+
canDeleteFolder ? /* @__PURE__ */ jsx106(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
|
|
14363
14478
|
] })
|
|
14364
14479
|
},
|
|
14365
14480
|
f.id
|
|
14366
14481
|
)),
|
|
14367
|
-
currentFiles.map((file) => /* @__PURE__ */
|
|
14482
|
+
currentFiles.map((file) => /* @__PURE__ */ jsx106(
|
|
14368
14483
|
RowShell,
|
|
14369
14484
|
{
|
|
14370
14485
|
icon: iconForMime(file.mime, file.name),
|
|
@@ -14372,8 +14487,8 @@ function FileBrowser({
|
|
|
14372
14487
|
meta: file.size ? formatBytes(file.size) : void 0,
|
|
14373
14488
|
onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
|
|
14374
14489
|
draggableId: canMove ? { kind: "file", id: file.id } : void 0,
|
|
14375
|
-
actions: /* @__PURE__ */
|
|
14376
|
-
canMove ? /* @__PURE__ */
|
|
14490
|
+
actions: /* @__PURE__ */ jsxs93(Fragment31, { children: [
|
|
14491
|
+
canMove ? /* @__PURE__ */ jsx106(
|
|
14377
14492
|
FolderPickerMenu,
|
|
14378
14493
|
{
|
|
14379
14494
|
label: "Move " + file.name,
|
|
@@ -14381,7 +14496,7 @@ function FileBrowser({
|
|
|
14381
14496
|
onPick: (target) => onMoveFile && onMoveFile(file.id, target)
|
|
14382
14497
|
}
|
|
14383
14498
|
) : null,
|
|
14384
|
-
canRemoveFile ? /* @__PURE__ */
|
|
14499
|
+
canRemoveFile ? /* @__PURE__ */ jsx106(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
|
|
14385
14500
|
] })
|
|
14386
14501
|
},
|
|
14387
14502
|
file.id
|
|
@@ -14390,10 +14505,10 @@ function FileBrowser({
|
|
|
14390
14505
|
}
|
|
14391
14506
|
) })
|
|
14392
14507
|
] }),
|
|
14393
|
-
/* @__PURE__ */
|
|
14394
|
-
/* @__PURE__ */
|
|
14395
|
-
/* @__PURE__ */
|
|
14396
|
-
] }), children: /* @__PURE__ */
|
|
14508
|
+
/* @__PURE__ */ jsx106(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs93(Fragment31, { children: [
|
|
14509
|
+
/* @__PURE__ */ jsx106(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
|
|
14510
|
+
/* @__PURE__ */ jsx106(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
|
|
14511
|
+
] }), children: /* @__PURE__ */ jsx106(
|
|
14397
14512
|
"input",
|
|
14398
14513
|
{
|
|
14399
14514
|
className: "fd-fb-input",
|
|
@@ -14407,10 +14522,10 @@ function FileBrowser({
|
|
|
14407
14522
|
autoFocus: true
|
|
14408
14523
|
}
|
|
14409
14524
|
) }),
|
|
14410
|
-
/* @__PURE__ */
|
|
14411
|
-
/* @__PURE__ */
|
|
14412
|
-
/* @__PURE__ */
|
|
14413
|
-
] }), children: /* @__PURE__ */
|
|
14525
|
+
/* @__PURE__ */ jsx106(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs93(Fragment31, { children: [
|
|
14526
|
+
/* @__PURE__ */ jsx106(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
|
|
14527
|
+
/* @__PURE__ */ jsx106(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
|
|
14528
|
+
] }), children: /* @__PURE__ */ jsx106(
|
|
14414
14529
|
"input",
|
|
14415
14530
|
{
|
|
14416
14531
|
className: "fd-fb-input",
|
|
@@ -14424,22 +14539,22 @@ function FileBrowser({
|
|
|
14424
14539
|
autoFocus: true
|
|
14425
14540
|
}
|
|
14426
14541
|
) }),
|
|
14427
|
-
/* @__PURE__ */
|
|
14542
|
+
/* @__PURE__ */ jsx106(
|
|
14428
14543
|
Modal,
|
|
14429
14544
|
{
|
|
14430
14545
|
open: deleteTarget != null,
|
|
14431
14546
|
title: deleteTarget ? "Delete \u201C" + deleteTarget.name + "\u201D?" : "Delete folder?",
|
|
14432
14547
|
description: "This can't be undone. The folder must be empty.",
|
|
14433
14548
|
onClose: () => setDeleteTarget(null),
|
|
14434
|
-
footer: /* @__PURE__ */
|
|
14435
|
-
/* @__PURE__ */
|
|
14436
|
-
/* @__PURE__ */
|
|
14549
|
+
footer: /* @__PURE__ */ jsxs93(Fragment31, { children: [
|
|
14550
|
+
/* @__PURE__ */ jsx106(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
|
|
14551
|
+
/* @__PURE__ */ jsx106(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
|
|
14437
14552
|
] })
|
|
14438
14553
|
}
|
|
14439
14554
|
)
|
|
14440
14555
|
] });
|
|
14441
14556
|
if (!canUpload) return content;
|
|
14442
|
-
return /* @__PURE__ */
|
|
14557
|
+
return /* @__PURE__ */ jsx106(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
|
|
14443
14558
|
}
|
|
14444
14559
|
function BreadcrumbCrumb({
|
|
14445
14560
|
label,
|
|
@@ -14448,8 +14563,8 @@ function BreadcrumbCrumb({
|
|
|
14448
14563
|
isDropTarget,
|
|
14449
14564
|
onDropPayload
|
|
14450
14565
|
}) {
|
|
14451
|
-
const [over, setOver] =
|
|
14452
|
-
const dragCounter =
|
|
14566
|
+
const [over, setOver] = React77.useState(false);
|
|
14567
|
+
const dragCounter = React77.useRef(0);
|
|
14453
14568
|
const dropHandlers = isDropTarget ? {
|
|
14454
14569
|
onDragEnter: (e) => {
|
|
14455
14570
|
if (!hasInternalPayload(e)) return;
|
|
@@ -14474,11 +14589,11 @@ function BreadcrumbCrumb({
|
|
|
14474
14589
|
if (payload && onDropPayload) onDropPayload(payload);
|
|
14475
14590
|
}
|
|
14476
14591
|
} : {};
|
|
14477
|
-
return /* @__PURE__ */
|
|
14592
|
+
return /* @__PURE__ */ jsx106("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx106("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx106("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
|
|
14478
14593
|
}
|
|
14479
14594
|
|
|
14480
14595
|
// src/kits/query.ts
|
|
14481
|
-
import * as
|
|
14596
|
+
import * as React78 from "react";
|
|
14482
14597
|
|
|
14483
14598
|
// src/kits/queryUrl.ts
|
|
14484
14599
|
var historyUrlAdapter = {
|
|
@@ -14616,38 +14731,38 @@ function requestFor(params, query, paging, after) {
|
|
|
14616
14731
|
}
|
|
14617
14732
|
var toError = (e) => e instanceof Error ? e : new Error(String(e));
|
|
14618
14733
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "page", url }) {
|
|
14619
|
-
const [base] =
|
|
14734
|
+
const [base] = React78.useState(() => {
|
|
14620
14735
|
const store = PREFS || window.PlannerPrefs;
|
|
14621
14736
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
14622
14737
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
14623
14738
|
});
|
|
14624
|
-
const [mountParams] =
|
|
14625
|
-
const address =
|
|
14626
|
-
const [query, setQuery] =
|
|
14627
|
-
const savePref =
|
|
14739
|
+
const [mountParams] = React78.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
|
|
14740
|
+
const address = React78.useRef(mountParams);
|
|
14741
|
+
const [query, setQuery] = React78.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
|
|
14742
|
+
const savePref = React78.useCallback((patch2) => {
|
|
14628
14743
|
const store = PREFS || window.PlannerPrefs;
|
|
14629
14744
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
14630
14745
|
}, [prefsKey]);
|
|
14631
|
-
const [res, setRes] =
|
|
14632
|
-
const [loading, setLoading] =
|
|
14633
|
-
const [loadingMore, setLoadingMore] =
|
|
14634
|
-
const [failure, setFailure] =
|
|
14635
|
-
const [reloadToken, setReloadToken] =
|
|
14636
|
-
const moreController =
|
|
14746
|
+
const [res, setRes] = React78.useState(null);
|
|
14747
|
+
const [loading, setLoading] = React78.useState(true);
|
|
14748
|
+
const [loadingMore, setLoadingMore] = React78.useState(false);
|
|
14749
|
+
const [failure, setFailure] = React78.useState(null);
|
|
14750
|
+
const [reloadToken, setReloadToken] = React78.useState(0);
|
|
14751
|
+
const moreController = React78.useRef(null);
|
|
14637
14752
|
const depKey = (deps || []).join("|");
|
|
14638
14753
|
const paramKey = JSON.stringify(params || {});
|
|
14639
14754
|
const queryKey = JSON.stringify(query);
|
|
14640
|
-
const lifetime =
|
|
14641
|
-
|
|
14755
|
+
const lifetime = React78.useRef(null);
|
|
14756
|
+
React78.useEffect(() => {
|
|
14642
14757
|
const controller = new AbortController();
|
|
14643
14758
|
lifetime.current = controller;
|
|
14644
14759
|
return () => controller.abort();
|
|
14645
14760
|
}, []);
|
|
14646
|
-
const latest =
|
|
14647
|
-
|
|
14761
|
+
const latest = React78.useRef({ res, loading, query, params, endpoint, url, base });
|
|
14762
|
+
React78.useLayoutEffect(() => {
|
|
14648
14763
|
latest.current = { res, loading, query, params, endpoint, url, base };
|
|
14649
14764
|
});
|
|
14650
|
-
|
|
14765
|
+
React78.useEffect(() => {
|
|
14651
14766
|
const controller = new AbortController();
|
|
14652
14767
|
const { signal } = controller;
|
|
14653
14768
|
setLoading(true);
|
|
@@ -14683,7 +14798,7 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "
|
|
|
14683
14798
|
};
|
|
14684
14799
|
}, [endpoint, queryKey, paramKey, depKey, paging, reloadToken]);
|
|
14685
14800
|
const adapter = url ? url.adapter ?? historyUrlAdapter : null;
|
|
14686
|
-
|
|
14801
|
+
React78.useEffect(() => {
|
|
14687
14802
|
if (!adapter) return;
|
|
14688
14803
|
return adapter.subscribe((params2) => {
|
|
14689
14804
|
const { url: u, base: b } = latest.current;
|
|
@@ -15033,12 +15148,12 @@ function createVersionStore(initialState, options) {
|
|
|
15033
15148
|
}
|
|
15034
15149
|
|
|
15035
15150
|
// src/kits/documentTitle.ts
|
|
15036
|
-
import * as
|
|
15151
|
+
import * as React79 from "react";
|
|
15037
15152
|
function formatDocumentTitle(routeTitle, appName) {
|
|
15038
15153
|
return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
|
|
15039
15154
|
}
|
|
15040
15155
|
function useDocumentTitle(routeTitle, appName) {
|
|
15041
|
-
|
|
15156
|
+
React79.useEffect(() => {
|
|
15042
15157
|
if (typeof document === "undefined") return;
|
|
15043
15158
|
document.title = formatDocumentTitle(routeTitle, appName);
|
|
15044
15159
|
}, [routeTitle, appName]);
|
|
@@ -15109,6 +15224,7 @@ export {
|
|
|
15109
15224
|
FILE_VIEWER_TEXT_LIMIT,
|
|
15110
15225
|
FactList,
|
|
15111
15226
|
FeatureGate,
|
|
15227
|
+
Fieldset,
|
|
15112
15228
|
FileBrowser,
|
|
15113
15229
|
FileChip,
|
|
15114
15230
|
FileGrid,
|
|
@@ -15162,6 +15278,7 @@ export {
|
|
|
15162
15278
|
QuotaRow,
|
|
15163
15279
|
ROOT_STEP,
|
|
15164
15280
|
Radio,
|
|
15281
|
+
RadioGroup,
|
|
15165
15282
|
RangeSlider,
|
|
15166
15283
|
RelativeTime,
|
|
15167
15284
|
RoadmapTimeline,
|