@flytedan/flytebot-design-system 0.48.1 → 0.49.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/index.cjs +1172 -933
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +46 -1
- package/dist/index.d.ts +46 -1
- package/dist/index.js +1171 -933
- package/dist/index.js.map +1 -1
- package/package.json +7 -1
- package/styles/components.css +69 -0
package/dist/index.js
CHANGED
|
@@ -4641,7 +4641,7 @@ function CodeBlock({
|
|
|
4641
4641
|
code = "",
|
|
4642
4642
|
language,
|
|
4643
4643
|
filename,
|
|
4644
|
-
lineNumbers = false,
|
|
4644
|
+
lineNumbers: lineNumbers2 = false,
|
|
4645
4645
|
wrap: wrapDefault = false,
|
|
4646
4646
|
collapseAfter = 26,
|
|
4647
4647
|
copyable = true,
|
|
@@ -4668,7 +4668,7 @@ function CodeBlock({
|
|
|
4668
4668
|
] }) : null
|
|
4669
4669
|
] }),
|
|
4670
4670
|
/* @__PURE__ */ jsxs41("div", { className: "fd-code-body", children: [
|
|
4671
|
-
|
|
4671
|
+
lineNumbers2 ? /* @__PURE__ */ jsx49("pre", { className: "fd-code-gutter", "aria-hidden": "true", children: shown.split("\n").map((_, i) => i + 1 + "\n").join("") }) : null,
|
|
4672
4672
|
/* @__PURE__ */ jsx49("pre", { className: "fd-code-pre", tabIndex: 0, children: /* @__PURE__ */ jsx49("code", { children: /* @__PURE__ */ jsx49(Highlighted, { code: shown, lang: language }) }) })
|
|
4673
4673
|
] }),
|
|
4674
4674
|
foldable ? /* @__PURE__ */ jsxs41("button", { type: "button", className: "fd-code-fold", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
@@ -7251,17 +7251,254 @@ var MarkdownEditor = React42.forwardRef(function MarkdownEditor2({
|
|
|
7251
7251
|
] });
|
|
7252
7252
|
});
|
|
7253
7253
|
|
|
7254
|
+
// src/components/forms/CodeEditor.tsx
|
|
7255
|
+
import * as React43 from "react";
|
|
7256
|
+
import { EditorView, keymap, lineNumbers, placeholder as cmPlaceholder, drawSelection, Decoration } from "@codemirror/view";
|
|
7257
|
+
import { EditorState, StateEffect, StateField, Compartment } from "@codemirror/state";
|
|
7258
|
+
import { defaultKeymap, history, historyKeymap, indentMore, indentLess } from "@codemirror/commands";
|
|
7259
|
+
import { sql as sqlLang } from "@codemirror/lang-sql";
|
|
7260
|
+
import { syntaxHighlighting, HighlightStyle, indentOnInput, bracketMatching } from "@codemirror/language";
|
|
7261
|
+
import { tags } from "@lezer/highlight";
|
|
7262
|
+
import { jsx as jsx72, jsxs as jsxs63 } from "react/jsx-runtime";
|
|
7263
|
+
function clampOffset(state, line, column) {
|
|
7264
|
+
const total = state.doc.lines;
|
|
7265
|
+
const ln = state.doc.line(Math.min(Math.max(1, line), total));
|
|
7266
|
+
const col = Math.max(0, (column || 1) - 1);
|
|
7267
|
+
return Math.min(ln.from + col, ln.to);
|
|
7268
|
+
}
|
|
7269
|
+
function toCmDiagnostics(state, diags) {
|
|
7270
|
+
return diags.map((d) => {
|
|
7271
|
+
const from = clampOffset(state, d.line, d.column ?? 1);
|
|
7272
|
+
const endLine = d.endLine ?? d.line;
|
|
7273
|
+
const endColumn = d.endColumn ?? state.doc.line(Math.min(Math.max(1, endLine), state.doc.lines)).length + 1;
|
|
7274
|
+
let to = clampOffset(state, endLine, endColumn);
|
|
7275
|
+
if (to <= from) to = Math.min(from + 1, state.doc.length);
|
|
7276
|
+
return { from, to, severity: d.severity || "error", message: d.message, source: void 0 };
|
|
7277
|
+
});
|
|
7278
|
+
}
|
|
7279
|
+
var setDiagnosticsEffect = StateEffect.define();
|
|
7280
|
+
var diagnosticsField = StateField.define({
|
|
7281
|
+
create: () => [],
|
|
7282
|
+
update(value, tr) {
|
|
7283
|
+
for (const e of tr.effects) if (e.is(setDiagnosticsEffect)) return e.value;
|
|
7284
|
+
if (!tr.docChanged) return value;
|
|
7285
|
+
return value.map((d) => ({ ...d, from: tr.changes.mapPos(d.from), to: tr.changes.mapPos(d.to) }));
|
|
7286
|
+
}
|
|
7287
|
+
});
|
|
7288
|
+
var tokenHighlight = HighlightStyle.define([
|
|
7289
|
+
{ tag: tags.keyword, class: "tok-kw" },
|
|
7290
|
+
{ tag: tags.string, class: "tok-str" },
|
|
7291
|
+
{ tag: [tags.number, tags.bool], class: "tok-num" },
|
|
7292
|
+
{ tag: tags.comment, class: "tok-com" },
|
|
7293
|
+
{ tag: [tags.function(tags.variableName), tags.function(tags.propertyName)], class: "tok-fn" },
|
|
7294
|
+
{ tag: tags.typeName, class: "tok-type" },
|
|
7295
|
+
{ tag: tags.propertyName, class: "tok-prop" },
|
|
7296
|
+
{ tag: tags.null, class: "tok-lit" },
|
|
7297
|
+
{ tag: [tags.punctuation, tags.paren, tags.bracket], class: "tok-pun" },
|
|
7298
|
+
{ tag: tags.operator, class: "tok-op" }
|
|
7299
|
+
]);
|
|
7300
|
+
var editorTheme = EditorView.theme({
|
|
7301
|
+
"&": {
|
|
7302
|
+
fontFamily: "var(--font-mono)",
|
|
7303
|
+
fontSize: "12.5px",
|
|
7304
|
+
color: "var(--text)",
|
|
7305
|
+
backgroundColor: "transparent",
|
|
7306
|
+
height: "100%"
|
|
7307
|
+
},
|
|
7308
|
+
".cm-content": { padding: "10px 12px", caretColor: "var(--text)" },
|
|
7309
|
+
".cm-scroller": { fontFamily: "var(--font-mono)", lineHeight: "1.62" },
|
|
7310
|
+
".cm-gutters": {
|
|
7311
|
+
backgroundColor: "transparent",
|
|
7312
|
+
color: "var(--text-disabled)",
|
|
7313
|
+
border: "0",
|
|
7314
|
+
borderRight: "1px solid var(--chat-code-border)"
|
|
7315
|
+
},
|
|
7316
|
+
".cm-lineNumbers .cm-gutterElement": { padding: "0 8px 0 12px" },
|
|
7317
|
+
".cm-activeLine": { backgroundColor: "var(--surface-2)" },
|
|
7318
|
+
".cm-activeLineGutter": { backgroundColor: "var(--surface-2)", color: "var(--text-2)" },
|
|
7319
|
+
"&.cm-focused": { outline: "none" },
|
|
7320
|
+
".cm-cursor": { borderLeftColor: "var(--text)" },
|
|
7321
|
+
".cm-selectionBackground, &.cm-focused .cm-selectionBackground": { backgroundColor: "var(--blue-100) !important" },
|
|
7322
|
+
".cm-placeholder": { color: "var(--text-disabled)" },
|
|
7323
|
+
".fd-cm-diag-error": { textDecoration: "underline wavy var(--danger-solid)", textUnderlineOffset: "3px" },
|
|
7324
|
+
".fd-cm-diag-warning": { textDecoration: "underline wavy var(--warn-solid)", textUnderlineOffset: "3px" },
|
|
7325
|
+
".fd-cm-diag-info": { textDecoration: "underline wavy var(--info-solid)", textUnderlineOffset: "3px" }
|
|
7326
|
+
}, { dark: false });
|
|
7327
|
+
function severityClass(sev) {
|
|
7328
|
+
return sev === "warning" ? "fd-cm-diag-warning" : sev === "info" ? "fd-cm-diag-info" : "fd-cm-diag-error";
|
|
7329
|
+
}
|
|
7330
|
+
function decorationsFromDiagnostics() {
|
|
7331
|
+
return EditorView.decorations.compute([diagnosticsField], (state) => {
|
|
7332
|
+
const diags = state.field(diagnosticsField);
|
|
7333
|
+
if (!diags.length) return Decoration.none;
|
|
7334
|
+
const marks = diags.filter((d) => d.from < d.to).sort((a, b) => a.from - b.from).map((d) => Decoration.mark({ class: severityClass(d.severity) }).range(d.from, d.to));
|
|
7335
|
+
return Decoration.set(marks, true);
|
|
7336
|
+
});
|
|
7337
|
+
}
|
|
7338
|
+
function CodeEditor({
|
|
7339
|
+
value,
|
|
7340
|
+
onChange,
|
|
7341
|
+
label,
|
|
7342
|
+
help,
|
|
7343
|
+
error,
|
|
7344
|
+
required = false,
|
|
7345
|
+
disabled = false,
|
|
7346
|
+
readOnly = false,
|
|
7347
|
+
placeholder: placeholderText = "",
|
|
7348
|
+
diagnostics = [],
|
|
7349
|
+
showEscapeHint = true,
|
|
7350
|
+
minHeight = 160,
|
|
7351
|
+
id,
|
|
7352
|
+
className = "",
|
|
7353
|
+
style,
|
|
7354
|
+
autoFocus = false
|
|
7355
|
+
}) {
|
|
7356
|
+
const fieldId = useFieldId(id);
|
|
7357
|
+
const descId = fieldId + "-desc";
|
|
7358
|
+
const liveId = fieldId + "-live";
|
|
7359
|
+
const hostRef = React43.useRef(null);
|
|
7360
|
+
const viewRef = React43.useRef(null);
|
|
7361
|
+
const valueRef = React43.useRef(value);
|
|
7362
|
+
const onChangeRef = React43.useRef(onChange);
|
|
7363
|
+
onChangeRef.current = onChange;
|
|
7364
|
+
const editableCompartment = React43.useRef(new Compartment()).current;
|
|
7365
|
+
const attributesCompartment = React43.useRef(new Compartment()).current;
|
|
7366
|
+
const errorRef = React43.useRef(error);
|
|
7367
|
+
errorRef.current = error;
|
|
7368
|
+
const diagnosticsCountRef = React43.useRef(diagnostics.length);
|
|
7369
|
+
diagnosticsCountRef.current = diagnostics.length;
|
|
7370
|
+
function contentAttributes() {
|
|
7371
|
+
return {
|
|
7372
|
+
id: fieldId,
|
|
7373
|
+
"aria-describedby": descId + " " + liveId,
|
|
7374
|
+
"aria-invalid": errorRef.current || diagnosticsCountRef.current ? "true" : "false",
|
|
7375
|
+
...label ? { "aria-label": label } : {}
|
|
7376
|
+
};
|
|
7377
|
+
}
|
|
7378
|
+
React43.useEffect(() => {
|
|
7379
|
+
const host = hostRef.current;
|
|
7380
|
+
if (!host) return;
|
|
7381
|
+
const updateListener = EditorView.updateListener.of((update) => {
|
|
7382
|
+
if (!update.docChanged) return;
|
|
7383
|
+
const next = update.state.doc.toString();
|
|
7384
|
+
valueRef.current = next;
|
|
7385
|
+
onChangeRef.current && onChangeRef.current(next);
|
|
7386
|
+
});
|
|
7387
|
+
const state = EditorState.create({
|
|
7388
|
+
doc: value,
|
|
7389
|
+
extensions: [
|
|
7390
|
+
lineNumbers(),
|
|
7391
|
+
history(),
|
|
7392
|
+
drawSelection(),
|
|
7393
|
+
indentOnInput(),
|
|
7394
|
+
bracketMatching(),
|
|
7395
|
+
sqlLang(),
|
|
7396
|
+
syntaxHighlighting(tokenHighlight),
|
|
7397
|
+
diagnosticsField,
|
|
7398
|
+
decorationsFromDiagnostics(),
|
|
7399
|
+
editorTheme,
|
|
7400
|
+
cmPlaceholder(placeholderText),
|
|
7401
|
+
keymap.of([
|
|
7402
|
+
{ key: "Tab", run: indentMore, shift: indentLess },
|
|
7403
|
+
...defaultKeymap,
|
|
7404
|
+
...historyKeymap
|
|
7405
|
+
]),
|
|
7406
|
+
editableCompartment.of(EditorView.editable.of(!disabled)),
|
|
7407
|
+
EditorState.readOnly.of(readOnly),
|
|
7408
|
+
updateListener,
|
|
7409
|
+
attributesCompartment.of(EditorView.contentAttributes.of(contentAttributes()))
|
|
7410
|
+
]
|
|
7411
|
+
});
|
|
7412
|
+
const view = new EditorView({ state, parent: host });
|
|
7413
|
+
viewRef.current = view;
|
|
7414
|
+
if (autoFocus) view.focus();
|
|
7415
|
+
return () => {
|
|
7416
|
+
view.destroy();
|
|
7417
|
+
viewRef.current = null;
|
|
7418
|
+
};
|
|
7419
|
+
}, []);
|
|
7420
|
+
React43.useEffect(() => {
|
|
7421
|
+
const view = viewRef.current;
|
|
7422
|
+
if (!view) return;
|
|
7423
|
+
const current2 = view.state.doc.toString();
|
|
7424
|
+
if (current2 !== value) {
|
|
7425
|
+
view.dispatch({ changes: { from: 0, to: current2.length, insert: value } });
|
|
7426
|
+
}
|
|
7427
|
+
valueRef.current = value;
|
|
7428
|
+
}, [value]);
|
|
7429
|
+
React43.useEffect(() => {
|
|
7430
|
+
const view = viewRef.current;
|
|
7431
|
+
if (!view) return;
|
|
7432
|
+
view.dispatch({ effects: editableCompartment.reconfigure(EditorView.editable.of(!disabled)) });
|
|
7433
|
+
}, [disabled, editableCompartment]);
|
|
7434
|
+
React43.useEffect(() => {
|
|
7435
|
+
const view = viewRef.current;
|
|
7436
|
+
if (!view) return;
|
|
7437
|
+
view.dispatch({
|
|
7438
|
+
effects: [
|
|
7439
|
+
setDiagnosticsEffect.of(toCmDiagnostics(view.state, diagnostics)),
|
|
7440
|
+
attributesCompartment.reconfigure(EditorView.contentAttributes.of(contentAttributes()))
|
|
7441
|
+
]
|
|
7442
|
+
});
|
|
7443
|
+
}, [diagnostics, error]);
|
|
7444
|
+
const box = ["fd-input", "fd-code-editor", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
7445
|
+
const announce = diagnostics.length ? diagnostics.length + (diagnostics.length === 1 ? " problem: " : " problems: ") + diagnostics.map((d) => "line " + d.line + (d.column ? ", column " + d.column : "") + ": " + d.message).join("; ") : "";
|
|
7446
|
+
return /* @__PURE__ */ jsxs63("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
|
|
7447
|
+
label ? /* @__PURE__ */ jsx72(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
|
|
7448
|
+
/* @__PURE__ */ jsx72(
|
|
7449
|
+
"div",
|
|
7450
|
+
{
|
|
7451
|
+
className: box,
|
|
7452
|
+
style: { minHeight },
|
|
7453
|
+
children: /* @__PURE__ */ jsx72(
|
|
7454
|
+
"div",
|
|
7455
|
+
{
|
|
7456
|
+
ref: hostRef,
|
|
7457
|
+
className: "fd-code-editor-host",
|
|
7458
|
+
style: { minHeight }
|
|
7459
|
+
}
|
|
7460
|
+
)
|
|
7461
|
+
}
|
|
7462
|
+
),
|
|
7463
|
+
/* @__PURE__ */ jsxs63("span", { id: descId, className: "fd-sr", children: [
|
|
7464
|
+
help ? help + ". " : "",
|
|
7465
|
+
showEscapeHint ? "Tab indents. Press Escape, then Tab, to move focus out of the editor." : ""
|
|
7466
|
+
] }),
|
|
7467
|
+
/* @__PURE__ */ jsx72("div", { id: liveId, className: "fd-sr", role: "status", "aria-live": "polite", children: announce }),
|
|
7468
|
+
diagnostics.length ? /* @__PURE__ */ jsx72("ul", { className: "fd-code-editor-diagnostics", children: diagnostics.map((d, i) => /* @__PURE__ */ jsxs63("li", { className: "fd-code-editor-diag is-" + (d.severity || "error"), children: [
|
|
7469
|
+
/* @__PURE__ */ jsx72(
|
|
7470
|
+
"i",
|
|
7471
|
+
{
|
|
7472
|
+
className: "ph ph-" + (d.severity === "warning" ? "warning" : d.severity === "info" ? "info" : "warning-circle"),
|
|
7473
|
+
"aria-hidden": "true"
|
|
7474
|
+
}
|
|
7475
|
+
),
|
|
7476
|
+
/* @__PURE__ */ jsxs63("span", { className: "fd-code-editor-diag-loc", children: [
|
|
7477
|
+
"Line ",
|
|
7478
|
+
d.line,
|
|
7479
|
+
d.column ? ":" + d.column : ""
|
|
7480
|
+
] }),
|
|
7481
|
+
/* @__PURE__ */ jsx72("span", { children: d.message })
|
|
7482
|
+
] }, i)) }) : null,
|
|
7483
|
+
error ? /* @__PURE__ */ jsxs63("span", { className: "fd-field-error", children: [
|
|
7484
|
+
/* @__PURE__ */ jsx72("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
7485
|
+
error
|
|
7486
|
+
] }) : !diagnostics.length && help ? /* @__PURE__ */ jsx72("span", { className: "fd-field-help", children: help }) : null,
|
|
7487
|
+
showEscapeHint ? /* @__PURE__ */ jsx72("span", { className: "fd-field-help fd-code-editor-hint", children: "Tab indents. Escape, then Tab, moves focus out." }) : null
|
|
7488
|
+
] });
|
|
7489
|
+
}
|
|
7490
|
+
|
|
7254
7491
|
// src/components/platform/AccountMenu.tsx
|
|
7255
|
-
import * as
|
|
7492
|
+
import * as React45 from "react";
|
|
7256
7493
|
|
|
7257
7494
|
// src/kits/sessionContext.tsx
|
|
7258
|
-
import * as
|
|
7259
|
-
var SessionContext =
|
|
7495
|
+
import * as React44 from "react";
|
|
7496
|
+
var SessionContext = React44.createContext(null);
|
|
7260
7497
|
function SessionProvider({ value, children }) {
|
|
7261
|
-
return
|
|
7498
|
+
return React44.createElement(SessionContext.Provider, { value }, children);
|
|
7262
7499
|
}
|
|
7263
7500
|
function useSessionContext() {
|
|
7264
|
-
const ctx =
|
|
7501
|
+
const ctx = React44.useContext(SessionContext);
|
|
7265
7502
|
if (!ctx) {
|
|
7266
7503
|
throw new Error(
|
|
7267
7504
|
"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."
|
|
@@ -7271,11 +7508,11 @@ function useSessionContext() {
|
|
|
7271
7508
|
}
|
|
7272
7509
|
|
|
7273
7510
|
// src/components/platform/AccountMenu.tsx
|
|
7274
|
-
import { Fragment as Fragment16, jsx as
|
|
7511
|
+
import { Fragment as Fragment16, jsx as jsx73, jsxs as jsxs64 } from "react/jsx-runtime";
|
|
7275
7512
|
var DEFAULT_LINKS = [];
|
|
7276
7513
|
var DEFAULT_GROUPS = [];
|
|
7277
7514
|
function Item({ item, onPick }) {
|
|
7278
|
-
return /* @__PURE__ */
|
|
7515
|
+
return /* @__PURE__ */ jsxs64(
|
|
7279
7516
|
"button",
|
|
7280
7517
|
{
|
|
7281
7518
|
type: "button",
|
|
@@ -7283,9 +7520,9 @@ function Item({ item, onPick }) {
|
|
|
7283
7520
|
className: "fd-acct-item",
|
|
7284
7521
|
onClick: () => onPick(item),
|
|
7285
7522
|
children: [
|
|
7286
|
-
item.icon ? /* @__PURE__ */
|
|
7287
|
-
/* @__PURE__ */
|
|
7288
|
-
item.badge ? /* @__PURE__ */
|
|
7523
|
+
item.icon ? /* @__PURE__ */ jsx73("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
|
|
7524
|
+
/* @__PURE__ */ jsx73("span", { style: { flex: 1 }, children: item.label }),
|
|
7525
|
+
item.badge ? /* @__PURE__ */ jsx73(Badge, { tone: "neutral", children: item.badge }) : null
|
|
7289
7526
|
]
|
|
7290
7527
|
}
|
|
7291
7528
|
);
|
|
@@ -7301,11 +7538,11 @@ function AccountMenu({
|
|
|
7301
7538
|
...rest
|
|
7302
7539
|
}) {
|
|
7303
7540
|
const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
|
|
7304
|
-
const [open2, setOpen] =
|
|
7305
|
-
const [switching, setSwitching] =
|
|
7306
|
-
const [signingOut, setSigningOut] =
|
|
7307
|
-
const [signOutError, setSignOutError] =
|
|
7308
|
-
const ref =
|
|
7541
|
+
const [open2, setOpen] = React45.useState(false);
|
|
7542
|
+
const [switching, setSwitching] = React45.useState(false);
|
|
7543
|
+
const [signingOut, setSigningOut] = React45.useState(false);
|
|
7544
|
+
const [signOutError, setSignOutError] = React45.useState(null);
|
|
7545
|
+
const ref = React45.useRef(null);
|
|
7309
7546
|
const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
|
|
7310
7547
|
const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || !pending && can2(l.perm)) })).filter((g) => g.links.length);
|
|
7311
7548
|
const closeMenu = () => {
|
|
@@ -7333,8 +7570,8 @@ function AccountMenu({
|
|
|
7333
7570
|
}
|
|
7334
7571
|
};
|
|
7335
7572
|
const showSwitcher = allowUserSwitch && !!demo;
|
|
7336
|
-
return /* @__PURE__ */
|
|
7337
|
-
/* @__PURE__ */
|
|
7573
|
+
return /* @__PURE__ */ jsxs64(Fragment16, { children: [
|
|
7574
|
+
/* @__PURE__ */ jsxs64(
|
|
7338
7575
|
"button",
|
|
7339
7576
|
{
|
|
7340
7577
|
type: "button",
|
|
@@ -7346,12 +7583,12 @@ function AccountMenu({
|
|
|
7346
7583
|
onClick: () => open2 ? closeMenu() : setOpen(true),
|
|
7347
7584
|
...rest,
|
|
7348
7585
|
children: [
|
|
7349
|
-
/* @__PURE__ */
|
|
7350
|
-
/* @__PURE__ */
|
|
7586
|
+
/* @__PURE__ */ jsx73(Avatar, { name: user.name, size: "sm" }),
|
|
7587
|
+
/* @__PURE__ */ jsx73("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
|
|
7351
7588
|
]
|
|
7352
7589
|
}
|
|
7353
7590
|
),
|
|
7354
|
-
/* @__PURE__ */
|
|
7591
|
+
/* @__PURE__ */ jsx73(
|
|
7355
7592
|
Popover,
|
|
7356
7593
|
{
|
|
7357
7594
|
open: open2,
|
|
@@ -7359,27 +7596,27 @@ function AccountMenu({
|
|
|
7359
7596
|
onClose: closeMenu,
|
|
7360
7597
|
placement: "bottom-end",
|
|
7361
7598
|
width: 272,
|
|
7362
|
-
children: /* @__PURE__ */
|
|
7363
|
-
/* @__PURE__ */
|
|
7364
|
-
/* @__PURE__ */
|
|
7365
|
-
/* @__PURE__ */
|
|
7366
|
-
/* @__PURE__ */
|
|
7367
|
-
/* @__PURE__ */
|
|
7599
|
+
children: /* @__PURE__ */ jsxs64("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
|
|
7600
|
+
/* @__PURE__ */ jsxs64("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
7601
|
+
/* @__PURE__ */ jsx73(Avatar, { name: user.name }),
|
|
7602
|
+
/* @__PURE__ */ jsxs64("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
|
|
7603
|
+
/* @__PURE__ */ jsx73("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
|
|
7604
|
+
/* @__PURE__ */ jsx73("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
|
|
7368
7605
|
] })
|
|
7369
7606
|
] }),
|
|
7370
|
-
showRoles && roles.length ? /* @__PURE__ */
|
|
7371
|
-
visibleLinks.length ? /* @__PURE__ */
|
|
7372
|
-
visibleGroups.map((g) => /* @__PURE__ */
|
|
7373
|
-
/* @__PURE__ */
|
|
7374
|
-
g.links.map((l) => /* @__PURE__ */
|
|
7607
|
+
showRoles && roles.length ? /* @__PURE__ */ jsx73("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ jsx73(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
|
|
7608
|
+
visibleLinks.length ? /* @__PURE__ */ jsx73("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ jsx73(Item, { item: l, onPick: pick }, l.id)) }) : null,
|
|
7609
|
+
visibleGroups.map((g) => /* @__PURE__ */ jsxs64("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
7610
|
+
/* @__PURE__ */ jsx73("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
|
|
7611
|
+
g.links.map((l) => /* @__PURE__ */ jsx73(Item, { item: l, onPick: pick }, l.id))
|
|
7375
7612
|
] }, g.label)),
|
|
7376
|
-
showSwitcher && demo ? /* @__PURE__ */
|
|
7377
|
-
/* @__PURE__ */
|
|
7378
|
-
/* @__PURE__ */
|
|
7379
|
-
/* @__PURE__ */
|
|
7380
|
-
/* @__PURE__ */
|
|
7613
|
+
showSwitcher && demo ? /* @__PURE__ */ jsxs64("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
7614
|
+
/* @__PURE__ */ jsxs64("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
|
|
7615
|
+
/* @__PURE__ */ jsx73("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
|
|
7616
|
+
/* @__PURE__ */ jsx73("span", { style: { flex: 1 }, children: "View as another member" }),
|
|
7617
|
+
/* @__PURE__ */ jsx73("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
|
|
7381
7618
|
] }),
|
|
7382
|
-
switching ? /* @__PURE__ */
|
|
7619
|
+
switching ? /* @__PURE__ */ jsx73("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ jsxs64(
|
|
7383
7620
|
"button",
|
|
7384
7621
|
{
|
|
7385
7622
|
type: "button",
|
|
@@ -7391,19 +7628,19 @@ function AccountMenu({
|
|
|
7391
7628
|
setSwitching(false);
|
|
7392
7629
|
},
|
|
7393
7630
|
children: [
|
|
7394
|
-
/* @__PURE__ */
|
|
7395
|
-
/* @__PURE__ */
|
|
7396
|
-
/* @__PURE__ */
|
|
7397
|
-
u.roles ? /* @__PURE__ */
|
|
7631
|
+
/* @__PURE__ */ jsx73(Avatar, { name: u.name, size: "sm" }),
|
|
7632
|
+
/* @__PURE__ */ jsxs64("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
|
|
7633
|
+
/* @__PURE__ */ jsx73("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
|
|
7634
|
+
u.roles ? /* @__PURE__ */ jsx73("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
|
|
7398
7635
|
] }),
|
|
7399
|
-
u.id === user.id ? /* @__PURE__ */
|
|
7636
|
+
u.id === user.id ? /* @__PURE__ */ jsx73("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
|
|
7400
7637
|
]
|
|
7401
7638
|
},
|
|
7402
7639
|
u.id
|
|
7403
7640
|
)) }) : null
|
|
7404
7641
|
] }) : null,
|
|
7405
|
-
/* @__PURE__ */
|
|
7406
|
-
/* @__PURE__ */
|
|
7642
|
+
/* @__PURE__ */ jsxs64("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
7643
|
+
/* @__PURE__ */ jsxs64(
|
|
7407
7644
|
"button",
|
|
7408
7645
|
{
|
|
7409
7646
|
type: "button",
|
|
@@ -7413,14 +7650,14 @@ function AccountMenu({
|
|
|
7413
7650
|
disabled: signingOut,
|
|
7414
7651
|
onClick: signOut,
|
|
7415
7652
|
children: [
|
|
7416
|
-
signingOut ? /* @__PURE__ */
|
|
7417
|
-
/* @__PURE__ */
|
|
7653
|
+
signingOut ? /* @__PURE__ */ jsx73(Spinner, { size: "sm" }) : /* @__PURE__ */ jsx73("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
|
|
7654
|
+
/* @__PURE__ */ jsx73("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
|
|
7418
7655
|
]
|
|
7419
7656
|
}
|
|
7420
7657
|
),
|
|
7421
|
-
signOutError ? /* @__PURE__ */
|
|
7422
|
-
/* @__PURE__ */
|
|
7423
|
-
/* @__PURE__ */
|
|
7658
|
+
signOutError ? /* @__PURE__ */ jsxs64("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
|
|
7659
|
+
/* @__PURE__ */ jsx73("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
|
|
7660
|
+
/* @__PURE__ */ jsx73("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
|
|
7424
7661
|
] }) : null
|
|
7425
7662
|
] })
|
|
7426
7663
|
] })
|
|
@@ -7430,13 +7667,13 @@ function AccountMenu({
|
|
|
7430
7667
|
}
|
|
7431
7668
|
|
|
7432
7669
|
// src/components/platform/AppSwitcher.tsx
|
|
7433
|
-
import * as
|
|
7434
|
-
import { jsx as
|
|
7670
|
+
import * as React46 from "react";
|
|
7671
|
+
import { jsx as jsx74, jsxs as jsxs65 } from "react/jsx-runtime";
|
|
7435
7672
|
function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
7436
7673
|
const { apps: contextApps } = useSessionContext();
|
|
7437
7674
|
const apps = appsProp ?? contextApps ?? [];
|
|
7438
|
-
const [open2, setOpen] =
|
|
7439
|
-
const anchorRef =
|
|
7675
|
+
const [open2, setOpen] = React46.useState(false);
|
|
7676
|
+
const anchorRef = React46.useRef(null);
|
|
7440
7677
|
if (!apps.length) return null;
|
|
7441
7678
|
const items = apps.map((app) => ({
|
|
7442
7679
|
id: app.key,
|
|
@@ -7450,8 +7687,8 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7450
7687
|
window.location.href = app.url;
|
|
7451
7688
|
}
|
|
7452
7689
|
}));
|
|
7453
|
-
return /* @__PURE__ */
|
|
7454
|
-
/* @__PURE__ */
|
|
7690
|
+
return /* @__PURE__ */ jsxs65(React46.Fragment, { children: [
|
|
7691
|
+
/* @__PURE__ */ jsx74("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx74(
|
|
7455
7692
|
IconButton,
|
|
7456
7693
|
{
|
|
7457
7694
|
icon: "squares-four",
|
|
@@ -7461,7 +7698,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7461
7698
|
onClick: () => setOpen((v) => !v)
|
|
7462
7699
|
}
|
|
7463
7700
|
) }),
|
|
7464
|
-
/* @__PURE__ */
|
|
7701
|
+
/* @__PURE__ */ jsx74(
|
|
7465
7702
|
Popover,
|
|
7466
7703
|
{
|
|
7467
7704
|
open: open2,
|
|
@@ -7472,17 +7709,17 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7472
7709
|
label: "All flytedesk apps",
|
|
7473
7710
|
width: 240,
|
|
7474
7711
|
maxHeight: 360,
|
|
7475
|
-
children: /* @__PURE__ */
|
|
7712
|
+
children: /* @__PURE__ */ jsx74(Menu, { items, onClose: () => setOpen(false) })
|
|
7476
7713
|
}
|
|
7477
7714
|
)
|
|
7478
7715
|
] });
|
|
7479
7716
|
}
|
|
7480
7717
|
|
|
7481
7718
|
// src/components/platform/AppearanceMenu.tsx
|
|
7482
|
-
import * as
|
|
7719
|
+
import * as React48 from "react";
|
|
7483
7720
|
|
|
7484
7721
|
// src/kits/appearance.ts
|
|
7485
|
-
import * as
|
|
7722
|
+
import * as React47 from "react";
|
|
7486
7723
|
var DEFAULT_STORAGE_KEY = "fd-appearance";
|
|
7487
7724
|
var DEFAULT_PREFS = {
|
|
7488
7725
|
theme: "system",
|
|
@@ -7577,11 +7814,11 @@ function applyPrefs(prefs, root = document.documentElement) {
|
|
|
7577
7814
|
else root.removeAttribute("data-motion");
|
|
7578
7815
|
}
|
|
7579
7816
|
function useAppearancePrefs(store) {
|
|
7580
|
-
const prefs =
|
|
7581
|
-
|
|
7817
|
+
const prefs = React47.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
7818
|
+
React47.useEffect(() => {
|
|
7582
7819
|
applyPrefs(prefs);
|
|
7583
7820
|
}, [prefs]);
|
|
7584
|
-
|
|
7821
|
+
React47.useEffect(() => {
|
|
7585
7822
|
if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
7586
7823
|
return;
|
|
7587
7824
|
}
|
|
@@ -7590,7 +7827,7 @@ function useAppearancePrefs(store) {
|
|
|
7590
7827
|
mq.addEventListener("change", onChange);
|
|
7591
7828
|
return () => mq.removeEventListener("change", onChange);
|
|
7592
7829
|
}, [prefs]);
|
|
7593
|
-
const update =
|
|
7830
|
+
const update = React47.useCallback(
|
|
7594
7831
|
(patch) => {
|
|
7595
7832
|
store.write({ ...store.getSnapshot(), ...patch });
|
|
7596
7833
|
},
|
|
@@ -7600,7 +7837,7 @@ function useAppearancePrefs(store) {
|
|
|
7600
7837
|
}
|
|
7601
7838
|
|
|
7602
7839
|
// src/components/platform/AppearanceMenu.tsx
|
|
7603
|
-
import { jsx as
|
|
7840
|
+
import { jsx as jsx75, jsxs as jsxs66 } from "react/jsx-runtime";
|
|
7604
7841
|
var THEME_OPTIONS = [
|
|
7605
7842
|
{ value: "light", label: "Light" },
|
|
7606
7843
|
{ value: "dark", label: "Dark" },
|
|
@@ -7613,16 +7850,16 @@ var TEXT_SCALE_OPTIONS = [
|
|
|
7613
7850
|
{ value: "xl", label: "XL" }
|
|
7614
7851
|
];
|
|
7615
7852
|
function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
|
|
7616
|
-
const store =
|
|
7853
|
+
const store = React48.useMemo(
|
|
7617
7854
|
() => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
|
|
7618
7855
|
[storeProp, storageKey, storage, defaults]
|
|
7619
7856
|
);
|
|
7620
7857
|
const [prefs, update] = useAppearancePrefs(store);
|
|
7621
|
-
const [open2, setOpen] =
|
|
7622
|
-
const anchorRef =
|
|
7858
|
+
const [open2, setOpen] = React48.useState(false);
|
|
7859
|
+
const anchorRef = React48.useRef(null);
|
|
7623
7860
|
const patch = (p) => update(p);
|
|
7624
|
-
return /* @__PURE__ */
|
|
7625
|
-
/* @__PURE__ */
|
|
7861
|
+
return /* @__PURE__ */ jsxs66(React48.Fragment, { children: [
|
|
7862
|
+
/* @__PURE__ */ jsx75("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx75(
|
|
7626
7863
|
IconButton,
|
|
7627
7864
|
{
|
|
7628
7865
|
icon: "circle-half",
|
|
@@ -7630,7 +7867,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7630
7867
|
onClick: () => setOpen((v) => !v)
|
|
7631
7868
|
}
|
|
7632
7869
|
) }),
|
|
7633
|
-
/* @__PURE__ */
|
|
7870
|
+
/* @__PURE__ */ jsx75(
|
|
7634
7871
|
Popover,
|
|
7635
7872
|
{
|
|
7636
7873
|
open: open2,
|
|
@@ -7640,10 +7877,10 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7640
7877
|
padded: true,
|
|
7641
7878
|
width: 260,
|
|
7642
7879
|
label: "Appearance settings",
|
|
7643
|
-
children: /* @__PURE__ */
|
|
7644
|
-
/* @__PURE__ */
|
|
7645
|
-
/* @__PURE__ */
|
|
7646
|
-
/* @__PURE__ */
|
|
7880
|
+
children: /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
|
|
7881
|
+
/* @__PURE__ */ jsxs66("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
7882
|
+
/* @__PURE__ */ jsx75("span", { className: "fd-field-label", children: "Theme" }),
|
|
7883
|
+
/* @__PURE__ */ jsx75(
|
|
7647
7884
|
SegmentedControl,
|
|
7648
7885
|
{
|
|
7649
7886
|
options: THEME_OPTIONS,
|
|
@@ -7653,9 +7890,9 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7653
7890
|
}
|
|
7654
7891
|
)
|
|
7655
7892
|
] }),
|
|
7656
|
-
/* @__PURE__ */
|
|
7657
|
-
/* @__PURE__ */
|
|
7658
|
-
/* @__PURE__ */
|
|
7893
|
+
/* @__PURE__ */ jsxs66("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
7894
|
+
/* @__PURE__ */ jsx75("span", { className: "fd-field-label", children: "Text size" }),
|
|
7895
|
+
/* @__PURE__ */ jsx75(
|
|
7659
7896
|
SegmentedControl,
|
|
7660
7897
|
{
|
|
7661
7898
|
options: TEXT_SCALE_OPTIONS,
|
|
@@ -7665,7 +7902,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7665
7902
|
}
|
|
7666
7903
|
)
|
|
7667
7904
|
] }),
|
|
7668
|
-
/* @__PURE__ */
|
|
7905
|
+
/* @__PURE__ */ jsx75(
|
|
7669
7906
|
Switch,
|
|
7670
7907
|
{
|
|
7671
7908
|
label: "High contrast",
|
|
@@ -7674,7 +7911,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7674
7911
|
onChange: (e) => patch({ highContrast: e.target.checked })
|
|
7675
7912
|
}
|
|
7676
7913
|
),
|
|
7677
|
-
/* @__PURE__ */
|
|
7914
|
+
/* @__PURE__ */ jsx75(
|
|
7678
7915
|
Switch,
|
|
7679
7916
|
{
|
|
7680
7917
|
label: "Reduce motion",
|
|
@@ -7690,14 +7927,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7690
7927
|
}
|
|
7691
7928
|
|
|
7692
7929
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
7693
|
-
import * as
|
|
7694
|
-
import { jsx as
|
|
7930
|
+
import * as React49 from "react";
|
|
7931
|
+
import { jsx as jsx76, jsxs as jsxs67 } from "react/jsx-runtime";
|
|
7695
7932
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
7696
7933
|
function Json({ obj }) {
|
|
7697
|
-
return /* @__PURE__ */
|
|
7934
|
+
return /* @__PURE__ */ jsx76("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
7698
7935
|
}
|
|
7699
7936
|
function Endpoint({ s, onRequest }) {
|
|
7700
|
-
const [tried, setTried] =
|
|
7937
|
+
const [tried, setTried] = React49.useState(null);
|
|
7701
7938
|
const run = async () => {
|
|
7702
7939
|
setTried("busy");
|
|
7703
7940
|
const t0 = (window.performance || Date).now();
|
|
@@ -7708,50 +7945,50 @@ function Endpoint({ s, onRequest }) {
|
|
|
7708
7945
|
setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
|
|
7709
7946
|
}
|
|
7710
7947
|
};
|
|
7711
|
-
return /* @__PURE__ */
|
|
7712
|
-
/* @__PURE__ */
|
|
7713
|
-
/* @__PURE__ */
|
|
7714
|
-
/* @__PURE__ */
|
|
7715
|
-
s.isList ? /* @__PURE__ */
|
|
7716
|
-
/* @__PURE__ */
|
|
7717
|
-
/* @__PURE__ */
|
|
7948
|
+
return /* @__PURE__ */ jsx76(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
7949
|
+
/* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
|
|
7950
|
+
/* @__PURE__ */ jsx76(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
|
|
7951
|
+
/* @__PURE__ */ jsx76("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
|
|
7952
|
+
s.isList ? /* @__PURE__ */ jsx76(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
|
|
7953
|
+
/* @__PURE__ */ jsx76("span", { style: { flex: 1 } }),
|
|
7954
|
+
/* @__PURE__ */ jsxs67("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
7718
7955
|
s.latency[0],
|
|
7719
7956
|
"\u2013",
|
|
7720
7957
|
s.latency[1],
|
|
7721
7958
|
"ms"
|
|
7722
7959
|
] }),
|
|
7723
|
-
/* @__PURE__ */
|
|
7960
|
+
/* @__PURE__ */ jsx76(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
|
|
7724
7961
|
] }),
|
|
7725
|
-
/* @__PURE__ */
|
|
7726
|
-
/* @__PURE__ */
|
|
7727
|
-
/* @__PURE__ */
|
|
7728
|
-
/* @__PURE__ */
|
|
7729
|
-
s.usedBy && s.usedBy.length ? /* @__PURE__ */
|
|
7962
|
+
/* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
|
|
7963
|
+
/* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
7964
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
|
|
7965
|
+
/* @__PURE__ */ jsx76("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
|
|
7966
|
+
s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx76("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx76(Tag, { children: u }, u)) }) : null
|
|
7730
7967
|
] }),
|
|
7731
|
-
/* @__PURE__ */
|
|
7732
|
-
s.request ? /* @__PURE__ */
|
|
7733
|
-
/* @__PURE__ */
|
|
7734
|
-
/* @__PURE__ */
|
|
7968
|
+
/* @__PURE__ */ jsxs67("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
|
|
7969
|
+
s.request ? /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
7970
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Request body" }),
|
|
7971
|
+
/* @__PURE__ */ jsx76(Json, { obj: s.request })
|
|
7735
7972
|
] }) : null,
|
|
7736
|
-
s.query ? /* @__PURE__ */
|
|
7737
|
-
/* @__PURE__ */
|
|
7738
|
-
/* @__PURE__ */
|
|
7973
|
+
s.query ? /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
7974
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Query" }),
|
|
7975
|
+
/* @__PURE__ */ jsx76(Json, { obj: s.query })
|
|
7739
7976
|
] }) : null,
|
|
7740
|
-
/* @__PURE__ */
|
|
7741
|
-
/* @__PURE__ */
|
|
7742
|
-
/* @__PURE__ */
|
|
7977
|
+
/* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
7978
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Response 200" }),
|
|
7979
|
+
/* @__PURE__ */ jsx76(Json, { obj: s.response })
|
|
7743
7980
|
] })
|
|
7744
7981
|
] }),
|
|
7745
|
-
s.notes ? /* @__PURE__ */
|
|
7746
|
-
tried && tried !== "busy" ? /* @__PURE__ */
|
|
7747
|
-
/* @__PURE__ */
|
|
7748
|
-
/* @__PURE__ */
|
|
7749
|
-
/* @__PURE__ */
|
|
7982
|
+
s.notes ? /* @__PURE__ */ jsx76(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
|
|
7983
|
+
tried && tried !== "busy" ? /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
7984
|
+
/* @__PURE__ */ jsxs67("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
7985
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
|
|
7986
|
+
/* @__PURE__ */ jsxs67(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
|
|
7750
7987
|
tried.ms,
|
|
7751
7988
|
"ms"
|
|
7752
7989
|
] })
|
|
7753
7990
|
] }),
|
|
7754
|
-
/* @__PURE__ */
|
|
7991
|
+
/* @__PURE__ */ jsx76(Json, { obj: tried.error ? { error: tried.error } : tried.data })
|
|
7755
7992
|
] }) : null
|
|
7756
7993
|
] })
|
|
7757
7994
|
] }) });
|
|
@@ -7770,58 +8007,58 @@ function ApiSpecBrowser({
|
|
|
7770
8007
|
className = "",
|
|
7771
8008
|
...rest
|
|
7772
8009
|
}) {
|
|
7773
|
-
const [q, setQ] =
|
|
7774
|
-
const [method, setMethod] =
|
|
7775
|
-
const [mod, setMod] =
|
|
7776
|
-
const [listOnly, setListOnly] =
|
|
8010
|
+
const [q, setQ] = React49.useState("");
|
|
8011
|
+
const [method, setMethod] = React49.useState(null);
|
|
8012
|
+
const [mod, setMod] = React49.useState(null);
|
|
8013
|
+
const [listOnly, setListOnly] = React49.useState(false);
|
|
7777
8014
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
7778
8015
|
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())));
|
|
7779
8016
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
7780
8017
|
const methods = [...new Set(spec.map((s) => s.method))];
|
|
7781
8018
|
const listCount = spec.filter((s) => s.isList).length;
|
|
7782
|
-
return /* @__PURE__ */
|
|
7783
|
-
/* @__PURE__ */
|
|
7784
|
-
kicker ? /* @__PURE__ */
|
|
7785
|
-
/* @__PURE__ */
|
|
7786
|
-
lede ? /* @__PURE__ */
|
|
8019
|
+
return /* @__PURE__ */ jsxs67("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
|
|
8020
|
+
/* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
8021
|
+
kicker ? /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: kicker }) : null,
|
|
8022
|
+
/* @__PURE__ */ jsx76("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
8023
|
+
lede ? /* @__PURE__ */ jsx76("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
|
|
7787
8024
|
] }),
|
|
7788
|
-
modules && modules.length ? /* @__PURE__ */
|
|
7789
|
-
/* @__PURE__ */
|
|
7790
|
-
/* @__PURE__ */
|
|
7791
|
-
/* @__PURE__ */
|
|
8025
|
+
modules && modules.length ? /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
8026
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
|
|
8027
|
+
/* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
8028
|
+
/* @__PURE__ */ jsxs67(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
|
|
7792
8029
|
"All screens ",
|
|
7793
|
-
/* @__PURE__ */
|
|
8030
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-mono", children: spec.length })
|
|
7794
8031
|
] }),
|
|
7795
|
-
modules.map((m) => /* @__PURE__ */
|
|
8032
|
+
modules.map((m) => /* @__PURE__ */ jsxs67(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
|
|
7796
8033
|
m.label,
|
|
7797
8034
|
" ",
|
|
7798
|
-
/* @__PURE__ */
|
|
8035
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-mono", children: m.endpoints.length })
|
|
7799
8036
|
] }, m.id))
|
|
7800
8037
|
] }),
|
|
7801
|
-
activeModule ? /* @__PURE__ */
|
|
8038
|
+
activeModule ? /* @__PURE__ */ jsx76(
|
|
7802
8039
|
Flag,
|
|
7803
8040
|
{
|
|
7804
8041
|
tone: "info",
|
|
7805
8042
|
statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
|
|
7806
8043
|
cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
|
|
7807
|
-
actions: /* @__PURE__ */
|
|
8044
|
+
actions: /* @__PURE__ */ jsx76(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
|
|
7808
8045
|
}
|
|
7809
8046
|
) : null
|
|
7810
8047
|
] }) : null,
|
|
7811
|
-
sourceNote ? /* @__PURE__ */
|
|
7812
|
-
/* @__PURE__ */
|
|
7813
|
-
/* @__PURE__ */
|
|
7814
|
-
methods.map((m) => /* @__PURE__ */
|
|
8048
|
+
sourceNote ? /* @__PURE__ */ jsx76(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
|
|
8049
|
+
/* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
8050
|
+
/* @__PURE__ */ jsx76(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
|
|
8051
|
+
methods.map((m) => /* @__PURE__ */ jsxs67(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
|
|
7815
8052
|
m,
|
|
7816
8053
|
" ",
|
|
7817
|
-
/* @__PURE__ */
|
|
8054
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
|
|
7818
8055
|
] }, m)),
|
|
7819
|
-
listCount ? /* @__PURE__ */
|
|
8056
|
+
listCount ? /* @__PURE__ */ jsxs67(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
|
|
7820
8057
|
"Paged lists ",
|
|
7821
|
-
/* @__PURE__ */
|
|
8058
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-mono", children: listCount })
|
|
7822
8059
|
] }) : null,
|
|
7823
|
-
/* @__PURE__ */
|
|
7824
|
-
/* @__PURE__ */
|
|
8060
|
+
/* @__PURE__ */ jsx76("span", { style: { flex: 1 } }),
|
|
8061
|
+
/* @__PURE__ */ jsxs67("span", { className: "fd-body-sm fd-muted", children: [
|
|
7825
8062
|
hits.length,
|
|
7826
8063
|
" of ",
|
|
7827
8064
|
spec.length,
|
|
@@ -7829,31 +8066,31 @@ function ApiSpecBrowser({
|
|
|
7829
8066
|
listCount ? " \xB7 " + listCount + " paged" : ""
|
|
7830
8067
|
] })
|
|
7831
8068
|
] }),
|
|
7832
|
-
hits.length === 0 ? /* @__PURE__ */
|
|
8069
|
+
hits.length === 0 ? /* @__PURE__ */ jsx76(Card, { elevation: "flat", children: /* @__PURE__ */ jsx76("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
|
|
7833
8070
|
const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
|
|
7834
8071
|
if (!items.length) return null;
|
|
7835
|
-
return /* @__PURE__ */
|
|
7836
|
-
/* @__PURE__ */
|
|
7837
|
-
items.map((s) => /* @__PURE__ */
|
|
8072
|
+
return /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 12 }, children: [
|
|
8073
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-label-lg", children: g }),
|
|
8074
|
+
items.map((s) => /* @__PURE__ */ jsx76(Endpoint, { s, onRequest }, s.id))
|
|
7838
8075
|
] }, g);
|
|
7839
8076
|
}),
|
|
7840
|
-
conventions && conventions.length ? /* @__PURE__ */
|
|
7841
|
-
/* @__PURE__ */
|
|
7842
|
-
/* @__PURE__ */
|
|
8077
|
+
conventions && conventions.length ? /* @__PURE__ */ jsx76(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx76("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
|
|
8078
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
|
|
8079
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
|
|
7843
8080
|
] }, k)) }) }) : null,
|
|
7844
|
-
openQuestions && openQuestions.length ? /* @__PURE__ */
|
|
7845
|
-
/* @__PURE__ */
|
|
7846
|
-
/* @__PURE__ */
|
|
7847
|
-
/* @__PURE__ */
|
|
7848
|
-
/* @__PURE__ */
|
|
8081
|
+
openQuestions && openQuestions.length ? /* @__PURE__ */ jsx76(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx76("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
|
|
8082
|
+
/* @__PURE__ */ jsx76(Badge, { tone: "danger", children: id }),
|
|
8083
|
+
/* @__PURE__ */ jsxs67("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
|
|
8084
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
|
|
8085
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-body-sm fd-muted", children: why })
|
|
7849
8086
|
] })
|
|
7850
8087
|
] }, id)) }) }) : null
|
|
7851
8088
|
] });
|
|
7852
8089
|
}
|
|
7853
8090
|
|
|
7854
8091
|
// src/components/platform/ProfilePage.tsx
|
|
7855
|
-
import * as
|
|
7856
|
-
import { jsx as
|
|
8092
|
+
import * as React50 from "react";
|
|
8093
|
+
import { jsx as jsx77, jsxs as jsxs68 } from "react/jsx-runtime";
|
|
7857
8094
|
function fieldInitialValue(field, user) {
|
|
7858
8095
|
if (field.value) return field.value(user);
|
|
7859
8096
|
const raw = user[field.key];
|
|
@@ -7888,21 +8125,21 @@ function ProfilePage({
|
|
|
7888
8125
|
}) {
|
|
7889
8126
|
const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
|
|
7890
8127
|
const user = userProp || sessionUser;
|
|
7891
|
-
const initialFieldValues =
|
|
8128
|
+
const initialFieldValues = React50.useMemo(() => {
|
|
7892
8129
|
const values2 = {};
|
|
7893
8130
|
for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
|
|
7894
8131
|
return values2;
|
|
7895
8132
|
}, [user.id, fields]);
|
|
7896
|
-
const initialNotify =
|
|
8133
|
+
const initialNotify = React50.useMemo(() => {
|
|
7897
8134
|
const values2 = {};
|
|
7898
8135
|
for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
|
|
7899
8136
|
return values2;
|
|
7900
8137
|
}, [user.id, notifications]);
|
|
7901
|
-
const [values, setValues] =
|
|
7902
|
-
const [notify, setNotify] =
|
|
7903
|
-
const [saving, setSaving] =
|
|
7904
|
-
const [saved, setSaved] =
|
|
7905
|
-
const [prevUserId, setPrevUserId] =
|
|
8138
|
+
const [values, setValues] = React50.useState(initialFieldValues);
|
|
8139
|
+
const [notify, setNotify] = React50.useState(initialNotify);
|
|
8140
|
+
const [saving, setSaving] = React50.useState(false);
|
|
8141
|
+
const [saved, setSaved] = React50.useState(false);
|
|
8142
|
+
const [prevUserId, setPrevUserId] = React50.useState(user.id);
|
|
7906
8143
|
if (user.id !== prevUserId) {
|
|
7907
8144
|
setPrevUserId(user.id);
|
|
7908
8145
|
setValues(initialFieldValues);
|
|
@@ -7939,37 +8176,37 @@ function ProfilePage({
|
|
|
7939
8176
|
};
|
|
7940
8177
|
const displayName = fields.some((f) => f.key === "name") ? values.name || user.name : user.name;
|
|
7941
8178
|
const fieldGroups = groupFields(fields);
|
|
7942
|
-
return /* @__PURE__ */
|
|
7943
|
-
/* @__PURE__ */
|
|
7944
|
-
/* @__PURE__ */
|
|
7945
|
-
/* @__PURE__ */
|
|
7946
|
-
/* @__PURE__ */
|
|
8179
|
+
return /* @__PURE__ */ jsxs68("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
|
|
8180
|
+
/* @__PURE__ */ jsxs68("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
8181
|
+
/* @__PURE__ */ jsx77("span", { className: "fd-overline fd-muted", children: "Account" }),
|
|
8182
|
+
/* @__PURE__ */ jsx77("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
|
|
8183
|
+
/* @__PURE__ */ jsx77("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." })
|
|
7947
8184
|
] }),
|
|
7948
|
-
/* @__PURE__ */
|
|
7949
|
-
/* @__PURE__ */
|
|
7950
|
-
/* @__PURE__ */
|
|
7951
|
-
/* @__PURE__ */
|
|
7952
|
-
/* @__PURE__ */
|
|
7953
|
-
roles.map((r) => /* @__PURE__ */
|
|
7954
|
-
user.sso ? /* @__PURE__ */
|
|
8185
|
+
/* @__PURE__ */ jsx77(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs68("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
|
|
8186
|
+
/* @__PURE__ */ jsx77(Avatar, { name: displayName, size: "lg" }),
|
|
8187
|
+
/* @__PURE__ */ jsxs68("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
|
|
8188
|
+
/* @__PURE__ */ jsx77("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
|
|
8189
|
+
/* @__PURE__ */ jsxs68("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
|
|
8190
|
+
roles.map((r) => /* @__PURE__ */ jsx77(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
|
|
8191
|
+
user.sso ? /* @__PURE__ */ jsx77(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
|
|
7955
8192
|
] })
|
|
7956
8193
|
] }),
|
|
7957
|
-
onChangePhoto ? /* @__PURE__ */
|
|
8194
|
+
onChangePhoto ? /* @__PURE__ */ jsx77(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
|
|
7958
8195
|
] }) }),
|
|
7959
|
-
fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */
|
|
8196
|
+
fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ jsx77(
|
|
7960
8197
|
Card,
|
|
7961
8198
|
{
|
|
7962
|
-
title: description ? /* @__PURE__ */
|
|
7963
|
-
/* @__PURE__ */
|
|
7964
|
-
/* @__PURE__ */
|
|
8199
|
+
title: description ? /* @__PURE__ */ jsxs68("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
8200
|
+
/* @__PURE__ */ jsx77("span", { children: group }),
|
|
8201
|
+
/* @__PURE__ */ jsx77("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
|
|
7965
8202
|
] }) : group,
|
|
7966
8203
|
elevation: "flat",
|
|
7967
|
-
children: /* @__PURE__ */
|
|
7968
|
-
/* @__PURE__ */
|
|
8204
|
+
children: /* @__PURE__ */ jsxs68("div", { className: "fd-stack", style: { gap: 14 }, children: [
|
|
8205
|
+
/* @__PURE__ */ jsx77("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
|
|
7969
8206
|
const help = typeof field.help === "function" ? field.help(user) : field.help;
|
|
7970
8207
|
const readOnly = field.readOnly || field.type === "readonly";
|
|
7971
8208
|
if (field.type === "select") {
|
|
7972
|
-
return /* @__PURE__ */
|
|
8209
|
+
return /* @__PURE__ */ jsx77(
|
|
7973
8210
|
Select,
|
|
7974
8211
|
{
|
|
7975
8212
|
label: field.label,
|
|
@@ -7983,7 +8220,7 @@ function ProfilePage({
|
|
|
7983
8220
|
field.key
|
|
7984
8221
|
);
|
|
7985
8222
|
}
|
|
7986
|
-
return /* @__PURE__ */
|
|
8223
|
+
return /* @__PURE__ */ jsx77(
|
|
7987
8224
|
Input,
|
|
7988
8225
|
{
|
|
7989
8226
|
label: field.label,
|
|
@@ -7999,7 +8236,7 @@ function ProfilePage({
|
|
|
7999
8236
|
}) }),
|
|
8000
8237
|
groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
|
|
8001
8238
|
const help = typeof field.help === "function" ? field.help(user) : field.help;
|
|
8002
|
-
return /* @__PURE__ */
|
|
8239
|
+
return /* @__PURE__ */ jsx77(
|
|
8003
8240
|
Textarea,
|
|
8004
8241
|
{
|
|
8005
8242
|
label: field.label,
|
|
@@ -8019,16 +8256,16 @@ function ProfilePage({
|
|
|
8019
8256
|
group
|
|
8020
8257
|
)),
|
|
8021
8258
|
extra,
|
|
8022
|
-
notifications.length > 0 ? /* @__PURE__ */
|
|
8023
|
-
/* @__PURE__ */
|
|
8259
|
+
notifications.length > 0 ? /* @__PURE__ */ jsx77(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ jsx77("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ jsx77(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
|
|
8260
|
+
/* @__PURE__ */ jsxs68(
|
|
8024
8261
|
Card,
|
|
8025
8262
|
{
|
|
8026
|
-
title: /* @__PURE__ */
|
|
8027
|
-
/* @__PURE__ */
|
|
8028
|
-
/* @__PURE__ */
|
|
8263
|
+
title: /* @__PURE__ */ jsxs68("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
8264
|
+
/* @__PURE__ */ jsx77("span", { children: "Access" }),
|
|
8265
|
+
/* @__PURE__ */ jsx77("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
|
|
8029
8266
|
] }),
|
|
8030
8267
|
elevation: "flat",
|
|
8031
|
-
action: /* @__PURE__ */
|
|
8268
|
+
action: /* @__PURE__ */ jsx77(
|
|
8032
8269
|
Button,
|
|
8033
8270
|
{
|
|
8034
8271
|
size: "sm",
|
|
@@ -8039,39 +8276,39 @@ function ProfilePage({
|
|
|
8039
8276
|
}
|
|
8040
8277
|
),
|
|
8041
8278
|
children: [
|
|
8042
|
-
/* @__PURE__ */
|
|
8043
|
-
/* @__PURE__ */
|
|
8044
|
-
/* @__PURE__ */
|
|
8279
|
+
/* @__PURE__ */ jsxs68("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
8280
|
+
/* @__PURE__ */ jsx77(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
|
|
8281
|
+
/* @__PURE__ */ jsxs68(CardRow, { label: "Permissions", children: [
|
|
8045
8282
|
permissions.length,
|
|
8046
8283
|
" granted"
|
|
8047
8284
|
] }),
|
|
8048
|
-
/* @__PURE__ */
|
|
8285
|
+
/* @__PURE__ */ jsx77(CardRow, { label: "Member since", children: user.joined || "\u2014" })
|
|
8049
8286
|
] }),
|
|
8050
|
-
/* @__PURE__ */
|
|
8287
|
+
/* @__PURE__ */ jsx77("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." })
|
|
8051
8288
|
]
|
|
8052
8289
|
}
|
|
8053
8290
|
),
|
|
8054
|
-
sessions ? /* @__PURE__ */
|
|
8291
|
+
sessions ? /* @__PURE__ */ jsx77(
|
|
8055
8292
|
Card,
|
|
8056
8293
|
{
|
|
8057
8294
|
title: "Signed-in devices",
|
|
8058
8295
|
elevation: "flat",
|
|
8059
|
-
action: /* @__PURE__ */
|
|
8060
|
-
children: /* @__PURE__ */
|
|
8061
|
-
/* @__PURE__ */
|
|
8062
|
-
/* @__PURE__ */
|
|
8063
|
-
/* @__PURE__ */
|
|
8064
|
-
/* @__PURE__ */
|
|
8296
|
+
action: /* @__PURE__ */ jsx77(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
|
|
8297
|
+
children: /* @__PURE__ */ jsx77("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ jsx77("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ jsxs68("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
|
|
8298
|
+
/* @__PURE__ */ jsx77("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
8299
|
+
/* @__PURE__ */ jsxs68("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
|
|
8300
|
+
/* @__PURE__ */ jsx77("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
|
|
8301
|
+
/* @__PURE__ */ jsxs68("span", { className: "fd-body-sm fd-muted", children: [
|
|
8065
8302
|
s.where,
|
|
8066
8303
|
" \xB7 ",
|
|
8067
8304
|
s.when
|
|
8068
8305
|
] })
|
|
8069
8306
|
] }),
|
|
8070
|
-
s.current ? /* @__PURE__ */
|
|
8307
|
+
s.current ? /* @__PURE__ */ jsx77(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx77(Button, { size: "sm", variant: "ghost", children: "Revoke" })
|
|
8071
8308
|
] }, s.id)) })
|
|
8072
8309
|
}
|
|
8073
8310
|
) : null,
|
|
8074
|
-
/* @__PURE__ */
|
|
8311
|
+
/* @__PURE__ */ jsxs68("div", { className: "fd-row", style: {
|
|
8075
8312
|
gap: 10,
|
|
8076
8313
|
flexWrap: "wrap",
|
|
8077
8314
|
position: "sticky",
|
|
@@ -8082,19 +8319,19 @@ function ProfilePage({
|
|
|
8082
8319
|
border: "1px solid var(--border)",
|
|
8083
8320
|
boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
|
|
8084
8321
|
}, children: [
|
|
8085
|
-
/* @__PURE__ */
|
|
8086
|
-
/* @__PURE__ */
|
|
8087
|
-
/* @__PURE__ */
|
|
8322
|
+
/* @__PURE__ */ jsx77("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
|
|
8323
|
+
/* @__PURE__ */ jsx77(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
|
|
8324
|
+
/* @__PURE__ */ jsx77(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
|
|
8088
8325
|
] })
|
|
8089
8326
|
] });
|
|
8090
8327
|
}
|
|
8091
8328
|
|
|
8092
8329
|
// src/components/platform/SignInPage.tsx
|
|
8093
|
-
import * as
|
|
8094
|
-
import { Fragment as Fragment19, jsx as
|
|
8330
|
+
import * as React51 from "react";
|
|
8331
|
+
import { Fragment as Fragment19, jsx as jsx78, jsxs as jsxs69 } from "react/jsx-runtime";
|
|
8095
8332
|
function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
8096
|
-
const [signingIn, setSigningIn] =
|
|
8097
|
-
const [resuming, setResuming] =
|
|
8333
|
+
const [signingIn, setSigningIn] = React51.useState(false);
|
|
8334
|
+
const [resuming, setResuming] = React51.useState(false);
|
|
8098
8335
|
function handleSignIn() {
|
|
8099
8336
|
setSigningIn(true);
|
|
8100
8337
|
onSignIn();
|
|
@@ -8103,7 +8340,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8103
8340
|
setResuming(true);
|
|
8104
8341
|
continueAs.onContinue().finally(() => setResuming(false));
|
|
8105
8342
|
}
|
|
8106
|
-
return /* @__PURE__ */
|
|
8343
|
+
return /* @__PURE__ */ jsxs69(
|
|
8107
8344
|
"div",
|
|
8108
8345
|
{
|
|
8109
8346
|
style: {
|
|
@@ -8117,7 +8354,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8117
8354
|
background: "radial-gradient(circle at 15% 15%, var(--blue-700) 0%, transparent 45%), radial-gradient(circle at 85% 85%, var(--blue-600) 0%, transparent 40%), linear-gradient(160deg, var(--navy) 0%, var(--blue-950) 55%, var(--blue-900) 100%)"
|
|
8118
8355
|
},
|
|
8119
8356
|
children: [
|
|
8120
|
-
/* @__PURE__ */
|
|
8357
|
+
/* @__PURE__ */ jsx78(
|
|
8121
8358
|
"div",
|
|
8122
8359
|
{
|
|
8123
8360
|
"aria-hidden": true,
|
|
@@ -8130,7 +8367,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8130
8367
|
}
|
|
8131
8368
|
}
|
|
8132
8369
|
),
|
|
8133
|
-
/* @__PURE__ */
|
|
8370
|
+
/* @__PURE__ */ jsxs69(
|
|
8134
8371
|
"div",
|
|
8135
8372
|
{
|
|
8136
8373
|
style: {
|
|
@@ -8142,8 +8379,8 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8142
8379
|
alignItems: "center"
|
|
8143
8380
|
},
|
|
8144
8381
|
children: [
|
|
8145
|
-
/* @__PURE__ */
|
|
8146
|
-
/* @__PURE__ */
|
|
8382
|
+
/* @__PURE__ */ jsx78("div", { style: { marginBottom: "var(--s-32)" }, "data-theme": "dark", children: /* @__PURE__ */ jsx78(FlytedeskMark, { size: "lg" }) }),
|
|
8383
|
+
/* @__PURE__ */ jsxs69(
|
|
8147
8384
|
"div",
|
|
8148
8385
|
{
|
|
8149
8386
|
style: {
|
|
@@ -8153,7 +8390,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8153
8390
|
boxShadow: "0 24px 64px -12px rgba(2, 8, 20, 0.55), 0 2px 8px rgba(2, 8, 20, 0.3)"
|
|
8154
8391
|
},
|
|
8155
8392
|
children: [
|
|
8156
|
-
/* @__PURE__ */
|
|
8393
|
+
/* @__PURE__ */ jsx78(
|
|
8157
8394
|
"div",
|
|
8158
8395
|
{
|
|
8159
8396
|
style: {
|
|
@@ -8162,7 +8399,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8162
8399
|
}
|
|
8163
8400
|
}
|
|
8164
8401
|
),
|
|
8165
|
-
/* @__PURE__ */
|
|
8402
|
+
/* @__PURE__ */ jsx78(Card, { children: /* @__PURE__ */ jsxs69(
|
|
8166
8403
|
"div",
|
|
8167
8404
|
{
|
|
8168
8405
|
style: {
|
|
@@ -8174,13 +8411,13 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8174
8411
|
padding: "var(--s-8) 0"
|
|
8175
8412
|
},
|
|
8176
8413
|
children: [
|
|
8177
|
-
/* @__PURE__ */
|
|
8178
|
-
/* @__PURE__ */
|
|
8179
|
-
/* @__PURE__ */
|
|
8414
|
+
/* @__PURE__ */ jsxs69("div", { children: [
|
|
8415
|
+
/* @__PURE__ */ jsx78("h1", { className: "fd-h3", style: { color: "var(--navy)" }, children: productName }),
|
|
8416
|
+
/* @__PURE__ */ jsx78("p", { className: "fd-body-sm fd-muted", style: { marginTop: "var(--s-4)" }, children: continueAs ? "Your session timed out, but you're likely still signed in" : "Sign in with your flytedesk workspace account" })
|
|
8180
8417
|
] }),
|
|
8181
|
-
error ? /* @__PURE__ */
|
|
8182
|
-
continueAs ? /* @__PURE__ */
|
|
8183
|
-
/* @__PURE__ */
|
|
8418
|
+
error ? /* @__PURE__ */ jsx78("div", { role: "alert", style: { width: "100%" }, children: /* @__PURE__ */ jsx78(Banner, { tone: "danger", title: error }) }) : null,
|
|
8419
|
+
continueAs ? /* @__PURE__ */ jsxs69(Fragment19, { children: [
|
|
8420
|
+
/* @__PURE__ */ jsx78(
|
|
8184
8421
|
Button,
|
|
8185
8422
|
{
|
|
8186
8423
|
variant: "primary",
|
|
@@ -8191,7 +8428,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8191
8428
|
children: resuming ? "Resuming\u2026" : `Continue as ${continueAs.name}`
|
|
8192
8429
|
}
|
|
8193
8430
|
),
|
|
8194
|
-
/* @__PURE__ */
|
|
8431
|
+
/* @__PURE__ */ jsx78(
|
|
8195
8432
|
"button",
|
|
8196
8433
|
{
|
|
8197
8434
|
type: "button",
|
|
@@ -8208,7 +8445,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8208
8445
|
children: "Not you? Sign in with flytedesk ID"
|
|
8209
8446
|
}
|
|
8210
8447
|
)
|
|
8211
|
-
] }) : /* @__PURE__ */
|
|
8448
|
+
] }) : /* @__PURE__ */ jsx78(
|
|
8212
8449
|
Button,
|
|
8213
8450
|
{
|
|
8214
8451
|
variant: "primary",
|
|
@@ -8216,7 +8453,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8216
8453
|
loading: signingIn,
|
|
8217
8454
|
disabled: signingIn,
|
|
8218
8455
|
onClick: handleSignIn,
|
|
8219
|
-
children: /* @__PURE__ */
|
|
8456
|
+
children: /* @__PURE__ */ jsxs69(
|
|
8220
8457
|
"span",
|
|
8221
8458
|
{
|
|
8222
8459
|
style: {
|
|
@@ -8228,14 +8465,14 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8228
8465
|
flexWrap: "nowrap"
|
|
8229
8466
|
},
|
|
8230
8467
|
children: [
|
|
8231
|
-
/* @__PURE__ */
|
|
8232
|
-
/* @__PURE__ */
|
|
8468
|
+
/* @__PURE__ */ jsx78(GoogleGlyph, {}),
|
|
8469
|
+
/* @__PURE__ */ jsx78("span", { children: signingIn ? "Signing in\u2026" : "Sign in with flytedesk ID" })
|
|
8233
8470
|
]
|
|
8234
8471
|
}
|
|
8235
8472
|
)
|
|
8236
8473
|
}
|
|
8237
8474
|
),
|
|
8238
|
-
/* @__PURE__ */
|
|
8475
|
+
/* @__PURE__ */ jsx78("p", { className: "fd-body-sm fd-muted", style: { fontSize: "12px" }, children: "One account, every flytedesk app." })
|
|
8239
8476
|
]
|
|
8240
8477
|
}
|
|
8241
8478
|
) })
|
|
@@ -8250,29 +8487,29 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8250
8487
|
);
|
|
8251
8488
|
}
|
|
8252
8489
|
function GoogleGlyph() {
|
|
8253
|
-
return /* @__PURE__ */
|
|
8254
|
-
/* @__PURE__ */
|
|
8490
|
+
return /* @__PURE__ */ jsxs69("svg", { width: "18", height: "18", viewBox: "0 0 18 18", "aria-hidden": true, children: [
|
|
8491
|
+
/* @__PURE__ */ jsx78(
|
|
8255
8492
|
"path",
|
|
8256
8493
|
{
|
|
8257
8494
|
fill: "#4285F4",
|
|
8258
8495
|
d: "M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.87 2.68-6.62Z"
|
|
8259
8496
|
}
|
|
8260
8497
|
),
|
|
8261
|
-
/* @__PURE__ */
|
|
8498
|
+
/* @__PURE__ */ jsx78(
|
|
8262
8499
|
"path",
|
|
8263
8500
|
{
|
|
8264
8501
|
fill: "#34A853",
|
|
8265
8502
|
d: "M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.81.54-1.84.87-3.04.87-2.34 0-4.32-1.58-5.03-3.7H.96v2.33A9 9 0 0 0 9 18Z"
|
|
8266
8503
|
}
|
|
8267
8504
|
),
|
|
8268
|
-
/* @__PURE__ */
|
|
8505
|
+
/* @__PURE__ */ jsx78(
|
|
8269
8506
|
"path",
|
|
8270
8507
|
{
|
|
8271
8508
|
fill: "#FBBC05",
|
|
8272
8509
|
d: "M3.97 10.73A5.4 5.4 0 0 1 3.68 9c0-.6.1-1.19.29-1.73V4.94H.96A9 9 0 0 0 0 9c0 1.45.35 2.83.96 4.06l3.01-2.33Z"
|
|
8273
8510
|
}
|
|
8274
8511
|
),
|
|
8275
|
-
/* @__PURE__ */
|
|
8512
|
+
/* @__PURE__ */ jsx78(
|
|
8276
8513
|
"path",
|
|
8277
8514
|
{
|
|
8278
8515
|
fill: "#EA4335",
|
|
@@ -8283,10 +8520,10 @@ function GoogleGlyph() {
|
|
|
8283
8520
|
}
|
|
8284
8521
|
|
|
8285
8522
|
// src/components/platform/RoadmapTimeline.tsx
|
|
8286
|
-
import * as
|
|
8523
|
+
import * as React54 from "react";
|
|
8287
8524
|
|
|
8288
8525
|
// src/kits/session.ts
|
|
8289
|
-
import * as
|
|
8526
|
+
import * as React52 from "react";
|
|
8290
8527
|
var PERMISSION_CATALOG = [
|
|
8291
8528
|
{ group: "Plans", items: [
|
|
8292
8529
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -9853,8 +10090,8 @@ function roadmap(overrides) {
|
|
|
9853
10090
|
};
|
|
9854
10091
|
}
|
|
9855
10092
|
function useSession() {
|
|
9856
|
-
const [s, setS] =
|
|
9857
|
-
|
|
10093
|
+
const [s, setS] = React52.useState(getSession);
|
|
10094
|
+
React52.useEffect(() => subscribe(setS), []);
|
|
9858
10095
|
return s;
|
|
9859
10096
|
}
|
|
9860
10097
|
var SessionKit = {
|
|
@@ -9887,7 +10124,7 @@ var SessionKit = {
|
|
|
9887
10124
|
};
|
|
9888
10125
|
function DemoSessionProvider({ children }) {
|
|
9889
10126
|
const session = useSession();
|
|
9890
|
-
const value =
|
|
10127
|
+
const value = React52.useMemo(
|
|
9891
10128
|
() => ({
|
|
9892
10129
|
user: session.user,
|
|
9893
10130
|
roles: session.roles,
|
|
@@ -9903,11 +10140,11 @@ function DemoSessionProvider({ children }) {
|
|
|
9903
10140
|
}),
|
|
9904
10141
|
[session]
|
|
9905
10142
|
);
|
|
9906
|
-
return
|
|
10143
|
+
return React52.createElement(SessionProvider, { value }, children);
|
|
9907
10144
|
}
|
|
9908
10145
|
|
|
9909
10146
|
// src/kits/runtime.ts
|
|
9910
|
-
import * as
|
|
10147
|
+
import * as React53 from "react";
|
|
9911
10148
|
var WIRED_ENDPOINTS = [
|
|
9912
10149
|
// Nothing yet. Every id below would come from a real service:
|
|
9913
10150
|
// "plan.get", "placements.list", …
|
|
@@ -10078,8 +10315,8 @@ var RuntimeKit = {
|
|
|
10078
10315
|
};
|
|
10079
10316
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
10080
10317
|
function useRuntimeMode() {
|
|
10081
|
-
const [m, setM] =
|
|
10082
|
-
|
|
10318
|
+
const [m, setM] = React53.useState(RuntimeKit.getMode());
|
|
10319
|
+
React53.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
10083
10320
|
return m;
|
|
10084
10321
|
}
|
|
10085
10322
|
function useFeatureStatus(key) {
|
|
@@ -10098,7 +10335,7 @@ var UseRuntimeMode = useRuntimeMode;
|
|
|
10098
10335
|
var UseFeatureStatus = useFeatureStatus;
|
|
10099
10336
|
|
|
10100
10337
|
// src/components/platform/RoadmapTimeline.tsx
|
|
10101
|
-
import { jsx as
|
|
10338
|
+
import { jsx as jsx79, jsxs as jsxs70 } from "react/jsx-runtime";
|
|
10102
10339
|
var STATUS = {
|
|
10103
10340
|
shipped: { tone: "success", icon: "check-circle", label: "Wired" },
|
|
10104
10341
|
next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
|
|
@@ -10113,45 +10350,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
10113
10350
|
const s = STATUS[item.status] || STATUS.planned;
|
|
10114
10351
|
const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
|
|
10115
10352
|
const blocking = deps.filter((d) => !d.implemented);
|
|
10116
|
-
return /* @__PURE__ */
|
|
10117
|
-
/* @__PURE__ */
|
|
10118
|
-
/* @__PURE__ */
|
|
10119
|
-
/* @__PURE__ */
|
|
10120
|
-
/* @__PURE__ */
|
|
10353
|
+
return /* @__PURE__ */ jsx79(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
10354
|
+
/* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
10355
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
|
|
10356
|
+
/* @__PURE__ */ jsx79(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
|
|
10357
|
+
/* @__PURE__ */ jsx79(Badge, { tone: s.tone, icon: s.icon, children: s.label })
|
|
10121
10358
|
] }),
|
|
10122
|
-
/* @__PURE__ */
|
|
10123
|
-
item.backend ? /* @__PURE__ */
|
|
10124
|
-
/* @__PURE__ */
|
|
10125
|
-
/* @__PURE__ */
|
|
10359
|
+
/* @__PURE__ */ jsx79("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
|
|
10360
|
+
item.backend ? /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
|
|
10361
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
|
|
10362
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
|
|
10126
10363
|
] }) : null,
|
|
10127
|
-
/* @__PURE__ */
|
|
10128
|
-
item.effort ? /* @__PURE__ */
|
|
10129
|
-
/* @__PURE__ */
|
|
10364
|
+
/* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
10365
|
+
item.effort ? /* @__PURE__ */ jsxs70("span", { className: "fd-body-sm fd-muted", children: [
|
|
10366
|
+
/* @__PURE__ */ jsx79("i", { className: "ph ph-hourglass-medium" }),
|
|
10130
10367
|
" ",
|
|
10131
10368
|
item.effort
|
|
10132
10369
|
] }) : null,
|
|
10133
|
-
/* @__PURE__ */
|
|
10134
|
-
/* @__PURE__ */
|
|
10370
|
+
/* @__PURE__ */ jsxs70("span", { className: "fd-body-sm fd-muted", children: [
|
|
10371
|
+
/* @__PURE__ */ jsx79("i", { className: "ph ph-user" }),
|
|
10135
10372
|
" ",
|
|
10136
10373
|
item.owner
|
|
10137
10374
|
] }),
|
|
10138
|
-
item.screen ? /* @__PURE__ */
|
|
10139
|
-
/* @__PURE__ */
|
|
10140
|
-
/* @__PURE__ */
|
|
10375
|
+
item.screen ? /* @__PURE__ */ jsx79(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
|
|
10376
|
+
/* @__PURE__ */ jsx79("span", { style: { flex: 1 } }),
|
|
10377
|
+
/* @__PURE__ */ jsx79(
|
|
10141
10378
|
"button",
|
|
10142
10379
|
{
|
|
10143
10380
|
type: "button",
|
|
10144
10381
|
onClick: () => onOpenFlag && onOpenFlag(item.key),
|
|
10145
10382
|
style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
|
|
10146
|
-
children: /* @__PURE__ */
|
|
10383
|
+
children: /* @__PURE__ */ jsx79("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
|
|
10147
10384
|
}
|
|
10148
10385
|
)
|
|
10149
10386
|
] }),
|
|
10150
|
-
deps.length ? /* @__PURE__ */
|
|
10151
|
-
/* @__PURE__ */
|
|
10152
|
-
deps.map((d) => /* @__PURE__ */
|
|
10387
|
+
deps.length ? /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
|
|
10388
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
|
|
10389
|
+
deps.map((d) => /* @__PURE__ */ jsx79(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
|
|
10153
10390
|
] }) : null,
|
|
10154
|
-
blocking.length && !item.implemented ? /* @__PURE__ */
|
|
10391
|
+
blocking.length && !item.implemented ? /* @__PURE__ */ jsxs70("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
|
|
10155
10392
|
"Blocked until ",
|
|
10156
10393
|
blocking.map((d) => d.label).join(" and "),
|
|
10157
10394
|
" ",
|
|
@@ -10162,12 +10399,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
10162
10399
|
}
|
|
10163
10400
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
10164
10401
|
const session = SessionKit.useSession();
|
|
10165
|
-
const [project, setProject] =
|
|
10166
|
-
const [q, setQ] =
|
|
10167
|
-
const scrollRef =
|
|
10168
|
-
const nowRef =
|
|
10169
|
-
const rm =
|
|
10170
|
-
const byKey =
|
|
10402
|
+
const [project, setProject] = React54.useState("");
|
|
10403
|
+
const [q, setQ] = React54.useState("");
|
|
10404
|
+
const scrollRef = React54.useRef(null);
|
|
10405
|
+
const nowRef = React54.useRef(null);
|
|
10406
|
+
const rm = React54.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
10407
|
+
const byKey = React54.useMemo(() => {
|
|
10171
10408
|
const m = {};
|
|
10172
10409
|
rm.items.forEach((i) => {
|
|
10173
10410
|
m[i.key] = i;
|
|
@@ -10176,7 +10413,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10176
10413
|
}, [rm]);
|
|
10177
10414
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
10178
10415
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
10179
|
-
|
|
10416
|
+
React54.useEffect(() => {
|
|
10180
10417
|
let raf1 = 0, raf2 = 0;
|
|
10181
10418
|
const place = () => {
|
|
10182
10419
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -10204,23 +10441,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10204
10441
|
}, 0);
|
|
10205
10442
|
const nextPhase = items.find((i) => !i.implemented);
|
|
10206
10443
|
let lastPhase = null;
|
|
10207
|
-
return /* @__PURE__ */
|
|
10208
|
-
/* @__PURE__ */
|
|
10209
|
-
/* @__PURE__ */
|
|
10210
|
-
/* @__PURE__ */
|
|
10211
|
-
/* @__PURE__ */
|
|
10444
|
+
return /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
|
|
10445
|
+
/* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
10446
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Architecture" }),
|
|
10447
|
+
/* @__PURE__ */ jsx79("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
10448
|
+
/* @__PURE__ */ jsx79("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." })
|
|
10212
10449
|
] }),
|
|
10213
|
-
/* @__PURE__ */
|
|
10214
|
-
/* @__PURE__ */
|
|
10215
|
-
/* @__PURE__ */
|
|
10216
|
-
/* @__PURE__ */
|
|
10217
|
-
/* @__PURE__ */
|
|
10450
|
+
/* @__PURE__ */ jsxs70("div", { className: "fd-grid-stats is-thin", children: [
|
|
10451
|
+
/* @__PURE__ */ jsx79(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
|
|
10452
|
+
/* @__PURE__ */ jsx79(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
|
|
10453
|
+
/* @__PURE__ */ jsx79(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
|
|
10454
|
+
/* @__PURE__ */ jsx79(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
|
|
10218
10455
|
] }),
|
|
10219
|
-
/* @__PURE__ */
|
|
10220
|
-
/* @__PURE__ */
|
|
10221
|
-
/* @__PURE__ */
|
|
10222
|
-
/* @__PURE__ */
|
|
10223
|
-
/* @__PURE__ */
|
|
10456
|
+
/* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
10457
|
+
/* @__PURE__ */ jsx79(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 } }),
|
|
10458
|
+
/* @__PURE__ */ jsx79(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
|
|
10459
|
+
/* @__PURE__ */ jsx79("span", { style: { flex: 1 } }),
|
|
10460
|
+
/* @__PURE__ */ jsx79(
|
|
10224
10461
|
Button,
|
|
10225
10462
|
{
|
|
10226
10463
|
size: "sm",
|
|
@@ -10234,7 +10471,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10234
10471
|
}
|
|
10235
10472
|
)
|
|
10236
10473
|
] }),
|
|
10237
|
-
/* @__PURE__ */
|
|
10474
|
+
/* @__PURE__ */ jsx79(
|
|
10238
10475
|
Flag,
|
|
10239
10476
|
{
|
|
10240
10477
|
tone: "info",
|
|
@@ -10243,60 +10480,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10243
10480
|
actions: null
|
|
10244
10481
|
}
|
|
10245
10482
|
),
|
|
10246
|
-
/* @__PURE__ */
|
|
10247
|
-
/* @__PURE__ */
|
|
10483
|
+
/* @__PURE__ */ jsx79("div", { className: "fd-rm", children: /* @__PURE__ */ jsx79("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs70("div", { className: "fd-rm-track", children: [
|
|
10484
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx79("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
|
|
10248
10485
|
items.map((item, n) => {
|
|
10249
10486
|
const showPhase = item.phase !== lastPhase;
|
|
10250
10487
|
lastPhase = item.phase;
|
|
10251
10488
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
10252
10489
|
const isBoundary = n === firstPending;
|
|
10253
|
-
return /* @__PURE__ */
|
|
10254
|
-
showPhase ? /* @__PURE__ */
|
|
10255
|
-
/* @__PURE__ */
|
|
10256
|
-
/* @__PURE__ */
|
|
10257
|
-
item.phase === 0 ? null : /* @__PURE__ */
|
|
10490
|
+
return /* @__PURE__ */ jsxs70(React54.Fragment, { children: [
|
|
10491
|
+
showPhase ? /* @__PURE__ */ jsxs70("div", { className: "fd-rm-era", children: [
|
|
10492
|
+
/* @__PURE__ */ jsxs70("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
10493
|
+
/* @__PURE__ */ jsx79("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
10494
|
+
item.phase === 0 ? null : /* @__PURE__ */ jsxs70("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
10258
10495
|
fmtDate(item.phaseStart),
|
|
10259
10496
|
" \u2013 ",
|
|
10260
10497
|
fmtDate(item.date)
|
|
10261
10498
|
] }),
|
|
10262
|
-
/* @__PURE__ */
|
|
10499
|
+
/* @__PURE__ */ jsxs70("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
10263
10500
|
"\xB7 ",
|
|
10264
10501
|
inPhase,
|
|
10265
10502
|
" feature",
|
|
10266
10503
|
inPhase === 1 ? "" : "s"
|
|
10267
10504
|
] })
|
|
10268
10505
|
] }),
|
|
10269
|
-
item.phaseWhy ? /* @__PURE__ */
|
|
10506
|
+
item.phaseWhy ? /* @__PURE__ */ jsx79("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
|
|
10270
10507
|
] }) : null,
|
|
10271
|
-
isBoundary ? /* @__PURE__ */
|
|
10272
|
-
/* @__PURE__ */
|
|
10508
|
+
isBoundary ? /* @__PURE__ */ jsx79("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs70("span", { className: "fd-rm-now-pill", children: [
|
|
10509
|
+
/* @__PURE__ */ jsx79("i", { className: "ph ph-map-pin" }),
|
|
10273
10510
|
" You are here \u2014 everything above is wired"
|
|
10274
10511
|
] }) }) : null,
|
|
10275
|
-
/* @__PURE__ */
|
|
10276
|
-
/* @__PURE__ */
|
|
10277
|
-
/* @__PURE__ */
|
|
10512
|
+
/* @__PURE__ */ jsxs70("div", { className: "fd-rm-row", children: [
|
|
10513
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
|
|
10514
|
+
/* @__PURE__ */ jsxs70("div", { className: "fd-rm-date", children: [
|
|
10278
10515
|
fmtDate(item.date),
|
|
10279
|
-
/* @__PURE__ */
|
|
10280
|
-
/* @__PURE__ */
|
|
10516
|
+
/* @__PURE__ */ jsx79("br", {}),
|
|
10517
|
+
/* @__PURE__ */ jsx79("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
|
|
10281
10518
|
] }),
|
|
10282
|
-
/* @__PURE__ */
|
|
10519
|
+
/* @__PURE__ */ jsx79(RoadmapCard, { item, byKey, onOpenFlag })
|
|
10283
10520
|
] })
|
|
10284
10521
|
] }, item.key);
|
|
10285
10522
|
}),
|
|
10286
|
-
!items.length ? /* @__PURE__ */
|
|
10523
|
+
!items.length ? /* @__PURE__ */ jsx79("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
|
|
10287
10524
|
] }) }) }),
|
|
10288
|
-
/* @__PURE__ */
|
|
10525
|
+
/* @__PURE__ */ jsxs70("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
|
|
10289
10526
|
"Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
|
|
10290
|
-
/* @__PURE__ */
|
|
10527
|
+
/* @__PURE__ */ jsx79("code", { className: "fd-mono", children: "implemented" }),
|
|
10291
10528
|
" field, so this page cannot drift from what the apps actually do."
|
|
10292
10529
|
] })
|
|
10293
10530
|
] });
|
|
10294
10531
|
}
|
|
10295
10532
|
|
|
10296
10533
|
// src/components/platform/ComingSoon.tsx
|
|
10297
|
-
import * as
|
|
10534
|
+
import * as React55 from "react";
|
|
10298
10535
|
import { createPortal as createPortal5 } from "react-dom";
|
|
10299
|
-
import { Fragment as Fragment21, jsx as
|
|
10536
|
+
import { Fragment as Fragment21, jsx as jsx80, jsxs as jsxs71 } from "react/jsx-runtime";
|
|
10300
10537
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
10301
10538
|
function readBypassed() {
|
|
10302
10539
|
try {
|
|
@@ -10312,8 +10549,8 @@ function writeBypassed(list) {
|
|
|
10312
10549
|
}
|
|
10313
10550
|
}
|
|
10314
10551
|
function useBypass(key) {
|
|
10315
|
-
const [on, setOn] =
|
|
10316
|
-
|
|
10552
|
+
const [on, setOn] = React55.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
10553
|
+
React55.useEffect(() => {
|
|
10317
10554
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
10318
10555
|
}, [key]);
|
|
10319
10556
|
const set = (next) => {
|
|
@@ -10326,43 +10563,43 @@ function useBypass(key) {
|
|
|
10326
10563
|
return [on, set];
|
|
10327
10564
|
}
|
|
10328
10565
|
function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
|
|
10329
|
-
return /* @__PURE__ */
|
|
10330
|
-
/* @__PURE__ */
|
|
10331
|
-
/* @__PURE__ */
|
|
10566
|
+
return /* @__PURE__ */ jsxs71(Fragment21, { children: [
|
|
10567
|
+
/* @__PURE__ */ jsxs71("span", { className: "fd-soon-badge", children: [
|
|
10568
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
10332
10569
|
label
|
|
10333
10570
|
] }),
|
|
10334
|
-
detail ? /* @__PURE__ */
|
|
10335
|
-
backend ? /* @__PURE__ */
|
|
10336
|
-
/* @__PURE__ */
|
|
10571
|
+
detail ? /* @__PURE__ */ jsx80("span", { className: "fd-soon-detail", children: detail }) : null,
|
|
10572
|
+
backend ? /* @__PURE__ */ jsxs71("span", { className: "fd-soon-backend", children: [
|
|
10573
|
+
/* @__PURE__ */ jsx80("span", { className: "fd-overline", children: "Needs" }),
|
|
10337
10574
|
" ",
|
|
10338
10575
|
backend
|
|
10339
10576
|
] }) : null,
|
|
10340
|
-
eta || effort || onRoadmap ? /* @__PURE__ */
|
|
10341
|
-
eta ? /* @__PURE__ */
|
|
10342
|
-
/* @__PURE__ */
|
|
10577
|
+
eta || effort || onRoadmap ? /* @__PURE__ */ jsxs71("span", { className: "fd-soon-meta", children: [
|
|
10578
|
+
eta ? /* @__PURE__ */ jsxs71("span", { children: [
|
|
10579
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
|
|
10343
10580
|
" ",
|
|
10344
10581
|
eta
|
|
10345
10582
|
] }) : null,
|
|
10346
|
-
effort ? /* @__PURE__ */
|
|
10347
|
-
/* @__PURE__ */
|
|
10583
|
+
effort ? /* @__PURE__ */ jsxs71("span", { children: [
|
|
10584
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
|
|
10348
10585
|
" ",
|
|
10349
10586
|
effort
|
|
10350
10587
|
] }) : null,
|
|
10351
|
-
onRoadmap ? /* @__PURE__ */
|
|
10588
|
+
onRoadmap ? /* @__PURE__ */ jsxs71("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
10352
10589
|
"See the roadmap ",
|
|
10353
|
-
/* @__PURE__ */
|
|
10590
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
10354
10591
|
] }) : null
|
|
10355
10592
|
] }) : null,
|
|
10356
|
-
allowed ? /* @__PURE__ */
|
|
10357
|
-
/* @__PURE__ */
|
|
10593
|
+
allowed ? /* @__PURE__ */ jsxs71("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
|
|
10594
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-eye", "aria-hidden": "true" }),
|
|
10358
10595
|
" View and use it anyway"
|
|
10359
10596
|
] }) : null
|
|
10360
10597
|
] });
|
|
10361
10598
|
}
|
|
10362
10599
|
function useHoverCard(open2) {
|
|
10363
|
-
const anchor =
|
|
10364
|
-
const [pos, setPos] =
|
|
10365
|
-
|
|
10600
|
+
const anchor = React55.useRef(null);
|
|
10601
|
+
const [pos, setPos] = React55.useState(null);
|
|
10602
|
+
React55.useLayoutEffect(() => {
|
|
10366
10603
|
if (!open2 || !anchor.current) {
|
|
10367
10604
|
setPos(null);
|
|
10368
10605
|
return;
|
|
@@ -10414,9 +10651,9 @@ function ComingSoon({
|
|
|
10414
10651
|
const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
|
|
10415
10652
|
if (inline) {
|
|
10416
10653
|
if (allowed && bypassed) {
|
|
10417
|
-
return /* @__PURE__ */
|
|
10654
|
+
return /* @__PURE__ */ jsxs71("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
|
|
10418
10655
|
children,
|
|
10419
|
-
/* @__PURE__ */
|
|
10656
|
+
/* @__PURE__ */ jsx80(
|
|
10420
10657
|
"button",
|
|
10421
10658
|
{
|
|
10422
10659
|
type: "button",
|
|
@@ -10424,12 +10661,12 @@ function ComingSoon({
|
|
|
10424
10661
|
title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
|
|
10425
10662
|
onClick: () => setBypassed(false),
|
|
10426
10663
|
"aria-label": "Re-blur this unwired feature",
|
|
10427
|
-
children: /* @__PURE__ */
|
|
10664
|
+
children: /* @__PURE__ */ jsx80("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
10428
10665
|
}
|
|
10429
10666
|
)
|
|
10430
10667
|
] });
|
|
10431
10668
|
}
|
|
10432
|
-
return /* @__PURE__ */
|
|
10669
|
+
return /* @__PURE__ */ jsx80(
|
|
10433
10670
|
InlineSoon,
|
|
10434
10671
|
{
|
|
10435
10672
|
label,
|
|
@@ -10449,20 +10686,20 @@ function ComingSoon({
|
|
|
10449
10686
|
);
|
|
10450
10687
|
}
|
|
10451
10688
|
if (allowed && bypassed) {
|
|
10452
|
-
return /* @__PURE__ */
|
|
10453
|
-
/* @__PURE__ */
|
|
10454
|
-
/* @__PURE__ */
|
|
10455
|
-
/* @__PURE__ */
|
|
10689
|
+
return /* @__PURE__ */ jsxs71("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
|
|
10690
|
+
/* @__PURE__ */ jsxs71("div", { className: "fd-soon-bar", role: "status", children: [
|
|
10691
|
+
/* @__PURE__ */ jsxs71("span", { className: "fd-soon-badge", children: [
|
|
10692
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
10456
10693
|
"Unwired feature \u2014 you are using it anyway"
|
|
10457
10694
|
] }),
|
|
10458
|
-
/* @__PURE__ */
|
|
10459
|
-
/* @__PURE__ */
|
|
10460
|
-
onRoadmap ? /* @__PURE__ */
|
|
10695
|
+
/* @__PURE__ */ jsx80("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
|
|
10696
|
+
/* @__PURE__ */ jsxs71("span", { className: "fd-soon-bar-actions", children: [
|
|
10697
|
+
onRoadmap ? /* @__PURE__ */ jsxs71("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
10461
10698
|
"Roadmap ",
|
|
10462
|
-
/* @__PURE__ */
|
|
10699
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
10463
10700
|
] }) : null,
|
|
10464
|
-
/* @__PURE__ */
|
|
10465
|
-
/* @__PURE__ */
|
|
10701
|
+
/* @__PURE__ */ jsxs71("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
|
|
10702
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
|
|
10466
10703
|
" Re-blur"
|
|
10467
10704
|
] })
|
|
10468
10705
|
] })
|
|
@@ -10470,10 +10707,10 @@ function ComingSoon({
|
|
|
10470
10707
|
children
|
|
10471
10708
|
] });
|
|
10472
10709
|
}
|
|
10473
|
-
return /* @__PURE__ */
|
|
10474
|
-
/* @__PURE__ */
|
|
10475
|
-
/* @__PURE__ */
|
|
10476
|
-
/* @__PURE__ */
|
|
10710
|
+
return /* @__PURE__ */ jsxs71("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
|
|
10711
|
+
/* @__PURE__ */ jsx80("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
10712
|
+
/* @__PURE__ */ jsx80("div", { className: "fd-soon-veil" }),
|
|
10713
|
+
/* @__PURE__ */ jsx80("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx80(
|
|
10477
10714
|
SoonCard,
|
|
10478
10715
|
{
|
|
10479
10716
|
label,
|
|
@@ -10489,10 +10726,10 @@ function ComingSoon({
|
|
|
10489
10726
|
] });
|
|
10490
10727
|
}
|
|
10491
10728
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
10492
|
-
const [open2, setOpen] =
|
|
10729
|
+
const [open2, setOpen] = React55.useState(false);
|
|
10493
10730
|
const [anchor, pos] = useHoverCard(open2);
|
|
10494
10731
|
const zIndex = useOverlayLayer(open2);
|
|
10495
|
-
const close2 =
|
|
10732
|
+
const close2 = React55.useRef(null);
|
|
10496
10733
|
const show = () => {
|
|
10497
10734
|
if (close2.current) {
|
|
10498
10735
|
clearTimeout(close2.current);
|
|
@@ -10508,10 +10745,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10508
10745
|
setOpen(false);
|
|
10509
10746
|
}, 140);
|
|
10510
10747
|
};
|
|
10511
|
-
|
|
10748
|
+
React55.useEffect(() => () => {
|
|
10512
10749
|
if (close2.current) clearTimeout(close2.current);
|
|
10513
10750
|
}, []);
|
|
10514
|
-
return /* @__PURE__ */
|
|
10751
|
+
return /* @__PURE__ */ jsxs71(
|
|
10515
10752
|
"span",
|
|
10516
10753
|
{
|
|
10517
10754
|
ref: anchor,
|
|
@@ -10522,8 +10759,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10522
10759
|
onBlur: hide,
|
|
10523
10760
|
...rest,
|
|
10524
10761
|
children: [
|
|
10525
|
-
/* @__PURE__ */
|
|
10526
|
-
/* @__PURE__ */
|
|
10762
|
+
/* @__PURE__ */ jsx80("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
10763
|
+
/* @__PURE__ */ jsx80(
|
|
10527
10764
|
"button",
|
|
10528
10765
|
{
|
|
10529
10766
|
type: "button",
|
|
@@ -10534,11 +10771,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10534
10771
|
onFocus: show,
|
|
10535
10772
|
onBlur: hide,
|
|
10536
10773
|
onClick: () => open2 ? setOpen(false) : show(),
|
|
10537
|
-
children: /* @__PURE__ */
|
|
10774
|
+
children: /* @__PURE__ */ jsx80("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
10538
10775
|
}
|
|
10539
10776
|
),
|
|
10540
10777
|
open2 && pos ? createPortal5(
|
|
10541
|
-
/* @__PURE__ */
|
|
10778
|
+
/* @__PURE__ */ jsx80(LayerProvider, { zIndex, children: /* @__PURE__ */ jsx80(
|
|
10542
10779
|
"div",
|
|
10543
10780
|
{
|
|
10544
10781
|
className: "fd-soon-note fd-soon-hovercard",
|
|
@@ -10546,7 +10783,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10546
10783
|
style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
|
|
10547
10784
|
onMouseEnter: show,
|
|
10548
10785
|
onMouseLeave: hide,
|
|
10549
|
-
children: /* @__PURE__ */
|
|
10786
|
+
children: /* @__PURE__ */ jsx80(
|
|
10550
10787
|
SoonCard,
|
|
10551
10788
|
{
|
|
10552
10789
|
label,
|
|
@@ -10576,10 +10813,10 @@ function formatEta(iso2) {
|
|
|
10576
10813
|
var FormatEta = formatEta;
|
|
10577
10814
|
|
|
10578
10815
|
// src/components/platform/Gate.tsx
|
|
10579
|
-
import { jsx as
|
|
10816
|
+
import { jsx as jsx81, jsxs as jsxs72 } from "react/jsx-runtime";
|
|
10580
10817
|
function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
|
|
10581
10818
|
const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
|
|
10582
|
-
return /* @__PURE__ */
|
|
10819
|
+
return /* @__PURE__ */ jsxs72(
|
|
10583
10820
|
"div",
|
|
10584
10821
|
{
|
|
10585
10822
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -10595,14 +10832,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
10595
10832
|
},
|
|
10596
10833
|
...rest,
|
|
10597
10834
|
children: [
|
|
10598
|
-
/* @__PURE__ */
|
|
10599
|
-
/* @__PURE__ */
|
|
10600
|
-
/* @__PURE__ */
|
|
10835
|
+
/* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
10836
|
+
/* @__PURE__ */ jsx81("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
10837
|
+
/* @__PURE__ */ jsx81("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
|
|
10601
10838
|
] }),
|
|
10602
|
-
/* @__PURE__ */
|
|
10603
|
-
need.length ? /* @__PURE__ */
|
|
10604
|
-
/* @__PURE__ */
|
|
10605
|
-
need.map((p) => /* @__PURE__ */
|
|
10839
|
+
/* @__PURE__ */ jsx81("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." }),
|
|
10840
|
+
need.length ? /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
|
|
10841
|
+
/* @__PURE__ */ jsx81("span", { className: "fd-overline fd-muted", children: "Requires" }),
|
|
10842
|
+
need.map((p) => /* @__PURE__ */ jsx81("code", { className: "fd-mono", style: {
|
|
10606
10843
|
fontSize: 11.5,
|
|
10607
10844
|
padding: "2px 7px",
|
|
10608
10845
|
borderRadius: 5,
|
|
@@ -10615,7 +10852,7 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
10615
10852
|
);
|
|
10616
10853
|
}
|
|
10617
10854
|
function GatePending({ compact: compact3 = false, className = "" }) {
|
|
10618
|
-
return /* @__PURE__ */
|
|
10855
|
+
return /* @__PURE__ */ jsxs72(
|
|
10619
10856
|
"div",
|
|
10620
10857
|
{
|
|
10621
10858
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -10631,11 +10868,11 @@ function GatePending({ compact: compact3 = false, className = "" }) {
|
|
|
10631
10868
|
textAlign: "left"
|
|
10632
10869
|
},
|
|
10633
10870
|
children: [
|
|
10634
|
-
/* @__PURE__ */
|
|
10635
|
-
/* @__PURE__ */
|
|
10636
|
-
/* @__PURE__ */
|
|
10871
|
+
/* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
10872
|
+
/* @__PURE__ */ jsx81("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
10873
|
+
/* @__PURE__ */ jsx81("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
|
|
10637
10874
|
] }),
|
|
10638
|
-
/* @__PURE__ */
|
|
10875
|
+
/* @__PURE__ */ jsx81("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." })
|
|
10639
10876
|
]
|
|
10640
10877
|
}
|
|
10641
10878
|
);
|
|
@@ -10645,7 +10882,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
|
|
|
10645
10882
|
if (pending) {
|
|
10646
10883
|
if (pendingFallback !== void 0) return pendingFallback;
|
|
10647
10884
|
if (silent) return null;
|
|
10648
|
-
return /* @__PURE__ */
|
|
10885
|
+
return /* @__PURE__ */ jsx81(GatePending, { compact: compact3 });
|
|
10649
10886
|
}
|
|
10650
10887
|
let ok = true;
|
|
10651
10888
|
if (perm) ok = ok && can2(perm);
|
|
@@ -10654,7 +10891,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
|
|
|
10654
10891
|
if (ok) return children;
|
|
10655
10892
|
if (fallback !== void 0) return fallback;
|
|
10656
10893
|
if (silent) return null;
|
|
10657
|
-
return /* @__PURE__ */
|
|
10894
|
+
return /* @__PURE__ */ jsx81(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
|
|
10658
10895
|
}
|
|
10659
10896
|
function FeatureGate({
|
|
10660
10897
|
flag,
|
|
@@ -10677,7 +10914,7 @@ function FeatureGate({
|
|
|
10677
10914
|
const f = SessionKit.findFlag(flag) || {};
|
|
10678
10915
|
const missing = rt.missing || [];
|
|
10679
10916
|
const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
|
|
10680
|
-
return /* @__PURE__ */
|
|
10917
|
+
return /* @__PURE__ */ jsx81(
|
|
10681
10918
|
ComingSoon,
|
|
10682
10919
|
{
|
|
10683
10920
|
label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
|
|
@@ -10698,22 +10935,22 @@ function FeatureGate({
|
|
|
10698
10935
|
function PermissionHint({ perm, children }) {
|
|
10699
10936
|
const { can: can2, pending } = useSessionContext();
|
|
10700
10937
|
if (pending) {
|
|
10701
|
-
return /* @__PURE__ */
|
|
10938
|
+
return /* @__PURE__ */ jsx81("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ jsx81("span", { style: { pointerEvents: "none" }, children }) });
|
|
10702
10939
|
}
|
|
10703
10940
|
if (can2(perm)) return children;
|
|
10704
|
-
return /* @__PURE__ */
|
|
10941
|
+
return /* @__PURE__ */ jsx81(
|
|
10705
10942
|
"span",
|
|
10706
10943
|
{
|
|
10707
10944
|
title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
|
|
10708
10945
|
style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
|
|
10709
10946
|
"aria-disabled": "true",
|
|
10710
|
-
children: /* @__PURE__ */
|
|
10947
|
+
children: /* @__PURE__ */ jsx81("span", { style: { pointerEvents: "none" }, children })
|
|
10711
10948
|
}
|
|
10712
10949
|
);
|
|
10713
10950
|
}
|
|
10714
10951
|
|
|
10715
10952
|
// src/components/platform/ModeSwitch.tsx
|
|
10716
|
-
import { Fragment as Fragment22, jsx as
|
|
10953
|
+
import { Fragment as Fragment22, jsx as jsx82, jsxs as jsxs73 } from "react/jsx-runtime";
|
|
10717
10954
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
10718
10955
|
const mode2 = useRuntimeMode();
|
|
10719
10956
|
const panel = useInlinePanel();
|
|
@@ -10725,8 +10962,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
10725
10962
|
RuntimeKit.setMode(next);
|
|
10726
10963
|
setOpen(false);
|
|
10727
10964
|
};
|
|
10728
|
-
return /* @__PURE__ */
|
|
10729
|
-
/* @__PURE__ */
|
|
10965
|
+
return /* @__PURE__ */ jsxs73("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
|
|
10966
|
+
/* @__PURE__ */ jsxs73(
|
|
10730
10967
|
"button",
|
|
10731
10968
|
{
|
|
10732
10969
|
type: "button",
|
|
@@ -10736,29 +10973,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
10736
10973
|
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.",
|
|
10737
10974
|
className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
|
|
10738
10975
|
children: [
|
|
10739
|
-
/* @__PURE__ */
|
|
10740
|
-
test && requestCount ? /* @__PURE__ */
|
|
10976
|
+
/* @__PURE__ */ jsx82("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
|
|
10977
|
+
test && requestCount ? /* @__PURE__ */ jsx82("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
|
|
10741
10978
|
]
|
|
10742
10979
|
}
|
|
10743
10980
|
),
|
|
10744
|
-
open2 ? /* @__PURE__ */
|
|
10745
|
-
/* @__PURE__ */
|
|
10746
|
-
/* @__PURE__ */
|
|
10747
|
-
/* @__PURE__ */
|
|
10981
|
+
open2 ? /* @__PURE__ */ jsx82(InlinePanelLayers, { panel, children: /* @__PURE__ */ jsxs73("span", { className: "fd-view-enter fd-mode-pop", style: { zIndex }, children: [
|
|
10982
|
+
/* @__PURE__ */ jsxs73("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
10983
|
+
/* @__PURE__ */ jsxs73("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
|
|
10984
|
+
/* @__PURE__ */ jsx82("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
|
|
10748
10985
|
test ? "Test mode" : "Live mode"
|
|
10749
10986
|
] }),
|
|
10750
|
-
test ? /* @__PURE__ */
|
|
10987
|
+
test ? /* @__PURE__ */ jsxs73("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
10751
10988
|
requestCount,
|
|
10752
10989
|
" simulated request",
|
|
10753
10990
|
requestCount === 1 ? "" : "s"
|
|
10754
10991
|
] }) : null,
|
|
10755
|
-
/* @__PURE__ */
|
|
10756
|
-
test && onClearLog ? /* @__PURE__ */
|
|
10992
|
+
/* @__PURE__ */ jsx82("span", { style: { flex: 1 } }),
|
|
10993
|
+
test && onClearLog ? /* @__PURE__ */ jsx82("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
|
|
10757
10994
|
] }),
|
|
10758
|
-
/* @__PURE__ */
|
|
10759
|
-
/* @__PURE__ */
|
|
10760
|
-
/* @__PURE__ */
|
|
10761
|
-
/* @__PURE__ */
|
|
10995
|
+
/* @__PURE__ */ jsxs73("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
10996
|
+
/* @__PURE__ */ jsx82("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." }),
|
|
10997
|
+
/* @__PURE__ */ jsxs73("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
|
|
10998
|
+
/* @__PURE__ */ jsxs73("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
10762
10999
|
s.endpointsWired,
|
|
10763
11000
|
" endpoint",
|
|
10764
11001
|
s.endpointsWired === 1 ? "" : "s",
|
|
@@ -10768,58 +11005,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
10768
11005
|
s.total,
|
|
10769
11006
|
" features complete"
|
|
10770
11007
|
] }),
|
|
10771
|
-
onOpenSpec ? /* @__PURE__ */
|
|
10772
|
-
/* @__PURE__ */
|
|
10773
|
-
/* @__PURE__ */
|
|
11008
|
+
onOpenSpec ? /* @__PURE__ */ jsxs73(Fragment22, { children: [
|
|
11009
|
+
/* @__PURE__ */ jsx82("span", { style: { flex: 1 } }),
|
|
11010
|
+
/* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-link", onClick: () => {
|
|
10774
11011
|
setOpen(false);
|
|
10775
11012
|
onOpenSpec();
|
|
10776
11013
|
}, children: [
|
|
10777
11014
|
"API spec ",
|
|
10778
|
-
/* @__PURE__ */
|
|
11015
|
+
/* @__PURE__ */ jsx82("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
10779
11016
|
] })
|
|
10780
11017
|
] }) : null
|
|
10781
11018
|
] })
|
|
10782
11019
|
] }),
|
|
10783
|
-
/* @__PURE__ */
|
|
10784
|
-
/* @__PURE__ */
|
|
10785
|
-
/* @__PURE__ */
|
|
10786
|
-
/* @__PURE__ */
|
|
10787
|
-
/* @__PURE__ */
|
|
10788
|
-
/* @__PURE__ */
|
|
11020
|
+
/* @__PURE__ */ jsxs73("span", { className: "fd-mode-choice", children: [
|
|
11021
|
+
/* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
|
|
11022
|
+
/* @__PURE__ */ jsx82("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
11023
|
+
/* @__PURE__ */ jsxs73("span", { className: "fd-mode-opt-text", children: [
|
|
11024
|
+
/* @__PURE__ */ jsx82("span", { className: "fd-mode-opt-title", children: "Live mode" }),
|
|
11025
|
+
/* @__PURE__ */ jsx82("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
|
|
10789
11026
|
] }),
|
|
10790
|
-
!test ? /* @__PURE__ */
|
|
11027
|
+
!test ? /* @__PURE__ */ jsx82("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
10791
11028
|
] }),
|
|
10792
|
-
/* @__PURE__ */
|
|
10793
|
-
/* @__PURE__ */
|
|
10794
|
-
/* @__PURE__ */
|
|
10795
|
-
/* @__PURE__ */
|
|
10796
|
-
/* @__PURE__ */
|
|
11029
|
+
/* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
|
|
11030
|
+
/* @__PURE__ */ jsx82("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
11031
|
+
/* @__PURE__ */ jsxs73("span", { className: "fd-mode-opt-text", children: [
|
|
11032
|
+
/* @__PURE__ */ jsx82("span", { className: "fd-mode-opt-title", children: "Test mode" }),
|
|
11033
|
+
/* @__PURE__ */ jsx82("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
|
|
10797
11034
|
] }),
|
|
10798
|
-
test ? /* @__PURE__ */
|
|
11035
|
+
test ? /* @__PURE__ */ jsx82("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
10799
11036
|
] })
|
|
10800
11037
|
] }),
|
|
10801
|
-
test && renderLog ? /* @__PURE__ */
|
|
11038
|
+
test && renderLog ? /* @__PURE__ */ jsx82("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
|
|
10802
11039
|
] }) }) : null
|
|
10803
11040
|
] });
|
|
10804
11041
|
}
|
|
10805
11042
|
function TestModeBar({ onExit }) {
|
|
10806
11043
|
const mode2 = useRuntimeMode();
|
|
10807
11044
|
if (mode2 !== "test") return null;
|
|
10808
|
-
return /* @__PURE__ */
|
|
10809
|
-
/* @__PURE__ */
|
|
10810
|
-
/* @__PURE__ */
|
|
11045
|
+
return /* @__PURE__ */ jsxs73("div", { className: "fd-testbar", role: "status", children: [
|
|
11046
|
+
/* @__PURE__ */ jsxs73("span", { className: "fd-badge fd-badge-warning", children: [
|
|
11047
|
+
/* @__PURE__ */ jsx82("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
10811
11048
|
"Test mode"
|
|
10812
11049
|
] }),
|
|
10813
|
-
/* @__PURE__ */
|
|
10814
|
-
/* @__PURE__ */
|
|
10815
|
-
/* @__PURE__ */
|
|
11050
|
+
/* @__PURE__ */ jsx82("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
|
|
11051
|
+
/* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
|
|
11052
|
+
/* @__PURE__ */ jsx82("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
10816
11053
|
" Back to live mode"
|
|
10817
11054
|
] })
|
|
10818
11055
|
] });
|
|
10819
11056
|
}
|
|
10820
11057
|
|
|
10821
11058
|
// src/components/planner/ChannelMeta.tsx
|
|
10822
|
-
import { jsx as
|
|
11059
|
+
import { jsx as jsx83, jsxs as jsxs74 } from "react/jsx-runtime";
|
|
10823
11060
|
var CHANNEL_WEIGHTS = {
|
|
10824
11061
|
"OOH": 50,
|
|
10825
11062
|
"DOOH": 50,
|
|
@@ -10872,9 +11109,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
10872
11109
|
const m = ChannelMeta(channel);
|
|
10873
11110
|
const wt = channelWeightOf(channel || "");
|
|
10874
11111
|
if (dot) {
|
|
10875
|
-
return /* @__PURE__ */
|
|
11112
|
+
return /* @__PURE__ */ jsx83("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
|
|
10876
11113
|
}
|
|
10877
|
-
return /* @__PURE__ */
|
|
11114
|
+
return /* @__PURE__ */ jsxs74(
|
|
10878
11115
|
"span",
|
|
10879
11116
|
{
|
|
10880
11117
|
className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
|
|
@@ -10882,16 +11119,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
10882
11119
|
style: { "--chan": m.color },
|
|
10883
11120
|
...rest,
|
|
10884
11121
|
children: [
|
|
10885
|
-
/* @__PURE__ */
|
|
10886
|
-
showLabel ? /* @__PURE__ */
|
|
10887
|
-
weight ? /* @__PURE__ */
|
|
11122
|
+
/* @__PURE__ */ jsx83("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
|
|
11123
|
+
showLabel ? /* @__PURE__ */ jsx83("span", { className: "fd-chan-label", children: m.label }) : null,
|
|
11124
|
+
weight ? /* @__PURE__ */ jsx83("span", { className: "fd-chan-weight", children: wt || 0 }) : null
|
|
10888
11125
|
]
|
|
10889
11126
|
}
|
|
10890
11127
|
);
|
|
10891
11128
|
}
|
|
10892
11129
|
|
|
10893
11130
|
// src/components/planner/SaturationDistribution.tsx
|
|
10894
|
-
import { jsx as
|
|
11131
|
+
import { jsx as jsx84, jsxs as jsxs75 } from "react/jsx-runtime";
|
|
10895
11132
|
var BANDS2 = [
|
|
10896
11133
|
{ key: "weak", label: "Weak", n: 1, range: "< 50" },
|
|
10897
11134
|
{ key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
|
|
@@ -10902,24 +11139,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
10902
11139
|
const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
|
|
10903
11140
|
const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
|
|
10904
11141
|
const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
|
|
10905
|
-
return /* @__PURE__ */
|
|
10906
|
-
/* @__PURE__ */
|
|
11142
|
+
return /* @__PURE__ */ jsxs75("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
11143
|
+
/* @__PURE__ */ jsx84("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
|
|
10907
11144
|
const mark = "var(--csi-" + g.n + "-mark)";
|
|
10908
11145
|
const active = selectedBand === g.key;
|
|
10909
|
-
return /* @__PURE__ */
|
|
11146
|
+
return /* @__PURE__ */ jsxs75(
|
|
10910
11147
|
"button",
|
|
10911
11148
|
{
|
|
10912
11149
|
type: "button",
|
|
10913
11150
|
onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
|
|
10914
11151
|
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)" },
|
|
10915
11152
|
children: [
|
|
10916
|
-
/* @__PURE__ */
|
|
11153
|
+
/* @__PURE__ */ jsx84("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx84("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
|
|
10917
11154
|
// `overflow: hidden` + `white-space: nowrap` only clips once the span
|
|
10918
11155
|
// actually HAS a bounded width to clip against (see the grid/flex
|
|
10919
11156
|
// `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
|
|
10920
11157
|
// that clip readable instead of a hard cut mid-letter; the full name
|
|
10921
11158
|
// is still one hover away via `title`.
|
|
10922
|
-
/* @__PURE__ */
|
|
11159
|
+
/* @__PURE__ */ jsx84(
|
|
10923
11160
|
"span",
|
|
10924
11161
|
{
|
|
10925
11162
|
title: c.name + " \xB7 " + c.crp,
|
|
@@ -10929,13 +11166,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
10929
11166
|
c.name
|
|
10930
11167
|
)
|
|
10931
11168
|
)) }),
|
|
10932
|
-
/* @__PURE__ */
|
|
10933
|
-
/* @__PURE__ */
|
|
10934
|
-
/* @__PURE__ */
|
|
11169
|
+
/* @__PURE__ */ jsxs75("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
|
|
11170
|
+
/* @__PURE__ */ jsx84("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
|
|
11171
|
+
/* @__PURE__ */ jsx84("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx84("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
|
|
10935
11172
|
] }),
|
|
10936
|
-
/* @__PURE__ */
|
|
10937
|
-
/* @__PURE__ */
|
|
10938
|
-
/* @__PURE__ */
|
|
11173
|
+
/* @__PURE__ */ jsxs75("span", { className: "fd-stack", style: { gap: 1 }, children: [
|
|
11174
|
+
/* @__PURE__ */ jsx84("span", { className: "fd-label-lg", children: g.label }),
|
|
11175
|
+
/* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
|
|
10939
11176
|
"CRP ",
|
|
10940
11177
|
g.range
|
|
10941
11178
|
] })
|
|
@@ -10945,10 +11182,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
10945
11182
|
g.key
|
|
10946
11183
|
);
|
|
10947
11184
|
}) }),
|
|
10948
|
-
floorBand ? /* @__PURE__ */
|
|
10949
|
-
/* @__PURE__ */
|
|
10950
|
-
/* @__PURE__ */
|
|
10951
|
-
/* @__PURE__ */
|
|
11185
|
+
floorBand ? /* @__PURE__ */ jsxs75("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: [
|
|
11186
|
+
/* @__PURE__ */ jsx84("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx84("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
|
|
11187
|
+
/* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
|
|
11188
|
+
/* @__PURE__ */ jsxs75("strong", { style: { color: "var(--text)" }, children: [
|
|
10952
11189
|
"Plan floor ",
|
|
10953
11190
|
floorScore
|
|
10954
11191
|
] }),
|
|
@@ -10959,8 +11196,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
10959
11196
|
}
|
|
10960
11197
|
|
|
10961
11198
|
// src/components/planner/MixGap.tsx
|
|
10962
|
-
import * as
|
|
10963
|
-
import { Fragment as Fragment23, jsx as
|
|
11199
|
+
import * as React56 from "react";
|
|
11200
|
+
import { Fragment as Fragment23, jsx as jsx85, jsxs as jsxs76 } from "react/jsx-runtime";
|
|
10964
11201
|
var MIX_GAP_LAYOUT = {
|
|
10965
11202
|
trackHeight: 30,
|
|
10966
11203
|
barHeight: 20,
|
|
@@ -10974,19 +11211,19 @@ function mixGapOffset(value, max) {
|
|
|
10974
11211
|
}
|
|
10975
11212
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
10976
11213
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
10977
|
-
const [hover, setHover] =
|
|
11214
|
+
const [hover, setHover] = React56.useState(null);
|
|
10978
11215
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
10979
11216
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
10980
11217
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
10981
11218
|
const barTop = (trackHeight - barHeight) / 2;
|
|
10982
|
-
return /* @__PURE__ */
|
|
10983
|
-
/* @__PURE__ */
|
|
10984
|
-
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */
|
|
10985
|
-
/* @__PURE__ */
|
|
11219
|
+
return /* @__PURE__ */ jsxs76("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
|
|
11220
|
+
/* @__PURE__ */ jsxs76("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
|
|
11221
|
+
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs76("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
11222
|
+
/* @__PURE__ */ jsx85("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
|
|
10986
11223
|
l
|
|
10987
11224
|
] }, l)),
|
|
10988
|
-
/* @__PURE__ */
|
|
10989
|
-
/* @__PURE__ */
|
|
11225
|
+
/* @__PURE__ */ jsxs76("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
11226
|
+
/* @__PURE__ */ jsx85("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
|
|
10990
11227
|
"Target"
|
|
10991
11228
|
] })
|
|
10992
11229
|
] }),
|
|
@@ -10995,7 +11232,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
10995
11232
|
const tone = toneOf(gap);
|
|
10996
11233
|
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 : "");
|
|
10997
11234
|
const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
|
|
10998
|
-
return /* @__PURE__ */
|
|
11235
|
+
return /* @__PURE__ */ jsxs76(
|
|
10999
11236
|
"div",
|
|
11000
11237
|
{
|
|
11001
11238
|
className: "fd-row",
|
|
@@ -11003,15 +11240,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11003
11240
|
onMouseEnter: () => setHover(r.channel),
|
|
11004
11241
|
onMouseLeave: () => setHover(null),
|
|
11005
11242
|
children: [
|
|
11006
|
-
/* @__PURE__ */
|
|
11007
|
-
/* @__PURE__ */
|
|
11008
|
-
/* @__PURE__ */
|
|
11009
|
-
/* @__PURE__ */
|
|
11010
|
-
/* @__PURE__ */
|
|
11243
|
+
/* @__PURE__ */ jsx85("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx85(ChannelTag, { channel: r.channel, size: "sm" }) }),
|
|
11244
|
+
/* @__PURE__ */ jsx85("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx85("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs76(Fragment23, { children: [
|
|
11245
|
+
/* @__PURE__ */ jsx85("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)" } }),
|
|
11246
|
+
/* @__PURE__ */ jsx85("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 } }),
|
|
11247
|
+
/* @__PURE__ */ jsxs76("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: [
|
|
11011
11248
|
r.realized,
|
|
11012
11249
|
"%"
|
|
11013
11250
|
] }),
|
|
11014
|
-
hover === r.channel ? /* @__PURE__ */
|
|
11251
|
+
hover === r.channel ? /* @__PURE__ */ jsx85("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
|
|
11015
11252
|
] }) })
|
|
11016
11253
|
]
|
|
11017
11254
|
},
|
|
@@ -11022,7 +11259,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11022
11259
|
}
|
|
11023
11260
|
|
|
11024
11261
|
// src/components/planner/ChannelContribution.tsx
|
|
11025
|
-
import { jsx as
|
|
11262
|
+
import { jsx as jsx86, jsxs as jsxs77 } from "react/jsx-runtime";
|
|
11026
11263
|
var money = (n) => "$" + Math.round(n).toLocaleString();
|
|
11027
11264
|
function ChannelContribution({
|
|
11028
11265
|
channels = [],
|
|
@@ -11038,9 +11275,9 @@ function ChannelContribution({
|
|
|
11038
11275
|
const grand = total !== void 0 ? total : base + bonus;
|
|
11039
11276
|
const pct = (v) => grand ? v / grand * 100 : 0;
|
|
11040
11277
|
const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
|
|
11041
|
-
return /* @__PURE__ */
|
|
11042
|
-
loading ? /* @__PURE__ */
|
|
11043
|
-
channels.map((c) => /* @__PURE__ */
|
|
11278
|
+
return /* @__PURE__ */ jsxs77("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
11279
|
+
loading ? /* @__PURE__ */ jsx86("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs77("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
|
|
11280
|
+
channels.map((c) => /* @__PURE__ */ jsx86(
|
|
11044
11281
|
"span",
|
|
11045
11282
|
{
|
|
11046
11283
|
title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
|
|
@@ -11049,7 +11286,7 @@ function ChannelContribution({
|
|
|
11049
11286
|
},
|
|
11050
11287
|
c.name
|
|
11051
11288
|
)),
|
|
11052
|
-
bonus > 0 ? /* @__PURE__ */
|
|
11289
|
+
bonus > 0 ? /* @__PURE__ */ jsx86(
|
|
11053
11290
|
"span",
|
|
11054
11291
|
{
|
|
11055
11292
|
title: "Surround-sound bonus +" + bonusPct + "%",
|
|
@@ -11058,18 +11295,18 @@ function ChannelContribution({
|
|
|
11058
11295
|
}
|
|
11059
11296
|
) : null
|
|
11060
11297
|
] }),
|
|
11061
|
-
showTable ? /* @__PURE__ */
|
|
11062
|
-
/* @__PURE__ */
|
|
11063
|
-
/* @__PURE__ */
|
|
11064
|
-
/* @__PURE__ */
|
|
11065
|
-
/* @__PURE__ */
|
|
11066
|
-
/* @__PURE__ */
|
|
11067
|
-
/* @__PURE__ */
|
|
11298
|
+
showTable ? /* @__PURE__ */ jsxs77("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
|
|
11299
|
+
/* @__PURE__ */ jsx86("thead", { children: /* @__PURE__ */ jsxs77("tr", { children: [
|
|
11300
|
+
/* @__PURE__ */ jsx86("th", { style: { width: "34%" }, children: "Channel" }),
|
|
11301
|
+
/* @__PURE__ */ jsx86("th", { style: { width: "16%" }, children: "Weight" }),
|
|
11302
|
+
/* @__PURE__ */ jsx86("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
|
|
11303
|
+
/* @__PURE__ */ jsx86("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
|
|
11304
|
+
/* @__PURE__ */ jsx86("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
|
|
11068
11305
|
] }) }),
|
|
11069
|
-
/* @__PURE__ */
|
|
11070
|
-
channels.map((c) => /* @__PURE__ */
|
|
11071
|
-
/* @__PURE__ */
|
|
11072
|
-
/* @__PURE__ */
|
|
11306
|
+
/* @__PURE__ */ jsxs77("tbody", { children: [
|
|
11307
|
+
channels.map((c) => /* @__PURE__ */ jsxs77("tr", { children: [
|
|
11308
|
+
/* @__PURE__ */ jsx86("td", { children: /* @__PURE__ */ jsx86(ChannelTag, { channel: c.name, size: "sm" }) }),
|
|
11309
|
+
/* @__PURE__ */ jsx86("td", { children: /* @__PURE__ */ jsx86(
|
|
11073
11310
|
"span",
|
|
11074
11311
|
{
|
|
11075
11312
|
className: "fd-badge fd-badge-neutral",
|
|
@@ -11078,38 +11315,38 @@ function ChannelContribution({
|
|
|
11078
11315
|
children: "weight " + (channelWeightOf(c.name) || 0)
|
|
11079
11316
|
}
|
|
11080
11317
|
) }),
|
|
11081
|
-
/* @__PURE__ */
|
|
11082
|
-
/* @__PURE__ */
|
|
11083
|
-
/* @__PURE__ */
|
|
11318
|
+
/* @__PURE__ */ jsx86("td", { className: "is-num", children: c.spend }),
|
|
11319
|
+
/* @__PURE__ */ jsx86("td", { className: "is-num", children: c.crp.toFixed(1) }),
|
|
11320
|
+
/* @__PURE__ */ jsxs77("td", { className: "is-num", children: [
|
|
11084
11321
|
pct(c.crp).toFixed(0),
|
|
11085
11322
|
"%"
|
|
11086
11323
|
] })
|
|
11087
11324
|
] }, c.name)),
|
|
11088
|
-
bonus > 0 ? /* @__PURE__ */
|
|
11089
|
-
/* @__PURE__ */
|
|
11090
|
-
/* @__PURE__ */
|
|
11325
|
+
bonus > 0 ? /* @__PURE__ */ jsxs77("tr", { children: [
|
|
11326
|
+
/* @__PURE__ */ jsx86("td", { children: /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
|
|
11327
|
+
/* @__PURE__ */ jsx86("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" } }),
|
|
11091
11328
|
"Surround-sound bonus"
|
|
11092
11329
|
] }) }),
|
|
11093
|
-
/* @__PURE__ */
|
|
11330
|
+
/* @__PURE__ */ jsx86("td", { children: /* @__PURE__ */ jsxs77("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
|
|
11094
11331
|
"+",
|
|
11095
11332
|
bonusPct,
|
|
11096
11333
|
"% of +",
|
|
11097
11334
|
bonusMax,
|
|
11098
11335
|
"%"
|
|
11099
11336
|
] }) }),
|
|
11100
|
-
/* @__PURE__ */
|
|
11101
|
-
/* @__PURE__ */
|
|
11102
|
-
/* @__PURE__ */
|
|
11337
|
+
/* @__PURE__ */ jsx86("td", { className: "is-num fd-muted", children: "\u2014" }),
|
|
11338
|
+
/* @__PURE__ */ jsx86("td", { className: "is-num", children: bonus.toFixed(1) }),
|
|
11339
|
+
/* @__PURE__ */ jsxs77("td", { className: "is-num", children: [
|
|
11103
11340
|
pct(bonus).toFixed(0),
|
|
11104
11341
|
"%"
|
|
11105
11342
|
] })
|
|
11106
11343
|
] }) : null,
|
|
11107
|
-
/* @__PURE__ */
|
|
11108
|
-
/* @__PURE__ */
|
|
11109
|
-
/* @__PURE__ */
|
|
11110
|
-
/* @__PURE__ */
|
|
11111
|
-
/* @__PURE__ */
|
|
11112
|
-
/* @__PURE__ */
|
|
11344
|
+
/* @__PURE__ */ jsxs77("tr", { style: { background: "var(--surface-2)" }, children: [
|
|
11345
|
+
/* @__PURE__ */ jsx86("td", { style: { fontWeight: 700 }, children: "Campus total" }),
|
|
11346
|
+
/* @__PURE__ */ jsx86("td", {}),
|
|
11347
|
+
/* @__PURE__ */ jsx86("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
|
|
11348
|
+
/* @__PURE__ */ jsx86("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
|
|
11349
|
+
/* @__PURE__ */ jsx86("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
|
|
11113
11350
|
] })
|
|
11114
11351
|
] })
|
|
11115
11352
|
] }) : null
|
|
@@ -11117,8 +11354,8 @@ function ChannelContribution({
|
|
|
11117
11354
|
}
|
|
11118
11355
|
|
|
11119
11356
|
// src/components/planner/BudgetReallocator.tsx
|
|
11120
|
-
import * as
|
|
11121
|
-
import { Fragment as Fragment24, jsx as
|
|
11357
|
+
import * as React57 from "react";
|
|
11358
|
+
import { Fragment as Fragment24, jsx as jsx87, jsxs as jsxs78 } from "react/jsx-runtime";
|
|
11122
11359
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
11123
11360
|
function BudgetReallocator({
|
|
11124
11361
|
campus,
|
|
@@ -11133,8 +11370,8 @@ function BudgetReallocator({
|
|
|
11133
11370
|
onCancel,
|
|
11134
11371
|
className = ""
|
|
11135
11372
|
}) {
|
|
11136
|
-
const [draft, setDraft] =
|
|
11137
|
-
|
|
11373
|
+
const [draft, setDraft] = React57.useState(spend);
|
|
11374
|
+
React57.useEffect(() => setDraft(spend), [spend]);
|
|
11138
11375
|
const dirty = draft !== spend;
|
|
11139
11376
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
11140
11377
|
const nextBand = bandFor(nextCrp);
|
|
@@ -11149,10 +11386,10 @@ function BudgetReallocator({
|
|
|
11149
11386
|
setDraft(spend);
|
|
11150
11387
|
if (onCancel) onCancel();
|
|
11151
11388
|
};
|
|
11152
|
-
const trackRef =
|
|
11153
|
-
const chipRef =
|
|
11154
|
-
const [chipLeft, setChipLeft] =
|
|
11155
|
-
|
|
11389
|
+
const trackRef = React57.useRef(null);
|
|
11390
|
+
const chipRef = React57.useRef(null);
|
|
11391
|
+
const [chipLeft, setChipLeft] = React57.useState(null);
|
|
11392
|
+
React57.useLayoutEffect(() => {
|
|
11156
11393
|
const track = trackRef.current;
|
|
11157
11394
|
if (!dirty || !track) {
|
|
11158
11395
|
setChipLeft(null);
|
|
@@ -11173,23 +11410,23 @@ function BudgetReallocator({
|
|
|
11173
11410
|
ro.observe(track);
|
|
11174
11411
|
return () => ro.disconnect();
|
|
11175
11412
|
}, [dirty, pct]);
|
|
11176
|
-
return /* @__PURE__ */
|
|
11413
|
+
return /* @__PURE__ */ jsxs78(
|
|
11177
11414
|
"div",
|
|
11178
11415
|
{
|
|
11179
11416
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
11180
11417
|
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)" },
|
|
11181
11418
|
children: [
|
|
11182
|
-
/* @__PURE__ */
|
|
11183
|
-
/* @__PURE__ */
|
|
11184
|
-
/* @__PURE__ */
|
|
11185
|
-
dirty ? /* @__PURE__ */
|
|
11186
|
-
/* @__PURE__ */
|
|
11187
|
-
/* @__PURE__ */
|
|
11419
|
+
/* @__PURE__ */ jsxs78("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
11420
|
+
/* @__PURE__ */ jsx87("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
|
|
11421
|
+
/* @__PURE__ */ jsx87(CsiBadge, { band: nowBand, crp, size: "medium" }),
|
|
11422
|
+
dirty ? /* @__PURE__ */ jsxs78(Fragment24, { children: [
|
|
11423
|
+
/* @__PURE__ */ jsx87("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
|
|
11424
|
+
/* @__PURE__ */ jsx87(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
|
|
11188
11425
|
] }) : null
|
|
11189
11426
|
] }),
|
|
11190
|
-
/* @__PURE__ */
|
|
11191
|
-
/* @__PURE__ */
|
|
11192
|
-
dirty ? /* @__PURE__ */
|
|
11427
|
+
/* @__PURE__ */ jsxs78("div", { className: "fd-slider", ref: trackRef, children: [
|
|
11428
|
+
/* @__PURE__ */ jsx87("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
11429
|
+
dirty ? /* @__PURE__ */ jsx87(
|
|
11193
11430
|
"span",
|
|
11194
11431
|
{
|
|
11195
11432
|
ref: chipRef,
|
|
@@ -11201,7 +11438,7 @@ function BudgetReallocator({
|
|
|
11201
11438
|
children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
|
|
11202
11439
|
}
|
|
11203
11440
|
) : null,
|
|
11204
|
-
/* @__PURE__ */
|
|
11441
|
+
/* @__PURE__ */ jsx87(
|
|
11205
11442
|
"input",
|
|
11206
11443
|
{
|
|
11207
11444
|
type: "range",
|
|
@@ -11217,13 +11454,13 @@ function BudgetReallocator({
|
|
|
11217
11454
|
}
|
|
11218
11455
|
)
|
|
11219
11456
|
] }),
|
|
11220
|
-
/* @__PURE__ */
|
|
11221
|
-
/* @__PURE__ */
|
|
11222
|
-
/* @__PURE__ */
|
|
11223
|
-
/* @__PURE__ */
|
|
11457
|
+
/* @__PURE__ */ jsxs78("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
11458
|
+
/* @__PURE__ */ jsxs78("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
|
|
11459
|
+
/* @__PURE__ */ jsx87("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
|
|
11460
|
+
/* @__PURE__ */ jsx87("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
|
|
11224
11461
|
] }),
|
|
11225
|
-
/* @__PURE__ */
|
|
11226
|
-
/* @__PURE__ */
|
|
11462
|
+
/* @__PURE__ */ jsx87("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
|
|
11463
|
+
/* @__PURE__ */ jsx87(
|
|
11227
11464
|
"button",
|
|
11228
11465
|
{
|
|
11229
11466
|
type: "button",
|
|
@@ -11242,7 +11479,7 @@ function BudgetReallocator({
|
|
|
11242
11479
|
}
|
|
11243
11480
|
|
|
11244
11481
|
// src/components/planner/SurroundSound.tsx
|
|
11245
|
-
import { jsx as
|
|
11482
|
+
import { jsx as jsx88, jsxs as jsxs79 } from "react/jsx-runtime";
|
|
11246
11483
|
var CATEGORIES = [
|
|
11247
11484
|
{ key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
|
|
11248
11485
|
{ key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
|
|
@@ -11254,26 +11491,26 @@ var CATEGORIES = [
|
|
|
11254
11491
|
function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
|
|
11255
11492
|
const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
|
|
11256
11493
|
const single = present.length <= 2;
|
|
11257
|
-
return /* @__PURE__ */
|
|
11258
|
-
/* @__PURE__ */
|
|
11494
|
+
return /* @__PURE__ */ jsxs79("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
|
|
11495
|
+
/* @__PURE__ */ jsx88("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
|
|
11259
11496
|
const on = present.includes(c.key);
|
|
11260
|
-
return /* @__PURE__ */
|
|
11497
|
+
return /* @__PURE__ */ jsxs79(
|
|
11261
11498
|
"span",
|
|
11262
11499
|
{
|
|
11263
11500
|
title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
|
|
11264
11501
|
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)" },
|
|
11265
11502
|
children: [
|
|
11266
|
-
/* @__PURE__ */
|
|
11267
|
-
/* @__PURE__ */
|
|
11503
|
+
/* @__PURE__ */ jsx88("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
11504
|
+
/* @__PURE__ */ jsx88("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
|
|
11268
11505
|
]
|
|
11269
11506
|
},
|
|
11270
11507
|
c.key
|
|
11271
11508
|
);
|
|
11272
11509
|
}) }),
|
|
11273
|
-
/* @__PURE__ */
|
|
11274
|
-
/* @__PURE__ */
|
|
11275
|
-
/* @__PURE__ */
|
|
11276
|
-
/* @__PURE__ */
|
|
11510
|
+
/* @__PURE__ */ jsxs79("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
11511
|
+
/* @__PURE__ */ jsxs79("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
11512
|
+
/* @__PURE__ */ jsx88("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
|
|
11513
|
+
/* @__PURE__ */ jsxs79("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
|
|
11277
11514
|
"+",
|
|
11278
11515
|
bonusPct,
|
|
11279
11516
|
"% of +",
|
|
@@ -11281,8 +11518,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
11281
11518
|
"%"
|
|
11282
11519
|
] })
|
|
11283
11520
|
] }),
|
|
11284
|
-
/* @__PURE__ */
|
|
11285
|
-
/* @__PURE__ */
|
|
11521
|
+
/* @__PURE__ */ jsx88("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx88("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
|
|
11522
|
+
/* @__PURE__ */ jsxs79("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
|
|
11286
11523
|
present.length,
|
|
11287
11524
|
" of 6 channel categories present.",
|
|
11288
11525
|
" ",
|
|
@@ -11294,7 +11531,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
11294
11531
|
}
|
|
11295
11532
|
|
|
11296
11533
|
// src/components/planner/Importance.tsx
|
|
11297
|
-
import { jsx as
|
|
11534
|
+
import { jsx as jsx89, jsxs as jsxs80 } from "react/jsx-runtime";
|
|
11298
11535
|
var IMPORTANCE_LEVELS = [
|
|
11299
11536
|
{ id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
|
|
11300
11537
|
{ id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
|
|
@@ -11324,7 +11561,7 @@ function importanceTokens(id) {
|
|
|
11324
11561
|
function ImportanceTag({ level, showLabel = true, size = "sm", className = "", disabled = false }) {
|
|
11325
11562
|
const lvl = importanceLevel(level);
|
|
11326
11563
|
const t = importanceTokens(level);
|
|
11327
|
-
return /* @__PURE__ */
|
|
11564
|
+
return /* @__PURE__ */ jsxs80(
|
|
11328
11565
|
"span",
|
|
11329
11566
|
{
|
|
11330
11567
|
className: ["fd-imp-tag", size === "md" ? "is-md" : "", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "),
|
|
@@ -11332,16 +11569,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
|
|
|
11332
11569
|
title: lvl.label + " \u2014 " + lvl.description,
|
|
11333
11570
|
"aria-disabled": disabled ? "true" : void 0,
|
|
11334
11571
|
children: [
|
|
11335
|
-
/* @__PURE__ */
|
|
11336
|
-
showLabel ? lvl.label : /* @__PURE__ */
|
|
11572
|
+
/* @__PURE__ */ jsx89("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
|
|
11573
|
+
showLabel ? lvl.label : /* @__PURE__ */ jsx89("span", { className: "fd-sr", children: lvl.label })
|
|
11337
11574
|
]
|
|
11338
11575
|
}
|
|
11339
11576
|
);
|
|
11340
11577
|
}
|
|
11341
11578
|
|
|
11342
11579
|
// src/components/planner/PreferenceMeter.tsx
|
|
11343
|
-
import * as
|
|
11344
|
-
import { jsx as
|
|
11580
|
+
import * as React58 from "react";
|
|
11581
|
+
import { jsx as jsx90, jsxs as jsxs81 } from "react/jsx-runtime";
|
|
11345
11582
|
function preferenceScore(criteria) {
|
|
11346
11583
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
11347
11584
|
const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
|
|
@@ -11370,8 +11607,8 @@ function PreferenceMeter({
|
|
|
11370
11607
|
className = ""
|
|
11371
11608
|
}) {
|
|
11372
11609
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
11373
|
-
const segments =
|
|
11374
|
-
return /* @__PURE__ */
|
|
11610
|
+
const segments = React58.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
11611
|
+
return /* @__PURE__ */ jsx90(
|
|
11375
11612
|
ScoreMeter,
|
|
11376
11613
|
{
|
|
11377
11614
|
score: value,
|
|
@@ -11383,22 +11620,22 @@ function PreferenceMeter({
|
|
|
11383
11620
|
placement,
|
|
11384
11621
|
className,
|
|
11385
11622
|
breakdownLabel: breakdownTitle,
|
|
11386
|
-
breakdown: /* @__PURE__ */
|
|
11387
|
-
/* @__PURE__ */
|
|
11388
|
-
/* @__PURE__ */
|
|
11389
|
-
/* @__PURE__ */
|
|
11623
|
+
breakdown: /* @__PURE__ */ jsxs81("div", { className: "fd-prefbreak", children: [
|
|
11624
|
+
/* @__PURE__ */ jsxs81("div", { className: "fd-prefbreak-head", children: [
|
|
11625
|
+
/* @__PURE__ */ jsx90("span", { className: "fd-label-lg", children: breakdownTitle }),
|
|
11626
|
+
/* @__PURE__ */ jsx90("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
|
|
11390
11627
|
] }),
|
|
11391
|
-
/* @__PURE__ */
|
|
11628
|
+
/* @__PURE__ */ jsx90("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
|
|
11392
11629
|
const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
|
|
11393
|
-
return /* @__PURE__ */
|
|
11394
|
-
/* @__PURE__ */
|
|
11395
|
-
/* @__PURE__ */
|
|
11396
|
-
/* @__PURE__ */
|
|
11397
|
-
c.note ? /* @__PURE__ */
|
|
11630
|
+
return /* @__PURE__ */ jsxs81("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
|
|
11631
|
+
/* @__PURE__ */ jsx90(ImportanceTag, { level: c.importance }),
|
|
11632
|
+
/* @__PURE__ */ jsxs81("span", { className: "fd-prefbreak-text", children: [
|
|
11633
|
+
/* @__PURE__ */ jsx90("span", { className: "fd-prefbreak-label", children: c.label }),
|
|
11634
|
+
c.note ? /* @__PURE__ */ jsx90("span", { className: "fd-prefbreak-note", children: c.note }) : null
|
|
11398
11635
|
] }),
|
|
11399
|
-
/* @__PURE__ */
|
|
11636
|
+
/* @__PURE__ */ jsxs81("span", { className: "fd-prefbreak-val fd-tabular", children: [
|
|
11400
11637
|
Math.round(Number(c.earned) || 0),
|
|
11401
|
-
/* @__PURE__ */
|
|
11638
|
+
/* @__PURE__ */ jsx90("span", { className: "fd-prefbreak-sep", children: "/" }),
|
|
11402
11639
|
Math.round(c.weight)
|
|
11403
11640
|
] })
|
|
11404
11641
|
] }, c.id);
|
|
@@ -11409,10 +11646,10 @@ function PreferenceMeter({
|
|
|
11409
11646
|
}
|
|
11410
11647
|
|
|
11411
11648
|
// src/components/chat/AgentChatPanel.tsx
|
|
11412
|
-
import * as
|
|
11649
|
+
import * as React64 from "react";
|
|
11413
11650
|
|
|
11414
11651
|
// src/components/chat/chatEngine.ts
|
|
11415
|
-
import * as
|
|
11652
|
+
import * as React59 from "react";
|
|
11416
11653
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
11417
11654
|
var JOB_PENDING = ["queued", "running"];
|
|
11418
11655
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -11466,22 +11703,22 @@ function useChatEngine(opts) {
|
|
|
11466
11703
|
onClear,
|
|
11467
11704
|
onFeedback
|
|
11468
11705
|
} = opts || {};
|
|
11469
|
-
const [status, setStatus] =
|
|
11470
|
-
const [threadId, setThreadId] =
|
|
11471
|
-
const [messages, setMessages] =
|
|
11472
|
-
const [queue, setQueue] =
|
|
11473
|
-
const [fatal, setFatal] =
|
|
11474
|
-
const [busy, setBusy] =
|
|
11475
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
11476
|
-
const listRef =
|
|
11477
|
-
const queueRef =
|
|
11478
|
-
const busyRef =
|
|
11479
|
-
const stoppedRef =
|
|
11480
|
-
const abortRef =
|
|
11481
|
-
const serverCount =
|
|
11482
|
-
const threadRef =
|
|
11483
|
-
const mounted =
|
|
11484
|
-
|
|
11706
|
+
const [status, setStatus] = React59.useState("idle");
|
|
11707
|
+
const [threadId, setThreadId] = React59.useState(null);
|
|
11708
|
+
const [messages, setMessages] = React59.useState([]);
|
|
11709
|
+
const [queue, setQueue] = React59.useState([]);
|
|
11710
|
+
const [fatal, setFatal] = React59.useState(null);
|
|
11711
|
+
const [busy, setBusy] = React59.useState(false);
|
|
11712
|
+
const [turnStartedAt, setTurnStartedAt] = React59.useState(null);
|
|
11713
|
+
const listRef = React59.useRef([]);
|
|
11714
|
+
const queueRef = React59.useRef([]);
|
|
11715
|
+
const busyRef = React59.useRef(false);
|
|
11716
|
+
const stoppedRef = React59.useRef(false);
|
|
11717
|
+
const abortRef = React59.useRef(null);
|
|
11718
|
+
const serverCount = React59.useRef(0);
|
|
11719
|
+
const threadRef = React59.useRef(null);
|
|
11720
|
+
const mounted = React59.useRef(true);
|
|
11721
|
+
React59.useEffect(() => {
|
|
11485
11722
|
mounted.current = true;
|
|
11486
11723
|
return () => {
|
|
11487
11724
|
mounted.current = false;
|
|
@@ -11503,14 +11740,14 @@ function useChatEngine(opts) {
|
|
|
11503
11740
|
}
|
|
11504
11741
|
return false;
|
|
11505
11742
|
};
|
|
11506
|
-
const loadThread =
|
|
11743
|
+
const loadThread = React59.useCallback(async (id) => {
|
|
11507
11744
|
const data = await apiAdapter.getThread(id);
|
|
11508
11745
|
const list = [...data && data.messages || []];
|
|
11509
11746
|
serverCount.current = list.length;
|
|
11510
11747
|
commit(list);
|
|
11511
11748
|
return list;
|
|
11512
11749
|
}, [apiAdapter]);
|
|
11513
|
-
|
|
11750
|
+
React59.useEffect(() => {
|
|
11514
11751
|
if (!apiAdapter) {
|
|
11515
11752
|
setStatus("idle");
|
|
11516
11753
|
setFatal(null);
|
|
@@ -11723,7 +11960,7 @@ function useChatEngine(opts) {
|
|
|
11723
11960
|
await dispatchTurn(turn);
|
|
11724
11961
|
}
|
|
11725
11962
|
}
|
|
11726
|
-
const send =
|
|
11963
|
+
const send = React59.useCallback((text, attachments) => {
|
|
11727
11964
|
const body = (text || "").trim();
|
|
11728
11965
|
if (!body && !(attachments && attachments.length)) return;
|
|
11729
11966
|
if (status === "disconnected") return;
|
|
@@ -11733,7 +11970,7 @@ function useChatEngine(opts) {
|
|
|
11733
11970
|
stoppedRef.current = false;
|
|
11734
11971
|
drain();
|
|
11735
11972
|
}, [status]);
|
|
11736
|
-
const stop =
|
|
11973
|
+
const stop = React59.useCallback(() => {
|
|
11737
11974
|
stoppedRef.current = true;
|
|
11738
11975
|
const ac = abortRef.current;
|
|
11739
11976
|
if (ac) {
|
|
@@ -11752,11 +11989,11 @@ function useChatEngine(opts) {
|
|
|
11752
11989
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
11753
11990
|
}
|
|
11754
11991
|
}, [apiAdapter]);
|
|
11755
|
-
const removeQueued =
|
|
11992
|
+
const removeQueued = React59.useCallback((id) => {
|
|
11756
11993
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
11757
11994
|
setQueue(queueRef.current.slice());
|
|
11758
11995
|
}, []);
|
|
11759
|
-
const retry =
|
|
11996
|
+
const retry = React59.useCallback(() => {
|
|
11760
11997
|
const list = listRef.current;
|
|
11761
11998
|
let at = -1;
|
|
11762
11999
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -11772,19 +12009,19 @@ function useChatEngine(opts) {
|
|
|
11772
12009
|
setQueue(queueRef.current.slice());
|
|
11773
12010
|
drain();
|
|
11774
12011
|
}, []);
|
|
11775
|
-
const clear =
|
|
12012
|
+
const clear = React59.useCallback(() => {
|
|
11776
12013
|
commit([]);
|
|
11777
12014
|
serverCount.current = 0;
|
|
11778
12015
|
queueRef.current = [];
|
|
11779
12016
|
setQueue([]);
|
|
11780
12017
|
onClear && onClear();
|
|
11781
12018
|
}, [onClear]);
|
|
11782
|
-
const setFeedback =
|
|
12019
|
+
const setFeedback = React59.useCallback((id, value) => {
|
|
11783
12020
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
11784
12021
|
const msg = listRef.current.find((m) => m.id === id);
|
|
11785
12022
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
11786
12023
|
}, [onFeedback]);
|
|
11787
|
-
const reload =
|
|
12024
|
+
const reload = React59.useCallback(async () => {
|
|
11788
12025
|
if (!threadRef.current) return;
|
|
11789
12026
|
setStatus("loading");
|
|
11790
12027
|
try {
|
|
@@ -11822,11 +12059,11 @@ var ChatKit = {
|
|
|
11822
12059
|
};
|
|
11823
12060
|
|
|
11824
12061
|
// src/components/chat/ChatTranscript.tsx
|
|
11825
|
-
import * as
|
|
12062
|
+
import * as React61 from "react";
|
|
11826
12063
|
|
|
11827
12064
|
// src/components/chat/ChatTurn.tsx
|
|
11828
|
-
import * as
|
|
11829
|
-
import { jsx as
|
|
12065
|
+
import * as React60 from "react";
|
|
12066
|
+
import { jsx as jsx91, jsxs as jsxs82 } from "react/jsx-runtime";
|
|
11830
12067
|
function JsonView({ value }) {
|
|
11831
12068
|
let text;
|
|
11832
12069
|
try {
|
|
@@ -11834,67 +12071,67 @@ function JsonView({ value }) {
|
|
|
11834
12071
|
} catch (e) {
|
|
11835
12072
|
text = String(value);
|
|
11836
12073
|
}
|
|
11837
|
-
return /* @__PURE__ */
|
|
12074
|
+
return /* @__PURE__ */ jsx91(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
|
|
11838
12075
|
}
|
|
11839
12076
|
function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
11840
12077
|
if (!packet) return null;
|
|
11841
12078
|
const s = schema || {};
|
|
11842
12079
|
const invalid = packet.valid === false;
|
|
11843
12080
|
const title = s.heading || packet.type;
|
|
11844
|
-
return /* @__PURE__ */
|
|
11845
|
-
/* @__PURE__ */
|
|
11846
|
-
/* @__PURE__ */
|
|
11847
|
-
/* @__PURE__ */
|
|
11848
|
-
packet.repaired ? /* @__PURE__ */
|
|
11849
|
-
invalid ? /* @__PURE__ */
|
|
12081
|
+
return /* @__PURE__ */ jsxs82("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
|
|
12082
|
+
/* @__PURE__ */ jsxs82("header", { className: "fdc-packet-head", children: [
|
|
12083
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
|
|
12084
|
+
/* @__PURE__ */ jsx91("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
|
|
12085
|
+
packet.repaired ? /* @__PURE__ */ jsx91("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
|
|
12086
|
+
invalid ? /* @__PURE__ */ jsx91("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
|
|
11850
12087
|
] }),
|
|
11851
|
-
invalid ? /* @__PURE__ */
|
|
11852
|
-
/* @__PURE__ */
|
|
11853
|
-
/* @__PURE__ */
|
|
11854
|
-
] }) : /* @__PURE__ */
|
|
11855
|
-
!invalid && onApply ? /* @__PURE__ */
|
|
11856
|
-
packet.repaired ? /* @__PURE__ */
|
|
11857
|
-
/* @__PURE__ */
|
|
11858
|
-
/* @__PURE__ */
|
|
12088
|
+
invalid ? /* @__PURE__ */ jsxs82("div", { className: "fdc-packet-alert", role: "alert", children: [
|
|
12089
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
12090
|
+
/* @__PURE__ */ jsx91("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
|
|
12091
|
+
] }) : /* @__PURE__ */ jsx91("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx91(JsonView, { value: packet.payload }) }),
|
|
12092
|
+
!invalid && onApply ? /* @__PURE__ */ jsxs82("footer", { className: "fdc-packet-foot", children: [
|
|
12093
|
+
packet.repaired ? /* @__PURE__ */ jsx91("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx91("span", {}),
|
|
12094
|
+
/* @__PURE__ */ jsxs82("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
|
|
12095
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
|
|
11859
12096
|
applied ? "Applied" : s.applyLabel || "Apply"
|
|
11860
12097
|
] })
|
|
11861
12098
|
] }) : null
|
|
11862
12099
|
] });
|
|
11863
12100
|
}
|
|
11864
12101
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
11865
|
-
const [open2, setOpen] =
|
|
12102
|
+
const [open2, setOpen] = React60.useState(defaultOpen);
|
|
11866
12103
|
if (!text) return null;
|
|
11867
|
-
return /* @__PURE__ */
|
|
11868
|
-
/* @__PURE__ */
|
|
11869
|
-
/* @__PURE__ */
|
|
11870
|
-
/* @__PURE__ */
|
|
11871
|
-
streaming ? /* @__PURE__ */
|
|
11872
|
-
/* @__PURE__ */
|
|
11873
|
-
/* @__PURE__ */
|
|
11874
|
-
/* @__PURE__ */
|
|
12104
|
+
return /* @__PURE__ */ jsxs82("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
|
|
12105
|
+
/* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
12106
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-brain", "aria-hidden": "true" }),
|
|
12107
|
+
/* @__PURE__ */ jsx91("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
|
|
12108
|
+
streaming ? /* @__PURE__ */ jsxs82("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
12109
|
+
/* @__PURE__ */ jsx91("span", {}),
|
|
12110
|
+
/* @__PURE__ */ jsx91("span", {}),
|
|
12111
|
+
/* @__PURE__ */ jsx91("span", {})
|
|
11875
12112
|
] }) : null,
|
|
11876
|
-
/* @__PURE__ */
|
|
12113
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
|
|
11877
12114
|
] }),
|
|
11878
|
-
open2 ? /* @__PURE__ */
|
|
12115
|
+
open2 ? /* @__PURE__ */ jsx91("div", { className: "fdc-think-body", children: text }) : null
|
|
11879
12116
|
] });
|
|
11880
12117
|
}
|
|
11881
12118
|
function Citations({ items = [], onOpen }) {
|
|
11882
|
-
const [open2, setOpen] =
|
|
12119
|
+
const [open2, setOpen] = React60.useState(false);
|
|
11883
12120
|
if (!items.length) return null;
|
|
11884
|
-
return /* @__PURE__ */
|
|
11885
|
-
/* @__PURE__ */
|
|
11886
|
-
/* @__PURE__ */
|
|
11887
|
-
/* @__PURE__ */
|
|
12121
|
+
return /* @__PURE__ */ jsxs82("div", { className: "fdc-cites", children: [
|
|
12122
|
+
/* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
12123
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
|
|
12124
|
+
/* @__PURE__ */ jsxs82("span", { children: [
|
|
11888
12125
|
items.length,
|
|
11889
12126
|
" source",
|
|
11890
12127
|
items.length === 1 ? "" : "s"
|
|
11891
12128
|
] }),
|
|
11892
|
-
/* @__PURE__ */
|
|
12129
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
|
|
11893
12130
|
] }),
|
|
11894
|
-
open2 ? /* @__PURE__ */
|
|
11895
|
-
/* @__PURE__ */
|
|
11896
|
-
c.url ? /* @__PURE__ */
|
|
11897
|
-
c.detail ? /* @__PURE__ */
|
|
12131
|
+
open2 ? /* @__PURE__ */ jsx91("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs82("li", { children: [
|
|
12132
|
+
/* @__PURE__ */ jsx91("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
|
|
12133
|
+
c.url ? /* @__PURE__ */ jsx91("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx91("span", { children: c.title || "Source" }),
|
|
12134
|
+
c.detail ? /* @__PURE__ */ jsx91("span", { className: "fdc-cite-detail", children: c.detail }) : null
|
|
11898
12135
|
] }, c.id || i)) }) : null
|
|
11899
12136
|
] });
|
|
11900
12137
|
}
|
|
@@ -11905,29 +12142,29 @@ function clampText(text, max) {
|
|
|
11905
12142
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
11906
12143
|
}
|
|
11907
12144
|
function MessageBody({ message: m, ctx }) {
|
|
11908
|
-
const [expanded, setExpanded] =
|
|
12145
|
+
const [expanded, setExpanded] = React60.useState(false);
|
|
11909
12146
|
const isUser = m.role === "user";
|
|
11910
12147
|
const raw = m.text || "";
|
|
11911
12148
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
11912
12149
|
const body = clamped != null ? clamped : raw;
|
|
11913
12150
|
const showMd = ctx.markdown && !isUser;
|
|
11914
|
-
return /* @__PURE__ */
|
|
11915
|
-
m.thinking && ctx.showThinking ? /* @__PURE__ */
|
|
11916
|
-
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */
|
|
11917
|
-
body ? /* @__PURE__ */
|
|
11918
|
-
showMd ? /* @__PURE__ */
|
|
11919
|
-
m.streaming ? /* @__PURE__ */
|
|
12151
|
+
return /* @__PURE__ */ jsxs82("div", { className: "fdc-body", children: [
|
|
12152
|
+
m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx91(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
|
|
12153
|
+
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx91(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
|
|
12154
|
+
body ? /* @__PURE__ */ jsxs82("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
|
|
12155
|
+
showMd ? /* @__PURE__ */ jsx91(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx91("div", { className: "fdc-plain", children: body }),
|
|
12156
|
+
m.streaming ? /* @__PURE__ */ jsx91("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
|
|
11920
12157
|
] }) : null,
|
|
11921
|
-
clamped != null ? /* @__PURE__ */
|
|
11922
|
-
/* @__PURE__ */
|
|
12158
|
+
clamped != null ? /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
|
|
12159
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
|
|
11923
12160
|
"Show more",
|
|
11924
|
-
/* @__PURE__ */
|
|
11925
|
-
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */
|
|
11926
|
-
/* @__PURE__ */
|
|
12161
|
+
/* @__PURE__ */ jsx91("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
|
|
12162
|
+
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
|
|
12163
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
|
|
11927
12164
|
"Show less"
|
|
11928
12165
|
] }) : null,
|
|
11929
|
-
m.attachments && m.attachments.length ? /* @__PURE__ */
|
|
11930
|
-
m.packet ? /* @__PURE__ */
|
|
12166
|
+
m.attachments && m.attachments.length ? /* @__PURE__ */ jsx91(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
|
|
12167
|
+
m.packet ? /* @__PURE__ */ jsx91(
|
|
11931
12168
|
PacketCard,
|
|
11932
12169
|
{
|
|
11933
12170
|
packet: m.packet,
|
|
@@ -11937,44 +12174,44 @@ function MessageBody({ message: m, ctx }) {
|
|
|
11937
12174
|
applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
|
|
11938
12175
|
}
|
|
11939
12176
|
) : null,
|
|
11940
|
-
m.citations && m.citations.length ? /* @__PURE__ */
|
|
11941
|
-
m.working ? /* @__PURE__ */
|
|
11942
|
-
/* @__PURE__ */
|
|
11943
|
-
/* @__PURE__ */
|
|
11944
|
-
/* @__PURE__ */
|
|
11945
|
-
/* @__PURE__ */
|
|
12177
|
+
m.citations && m.citations.length ? /* @__PURE__ */ jsx91(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
|
|
12178
|
+
m.working ? /* @__PURE__ */ jsxs82("div", { className: "fdc-working", role: "status", children: [
|
|
12179
|
+
/* @__PURE__ */ jsxs82("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
12180
|
+
/* @__PURE__ */ jsx91("span", {}),
|
|
12181
|
+
/* @__PURE__ */ jsx91("span", {}),
|
|
12182
|
+
/* @__PURE__ */ jsx91("span", {})
|
|
11946
12183
|
] }),
|
|
11947
|
-
/* @__PURE__ */
|
|
12184
|
+
/* @__PURE__ */ jsxs82("span", { className: "fdc-working-label", children: [
|
|
11948
12185
|
m.resumed ? "Resuming" : "Working",
|
|
11949
|
-
m.job && m.job.status ? /* @__PURE__ */
|
|
12186
|
+
m.job && m.job.status ? /* @__PURE__ */ jsxs82("span", { className: "fdc-working-job", children: [
|
|
11950
12187
|
" \xB7 ",
|
|
11951
12188
|
m.job.status
|
|
11952
12189
|
] }) : null,
|
|
11953
|
-
m.job && m.job.detail ? /* @__PURE__ */
|
|
12190
|
+
m.job && m.job.detail ? /* @__PURE__ */ jsxs82("span", { className: "fdc-working-job", children: [
|
|
11954
12191
|
" \xB7 ",
|
|
11955
12192
|
m.job.detail
|
|
11956
12193
|
] }) : null
|
|
11957
12194
|
] }),
|
|
11958
|
-
m.jobId ? /* @__PURE__ */
|
|
12195
|
+
m.jobId ? /* @__PURE__ */ jsx91("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
|
|
11959
12196
|
] }) : null,
|
|
11960
|
-
m.stopped ? /* @__PURE__ */
|
|
11961
|
-
/* @__PURE__ */
|
|
12197
|
+
m.stopped ? /* @__PURE__ */ jsxs82("div", { className: "fdc-stopped", children: [
|
|
12198
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
11962
12199
|
"Stopped"
|
|
11963
12200
|
] }) : null,
|
|
11964
|
-
m.error ? /* @__PURE__ */
|
|
11965
|
-
/* @__PURE__ */
|
|
11966
|
-
/* @__PURE__ */
|
|
11967
|
-
m.retryable && ctx.onRetry ? /* @__PURE__ */
|
|
11968
|
-
/* @__PURE__ */
|
|
12201
|
+
m.error ? /* @__PURE__ */ jsxs82("div", { className: "fdc-error", role: "alert", children: [
|
|
12202
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
12203
|
+
/* @__PURE__ */ jsx91("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
|
|
12204
|
+
m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
|
|
12205
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
11969
12206
|
"Retry"
|
|
11970
12207
|
] }) : null
|
|
11971
12208
|
] }) : null
|
|
11972
12209
|
] });
|
|
11973
12210
|
}
|
|
11974
12211
|
function useCopyRun() {
|
|
11975
|
-
const [done, setDone] =
|
|
11976
|
-
const t =
|
|
11977
|
-
|
|
12212
|
+
const [done, setDone] = React60.useState(false);
|
|
12213
|
+
const t = React60.useRef(null);
|
|
12214
|
+
React60.useEffect(() => () => {
|
|
11978
12215
|
if (t.current) clearTimeout(t.current);
|
|
11979
12216
|
}, []);
|
|
11980
12217
|
return [done, (text) => {
|
|
@@ -11994,16 +12231,16 @@ function RunActions({ group, ctx }) {
|
|
|
11994
12231
|
const isAssistant = group.role === "assistant";
|
|
11995
12232
|
const fb = last.feedback;
|
|
11996
12233
|
if (!ctx.messageActions) return null;
|
|
11997
|
-
return /* @__PURE__ */
|
|
11998
|
-
/* @__PURE__ */
|
|
11999
|
-
/* @__PURE__ */
|
|
12000
|
-
/* @__PURE__ */
|
|
12234
|
+
return /* @__PURE__ */ jsxs82("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
|
|
12235
|
+
/* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
|
|
12236
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
|
|
12237
|
+
/* @__PURE__ */ jsx91("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
|
|
12001
12238
|
] }),
|
|
12002
|
-
isAssistant && ctx.onRetry ? /* @__PURE__ */
|
|
12003
|
-
group.role === "user" && ctx.onEdit ? /* @__PURE__ */
|
|
12004
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */
|
|
12005
|
-
/* @__PURE__ */
|
|
12006
|
-
/* @__PURE__ */
|
|
12239
|
+
isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx91("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx91("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
12240
|
+
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx91("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx91("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
12241
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs82(React60.Fragment, { children: [
|
|
12242
|
+
/* @__PURE__ */ jsx91("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__ */ jsx91("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
12243
|
+
/* @__PURE__ */ jsx91("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__ */ jsx91("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
12007
12244
|
] }) : null,
|
|
12008
12245
|
ctx.extraActions ? ctx.extraActions(group) : null
|
|
12009
12246
|
] });
|
|
@@ -12013,22 +12250,22 @@ function ChatTurn({ group, ctx }) {
|
|
|
12013
12250
|
const name = isUser ? ctx.userName : group.author || ctx.assistantName;
|
|
12014
12251
|
const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
|
|
12015
12252
|
const stamp = group.messages[0].timestamp;
|
|
12016
|
-
return /* @__PURE__ */
|
|
12017
|
-
/* @__PURE__ */
|
|
12018
|
-
ctx.showAvatars ? /* @__PURE__ */
|
|
12019
|
-
/* @__PURE__ */
|
|
12020
|
-
stamp ? /* @__PURE__ */
|
|
12021
|
-
group.messages.some((m) => m.model) ? /* @__PURE__ */
|
|
12253
|
+
return /* @__PURE__ */ jsxs82("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
|
|
12254
|
+
/* @__PURE__ */ jsxs82("div", { className: "fdc-turn-head", children: [
|
|
12255
|
+
ctx.showAvatars ? /* @__PURE__ */ jsx91("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx91("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx91("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx91("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
|
|
12256
|
+
/* @__PURE__ */ jsx91("span", { className: "fdc-who", children: name }),
|
|
12257
|
+
stamp ? /* @__PURE__ */ jsx91(RelativeTime, { className: "fdc-when", value: stamp }) : null,
|
|
12258
|
+
group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx91("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
|
|
12022
12259
|
] }),
|
|
12023
|
-
/* @__PURE__ */
|
|
12024
|
-
group.messages.map((m) => /* @__PURE__ */
|
|
12025
|
-
/* @__PURE__ */
|
|
12260
|
+
/* @__PURE__ */ jsxs82("div", { className: "fdc-turn-body", children: [
|
|
12261
|
+
group.messages.map((m) => /* @__PURE__ */ jsx91("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx91(MessageBody, { message: m, ctx }) }, m.id)),
|
|
12262
|
+
/* @__PURE__ */ jsx91(RunActions, { group, ctx })
|
|
12026
12263
|
] })
|
|
12027
12264
|
] });
|
|
12028
12265
|
}
|
|
12029
12266
|
|
|
12030
12267
|
// src/components/chat/ChatTranscript.tsx
|
|
12031
|
-
import { jsx as
|
|
12268
|
+
import { jsx as jsx92, jsxs as jsxs83 } from "react/jsx-runtime";
|
|
12032
12269
|
var GROUP_WINDOW = 6e4;
|
|
12033
12270
|
var STICK_PX = 100;
|
|
12034
12271
|
function groupMessages(list) {
|
|
@@ -12061,25 +12298,25 @@ function dayLabel(key) {
|
|
|
12061
12298
|
}
|
|
12062
12299
|
function Suggestions({ items = [], onPick }) {
|
|
12063
12300
|
if (!items.length) return null;
|
|
12064
|
-
return /* @__PURE__ */
|
|
12301
|
+
return /* @__PURE__ */ jsx92("div", { className: "fdc-suggest", children: items.map((s, i) => {
|
|
12065
12302
|
const it = typeof s === "string" ? { label: s, text: s } : s;
|
|
12066
|
-
return /* @__PURE__ */
|
|
12067
|
-
it.icon ? /* @__PURE__ */
|
|
12068
|
-
/* @__PURE__ */
|
|
12069
|
-
/* @__PURE__ */
|
|
12070
|
-
it.description ? /* @__PURE__ */
|
|
12303
|
+
return /* @__PURE__ */ jsxs83("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
|
|
12304
|
+
it.icon ? /* @__PURE__ */ jsx92("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
|
|
12305
|
+
/* @__PURE__ */ jsxs83("span", { className: "fdc-suggest-text", children: [
|
|
12306
|
+
/* @__PURE__ */ jsx92("span", { className: "fdc-suggest-label", children: it.label }),
|
|
12307
|
+
it.description ? /* @__PURE__ */ jsx92("span", { className: "fdc-suggest-desc", children: it.description }) : null
|
|
12071
12308
|
] }),
|
|
12072
|
-
/* @__PURE__ */
|
|
12309
|
+
/* @__PURE__ */ jsx92("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
|
|
12073
12310
|
] }, it.id || i);
|
|
12074
12311
|
}) });
|
|
12075
12312
|
}
|
|
12076
12313
|
function LoadingTurns() {
|
|
12077
|
-
return /* @__PURE__ */
|
|
12078
|
-
/* @__PURE__ */
|
|
12079
|
-
/* @__PURE__ */
|
|
12080
|
-
/* @__PURE__ */
|
|
12081
|
-
/* @__PURE__ */
|
|
12082
|
-
/* @__PURE__ */
|
|
12314
|
+
return /* @__PURE__ */ jsx92("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs83("div", { className: "fdc-skel-turn", children: [
|
|
12315
|
+
/* @__PURE__ */ jsx92("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
|
|
12316
|
+
/* @__PURE__ */ jsxs83("div", { className: "fdc-skel-lines", children: [
|
|
12317
|
+
/* @__PURE__ */ jsx92("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
|
|
12318
|
+
/* @__PURE__ */ jsx92("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
|
|
12319
|
+
/* @__PURE__ */ jsx92("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
|
|
12083
12320
|
] })
|
|
12084
12321
|
] }, i)) });
|
|
12085
12322
|
}
|
|
@@ -12096,10 +12333,10 @@ function ChatTranscript({
|
|
|
12096
12333
|
renderEmpty,
|
|
12097
12334
|
className = ""
|
|
12098
12335
|
}) {
|
|
12099
|
-
const scroller =
|
|
12100
|
-
const stick =
|
|
12101
|
-
const [pill, setPill] =
|
|
12102
|
-
const seen =
|
|
12336
|
+
const scroller = React61.useRef(null);
|
|
12337
|
+
const stick = React61.useRef(true);
|
|
12338
|
+
const [pill, setPill] = React61.useState(0);
|
|
12339
|
+
const seen = React61.useRef(0);
|
|
12103
12340
|
const toBottom = (smooth) => {
|
|
12104
12341
|
const el = scroller.current;
|
|
12105
12342
|
if (!el) return;
|
|
@@ -12118,7 +12355,7 @@ function ChatTranscript({
|
|
|
12118
12355
|
seen.current = messages.length;
|
|
12119
12356
|
}
|
|
12120
12357
|
};
|
|
12121
|
-
|
|
12358
|
+
React61.useLayoutEffect(() => {
|
|
12122
12359
|
const el = scroller.current;
|
|
12123
12360
|
if (!el) return;
|
|
12124
12361
|
if (stick.current) {
|
|
@@ -12126,7 +12363,7 @@ function ChatTranscript({
|
|
|
12126
12363
|
seen.current = messages.length;
|
|
12127
12364
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
12128
12365
|
}, [messages]);
|
|
12129
|
-
|
|
12366
|
+
React61.useEffect(() => {
|
|
12130
12367
|
const el = scroller.current;
|
|
12131
12368
|
const inner = el && el.firstChild;
|
|
12132
12369
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -12136,38 +12373,38 @@ function ChatTranscript({
|
|
|
12136
12373
|
ro.observe(inner);
|
|
12137
12374
|
return () => ro.disconnect();
|
|
12138
12375
|
}, []);
|
|
12139
|
-
const groups =
|
|
12376
|
+
const groups = React61.useMemo(() => groupMessages(messages), [messages]);
|
|
12140
12377
|
const empty = !messages.length && status === "ready";
|
|
12141
|
-
return /* @__PURE__ */
|
|
12142
|
-
/* @__PURE__ */
|
|
12143
|
-
status === "loading" || status === "resolving" ? /* @__PURE__ */
|
|
12144
|
-
status === "disconnected" ? /* @__PURE__ */
|
|
12145
|
-
/* @__PURE__ */
|
|
12146
|
-
/* @__PURE__ */
|
|
12147
|
-
/* @__PURE__ */
|
|
12148
|
-
ctx.onReconnect ? /* @__PURE__ */
|
|
12149
|
-
/* @__PURE__ */
|
|
12378
|
+
return /* @__PURE__ */ jsxs83("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
12379
|
+
/* @__PURE__ */ jsxs83("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
12380
|
+
status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx92(LoadingTurns, {}) : null,
|
|
12381
|
+
status === "disconnected" ? /* @__PURE__ */ jsxs83("div", { className: "fdc-dead", children: [
|
|
12382
|
+
/* @__PURE__ */ jsx92("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx92("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
|
|
12383
|
+
/* @__PURE__ */ jsx92("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
|
|
12384
|
+
/* @__PURE__ */ jsx92("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." }),
|
|
12385
|
+
ctx.onReconnect ? /* @__PURE__ */ jsxs83("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
|
|
12386
|
+
/* @__PURE__ */ jsx92("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
12150
12387
|
"Try again"
|
|
12151
12388
|
] }) : null
|
|
12152
12389
|
] }) : null,
|
|
12153
|
-
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */
|
|
12154
|
-
/* @__PURE__ */
|
|
12155
|
-
/* @__PURE__ */
|
|
12156
|
-
emptyDescription ? /* @__PURE__ */
|
|
12157
|
-
/* @__PURE__ */
|
|
12390
|
+
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs83("div", { className: "fdc-empty", children: [
|
|
12391
|
+
/* @__PURE__ */ jsx92("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx92("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
|
|
12392
|
+
/* @__PURE__ */ jsx92("h3", { className: "fdc-empty-title", children: emptyTitle }),
|
|
12393
|
+
emptyDescription ? /* @__PURE__ */ jsx92("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
|
|
12394
|
+
/* @__PURE__ */ jsx92(Suggestions, { items: suggestions, onPick })
|
|
12158
12395
|
] }) : null,
|
|
12159
12396
|
groups.map((g, i) => {
|
|
12160
12397
|
const prev = groups[i - 1];
|
|
12161
12398
|
const k = dayKey(g.messages[0].timestamp);
|
|
12162
12399
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
12163
|
-
return /* @__PURE__ */
|
|
12164
|
-
showDay ? /* @__PURE__ */
|
|
12165
|
-
/* @__PURE__ */
|
|
12400
|
+
return /* @__PURE__ */ jsxs83(React61.Fragment, { children: [
|
|
12401
|
+
showDay ? /* @__PURE__ */ jsx92("div", { className: "fdc-day", children: /* @__PURE__ */ jsx92("span", { children: dayLabel(k) }) }) : null,
|
|
12402
|
+
/* @__PURE__ */ jsx92(ChatTurn, { group: g, ctx })
|
|
12166
12403
|
] }, g.key || i);
|
|
12167
12404
|
})
|
|
12168
12405
|
] }),
|
|
12169
|
-
pill ? /* @__PURE__ */
|
|
12170
|
-
/* @__PURE__ */
|
|
12406
|
+
pill ? /* @__PURE__ */ jsxs83("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
|
|
12407
|
+
/* @__PURE__ */ jsx92("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
|
|
12171
12408
|
pill,
|
|
12172
12409
|
" new message",
|
|
12173
12410
|
pill === 1 ? "" : "s"
|
|
@@ -12177,8 +12414,8 @@ function ChatTranscript({
|
|
|
12177
12414
|
var TranscriptKit = { groupMessages };
|
|
12178
12415
|
|
|
12179
12416
|
// src/components/chat/ChatComposer.tsx
|
|
12180
|
-
import * as
|
|
12181
|
-
import { jsx as
|
|
12417
|
+
import * as React62 from "react";
|
|
12418
|
+
import { jsx as jsx93, jsxs as jsxs84 } from "react/jsx-runtime";
|
|
12182
12419
|
function ChatComposer({
|
|
12183
12420
|
onSubmit,
|
|
12184
12421
|
onStop,
|
|
@@ -12205,17 +12442,17 @@ function ChatComposer({
|
|
|
12205
12442
|
onReject,
|
|
12206
12443
|
onOpenAttachment
|
|
12207
12444
|
}) {
|
|
12208
|
-
const [text, setText] =
|
|
12209
|
-
const [trigger, setTrigger] =
|
|
12210
|
-
const [mentionItems, setMentionItems] =
|
|
12211
|
-
const [listening, setListening] =
|
|
12212
|
-
const [notice, setNotice] =
|
|
12213
|
-
const editor =
|
|
12214
|
-
const wrap =
|
|
12215
|
-
const stopVoice =
|
|
12445
|
+
const [text, setText] = React62.useState(draft || "");
|
|
12446
|
+
const [trigger, setTrigger] = React62.useState(null);
|
|
12447
|
+
const [mentionItems, setMentionItems] = React62.useState([]);
|
|
12448
|
+
const [listening, setListening] = React62.useState(false);
|
|
12449
|
+
const [notice, setNotice] = React62.useState(null);
|
|
12450
|
+
const editor = React62.useRef(null);
|
|
12451
|
+
const wrap = React62.useRef(null);
|
|
12452
|
+
const stopVoice = React62.useRef(null);
|
|
12216
12453
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
12217
12454
|
} });
|
|
12218
|
-
|
|
12455
|
+
React62.useEffect(() => {
|
|
12219
12456
|
if (draft != null && draft !== text) setText(draft);
|
|
12220
12457
|
}, [draft]);
|
|
12221
12458
|
const change = (v) => {
|
|
@@ -12251,7 +12488,7 @@ function ChatComposer({
|
|
|
12251
12488
|
e.preventDefault();
|
|
12252
12489
|
staged.add(found.files);
|
|
12253
12490
|
};
|
|
12254
|
-
|
|
12491
|
+
React62.useEffect(() => {
|
|
12255
12492
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
12256
12493
|
setMentionItems([]);
|
|
12257
12494
|
return;
|
|
@@ -12269,7 +12506,7 @@ function ChatComposer({
|
|
|
12269
12506
|
const q = (trigger.query || "").toLowerCase();
|
|
12270
12507
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
12271
12508
|
}, [trigger, mentionSources]);
|
|
12272
|
-
const slashItems =
|
|
12509
|
+
const slashItems = React62.useMemo(() => {
|
|
12273
12510
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
12274
12511
|
const q = (trigger.query || "").toLowerCase();
|
|
12275
12512
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -12283,7 +12520,7 @@ function ChatComposer({
|
|
|
12283
12520
|
description: it.description,
|
|
12284
12521
|
icon: it.icon,
|
|
12285
12522
|
meta: mention.meta,
|
|
12286
|
-
shortcut: slash.shortcut ? /* @__PURE__ */
|
|
12523
|
+
shortcut: slash.shortcut ? /* @__PURE__ */ jsx93(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
|
|
12287
12524
|
onSelect: () => {
|
|
12288
12525
|
const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
|
|
12289
12526
|
editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
|
|
@@ -12342,14 +12579,14 @@ function ChatComposer({
|
|
|
12342
12579
|
stopVoice.current = typeof res === "function" ? res : () => {
|
|
12343
12580
|
};
|
|
12344
12581
|
};
|
|
12345
|
-
return /* @__PURE__ */
|
|
12346
|
-
queue.length ? /* @__PURE__ */
|
|
12347
|
-
/* @__PURE__ */
|
|
12348
|
-
/* @__PURE__ */
|
|
12349
|
-
onRemoveQueued ? /* @__PURE__ */
|
|
12582
|
+
return /* @__PURE__ */ jsxs84("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
|
|
12583
|
+
queue.length ? /* @__PURE__ */ jsx93("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs84("div", { className: "fdc-queue-row", children: [
|
|
12584
|
+
/* @__PURE__ */ jsx93("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
|
|
12585
|
+
/* @__PURE__ */ jsx93("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)" : "") }),
|
|
12586
|
+
onRemoveQueued ? /* @__PURE__ */ jsx93("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx93("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
12350
12587
|
] }, q.id)) }) : null,
|
|
12351
12588
|
sessionBar,
|
|
12352
|
-
/* @__PURE__ */
|
|
12589
|
+
/* @__PURE__ */ jsx93(
|
|
12353
12590
|
Dropzone,
|
|
12354
12591
|
{
|
|
12355
12592
|
className: "fdc-field",
|
|
@@ -12363,9 +12600,9 @@ function ChatComposer({
|
|
|
12363
12600
|
disabled: !fileUploadHandler || disabled,
|
|
12364
12601
|
label: "Drop to attach",
|
|
12365
12602
|
hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
|
|
12366
|
-
children: /* @__PURE__ */
|
|
12367
|
-
staged.items.length ? /* @__PURE__ */
|
|
12368
|
-
/* @__PURE__ */
|
|
12603
|
+
children: /* @__PURE__ */ jsxs84("div", { ref: wrap, className: "fdc-field-inner", children: [
|
|
12604
|
+
staged.items.length ? /* @__PURE__ */ jsx93("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx93(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
|
|
12605
|
+
/* @__PURE__ */ jsx93(
|
|
12369
12606
|
MarkdownEditor,
|
|
12370
12607
|
{
|
|
12371
12608
|
ref: editor,
|
|
@@ -12384,33 +12621,33 @@ function ChatComposer({
|
|
|
12384
12621
|
ariaLabel: "Message"
|
|
12385
12622
|
}
|
|
12386
12623
|
),
|
|
12387
|
-
/* @__PURE__ */
|
|
12388
|
-
fileUploadHandler ? /* @__PURE__ */
|
|
12389
|
-
voiceHandler ? /* @__PURE__ */
|
|
12624
|
+
/* @__PURE__ */ jsxs84("div", { className: "fdc-tools", children: [
|
|
12625
|
+
fileUploadHandler ? /* @__PURE__ */ jsx93(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
|
|
12626
|
+
voiceHandler ? /* @__PURE__ */ jsx93("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx93("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
|
|
12390
12627
|
toolbarExtras,
|
|
12391
|
-
/* @__PURE__ */
|
|
12392
|
-
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */
|
|
12628
|
+
/* @__PURE__ */ jsx93("span", { className: "fdc-tools-gap" }),
|
|
12629
|
+
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs84("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
|
|
12393
12630
|
text.length,
|
|
12394
12631
|
"/",
|
|
12395
12632
|
maxLength
|
|
12396
12633
|
] }) : null,
|
|
12397
|
-
busy ? /* @__PURE__ */
|
|
12398
|
-
/* @__PURE__ */
|
|
12399
|
-
/* @__PURE__ */
|
|
12400
|
-
] }) : /* @__PURE__ */
|
|
12401
|
-
/* @__PURE__ */
|
|
12402
|
-
/* @__PURE__ */
|
|
12634
|
+
busy ? /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
|
|
12635
|
+
/* @__PURE__ */ jsx93("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
12636
|
+
/* @__PURE__ */ jsx93("span", { children: "Stop" })
|
|
12637
|
+
] }) : /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
|
|
12638
|
+
/* @__PURE__ */ jsx93("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
|
|
12639
|
+
/* @__PURE__ */ jsx93("span", { className: "fdc-send-label", children: "Send" })
|
|
12403
12640
|
] })
|
|
12404
12641
|
] })
|
|
12405
12642
|
] })
|
|
12406
12643
|
}
|
|
12407
12644
|
),
|
|
12408
|
-
notice ? /* @__PURE__ */
|
|
12409
|
-
/* @__PURE__ */
|
|
12645
|
+
notice ? /* @__PURE__ */ jsxs84("div", { className: "fdc-notice", role: "status", children: [
|
|
12646
|
+
/* @__PURE__ */ jsx93("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
12410
12647
|
notice
|
|
12411
12648
|
] }) : null,
|
|
12412
|
-
hint && !notice ? /* @__PURE__ */
|
|
12413
|
-
/* @__PURE__ */
|
|
12649
|
+
hint && !notice ? /* @__PURE__ */ jsx93("div", { className: "fdc-hint", children: hint }) : null,
|
|
12650
|
+
/* @__PURE__ */ jsx93(
|
|
12414
12651
|
Popover,
|
|
12415
12652
|
{
|
|
12416
12653
|
open: menuOpen,
|
|
@@ -12424,12 +12661,12 @@ function ChatComposer({
|
|
|
12424
12661
|
returnFocus: false,
|
|
12425
12662
|
closeOnOutside: true,
|
|
12426
12663
|
label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
|
|
12427
|
-
children: /* @__PURE__ */
|
|
12664
|
+
children: /* @__PURE__ */ jsx93(
|
|
12428
12665
|
Menu,
|
|
12429
12666
|
{
|
|
12430
12667
|
items: menuItems,
|
|
12431
12668
|
autoFocus: false,
|
|
12432
|
-
header: /* @__PURE__ */
|
|
12669
|
+
header: /* @__PURE__ */ jsx93("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
|
|
12433
12670
|
onClose: () => setTrigger(null)
|
|
12434
12671
|
}
|
|
12435
12672
|
)
|
|
@@ -12439,12 +12676,12 @@ function ChatComposer({
|
|
|
12439
12676
|
}
|
|
12440
12677
|
|
|
12441
12678
|
// src/components/chat/ChatSessionBar.tsx
|
|
12442
|
-
import * as
|
|
12443
|
-
import { jsx as
|
|
12679
|
+
import * as React63 from "react";
|
|
12680
|
+
import { jsx as jsx94, jsxs as jsxs85 } from "react/jsx-runtime";
|
|
12444
12681
|
var compact2 = meterFormats.compact;
|
|
12445
12682
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
12446
|
-
const [open2, setOpen] =
|
|
12447
|
-
const anchor =
|
|
12683
|
+
const [open2, setOpen] = React63.useState(false);
|
|
12684
|
+
const anchor = React63.useRef(null);
|
|
12448
12685
|
const stats = sessionStats || null;
|
|
12449
12686
|
const cu = contextUsage || null;
|
|
12450
12687
|
const limits = usageLimits || null;
|
|
@@ -12459,9 +12696,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12459
12696
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
12460
12697
|
if (cu) bits.push(pct + "% context");
|
|
12461
12698
|
const expandable = !!(cu || limits);
|
|
12462
|
-
return /* @__PURE__ */
|
|
12463
|
-
/* @__PURE__ */
|
|
12464
|
-
/* @__PURE__ */
|
|
12699
|
+
return /* @__PURE__ */ jsxs85(React63.Fragment, { children: [
|
|
12700
|
+
/* @__PURE__ */ jsxs85("div", { className: "fdc-bar", children: [
|
|
12701
|
+
/* @__PURE__ */ jsxs85(
|
|
12465
12702
|
"button",
|
|
12466
12703
|
{
|
|
12467
12704
|
type: "button",
|
|
@@ -12472,15 +12709,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12472
12709
|
"aria-expanded": expandable ? open2 : void 0,
|
|
12473
12710
|
"aria-label": expandable ? "Usage details" : void 0,
|
|
12474
12711
|
children: [
|
|
12475
|
-
cu ? /* @__PURE__ */
|
|
12476
|
-
/* @__PURE__ */
|
|
12477
|
-
expandable ? /* @__PURE__ */
|
|
12712
|
+
cu ? /* @__PURE__ */ jsx94("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx94(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
|
|
12713
|
+
/* @__PURE__ */ jsx94("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
|
|
12714
|
+
expandable ? /* @__PURE__ */ jsx94("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
|
|
12478
12715
|
]
|
|
12479
12716
|
}
|
|
12480
12717
|
),
|
|
12481
12718
|
extras
|
|
12482
12719
|
] }),
|
|
12483
|
-
/* @__PURE__ */
|
|
12720
|
+
/* @__PURE__ */ jsx94(
|
|
12484
12721
|
Popover,
|
|
12485
12722
|
{
|
|
12486
12723
|
open: open2,
|
|
@@ -12491,15 +12728,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12491
12728
|
maxHeight: 460,
|
|
12492
12729
|
padded: true,
|
|
12493
12730
|
label: "Usage",
|
|
12494
|
-
footer: onClear ? /* @__PURE__ */
|
|
12731
|
+
footer: onClear ? /* @__PURE__ */ jsxs85("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
|
|
12495
12732
|
setOpen(false);
|
|
12496
12733
|
onClear();
|
|
12497
12734
|
}, children: [
|
|
12498
|
-
/* @__PURE__ */
|
|
12735
|
+
/* @__PURE__ */ jsx94("i", { className: "ph ph-trash", "aria-hidden": "true" }),
|
|
12499
12736
|
"Clear conversation"
|
|
12500
12737
|
] }) : void 0,
|
|
12501
|
-
children: /* @__PURE__ */
|
|
12502
|
-
cu ? /* @__PURE__ */
|
|
12738
|
+
children: /* @__PURE__ */ jsxs85("div", { className: "fdc-usage", children: [
|
|
12739
|
+
cu ? /* @__PURE__ */ jsx94("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx94(
|
|
12503
12740
|
SegmentedMeter,
|
|
12504
12741
|
{
|
|
12505
12742
|
total,
|
|
@@ -12511,9 +12748,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12511
12748
|
remainderLabel: "Free"
|
|
12512
12749
|
}
|
|
12513
12750
|
) }) : null,
|
|
12514
|
-
limits && limits.length ? /* @__PURE__ */
|
|
12515
|
-
/* @__PURE__ */
|
|
12516
|
-
/* @__PURE__ */
|
|
12751
|
+
limits && limits.length ? /* @__PURE__ */ jsxs85("section", { className: "fdc-usage-sec", children: [
|
|
12752
|
+
/* @__PURE__ */ jsx94("h4", { className: "fdc-usage-h", children: "Usage limits" }),
|
|
12753
|
+
/* @__PURE__ */ jsx94("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx94(
|
|
12517
12754
|
QuotaRow,
|
|
12518
12755
|
{
|
|
12519
12756
|
label: l.label,
|
|
@@ -12523,25 +12760,25 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12523
12760
|
l.id
|
|
12524
12761
|
)) })
|
|
12525
12762
|
] }) : null,
|
|
12526
|
-
stats ? /* @__PURE__ */
|
|
12527
|
-
stats.elapsedMs ? /* @__PURE__ */
|
|
12528
|
-
/* @__PURE__ */
|
|
12529
|
-
/* @__PURE__ */
|
|
12763
|
+
stats ? /* @__PURE__ */ jsxs85("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
|
|
12764
|
+
stats.elapsedMs ? /* @__PURE__ */ jsxs85("div", { children: [
|
|
12765
|
+
/* @__PURE__ */ jsx94("span", { children: "Session" }),
|
|
12766
|
+
/* @__PURE__ */ jsx94("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
|
|
12530
12767
|
] }) : null,
|
|
12531
|
-
stats.tokens ? /* @__PURE__ */
|
|
12532
|
-
/* @__PURE__ */
|
|
12533
|
-
/* @__PURE__ */
|
|
12768
|
+
stats.tokens ? /* @__PURE__ */ jsxs85("div", { children: [
|
|
12769
|
+
/* @__PURE__ */ jsx94("span", { children: "Tokens" }),
|
|
12770
|
+
/* @__PURE__ */ jsx94("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
|
|
12534
12771
|
] }) : null,
|
|
12535
|
-
stats.costUsd != null ? /* @__PURE__ */
|
|
12536
|
-
/* @__PURE__ */
|
|
12537
|
-
/* @__PURE__ */
|
|
12772
|
+
stats.costUsd != null ? /* @__PURE__ */ jsxs85("div", { children: [
|
|
12773
|
+
/* @__PURE__ */ jsx94("span", { children: "Cost" }),
|
|
12774
|
+
/* @__PURE__ */ jsxs85("b", { className: "fd-tabular", children: [
|
|
12538
12775
|
"$",
|
|
12539
12776
|
Number(stats.costUsd).toFixed(3)
|
|
12540
12777
|
] })
|
|
12541
12778
|
] }) : null,
|
|
12542
|
-
stats.turns ? /* @__PURE__ */
|
|
12543
|
-
/* @__PURE__ */
|
|
12544
|
-
/* @__PURE__ */
|
|
12779
|
+
stats.turns ? /* @__PURE__ */ jsxs85("div", { children: [
|
|
12780
|
+
/* @__PURE__ */ jsx94("span", { children: "Turns" }),
|
|
12781
|
+
/* @__PURE__ */ jsx94("b", { className: "fd-tabular", children: stats.turns })
|
|
12545
12782
|
] }) : null
|
|
12546
12783
|
] }) : null
|
|
12547
12784
|
] })
|
|
@@ -12580,7 +12817,7 @@ function ModelControls({
|
|
|
12580
12817
|
disabled: m.disabled,
|
|
12581
12818
|
checked: m.id === (current2 && current2.id),
|
|
12582
12819
|
meta: m.meta,
|
|
12583
|
-
shortcut: m.shortcut ? /* @__PURE__ */
|
|
12820
|
+
shortcut: m.shortcut ? /* @__PURE__ */ jsx94(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
|
|
12584
12821
|
onSelect: () => onModelChange && onModelChange(m.id)
|
|
12585
12822
|
});
|
|
12586
12823
|
const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
|
|
@@ -12593,15 +12830,15 @@ function ModelControls({
|
|
|
12593
12830
|
items.push({ kind: "section", label: "Fast mode" });
|
|
12594
12831
|
items.push({
|
|
12595
12832
|
kind: "custom",
|
|
12596
|
-
render: () => /* @__PURE__ */
|
|
12597
|
-
/* @__PURE__ */
|
|
12598
|
-
/* @__PURE__ */
|
|
12599
|
-
/* @__PURE__ */
|
|
12833
|
+
render: () => /* @__PURE__ */ jsxs85("label", { className: "fdc-switchrow", children: [
|
|
12834
|
+
/* @__PURE__ */ jsx94("span", { children: fastModeLabel }),
|
|
12835
|
+
/* @__PURE__ */ jsx94("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
|
|
12836
|
+
/* @__PURE__ */ jsx94("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx94("span", { className: "fd-switch-thumb" }) })
|
|
12600
12837
|
] })
|
|
12601
12838
|
});
|
|
12602
12839
|
}
|
|
12603
|
-
return /* @__PURE__ */
|
|
12604
|
-
/* @__PURE__ */
|
|
12840
|
+
return /* @__PURE__ */ jsxs85(React63.Fragment, { children: [
|
|
12841
|
+
/* @__PURE__ */ jsx94(
|
|
12605
12842
|
MenuButton,
|
|
12606
12843
|
{
|
|
12607
12844
|
items,
|
|
@@ -12612,7 +12849,7 @@ function ModelControls({
|
|
|
12612
12849
|
title: "Choose a model"
|
|
12613
12850
|
}
|
|
12614
12851
|
),
|
|
12615
|
-
effortLevels && effortLevels.length ? /* @__PURE__ */
|
|
12852
|
+
effortLevels && effortLevels.length ? /* @__PURE__ */ jsx94(
|
|
12616
12853
|
MenuButton,
|
|
12617
12854
|
{
|
|
12618
12855
|
placement: "top-end",
|
|
@@ -12633,7 +12870,7 @@ function ModelControls({
|
|
|
12633
12870
|
}
|
|
12634
12871
|
|
|
12635
12872
|
// src/components/chat/AgentChatPanel.tsx
|
|
12636
|
-
import { jsx as
|
|
12873
|
+
import { jsx as jsx95, jsxs as jsxs86 } from "react/jsx-runtime";
|
|
12637
12874
|
var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
|
|
12638
12875
|
function AgentChatPanel({
|
|
12639
12876
|
/* required */
|
|
@@ -12717,11 +12954,11 @@ function AgentChatPanel({
|
|
|
12717
12954
|
onFeedback,
|
|
12718
12955
|
onEditMessage
|
|
12719
12956
|
}) {
|
|
12720
|
-
const [panelWidth, setPanelWidth] =
|
|
12721
|
-
const [applied, setApplied] =
|
|
12722
|
-
const [draft, setDraft] =
|
|
12723
|
-
const dragging =
|
|
12724
|
-
|
|
12957
|
+
const [panelWidth, setPanelWidth] = React64.useState(width);
|
|
12958
|
+
const [applied, setApplied] = React64.useState({});
|
|
12959
|
+
const [draft, setDraft] = React64.useState("");
|
|
12960
|
+
const dragging = React64.useRef(null);
|
|
12961
|
+
React64.useEffect(() => setPanelWidth(width), [width]);
|
|
12725
12962
|
const engine = useChatEngine({
|
|
12726
12963
|
contextType,
|
|
12727
12964
|
contextId,
|
|
@@ -12787,7 +13024,7 @@ function AgentChatPanel({
|
|
|
12787
13024
|
onReconnect: engine.reload,
|
|
12788
13025
|
deadTitle: "The assistant isn\u2019t reachable"
|
|
12789
13026
|
};
|
|
12790
|
-
const sessionBar = /* @__PURE__ */
|
|
13027
|
+
const sessionBar = /* @__PURE__ */ jsx95(
|
|
12791
13028
|
ChatSessionBar,
|
|
12792
13029
|
{
|
|
12793
13030
|
sessionStats,
|
|
@@ -12796,7 +13033,7 @@ function AgentChatPanel({
|
|
|
12796
13033
|
onClear: engine.visible.length ? engine.clear : void 0
|
|
12797
13034
|
}
|
|
12798
13035
|
);
|
|
12799
|
-
const modelControls = /* @__PURE__ */
|
|
13036
|
+
const modelControls = /* @__PURE__ */ jsx95(
|
|
12800
13037
|
ModelControls,
|
|
12801
13038
|
{
|
|
12802
13039
|
models,
|
|
@@ -12811,7 +13048,7 @@ function AgentChatPanel({
|
|
|
12811
13048
|
narrow
|
|
12812
13049
|
}
|
|
12813
13050
|
);
|
|
12814
|
-
const threadMenu = threads && threads.length ? /* @__PURE__ */
|
|
13051
|
+
const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx95(
|
|
12815
13052
|
MenuButton,
|
|
12816
13053
|
{
|
|
12817
13054
|
variant: "ghost",
|
|
@@ -12838,7 +13075,7 @@ function AgentChatPanel({
|
|
|
12838
13075
|
})))
|
|
12839
13076
|
}
|
|
12840
13077
|
) : null;
|
|
12841
|
-
return /* @__PURE__ */
|
|
13078
|
+
return /* @__PURE__ */ jsxs86(
|
|
12842
13079
|
"aside",
|
|
12843
13080
|
{
|
|
12844
13081
|
className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
|
|
@@ -12849,7 +13086,7 @@ function AgentChatPanel({
|
|
|
12849
13086
|
},
|
|
12850
13087
|
"aria-label": title,
|
|
12851
13088
|
children: [
|
|
12852
|
-
surface === "sidebar" && resizable ? /* @__PURE__ */
|
|
13089
|
+
surface === "sidebar" && resizable ? /* @__PURE__ */ jsx95(
|
|
12853
13090
|
"div",
|
|
12854
13091
|
{
|
|
12855
13092
|
className: "fdc-grip",
|
|
@@ -12864,20 +13101,20 @@ function AgentChatPanel({
|
|
|
12864
13101
|
}
|
|
12865
13102
|
}
|
|
12866
13103
|
) : null,
|
|
12867
|
-
showHeader ? /* @__PURE__ */
|
|
12868
|
-
/* @__PURE__ */
|
|
12869
|
-
/* @__PURE__ */
|
|
12870
|
-
/* @__PURE__ */
|
|
12871
|
-
subtitle ? /* @__PURE__ */
|
|
13104
|
+
showHeader ? /* @__PURE__ */ jsxs86("header", { className: "fdc-head", children: [
|
|
13105
|
+
/* @__PURE__ */ jsx95("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-" + assistantIcon }) }),
|
|
13106
|
+
/* @__PURE__ */ jsxs86("span", { className: "fdc-head-titles", children: [
|
|
13107
|
+
/* @__PURE__ */ jsx95("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
|
|
13108
|
+
subtitle ? /* @__PURE__ */ jsx95("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
|
|
12872
13109
|
] }),
|
|
12873
|
-
/* @__PURE__ */
|
|
13110
|
+
/* @__PURE__ */ jsxs86("span", { className: "fdc-head-acts", children: [
|
|
12874
13111
|
headerActions,
|
|
12875
13112
|
threadMenu,
|
|
12876
|
-
onNewThread ? /* @__PURE__ */
|
|
12877
|
-
onClose ? /* @__PURE__ */
|
|
13113
|
+
onNewThread ? /* @__PURE__ */ jsx95("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
|
|
13114
|
+
onClose ? /* @__PURE__ */ jsx95("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
12878
13115
|
] })
|
|
12879
13116
|
] }) : null,
|
|
12880
|
-
/* @__PURE__ */
|
|
13117
|
+
/* @__PURE__ */ jsx95(
|
|
12881
13118
|
ChatTranscript,
|
|
12882
13119
|
{
|
|
12883
13120
|
messages: engine.visible,
|
|
@@ -12892,7 +13129,7 @@ function AgentChatPanel({
|
|
|
12892
13129
|
renderEmpty
|
|
12893
13130
|
}
|
|
12894
13131
|
),
|
|
12895
|
-
/* @__PURE__ */
|
|
13132
|
+
/* @__PURE__ */ jsx95(
|
|
12896
13133
|
ChatComposer,
|
|
12897
13134
|
{
|
|
12898
13135
|
onSubmit: (text, atts) => engine.send(text, atts),
|
|
@@ -12925,8 +13162,8 @@ function AgentChatPanel({
|
|
|
12925
13162
|
}
|
|
12926
13163
|
|
|
12927
13164
|
// src/components/files/FileViewer.tsx
|
|
12928
|
-
import * as
|
|
12929
|
-
import { jsx as
|
|
13165
|
+
import * as React65 from "react";
|
|
13166
|
+
import { jsx as jsx96, jsxs as jsxs87 } from "react/jsx-runtime";
|
|
12930
13167
|
function previewKindOf(file) {
|
|
12931
13168
|
const mime = (file.mime || "").toLowerCase();
|
|
12932
13169
|
const ext = extensionOf(file.name || "");
|
|
@@ -12982,13 +13219,13 @@ function parseDelimited(text, delimiter) {
|
|
|
12982
13219
|
return rows;
|
|
12983
13220
|
}
|
|
12984
13221
|
function usePreview(file, kind, resolveUrl) {
|
|
12985
|
-
const [state, setState] =
|
|
12986
|
-
const [attempt, setAttempt] =
|
|
12987
|
-
const resolveRef =
|
|
12988
|
-
|
|
13222
|
+
const [state, setState] = React65.useState({ status: "loading" });
|
|
13223
|
+
const [attempt, setAttempt] = React65.useState(0);
|
|
13224
|
+
const resolveRef = React65.useRef(resolveUrl);
|
|
13225
|
+
React65.useEffect(() => {
|
|
12989
13226
|
resolveRef.current = resolveUrl;
|
|
12990
13227
|
}, [resolveUrl]);
|
|
12991
|
-
|
|
13228
|
+
React65.useEffect(() => {
|
|
12992
13229
|
if (kind === "none") {
|
|
12993
13230
|
setState({ status: "ready" });
|
|
12994
13231
|
return;
|
|
@@ -13018,19 +13255,19 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
13018
13255
|
if (ac) ac.abort();
|
|
13019
13256
|
};
|
|
13020
13257
|
}, [file.id, kind, attempt]);
|
|
13021
|
-
return { ...state, retry:
|
|
13258
|
+
return { ...state, retry: React65.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
13022
13259
|
}
|
|
13023
13260
|
function PreviewBody({ file, kind, state }) {
|
|
13024
|
-
if (kind === "image") return /* @__PURE__ */
|
|
13025
|
-
if (kind === "pdf") return /* @__PURE__ */
|
|
13026
|
-
if (kind === "markdown") return /* @__PURE__ */
|
|
13261
|
+
if (kind === "image") return /* @__PURE__ */ jsx96("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
13262
|
+
if (kind === "pdf") return /* @__PURE__ */ jsx96("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
|
|
13263
|
+
if (kind === "markdown") return /* @__PURE__ */ jsx96(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
|
|
13027
13264
|
if (kind === "json") {
|
|
13028
13265
|
let pretty = state.text || "";
|
|
13029
13266
|
try {
|
|
13030
13267
|
pretty = JSON.stringify(JSON.parse(pretty), null, 2);
|
|
13031
13268
|
} catch {
|
|
13032
13269
|
}
|
|
13033
|
-
return /* @__PURE__ */
|
|
13270
|
+
return /* @__PURE__ */ jsx96(CodeBlock, { code: pretty, language: "json" });
|
|
13034
13271
|
}
|
|
13035
13272
|
if (kind === "csv") {
|
|
13036
13273
|
const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
|
|
@@ -13038,12 +13275,12 @@ function PreviewBody({ file, kind, state }) {
|
|
|
13038
13275
|
const head = rows[0] || [];
|
|
13039
13276
|
const dataRows = rows.slice(1);
|
|
13040
13277
|
const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
|
|
13041
|
-
return /* @__PURE__ */
|
|
13042
|
-
/* @__PURE__ */
|
|
13043
|
-
/* @__PURE__ */
|
|
13044
|
-
/* @__PURE__ */
|
|
13278
|
+
return /* @__PURE__ */ jsxs87("div", { className: "fd-fv-csv", children: [
|
|
13279
|
+
/* @__PURE__ */ jsxs87("table", { className: "fd-fv-csv-table", children: [
|
|
13280
|
+
/* @__PURE__ */ jsx96("thead", { children: /* @__PURE__ */ jsx96("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx96("th", { children: c }, i)) }) }),
|
|
13281
|
+
/* @__PURE__ */ jsx96("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx96("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx96("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
|
|
13045
13282
|
] }),
|
|
13046
|
-
dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */
|
|
13283
|
+
dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs87("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
|
|
13047
13284
|
"Showing the first ",
|
|
13048
13285
|
FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
|
|
13049
13286
|
" of ",
|
|
@@ -13052,24 +13289,24 @@ function PreviewBody({ file, kind, state }) {
|
|
|
13052
13289
|
] }) : null
|
|
13053
13290
|
] });
|
|
13054
13291
|
}
|
|
13055
|
-
if (kind === "text") return /* @__PURE__ */
|
|
13056
|
-
return /* @__PURE__ */
|
|
13057
|
-
/* @__PURE__ */
|
|
13058
|
-
/* @__PURE__ */
|
|
13059
|
-
/* @__PURE__ */
|
|
13292
|
+
if (kind === "text") return /* @__PURE__ */ jsx96(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
|
|
13293
|
+
return /* @__PURE__ */ jsxs87("div", { className: "fd-fv-fallback", children: [
|
|
13294
|
+
/* @__PURE__ */ jsx96("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx96("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
|
|
13295
|
+
/* @__PURE__ */ jsx96("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
|
|
13296
|
+
/* @__PURE__ */ jsxs87("span", { className: "fd-fv-fallback-meta", children: [
|
|
13060
13297
|
file.mime || "Unknown type",
|
|
13061
13298
|
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
13062
13299
|
] })
|
|
13063
13300
|
] });
|
|
13064
13301
|
}
|
|
13065
13302
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
13066
|
-
const kind =
|
|
13303
|
+
const kind = React65.useMemo(() => previewKindOf(file), [file]);
|
|
13067
13304
|
const preview = usePreview(file, kind, resolveUrl);
|
|
13068
|
-
const [tab, setTab] =
|
|
13069
|
-
const [downloading, setDownloading] =
|
|
13070
|
-
const [downloadError, setDownloadError] =
|
|
13305
|
+
const [tab, setTab] = React65.useState("preview");
|
|
13306
|
+
const [downloading, setDownloading] = React65.useState(false);
|
|
13307
|
+
const [downloadError, setDownloadError] = React65.useState(null);
|
|
13071
13308
|
const hasSide = sidePanel != null;
|
|
13072
|
-
|
|
13309
|
+
React65.useEffect(() => {
|
|
13073
13310
|
setTab("preview");
|
|
13074
13311
|
}, [file.id]);
|
|
13075
13312
|
const download = () => {
|
|
@@ -13085,29 +13322,29 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13085
13322
|
a.remove();
|
|
13086
13323
|
}).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
|
|
13087
13324
|
};
|
|
13088
|
-
return /* @__PURE__ */
|
|
13325
|
+
return /* @__PURE__ */ jsxs87(
|
|
13089
13326
|
"section",
|
|
13090
13327
|
{
|
|
13091
13328
|
className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
|
|
13092
13329
|
"aria-label": file.name || "File",
|
|
13093
13330
|
children: [
|
|
13094
|
-
/* @__PURE__ */
|
|
13095
|
-
/* @__PURE__ */
|
|
13096
|
-
/* @__PURE__ */
|
|
13097
|
-
/* @__PURE__ */
|
|
13098
|
-
/* @__PURE__ */
|
|
13331
|
+
/* @__PURE__ */ jsxs87("header", { className: "fd-fv-head", children: [
|
|
13332
|
+
/* @__PURE__ */ jsx96("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx96("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
|
|
13333
|
+
/* @__PURE__ */ jsxs87("span", { className: "fd-fv-head-titles", children: [
|
|
13334
|
+
/* @__PURE__ */ jsx96("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
|
|
13335
|
+
/* @__PURE__ */ jsxs87("span", { className: "fd-fv-head-meta", children: [
|
|
13099
13336
|
file.mime || "Unknown type",
|
|
13100
13337
|
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
13101
13338
|
] })
|
|
13102
13339
|
] }),
|
|
13103
|
-
/* @__PURE__ */
|
|
13340
|
+
/* @__PURE__ */ jsxs87("span", { className: "fd-fv-head-actions", children: [
|
|
13104
13341
|
actions,
|
|
13105
|
-
/* @__PURE__ */
|
|
13106
|
-
onClose ? /* @__PURE__ */
|
|
13342
|
+
/* @__PURE__ */ jsx96(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
|
|
13343
|
+
onClose ? /* @__PURE__ */ jsx96(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
|
|
13107
13344
|
] })
|
|
13108
13345
|
] }),
|
|
13109
|
-
downloadError ? /* @__PURE__ */
|
|
13110
|
-
hasSide ? /* @__PURE__ */
|
|
13346
|
+
downloadError ? /* @__PURE__ */ jsx96("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
|
|
13347
|
+
hasSide ? /* @__PURE__ */ jsx96(
|
|
13111
13348
|
Tabs,
|
|
13112
13349
|
{
|
|
13113
13350
|
className: "fd-fv-tabs",
|
|
@@ -13116,19 +13353,19 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13116
13353
|
onChange: (v) => setTab(v)
|
|
13117
13354
|
}
|
|
13118
13355
|
) : null,
|
|
13119
|
-
/* @__PURE__ */
|
|
13120
|
-
/* @__PURE__ */
|
|
13356
|
+
/* @__PURE__ */ jsxs87("div", { className: "fd-fv-body", children: [
|
|
13357
|
+
/* @__PURE__ */ jsx96("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx96(
|
|
13121
13358
|
LoadingRegion,
|
|
13122
13359
|
{
|
|
13123
13360
|
state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
|
|
13124
13361
|
error: preview.error,
|
|
13125
13362
|
label: "Loading preview of " + (file.name || "file"),
|
|
13126
13363
|
onRetry: preview.status === "error" ? preview.retry : void 0,
|
|
13127
|
-
skeleton: /* @__PURE__ */
|
|
13128
|
-
children: /* @__PURE__ */
|
|
13364
|
+
skeleton: /* @__PURE__ */ jsx96(Skeleton, { shape: "card", h: 220 }),
|
|
13365
|
+
children: /* @__PURE__ */ jsx96(PreviewBody, { file, kind, state: preview })
|
|
13129
13366
|
}
|
|
13130
13367
|
) }),
|
|
13131
|
-
hasSide ? /* @__PURE__ */
|
|
13368
|
+
hasSide ? /* @__PURE__ */ jsx96("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
|
|
13132
13369
|
] })
|
|
13133
13370
|
]
|
|
13134
13371
|
}
|
|
@@ -13136,8 +13373,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13136
13373
|
}
|
|
13137
13374
|
|
|
13138
13375
|
// src/components/files/FileBrowser.tsx
|
|
13139
|
-
import * as
|
|
13140
|
-
import { Fragment as Fragment28, jsx as
|
|
13376
|
+
import * as React66 from "react";
|
|
13377
|
+
import { Fragment as Fragment28, jsx as jsx97, jsxs as jsxs88 } from "react/jsx-runtime";
|
|
13141
13378
|
function childrenOf(folders, parentId) {
|
|
13142
13379
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
13143
13380
|
}
|
|
@@ -13209,8 +13446,8 @@ function FolderPickerMenu({
|
|
|
13209
13446
|
}) {
|
|
13210
13447
|
const panel = useInlinePanel();
|
|
13211
13448
|
const { open: open2, setOpen, ref, zIndex } = panel;
|
|
13212
|
-
return /* @__PURE__ */
|
|
13213
|
-
/* @__PURE__ */
|
|
13449
|
+
return /* @__PURE__ */ jsxs88("span", { className: "fd-fb-menu-anchor", ref, children: [
|
|
13450
|
+
/* @__PURE__ */ jsx97(
|
|
13214
13451
|
IconButton,
|
|
13215
13452
|
{
|
|
13216
13453
|
icon: "arrows-out-cardinal",
|
|
@@ -13222,9 +13459,9 @@ function FolderPickerMenu({
|
|
|
13222
13459
|
onClick: () => setOpen((v) => !v)
|
|
13223
13460
|
}
|
|
13224
13461
|
),
|
|
13225
|
-
open2 ? /* @__PURE__ */
|
|
13226
|
-
/* @__PURE__ */
|
|
13227
|
-
destinations.map((d) => /* @__PURE__ */
|
|
13462
|
+
open2 ? /* @__PURE__ */ jsx97(InlinePanelLayers, { panel, children: /* @__PURE__ */ jsxs88("div", { className: "fd-fb-menu", role: "menu", "aria-label": label, style: { zIndex }, children: [
|
|
13463
|
+
/* @__PURE__ */ jsx97("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
|
|
13464
|
+
destinations.map((d) => /* @__PURE__ */ jsxs88(
|
|
13228
13465
|
"button",
|
|
13229
13466
|
{
|
|
13230
13467
|
type: "button",
|
|
@@ -13236,7 +13473,7 @@ function FolderPickerMenu({
|
|
|
13236
13473
|
setOpen(false);
|
|
13237
13474
|
},
|
|
13238
13475
|
children: [
|
|
13239
|
-
/* @__PURE__ */
|
|
13476
|
+
/* @__PURE__ */ jsx97("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
|
|
13240
13477
|
d.name
|
|
13241
13478
|
]
|
|
13242
13479
|
},
|
|
@@ -13246,8 +13483,8 @@ function FolderPickerMenu({
|
|
|
13246
13483
|
] });
|
|
13247
13484
|
}
|
|
13248
13485
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
13249
|
-
const [over, setOver] =
|
|
13250
|
-
const dragCounter =
|
|
13486
|
+
const [over, setOver] = React66.useState(false);
|
|
13487
|
+
const dragCounter = React66.useRef(0);
|
|
13251
13488
|
const dropHandlers = isDropTarget ? {
|
|
13252
13489
|
onDragEnter: (e) => {
|
|
13253
13490
|
if (!hasInternalPayload(e)) return;
|
|
@@ -13272,8 +13509,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
13272
13509
|
if (payload && onDropPayload) onDropPayload(payload);
|
|
13273
13510
|
}
|
|
13274
13511
|
} : {};
|
|
13275
|
-
return /* @__PURE__ */
|
|
13276
|
-
/* @__PURE__ */
|
|
13512
|
+
return /* @__PURE__ */ jsxs88("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
|
|
13513
|
+
/* @__PURE__ */ jsxs88(
|
|
13277
13514
|
"button",
|
|
13278
13515
|
{
|
|
13279
13516
|
type: "button",
|
|
@@ -13282,26 +13519,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
13282
13519
|
draggable: !!draggableId,
|
|
13283
13520
|
onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
|
|
13284
13521
|
children: [
|
|
13285
|
-
/* @__PURE__ */
|
|
13286
|
-
/* @__PURE__ */
|
|
13287
|
-
/* @__PURE__ */
|
|
13288
|
-
meta ? /* @__PURE__ */
|
|
13522
|
+
/* @__PURE__ */ jsx97("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx97("i", { className: "ph ph-" + icon }) }),
|
|
13523
|
+
/* @__PURE__ */ jsxs88("span", { className: "fd-fb-row-text", children: [
|
|
13524
|
+
/* @__PURE__ */ jsx97("span", { className: "fd-fb-row-name", title: name, children: name }),
|
|
13525
|
+
meta ? /* @__PURE__ */ jsx97("span", { className: "fd-fb-row-meta", children: meta }) : null
|
|
13289
13526
|
] })
|
|
13290
13527
|
]
|
|
13291
13528
|
}
|
|
13292
13529
|
),
|
|
13293
|
-
actions ? /* @__PURE__ */
|
|
13530
|
+
actions ? /* @__PURE__ */ jsx97("span", { className: "fd-fb-row-actions", children: actions }) : null
|
|
13294
13531
|
] });
|
|
13295
13532
|
}
|
|
13296
13533
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
13297
13534
|
const kids = childrenOf(folders, folder.id);
|
|
13298
|
-
const [expanded, setExpanded] =
|
|
13299
|
-
|
|
13535
|
+
const [expanded, setExpanded] = React66.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
13536
|
+
React66.useEffect(() => {
|
|
13300
13537
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
13301
13538
|
}, [currentFolderId, folder.id, folders]);
|
|
13302
13539
|
const isCurrent = folder.id === currentFolderId;
|
|
13303
|
-
return /* @__PURE__ */
|
|
13304
|
-
/* @__PURE__ */
|
|
13540
|
+
return /* @__PURE__ */ jsxs88("div", { className: "fd-fb-tree-node", children: [
|
|
13541
|
+
/* @__PURE__ */ jsx97(
|
|
13305
13542
|
RowShell,
|
|
13306
13543
|
{
|
|
13307
13544
|
icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
|
|
@@ -13311,7 +13548,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
|
|
|
13311
13548
|
isDropTarget: canMove,
|
|
13312
13549
|
onDropPayload: (payload) => onMoveInto(payload, folder.id),
|
|
13313
13550
|
className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
|
|
13314
|
-
actions: kids.length ? /* @__PURE__ */
|
|
13551
|
+
actions: kids.length ? /* @__PURE__ */ jsx97(
|
|
13315
13552
|
IconButton,
|
|
13316
13553
|
{
|
|
13317
13554
|
icon: expanded ? "caret-down" : "caret-right",
|
|
@@ -13323,7 +13560,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
|
|
|
13323
13560
|
) : void 0
|
|
13324
13561
|
}
|
|
13325
13562
|
),
|
|
13326
|
-
expanded && kids.length ? /* @__PURE__ */
|
|
13563
|
+
expanded && kids.length ? /* @__PURE__ */ jsx97("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx97(
|
|
13327
13564
|
TreeNode,
|
|
13328
13565
|
{
|
|
13329
13566
|
folder: k,
|
|
@@ -13362,15 +13599,15 @@ function FileBrowser({
|
|
|
13362
13599
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
13363
13600
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
13364
13601
|
const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
|
|
13365
|
-
const [createOpen, setCreateOpen] =
|
|
13366
|
-
const [createName, setCreateName] =
|
|
13367
|
-
const [renameTarget, setRenameTarget] =
|
|
13368
|
-
const [renameValue, setRenameValue] =
|
|
13369
|
-
const [deleteTarget, setDeleteTarget] =
|
|
13370
|
-
const uploadInputRef =
|
|
13371
|
-
const crumbFolders =
|
|
13372
|
-
const subfolders =
|
|
13373
|
-
const currentFiles =
|
|
13602
|
+
const [createOpen, setCreateOpen] = React66.useState(false);
|
|
13603
|
+
const [createName, setCreateName] = React66.useState("");
|
|
13604
|
+
const [renameTarget, setRenameTarget] = React66.useState(null);
|
|
13605
|
+
const [renameValue, setRenameValue] = React66.useState("");
|
|
13606
|
+
const [deleteTarget, setDeleteTarget] = React66.useState(null);
|
|
13607
|
+
const uploadInputRef = React66.useRef(null);
|
|
13608
|
+
const crumbFolders = React66.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
13609
|
+
const subfolders = React66.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
13610
|
+
const currentFiles = React66.useMemo(
|
|
13374
13611
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
13375
13612
|
[files, currentFolderId]
|
|
13376
13613
|
);
|
|
@@ -13409,10 +13646,10 @@ function FileBrowser({
|
|
|
13409
13646
|
if (deleteTarget && onDeleteFolder) onDeleteFolder(deleteTarget);
|
|
13410
13647
|
setDeleteTarget(null);
|
|
13411
13648
|
};
|
|
13412
|
-
const content = /* @__PURE__ */
|
|
13413
|
-
/* @__PURE__ */
|
|
13414
|
-
/* @__PURE__ */
|
|
13415
|
-
/* @__PURE__ */
|
|
13649
|
+
const content = /* @__PURE__ */ jsxs88("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
|
|
13650
|
+
/* @__PURE__ */ jsxs88("div", { className: "fd-fb-head", children: [
|
|
13651
|
+
/* @__PURE__ */ jsxs88("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
|
|
13652
|
+
/* @__PURE__ */ jsx97(
|
|
13416
13653
|
BreadcrumbCrumb,
|
|
13417
13654
|
{
|
|
13418
13655
|
label: "Home",
|
|
@@ -13422,7 +13659,7 @@ function FileBrowser({
|
|
|
13422
13659
|
onDropPayload: (p) => moveIntoFolder(p, null)
|
|
13423
13660
|
}
|
|
13424
13661
|
),
|
|
13425
|
-
crumbFolders.map((f, i) => /* @__PURE__ */
|
|
13662
|
+
crumbFolders.map((f, i) => /* @__PURE__ */ jsx97(
|
|
13426
13663
|
BreadcrumbCrumb,
|
|
13427
13664
|
{
|
|
13428
13665
|
label: f.name,
|
|
@@ -13434,11 +13671,11 @@ function FileBrowser({
|
|
|
13434
13671
|
f.id
|
|
13435
13672
|
))
|
|
13436
13673
|
] }),
|
|
13437
|
-
/* @__PURE__ */
|
|
13438
|
-
canCreateFolder ? /* @__PURE__ */
|
|
13439
|
-
canUpload ? /* @__PURE__ */
|
|
13440
|
-
/* @__PURE__ */
|
|
13441
|
-
/* @__PURE__ */
|
|
13674
|
+
/* @__PURE__ */ jsxs88("span", { className: "fd-fb-actions", children: [
|
|
13675
|
+
canCreateFolder ? /* @__PURE__ */ jsx97(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
|
|
13676
|
+
canUpload ? /* @__PURE__ */ jsxs88(Fragment28, { children: [
|
|
13677
|
+
/* @__PURE__ */ jsx97(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
|
|
13678
|
+
/* @__PURE__ */ jsx97(
|
|
13442
13679
|
"input",
|
|
13443
13680
|
{
|
|
13444
13681
|
ref: uploadInputRef,
|
|
@@ -13456,9 +13693,9 @@ function FileBrowser({
|
|
|
13456
13693
|
] }) : null
|
|
13457
13694
|
] })
|
|
13458
13695
|
] }),
|
|
13459
|
-
/* @__PURE__ */
|
|
13460
|
-
/* @__PURE__ */
|
|
13461
|
-
/* @__PURE__ */
|
|
13696
|
+
/* @__PURE__ */ jsxs88("div", { className: "fd-fb-body", children: [
|
|
13697
|
+
/* @__PURE__ */ jsxs88("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
|
|
13698
|
+
/* @__PURE__ */ jsx97(
|
|
13462
13699
|
RowShell,
|
|
13463
13700
|
{
|
|
13464
13701
|
icon: "house-simple",
|
|
@@ -13469,7 +13706,7 @@ function FileBrowser({
|
|
|
13469
13706
|
className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
|
|
13470
13707
|
}
|
|
13471
13708
|
),
|
|
13472
|
-
childrenOf(folders, null).map((f) => /* @__PURE__ */
|
|
13709
|
+
childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx97(
|
|
13473
13710
|
TreeNode,
|
|
13474
13711
|
{
|
|
13475
13712
|
folder: f,
|
|
@@ -13483,18 +13720,18 @@ function FileBrowser({
|
|
|
13483
13720
|
f.id
|
|
13484
13721
|
))
|
|
13485
13722
|
] }),
|
|
13486
|
-
/* @__PURE__ */
|
|
13723
|
+
/* @__PURE__ */ jsx97("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx97(
|
|
13487
13724
|
LoadingRegion,
|
|
13488
13725
|
{
|
|
13489
13726
|
state: loading ? "loading" : "ready",
|
|
13490
13727
|
label: "Loading folder contents",
|
|
13491
|
-
skeleton: /* @__PURE__ */
|
|
13492
|
-
/* @__PURE__ */
|
|
13493
|
-
/* @__PURE__ */
|
|
13494
|
-
/* @__PURE__ */
|
|
13728
|
+
skeleton: /* @__PURE__ */ jsxs88("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
|
|
13729
|
+
/* @__PURE__ */ jsx97(Skeleton, { h: 44, radius: "10px" }),
|
|
13730
|
+
/* @__PURE__ */ jsx97(Skeleton, { h: 44, radius: "10px" }),
|
|
13731
|
+
/* @__PURE__ */ jsx97(Skeleton, { h: 44, radius: "10px" })
|
|
13495
13732
|
] }),
|
|
13496
|
-
children: isEmpty ? /* @__PURE__ */
|
|
13497
|
-
subfolders.map((f) => /* @__PURE__ */
|
|
13733
|
+
children: isEmpty ? /* @__PURE__ */ jsx97(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__ */ jsxs88("div", { className: "fd-fb-list", children: [
|
|
13734
|
+
subfolders.map((f) => /* @__PURE__ */ jsx97(
|
|
13498
13735
|
RowShell,
|
|
13499
13736
|
{
|
|
13500
13737
|
icon: "folder-simple",
|
|
@@ -13503,9 +13740,9 @@ function FileBrowser({
|
|
|
13503
13740
|
draggableId: canMove ? { kind: "folder", id: f.id } : void 0,
|
|
13504
13741
|
isDropTarget: canMove,
|
|
13505
13742
|
onDropPayload: (p) => moveIntoFolder(p, f.id),
|
|
13506
|
-
actions: /* @__PURE__ */
|
|
13507
|
-
canRenameFolder ? /* @__PURE__ */
|
|
13508
|
-
canMove ? /* @__PURE__ */
|
|
13743
|
+
actions: /* @__PURE__ */ jsxs88(Fragment28, { children: [
|
|
13744
|
+
canRenameFolder ? /* @__PURE__ */ jsx97(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
|
|
13745
|
+
canMove ? /* @__PURE__ */ jsx97(
|
|
13509
13746
|
FolderPickerMenu,
|
|
13510
13747
|
{
|
|
13511
13748
|
label: "Move " + f.name,
|
|
@@ -13513,12 +13750,12 @@ function FileBrowser({
|
|
|
13513
13750
|
onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
|
|
13514
13751
|
}
|
|
13515
13752
|
) : null,
|
|
13516
|
-
canDeleteFolder ? /* @__PURE__ */
|
|
13753
|
+
canDeleteFolder ? /* @__PURE__ */ jsx97(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
|
|
13517
13754
|
] })
|
|
13518
13755
|
},
|
|
13519
13756
|
f.id
|
|
13520
13757
|
)),
|
|
13521
|
-
currentFiles.map((file) => /* @__PURE__ */
|
|
13758
|
+
currentFiles.map((file) => /* @__PURE__ */ jsx97(
|
|
13522
13759
|
RowShell,
|
|
13523
13760
|
{
|
|
13524
13761
|
icon: iconForMime(file.mime, file.name),
|
|
@@ -13526,8 +13763,8 @@ function FileBrowser({
|
|
|
13526
13763
|
meta: file.size ? formatBytes(file.size) : void 0,
|
|
13527
13764
|
onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
|
|
13528
13765
|
draggableId: canMove ? { kind: "file", id: file.id } : void 0,
|
|
13529
|
-
actions: /* @__PURE__ */
|
|
13530
|
-
canMove ? /* @__PURE__ */
|
|
13766
|
+
actions: /* @__PURE__ */ jsxs88(Fragment28, { children: [
|
|
13767
|
+
canMove ? /* @__PURE__ */ jsx97(
|
|
13531
13768
|
FolderPickerMenu,
|
|
13532
13769
|
{
|
|
13533
13770
|
label: "Move " + file.name,
|
|
@@ -13535,7 +13772,7 @@ function FileBrowser({
|
|
|
13535
13772
|
onPick: (target) => onMoveFile && onMoveFile(file.id, target)
|
|
13536
13773
|
}
|
|
13537
13774
|
) : null,
|
|
13538
|
-
canRemoveFile ? /* @__PURE__ */
|
|
13775
|
+
canRemoveFile ? /* @__PURE__ */ jsx97(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
|
|
13539
13776
|
] })
|
|
13540
13777
|
},
|
|
13541
13778
|
file.id
|
|
@@ -13544,10 +13781,10 @@ function FileBrowser({
|
|
|
13544
13781
|
}
|
|
13545
13782
|
) })
|
|
13546
13783
|
] }),
|
|
13547
|
-
/* @__PURE__ */
|
|
13548
|
-
/* @__PURE__ */
|
|
13549
|
-
/* @__PURE__ */
|
|
13550
|
-
] }), children: /* @__PURE__ */
|
|
13784
|
+
/* @__PURE__ */ jsx97(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs88(Fragment28, { children: [
|
|
13785
|
+
/* @__PURE__ */ jsx97(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
|
|
13786
|
+
/* @__PURE__ */ jsx97(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
|
|
13787
|
+
] }), children: /* @__PURE__ */ jsx97(
|
|
13551
13788
|
"input",
|
|
13552
13789
|
{
|
|
13553
13790
|
className: "fd-fb-input",
|
|
@@ -13561,10 +13798,10 @@ function FileBrowser({
|
|
|
13561
13798
|
autoFocus: true
|
|
13562
13799
|
}
|
|
13563
13800
|
) }),
|
|
13564
|
-
/* @__PURE__ */
|
|
13565
|
-
/* @__PURE__ */
|
|
13566
|
-
/* @__PURE__ */
|
|
13567
|
-
] }), children: /* @__PURE__ */
|
|
13801
|
+
/* @__PURE__ */ jsx97(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs88(Fragment28, { children: [
|
|
13802
|
+
/* @__PURE__ */ jsx97(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
|
|
13803
|
+
/* @__PURE__ */ jsx97(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
|
|
13804
|
+
] }), children: /* @__PURE__ */ jsx97(
|
|
13568
13805
|
"input",
|
|
13569
13806
|
{
|
|
13570
13807
|
className: "fd-fb-input",
|
|
@@ -13578,22 +13815,22 @@ function FileBrowser({
|
|
|
13578
13815
|
autoFocus: true
|
|
13579
13816
|
}
|
|
13580
13817
|
) }),
|
|
13581
|
-
/* @__PURE__ */
|
|
13818
|
+
/* @__PURE__ */ jsx97(
|
|
13582
13819
|
Modal,
|
|
13583
13820
|
{
|
|
13584
13821
|
open: deleteTarget != null,
|
|
13585
13822
|
title: deleteTarget ? "Delete \u201C" + deleteTarget.name + "\u201D?" : "Delete folder?",
|
|
13586
13823
|
description: "This can't be undone. The folder must be empty.",
|
|
13587
13824
|
onClose: () => setDeleteTarget(null),
|
|
13588
|
-
footer: /* @__PURE__ */
|
|
13589
|
-
/* @__PURE__ */
|
|
13590
|
-
/* @__PURE__ */
|
|
13825
|
+
footer: /* @__PURE__ */ jsxs88(Fragment28, { children: [
|
|
13826
|
+
/* @__PURE__ */ jsx97(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
|
|
13827
|
+
/* @__PURE__ */ jsx97(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
|
|
13591
13828
|
] })
|
|
13592
13829
|
}
|
|
13593
13830
|
)
|
|
13594
13831
|
] });
|
|
13595
13832
|
if (!canUpload) return content;
|
|
13596
|
-
return /* @__PURE__ */
|
|
13833
|
+
return /* @__PURE__ */ jsx97(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
|
|
13597
13834
|
}
|
|
13598
13835
|
function BreadcrumbCrumb({
|
|
13599
13836
|
label,
|
|
@@ -13602,8 +13839,8 @@ function BreadcrumbCrumb({
|
|
|
13602
13839
|
isDropTarget,
|
|
13603
13840
|
onDropPayload
|
|
13604
13841
|
}) {
|
|
13605
|
-
const [over, setOver] =
|
|
13606
|
-
const dragCounter =
|
|
13842
|
+
const [over, setOver] = React66.useState(false);
|
|
13843
|
+
const dragCounter = React66.useRef(0);
|
|
13607
13844
|
const dropHandlers = isDropTarget ? {
|
|
13608
13845
|
onDragEnter: (e) => {
|
|
13609
13846
|
if (!hasInternalPayload(e)) return;
|
|
@@ -13628,11 +13865,11 @@ function BreadcrumbCrumb({
|
|
|
13628
13865
|
if (payload && onDropPayload) onDropPayload(payload);
|
|
13629
13866
|
}
|
|
13630
13867
|
} : {};
|
|
13631
|
-
return /* @__PURE__ */
|
|
13868
|
+
return /* @__PURE__ */ jsx97("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx97("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx97("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
|
|
13632
13869
|
}
|
|
13633
13870
|
|
|
13634
13871
|
// src/kits/query.ts
|
|
13635
|
-
import * as
|
|
13872
|
+
import * as React67 from "react";
|
|
13636
13873
|
var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
|
|
13637
13874
|
var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
|
|
13638
13875
|
var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
|
|
@@ -13687,22 +13924,22 @@ function compare(a, b, dir) {
|
|
|
13687
13924
|
var API = null;
|
|
13688
13925
|
var PREFS = null;
|
|
13689
13926
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
13690
|
-
const [query, setQuery] =
|
|
13927
|
+
const [query, setQuery] = React67.useState(() => {
|
|
13691
13928
|
const store = PREFS || window.PlannerPrefs;
|
|
13692
13929
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
13693
13930
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
13694
13931
|
});
|
|
13695
|
-
const savePref =
|
|
13932
|
+
const savePref = React67.useCallback((patch2) => {
|
|
13696
13933
|
const store = PREFS || window.PlannerPrefs;
|
|
13697
13934
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
13698
13935
|
}, [prefsKey]);
|
|
13699
|
-
const [res, setRes] =
|
|
13700
|
-
const [loading, setLoading] =
|
|
13701
|
-
const seq2 =
|
|
13936
|
+
const [res, setRes] = React67.useState(null);
|
|
13937
|
+
const [loading, setLoading] = React67.useState(true);
|
|
13938
|
+
const seq2 = React67.useRef(0);
|
|
13702
13939
|
const depKey = (deps || []).join("|");
|
|
13703
13940
|
const paramKey = JSON.stringify(params || {});
|
|
13704
13941
|
const queryKey = JSON.stringify(query);
|
|
13705
|
-
|
|
13942
|
+
React67.useEffect(() => {
|
|
13706
13943
|
const id = ++seq2.current;
|
|
13707
13944
|
setLoading(true);
|
|
13708
13945
|
const t = setTimeout(() => {
|
|
@@ -14021,12 +14258,12 @@ function createVersionStore(initialState, options) {
|
|
|
14021
14258
|
}
|
|
14022
14259
|
|
|
14023
14260
|
// src/kits/documentTitle.ts
|
|
14024
|
-
import * as
|
|
14261
|
+
import * as React68 from "react";
|
|
14025
14262
|
function formatDocumentTitle(routeTitle, appName) {
|
|
14026
14263
|
return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
|
|
14027
14264
|
}
|
|
14028
14265
|
function useDocumentTitle(routeTitle, appName) {
|
|
14029
|
-
|
|
14266
|
+
React68.useEffect(() => {
|
|
14030
14267
|
if (typeof document === "undefined") return;
|
|
14031
14268
|
document.title = formatDocumentTitle(routeTitle, appName);
|
|
14032
14269
|
}, [routeTitle, appName]);
|
|
@@ -14068,6 +14305,7 @@ export {
|
|
|
14068
14305
|
Clamp,
|
|
14069
14306
|
ClockFace,
|
|
14070
14307
|
CodeBlock,
|
|
14308
|
+
CodeEditor,
|
|
14071
14309
|
Collapsible,
|
|
14072
14310
|
ComingSoon,
|
|
14073
14311
|
CsiBadge,
|