@flytedan/flytebot-design-system 0.48.0 → 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 +1205 -951
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +80 -12
- package/dist/index.d.ts +80 -12
- package/dist/index.js +1215 -962
- package/dist/index.js.map +1 -1
- package/package.json +7 -1
- package/styles/components.css +110 -0
package/dist/index.cjs
CHANGED
|
@@ -66,6 +66,7 @@ __export(index_exports, {
|
|
|
66
66
|
Clamp: () => Clamp,
|
|
67
67
|
ClockFace: () => ClockFace,
|
|
68
68
|
CodeBlock: () => CodeBlock,
|
|
69
|
+
CodeEditor: () => CodeEditor,
|
|
69
70
|
Collapsible: () => Collapsible,
|
|
70
71
|
ComingSoon: () => ComingSoon,
|
|
71
72
|
CsiBadge: () => CsiBadge,
|
|
@@ -1095,28 +1096,28 @@ function Card({
|
|
|
1095
1096
|
interactive ? "fd-card-interactive" : "",
|
|
1096
1097
|
className
|
|
1097
1098
|
].filter(Boolean).join(" ");
|
|
1098
|
-
const
|
|
1099
|
+
const titleOnlyHead = title ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "fd-card-head", children: [
|
|
1099
1100
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "fd-card-head-title", title: truncationTitle(title), children: title }),
|
|
1100
|
-
action
|
|
1101
|
+
!interactive && action
|
|
1101
1102
|
] }) : null;
|
|
1102
1103
|
const body = padded ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "fd-card-body", children }) : children;
|
|
1103
1104
|
const foot = footer ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "fd-card-foot", children: footer }) : null;
|
|
1104
|
-
if (
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
body
|
|
1108
|
-
|
|
1105
|
+
if (interactive) {
|
|
1106
|
+
const inner = href != null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("a", { href, onClick, className: cls, role, tabIndex, ...rest, children: [
|
|
1107
|
+
titleOnlyHead,
|
|
1108
|
+
body
|
|
1109
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("button", { type: "button", onClick, className: cls, role, tabIndex, ...rest, children: [
|
|
1110
|
+
titleOnlyHead,
|
|
1111
|
+
body
|
|
1109
1112
|
] });
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
head,
|
|
1114
|
-
body,
|
|
1113
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "fd-card-shell", children: [
|
|
1114
|
+
inner,
|
|
1115
|
+
action ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "fd-card-shell-action", children: action }) : null,
|
|
1115
1116
|
foot
|
|
1116
1117
|
] });
|
|
1117
1118
|
}
|
|
1118
1119
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cls, role, tabIndex, ...rest, children: [
|
|
1119
|
-
|
|
1120
|
+
titleOnlyHead,
|
|
1120
1121
|
body,
|
|
1121
1122
|
foot
|
|
1122
1123
|
] });
|
|
@@ -1290,8 +1291,21 @@ function ScreenHead({ kicker, title, lede, actions }) {
|
|
|
1290
1291
|
// src/components/layout/CardGrid.tsx
|
|
1291
1292
|
var React8 = __toESM(require("react"), 1);
|
|
1292
1293
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1294
|
+
function flattenFragments(children) {
|
|
1295
|
+
const out = [];
|
|
1296
|
+
React8.Children.forEach(children, (child) => {
|
|
1297
|
+
if (child === null || child === void 0 || typeof child === "boolean") return;
|
|
1298
|
+
if (React8.isValidElement(child) && child.type === React8.Fragment) {
|
|
1299
|
+
const fragmentChildren = child.props.children;
|
|
1300
|
+
out.push(...flattenFragments(fragmentChildren));
|
|
1301
|
+
return;
|
|
1302
|
+
}
|
|
1303
|
+
out.push(child);
|
|
1304
|
+
});
|
|
1305
|
+
return out;
|
|
1306
|
+
}
|
|
1293
1307
|
function CardGrid({ children, minCardWidth = 280, gap = "lg", className = "", style }) {
|
|
1294
|
-
const items =
|
|
1308
|
+
const items = flattenFragments(children);
|
|
1295
1309
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1296
1310
|
"div",
|
|
1297
1311
|
{
|
|
@@ -1299,10 +1313,12 @@ function CardGrid({ children, minCardWidth = 280, gap = "lg", className = "", st
|
|
|
1299
1313
|
className: ["fd-card-grid", "fd-gap-" + gap, className].filter(Boolean).join(" "),
|
|
1300
1314
|
style: { ["--card-grid-min"]: minCardWidth + "px", ...style },
|
|
1301
1315
|
children: items.map((child, i) => {
|
|
1302
|
-
if (
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1316
|
+
if (React8.isValidElement(child)) {
|
|
1317
|
+
const existingRole = child.props.role;
|
|
1318
|
+
if (existingRole) return child;
|
|
1319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { role: "listitem", children: child }, child.key ?? i);
|
|
1320
|
+
}
|
|
1321
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { role: "listitem", children: child }, i);
|
|
1306
1322
|
})
|
|
1307
1323
|
}
|
|
1308
1324
|
);
|
|
@@ -4870,7 +4886,7 @@ function CodeBlock({
|
|
|
4870
4886
|
code = "",
|
|
4871
4887
|
language,
|
|
4872
4888
|
filename,
|
|
4873
|
-
lineNumbers = false,
|
|
4889
|
+
lineNumbers: lineNumbers2 = false,
|
|
4874
4890
|
wrap: wrapDefault = false,
|
|
4875
4891
|
collapseAfter = 26,
|
|
4876
4892
|
copyable = true,
|
|
@@ -4897,7 +4913,7 @@ function CodeBlock({
|
|
|
4897
4913
|
] }) : null
|
|
4898
4914
|
] }),
|
|
4899
4915
|
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-code-body", children: [
|
|
4900
|
-
|
|
4916
|
+
lineNumbers2 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("pre", { className: "fd-code-gutter", "aria-hidden": "true", children: shown.split("\n").map((_, i) => i + 1 + "\n").join("") }) : null,
|
|
4901
4917
|
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("pre", { className: "fd-code-pre", tabIndex: 0, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("code", { children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Highlighted, { code: shown, lang: language }) }) })
|
|
4902
4918
|
] }),
|
|
4903
4919
|
foldable ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("button", { type: "button", className: "fd-code-fold", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
@@ -7480,17 +7496,254 @@ var MarkdownEditor = React42.forwardRef(function MarkdownEditor2({
|
|
|
7480
7496
|
] });
|
|
7481
7497
|
});
|
|
7482
7498
|
|
|
7499
|
+
// src/components/forms/CodeEditor.tsx
|
|
7500
|
+
var React43 = __toESM(require("react"), 1);
|
|
7501
|
+
var import_view = require("@codemirror/view");
|
|
7502
|
+
var import_state = require("@codemirror/state");
|
|
7503
|
+
var import_commands = require("@codemirror/commands");
|
|
7504
|
+
var import_lang_sql = require("@codemirror/lang-sql");
|
|
7505
|
+
var import_language = require("@codemirror/language");
|
|
7506
|
+
var import_highlight = require("@lezer/highlight");
|
|
7507
|
+
var import_jsx_runtime73 = require("react/jsx-runtime");
|
|
7508
|
+
function clampOffset(state, line, column) {
|
|
7509
|
+
const total = state.doc.lines;
|
|
7510
|
+
const ln = state.doc.line(Math.min(Math.max(1, line), total));
|
|
7511
|
+
const col = Math.max(0, (column || 1) - 1);
|
|
7512
|
+
return Math.min(ln.from + col, ln.to);
|
|
7513
|
+
}
|
|
7514
|
+
function toCmDiagnostics(state, diags) {
|
|
7515
|
+
return diags.map((d) => {
|
|
7516
|
+
const from = clampOffset(state, d.line, d.column ?? 1);
|
|
7517
|
+
const endLine = d.endLine ?? d.line;
|
|
7518
|
+
const endColumn = d.endColumn ?? state.doc.line(Math.min(Math.max(1, endLine), state.doc.lines)).length + 1;
|
|
7519
|
+
let to = clampOffset(state, endLine, endColumn);
|
|
7520
|
+
if (to <= from) to = Math.min(from + 1, state.doc.length);
|
|
7521
|
+
return { from, to, severity: d.severity || "error", message: d.message, source: void 0 };
|
|
7522
|
+
});
|
|
7523
|
+
}
|
|
7524
|
+
var setDiagnosticsEffect = import_state.StateEffect.define();
|
|
7525
|
+
var diagnosticsField = import_state.StateField.define({
|
|
7526
|
+
create: () => [],
|
|
7527
|
+
update(value, tr) {
|
|
7528
|
+
for (const e of tr.effects) if (e.is(setDiagnosticsEffect)) return e.value;
|
|
7529
|
+
if (!tr.docChanged) return value;
|
|
7530
|
+
return value.map((d) => ({ ...d, from: tr.changes.mapPos(d.from), to: tr.changes.mapPos(d.to) }));
|
|
7531
|
+
}
|
|
7532
|
+
});
|
|
7533
|
+
var tokenHighlight = import_language.HighlightStyle.define([
|
|
7534
|
+
{ tag: import_highlight.tags.keyword, class: "tok-kw" },
|
|
7535
|
+
{ tag: import_highlight.tags.string, class: "tok-str" },
|
|
7536
|
+
{ tag: [import_highlight.tags.number, import_highlight.tags.bool], class: "tok-num" },
|
|
7537
|
+
{ tag: import_highlight.tags.comment, class: "tok-com" },
|
|
7538
|
+
{ tag: [import_highlight.tags.function(import_highlight.tags.variableName), import_highlight.tags.function(import_highlight.tags.propertyName)], class: "tok-fn" },
|
|
7539
|
+
{ tag: import_highlight.tags.typeName, class: "tok-type" },
|
|
7540
|
+
{ tag: import_highlight.tags.propertyName, class: "tok-prop" },
|
|
7541
|
+
{ tag: import_highlight.tags.null, class: "tok-lit" },
|
|
7542
|
+
{ tag: [import_highlight.tags.punctuation, import_highlight.tags.paren, import_highlight.tags.bracket], class: "tok-pun" },
|
|
7543
|
+
{ tag: import_highlight.tags.operator, class: "tok-op" }
|
|
7544
|
+
]);
|
|
7545
|
+
var editorTheme = import_view.EditorView.theme({
|
|
7546
|
+
"&": {
|
|
7547
|
+
fontFamily: "var(--font-mono)",
|
|
7548
|
+
fontSize: "12.5px",
|
|
7549
|
+
color: "var(--text)",
|
|
7550
|
+
backgroundColor: "transparent",
|
|
7551
|
+
height: "100%"
|
|
7552
|
+
},
|
|
7553
|
+
".cm-content": { padding: "10px 12px", caretColor: "var(--text)" },
|
|
7554
|
+
".cm-scroller": { fontFamily: "var(--font-mono)", lineHeight: "1.62" },
|
|
7555
|
+
".cm-gutters": {
|
|
7556
|
+
backgroundColor: "transparent",
|
|
7557
|
+
color: "var(--text-disabled)",
|
|
7558
|
+
border: "0",
|
|
7559
|
+
borderRight: "1px solid var(--chat-code-border)"
|
|
7560
|
+
},
|
|
7561
|
+
".cm-lineNumbers .cm-gutterElement": { padding: "0 8px 0 12px" },
|
|
7562
|
+
".cm-activeLine": { backgroundColor: "var(--surface-2)" },
|
|
7563
|
+
".cm-activeLineGutter": { backgroundColor: "var(--surface-2)", color: "var(--text-2)" },
|
|
7564
|
+
"&.cm-focused": { outline: "none" },
|
|
7565
|
+
".cm-cursor": { borderLeftColor: "var(--text)" },
|
|
7566
|
+
".cm-selectionBackground, &.cm-focused .cm-selectionBackground": { backgroundColor: "var(--blue-100) !important" },
|
|
7567
|
+
".cm-placeholder": { color: "var(--text-disabled)" },
|
|
7568
|
+
".fd-cm-diag-error": { textDecoration: "underline wavy var(--danger-solid)", textUnderlineOffset: "3px" },
|
|
7569
|
+
".fd-cm-diag-warning": { textDecoration: "underline wavy var(--warn-solid)", textUnderlineOffset: "3px" },
|
|
7570
|
+
".fd-cm-diag-info": { textDecoration: "underline wavy var(--info-solid)", textUnderlineOffset: "3px" }
|
|
7571
|
+
}, { dark: false });
|
|
7572
|
+
function severityClass(sev) {
|
|
7573
|
+
return sev === "warning" ? "fd-cm-diag-warning" : sev === "info" ? "fd-cm-diag-info" : "fd-cm-diag-error";
|
|
7574
|
+
}
|
|
7575
|
+
function decorationsFromDiagnostics() {
|
|
7576
|
+
return import_view.EditorView.decorations.compute([diagnosticsField], (state) => {
|
|
7577
|
+
const diags = state.field(diagnosticsField);
|
|
7578
|
+
if (!diags.length) return import_view.Decoration.none;
|
|
7579
|
+
const marks = diags.filter((d) => d.from < d.to).sort((a, b) => a.from - b.from).map((d) => import_view.Decoration.mark({ class: severityClass(d.severity) }).range(d.from, d.to));
|
|
7580
|
+
return import_view.Decoration.set(marks, true);
|
|
7581
|
+
});
|
|
7582
|
+
}
|
|
7583
|
+
function CodeEditor({
|
|
7584
|
+
value,
|
|
7585
|
+
onChange,
|
|
7586
|
+
label,
|
|
7587
|
+
help,
|
|
7588
|
+
error,
|
|
7589
|
+
required = false,
|
|
7590
|
+
disabled = false,
|
|
7591
|
+
readOnly = false,
|
|
7592
|
+
placeholder: placeholderText = "",
|
|
7593
|
+
diagnostics = [],
|
|
7594
|
+
showEscapeHint = true,
|
|
7595
|
+
minHeight = 160,
|
|
7596
|
+
id,
|
|
7597
|
+
className = "",
|
|
7598
|
+
style,
|
|
7599
|
+
autoFocus = false
|
|
7600
|
+
}) {
|
|
7601
|
+
const fieldId = useFieldId(id);
|
|
7602
|
+
const descId = fieldId + "-desc";
|
|
7603
|
+
const liveId = fieldId + "-live";
|
|
7604
|
+
const hostRef = React43.useRef(null);
|
|
7605
|
+
const viewRef = React43.useRef(null);
|
|
7606
|
+
const valueRef = React43.useRef(value);
|
|
7607
|
+
const onChangeRef = React43.useRef(onChange);
|
|
7608
|
+
onChangeRef.current = onChange;
|
|
7609
|
+
const editableCompartment = React43.useRef(new import_state.Compartment()).current;
|
|
7610
|
+
const attributesCompartment = React43.useRef(new import_state.Compartment()).current;
|
|
7611
|
+
const errorRef = React43.useRef(error);
|
|
7612
|
+
errorRef.current = error;
|
|
7613
|
+
const diagnosticsCountRef = React43.useRef(diagnostics.length);
|
|
7614
|
+
diagnosticsCountRef.current = diagnostics.length;
|
|
7615
|
+
function contentAttributes() {
|
|
7616
|
+
return {
|
|
7617
|
+
id: fieldId,
|
|
7618
|
+
"aria-describedby": descId + " " + liveId,
|
|
7619
|
+
"aria-invalid": errorRef.current || diagnosticsCountRef.current ? "true" : "false",
|
|
7620
|
+
...label ? { "aria-label": label } : {}
|
|
7621
|
+
};
|
|
7622
|
+
}
|
|
7623
|
+
React43.useEffect(() => {
|
|
7624
|
+
const host = hostRef.current;
|
|
7625
|
+
if (!host) return;
|
|
7626
|
+
const updateListener = import_view.EditorView.updateListener.of((update) => {
|
|
7627
|
+
if (!update.docChanged) return;
|
|
7628
|
+
const next = update.state.doc.toString();
|
|
7629
|
+
valueRef.current = next;
|
|
7630
|
+
onChangeRef.current && onChangeRef.current(next);
|
|
7631
|
+
});
|
|
7632
|
+
const state = import_state.EditorState.create({
|
|
7633
|
+
doc: value,
|
|
7634
|
+
extensions: [
|
|
7635
|
+
(0, import_view.lineNumbers)(),
|
|
7636
|
+
(0, import_commands.history)(),
|
|
7637
|
+
(0, import_view.drawSelection)(),
|
|
7638
|
+
(0, import_language.indentOnInput)(),
|
|
7639
|
+
(0, import_language.bracketMatching)(),
|
|
7640
|
+
(0, import_lang_sql.sql)(),
|
|
7641
|
+
(0, import_language.syntaxHighlighting)(tokenHighlight),
|
|
7642
|
+
diagnosticsField,
|
|
7643
|
+
decorationsFromDiagnostics(),
|
|
7644
|
+
editorTheme,
|
|
7645
|
+
(0, import_view.placeholder)(placeholderText),
|
|
7646
|
+
import_view.keymap.of([
|
|
7647
|
+
{ key: "Tab", run: import_commands.indentMore, shift: import_commands.indentLess },
|
|
7648
|
+
...import_commands.defaultKeymap,
|
|
7649
|
+
...import_commands.historyKeymap
|
|
7650
|
+
]),
|
|
7651
|
+
editableCompartment.of(import_view.EditorView.editable.of(!disabled)),
|
|
7652
|
+
import_state.EditorState.readOnly.of(readOnly),
|
|
7653
|
+
updateListener,
|
|
7654
|
+
attributesCompartment.of(import_view.EditorView.contentAttributes.of(contentAttributes()))
|
|
7655
|
+
]
|
|
7656
|
+
});
|
|
7657
|
+
const view = new import_view.EditorView({ state, parent: host });
|
|
7658
|
+
viewRef.current = view;
|
|
7659
|
+
if (autoFocus) view.focus();
|
|
7660
|
+
return () => {
|
|
7661
|
+
view.destroy();
|
|
7662
|
+
viewRef.current = null;
|
|
7663
|
+
};
|
|
7664
|
+
}, []);
|
|
7665
|
+
React43.useEffect(() => {
|
|
7666
|
+
const view = viewRef.current;
|
|
7667
|
+
if (!view) return;
|
|
7668
|
+
const current2 = view.state.doc.toString();
|
|
7669
|
+
if (current2 !== value) {
|
|
7670
|
+
view.dispatch({ changes: { from: 0, to: current2.length, insert: value } });
|
|
7671
|
+
}
|
|
7672
|
+
valueRef.current = value;
|
|
7673
|
+
}, [value]);
|
|
7674
|
+
React43.useEffect(() => {
|
|
7675
|
+
const view = viewRef.current;
|
|
7676
|
+
if (!view) return;
|
|
7677
|
+
view.dispatch({ effects: editableCompartment.reconfigure(import_view.EditorView.editable.of(!disabled)) });
|
|
7678
|
+
}, [disabled, editableCompartment]);
|
|
7679
|
+
React43.useEffect(() => {
|
|
7680
|
+
const view = viewRef.current;
|
|
7681
|
+
if (!view) return;
|
|
7682
|
+
view.dispatch({
|
|
7683
|
+
effects: [
|
|
7684
|
+
setDiagnosticsEffect.of(toCmDiagnostics(view.state, diagnostics)),
|
|
7685
|
+
attributesCompartment.reconfigure(import_view.EditorView.contentAttributes.of(contentAttributes()))
|
|
7686
|
+
]
|
|
7687
|
+
});
|
|
7688
|
+
}, [diagnostics, error]);
|
|
7689
|
+
const box = ["fd-input", "fd-code-editor", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
7690
|
+
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("; ") : "";
|
|
7691
|
+
return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
|
|
7692
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
|
|
7693
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
7694
|
+
"div",
|
|
7695
|
+
{
|
|
7696
|
+
className: box,
|
|
7697
|
+
style: { minHeight },
|
|
7698
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
7699
|
+
"div",
|
|
7700
|
+
{
|
|
7701
|
+
ref: hostRef,
|
|
7702
|
+
className: "fd-code-editor-host",
|
|
7703
|
+
style: { minHeight }
|
|
7704
|
+
}
|
|
7705
|
+
)
|
|
7706
|
+
}
|
|
7707
|
+
),
|
|
7708
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { id: descId, className: "fd-sr", children: [
|
|
7709
|
+
help ? help + ". " : "",
|
|
7710
|
+
showEscapeHint ? "Tab indents. Press Escape, then Tab, to move focus out of the editor." : ""
|
|
7711
|
+
] }),
|
|
7712
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { id: liveId, className: "fd-sr", role: "status", "aria-live": "polite", children: announce }),
|
|
7713
|
+
diagnostics.length ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("ul", { className: "fd-code-editor-diagnostics", children: diagnostics.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("li", { className: "fd-code-editor-diag is-" + (d.severity || "error"), children: [
|
|
7714
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
7715
|
+
"i",
|
|
7716
|
+
{
|
|
7717
|
+
className: "ph ph-" + (d.severity === "warning" ? "warning" : d.severity === "info" ? "info" : "warning-circle"),
|
|
7718
|
+
"aria-hidden": "true"
|
|
7719
|
+
}
|
|
7720
|
+
),
|
|
7721
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fd-code-editor-diag-loc", children: [
|
|
7722
|
+
"Line ",
|
|
7723
|
+
d.line,
|
|
7724
|
+
d.column ? ":" + d.column : ""
|
|
7725
|
+
] }),
|
|
7726
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { children: d.message })
|
|
7727
|
+
] }, i)) }) : null,
|
|
7728
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fd-field-error", children: [
|
|
7729
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
7730
|
+
error
|
|
7731
|
+
] }) : !diagnostics.length && help ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-field-help", children: help }) : null,
|
|
7732
|
+
showEscapeHint ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-field-help fd-code-editor-hint", children: "Tab indents. Escape, then Tab, moves focus out." }) : null
|
|
7733
|
+
] });
|
|
7734
|
+
}
|
|
7735
|
+
|
|
7483
7736
|
// src/components/platform/AccountMenu.tsx
|
|
7484
|
-
var
|
|
7737
|
+
var React45 = __toESM(require("react"), 1);
|
|
7485
7738
|
|
|
7486
7739
|
// src/kits/sessionContext.tsx
|
|
7487
|
-
var
|
|
7488
|
-
var SessionContext =
|
|
7740
|
+
var React44 = __toESM(require("react"), 1);
|
|
7741
|
+
var SessionContext = React44.createContext(null);
|
|
7489
7742
|
function SessionProvider({ value, children }) {
|
|
7490
|
-
return
|
|
7743
|
+
return React44.createElement(SessionContext.Provider, { value }, children);
|
|
7491
7744
|
}
|
|
7492
7745
|
function useSessionContext() {
|
|
7493
|
-
const ctx =
|
|
7746
|
+
const ctx = React44.useContext(SessionContext);
|
|
7494
7747
|
if (!ctx) {
|
|
7495
7748
|
throw new Error(
|
|
7496
7749
|
"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."
|
|
@@ -7500,11 +7753,11 @@ function useSessionContext() {
|
|
|
7500
7753
|
}
|
|
7501
7754
|
|
|
7502
7755
|
// src/components/platform/AccountMenu.tsx
|
|
7503
|
-
var
|
|
7756
|
+
var import_jsx_runtime74 = require("react/jsx-runtime");
|
|
7504
7757
|
var DEFAULT_LINKS = [];
|
|
7505
7758
|
var DEFAULT_GROUPS = [];
|
|
7506
7759
|
function Item({ item, onPick }) {
|
|
7507
|
-
return /* @__PURE__ */ (0,
|
|
7760
|
+
return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
|
|
7508
7761
|
"button",
|
|
7509
7762
|
{
|
|
7510
7763
|
type: "button",
|
|
@@ -7512,9 +7765,9 @@ function Item({ item, onPick }) {
|
|
|
7512
7765
|
className: "fd-acct-item",
|
|
7513
7766
|
onClick: () => onPick(item),
|
|
7514
7767
|
children: [
|
|
7515
|
-
item.icon ? /* @__PURE__ */ (0,
|
|
7516
|
-
/* @__PURE__ */ (0,
|
|
7517
|
-
item.badge ? /* @__PURE__ */ (0,
|
|
7768
|
+
item.icon ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
|
|
7769
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { style: { flex: 1 }, children: item.label }),
|
|
7770
|
+
item.badge ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Badge, { tone: "neutral", children: item.badge }) : null
|
|
7518
7771
|
]
|
|
7519
7772
|
}
|
|
7520
7773
|
);
|
|
@@ -7530,11 +7783,11 @@ function AccountMenu({
|
|
|
7530
7783
|
...rest
|
|
7531
7784
|
}) {
|
|
7532
7785
|
const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
|
|
7533
|
-
const [open2, setOpen] =
|
|
7534
|
-
const [switching, setSwitching] =
|
|
7535
|
-
const [signingOut, setSigningOut] =
|
|
7536
|
-
const [signOutError, setSignOutError] =
|
|
7537
|
-
const ref =
|
|
7786
|
+
const [open2, setOpen] = React45.useState(false);
|
|
7787
|
+
const [switching, setSwitching] = React45.useState(false);
|
|
7788
|
+
const [signingOut, setSigningOut] = React45.useState(false);
|
|
7789
|
+
const [signOutError, setSignOutError] = React45.useState(null);
|
|
7790
|
+
const ref = React45.useRef(null);
|
|
7538
7791
|
const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
|
|
7539
7792
|
const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || !pending && can2(l.perm)) })).filter((g) => g.links.length);
|
|
7540
7793
|
const closeMenu = () => {
|
|
@@ -7562,8 +7815,8 @@ function AccountMenu({
|
|
|
7562
7815
|
}
|
|
7563
7816
|
};
|
|
7564
7817
|
const showSwitcher = allowUserSwitch && !!demo;
|
|
7565
|
-
return /* @__PURE__ */ (0,
|
|
7566
|
-
/* @__PURE__ */ (0,
|
|
7818
|
+
return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(import_jsx_runtime74.Fragment, { children: [
|
|
7819
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
|
|
7567
7820
|
"button",
|
|
7568
7821
|
{
|
|
7569
7822
|
type: "button",
|
|
@@ -7575,12 +7828,12 @@ function AccountMenu({
|
|
|
7575
7828
|
onClick: () => open2 ? closeMenu() : setOpen(true),
|
|
7576
7829
|
...rest,
|
|
7577
7830
|
children: [
|
|
7578
|
-
/* @__PURE__ */ (0,
|
|
7579
|
-
/* @__PURE__ */ (0,
|
|
7831
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Avatar, { name: user.name, size: "sm" }),
|
|
7832
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
|
|
7580
7833
|
]
|
|
7581
7834
|
}
|
|
7582
7835
|
),
|
|
7583
|
-
/* @__PURE__ */ (0,
|
|
7836
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
|
|
7584
7837
|
Popover,
|
|
7585
7838
|
{
|
|
7586
7839
|
open: open2,
|
|
@@ -7588,27 +7841,27 @@ function AccountMenu({
|
|
|
7588
7841
|
onClose: closeMenu,
|
|
7589
7842
|
placement: "bottom-end",
|
|
7590
7843
|
width: 272,
|
|
7591
|
-
children: /* @__PURE__ */ (0,
|
|
7592
|
-
/* @__PURE__ */ (0,
|
|
7593
|
-
/* @__PURE__ */ (0,
|
|
7594
|
-
/* @__PURE__ */ (0,
|
|
7595
|
-
/* @__PURE__ */ (0,
|
|
7596
|
-
/* @__PURE__ */ (0,
|
|
7844
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
|
|
7845
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
7846
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Avatar, { name: user.name }),
|
|
7847
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
|
|
7848
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
|
|
7849
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
|
|
7597
7850
|
] })
|
|
7598
7851
|
] }),
|
|
7599
|
-
showRoles && roles.length ? /* @__PURE__ */ (0,
|
|
7600
|
-
visibleLinks.length ? /* @__PURE__ */ (0,
|
|
7601
|
-
visibleGroups.map((g) => /* @__PURE__ */ (0,
|
|
7602
|
-
/* @__PURE__ */ (0,
|
|
7603
|
-
g.links.map((l) => /* @__PURE__ */ (0,
|
|
7852
|
+
showRoles && roles.length ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
|
|
7853
|
+
visibleLinks.length ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Item, { item: l, onPick: pick }, l.id)) }) : null,
|
|
7854
|
+
visibleGroups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
7855
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
|
|
7856
|
+
g.links.map((l) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Item, { item: l, onPick: pick }, l.id))
|
|
7604
7857
|
] }, g.label)),
|
|
7605
|
-
showSwitcher && demo ? /* @__PURE__ */ (0,
|
|
7606
|
-
/* @__PURE__ */ (0,
|
|
7607
|
-
/* @__PURE__ */ (0,
|
|
7608
|
-
/* @__PURE__ */ (0,
|
|
7609
|
-
/* @__PURE__ */ (0,
|
|
7858
|
+
showSwitcher && demo ? /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
7859
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
|
|
7860
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
|
|
7861
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
|
|
7862
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
|
|
7610
7863
|
] }),
|
|
7611
|
-
switching ? /* @__PURE__ */ (0,
|
|
7864
|
+
switching ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
|
|
7612
7865
|
"button",
|
|
7613
7866
|
{
|
|
7614
7867
|
type: "button",
|
|
@@ -7620,19 +7873,19 @@ function AccountMenu({
|
|
|
7620
7873
|
setSwitching(false);
|
|
7621
7874
|
},
|
|
7622
7875
|
children: [
|
|
7623
|
-
/* @__PURE__ */ (0,
|
|
7624
|
-
/* @__PURE__ */ (0,
|
|
7625
|
-
/* @__PURE__ */ (0,
|
|
7626
|
-
u.roles ? /* @__PURE__ */ (0,
|
|
7876
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Avatar, { name: u.name, size: "sm" }),
|
|
7877
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
|
|
7878
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
|
|
7879
|
+
u.roles ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
|
|
7627
7880
|
] }),
|
|
7628
|
-
u.id === user.id ? /* @__PURE__ */ (0,
|
|
7881
|
+
u.id === user.id ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
|
|
7629
7882
|
]
|
|
7630
7883
|
},
|
|
7631
7884
|
u.id
|
|
7632
7885
|
)) }) : null
|
|
7633
7886
|
] }) : null,
|
|
7634
|
-
/* @__PURE__ */ (0,
|
|
7635
|
-
/* @__PURE__ */ (0,
|
|
7887
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
7888
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
|
|
7636
7889
|
"button",
|
|
7637
7890
|
{
|
|
7638
7891
|
type: "button",
|
|
@@ -7642,14 +7895,14 @@ function AccountMenu({
|
|
|
7642
7895
|
disabled: signingOut,
|
|
7643
7896
|
onClick: signOut,
|
|
7644
7897
|
children: [
|
|
7645
|
-
signingOut ? /* @__PURE__ */ (0,
|
|
7646
|
-
/* @__PURE__ */ (0,
|
|
7898
|
+
signingOut ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Spinner, { size: "sm" }) : /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
|
|
7899
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
|
|
7647
7900
|
]
|
|
7648
7901
|
}
|
|
7649
7902
|
),
|
|
7650
|
-
signOutError ? /* @__PURE__ */ (0,
|
|
7651
|
-
/* @__PURE__ */ (0,
|
|
7652
|
-
/* @__PURE__ */ (0,
|
|
7903
|
+
signOutError ? /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
|
|
7904
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
|
|
7905
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
|
|
7653
7906
|
] }) : null
|
|
7654
7907
|
] })
|
|
7655
7908
|
] })
|
|
@@ -7659,13 +7912,13 @@ function AccountMenu({
|
|
|
7659
7912
|
}
|
|
7660
7913
|
|
|
7661
7914
|
// src/components/platform/AppSwitcher.tsx
|
|
7662
|
-
var
|
|
7663
|
-
var
|
|
7915
|
+
var React46 = __toESM(require("react"), 1);
|
|
7916
|
+
var import_jsx_runtime75 = require("react/jsx-runtime");
|
|
7664
7917
|
function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
7665
7918
|
const { apps: contextApps } = useSessionContext();
|
|
7666
7919
|
const apps = appsProp ?? contextApps ?? [];
|
|
7667
|
-
const [open2, setOpen] =
|
|
7668
|
-
const anchorRef =
|
|
7920
|
+
const [open2, setOpen] = React46.useState(false);
|
|
7921
|
+
const anchorRef = React46.useRef(null);
|
|
7669
7922
|
if (!apps.length) return null;
|
|
7670
7923
|
const items = apps.map((app) => ({
|
|
7671
7924
|
id: app.key,
|
|
@@ -7679,8 +7932,8 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7679
7932
|
window.location.href = app.url;
|
|
7680
7933
|
}
|
|
7681
7934
|
}));
|
|
7682
|
-
return /* @__PURE__ */ (0,
|
|
7683
|
-
/* @__PURE__ */ (0,
|
|
7935
|
+
return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(React46.Fragment, { children: [
|
|
7936
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
|
|
7684
7937
|
IconButton,
|
|
7685
7938
|
{
|
|
7686
7939
|
icon: "squares-four",
|
|
@@ -7690,7 +7943,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7690
7943
|
onClick: () => setOpen((v) => !v)
|
|
7691
7944
|
}
|
|
7692
7945
|
) }),
|
|
7693
|
-
/* @__PURE__ */ (0,
|
|
7946
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
|
|
7694
7947
|
Popover,
|
|
7695
7948
|
{
|
|
7696
7949
|
open: open2,
|
|
@@ -7701,17 +7954,17 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7701
7954
|
label: "All flytedesk apps",
|
|
7702
7955
|
width: 240,
|
|
7703
7956
|
maxHeight: 360,
|
|
7704
|
-
children: /* @__PURE__ */ (0,
|
|
7957
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(Menu, { items, onClose: () => setOpen(false) })
|
|
7705
7958
|
}
|
|
7706
7959
|
)
|
|
7707
7960
|
] });
|
|
7708
7961
|
}
|
|
7709
7962
|
|
|
7710
7963
|
// src/components/platform/AppearanceMenu.tsx
|
|
7711
|
-
var
|
|
7964
|
+
var React48 = __toESM(require("react"), 1);
|
|
7712
7965
|
|
|
7713
7966
|
// src/kits/appearance.ts
|
|
7714
|
-
var
|
|
7967
|
+
var React47 = __toESM(require("react"), 1);
|
|
7715
7968
|
var DEFAULT_STORAGE_KEY = "fd-appearance";
|
|
7716
7969
|
var DEFAULT_PREFS = {
|
|
7717
7970
|
theme: "system",
|
|
@@ -7806,11 +8059,11 @@ function applyPrefs(prefs, root = document.documentElement) {
|
|
|
7806
8059
|
else root.removeAttribute("data-motion");
|
|
7807
8060
|
}
|
|
7808
8061
|
function useAppearancePrefs(store) {
|
|
7809
|
-
const prefs =
|
|
7810
|
-
|
|
8062
|
+
const prefs = React47.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
8063
|
+
React47.useEffect(() => {
|
|
7811
8064
|
applyPrefs(prefs);
|
|
7812
8065
|
}, [prefs]);
|
|
7813
|
-
|
|
8066
|
+
React47.useEffect(() => {
|
|
7814
8067
|
if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
7815
8068
|
return;
|
|
7816
8069
|
}
|
|
@@ -7819,7 +8072,7 @@ function useAppearancePrefs(store) {
|
|
|
7819
8072
|
mq.addEventListener("change", onChange);
|
|
7820
8073
|
return () => mq.removeEventListener("change", onChange);
|
|
7821
8074
|
}, [prefs]);
|
|
7822
|
-
const update =
|
|
8075
|
+
const update = React47.useCallback(
|
|
7823
8076
|
(patch) => {
|
|
7824
8077
|
store.write({ ...store.getSnapshot(), ...patch });
|
|
7825
8078
|
},
|
|
@@ -7829,7 +8082,7 @@ function useAppearancePrefs(store) {
|
|
|
7829
8082
|
}
|
|
7830
8083
|
|
|
7831
8084
|
// src/components/platform/AppearanceMenu.tsx
|
|
7832
|
-
var
|
|
8085
|
+
var import_jsx_runtime76 = require("react/jsx-runtime");
|
|
7833
8086
|
var THEME_OPTIONS = [
|
|
7834
8087
|
{ value: "light", label: "Light" },
|
|
7835
8088
|
{ value: "dark", label: "Dark" },
|
|
@@ -7842,16 +8095,16 @@ var TEXT_SCALE_OPTIONS = [
|
|
|
7842
8095
|
{ value: "xl", label: "XL" }
|
|
7843
8096
|
];
|
|
7844
8097
|
function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
|
|
7845
|
-
const store =
|
|
8098
|
+
const store = React48.useMemo(
|
|
7846
8099
|
() => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
|
|
7847
8100
|
[storeProp, storageKey, storage, defaults]
|
|
7848
8101
|
);
|
|
7849
8102
|
const [prefs, update] = useAppearancePrefs(store);
|
|
7850
|
-
const [open2, setOpen] =
|
|
7851
|
-
const anchorRef =
|
|
8103
|
+
const [open2, setOpen] = React48.useState(false);
|
|
8104
|
+
const anchorRef = React48.useRef(null);
|
|
7852
8105
|
const patch = (p) => update(p);
|
|
7853
|
-
return /* @__PURE__ */ (0,
|
|
7854
|
-
/* @__PURE__ */ (0,
|
|
8106
|
+
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React48.Fragment, { children: [
|
|
8107
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
7855
8108
|
IconButton,
|
|
7856
8109
|
{
|
|
7857
8110
|
icon: "circle-half",
|
|
@@ -7859,7 +8112,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7859
8112
|
onClick: () => setOpen((v) => !v)
|
|
7860
8113
|
}
|
|
7861
8114
|
) }),
|
|
7862
|
-
/* @__PURE__ */ (0,
|
|
8115
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
7863
8116
|
Popover,
|
|
7864
8117
|
{
|
|
7865
8118
|
open: open2,
|
|
@@ -7869,10 +8122,10 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7869
8122
|
padded: true,
|
|
7870
8123
|
width: 260,
|
|
7871
8124
|
label: "Appearance settings",
|
|
7872
|
-
children: /* @__PURE__ */ (0,
|
|
7873
|
-
/* @__PURE__ */ (0,
|
|
7874
|
-
/* @__PURE__ */ (0,
|
|
7875
|
-
/* @__PURE__ */ (0,
|
|
8125
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
|
|
8126
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
8127
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-field-label", children: "Theme" }),
|
|
8128
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
7876
8129
|
SegmentedControl,
|
|
7877
8130
|
{
|
|
7878
8131
|
options: THEME_OPTIONS,
|
|
@@ -7882,9 +8135,9 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7882
8135
|
}
|
|
7883
8136
|
)
|
|
7884
8137
|
] }),
|
|
7885
|
-
/* @__PURE__ */ (0,
|
|
7886
|
-
/* @__PURE__ */ (0,
|
|
7887
|
-
/* @__PURE__ */ (0,
|
|
8138
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
8139
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-field-label", children: "Text size" }),
|
|
8140
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
7888
8141
|
SegmentedControl,
|
|
7889
8142
|
{
|
|
7890
8143
|
options: TEXT_SCALE_OPTIONS,
|
|
@@ -7894,7 +8147,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7894
8147
|
}
|
|
7895
8148
|
)
|
|
7896
8149
|
] }),
|
|
7897
|
-
/* @__PURE__ */ (0,
|
|
8150
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
7898
8151
|
Switch,
|
|
7899
8152
|
{
|
|
7900
8153
|
label: "High contrast",
|
|
@@ -7903,7 +8156,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7903
8156
|
onChange: (e) => patch({ highContrast: e.target.checked })
|
|
7904
8157
|
}
|
|
7905
8158
|
),
|
|
7906
|
-
/* @__PURE__ */ (0,
|
|
8159
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
7907
8160
|
Switch,
|
|
7908
8161
|
{
|
|
7909
8162
|
label: "Reduce motion",
|
|
@@ -7919,14 +8172,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7919
8172
|
}
|
|
7920
8173
|
|
|
7921
8174
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
7922
|
-
var
|
|
7923
|
-
var
|
|
8175
|
+
var React49 = __toESM(require("react"), 1);
|
|
8176
|
+
var import_jsx_runtime77 = require("react/jsx-runtime");
|
|
7924
8177
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
7925
8178
|
function Json({ obj }) {
|
|
7926
|
-
return /* @__PURE__ */ (0,
|
|
8179
|
+
return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
7927
8180
|
}
|
|
7928
8181
|
function Endpoint({ s, onRequest }) {
|
|
7929
|
-
const [tried, setTried] =
|
|
8182
|
+
const [tried, setTried] = React49.useState(null);
|
|
7930
8183
|
const run = async () => {
|
|
7931
8184
|
setTried("busy");
|
|
7932
8185
|
const t0 = (window.performance || Date).now();
|
|
@@ -7937,50 +8190,50 @@ function Endpoint({ s, onRequest }) {
|
|
|
7937
8190
|
setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
|
|
7938
8191
|
}
|
|
7939
8192
|
};
|
|
7940
|
-
return /* @__PURE__ */ (0,
|
|
7941
|
-
/* @__PURE__ */ (0,
|
|
7942
|
-
/* @__PURE__ */ (0,
|
|
7943
|
-
/* @__PURE__ */ (0,
|
|
7944
|
-
s.isList ? /* @__PURE__ */ (0,
|
|
7945
|
-
/* @__PURE__ */ (0,
|
|
7946
|
-
/* @__PURE__ */ (0,
|
|
8193
|
+
return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
8194
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
|
|
8195
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
|
|
8196
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
|
|
8197
|
+
s.isList ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
|
|
8198
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { style: { flex: 1 } }),
|
|
8199
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
7947
8200
|
s.latency[0],
|
|
7948
8201
|
"\u2013",
|
|
7949
8202
|
s.latency[1],
|
|
7950
8203
|
"ms"
|
|
7951
8204
|
] }),
|
|
7952
|
-
/* @__PURE__ */ (0,
|
|
8205
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
|
|
7953
8206
|
] }),
|
|
7954
|
-
/* @__PURE__ */ (0,
|
|
7955
|
-
/* @__PURE__ */ (0,
|
|
7956
|
-
/* @__PURE__ */ (0,
|
|
7957
|
-
/* @__PURE__ */ (0,
|
|
7958
|
-
s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0,
|
|
8207
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
|
|
8208
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8209
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
|
|
8210
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
|
|
8211
|
+
s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Tag, { children: u }, u)) }) : null
|
|
7959
8212
|
] }),
|
|
7960
|
-
/* @__PURE__ */ (0,
|
|
7961
|
-
s.request ? /* @__PURE__ */ (0,
|
|
7962
|
-
/* @__PURE__ */ (0,
|
|
7963
|
-
/* @__PURE__ */ (0,
|
|
8213
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
|
|
8214
|
+
s.request ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8215
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Request body" }),
|
|
8216
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Json, { obj: s.request })
|
|
7964
8217
|
] }) : null,
|
|
7965
|
-
s.query ? /* @__PURE__ */ (0,
|
|
7966
|
-
/* @__PURE__ */ (0,
|
|
7967
|
-
/* @__PURE__ */ (0,
|
|
8218
|
+
s.query ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8219
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Query" }),
|
|
8220
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Json, { obj: s.query })
|
|
7968
8221
|
] }) : null,
|
|
7969
|
-
/* @__PURE__ */ (0,
|
|
7970
|
-
/* @__PURE__ */ (0,
|
|
7971
|
-
/* @__PURE__ */ (0,
|
|
8222
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8223
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Response 200" }),
|
|
8224
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Json, { obj: s.response })
|
|
7972
8225
|
] })
|
|
7973
8226
|
] }),
|
|
7974
|
-
s.notes ? /* @__PURE__ */ (0,
|
|
7975
|
-
tried && tried !== "busy" ? /* @__PURE__ */ (0,
|
|
7976
|
-
/* @__PURE__ */ (0,
|
|
7977
|
-
/* @__PURE__ */ (0,
|
|
7978
|
-
/* @__PURE__ */ (0,
|
|
8227
|
+
s.notes ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
|
|
8228
|
+
tried && tried !== "busy" ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8229
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
8230
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
|
|
8231
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
|
|
7979
8232
|
tried.ms,
|
|
7980
8233
|
"ms"
|
|
7981
8234
|
] })
|
|
7982
8235
|
] }),
|
|
7983
|
-
/* @__PURE__ */ (0,
|
|
8236
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
|
|
7984
8237
|
] }) : null
|
|
7985
8238
|
] })
|
|
7986
8239
|
] }) });
|
|
@@ -7999,58 +8252,58 @@ function ApiSpecBrowser({
|
|
|
7999
8252
|
className = "",
|
|
8000
8253
|
...rest
|
|
8001
8254
|
}) {
|
|
8002
|
-
const [q, setQ] =
|
|
8003
|
-
const [method, setMethod] =
|
|
8004
|
-
const [mod, setMod] =
|
|
8005
|
-
const [listOnly, setListOnly] =
|
|
8255
|
+
const [q, setQ] = React49.useState("");
|
|
8256
|
+
const [method, setMethod] = React49.useState(null);
|
|
8257
|
+
const [mod, setMod] = React49.useState(null);
|
|
8258
|
+
const [listOnly, setListOnly] = React49.useState(false);
|
|
8006
8259
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
8007
8260
|
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())));
|
|
8008
8261
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
8009
8262
|
const methods = [...new Set(spec.map((s) => s.method))];
|
|
8010
8263
|
const listCount = spec.filter((s) => s.isList).length;
|
|
8011
|
-
return /* @__PURE__ */ (0,
|
|
8012
|
-
/* @__PURE__ */ (0,
|
|
8013
|
-
kicker ? /* @__PURE__ */ (0,
|
|
8014
|
-
/* @__PURE__ */ (0,
|
|
8015
|
-
lede ? /* @__PURE__ */ (0,
|
|
8264
|
+
return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
|
|
8265
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
8266
|
+
kicker ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: kicker }) : null,
|
|
8267
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
8268
|
+
lede ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
|
|
8016
8269
|
] }),
|
|
8017
|
-
modules && modules.length ? /* @__PURE__ */ (0,
|
|
8018
|
-
/* @__PURE__ */ (0,
|
|
8019
|
-
/* @__PURE__ */ (0,
|
|
8020
|
-
/* @__PURE__ */ (0,
|
|
8270
|
+
modules && modules.length ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
8271
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
|
|
8272
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
8273
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
|
|
8021
8274
|
"All screens ",
|
|
8022
|
-
/* @__PURE__ */ (0,
|
|
8275
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-mono", children: spec.length })
|
|
8023
8276
|
] }),
|
|
8024
|
-
modules.map((m) => /* @__PURE__ */ (0,
|
|
8277
|
+
modules.map((m) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
|
|
8025
8278
|
m.label,
|
|
8026
8279
|
" ",
|
|
8027
|
-
/* @__PURE__ */ (0,
|
|
8280
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
|
|
8028
8281
|
] }, m.id))
|
|
8029
8282
|
] }),
|
|
8030
|
-
activeModule ? /* @__PURE__ */ (0,
|
|
8283
|
+
activeModule ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
8031
8284
|
Flag,
|
|
8032
8285
|
{
|
|
8033
8286
|
tone: "info",
|
|
8034
8287
|
statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
|
|
8035
8288
|
cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
|
|
8036
|
-
actions: /* @__PURE__ */ (0,
|
|
8289
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
|
|
8037
8290
|
}
|
|
8038
8291
|
) : null
|
|
8039
8292
|
] }) : null,
|
|
8040
|
-
sourceNote ? /* @__PURE__ */ (0,
|
|
8041
|
-
/* @__PURE__ */ (0,
|
|
8042
|
-
/* @__PURE__ */ (0,
|
|
8043
|
-
methods.map((m) => /* @__PURE__ */ (0,
|
|
8293
|
+
sourceNote ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
|
|
8294
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
8295
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
|
|
8296
|
+
methods.map((m) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
|
|
8044
8297
|
m,
|
|
8045
8298
|
" ",
|
|
8046
|
-
/* @__PURE__ */ (0,
|
|
8299
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
|
|
8047
8300
|
] }, m)),
|
|
8048
|
-
listCount ? /* @__PURE__ */ (0,
|
|
8301
|
+
listCount ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
|
|
8049
8302
|
"Paged lists ",
|
|
8050
|
-
/* @__PURE__ */ (0,
|
|
8303
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-mono", children: listCount })
|
|
8051
8304
|
] }) : null,
|
|
8052
|
-
/* @__PURE__ */ (0,
|
|
8053
|
-
/* @__PURE__ */ (0,
|
|
8305
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { style: { flex: 1 } }),
|
|
8306
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
8054
8307
|
hits.length,
|
|
8055
8308
|
" of ",
|
|
8056
8309
|
spec.length,
|
|
@@ -8058,31 +8311,31 @@ function ApiSpecBrowser({
|
|
|
8058
8311
|
listCount ? " \xB7 " + listCount + " paged" : ""
|
|
8059
8312
|
] })
|
|
8060
8313
|
] }),
|
|
8061
|
-
hits.length === 0 ? /* @__PURE__ */ (0,
|
|
8314
|
+
hits.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
|
|
8062
8315
|
const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
|
|
8063
8316
|
if (!items.length) return null;
|
|
8064
|
-
return /* @__PURE__ */ (0,
|
|
8065
|
-
/* @__PURE__ */ (0,
|
|
8066
|
-
items.map((s) => /* @__PURE__ */ (0,
|
|
8317
|
+
return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 12 }, children: [
|
|
8318
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-label-lg", children: g }),
|
|
8319
|
+
items.map((s) => /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Endpoint, { s, onRequest }, s.id))
|
|
8067
8320
|
] }, g);
|
|
8068
8321
|
}),
|
|
8069
|
-
conventions && conventions.length ? /* @__PURE__ */ (0,
|
|
8070
|
-
/* @__PURE__ */ (0,
|
|
8071
|
-
/* @__PURE__ */ (0,
|
|
8322
|
+
conventions && conventions.length ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
|
|
8323
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
|
|
8324
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
|
|
8072
8325
|
] }, k)) }) }) : null,
|
|
8073
|
-
openQuestions && openQuestions.length ? /* @__PURE__ */ (0,
|
|
8074
|
-
/* @__PURE__ */ (0,
|
|
8075
|
-
/* @__PURE__ */ (0,
|
|
8076
|
-
/* @__PURE__ */ (0,
|
|
8077
|
-
/* @__PURE__ */ (0,
|
|
8326
|
+
openQuestions && openQuestions.length ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
|
|
8327
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Badge, { tone: "danger", children: id }),
|
|
8328
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
|
|
8329
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
|
|
8330
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm fd-muted", children: why })
|
|
8078
8331
|
] })
|
|
8079
8332
|
] }, id)) }) }) : null
|
|
8080
8333
|
] });
|
|
8081
8334
|
}
|
|
8082
8335
|
|
|
8083
8336
|
// src/components/platform/ProfilePage.tsx
|
|
8084
|
-
var
|
|
8085
|
-
var
|
|
8337
|
+
var React50 = __toESM(require("react"), 1);
|
|
8338
|
+
var import_jsx_runtime78 = require("react/jsx-runtime");
|
|
8086
8339
|
function fieldInitialValue(field, user) {
|
|
8087
8340
|
if (field.value) return field.value(user);
|
|
8088
8341
|
const raw = user[field.key];
|
|
@@ -8117,21 +8370,21 @@ function ProfilePage({
|
|
|
8117
8370
|
}) {
|
|
8118
8371
|
const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
|
|
8119
8372
|
const user = userProp || sessionUser;
|
|
8120
|
-
const initialFieldValues =
|
|
8373
|
+
const initialFieldValues = React50.useMemo(() => {
|
|
8121
8374
|
const values2 = {};
|
|
8122
8375
|
for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
|
|
8123
8376
|
return values2;
|
|
8124
8377
|
}, [user.id, fields]);
|
|
8125
|
-
const initialNotify =
|
|
8378
|
+
const initialNotify = React50.useMemo(() => {
|
|
8126
8379
|
const values2 = {};
|
|
8127
8380
|
for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
|
|
8128
8381
|
return values2;
|
|
8129
8382
|
}, [user.id, notifications]);
|
|
8130
|
-
const [values, setValues] =
|
|
8131
|
-
const [notify, setNotify] =
|
|
8132
|
-
const [saving, setSaving] =
|
|
8133
|
-
const [saved, setSaved] =
|
|
8134
|
-
const [prevUserId, setPrevUserId] =
|
|
8383
|
+
const [values, setValues] = React50.useState(initialFieldValues);
|
|
8384
|
+
const [notify, setNotify] = React50.useState(initialNotify);
|
|
8385
|
+
const [saving, setSaving] = React50.useState(false);
|
|
8386
|
+
const [saved, setSaved] = React50.useState(false);
|
|
8387
|
+
const [prevUserId, setPrevUserId] = React50.useState(user.id);
|
|
8135
8388
|
if (user.id !== prevUserId) {
|
|
8136
8389
|
setPrevUserId(user.id);
|
|
8137
8390
|
setValues(initialFieldValues);
|
|
@@ -8168,37 +8421,37 @@ function ProfilePage({
|
|
|
8168
8421
|
};
|
|
8169
8422
|
const displayName = fields.some((f) => f.key === "name") ? values.name || user.name : user.name;
|
|
8170
8423
|
const fieldGroups = groupFields(fields);
|
|
8171
|
-
return /* @__PURE__ */ (0,
|
|
8172
|
-
/* @__PURE__ */ (0,
|
|
8173
|
-
/* @__PURE__ */ (0,
|
|
8174
|
-
/* @__PURE__ */ (0,
|
|
8175
|
-
/* @__PURE__ */ (0,
|
|
8424
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
|
|
8425
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
8426
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
|
|
8427
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
|
|
8428
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
|
|
8176
8429
|
] }),
|
|
8177
|
-
/* @__PURE__ */ (0,
|
|
8178
|
-
/* @__PURE__ */ (0,
|
|
8179
|
-
/* @__PURE__ */ (0,
|
|
8180
|
-
/* @__PURE__ */ (0,
|
|
8181
|
-
/* @__PURE__ */ (0,
|
|
8182
|
-
roles.map((r) => /* @__PURE__ */ (0,
|
|
8183
|
-
user.sso ? /* @__PURE__ */ (0,
|
|
8430
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
|
|
8431
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Avatar, { name: displayName, size: "lg" }),
|
|
8432
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
|
|
8433
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
|
|
8434
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
|
|
8435
|
+
roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
|
|
8436
|
+
user.sso ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
|
|
8184
8437
|
] })
|
|
8185
8438
|
] }),
|
|
8186
|
-
onChangePhoto ? /* @__PURE__ */ (0,
|
|
8439
|
+
onChangePhoto ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
|
|
8187
8440
|
] }) }),
|
|
8188
|
-
fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ (0,
|
|
8441
|
+
fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
8189
8442
|
Card,
|
|
8190
8443
|
{
|
|
8191
|
-
title: description ? /* @__PURE__ */ (0,
|
|
8192
|
-
/* @__PURE__ */ (0,
|
|
8193
|
-
/* @__PURE__ */ (0,
|
|
8444
|
+
title: description ? /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
8445
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { children: group }),
|
|
8446
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
|
|
8194
8447
|
] }) : group,
|
|
8195
8448
|
elevation: "flat",
|
|
8196
|
-
children: /* @__PURE__ */ (0,
|
|
8197
|
-
/* @__PURE__ */ (0,
|
|
8449
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
|
|
8450
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
|
|
8198
8451
|
const help = typeof field.help === "function" ? field.help(user) : field.help;
|
|
8199
8452
|
const readOnly = field.readOnly || field.type === "readonly";
|
|
8200
8453
|
if (field.type === "select") {
|
|
8201
|
-
return /* @__PURE__ */ (0,
|
|
8454
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
8202
8455
|
Select,
|
|
8203
8456
|
{
|
|
8204
8457
|
label: field.label,
|
|
@@ -8212,7 +8465,7 @@ function ProfilePage({
|
|
|
8212
8465
|
field.key
|
|
8213
8466
|
);
|
|
8214
8467
|
}
|
|
8215
|
-
return /* @__PURE__ */ (0,
|
|
8468
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
8216
8469
|
Input,
|
|
8217
8470
|
{
|
|
8218
8471
|
label: field.label,
|
|
@@ -8228,7 +8481,7 @@ function ProfilePage({
|
|
|
8228
8481
|
}) }),
|
|
8229
8482
|
groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
|
|
8230
8483
|
const help = typeof field.help === "function" ? field.help(user) : field.help;
|
|
8231
|
-
return /* @__PURE__ */ (0,
|
|
8484
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
8232
8485
|
Textarea,
|
|
8233
8486
|
{
|
|
8234
8487
|
label: field.label,
|
|
@@ -8248,16 +8501,16 @@ function ProfilePage({
|
|
|
8248
8501
|
group
|
|
8249
8502
|
)),
|
|
8250
8503
|
extra,
|
|
8251
|
-
notifications.length > 0 ? /* @__PURE__ */ (0,
|
|
8252
|
-
/* @__PURE__ */ (0,
|
|
8504
|
+
notifications.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
|
|
8505
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
|
|
8253
8506
|
Card,
|
|
8254
8507
|
{
|
|
8255
|
-
title: /* @__PURE__ */ (0,
|
|
8256
|
-
/* @__PURE__ */ (0,
|
|
8257
|
-
/* @__PURE__ */ (0,
|
|
8508
|
+
title: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
8509
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { children: "Access" }),
|
|
8510
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
|
|
8258
8511
|
] }),
|
|
8259
8512
|
elevation: "flat",
|
|
8260
|
-
action: /* @__PURE__ */ (0,
|
|
8513
|
+
action: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
8261
8514
|
Button,
|
|
8262
8515
|
{
|
|
8263
8516
|
size: "sm",
|
|
@@ -8268,39 +8521,39 @@ function ProfilePage({
|
|
|
8268
8521
|
}
|
|
8269
8522
|
),
|
|
8270
8523
|
children: [
|
|
8271
|
-
/* @__PURE__ */ (0,
|
|
8272
|
-
/* @__PURE__ */ (0,
|
|
8273
|
-
/* @__PURE__ */ (0,
|
|
8524
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
8525
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
|
|
8526
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(CardRow, { label: "Permissions", children: [
|
|
8274
8527
|
permissions.length,
|
|
8275
8528
|
" granted"
|
|
8276
8529
|
] }),
|
|
8277
|
-
/* @__PURE__ */ (0,
|
|
8530
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
|
|
8278
8531
|
] }),
|
|
8279
|
-
/* @__PURE__ */ (0,
|
|
8532
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
|
|
8280
8533
|
]
|
|
8281
8534
|
}
|
|
8282
8535
|
),
|
|
8283
|
-
sessions ? /* @__PURE__ */ (0,
|
|
8536
|
+
sessions ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
8284
8537
|
Card,
|
|
8285
8538
|
{
|
|
8286
8539
|
title: "Signed-in devices",
|
|
8287
8540
|
elevation: "flat",
|
|
8288
|
-
action: /* @__PURE__ */ (0,
|
|
8289
|
-
children: /* @__PURE__ */ (0,
|
|
8290
|
-
/* @__PURE__ */ (0,
|
|
8291
|
-
/* @__PURE__ */ (0,
|
|
8292
|
-
/* @__PURE__ */ (0,
|
|
8293
|
-
/* @__PURE__ */ (0,
|
|
8541
|
+
action: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
|
|
8542
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
|
|
8543
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
8544
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
|
|
8545
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
|
|
8546
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
8294
8547
|
s.where,
|
|
8295
8548
|
" \xB7 ",
|
|
8296
8549
|
s.when
|
|
8297
8550
|
] })
|
|
8298
8551
|
] }),
|
|
8299
|
-
s.current ? /* @__PURE__ */ (0,
|
|
8552
|
+
s.current ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { size: "sm", variant: "ghost", children: "Revoke" })
|
|
8300
8553
|
] }, s.id)) })
|
|
8301
8554
|
}
|
|
8302
8555
|
) : null,
|
|
8303
|
-
/* @__PURE__ */ (0,
|
|
8556
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-row", style: {
|
|
8304
8557
|
gap: 10,
|
|
8305
8558
|
flexWrap: "wrap",
|
|
8306
8559
|
position: "sticky",
|
|
@@ -8311,19 +8564,19 @@ function ProfilePage({
|
|
|
8311
8564
|
border: "1px solid var(--border)",
|
|
8312
8565
|
boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
|
|
8313
8566
|
}, children: [
|
|
8314
|
-
/* @__PURE__ */ (0,
|
|
8315
|
-
/* @__PURE__ */ (0,
|
|
8316
|
-
/* @__PURE__ */ (0,
|
|
8567
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
|
|
8568
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
|
|
8569
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
|
|
8317
8570
|
] })
|
|
8318
8571
|
] });
|
|
8319
8572
|
}
|
|
8320
8573
|
|
|
8321
8574
|
// src/components/platform/SignInPage.tsx
|
|
8322
|
-
var
|
|
8323
|
-
var
|
|
8575
|
+
var React51 = __toESM(require("react"), 1);
|
|
8576
|
+
var import_jsx_runtime79 = require("react/jsx-runtime");
|
|
8324
8577
|
function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
8325
|
-
const [signingIn, setSigningIn] =
|
|
8326
|
-
const [resuming, setResuming] =
|
|
8578
|
+
const [signingIn, setSigningIn] = React51.useState(false);
|
|
8579
|
+
const [resuming, setResuming] = React51.useState(false);
|
|
8327
8580
|
function handleSignIn() {
|
|
8328
8581
|
setSigningIn(true);
|
|
8329
8582
|
onSignIn();
|
|
@@ -8332,7 +8585,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8332
8585
|
setResuming(true);
|
|
8333
8586
|
continueAs.onContinue().finally(() => setResuming(false));
|
|
8334
8587
|
}
|
|
8335
|
-
return /* @__PURE__ */ (0,
|
|
8588
|
+
return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
|
|
8336
8589
|
"div",
|
|
8337
8590
|
{
|
|
8338
8591
|
style: {
|
|
@@ -8346,7 +8599,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8346
8599
|
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%)"
|
|
8347
8600
|
},
|
|
8348
8601
|
children: [
|
|
8349
|
-
/* @__PURE__ */ (0,
|
|
8602
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8350
8603
|
"div",
|
|
8351
8604
|
{
|
|
8352
8605
|
"aria-hidden": true,
|
|
@@ -8359,7 +8612,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8359
8612
|
}
|
|
8360
8613
|
}
|
|
8361
8614
|
),
|
|
8362
|
-
/* @__PURE__ */ (0,
|
|
8615
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
|
|
8363
8616
|
"div",
|
|
8364
8617
|
{
|
|
8365
8618
|
style: {
|
|
@@ -8371,8 +8624,8 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8371
8624
|
alignItems: "center"
|
|
8372
8625
|
},
|
|
8373
8626
|
children: [
|
|
8374
|
-
/* @__PURE__ */ (0,
|
|
8375
|
-
/* @__PURE__ */ (0,
|
|
8627
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { style: { marginBottom: "var(--s-32)" }, "data-theme": "dark", children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(FlytedeskMark, { size: "lg" }) }),
|
|
8628
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
|
|
8376
8629
|
"div",
|
|
8377
8630
|
{
|
|
8378
8631
|
style: {
|
|
@@ -8382,7 +8635,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8382
8635
|
boxShadow: "0 24px 64px -12px rgba(2, 8, 20, 0.55), 0 2px 8px rgba(2, 8, 20, 0.3)"
|
|
8383
8636
|
},
|
|
8384
8637
|
children: [
|
|
8385
|
-
/* @__PURE__ */ (0,
|
|
8638
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8386
8639
|
"div",
|
|
8387
8640
|
{
|
|
8388
8641
|
style: {
|
|
@@ -8391,7 +8644,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8391
8644
|
}
|
|
8392
8645
|
}
|
|
8393
8646
|
),
|
|
8394
|
-
/* @__PURE__ */ (0,
|
|
8647
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
|
|
8395
8648
|
"div",
|
|
8396
8649
|
{
|
|
8397
8650
|
style: {
|
|
@@ -8403,13 +8656,13 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8403
8656
|
padding: "var(--s-8) 0"
|
|
8404
8657
|
},
|
|
8405
8658
|
children: [
|
|
8406
|
-
/* @__PURE__ */ (0,
|
|
8407
|
-
/* @__PURE__ */ (0,
|
|
8408
|
-
/* @__PURE__ */ (0,
|
|
8659
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { children: [
|
|
8660
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)("h1", { className: "fd-h3", style: { color: "var(--navy)" }, children: productName }),
|
|
8661
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)("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" })
|
|
8409
8662
|
] }),
|
|
8410
|
-
error ? /* @__PURE__ */ (0,
|
|
8411
|
-
continueAs ? /* @__PURE__ */ (0,
|
|
8412
|
-
/* @__PURE__ */ (0,
|
|
8663
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { role: "alert", style: { width: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Banner, { tone: "danger", title: error }) }) : null,
|
|
8664
|
+
continueAs ? /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(import_jsx_runtime79.Fragment, { children: [
|
|
8665
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8413
8666
|
Button,
|
|
8414
8667
|
{
|
|
8415
8668
|
variant: "primary",
|
|
@@ -8420,7 +8673,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8420
8673
|
children: resuming ? "Resuming\u2026" : `Continue as ${continueAs.name}`
|
|
8421
8674
|
}
|
|
8422
8675
|
),
|
|
8423
|
-
/* @__PURE__ */ (0,
|
|
8676
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8424
8677
|
"button",
|
|
8425
8678
|
{
|
|
8426
8679
|
type: "button",
|
|
@@ -8437,7 +8690,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8437
8690
|
children: "Not you? Sign in with flytedesk ID"
|
|
8438
8691
|
}
|
|
8439
8692
|
)
|
|
8440
|
-
] }) : /* @__PURE__ */ (0,
|
|
8693
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8441
8694
|
Button,
|
|
8442
8695
|
{
|
|
8443
8696
|
variant: "primary",
|
|
@@ -8445,7 +8698,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8445
8698
|
loading: signingIn,
|
|
8446
8699
|
disabled: signingIn,
|
|
8447
8700
|
onClick: handleSignIn,
|
|
8448
|
-
children: /* @__PURE__ */ (0,
|
|
8701
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
|
|
8449
8702
|
"span",
|
|
8450
8703
|
{
|
|
8451
8704
|
style: {
|
|
@@ -8457,14 +8710,14 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8457
8710
|
flexWrap: "nowrap"
|
|
8458
8711
|
},
|
|
8459
8712
|
children: [
|
|
8460
|
-
/* @__PURE__ */ (0,
|
|
8461
|
-
/* @__PURE__ */ (0,
|
|
8713
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(GoogleGlyph, {}),
|
|
8714
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { children: signingIn ? "Signing in\u2026" : "Sign in with flytedesk ID" })
|
|
8462
8715
|
]
|
|
8463
8716
|
}
|
|
8464
8717
|
)
|
|
8465
8718
|
}
|
|
8466
8719
|
),
|
|
8467
|
-
/* @__PURE__ */ (0,
|
|
8720
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "fd-body-sm fd-muted", style: { fontSize: "12px" }, children: "One account, every flytedesk app." })
|
|
8468
8721
|
]
|
|
8469
8722
|
}
|
|
8470
8723
|
) })
|
|
@@ -8479,29 +8732,29 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8479
8732
|
);
|
|
8480
8733
|
}
|
|
8481
8734
|
function GoogleGlyph() {
|
|
8482
|
-
return /* @__PURE__ */ (0,
|
|
8483
|
-
/* @__PURE__ */ (0,
|
|
8735
|
+
return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 18 18", "aria-hidden": true, children: [
|
|
8736
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8484
8737
|
"path",
|
|
8485
8738
|
{
|
|
8486
8739
|
fill: "#4285F4",
|
|
8487
8740
|
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"
|
|
8488
8741
|
}
|
|
8489
8742
|
),
|
|
8490
|
-
/* @__PURE__ */ (0,
|
|
8743
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8491
8744
|
"path",
|
|
8492
8745
|
{
|
|
8493
8746
|
fill: "#34A853",
|
|
8494
8747
|
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"
|
|
8495
8748
|
}
|
|
8496
8749
|
),
|
|
8497
|
-
/* @__PURE__ */ (0,
|
|
8750
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8498
8751
|
"path",
|
|
8499
8752
|
{
|
|
8500
8753
|
fill: "#FBBC05",
|
|
8501
8754
|
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"
|
|
8502
8755
|
}
|
|
8503
8756
|
),
|
|
8504
|
-
/* @__PURE__ */ (0,
|
|
8757
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8505
8758
|
"path",
|
|
8506
8759
|
{
|
|
8507
8760
|
fill: "#EA4335",
|
|
@@ -8512,10 +8765,10 @@ function GoogleGlyph() {
|
|
|
8512
8765
|
}
|
|
8513
8766
|
|
|
8514
8767
|
// src/components/platform/RoadmapTimeline.tsx
|
|
8515
|
-
var
|
|
8768
|
+
var React54 = __toESM(require("react"), 1);
|
|
8516
8769
|
|
|
8517
8770
|
// src/kits/session.ts
|
|
8518
|
-
var
|
|
8771
|
+
var React52 = __toESM(require("react"), 1);
|
|
8519
8772
|
var PERMISSION_CATALOG = [
|
|
8520
8773
|
{ group: "Plans", items: [
|
|
8521
8774
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -10082,8 +10335,8 @@ function roadmap(overrides) {
|
|
|
10082
10335
|
};
|
|
10083
10336
|
}
|
|
10084
10337
|
function useSession() {
|
|
10085
|
-
const [s, setS] =
|
|
10086
|
-
|
|
10338
|
+
const [s, setS] = React52.useState(getSession);
|
|
10339
|
+
React52.useEffect(() => subscribe(setS), []);
|
|
10087
10340
|
return s;
|
|
10088
10341
|
}
|
|
10089
10342
|
var SessionKit = {
|
|
@@ -10116,7 +10369,7 @@ var SessionKit = {
|
|
|
10116
10369
|
};
|
|
10117
10370
|
function DemoSessionProvider({ children }) {
|
|
10118
10371
|
const session = useSession();
|
|
10119
|
-
const value =
|
|
10372
|
+
const value = React52.useMemo(
|
|
10120
10373
|
() => ({
|
|
10121
10374
|
user: session.user,
|
|
10122
10375
|
roles: session.roles,
|
|
@@ -10132,11 +10385,11 @@ function DemoSessionProvider({ children }) {
|
|
|
10132
10385
|
}),
|
|
10133
10386
|
[session]
|
|
10134
10387
|
);
|
|
10135
|
-
return
|
|
10388
|
+
return React52.createElement(SessionProvider, { value }, children);
|
|
10136
10389
|
}
|
|
10137
10390
|
|
|
10138
10391
|
// src/kits/runtime.ts
|
|
10139
|
-
var
|
|
10392
|
+
var React53 = __toESM(require("react"), 1);
|
|
10140
10393
|
var WIRED_ENDPOINTS = [
|
|
10141
10394
|
// Nothing yet. Every id below would come from a real service:
|
|
10142
10395
|
// "plan.get", "placements.list", …
|
|
@@ -10307,8 +10560,8 @@ var RuntimeKit = {
|
|
|
10307
10560
|
};
|
|
10308
10561
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
10309
10562
|
function useRuntimeMode() {
|
|
10310
|
-
const [m, setM] =
|
|
10311
|
-
|
|
10563
|
+
const [m, setM] = React53.useState(RuntimeKit.getMode());
|
|
10564
|
+
React53.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
10312
10565
|
return m;
|
|
10313
10566
|
}
|
|
10314
10567
|
function useFeatureStatus(key) {
|
|
@@ -10327,7 +10580,7 @@ var UseRuntimeMode = useRuntimeMode;
|
|
|
10327
10580
|
var UseFeatureStatus = useFeatureStatus;
|
|
10328
10581
|
|
|
10329
10582
|
// src/components/platform/RoadmapTimeline.tsx
|
|
10330
|
-
var
|
|
10583
|
+
var import_jsx_runtime80 = require("react/jsx-runtime");
|
|
10331
10584
|
var STATUS = {
|
|
10332
10585
|
shipped: { tone: "success", icon: "check-circle", label: "Wired" },
|
|
10333
10586
|
next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
|
|
@@ -10342,45 +10595,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
10342
10595
|
const s = STATUS[item.status] || STATUS.planned;
|
|
10343
10596
|
const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
|
|
10344
10597
|
const blocking = deps.filter((d) => !d.implemented);
|
|
10345
|
-
return /* @__PURE__ */ (0,
|
|
10346
|
-
/* @__PURE__ */ (0,
|
|
10347
|
-
/* @__PURE__ */ (0,
|
|
10348
|
-
/* @__PURE__ */ (0,
|
|
10349
|
-
/* @__PURE__ */ (0,
|
|
10598
|
+
return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
10599
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
10600
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
|
|
10601
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
|
|
10602
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Badge, { tone: s.tone, icon: s.icon, children: s.label })
|
|
10350
10603
|
] }),
|
|
10351
|
-
/* @__PURE__ */ (0,
|
|
10352
|
-
item.backend ? /* @__PURE__ */ (0,
|
|
10353
|
-
/* @__PURE__ */ (0,
|
|
10354
|
-
/* @__PURE__ */ (0,
|
|
10604
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
|
|
10605
|
+
item.backend ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
|
|
10606
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
|
|
10607
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
|
|
10355
10608
|
] }) : null,
|
|
10356
|
-
/* @__PURE__ */ (0,
|
|
10357
|
-
item.effort ? /* @__PURE__ */ (0,
|
|
10358
|
-
/* @__PURE__ */ (0,
|
|
10609
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
10610
|
+
item.effort ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
10611
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-hourglass-medium" }),
|
|
10359
10612
|
" ",
|
|
10360
10613
|
item.effort
|
|
10361
10614
|
] }) : null,
|
|
10362
|
-
/* @__PURE__ */ (0,
|
|
10363
|
-
/* @__PURE__ */ (0,
|
|
10615
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
10616
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-user" }),
|
|
10364
10617
|
" ",
|
|
10365
10618
|
item.owner
|
|
10366
10619
|
] }),
|
|
10367
|
-
item.screen ? /* @__PURE__ */ (0,
|
|
10368
|
-
/* @__PURE__ */ (0,
|
|
10369
|
-
/* @__PURE__ */ (0,
|
|
10620
|
+
item.screen ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
|
|
10621
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { flex: 1 } }),
|
|
10622
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
|
|
10370
10623
|
"button",
|
|
10371
10624
|
{
|
|
10372
10625
|
type: "button",
|
|
10373
10626
|
onClick: () => onOpenFlag && onOpenFlag(item.key),
|
|
10374
10627
|
style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
|
|
10375
|
-
children: /* @__PURE__ */ (0,
|
|
10628
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
|
|
10376
10629
|
}
|
|
10377
10630
|
)
|
|
10378
10631
|
] }),
|
|
10379
|
-
deps.length ? /* @__PURE__ */ (0,
|
|
10380
|
-
/* @__PURE__ */ (0,
|
|
10381
|
-
deps.map((d) => /* @__PURE__ */ (0,
|
|
10632
|
+
deps.length ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
|
|
10633
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
|
|
10634
|
+
deps.map((d) => /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
|
|
10382
10635
|
] }) : null,
|
|
10383
|
-
blocking.length && !item.implemented ? /* @__PURE__ */ (0,
|
|
10636
|
+
blocking.length && !item.implemented ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
|
|
10384
10637
|
"Blocked until ",
|
|
10385
10638
|
blocking.map((d) => d.label).join(" and "),
|
|
10386
10639
|
" ",
|
|
@@ -10391,12 +10644,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
10391
10644
|
}
|
|
10392
10645
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
10393
10646
|
const session = SessionKit.useSession();
|
|
10394
|
-
const [project, setProject] =
|
|
10395
|
-
const [q, setQ] =
|
|
10396
|
-
const scrollRef =
|
|
10397
|
-
const nowRef =
|
|
10398
|
-
const rm =
|
|
10399
|
-
const byKey =
|
|
10647
|
+
const [project, setProject] = React54.useState("");
|
|
10648
|
+
const [q, setQ] = React54.useState("");
|
|
10649
|
+
const scrollRef = React54.useRef(null);
|
|
10650
|
+
const nowRef = React54.useRef(null);
|
|
10651
|
+
const rm = React54.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
10652
|
+
const byKey = React54.useMemo(() => {
|
|
10400
10653
|
const m = {};
|
|
10401
10654
|
rm.items.forEach((i) => {
|
|
10402
10655
|
m[i.key] = i;
|
|
@@ -10405,7 +10658,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10405
10658
|
}, [rm]);
|
|
10406
10659
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
10407
10660
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
10408
|
-
|
|
10661
|
+
React54.useEffect(() => {
|
|
10409
10662
|
let raf1 = 0, raf2 = 0;
|
|
10410
10663
|
const place = () => {
|
|
10411
10664
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -10433,23 +10686,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10433
10686
|
}, 0);
|
|
10434
10687
|
const nextPhase = items.find((i) => !i.implemented);
|
|
10435
10688
|
let lastPhase = null;
|
|
10436
|
-
return /* @__PURE__ */ (0,
|
|
10437
|
-
/* @__PURE__ */ (0,
|
|
10438
|
-
/* @__PURE__ */ (0,
|
|
10439
|
-
/* @__PURE__ */ (0,
|
|
10440
|
-
/* @__PURE__ */ (0,
|
|
10689
|
+
return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
|
|
10690
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
10691
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-overline fd-muted", children: "Architecture" }),
|
|
10692
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
10693
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede || "Every screen and feature in these tools is already designed and working against a simulated backend. This is the plan for connecting them to the real one \u2014 so the only work described here is server work." })
|
|
10441
10694
|
] }),
|
|
10442
|
-
/* @__PURE__ */ (0,
|
|
10443
|
-
/* @__PURE__ */ (0,
|
|
10444
|
-
/* @__PURE__ */ (0,
|
|
10445
|
-
/* @__PURE__ */ (0,
|
|
10446
|
-
/* @__PURE__ */ (0,
|
|
10695
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-grid-stats is-thin", children: [
|
|
10696
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
|
|
10697
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
|
|
10698
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
|
|
10699
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
|
|
10447
10700
|
] }),
|
|
10448
|
-
/* @__PURE__ */ (0,
|
|
10449
|
-
/* @__PURE__ */ (0,
|
|
10450
|
-
/* @__PURE__ */ (0,
|
|
10451
|
-
/* @__PURE__ */ (0,
|
|
10452
|
-
/* @__PURE__ */ (0,
|
|
10701
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
10702
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find a feature or a piece of backend work", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
|
|
10703
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
|
|
10704
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { flex: 1 } }),
|
|
10705
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
|
|
10453
10706
|
Button,
|
|
10454
10707
|
{
|
|
10455
10708
|
size: "sm",
|
|
@@ -10463,7 +10716,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10463
10716
|
}
|
|
10464
10717
|
)
|
|
10465
10718
|
] }),
|
|
10466
|
-
/* @__PURE__ */ (0,
|
|
10719
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
|
|
10467
10720
|
Flag,
|
|
10468
10721
|
{
|
|
10469
10722
|
tone: "info",
|
|
@@ -10472,60 +10725,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10472
10725
|
actions: null
|
|
10473
10726
|
}
|
|
10474
10727
|
),
|
|
10475
|
-
/* @__PURE__ */ (0,
|
|
10476
|
-
/* @__PURE__ */ (0,
|
|
10728
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-rm", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-rm-track", children: [
|
|
10729
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-rm-spine", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
|
|
10477
10730
|
items.map((item, n) => {
|
|
10478
10731
|
const showPhase = item.phase !== lastPhase;
|
|
10479
10732
|
lastPhase = item.phase;
|
|
10480
10733
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
10481
10734
|
const isBoundary = n === firstPending;
|
|
10482
|
-
return /* @__PURE__ */ (0,
|
|
10483
|
-
showPhase ? /* @__PURE__ */ (0,
|
|
10484
|
-
/* @__PURE__ */ (0,
|
|
10485
|
-
/* @__PURE__ */ (0,
|
|
10486
|
-
item.phase === 0 ? null : /* @__PURE__ */ (0,
|
|
10735
|
+
return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(React54.Fragment, { children: [
|
|
10736
|
+
showPhase ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-rm-era", children: [
|
|
10737
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
10738
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
10739
|
+
item.phase === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
10487
10740
|
fmtDate(item.phaseStart),
|
|
10488
10741
|
" \u2013 ",
|
|
10489
10742
|
fmtDate(item.date)
|
|
10490
10743
|
] }),
|
|
10491
|
-
/* @__PURE__ */ (0,
|
|
10744
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
10492
10745
|
"\xB7 ",
|
|
10493
10746
|
inPhase,
|
|
10494
10747
|
" feature",
|
|
10495
10748
|
inPhase === 1 ? "" : "s"
|
|
10496
10749
|
] })
|
|
10497
10750
|
] }),
|
|
10498
|
-
item.phaseWhy ? /* @__PURE__ */ (0,
|
|
10751
|
+
item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
|
|
10499
10752
|
] }) : null,
|
|
10500
|
-
isBoundary ? /* @__PURE__ */ (0,
|
|
10501
|
-
/* @__PURE__ */ (0,
|
|
10753
|
+
isBoundary ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-rm-now-pill", children: [
|
|
10754
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-map-pin" }),
|
|
10502
10755
|
" You are here \u2014 everything above is wired"
|
|
10503
10756
|
] }) }) : null,
|
|
10504
|
-
/* @__PURE__ */ (0,
|
|
10505
|
-
/* @__PURE__ */ (0,
|
|
10506
|
-
/* @__PURE__ */ (0,
|
|
10757
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-rm-row", children: [
|
|
10758
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
|
|
10759
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-rm-date", children: [
|
|
10507
10760
|
fmtDate(item.date),
|
|
10508
|
-
/* @__PURE__ */ (0,
|
|
10509
|
-
/* @__PURE__ */ (0,
|
|
10761
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("br", {}),
|
|
10762
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
|
|
10510
10763
|
] }),
|
|
10511
|
-
/* @__PURE__ */ (0,
|
|
10764
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
|
|
10512
10765
|
] })
|
|
10513
10766
|
] }, item.key);
|
|
10514
10767
|
}),
|
|
10515
|
-
!items.length ? /* @__PURE__ */ (0,
|
|
10768
|
+
!items.length ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
|
|
10516
10769
|
] }) }) }),
|
|
10517
|
-
/* @__PURE__ */ (0,
|
|
10770
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
|
|
10518
10771
|
"Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
|
|
10519
|
-
/* @__PURE__ */ (0,
|
|
10772
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("code", { className: "fd-mono", children: "implemented" }),
|
|
10520
10773
|
" field, so this page cannot drift from what the apps actually do."
|
|
10521
10774
|
] })
|
|
10522
10775
|
] });
|
|
10523
10776
|
}
|
|
10524
10777
|
|
|
10525
10778
|
// src/components/platform/ComingSoon.tsx
|
|
10526
|
-
var
|
|
10779
|
+
var React55 = __toESM(require("react"), 1);
|
|
10527
10780
|
var import_react_dom6 = require("react-dom");
|
|
10528
|
-
var
|
|
10781
|
+
var import_jsx_runtime81 = require("react/jsx-runtime");
|
|
10529
10782
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
10530
10783
|
function readBypassed() {
|
|
10531
10784
|
try {
|
|
@@ -10541,8 +10794,8 @@ function writeBypassed(list) {
|
|
|
10541
10794
|
}
|
|
10542
10795
|
}
|
|
10543
10796
|
function useBypass(key) {
|
|
10544
|
-
const [on, setOn] =
|
|
10545
|
-
|
|
10797
|
+
const [on, setOn] = React55.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
10798
|
+
React55.useEffect(() => {
|
|
10546
10799
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
10547
10800
|
}, [key]);
|
|
10548
10801
|
const set = (next) => {
|
|
@@ -10555,43 +10808,43 @@ function useBypass(key) {
|
|
|
10555
10808
|
return [on, set];
|
|
10556
10809
|
}
|
|
10557
10810
|
function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
|
|
10558
|
-
return /* @__PURE__ */ (0,
|
|
10559
|
-
/* @__PURE__ */ (0,
|
|
10560
|
-
/* @__PURE__ */ (0,
|
|
10811
|
+
return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(import_jsx_runtime81.Fragment, { children: [
|
|
10812
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-soon-badge", children: [
|
|
10813
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
10561
10814
|
label
|
|
10562
10815
|
] }),
|
|
10563
|
-
detail ? /* @__PURE__ */ (0,
|
|
10564
|
-
backend ? /* @__PURE__ */ (0,
|
|
10565
|
-
/* @__PURE__ */ (0,
|
|
10816
|
+
detail ? /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: "fd-soon-detail", children: detail }) : null,
|
|
10817
|
+
backend ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-soon-backend", children: [
|
|
10818
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: "fd-overline", children: "Needs" }),
|
|
10566
10819
|
" ",
|
|
10567
10820
|
backend
|
|
10568
10821
|
] }) : null,
|
|
10569
|
-
eta || effort || onRoadmap ? /* @__PURE__ */ (0,
|
|
10570
|
-
eta ? /* @__PURE__ */ (0,
|
|
10571
|
-
/* @__PURE__ */ (0,
|
|
10822
|
+
eta || effort || onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-soon-meta", children: [
|
|
10823
|
+
eta ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { children: [
|
|
10824
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
|
|
10572
10825
|
" ",
|
|
10573
10826
|
eta
|
|
10574
10827
|
] }) : null,
|
|
10575
|
-
effort ? /* @__PURE__ */ (0,
|
|
10576
|
-
/* @__PURE__ */ (0,
|
|
10828
|
+
effort ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { children: [
|
|
10829
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
|
|
10577
10830
|
" ",
|
|
10578
10831
|
effort
|
|
10579
10832
|
] }) : null,
|
|
10580
|
-
onRoadmap ? /* @__PURE__ */ (0,
|
|
10833
|
+
onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
10581
10834
|
"See the roadmap ",
|
|
10582
|
-
/* @__PURE__ */ (0,
|
|
10835
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
10583
10836
|
] }) : null
|
|
10584
10837
|
] }) : null,
|
|
10585
|
-
allowed ? /* @__PURE__ */ (0,
|
|
10586
|
-
/* @__PURE__ */ (0,
|
|
10838
|
+
allowed ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
|
|
10839
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-eye", "aria-hidden": "true" }),
|
|
10587
10840
|
" View and use it anyway"
|
|
10588
10841
|
] }) : null
|
|
10589
10842
|
] });
|
|
10590
10843
|
}
|
|
10591
10844
|
function useHoverCard(open2) {
|
|
10592
|
-
const anchor =
|
|
10593
|
-
const [pos, setPos] =
|
|
10594
|
-
|
|
10845
|
+
const anchor = React55.useRef(null);
|
|
10846
|
+
const [pos, setPos] = React55.useState(null);
|
|
10847
|
+
React55.useLayoutEffect(() => {
|
|
10595
10848
|
if (!open2 || !anchor.current) {
|
|
10596
10849
|
setPos(null);
|
|
10597
10850
|
return;
|
|
@@ -10643,9 +10896,9 @@ function ComingSoon({
|
|
|
10643
10896
|
const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
|
|
10644
10897
|
if (inline) {
|
|
10645
10898
|
if (allowed && bypassed) {
|
|
10646
|
-
return /* @__PURE__ */ (0,
|
|
10899
|
+
return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
|
|
10647
10900
|
children,
|
|
10648
|
-
/* @__PURE__ */ (0,
|
|
10901
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
10649
10902
|
"button",
|
|
10650
10903
|
{
|
|
10651
10904
|
type: "button",
|
|
@@ -10653,12 +10906,12 @@ function ComingSoon({
|
|
|
10653
10906
|
title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
|
|
10654
10907
|
onClick: () => setBypassed(false),
|
|
10655
10908
|
"aria-label": "Re-blur this unwired feature",
|
|
10656
|
-
children: /* @__PURE__ */ (0,
|
|
10909
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
10657
10910
|
}
|
|
10658
10911
|
)
|
|
10659
10912
|
] });
|
|
10660
10913
|
}
|
|
10661
|
-
return /* @__PURE__ */ (0,
|
|
10914
|
+
return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
10662
10915
|
InlineSoon,
|
|
10663
10916
|
{
|
|
10664
10917
|
label,
|
|
@@ -10678,20 +10931,20 @@ function ComingSoon({
|
|
|
10678
10931
|
);
|
|
10679
10932
|
}
|
|
10680
10933
|
if (allowed && bypassed) {
|
|
10681
|
-
return /* @__PURE__ */ (0,
|
|
10682
|
-
/* @__PURE__ */ (0,
|
|
10683
|
-
/* @__PURE__ */ (0,
|
|
10684
|
-
/* @__PURE__ */ (0,
|
|
10934
|
+
return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
|
|
10935
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "fd-soon-bar", role: "status", children: [
|
|
10936
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-soon-badge", children: [
|
|
10937
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
10685
10938
|
"Unwired feature \u2014 you are using it anyway"
|
|
10686
10939
|
] }),
|
|
10687
|
-
/* @__PURE__ */ (0,
|
|
10688
|
-
/* @__PURE__ */ (0,
|
|
10689
|
-
onRoadmap ? /* @__PURE__ */ (0,
|
|
10940
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
|
|
10941
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-soon-bar-actions", children: [
|
|
10942
|
+
onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
10690
10943
|
"Roadmap ",
|
|
10691
|
-
/* @__PURE__ */ (0,
|
|
10944
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
10692
10945
|
] }) : null,
|
|
10693
|
-
/* @__PURE__ */ (0,
|
|
10694
|
-
/* @__PURE__ */ (0,
|
|
10946
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
|
|
10947
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
|
|
10695
10948
|
" Re-blur"
|
|
10696
10949
|
] })
|
|
10697
10950
|
] })
|
|
@@ -10699,10 +10952,10 @@ function ComingSoon({
|
|
|
10699
10952
|
children
|
|
10700
10953
|
] });
|
|
10701
10954
|
}
|
|
10702
|
-
return /* @__PURE__ */ (0,
|
|
10703
|
-
/* @__PURE__ */ (0,
|
|
10704
|
-
/* @__PURE__ */ (0,
|
|
10705
|
-
/* @__PURE__ */ (0,
|
|
10955
|
+
return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
|
|
10956
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
10957
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "fd-soon-veil" }),
|
|
10958
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
10706
10959
|
SoonCard,
|
|
10707
10960
|
{
|
|
10708
10961
|
label,
|
|
@@ -10718,10 +10971,10 @@ function ComingSoon({
|
|
|
10718
10971
|
] });
|
|
10719
10972
|
}
|
|
10720
10973
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
10721
|
-
const [open2, setOpen] =
|
|
10974
|
+
const [open2, setOpen] = React55.useState(false);
|
|
10722
10975
|
const [anchor, pos] = useHoverCard(open2);
|
|
10723
10976
|
const zIndex = useOverlayLayer(open2);
|
|
10724
|
-
const close2 =
|
|
10977
|
+
const close2 = React55.useRef(null);
|
|
10725
10978
|
const show = () => {
|
|
10726
10979
|
if (close2.current) {
|
|
10727
10980
|
clearTimeout(close2.current);
|
|
@@ -10737,10 +10990,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10737
10990
|
setOpen(false);
|
|
10738
10991
|
}, 140);
|
|
10739
10992
|
};
|
|
10740
|
-
|
|
10993
|
+
React55.useEffect(() => () => {
|
|
10741
10994
|
if (close2.current) clearTimeout(close2.current);
|
|
10742
10995
|
}, []);
|
|
10743
|
-
return /* @__PURE__ */ (0,
|
|
10996
|
+
return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
|
|
10744
10997
|
"span",
|
|
10745
10998
|
{
|
|
10746
10999
|
ref: anchor,
|
|
@@ -10751,8 +11004,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10751
11004
|
onBlur: hide,
|
|
10752
11005
|
...rest,
|
|
10753
11006
|
children: [
|
|
10754
|
-
/* @__PURE__ */ (0,
|
|
10755
|
-
/* @__PURE__ */ (0,
|
|
11007
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
11008
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
10756
11009
|
"button",
|
|
10757
11010
|
{
|
|
10758
11011
|
type: "button",
|
|
@@ -10763,11 +11016,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10763
11016
|
onFocus: show,
|
|
10764
11017
|
onBlur: hide,
|
|
10765
11018
|
onClick: () => open2 ? setOpen(false) : show(),
|
|
10766
|
-
children: /* @__PURE__ */ (0,
|
|
11019
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
10767
11020
|
}
|
|
10768
11021
|
),
|
|
10769
11022
|
open2 && pos ? (0, import_react_dom6.createPortal)(
|
|
10770
|
-
/* @__PURE__ */ (0,
|
|
11023
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
10771
11024
|
"div",
|
|
10772
11025
|
{
|
|
10773
11026
|
className: "fd-soon-note fd-soon-hovercard",
|
|
@@ -10775,7 +11028,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10775
11028
|
style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
|
|
10776
11029
|
onMouseEnter: show,
|
|
10777
11030
|
onMouseLeave: hide,
|
|
10778
|
-
children: /* @__PURE__ */ (0,
|
|
11031
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
10779
11032
|
SoonCard,
|
|
10780
11033
|
{
|
|
10781
11034
|
label,
|
|
@@ -10805,10 +11058,10 @@ function formatEta(iso2) {
|
|
|
10805
11058
|
var FormatEta = formatEta;
|
|
10806
11059
|
|
|
10807
11060
|
// src/components/platform/Gate.tsx
|
|
10808
|
-
var
|
|
11061
|
+
var import_jsx_runtime82 = require("react/jsx-runtime");
|
|
10809
11062
|
function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
|
|
10810
11063
|
const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
|
|
10811
|
-
return /* @__PURE__ */ (0,
|
|
11064
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
|
|
10812
11065
|
"div",
|
|
10813
11066
|
{
|
|
10814
11067
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -10824,14 +11077,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
10824
11077
|
},
|
|
10825
11078
|
...rest,
|
|
10826
11079
|
children: [
|
|
10827
|
-
/* @__PURE__ */ (0,
|
|
10828
|
-
/* @__PURE__ */ (0,
|
|
10829
|
-
/* @__PURE__ */ (0,
|
|
11080
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
11081
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
11082
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
|
|
10830
11083
|
] }),
|
|
10831
|
-
/* @__PURE__ */ (0,
|
|
10832
|
-
need.length ? /* @__PURE__ */ (0,
|
|
10833
|
-
/* @__PURE__ */ (0,
|
|
10834
|
-
need.map((p) => /* @__PURE__ */ (0,
|
|
11084
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: detail || "Your roles do not grant this. An administrator can change that from Admin \u2192 Users." }),
|
|
11085
|
+
need.length ? /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
|
|
11086
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-overline fd-muted", children: "Requires" }),
|
|
11087
|
+
need.map((p) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("code", { className: "fd-mono", style: {
|
|
10835
11088
|
fontSize: 11.5,
|
|
10836
11089
|
padding: "2px 7px",
|
|
10837
11090
|
borderRadius: 5,
|
|
@@ -10844,7 +11097,7 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
10844
11097
|
);
|
|
10845
11098
|
}
|
|
10846
11099
|
function GatePending({ compact: compact3 = false, className = "" }) {
|
|
10847
|
-
return /* @__PURE__ */ (0,
|
|
11100
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
|
|
10848
11101
|
"div",
|
|
10849
11102
|
{
|
|
10850
11103
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -10860,11 +11113,11 @@ function GatePending({ compact: compact3 = false, className = "" }) {
|
|
|
10860
11113
|
textAlign: "left"
|
|
10861
11114
|
},
|
|
10862
11115
|
children: [
|
|
10863
|
-
/* @__PURE__ */ (0,
|
|
10864
|
-
/* @__PURE__ */ (0,
|
|
10865
|
-
/* @__PURE__ */ (0,
|
|
11116
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
11117
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
11118
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
|
|
10866
11119
|
] }),
|
|
10867
|
-
/* @__PURE__ */ (0,
|
|
11120
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: "Your access can't be verified right now. This will resolve on its own once the connection is back." })
|
|
10868
11121
|
]
|
|
10869
11122
|
}
|
|
10870
11123
|
);
|
|
@@ -10874,7 +11127,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
|
|
|
10874
11127
|
if (pending) {
|
|
10875
11128
|
if (pendingFallback !== void 0) return pendingFallback;
|
|
10876
11129
|
if (silent) return null;
|
|
10877
|
-
return /* @__PURE__ */ (0,
|
|
11130
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(GatePending, { compact: compact3 });
|
|
10878
11131
|
}
|
|
10879
11132
|
let ok = true;
|
|
10880
11133
|
if (perm) ok = ok && can2(perm);
|
|
@@ -10883,7 +11136,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
|
|
|
10883
11136
|
if (ok) return children;
|
|
10884
11137
|
if (fallback !== void 0) return fallback;
|
|
10885
11138
|
if (silent) return null;
|
|
10886
|
-
return /* @__PURE__ */ (0,
|
|
11139
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
|
|
10887
11140
|
}
|
|
10888
11141
|
function FeatureGate({
|
|
10889
11142
|
flag,
|
|
@@ -10906,7 +11159,7 @@ function FeatureGate({
|
|
|
10906
11159
|
const f = SessionKit.findFlag(flag) || {};
|
|
10907
11160
|
const missing = rt.missing || [];
|
|
10908
11161
|
const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
|
|
10909
|
-
return /* @__PURE__ */ (0,
|
|
11162
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
10910
11163
|
ComingSoon,
|
|
10911
11164
|
{
|
|
10912
11165
|
label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
|
|
@@ -10927,22 +11180,22 @@ function FeatureGate({
|
|
|
10927
11180
|
function PermissionHint({ perm, children }) {
|
|
10928
11181
|
const { can: can2, pending } = useSessionContext();
|
|
10929
11182
|
if (pending) {
|
|
10930
|
-
return /* @__PURE__ */ (0,
|
|
11183
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { pointerEvents: "none" }, children }) });
|
|
10931
11184
|
}
|
|
10932
11185
|
if (can2(perm)) return children;
|
|
10933
|
-
return /* @__PURE__ */ (0,
|
|
11186
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
10934
11187
|
"span",
|
|
10935
11188
|
{
|
|
10936
11189
|
title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
|
|
10937
11190
|
style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
|
|
10938
11191
|
"aria-disabled": "true",
|
|
10939
|
-
children: /* @__PURE__ */ (0,
|
|
11192
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { pointerEvents: "none" }, children })
|
|
10940
11193
|
}
|
|
10941
11194
|
);
|
|
10942
11195
|
}
|
|
10943
11196
|
|
|
10944
11197
|
// src/components/platform/ModeSwitch.tsx
|
|
10945
|
-
var
|
|
11198
|
+
var import_jsx_runtime83 = require("react/jsx-runtime");
|
|
10946
11199
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
10947
11200
|
const mode2 = useRuntimeMode();
|
|
10948
11201
|
const panel = useInlinePanel();
|
|
@@ -10954,8 +11207,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
10954
11207
|
RuntimeKit.setMode(next);
|
|
10955
11208
|
setOpen(false);
|
|
10956
11209
|
};
|
|
10957
|
-
return /* @__PURE__ */ (0,
|
|
10958
|
-
/* @__PURE__ */ (0,
|
|
11210
|
+
return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
|
|
11211
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(
|
|
10959
11212
|
"button",
|
|
10960
11213
|
{
|
|
10961
11214
|
type: "button",
|
|
@@ -10965,29 +11218,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
10965
11218
|
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.",
|
|
10966
11219
|
className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
|
|
10967
11220
|
children: [
|
|
10968
|
-
/* @__PURE__ */ (0,
|
|
10969
|
-
test && requestCount ? /* @__PURE__ */ (0,
|
|
11221
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
|
|
11222
|
+
test && requestCount ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
|
|
10970
11223
|
]
|
|
10971
11224
|
}
|
|
10972
11225
|
),
|
|
10973
|
-
open2 ? /* @__PURE__ */ (0,
|
|
10974
|
-
/* @__PURE__ */ (0,
|
|
10975
|
-
/* @__PURE__ */ (0,
|
|
10976
|
-
/* @__PURE__ */ (0,
|
|
11226
|
+
open2 ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(InlinePanelLayers, { panel, children: /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-view-enter fd-mode-pop", style: { zIndex }, children: [
|
|
11227
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
11228
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
|
|
11229
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
|
|
10977
11230
|
test ? "Test mode" : "Live mode"
|
|
10978
11231
|
] }),
|
|
10979
|
-
test ? /* @__PURE__ */ (0,
|
|
11232
|
+
test ? /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
10980
11233
|
requestCount,
|
|
10981
11234
|
" simulated request",
|
|
10982
11235
|
requestCount === 1 ? "" : "s"
|
|
10983
11236
|
] }) : null,
|
|
10984
|
-
/* @__PURE__ */ (0,
|
|
10985
|
-
test && onClearLog ? /* @__PURE__ */ (0,
|
|
11237
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { style: { flex: 1 } }),
|
|
11238
|
+
test && onClearLog ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
|
|
10986
11239
|
] }),
|
|
10987
|
-
/* @__PURE__ */ (0,
|
|
10988
|
-
/* @__PURE__ */ (0,
|
|
10989
|
-
/* @__PURE__ */ (0,
|
|
10990
|
-
/* @__PURE__ */ (0,
|
|
11240
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
11241
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-body-sm fd-secondary", style: { display: "block", textWrap: "pretty" }, children: test ? "Every feature is usable and nothing is obstructed, but no response comes from a real service \u2014 nothing you do here persists. Use this to review and demo the design." : "This is what a user would see today. " + s.incomplete + " of " + s.total + " features depend on backend work that is not wired yet, so they render under construction." }),
|
|
11242
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
|
|
11243
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
10991
11244
|
s.endpointsWired,
|
|
10992
11245
|
" endpoint",
|
|
10993
11246
|
s.endpointsWired === 1 ? "" : "s",
|
|
@@ -10997,58 +11250,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
10997
11250
|
s.total,
|
|
10998
11251
|
" features complete"
|
|
10999
11252
|
] }),
|
|
11000
|
-
onOpenSpec ? /* @__PURE__ */ (0,
|
|
11001
|
-
/* @__PURE__ */ (0,
|
|
11002
|
-
/* @__PURE__ */ (0,
|
|
11253
|
+
onOpenSpec ? /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(import_jsx_runtime83.Fragment, { children: [
|
|
11254
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { style: { flex: 1 } }),
|
|
11255
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => {
|
|
11003
11256
|
setOpen(false);
|
|
11004
11257
|
onOpenSpec();
|
|
11005
11258
|
}, children: [
|
|
11006
11259
|
"API spec ",
|
|
11007
|
-
/* @__PURE__ */ (0,
|
|
11260
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
11008
11261
|
] })
|
|
11009
11262
|
] }) : null
|
|
11010
11263
|
] })
|
|
11011
11264
|
] }),
|
|
11012
|
-
/* @__PURE__ */ (0,
|
|
11013
|
-
/* @__PURE__ */ (0,
|
|
11014
|
-
/* @__PURE__ */ (0,
|
|
11015
|
-
/* @__PURE__ */ (0,
|
|
11016
|
-
/* @__PURE__ */ (0,
|
|
11017
|
-
/* @__PURE__ */ (0,
|
|
11265
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-mode-choice", children: [
|
|
11266
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
|
|
11267
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
11268
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-mode-opt-text", children: [
|
|
11269
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-mode-opt-title", children: "Live mode" }),
|
|
11270
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
|
|
11018
11271
|
] }),
|
|
11019
|
-
!test ? /* @__PURE__ */ (0,
|
|
11272
|
+
!test ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
11020
11273
|
] }),
|
|
11021
|
-
/* @__PURE__ */ (0,
|
|
11022
|
-
/* @__PURE__ */ (0,
|
|
11023
|
-
/* @__PURE__ */ (0,
|
|
11024
|
-
/* @__PURE__ */ (0,
|
|
11025
|
-
/* @__PURE__ */ (0,
|
|
11274
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
|
|
11275
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
11276
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-mode-opt-text", children: [
|
|
11277
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-mode-opt-title", children: "Test mode" }),
|
|
11278
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
|
|
11026
11279
|
] }),
|
|
11027
|
-
test ? /* @__PURE__ */ (0,
|
|
11280
|
+
test ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
11028
11281
|
] })
|
|
11029
11282
|
] }),
|
|
11030
|
-
test && renderLog ? /* @__PURE__ */ (0,
|
|
11283
|
+
test && renderLog ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
|
|
11031
11284
|
] }) }) : null
|
|
11032
11285
|
] });
|
|
11033
11286
|
}
|
|
11034
11287
|
function TestModeBar({ onExit }) {
|
|
11035
11288
|
const mode2 = useRuntimeMode();
|
|
11036
11289
|
if (mode2 !== "test") return null;
|
|
11037
|
-
return /* @__PURE__ */ (0,
|
|
11038
|
-
/* @__PURE__ */ (0,
|
|
11039
|
-
/* @__PURE__ */ (0,
|
|
11290
|
+
return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "fd-testbar", role: "status", children: [
|
|
11291
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-badge fd-badge-warning", children: [
|
|
11292
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
11040
11293
|
"Test mode"
|
|
11041
11294
|
] }),
|
|
11042
|
-
/* @__PURE__ */ (0,
|
|
11043
|
-
/* @__PURE__ */ (0,
|
|
11044
|
-
/* @__PURE__ */ (0,
|
|
11295
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
|
|
11296
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
|
|
11297
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
11045
11298
|
" Back to live mode"
|
|
11046
11299
|
] })
|
|
11047
11300
|
] });
|
|
11048
11301
|
}
|
|
11049
11302
|
|
|
11050
11303
|
// src/components/planner/ChannelMeta.tsx
|
|
11051
|
-
var
|
|
11304
|
+
var import_jsx_runtime84 = require("react/jsx-runtime");
|
|
11052
11305
|
var CHANNEL_WEIGHTS = {
|
|
11053
11306
|
"OOH": 50,
|
|
11054
11307
|
"DOOH": 50,
|
|
@@ -11101,9 +11354,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
11101
11354
|
const m = ChannelMeta(channel);
|
|
11102
11355
|
const wt = channelWeightOf(channel || "");
|
|
11103
11356
|
if (dot) {
|
|
11104
|
-
return /* @__PURE__ */ (0,
|
|
11357
|
+
return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
|
|
11105
11358
|
}
|
|
11106
|
-
return /* @__PURE__ */ (0,
|
|
11359
|
+
return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(
|
|
11107
11360
|
"span",
|
|
11108
11361
|
{
|
|
11109
11362
|
className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
|
|
@@ -11111,16 +11364,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
11111
11364
|
style: { "--chan": m.color },
|
|
11112
11365
|
...rest,
|
|
11113
11366
|
children: [
|
|
11114
|
-
/* @__PURE__ */ (0,
|
|
11115
|
-
showLabel ? /* @__PURE__ */ (0,
|
|
11116
|
-
weight ? /* @__PURE__ */ (0,
|
|
11367
|
+
/* @__PURE__ */ (0, import_jsx_runtime84.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
|
|
11368
|
+
showLabel ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-chan-label", children: m.label }) : null,
|
|
11369
|
+
weight ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-chan-weight", children: wt || 0 }) : null
|
|
11117
11370
|
]
|
|
11118
11371
|
}
|
|
11119
11372
|
);
|
|
11120
11373
|
}
|
|
11121
11374
|
|
|
11122
11375
|
// src/components/planner/SaturationDistribution.tsx
|
|
11123
|
-
var
|
|
11376
|
+
var import_jsx_runtime85 = require("react/jsx-runtime");
|
|
11124
11377
|
var BANDS2 = [
|
|
11125
11378
|
{ key: "weak", label: "Weak", n: 1, range: "< 50" },
|
|
11126
11379
|
{ key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
|
|
@@ -11131,24 +11384,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11131
11384
|
const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
|
|
11132
11385
|
const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
|
|
11133
11386
|
const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
|
|
11134
|
-
return /* @__PURE__ */ (0,
|
|
11135
|
-
/* @__PURE__ */ (0,
|
|
11387
|
+
return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
11388
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
|
|
11136
11389
|
const mark = "var(--csi-" + g.n + "-mark)";
|
|
11137
11390
|
const active = selectedBand === g.key;
|
|
11138
|
-
return /* @__PURE__ */ (0,
|
|
11391
|
+
return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
|
|
11139
11392
|
"button",
|
|
11140
11393
|
{
|
|
11141
11394
|
type: "button",
|
|
11142
11395
|
onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
|
|
11143
11396
|
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)" },
|
|
11144
11397
|
children: [
|
|
11145
|
-
/* @__PURE__ */ (0,
|
|
11398
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
|
|
11146
11399
|
// `overflow: hidden` + `white-space: nowrap` only clips once the span
|
|
11147
11400
|
// actually HAS a bounded width to clip against (see the grid/flex
|
|
11148
11401
|
// `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
|
|
11149
11402
|
// that clip readable instead of a hard cut mid-letter; the full name
|
|
11150
11403
|
// is still one hover away via `title`.
|
|
11151
|
-
/* @__PURE__ */ (0,
|
|
11404
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
|
|
11152
11405
|
"span",
|
|
11153
11406
|
{
|
|
11154
11407
|
title: c.name + " \xB7 " + c.crp,
|
|
@@ -11158,13 +11411,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11158
11411
|
c.name
|
|
11159
11412
|
)
|
|
11160
11413
|
)) }),
|
|
11161
|
-
/* @__PURE__ */ (0,
|
|
11162
|
-
/* @__PURE__ */ (0,
|
|
11163
|
-
/* @__PURE__ */ (0,
|
|
11414
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
|
|
11415
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
|
|
11416
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
|
|
11164
11417
|
] }),
|
|
11165
|
-
/* @__PURE__ */ (0,
|
|
11166
|
-
/* @__PURE__ */ (0,
|
|
11167
|
-
/* @__PURE__ */ (0,
|
|
11418
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-stack", style: { gap: 1 }, children: [
|
|
11419
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-label-lg", children: g.label }),
|
|
11420
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
|
|
11168
11421
|
"CRP ",
|
|
11169
11422
|
g.range
|
|
11170
11423
|
] })
|
|
@@ -11174,10 +11427,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11174
11427
|
g.key
|
|
11175
11428
|
);
|
|
11176
11429
|
}) }),
|
|
11177
|
-
floorBand ? /* @__PURE__ */ (0,
|
|
11178
|
-
/* @__PURE__ */ (0,
|
|
11179
|
-
/* @__PURE__ */ (0,
|
|
11180
|
-
/* @__PURE__ */ (0,
|
|
11430
|
+
floorBand ? /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderRadius: "var(--r-md)", background: "var(--surface-2)", border: "1px solid var(--border)", flexWrap: "wrap" }, children: [
|
|
11431
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
|
|
11432
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
|
|
11433
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("strong", { style: { color: "var(--text)" }, children: [
|
|
11181
11434
|
"Plan floor ",
|
|
11182
11435
|
floorScore
|
|
11183
11436
|
] }),
|
|
@@ -11188,8 +11441,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11188
11441
|
}
|
|
11189
11442
|
|
|
11190
11443
|
// src/components/planner/MixGap.tsx
|
|
11191
|
-
var
|
|
11192
|
-
var
|
|
11444
|
+
var React56 = __toESM(require("react"), 1);
|
|
11445
|
+
var import_jsx_runtime86 = require("react/jsx-runtime");
|
|
11193
11446
|
var MIX_GAP_LAYOUT = {
|
|
11194
11447
|
trackHeight: 30,
|
|
11195
11448
|
barHeight: 20,
|
|
@@ -11203,19 +11456,19 @@ function mixGapOffset(value, max) {
|
|
|
11203
11456
|
}
|
|
11204
11457
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
11205
11458
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
11206
|
-
const [hover, setHover] =
|
|
11459
|
+
const [hover, setHover] = React56.useState(null);
|
|
11207
11460
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
11208
11461
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
11209
11462
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
11210
11463
|
const barTop = (trackHeight - barHeight) / 2;
|
|
11211
|
-
return /* @__PURE__ */ (0,
|
|
11212
|
-
/* @__PURE__ */ (0,
|
|
11213
|
-
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0,
|
|
11214
|
-
/* @__PURE__ */ (0,
|
|
11464
|
+
return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
|
|
11465
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
|
|
11466
|
+
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
11467
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
|
|
11215
11468
|
l
|
|
11216
11469
|
] }, l)),
|
|
11217
|
-
/* @__PURE__ */ (0,
|
|
11218
|
-
/* @__PURE__ */ (0,
|
|
11470
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
11471
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
|
|
11219
11472
|
"Target"
|
|
11220
11473
|
] })
|
|
11221
11474
|
] }),
|
|
@@ -11224,7 +11477,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11224
11477
|
const tone = toneOf(gap);
|
|
11225
11478
|
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 : "");
|
|
11226
11479
|
const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
|
|
11227
|
-
return /* @__PURE__ */ (0,
|
|
11480
|
+
return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
|
|
11228
11481
|
"div",
|
|
11229
11482
|
{
|
|
11230
11483
|
className: "fd-row",
|
|
@@ -11232,15 +11485,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11232
11485
|
onMouseEnter: () => setHover(r.channel),
|
|
11233
11486
|
onMouseLeave: () => setHover(null),
|
|
11234
11487
|
children: [
|
|
11235
|
-
/* @__PURE__ */ (0,
|
|
11236
|
-
/* @__PURE__ */ (0,
|
|
11237
|
-
/* @__PURE__ */ (0,
|
|
11238
|
-
/* @__PURE__ */ (0,
|
|
11239
|
-
/* @__PURE__ */ (0,
|
|
11488
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(ChannelTag, { channel: r.channel, size: "sm" }) }),
|
|
11489
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(import_jsx_runtime86.Fragment, { children: [
|
|
11490
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { "data-mixgap-bar": "", style: { position: "absolute", left: 0, top: barTop, height: barHeight, width: mixGapOffset(r.realized, max), background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
|
|
11491
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { "data-mixgap-target": "", style: { position: "absolute", left: `calc(${mixGapOffset(r.target, max)} - ${targetWidth / 2}px)`, top: 0, width: targetWidth, height: trackHeight, background: MIX_GAP_TARGET_STRIPE, borderRadius: 1 } }),
|
|
11492
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { "data-mixgap-label": "", className: "fd-num", style: { position: "absolute", left: labelLeft, top: "50%", transform: "translateY(-50%)", fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap" }, children: [
|
|
11240
11493
|
r.realized,
|
|
11241
11494
|
"%"
|
|
11242
11495
|
] }),
|
|
11243
|
-
hover === r.channel ? /* @__PURE__ */ (0,
|
|
11496
|
+
hover === r.channel ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: trackHeight + 4, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
|
|
11244
11497
|
] }) })
|
|
11245
11498
|
]
|
|
11246
11499
|
},
|
|
@@ -11251,7 +11504,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11251
11504
|
}
|
|
11252
11505
|
|
|
11253
11506
|
// src/components/planner/ChannelContribution.tsx
|
|
11254
|
-
var
|
|
11507
|
+
var import_jsx_runtime87 = require("react/jsx-runtime");
|
|
11255
11508
|
var money = (n) => "$" + Math.round(n).toLocaleString();
|
|
11256
11509
|
function ChannelContribution({
|
|
11257
11510
|
channels = [],
|
|
@@ -11267,9 +11520,9 @@ function ChannelContribution({
|
|
|
11267
11520
|
const grand = total !== void 0 ? total : base + bonus;
|
|
11268
11521
|
const pct = (v) => grand ? v / grand * 100 : 0;
|
|
11269
11522
|
const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
|
|
11270
|
-
return /* @__PURE__ */ (0,
|
|
11271
|
-
loading ? /* @__PURE__ */ (0,
|
|
11272
|
-
channels.map((c) => /* @__PURE__ */ (0,
|
|
11523
|
+
return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
11524
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
|
|
11525
|
+
channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
|
|
11273
11526
|
"span",
|
|
11274
11527
|
{
|
|
11275
11528
|
title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
|
|
@@ -11278,7 +11531,7 @@ function ChannelContribution({
|
|
|
11278
11531
|
},
|
|
11279
11532
|
c.name
|
|
11280
11533
|
)),
|
|
11281
|
-
bonus > 0 ? /* @__PURE__ */ (0,
|
|
11534
|
+
bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
|
|
11282
11535
|
"span",
|
|
11283
11536
|
{
|
|
11284
11537
|
title: "Surround-sound bonus +" + bonusPct + "%",
|
|
@@ -11287,18 +11540,18 @@ function ChannelContribution({
|
|
|
11287
11540
|
}
|
|
11288
11541
|
) : null
|
|
11289
11542
|
] }),
|
|
11290
|
-
showTable ? /* @__PURE__ */ (0,
|
|
11291
|
-
/* @__PURE__ */ (0,
|
|
11292
|
-
/* @__PURE__ */ (0,
|
|
11293
|
-
/* @__PURE__ */ (0,
|
|
11294
|
-
/* @__PURE__ */ (0,
|
|
11295
|
-
/* @__PURE__ */ (0,
|
|
11296
|
-
/* @__PURE__ */ (0,
|
|
11543
|
+
showTable ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
|
|
11544
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("tr", { children: [
|
|
11545
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("th", { style: { width: "34%" }, children: "Channel" }),
|
|
11546
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("th", { style: { width: "16%" }, children: "Weight" }),
|
|
11547
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
|
|
11548
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
|
|
11549
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
|
|
11297
11550
|
] }) }),
|
|
11298
|
-
/* @__PURE__ */ (0,
|
|
11299
|
-
channels.map((c) => /* @__PURE__ */ (0,
|
|
11300
|
-
/* @__PURE__ */ (0,
|
|
11301
|
-
/* @__PURE__ */ (0,
|
|
11551
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("tbody", { children: [
|
|
11552
|
+
channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("tr", { children: [
|
|
11553
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(ChannelTag, { channel: c.name, size: "sm" }) }),
|
|
11554
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
|
|
11302
11555
|
"span",
|
|
11303
11556
|
{
|
|
11304
11557
|
className: "fd-badge fd-badge-neutral",
|
|
@@ -11307,38 +11560,38 @@ function ChannelContribution({
|
|
|
11307
11560
|
children: "weight " + (channelWeightOf(c.name) || 0)
|
|
11308
11561
|
}
|
|
11309
11562
|
) }),
|
|
11310
|
-
/* @__PURE__ */ (0,
|
|
11311
|
-
/* @__PURE__ */ (0,
|
|
11312
|
-
/* @__PURE__ */ (0,
|
|
11563
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", children: c.spend }),
|
|
11564
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", children: c.crp.toFixed(1) }),
|
|
11565
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("td", { className: "is-num", children: [
|
|
11313
11566
|
pct(c.crp).toFixed(0),
|
|
11314
11567
|
"%"
|
|
11315
11568
|
] })
|
|
11316
11569
|
] }, c.name)),
|
|
11317
|
-
bonus > 0 ? /* @__PURE__ */ (0,
|
|
11318
|
-
/* @__PURE__ */ (0,
|
|
11319
|
-
/* @__PURE__ */ (0,
|
|
11570
|
+
bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("tr", { children: [
|
|
11571
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
|
|
11572
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { style: { width: 9, height: 9, borderRadius: 2, background: "repeating-linear-gradient(135deg,var(--csi-3-mark) 0 3px,var(--csi-2-mark) 3px 6px)", flex: "none" } }),
|
|
11320
11573
|
"Surround-sound bonus"
|
|
11321
11574
|
] }) }),
|
|
11322
|
-
/* @__PURE__ */ (0,
|
|
11575
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
|
|
11323
11576
|
"+",
|
|
11324
11577
|
bonusPct,
|
|
11325
11578
|
"% of +",
|
|
11326
11579
|
bonusMax,
|
|
11327
11580
|
"%"
|
|
11328
11581
|
] }) }),
|
|
11329
|
-
/* @__PURE__ */ (0,
|
|
11330
|
-
/* @__PURE__ */ (0,
|
|
11331
|
-
/* @__PURE__ */ (0,
|
|
11582
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num fd-muted", children: "\u2014" }),
|
|
11583
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", children: bonus.toFixed(1) }),
|
|
11584
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("td", { className: "is-num", children: [
|
|
11332
11585
|
pct(bonus).toFixed(0),
|
|
11333
11586
|
"%"
|
|
11334
11587
|
] })
|
|
11335
11588
|
] }) : null,
|
|
11336
|
-
/* @__PURE__ */ (0,
|
|
11337
|
-
/* @__PURE__ */ (0,
|
|
11338
|
-
/* @__PURE__ */ (0,
|
|
11339
|
-
/* @__PURE__ */ (0,
|
|
11340
|
-
/* @__PURE__ */ (0,
|
|
11341
|
-
/* @__PURE__ */ (0,
|
|
11589
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("tr", { style: { background: "var(--surface-2)" }, children: [
|
|
11590
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { style: { fontWeight: 700 }, children: "Campus total" }),
|
|
11591
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", {}),
|
|
11592
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
|
|
11593
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
|
|
11594
|
+
/* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
|
|
11342
11595
|
] })
|
|
11343
11596
|
] })
|
|
11344
11597
|
] }) : null
|
|
@@ -11346,8 +11599,8 @@ function ChannelContribution({
|
|
|
11346
11599
|
}
|
|
11347
11600
|
|
|
11348
11601
|
// src/components/planner/BudgetReallocator.tsx
|
|
11349
|
-
var
|
|
11350
|
-
var
|
|
11602
|
+
var React57 = __toESM(require("react"), 1);
|
|
11603
|
+
var import_jsx_runtime88 = require("react/jsx-runtime");
|
|
11351
11604
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
11352
11605
|
function BudgetReallocator({
|
|
11353
11606
|
campus,
|
|
@@ -11362,8 +11615,8 @@ function BudgetReallocator({
|
|
|
11362
11615
|
onCancel,
|
|
11363
11616
|
className = ""
|
|
11364
11617
|
}) {
|
|
11365
|
-
const [draft, setDraft] =
|
|
11366
|
-
|
|
11618
|
+
const [draft, setDraft] = React57.useState(spend);
|
|
11619
|
+
React57.useEffect(() => setDraft(spend), [spend]);
|
|
11367
11620
|
const dirty = draft !== spend;
|
|
11368
11621
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
11369
11622
|
const nextBand = bandFor(nextCrp);
|
|
@@ -11378,10 +11631,10 @@ function BudgetReallocator({
|
|
|
11378
11631
|
setDraft(spend);
|
|
11379
11632
|
if (onCancel) onCancel();
|
|
11380
11633
|
};
|
|
11381
|
-
const trackRef =
|
|
11382
|
-
const chipRef =
|
|
11383
|
-
const [chipLeft, setChipLeft] =
|
|
11384
|
-
|
|
11634
|
+
const trackRef = React57.useRef(null);
|
|
11635
|
+
const chipRef = React57.useRef(null);
|
|
11636
|
+
const [chipLeft, setChipLeft] = React57.useState(null);
|
|
11637
|
+
React57.useLayoutEffect(() => {
|
|
11385
11638
|
const track = trackRef.current;
|
|
11386
11639
|
if (!dirty || !track) {
|
|
11387
11640
|
setChipLeft(null);
|
|
@@ -11402,23 +11655,23 @@ function BudgetReallocator({
|
|
|
11402
11655
|
ro.observe(track);
|
|
11403
11656
|
return () => ro.disconnect();
|
|
11404
11657
|
}, [dirty, pct]);
|
|
11405
|
-
return /* @__PURE__ */ (0,
|
|
11658
|
+
return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(
|
|
11406
11659
|
"div",
|
|
11407
11660
|
{
|
|
11408
11661
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
11409
11662
|
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)" },
|
|
11410
11663
|
children: [
|
|
11411
|
-
/* @__PURE__ */ (0,
|
|
11412
|
-
/* @__PURE__ */ (0,
|
|
11413
|
-
/* @__PURE__ */ (0,
|
|
11414
|
-
dirty ? /* @__PURE__ */ (0,
|
|
11415
|
-
/* @__PURE__ */ (0,
|
|
11416
|
-
/* @__PURE__ */ (0,
|
|
11664
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
11665
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
|
|
11666
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)(CsiBadge, { band: nowBand, crp, size: "medium" }),
|
|
11667
|
+
dirty ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(import_jsx_runtime88.Fragment, { children: [
|
|
11668
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
|
|
11669
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
|
|
11417
11670
|
] }) : null
|
|
11418
11671
|
] }),
|
|
11419
|
-
/* @__PURE__ */ (0,
|
|
11420
|
-
/* @__PURE__ */ (0,
|
|
11421
|
-
dirty ? /* @__PURE__ */ (0,
|
|
11672
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-slider", ref: trackRef, children: [
|
|
11673
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
11674
|
+
dirty ? /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
|
|
11422
11675
|
"span",
|
|
11423
11676
|
{
|
|
11424
11677
|
ref: chipRef,
|
|
@@ -11430,7 +11683,7 @@ function BudgetReallocator({
|
|
|
11430
11683
|
children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
|
|
11431
11684
|
}
|
|
11432
11685
|
) : null,
|
|
11433
|
-
/* @__PURE__ */ (0,
|
|
11686
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
|
|
11434
11687
|
"input",
|
|
11435
11688
|
{
|
|
11436
11689
|
type: "range",
|
|
@@ -11446,13 +11699,13 @@ function BudgetReallocator({
|
|
|
11446
11699
|
}
|
|
11447
11700
|
)
|
|
11448
11701
|
] }),
|
|
11449
|
-
/* @__PURE__ */ (0,
|
|
11450
|
-
/* @__PURE__ */ (0,
|
|
11451
|
-
/* @__PURE__ */ (0,
|
|
11452
|
-
/* @__PURE__ */ (0,
|
|
11702
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
11703
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
|
|
11704
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
|
|
11705
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
|
|
11453
11706
|
] }),
|
|
11454
|
-
/* @__PURE__ */ (0,
|
|
11455
|
-
/* @__PURE__ */ (0,
|
|
11707
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
|
|
11708
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
|
|
11456
11709
|
"button",
|
|
11457
11710
|
{
|
|
11458
11711
|
type: "button",
|
|
@@ -11471,7 +11724,7 @@ function BudgetReallocator({
|
|
|
11471
11724
|
}
|
|
11472
11725
|
|
|
11473
11726
|
// src/components/planner/SurroundSound.tsx
|
|
11474
|
-
var
|
|
11727
|
+
var import_jsx_runtime89 = require("react/jsx-runtime");
|
|
11475
11728
|
var CATEGORIES = [
|
|
11476
11729
|
{ key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
|
|
11477
11730
|
{ key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
|
|
@@ -11483,26 +11736,26 @@ var CATEGORIES = [
|
|
|
11483
11736
|
function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
|
|
11484
11737
|
const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
|
|
11485
11738
|
const single = present.length <= 2;
|
|
11486
|
-
return /* @__PURE__ */ (0,
|
|
11487
|
-
/* @__PURE__ */ (0,
|
|
11739
|
+
return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
|
|
11740
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
|
|
11488
11741
|
const on = present.includes(c.key);
|
|
11489
|
-
return /* @__PURE__ */ (0,
|
|
11742
|
+
return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
|
|
11490
11743
|
"span",
|
|
11491
11744
|
{
|
|
11492
11745
|
title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
|
|
11493
11746
|
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)" },
|
|
11494
11747
|
children: [
|
|
11495
|
-
/* @__PURE__ */ (0,
|
|
11496
|
-
/* @__PURE__ */ (0,
|
|
11748
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
11749
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
|
|
11497
11750
|
]
|
|
11498
11751
|
},
|
|
11499
11752
|
c.key
|
|
11500
11753
|
);
|
|
11501
11754
|
}) }),
|
|
11502
|
-
/* @__PURE__ */ (0,
|
|
11503
|
-
/* @__PURE__ */ (0,
|
|
11504
|
-
/* @__PURE__ */ (0,
|
|
11505
|
-
/* @__PURE__ */ (0,
|
|
11755
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
11756
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
11757
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
|
|
11758
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
|
|
11506
11759
|
"+",
|
|
11507
11760
|
bonusPct,
|
|
11508
11761
|
"% of +",
|
|
@@ -11510,8 +11763,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
11510
11763
|
"%"
|
|
11511
11764
|
] })
|
|
11512
11765
|
] }),
|
|
11513
|
-
/* @__PURE__ */ (0,
|
|
11514
|
-
/* @__PURE__ */ (0,
|
|
11766
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
|
|
11767
|
+
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
|
|
11515
11768
|
present.length,
|
|
11516
11769
|
" of 6 channel categories present.",
|
|
11517
11770
|
" ",
|
|
@@ -11523,7 +11776,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
11523
11776
|
}
|
|
11524
11777
|
|
|
11525
11778
|
// src/components/planner/Importance.tsx
|
|
11526
|
-
var
|
|
11779
|
+
var import_jsx_runtime90 = require("react/jsx-runtime");
|
|
11527
11780
|
var IMPORTANCE_LEVELS = [
|
|
11528
11781
|
{ id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
|
|
11529
11782
|
{ id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
|
|
@@ -11553,7 +11806,7 @@ function importanceTokens(id) {
|
|
|
11553
11806
|
function ImportanceTag({ level, showLabel = true, size = "sm", className = "", disabled = false }) {
|
|
11554
11807
|
const lvl = importanceLevel(level);
|
|
11555
11808
|
const t = importanceTokens(level);
|
|
11556
|
-
return /* @__PURE__ */ (0,
|
|
11809
|
+
return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(
|
|
11557
11810
|
"span",
|
|
11558
11811
|
{
|
|
11559
11812
|
className: ["fd-imp-tag", size === "md" ? "is-md" : "", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "),
|
|
@@ -11561,16 +11814,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
|
|
|
11561
11814
|
title: lvl.label + " \u2014 " + lvl.description,
|
|
11562
11815
|
"aria-disabled": disabled ? "true" : void 0,
|
|
11563
11816
|
children: [
|
|
11564
|
-
/* @__PURE__ */ (0,
|
|
11565
|
-
showLabel ? lvl.label : /* @__PURE__ */ (0,
|
|
11817
|
+
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
|
|
11818
|
+
showLabel ? lvl.label : /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-sr", children: lvl.label })
|
|
11566
11819
|
]
|
|
11567
11820
|
}
|
|
11568
11821
|
);
|
|
11569
11822
|
}
|
|
11570
11823
|
|
|
11571
11824
|
// src/components/planner/PreferenceMeter.tsx
|
|
11572
|
-
var
|
|
11573
|
-
var
|
|
11825
|
+
var React58 = __toESM(require("react"), 1);
|
|
11826
|
+
var import_jsx_runtime91 = require("react/jsx-runtime");
|
|
11574
11827
|
function preferenceScore(criteria) {
|
|
11575
11828
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
11576
11829
|
const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
|
|
@@ -11599,8 +11852,8 @@ function PreferenceMeter({
|
|
|
11599
11852
|
className = ""
|
|
11600
11853
|
}) {
|
|
11601
11854
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
11602
|
-
const segments =
|
|
11603
|
-
return /* @__PURE__ */ (0,
|
|
11855
|
+
const segments = React58.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
11856
|
+
return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
|
|
11604
11857
|
ScoreMeter,
|
|
11605
11858
|
{
|
|
11606
11859
|
score: value,
|
|
@@ -11612,22 +11865,22 @@ function PreferenceMeter({
|
|
|
11612
11865
|
placement,
|
|
11613
11866
|
className,
|
|
11614
11867
|
breakdownLabel: breakdownTitle,
|
|
11615
|
-
breakdown: /* @__PURE__ */ (0,
|
|
11616
|
-
/* @__PURE__ */ (0,
|
|
11617
|
-
/* @__PURE__ */ (0,
|
|
11618
|
-
/* @__PURE__ */ (0,
|
|
11868
|
+
breakdown: /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fd-prefbreak", children: [
|
|
11869
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fd-prefbreak-head", children: [
|
|
11870
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-label-lg", children: breakdownTitle }),
|
|
11871
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
|
|
11619
11872
|
] }),
|
|
11620
|
-
/* @__PURE__ */ (0,
|
|
11873
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
|
|
11621
11874
|
const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
|
|
11622
|
-
return /* @__PURE__ */ (0,
|
|
11623
|
-
/* @__PURE__ */ (0,
|
|
11624
|
-
/* @__PURE__ */ (0,
|
|
11625
|
-
/* @__PURE__ */ (0,
|
|
11626
|
-
c.note ? /* @__PURE__ */ (0,
|
|
11875
|
+
return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
|
|
11876
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)(ImportanceTag, { level: c.importance }),
|
|
11877
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fd-prefbreak-text", children: [
|
|
11878
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-prefbreak-label", children: c.label }),
|
|
11879
|
+
c.note ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-prefbreak-note", children: c.note }) : null
|
|
11627
11880
|
] }),
|
|
11628
|
-
/* @__PURE__ */ (0,
|
|
11881
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fd-prefbreak-val fd-tabular", children: [
|
|
11629
11882
|
Math.round(Number(c.earned) || 0),
|
|
11630
|
-
/* @__PURE__ */ (0,
|
|
11883
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-prefbreak-sep", children: "/" }),
|
|
11631
11884
|
Math.round(c.weight)
|
|
11632
11885
|
] })
|
|
11633
11886
|
] }, c.id);
|
|
@@ -11638,10 +11891,10 @@ function PreferenceMeter({
|
|
|
11638
11891
|
}
|
|
11639
11892
|
|
|
11640
11893
|
// src/components/chat/AgentChatPanel.tsx
|
|
11641
|
-
var
|
|
11894
|
+
var React64 = __toESM(require("react"), 1);
|
|
11642
11895
|
|
|
11643
11896
|
// src/components/chat/chatEngine.ts
|
|
11644
|
-
var
|
|
11897
|
+
var React59 = __toESM(require("react"), 1);
|
|
11645
11898
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
11646
11899
|
var JOB_PENDING = ["queued", "running"];
|
|
11647
11900
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -11695,22 +11948,22 @@ function useChatEngine(opts) {
|
|
|
11695
11948
|
onClear,
|
|
11696
11949
|
onFeedback
|
|
11697
11950
|
} = opts || {};
|
|
11698
|
-
const [status, setStatus] =
|
|
11699
|
-
const [threadId, setThreadId] =
|
|
11700
|
-
const [messages, setMessages] =
|
|
11701
|
-
const [queue, setQueue] =
|
|
11702
|
-
const [fatal, setFatal] =
|
|
11703
|
-
const [busy, setBusy] =
|
|
11704
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
11705
|
-
const listRef =
|
|
11706
|
-
const queueRef =
|
|
11707
|
-
const busyRef =
|
|
11708
|
-
const stoppedRef =
|
|
11709
|
-
const abortRef =
|
|
11710
|
-
const serverCount =
|
|
11711
|
-
const threadRef =
|
|
11712
|
-
const mounted =
|
|
11713
|
-
|
|
11951
|
+
const [status, setStatus] = React59.useState("idle");
|
|
11952
|
+
const [threadId, setThreadId] = React59.useState(null);
|
|
11953
|
+
const [messages, setMessages] = React59.useState([]);
|
|
11954
|
+
const [queue, setQueue] = React59.useState([]);
|
|
11955
|
+
const [fatal, setFatal] = React59.useState(null);
|
|
11956
|
+
const [busy, setBusy] = React59.useState(false);
|
|
11957
|
+
const [turnStartedAt, setTurnStartedAt] = React59.useState(null);
|
|
11958
|
+
const listRef = React59.useRef([]);
|
|
11959
|
+
const queueRef = React59.useRef([]);
|
|
11960
|
+
const busyRef = React59.useRef(false);
|
|
11961
|
+
const stoppedRef = React59.useRef(false);
|
|
11962
|
+
const abortRef = React59.useRef(null);
|
|
11963
|
+
const serverCount = React59.useRef(0);
|
|
11964
|
+
const threadRef = React59.useRef(null);
|
|
11965
|
+
const mounted = React59.useRef(true);
|
|
11966
|
+
React59.useEffect(() => {
|
|
11714
11967
|
mounted.current = true;
|
|
11715
11968
|
return () => {
|
|
11716
11969
|
mounted.current = false;
|
|
@@ -11732,14 +11985,14 @@ function useChatEngine(opts) {
|
|
|
11732
11985
|
}
|
|
11733
11986
|
return false;
|
|
11734
11987
|
};
|
|
11735
|
-
const loadThread =
|
|
11988
|
+
const loadThread = React59.useCallback(async (id) => {
|
|
11736
11989
|
const data = await apiAdapter.getThread(id);
|
|
11737
11990
|
const list = [...data && data.messages || []];
|
|
11738
11991
|
serverCount.current = list.length;
|
|
11739
11992
|
commit(list);
|
|
11740
11993
|
return list;
|
|
11741
11994
|
}, [apiAdapter]);
|
|
11742
|
-
|
|
11995
|
+
React59.useEffect(() => {
|
|
11743
11996
|
if (!apiAdapter) {
|
|
11744
11997
|
setStatus("idle");
|
|
11745
11998
|
setFatal(null);
|
|
@@ -11952,7 +12205,7 @@ function useChatEngine(opts) {
|
|
|
11952
12205
|
await dispatchTurn(turn);
|
|
11953
12206
|
}
|
|
11954
12207
|
}
|
|
11955
|
-
const send =
|
|
12208
|
+
const send = React59.useCallback((text, attachments) => {
|
|
11956
12209
|
const body = (text || "").trim();
|
|
11957
12210
|
if (!body && !(attachments && attachments.length)) return;
|
|
11958
12211
|
if (status === "disconnected") return;
|
|
@@ -11962,7 +12215,7 @@ function useChatEngine(opts) {
|
|
|
11962
12215
|
stoppedRef.current = false;
|
|
11963
12216
|
drain();
|
|
11964
12217
|
}, [status]);
|
|
11965
|
-
const stop =
|
|
12218
|
+
const stop = React59.useCallback(() => {
|
|
11966
12219
|
stoppedRef.current = true;
|
|
11967
12220
|
const ac = abortRef.current;
|
|
11968
12221
|
if (ac) {
|
|
@@ -11981,11 +12234,11 @@ function useChatEngine(opts) {
|
|
|
11981
12234
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
11982
12235
|
}
|
|
11983
12236
|
}, [apiAdapter]);
|
|
11984
|
-
const removeQueued =
|
|
12237
|
+
const removeQueued = React59.useCallback((id) => {
|
|
11985
12238
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
11986
12239
|
setQueue(queueRef.current.slice());
|
|
11987
12240
|
}, []);
|
|
11988
|
-
const retry =
|
|
12241
|
+
const retry = React59.useCallback(() => {
|
|
11989
12242
|
const list = listRef.current;
|
|
11990
12243
|
let at = -1;
|
|
11991
12244
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -12001,19 +12254,19 @@ function useChatEngine(opts) {
|
|
|
12001
12254
|
setQueue(queueRef.current.slice());
|
|
12002
12255
|
drain();
|
|
12003
12256
|
}, []);
|
|
12004
|
-
const clear =
|
|
12257
|
+
const clear = React59.useCallback(() => {
|
|
12005
12258
|
commit([]);
|
|
12006
12259
|
serverCount.current = 0;
|
|
12007
12260
|
queueRef.current = [];
|
|
12008
12261
|
setQueue([]);
|
|
12009
12262
|
onClear && onClear();
|
|
12010
12263
|
}, [onClear]);
|
|
12011
|
-
const setFeedback =
|
|
12264
|
+
const setFeedback = React59.useCallback((id, value) => {
|
|
12012
12265
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
12013
12266
|
const msg = listRef.current.find((m) => m.id === id);
|
|
12014
12267
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
12015
12268
|
}, [onFeedback]);
|
|
12016
|
-
const reload =
|
|
12269
|
+
const reload = React59.useCallback(async () => {
|
|
12017
12270
|
if (!threadRef.current) return;
|
|
12018
12271
|
setStatus("loading");
|
|
12019
12272
|
try {
|
|
@@ -12051,11 +12304,11 @@ var ChatKit = {
|
|
|
12051
12304
|
};
|
|
12052
12305
|
|
|
12053
12306
|
// src/components/chat/ChatTranscript.tsx
|
|
12054
|
-
var
|
|
12307
|
+
var React61 = __toESM(require("react"), 1);
|
|
12055
12308
|
|
|
12056
12309
|
// src/components/chat/ChatTurn.tsx
|
|
12057
|
-
var
|
|
12058
|
-
var
|
|
12310
|
+
var React60 = __toESM(require("react"), 1);
|
|
12311
|
+
var import_jsx_runtime92 = require("react/jsx-runtime");
|
|
12059
12312
|
function JsonView({ value }) {
|
|
12060
12313
|
let text;
|
|
12061
12314
|
try {
|
|
@@ -12063,67 +12316,67 @@ function JsonView({ value }) {
|
|
|
12063
12316
|
} catch (e) {
|
|
12064
12317
|
text = String(value);
|
|
12065
12318
|
}
|
|
12066
|
-
return /* @__PURE__ */ (0,
|
|
12319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
|
|
12067
12320
|
}
|
|
12068
12321
|
function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
12069
12322
|
if (!packet) return null;
|
|
12070
12323
|
const s = schema || {};
|
|
12071
12324
|
const invalid = packet.valid === false;
|
|
12072
12325
|
const title = s.heading || packet.type;
|
|
12073
|
-
return /* @__PURE__ */ (0,
|
|
12074
|
-
/* @__PURE__ */ (0,
|
|
12075
|
-
/* @__PURE__ */ (0,
|
|
12076
|
-
/* @__PURE__ */ (0,
|
|
12077
|
-
packet.repaired ? /* @__PURE__ */ (0,
|
|
12078
|
-
invalid ? /* @__PURE__ */ (0,
|
|
12326
|
+
return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
|
|
12327
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("header", { className: "fdc-packet-head", children: [
|
|
12328
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
|
|
12329
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
|
|
12330
|
+
packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
|
|
12331
|
+
invalid ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
|
|
12079
12332
|
] }),
|
|
12080
|
-
invalid ? /* @__PURE__ */ (0,
|
|
12081
|
-
/* @__PURE__ */ (0,
|
|
12082
|
-
/* @__PURE__ */ (0,
|
|
12083
|
-
] }) : /* @__PURE__ */ (0,
|
|
12084
|
-
!invalid && onApply ? /* @__PURE__ */ (0,
|
|
12085
|
-
packet.repaired ? /* @__PURE__ */ (0,
|
|
12086
|
-
/* @__PURE__ */ (0,
|
|
12087
|
-
/* @__PURE__ */ (0,
|
|
12333
|
+
invalid ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-packet-alert", role: "alert", children: [
|
|
12334
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
12335
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
|
|
12336
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(JsonView, { value: packet.payload }) }),
|
|
12337
|
+
!invalid && onApply ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("footer", { className: "fdc-packet-foot", children: [
|
|
12338
|
+
packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {}),
|
|
12339
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
|
|
12340
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
|
|
12088
12341
|
applied ? "Applied" : s.applyLabel || "Apply"
|
|
12089
12342
|
] })
|
|
12090
12343
|
] }) : null
|
|
12091
12344
|
] });
|
|
12092
12345
|
}
|
|
12093
12346
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
12094
|
-
const [open2, setOpen] =
|
|
12347
|
+
const [open2, setOpen] = React60.useState(defaultOpen);
|
|
12095
12348
|
if (!text) return null;
|
|
12096
|
-
return /* @__PURE__ */ (0,
|
|
12097
|
-
/* @__PURE__ */ (0,
|
|
12098
|
-
/* @__PURE__ */ (0,
|
|
12099
|
-
/* @__PURE__ */ (0,
|
|
12100
|
-
streaming ? /* @__PURE__ */ (0,
|
|
12101
|
-
/* @__PURE__ */ (0,
|
|
12102
|
-
/* @__PURE__ */ (0,
|
|
12103
|
-
/* @__PURE__ */ (0,
|
|
12349
|
+
return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
|
|
12350
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
12351
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-brain", "aria-hidden": "true" }),
|
|
12352
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
|
|
12353
|
+
streaming ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
12354
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {}),
|
|
12355
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {}),
|
|
12356
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {})
|
|
12104
12357
|
] }) : null,
|
|
12105
|
-
/* @__PURE__ */ (0,
|
|
12358
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
|
|
12106
12359
|
] }),
|
|
12107
|
-
open2 ? /* @__PURE__ */ (0,
|
|
12360
|
+
open2 ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-think-body", children: text }) : null
|
|
12108
12361
|
] });
|
|
12109
12362
|
}
|
|
12110
12363
|
function Citations({ items = [], onOpen }) {
|
|
12111
|
-
const [open2, setOpen] =
|
|
12364
|
+
const [open2, setOpen] = React60.useState(false);
|
|
12112
12365
|
if (!items.length) return null;
|
|
12113
|
-
return /* @__PURE__ */ (0,
|
|
12114
|
-
/* @__PURE__ */ (0,
|
|
12115
|
-
/* @__PURE__ */ (0,
|
|
12116
|
-
/* @__PURE__ */ (0,
|
|
12366
|
+
return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-cites", children: [
|
|
12367
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
12368
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
|
|
12369
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { children: [
|
|
12117
12370
|
items.length,
|
|
12118
12371
|
" source",
|
|
12119
12372
|
items.length === 1 ? "" : "s"
|
|
12120
12373
|
] }),
|
|
12121
|
-
/* @__PURE__ */ (0,
|
|
12374
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
|
|
12122
12375
|
] }),
|
|
12123
|
-
open2 ? /* @__PURE__ */ (0,
|
|
12124
|
-
/* @__PURE__ */ (0,
|
|
12125
|
-
c.url ? /* @__PURE__ */ (0,
|
|
12126
|
-
c.detail ? /* @__PURE__ */ (0,
|
|
12376
|
+
open2 ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("li", { children: [
|
|
12377
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
|
|
12378
|
+
c.url ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { children: c.title || "Source" }),
|
|
12379
|
+
c.detail ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-cite-detail", children: c.detail }) : null
|
|
12127
12380
|
] }, c.id || i)) }) : null
|
|
12128
12381
|
] });
|
|
12129
12382
|
}
|
|
@@ -12134,29 +12387,29 @@ function clampText(text, max) {
|
|
|
12134
12387
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
12135
12388
|
}
|
|
12136
12389
|
function MessageBody({ message: m, ctx }) {
|
|
12137
|
-
const [expanded, setExpanded] =
|
|
12390
|
+
const [expanded, setExpanded] = React60.useState(false);
|
|
12138
12391
|
const isUser = m.role === "user";
|
|
12139
12392
|
const raw = m.text || "";
|
|
12140
12393
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
12141
12394
|
const body = clamped != null ? clamped : raw;
|
|
12142
12395
|
const showMd = ctx.markdown && !isUser;
|
|
12143
|
-
return /* @__PURE__ */ (0,
|
|
12144
|
-
m.thinking && ctx.showThinking ? /* @__PURE__ */ (0,
|
|
12145
|
-
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0,
|
|
12146
|
-
body ? /* @__PURE__ */ (0,
|
|
12147
|
-
showMd ? /* @__PURE__ */ (0,
|
|
12148
|
-
m.streaming ? /* @__PURE__ */ (0,
|
|
12396
|
+
return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-body", children: [
|
|
12397
|
+
m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
|
|
12398
|
+
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
|
|
12399
|
+
body ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
|
|
12400
|
+
showMd ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-plain", children: body }),
|
|
12401
|
+
m.streaming ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
|
|
12149
12402
|
] }) : null,
|
|
12150
|
-
clamped != null ? /* @__PURE__ */ (0,
|
|
12151
|
-
/* @__PURE__ */ (0,
|
|
12403
|
+
clamped != null ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
|
|
12404
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
|
|
12152
12405
|
"Show more",
|
|
12153
|
-
/* @__PURE__ */ (0,
|
|
12154
|
-
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0,
|
|
12155
|
-
/* @__PURE__ */ (0,
|
|
12406
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
|
|
12407
|
+
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
|
|
12408
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
|
|
12156
12409
|
"Show less"
|
|
12157
12410
|
] }) : null,
|
|
12158
|
-
m.attachments && m.attachments.length ? /* @__PURE__ */ (0,
|
|
12159
|
-
m.packet ? /* @__PURE__ */ (0,
|
|
12411
|
+
m.attachments && m.attachments.length ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
|
|
12412
|
+
m.packet ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(
|
|
12160
12413
|
PacketCard,
|
|
12161
12414
|
{
|
|
12162
12415
|
packet: m.packet,
|
|
@@ -12166,44 +12419,44 @@ function MessageBody({ message: m, ctx }) {
|
|
|
12166
12419
|
applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
|
|
12167
12420
|
}
|
|
12168
12421
|
) : null,
|
|
12169
|
-
m.citations && m.citations.length ? /* @__PURE__ */ (0,
|
|
12170
|
-
m.working ? /* @__PURE__ */ (0,
|
|
12171
|
-
/* @__PURE__ */ (0,
|
|
12172
|
-
/* @__PURE__ */ (0,
|
|
12173
|
-
/* @__PURE__ */ (0,
|
|
12174
|
-
/* @__PURE__ */ (0,
|
|
12422
|
+
m.citations && m.citations.length ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
|
|
12423
|
+
m.working ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-working", role: "status", children: [
|
|
12424
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
12425
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {}),
|
|
12426
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {}),
|
|
12427
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {})
|
|
12175
12428
|
] }),
|
|
12176
|
-
/* @__PURE__ */ (0,
|
|
12429
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-working-label", children: [
|
|
12177
12430
|
m.resumed ? "Resuming" : "Working",
|
|
12178
|
-
m.job && m.job.status ? /* @__PURE__ */ (0,
|
|
12431
|
+
m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-working-job", children: [
|
|
12179
12432
|
" \xB7 ",
|
|
12180
12433
|
m.job.status
|
|
12181
12434
|
] }) : null,
|
|
12182
|
-
m.job && m.job.detail ? /* @__PURE__ */ (0,
|
|
12435
|
+
m.job && m.job.detail ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-working-job", children: [
|
|
12183
12436
|
" \xB7 ",
|
|
12184
12437
|
m.job.detail
|
|
12185
12438
|
] }) : null
|
|
12186
12439
|
] }),
|
|
12187
|
-
m.jobId ? /* @__PURE__ */ (0,
|
|
12440
|
+
m.jobId ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
|
|
12188
12441
|
] }) : null,
|
|
12189
|
-
m.stopped ? /* @__PURE__ */ (0,
|
|
12190
|
-
/* @__PURE__ */ (0,
|
|
12442
|
+
m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-stopped", children: [
|
|
12443
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
12191
12444
|
"Stopped"
|
|
12192
12445
|
] }) : null,
|
|
12193
|
-
m.error ? /* @__PURE__ */ (0,
|
|
12194
|
-
/* @__PURE__ */ (0,
|
|
12195
|
-
/* @__PURE__ */ (0,
|
|
12196
|
-
m.retryable && ctx.onRetry ? /* @__PURE__ */ (0,
|
|
12197
|
-
/* @__PURE__ */ (0,
|
|
12446
|
+
m.error ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-error", role: "alert", children: [
|
|
12447
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
12448
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
|
|
12449
|
+
m.retryable && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
|
|
12450
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
12198
12451
|
"Retry"
|
|
12199
12452
|
] }) : null
|
|
12200
12453
|
] }) : null
|
|
12201
12454
|
] });
|
|
12202
12455
|
}
|
|
12203
12456
|
function useCopyRun() {
|
|
12204
|
-
const [done, setDone] =
|
|
12205
|
-
const t =
|
|
12206
|
-
|
|
12457
|
+
const [done, setDone] = React60.useState(false);
|
|
12458
|
+
const t = React60.useRef(null);
|
|
12459
|
+
React60.useEffect(() => () => {
|
|
12207
12460
|
if (t.current) clearTimeout(t.current);
|
|
12208
12461
|
}, []);
|
|
12209
12462
|
return [done, (text) => {
|
|
@@ -12223,16 +12476,16 @@ function RunActions({ group, ctx }) {
|
|
|
12223
12476
|
const isAssistant = group.role === "assistant";
|
|
12224
12477
|
const fb = last.feedback;
|
|
12225
12478
|
if (!ctx.messageActions) return null;
|
|
12226
|
-
return /* @__PURE__ */ (0,
|
|
12227
|
-
/* @__PURE__ */ (0,
|
|
12228
|
-
/* @__PURE__ */ (0,
|
|
12229
|
-
/* @__PURE__ */ (0,
|
|
12479
|
+
return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
|
|
12480
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
|
|
12481
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
|
|
12482
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
|
|
12230
12483
|
] }),
|
|
12231
|
-
isAssistant && ctx.onRetry ? /* @__PURE__ */ (0,
|
|
12232
|
-
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0,
|
|
12233
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0,
|
|
12234
|
-
/* @__PURE__ */ (0,
|
|
12235
|
-
/* @__PURE__ */ (0,
|
|
12484
|
+
isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
12485
|
+
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
12486
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)(React60.Fragment, { children: [
|
|
12487
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
12488
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
12236
12489
|
] }) : null,
|
|
12237
12490
|
ctx.extraActions ? ctx.extraActions(group) : null
|
|
12238
12491
|
] });
|
|
@@ -12242,22 +12495,22 @@ function ChatTurn({ group, ctx }) {
|
|
|
12242
12495
|
const name = isUser ? ctx.userName : group.author || ctx.assistantName;
|
|
12243
12496
|
const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
|
|
12244
12497
|
const stamp = group.messages[0].timestamp;
|
|
12245
|
-
return /* @__PURE__ */ (0,
|
|
12246
|
-
/* @__PURE__ */ (0,
|
|
12247
|
-
ctx.showAvatars ? /* @__PURE__ */ (0,
|
|
12248
|
-
/* @__PURE__ */ (0,
|
|
12249
|
-
stamp ? /* @__PURE__ */ (0,
|
|
12250
|
-
group.messages.some((m) => m.model) ? /* @__PURE__ */ (0,
|
|
12498
|
+
return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
|
|
12499
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-turn-head", children: [
|
|
12500
|
+
ctx.showAvatars ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
|
|
12501
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-who", children: name }),
|
|
12502
|
+
stamp ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(RelativeTime, { className: "fdc-when", value: stamp }) : null,
|
|
12503
|
+
group.messages.some((m) => m.model) ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
|
|
12251
12504
|
] }),
|
|
12252
|
-
/* @__PURE__ */ (0,
|
|
12253
|
-
group.messages.map((m) => /* @__PURE__ */ (0,
|
|
12254
|
-
/* @__PURE__ */ (0,
|
|
12505
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-turn-body", children: [
|
|
12506
|
+
group.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(MessageBody, { message: m, ctx }) }, m.id)),
|
|
12507
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)(RunActions, { group, ctx })
|
|
12255
12508
|
] })
|
|
12256
12509
|
] });
|
|
12257
12510
|
}
|
|
12258
12511
|
|
|
12259
12512
|
// src/components/chat/ChatTranscript.tsx
|
|
12260
|
-
var
|
|
12513
|
+
var import_jsx_runtime93 = require("react/jsx-runtime");
|
|
12261
12514
|
var GROUP_WINDOW = 6e4;
|
|
12262
12515
|
var STICK_PX = 100;
|
|
12263
12516
|
function groupMessages(list) {
|
|
@@ -12290,25 +12543,25 @@ function dayLabel(key) {
|
|
|
12290
12543
|
}
|
|
12291
12544
|
function Suggestions({ items = [], onPick }) {
|
|
12292
12545
|
if (!items.length) return null;
|
|
12293
|
-
return /* @__PURE__ */ (0,
|
|
12546
|
+
return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
|
|
12294
12547
|
const it = typeof s === "string" ? { label: s, text: s } : s;
|
|
12295
|
-
return /* @__PURE__ */ (0,
|
|
12296
|
-
it.icon ? /* @__PURE__ */ (0,
|
|
12297
|
-
/* @__PURE__ */ (0,
|
|
12298
|
-
/* @__PURE__ */ (0,
|
|
12299
|
-
it.description ? /* @__PURE__ */ (0,
|
|
12548
|
+
return /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
|
|
12549
|
+
it.icon ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
|
|
12550
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("span", { className: "fdc-suggest-text", children: [
|
|
12551
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-suggest-label", children: it.label }),
|
|
12552
|
+
it.description ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-suggest-desc", children: it.description }) : null
|
|
12300
12553
|
] }),
|
|
12301
|
-
/* @__PURE__ */ (0,
|
|
12554
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
|
|
12302
12555
|
] }, it.id || i);
|
|
12303
12556
|
}) });
|
|
12304
12557
|
}
|
|
12305
12558
|
function LoadingTurns() {
|
|
12306
|
-
return /* @__PURE__ */ (0,
|
|
12307
|
-
/* @__PURE__ */ (0,
|
|
12308
|
-
/* @__PURE__ */ (0,
|
|
12309
|
-
/* @__PURE__ */ (0,
|
|
12310
|
-
/* @__PURE__ */ (0,
|
|
12311
|
-
/* @__PURE__ */ (0,
|
|
12559
|
+
return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-skel-turn", children: [
|
|
12560
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
|
|
12561
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-skel-lines", children: [
|
|
12562
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
|
|
12563
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
|
|
12564
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
|
|
12312
12565
|
] })
|
|
12313
12566
|
] }, i)) });
|
|
12314
12567
|
}
|
|
@@ -12325,10 +12578,10 @@ function ChatTranscript({
|
|
|
12325
12578
|
renderEmpty,
|
|
12326
12579
|
className = ""
|
|
12327
12580
|
}) {
|
|
12328
|
-
const scroller =
|
|
12329
|
-
const stick =
|
|
12330
|
-
const [pill, setPill] =
|
|
12331
|
-
const seen =
|
|
12581
|
+
const scroller = React61.useRef(null);
|
|
12582
|
+
const stick = React61.useRef(true);
|
|
12583
|
+
const [pill, setPill] = React61.useState(0);
|
|
12584
|
+
const seen = React61.useRef(0);
|
|
12332
12585
|
const toBottom = (smooth) => {
|
|
12333
12586
|
const el = scroller.current;
|
|
12334
12587
|
if (!el) return;
|
|
@@ -12347,7 +12600,7 @@ function ChatTranscript({
|
|
|
12347
12600
|
seen.current = messages.length;
|
|
12348
12601
|
}
|
|
12349
12602
|
};
|
|
12350
|
-
|
|
12603
|
+
React61.useLayoutEffect(() => {
|
|
12351
12604
|
const el = scroller.current;
|
|
12352
12605
|
if (!el) return;
|
|
12353
12606
|
if (stick.current) {
|
|
@@ -12355,7 +12608,7 @@ function ChatTranscript({
|
|
|
12355
12608
|
seen.current = messages.length;
|
|
12356
12609
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
12357
12610
|
}, [messages]);
|
|
12358
|
-
|
|
12611
|
+
React61.useEffect(() => {
|
|
12359
12612
|
const el = scroller.current;
|
|
12360
12613
|
const inner = el && el.firstChild;
|
|
12361
12614
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -12365,38 +12618,38 @@ function ChatTranscript({
|
|
|
12365
12618
|
ro.observe(inner);
|
|
12366
12619
|
return () => ro.disconnect();
|
|
12367
12620
|
}, []);
|
|
12368
|
-
const groups =
|
|
12621
|
+
const groups = React61.useMemo(() => groupMessages(messages), [messages]);
|
|
12369
12622
|
const empty = !messages.length && status === "ready";
|
|
12370
|
-
return /* @__PURE__ */ (0,
|
|
12371
|
-
/* @__PURE__ */ (0,
|
|
12372
|
-
status === "loading" || status === "resolving" ? /* @__PURE__ */ (0,
|
|
12373
|
-
status === "disconnected" ? /* @__PURE__ */ (0,
|
|
12374
|
-
/* @__PURE__ */ (0,
|
|
12375
|
-
/* @__PURE__ */ (0,
|
|
12376
|
-
/* @__PURE__ */ (0,
|
|
12377
|
-
ctx.onReconnect ? /* @__PURE__ */ (0,
|
|
12378
|
-
/* @__PURE__ */ (0,
|
|
12623
|
+
return /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
12624
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
12625
|
+
status === "loading" || status === "resolving" ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(LoadingTurns, {}) : null,
|
|
12626
|
+
status === "disconnected" ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-dead", children: [
|
|
12627
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
|
|
12628
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
|
|
12629
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)("p", { className: "fdc-dead-body", children: fatal === "chat_unavailable" ? "The service reported chat_unavailable. Nothing you type will be lost \u2014 reopen the panel once it\u2019s back." : "The thread couldn\u2019t be resolved" + (fatal ? " (" + fatal + ")" : "") + ". The composer stays disabled until it resolves." }),
|
|
12630
|
+
ctx.onReconnect ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
|
|
12631
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
12379
12632
|
"Try again"
|
|
12380
12633
|
] }) : null
|
|
12381
12634
|
] }) : null,
|
|
12382
|
-
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0,
|
|
12383
|
-
/* @__PURE__ */ (0,
|
|
12384
|
-
/* @__PURE__ */ (0,
|
|
12385
|
-
emptyDescription ? /* @__PURE__ */ (0,
|
|
12386
|
-
/* @__PURE__ */ (0,
|
|
12635
|
+
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-empty", children: [
|
|
12636
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
|
|
12637
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)("h3", { className: "fdc-empty-title", children: emptyTitle }),
|
|
12638
|
+
emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
|
|
12639
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)(Suggestions, { items: suggestions, onPick })
|
|
12387
12640
|
] }) : null,
|
|
12388
12641
|
groups.map((g, i) => {
|
|
12389
12642
|
const prev = groups[i - 1];
|
|
12390
12643
|
const k = dayKey(g.messages[0].timestamp);
|
|
12391
12644
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
12392
|
-
return /* @__PURE__ */ (0,
|
|
12393
|
-
showDay ? /* @__PURE__ */ (0,
|
|
12394
|
-
/* @__PURE__ */ (0,
|
|
12645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)(React61.Fragment, { children: [
|
|
12646
|
+
showDay ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { children: dayLabel(k) }) }) : null,
|
|
12647
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)(ChatTurn, { group: g, ctx })
|
|
12395
12648
|
] }, g.key || i);
|
|
12396
12649
|
})
|
|
12397
12650
|
] }),
|
|
12398
|
-
pill ? /* @__PURE__ */ (0,
|
|
12399
|
-
/* @__PURE__ */ (0,
|
|
12651
|
+
pill ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
|
|
12652
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
|
|
12400
12653
|
pill,
|
|
12401
12654
|
" new message",
|
|
12402
12655
|
pill === 1 ? "" : "s"
|
|
@@ -12406,8 +12659,8 @@ function ChatTranscript({
|
|
|
12406
12659
|
var TranscriptKit = { groupMessages };
|
|
12407
12660
|
|
|
12408
12661
|
// src/components/chat/ChatComposer.tsx
|
|
12409
|
-
var
|
|
12410
|
-
var
|
|
12662
|
+
var React62 = __toESM(require("react"), 1);
|
|
12663
|
+
var import_jsx_runtime94 = require("react/jsx-runtime");
|
|
12411
12664
|
function ChatComposer({
|
|
12412
12665
|
onSubmit,
|
|
12413
12666
|
onStop,
|
|
@@ -12434,17 +12687,17 @@ function ChatComposer({
|
|
|
12434
12687
|
onReject,
|
|
12435
12688
|
onOpenAttachment
|
|
12436
12689
|
}) {
|
|
12437
|
-
const [text, setText] =
|
|
12438
|
-
const [trigger, setTrigger] =
|
|
12439
|
-
const [mentionItems, setMentionItems] =
|
|
12440
|
-
const [listening, setListening] =
|
|
12441
|
-
const [notice, setNotice] =
|
|
12442
|
-
const editor =
|
|
12443
|
-
const wrap =
|
|
12444
|
-
const stopVoice =
|
|
12690
|
+
const [text, setText] = React62.useState(draft || "");
|
|
12691
|
+
const [trigger, setTrigger] = React62.useState(null);
|
|
12692
|
+
const [mentionItems, setMentionItems] = React62.useState([]);
|
|
12693
|
+
const [listening, setListening] = React62.useState(false);
|
|
12694
|
+
const [notice, setNotice] = React62.useState(null);
|
|
12695
|
+
const editor = React62.useRef(null);
|
|
12696
|
+
const wrap = React62.useRef(null);
|
|
12697
|
+
const stopVoice = React62.useRef(null);
|
|
12445
12698
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
12446
12699
|
} });
|
|
12447
|
-
|
|
12700
|
+
React62.useEffect(() => {
|
|
12448
12701
|
if (draft != null && draft !== text) setText(draft);
|
|
12449
12702
|
}, [draft]);
|
|
12450
12703
|
const change = (v) => {
|
|
@@ -12480,7 +12733,7 @@ function ChatComposer({
|
|
|
12480
12733
|
e.preventDefault();
|
|
12481
12734
|
staged.add(found.files);
|
|
12482
12735
|
};
|
|
12483
|
-
|
|
12736
|
+
React62.useEffect(() => {
|
|
12484
12737
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
12485
12738
|
setMentionItems([]);
|
|
12486
12739
|
return;
|
|
@@ -12498,7 +12751,7 @@ function ChatComposer({
|
|
|
12498
12751
|
const q = (trigger.query || "").toLowerCase();
|
|
12499
12752
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
12500
12753
|
}, [trigger, mentionSources]);
|
|
12501
|
-
const slashItems =
|
|
12754
|
+
const slashItems = React62.useMemo(() => {
|
|
12502
12755
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
12503
12756
|
const q = (trigger.query || "").toLowerCase();
|
|
12504
12757
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -12512,7 +12765,7 @@ function ChatComposer({
|
|
|
12512
12765
|
description: it.description,
|
|
12513
12766
|
icon: it.icon,
|
|
12514
12767
|
meta: mention.meta,
|
|
12515
|
-
shortcut: slash.shortcut ? /* @__PURE__ */ (0,
|
|
12768
|
+
shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
|
|
12516
12769
|
onSelect: () => {
|
|
12517
12770
|
const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
|
|
12518
12771
|
editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
|
|
@@ -12571,14 +12824,14 @@ function ChatComposer({
|
|
|
12571
12824
|
stopVoice.current = typeof res === "function" ? res : () => {
|
|
12572
12825
|
};
|
|
12573
12826
|
};
|
|
12574
|
-
return /* @__PURE__ */ (0,
|
|
12575
|
-
queue.length ? /* @__PURE__ */ (0,
|
|
12576
|
-
/* @__PURE__ */ (0,
|
|
12577
|
-
/* @__PURE__ */ (0,
|
|
12578
|
-
onRemoveQueued ? /* @__PURE__ */ (0,
|
|
12827
|
+
return /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
|
|
12828
|
+
queue.length ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-queue-row", children: [
|
|
12829
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
|
|
12830
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fdc-queue-text", title: truncationTitle(q.text || (q.attachments ? q.attachments.length + " file(s)" : "")), children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
|
|
12831
|
+
onRemoveQueued ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
12579
12832
|
] }, q.id)) }) : null,
|
|
12580
12833
|
sessionBar,
|
|
12581
|
-
/* @__PURE__ */ (0,
|
|
12834
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
|
|
12582
12835
|
Dropzone,
|
|
12583
12836
|
{
|
|
12584
12837
|
className: "fdc-field",
|
|
@@ -12592,9 +12845,9 @@ function ChatComposer({
|
|
|
12592
12845
|
disabled: !fileUploadHandler || disabled,
|
|
12593
12846
|
label: "Drop to attach",
|
|
12594
12847
|
hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
|
|
12595
|
-
children: /* @__PURE__ */ (0,
|
|
12596
|
-
staged.items.length ? /* @__PURE__ */ (0,
|
|
12597
|
-
/* @__PURE__ */ (0,
|
|
12848
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { ref: wrap, className: "fdc-field-inner", children: [
|
|
12849
|
+
staged.items.length ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { className: "fdc-staged", children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
|
|
12850
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
|
|
12598
12851
|
MarkdownEditor,
|
|
12599
12852
|
{
|
|
12600
12853
|
ref: editor,
|
|
@@ -12613,33 +12866,33 @@ function ChatComposer({
|
|
|
12613
12866
|
ariaLabel: "Message"
|
|
12614
12867
|
}
|
|
12615
12868
|
),
|
|
12616
|
-
/* @__PURE__ */ (0,
|
|
12617
|
-
fileUploadHandler ? /* @__PURE__ */ (0,
|
|
12618
|
-
voiceHandler ? /* @__PURE__ */ (0,
|
|
12869
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-tools", children: [
|
|
12870
|
+
fileUploadHandler ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
|
|
12871
|
+
voiceHandler ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
|
|
12619
12872
|
toolbarExtras,
|
|
12620
|
-
/* @__PURE__ */ (0,
|
|
12621
|
-
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0,
|
|
12873
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fdc-tools-gap" }),
|
|
12874
|
+
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
|
|
12622
12875
|
text.length,
|
|
12623
12876
|
"/",
|
|
12624
12877
|
maxLength
|
|
12625
12878
|
] }) : null,
|
|
12626
|
-
busy ? /* @__PURE__ */ (0,
|
|
12627
|
-
/* @__PURE__ */ (0,
|
|
12628
|
-
/* @__PURE__ */ (0,
|
|
12629
|
-
] }) : /* @__PURE__ */ (0,
|
|
12630
|
-
/* @__PURE__ */ (0,
|
|
12631
|
-
/* @__PURE__ */ (0,
|
|
12879
|
+
busy ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
|
|
12880
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
12881
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: "Stop" })
|
|
12882
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
|
|
12883
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
|
|
12884
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fdc-send-label", children: "Send" })
|
|
12632
12885
|
] })
|
|
12633
12886
|
] })
|
|
12634
12887
|
] })
|
|
12635
12888
|
}
|
|
12636
12889
|
),
|
|
12637
|
-
notice ? /* @__PURE__ */ (0,
|
|
12638
|
-
/* @__PURE__ */ (0,
|
|
12890
|
+
notice ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-notice", role: "status", children: [
|
|
12891
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
12639
12892
|
notice
|
|
12640
12893
|
] }) : null,
|
|
12641
|
-
hint && !notice ? /* @__PURE__ */ (0,
|
|
12642
|
-
/* @__PURE__ */ (0,
|
|
12894
|
+
hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { className: "fdc-hint", children: hint }) : null,
|
|
12895
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
|
|
12643
12896
|
Popover,
|
|
12644
12897
|
{
|
|
12645
12898
|
open: menuOpen,
|
|
@@ -12653,12 +12906,12 @@ function ChatComposer({
|
|
|
12653
12906
|
returnFocus: false,
|
|
12654
12907
|
closeOnOutside: true,
|
|
12655
12908
|
label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
|
|
12656
|
-
children: /* @__PURE__ */ (0,
|
|
12909
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
|
|
12657
12910
|
Menu,
|
|
12658
12911
|
{
|
|
12659
12912
|
items: menuItems,
|
|
12660
12913
|
autoFocus: false,
|
|
12661
|
-
header: /* @__PURE__ */ (0,
|
|
12914
|
+
header: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
|
|
12662
12915
|
onClose: () => setTrigger(null)
|
|
12663
12916
|
}
|
|
12664
12917
|
)
|
|
@@ -12668,12 +12921,12 @@ function ChatComposer({
|
|
|
12668
12921
|
}
|
|
12669
12922
|
|
|
12670
12923
|
// src/components/chat/ChatSessionBar.tsx
|
|
12671
|
-
var
|
|
12672
|
-
var
|
|
12924
|
+
var React63 = __toESM(require("react"), 1);
|
|
12925
|
+
var import_jsx_runtime95 = require("react/jsx-runtime");
|
|
12673
12926
|
var compact2 = meterFormats.compact;
|
|
12674
12927
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
12675
|
-
const [open2, setOpen] =
|
|
12676
|
-
const anchor =
|
|
12928
|
+
const [open2, setOpen] = React63.useState(false);
|
|
12929
|
+
const anchor = React63.useRef(null);
|
|
12677
12930
|
const stats = sessionStats || null;
|
|
12678
12931
|
const cu = contextUsage || null;
|
|
12679
12932
|
const limits = usageLimits || null;
|
|
@@ -12688,9 +12941,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12688
12941
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
12689
12942
|
if (cu) bits.push(pct + "% context");
|
|
12690
12943
|
const expandable = !!(cu || limits);
|
|
12691
|
-
return /* @__PURE__ */ (0,
|
|
12692
|
-
/* @__PURE__ */ (0,
|
|
12693
|
-
/* @__PURE__ */ (0,
|
|
12944
|
+
return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(React63.Fragment, { children: [
|
|
12945
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { className: "fdc-bar", children: [
|
|
12946
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(
|
|
12694
12947
|
"button",
|
|
12695
12948
|
{
|
|
12696
12949
|
type: "button",
|
|
@@ -12701,15 +12954,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12701
12954
|
"aria-expanded": expandable ? open2 : void 0,
|
|
12702
12955
|
"aria-label": expandable ? "Usage details" : void 0,
|
|
12703
12956
|
children: [
|
|
12704
|
-
cu ? /* @__PURE__ */ (0,
|
|
12705
|
-
/* @__PURE__ */ (0,
|
|
12706
|
-
expandable ? /* @__PURE__ */ (0,
|
|
12957
|
+
cu ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
|
|
12958
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
|
|
12959
|
+
expandable ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
|
|
12707
12960
|
]
|
|
12708
12961
|
}
|
|
12709
12962
|
),
|
|
12710
12963
|
extras
|
|
12711
12964
|
] }),
|
|
12712
|
-
/* @__PURE__ */ (0,
|
|
12965
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
|
|
12713
12966
|
Popover,
|
|
12714
12967
|
{
|
|
12715
12968
|
open: open2,
|
|
@@ -12720,15 +12973,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12720
12973
|
maxHeight: 460,
|
|
12721
12974
|
padded: true,
|
|
12722
12975
|
label: "Usage",
|
|
12723
|
-
footer: onClear ? /* @__PURE__ */ (0,
|
|
12976
|
+
footer: onClear ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
|
|
12724
12977
|
setOpen(false);
|
|
12725
12978
|
onClear();
|
|
12726
12979
|
}, children: [
|
|
12727
|
-
/* @__PURE__ */ (0,
|
|
12980
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
|
|
12728
12981
|
"Clear conversation"
|
|
12729
12982
|
] }) : void 0,
|
|
12730
|
-
children: /* @__PURE__ */ (0,
|
|
12731
|
-
cu ? /* @__PURE__ */ (0,
|
|
12983
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { className: "fdc-usage", children: [
|
|
12984
|
+
cu ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
|
|
12732
12985
|
SegmentedMeter,
|
|
12733
12986
|
{
|
|
12734
12987
|
total,
|
|
@@ -12740,9 +12993,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12740
12993
|
remainderLabel: "Free"
|
|
12741
12994
|
}
|
|
12742
12995
|
) }) : null,
|
|
12743
|
-
limits && limits.length ? /* @__PURE__ */ (0,
|
|
12744
|
-
/* @__PURE__ */ (0,
|
|
12745
|
-
/* @__PURE__ */ (0,
|
|
12996
|
+
limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("section", { className: "fdc-usage-sec", children: [
|
|
12997
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
|
|
12998
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
|
|
12746
12999
|
QuotaRow,
|
|
12747
13000
|
{
|
|
12748
13001
|
label: l.label,
|
|
@@ -12752,25 +13005,25 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12752
13005
|
l.id
|
|
12753
13006
|
)) })
|
|
12754
13007
|
] }) : null,
|
|
12755
|
-
stats ? /* @__PURE__ */ (0,
|
|
12756
|
-
stats.elapsedMs ? /* @__PURE__ */ (0,
|
|
12757
|
-
/* @__PURE__ */ (0,
|
|
12758
|
-
/* @__PURE__ */ (0,
|
|
13008
|
+
stats ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
|
|
13009
|
+
stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { children: [
|
|
13010
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { children: "Session" }),
|
|
13011
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
|
|
12759
13012
|
] }) : null,
|
|
12760
|
-
stats.tokens ? /* @__PURE__ */ (0,
|
|
12761
|
-
/* @__PURE__ */ (0,
|
|
12762
|
-
/* @__PURE__ */ (0,
|
|
13013
|
+
stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { children: [
|
|
13014
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { children: "Tokens" }),
|
|
13015
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
|
|
12763
13016
|
] }) : null,
|
|
12764
|
-
stats.costUsd != null ? /* @__PURE__ */ (0,
|
|
12765
|
-
/* @__PURE__ */ (0,
|
|
12766
|
-
/* @__PURE__ */ (0,
|
|
13017
|
+
stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { children: [
|
|
13018
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { children: "Cost" }),
|
|
13019
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("b", { className: "fd-tabular", children: [
|
|
12767
13020
|
"$",
|
|
12768
13021
|
Number(stats.costUsd).toFixed(3)
|
|
12769
13022
|
] })
|
|
12770
13023
|
] }) : null,
|
|
12771
|
-
stats.turns ? /* @__PURE__ */ (0,
|
|
12772
|
-
/* @__PURE__ */ (0,
|
|
12773
|
-
/* @__PURE__ */ (0,
|
|
13024
|
+
stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { children: [
|
|
13025
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { children: "Turns" }),
|
|
13026
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("b", { className: "fd-tabular", children: stats.turns })
|
|
12774
13027
|
] }) : null
|
|
12775
13028
|
] }) : null
|
|
12776
13029
|
] })
|
|
@@ -12809,7 +13062,7 @@ function ModelControls({
|
|
|
12809
13062
|
disabled: m.disabled,
|
|
12810
13063
|
checked: m.id === (current2 && current2.id),
|
|
12811
13064
|
meta: m.meta,
|
|
12812
|
-
shortcut: m.shortcut ? /* @__PURE__ */ (0,
|
|
13065
|
+
shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
|
|
12813
13066
|
onSelect: () => onModelChange && onModelChange(m.id)
|
|
12814
13067
|
});
|
|
12815
13068
|
const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
|
|
@@ -12822,15 +13075,15 @@ function ModelControls({
|
|
|
12822
13075
|
items.push({ kind: "section", label: "Fast mode" });
|
|
12823
13076
|
items.push({
|
|
12824
13077
|
kind: "custom",
|
|
12825
|
-
render: () => /* @__PURE__ */ (0,
|
|
12826
|
-
/* @__PURE__ */ (0,
|
|
12827
|
-
/* @__PURE__ */ (0,
|
|
12828
|
-
/* @__PURE__ */ (0,
|
|
13078
|
+
render: () => /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("label", { className: "fdc-switchrow", children: [
|
|
13079
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { children: fastModeLabel }),
|
|
13080
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
|
|
13081
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fd-switch-thumb" }) })
|
|
12829
13082
|
] })
|
|
12830
13083
|
});
|
|
12831
13084
|
}
|
|
12832
|
-
return /* @__PURE__ */ (0,
|
|
12833
|
-
/* @__PURE__ */ (0,
|
|
13085
|
+
return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(React63.Fragment, { children: [
|
|
13086
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
|
|
12834
13087
|
MenuButton,
|
|
12835
13088
|
{
|
|
12836
13089
|
items,
|
|
@@ -12841,7 +13094,7 @@ function ModelControls({
|
|
|
12841
13094
|
title: "Choose a model"
|
|
12842
13095
|
}
|
|
12843
13096
|
),
|
|
12844
|
-
effortLevels && effortLevels.length ? /* @__PURE__ */ (0,
|
|
13097
|
+
effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
|
|
12845
13098
|
MenuButton,
|
|
12846
13099
|
{
|
|
12847
13100
|
placement: "top-end",
|
|
@@ -12862,7 +13115,7 @@ function ModelControls({
|
|
|
12862
13115
|
}
|
|
12863
13116
|
|
|
12864
13117
|
// src/components/chat/AgentChatPanel.tsx
|
|
12865
|
-
var
|
|
13118
|
+
var import_jsx_runtime96 = require("react/jsx-runtime");
|
|
12866
13119
|
var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
|
|
12867
13120
|
function AgentChatPanel({
|
|
12868
13121
|
/* required */
|
|
@@ -12946,11 +13199,11 @@ function AgentChatPanel({
|
|
|
12946
13199
|
onFeedback,
|
|
12947
13200
|
onEditMessage
|
|
12948
13201
|
}) {
|
|
12949
|
-
const [panelWidth, setPanelWidth] =
|
|
12950
|
-
const [applied, setApplied] =
|
|
12951
|
-
const [draft, setDraft] =
|
|
12952
|
-
const dragging =
|
|
12953
|
-
|
|
13202
|
+
const [panelWidth, setPanelWidth] = React64.useState(width);
|
|
13203
|
+
const [applied, setApplied] = React64.useState({});
|
|
13204
|
+
const [draft, setDraft] = React64.useState("");
|
|
13205
|
+
const dragging = React64.useRef(null);
|
|
13206
|
+
React64.useEffect(() => setPanelWidth(width), [width]);
|
|
12954
13207
|
const engine = useChatEngine({
|
|
12955
13208
|
contextType,
|
|
12956
13209
|
contextId,
|
|
@@ -13016,7 +13269,7 @@ function AgentChatPanel({
|
|
|
13016
13269
|
onReconnect: engine.reload,
|
|
13017
13270
|
deadTitle: "The assistant isn\u2019t reachable"
|
|
13018
13271
|
};
|
|
13019
|
-
const sessionBar = /* @__PURE__ */ (0,
|
|
13272
|
+
const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
|
|
13020
13273
|
ChatSessionBar,
|
|
13021
13274
|
{
|
|
13022
13275
|
sessionStats,
|
|
@@ -13025,7 +13278,7 @@ function AgentChatPanel({
|
|
|
13025
13278
|
onClear: engine.visible.length ? engine.clear : void 0
|
|
13026
13279
|
}
|
|
13027
13280
|
);
|
|
13028
|
-
const modelControls = /* @__PURE__ */ (0,
|
|
13281
|
+
const modelControls = /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
|
|
13029
13282
|
ModelControls,
|
|
13030
13283
|
{
|
|
13031
13284
|
models,
|
|
@@ -13040,7 +13293,7 @@ function AgentChatPanel({
|
|
|
13040
13293
|
narrow
|
|
13041
13294
|
}
|
|
13042
13295
|
);
|
|
13043
|
-
const threadMenu = threads && threads.length ? /* @__PURE__ */ (0,
|
|
13296
|
+
const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
|
|
13044
13297
|
MenuButton,
|
|
13045
13298
|
{
|
|
13046
13299
|
variant: "ghost",
|
|
@@ -13067,7 +13320,7 @@ function AgentChatPanel({
|
|
|
13067
13320
|
})))
|
|
13068
13321
|
}
|
|
13069
13322
|
) : null;
|
|
13070
|
-
return /* @__PURE__ */ (0,
|
|
13323
|
+
return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)(
|
|
13071
13324
|
"aside",
|
|
13072
13325
|
{
|
|
13073
13326
|
className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
|
|
@@ -13078,7 +13331,7 @@ function AgentChatPanel({
|
|
|
13078
13331
|
},
|
|
13079
13332
|
"aria-label": title,
|
|
13080
13333
|
children: [
|
|
13081
|
-
surface === "sidebar" && resizable ? /* @__PURE__ */ (0,
|
|
13334
|
+
surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
|
|
13082
13335
|
"div",
|
|
13083
13336
|
{
|
|
13084
13337
|
className: "fdc-grip",
|
|
@@ -13093,20 +13346,20 @@ function AgentChatPanel({
|
|
|
13093
13346
|
}
|
|
13094
13347
|
}
|
|
13095
13348
|
) : null,
|
|
13096
|
-
showHeader ? /* @__PURE__ */ (0,
|
|
13097
|
-
/* @__PURE__ */ (0,
|
|
13098
|
-
/* @__PURE__ */ (0,
|
|
13099
|
-
/* @__PURE__ */ (0,
|
|
13100
|
-
subtitle ? /* @__PURE__ */ (0,
|
|
13349
|
+
showHeader ? /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("header", { className: "fdc-head", children: [
|
|
13350
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("i", { className: "ph ph-" + assistantIcon }) }),
|
|
13351
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fdc-head-titles", children: [
|
|
13352
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
|
|
13353
|
+
subtitle ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
|
|
13101
13354
|
] }),
|
|
13102
|
-
/* @__PURE__ */ (0,
|
|
13355
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fdc-head-acts", children: [
|
|
13103
13356
|
headerActions,
|
|
13104
13357
|
threadMenu,
|
|
13105
|
-
onNewThread ? /* @__PURE__ */ (0,
|
|
13106
|
-
onClose ? /* @__PURE__ */ (0,
|
|
13358
|
+
onNewThread ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
|
|
13359
|
+
onClose ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
13107
13360
|
] })
|
|
13108
13361
|
] }) : null,
|
|
13109
|
-
/* @__PURE__ */ (0,
|
|
13362
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
|
|
13110
13363
|
ChatTranscript,
|
|
13111
13364
|
{
|
|
13112
13365
|
messages: engine.visible,
|
|
@@ -13121,7 +13374,7 @@ function AgentChatPanel({
|
|
|
13121
13374
|
renderEmpty
|
|
13122
13375
|
}
|
|
13123
13376
|
),
|
|
13124
|
-
/* @__PURE__ */ (0,
|
|
13377
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
|
|
13125
13378
|
ChatComposer,
|
|
13126
13379
|
{
|
|
13127
13380
|
onSubmit: (text, atts) => engine.send(text, atts),
|
|
@@ -13154,8 +13407,8 @@ function AgentChatPanel({
|
|
|
13154
13407
|
}
|
|
13155
13408
|
|
|
13156
13409
|
// src/components/files/FileViewer.tsx
|
|
13157
|
-
var
|
|
13158
|
-
var
|
|
13410
|
+
var React65 = __toESM(require("react"), 1);
|
|
13411
|
+
var import_jsx_runtime97 = require("react/jsx-runtime");
|
|
13159
13412
|
function previewKindOf(file) {
|
|
13160
13413
|
const mime = (file.mime || "").toLowerCase();
|
|
13161
13414
|
const ext = extensionOf(file.name || "");
|
|
@@ -13211,13 +13464,13 @@ function parseDelimited(text, delimiter) {
|
|
|
13211
13464
|
return rows;
|
|
13212
13465
|
}
|
|
13213
13466
|
function usePreview(file, kind, resolveUrl) {
|
|
13214
|
-
const [state, setState] =
|
|
13215
|
-
const [attempt, setAttempt] =
|
|
13216
|
-
const resolveRef =
|
|
13217
|
-
|
|
13467
|
+
const [state, setState] = React65.useState({ status: "loading" });
|
|
13468
|
+
const [attempt, setAttempt] = React65.useState(0);
|
|
13469
|
+
const resolveRef = React65.useRef(resolveUrl);
|
|
13470
|
+
React65.useEffect(() => {
|
|
13218
13471
|
resolveRef.current = resolveUrl;
|
|
13219
13472
|
}, [resolveUrl]);
|
|
13220
|
-
|
|
13473
|
+
React65.useEffect(() => {
|
|
13221
13474
|
if (kind === "none") {
|
|
13222
13475
|
setState({ status: "ready" });
|
|
13223
13476
|
return;
|
|
@@ -13247,19 +13500,19 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
13247
13500
|
if (ac) ac.abort();
|
|
13248
13501
|
};
|
|
13249
13502
|
}, [file.id, kind, attempt]);
|
|
13250
|
-
return { ...state, retry:
|
|
13503
|
+
return { ...state, retry: React65.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
13251
13504
|
}
|
|
13252
13505
|
function PreviewBody({ file, kind, state }) {
|
|
13253
|
-
if (kind === "image") return /* @__PURE__ */ (0,
|
|
13254
|
-
if (kind === "pdf") return /* @__PURE__ */ (0,
|
|
13255
|
-
if (kind === "markdown") return /* @__PURE__ */ (0,
|
|
13506
|
+
if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
13507
|
+
if (kind === "pdf") return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
|
|
13508
|
+
if (kind === "markdown") return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
|
|
13256
13509
|
if (kind === "json") {
|
|
13257
13510
|
let pretty = state.text || "";
|
|
13258
13511
|
try {
|
|
13259
13512
|
pretty = JSON.stringify(JSON.parse(pretty), null, 2);
|
|
13260
13513
|
} catch {
|
|
13261
13514
|
}
|
|
13262
|
-
return /* @__PURE__ */ (0,
|
|
13515
|
+
return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(CodeBlock, { code: pretty, language: "json" });
|
|
13263
13516
|
}
|
|
13264
13517
|
if (kind === "csv") {
|
|
13265
13518
|
const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
|
|
@@ -13267,12 +13520,12 @@ function PreviewBody({ file, kind, state }) {
|
|
|
13267
13520
|
const head = rows[0] || [];
|
|
13268
13521
|
const dataRows = rows.slice(1);
|
|
13269
13522
|
const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
|
|
13270
|
-
return /* @__PURE__ */ (0,
|
|
13271
|
-
/* @__PURE__ */ (0,
|
|
13272
|
-
/* @__PURE__ */ (0,
|
|
13273
|
-
/* @__PURE__ */ (0,
|
|
13523
|
+
return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fv-csv", children: [
|
|
13524
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("table", { className: "fd-fv-csv-table", children: [
|
|
13525
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("tr", { children: head.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("th", { children: c }, i)) }) }),
|
|
13526
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("tr", { children: head.map((_, ci) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
|
|
13274
13527
|
] }),
|
|
13275
|
-
dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ (0,
|
|
13528
|
+
dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
|
|
13276
13529
|
"Showing the first ",
|
|
13277
13530
|
FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
|
|
13278
13531
|
" of ",
|
|
@@ -13281,24 +13534,24 @@ function PreviewBody({ file, kind, state }) {
|
|
|
13281
13534
|
] }) : null
|
|
13282
13535
|
] });
|
|
13283
13536
|
}
|
|
13284
|
-
if (kind === "text") return /* @__PURE__ */ (0,
|
|
13285
|
-
return /* @__PURE__ */ (0,
|
|
13286
|
-
/* @__PURE__ */ (0,
|
|
13287
|
-
/* @__PURE__ */ (0,
|
|
13288
|
-
/* @__PURE__ */ (0,
|
|
13537
|
+
if (kind === "text") return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
|
|
13538
|
+
return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fv-fallback", children: [
|
|
13539
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
|
|
13540
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
|
|
13541
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fv-fallback-meta", children: [
|
|
13289
13542
|
file.mime || "Unknown type",
|
|
13290
13543
|
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
13291
13544
|
] })
|
|
13292
13545
|
] });
|
|
13293
13546
|
}
|
|
13294
13547
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
13295
|
-
const kind =
|
|
13548
|
+
const kind = React65.useMemo(() => previewKindOf(file), [file]);
|
|
13296
13549
|
const preview = usePreview(file, kind, resolveUrl);
|
|
13297
|
-
const [tab, setTab] =
|
|
13298
|
-
const [downloading, setDownloading] =
|
|
13299
|
-
const [downloadError, setDownloadError] =
|
|
13550
|
+
const [tab, setTab] = React65.useState("preview");
|
|
13551
|
+
const [downloading, setDownloading] = React65.useState(false);
|
|
13552
|
+
const [downloadError, setDownloadError] = React65.useState(null);
|
|
13300
13553
|
const hasSide = sidePanel != null;
|
|
13301
|
-
|
|
13554
|
+
React65.useEffect(() => {
|
|
13302
13555
|
setTab("preview");
|
|
13303
13556
|
}, [file.id]);
|
|
13304
13557
|
const download = () => {
|
|
@@ -13314,29 +13567,29 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13314
13567
|
a.remove();
|
|
13315
13568
|
}).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
|
|
13316
13569
|
};
|
|
13317
|
-
return /* @__PURE__ */ (0,
|
|
13570
|
+
return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(
|
|
13318
13571
|
"section",
|
|
13319
13572
|
{
|
|
13320
13573
|
className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
|
|
13321
13574
|
"aria-label": file.name || "File",
|
|
13322
13575
|
children: [
|
|
13323
|
-
/* @__PURE__ */ (0,
|
|
13324
|
-
/* @__PURE__ */ (0,
|
|
13325
|
-
/* @__PURE__ */ (0,
|
|
13326
|
-
/* @__PURE__ */ (0,
|
|
13327
|
-
/* @__PURE__ */ (0,
|
|
13576
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("header", { className: "fd-fv-head", children: [
|
|
13577
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
|
|
13578
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fv-head-titles", children: [
|
|
13579
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
|
|
13580
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fv-head-meta", children: [
|
|
13328
13581
|
file.mime || "Unknown type",
|
|
13329
13582
|
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
13330
13583
|
] })
|
|
13331
13584
|
] }),
|
|
13332
|
-
/* @__PURE__ */ (0,
|
|
13585
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fv-head-actions", children: [
|
|
13333
13586
|
actions,
|
|
13334
|
-
/* @__PURE__ */ (0,
|
|
13335
|
-
onClose ? /* @__PURE__ */ (0,
|
|
13587
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
|
|
13588
|
+
onClose ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
|
|
13336
13589
|
] })
|
|
13337
13590
|
] }),
|
|
13338
|
-
downloadError ? /* @__PURE__ */ (0,
|
|
13339
|
-
hasSide ? /* @__PURE__ */ (0,
|
|
13591
|
+
downloadError ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
|
|
13592
|
+
hasSide ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
|
|
13340
13593
|
Tabs,
|
|
13341
13594
|
{
|
|
13342
13595
|
className: "fd-fv-tabs",
|
|
@@ -13345,19 +13598,19 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13345
13598
|
onChange: (v) => setTab(v)
|
|
13346
13599
|
}
|
|
13347
13600
|
) : null,
|
|
13348
|
-
/* @__PURE__ */ (0,
|
|
13349
|
-
/* @__PURE__ */ (0,
|
|
13601
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fv-body", children: [
|
|
13602
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
|
|
13350
13603
|
LoadingRegion,
|
|
13351
13604
|
{
|
|
13352
13605
|
state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
|
|
13353
13606
|
error: preview.error,
|
|
13354
13607
|
label: "Loading preview of " + (file.name || "file"),
|
|
13355
13608
|
onRetry: preview.status === "error" ? preview.retry : void 0,
|
|
13356
|
-
skeleton: /* @__PURE__ */ (0,
|
|
13357
|
-
children: /* @__PURE__ */ (0,
|
|
13609
|
+
skeleton: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Skeleton, { shape: "card", h: 220 }),
|
|
13610
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(PreviewBody, { file, kind, state: preview })
|
|
13358
13611
|
}
|
|
13359
13612
|
) }),
|
|
13360
|
-
hasSide ? /* @__PURE__ */ (0,
|
|
13613
|
+
hasSide ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
|
|
13361
13614
|
] })
|
|
13362
13615
|
]
|
|
13363
13616
|
}
|
|
@@ -13365,8 +13618,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13365
13618
|
}
|
|
13366
13619
|
|
|
13367
13620
|
// src/components/files/FileBrowser.tsx
|
|
13368
|
-
var
|
|
13369
|
-
var
|
|
13621
|
+
var React66 = __toESM(require("react"), 1);
|
|
13622
|
+
var import_jsx_runtime98 = require("react/jsx-runtime");
|
|
13370
13623
|
function childrenOf(folders, parentId) {
|
|
13371
13624
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
13372
13625
|
}
|
|
@@ -13438,8 +13691,8 @@ function FolderPickerMenu({
|
|
|
13438
13691
|
}) {
|
|
13439
13692
|
const panel = useInlinePanel();
|
|
13440
13693
|
const { open: open2, setOpen, ref, zIndex } = panel;
|
|
13441
|
-
return /* @__PURE__ */ (0,
|
|
13442
|
-
/* @__PURE__ */ (0,
|
|
13694
|
+
return /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("span", { className: "fd-fb-menu-anchor", ref, children: [
|
|
13695
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13443
13696
|
IconButton,
|
|
13444
13697
|
{
|
|
13445
13698
|
icon: "arrows-out-cardinal",
|
|
@@ -13451,9 +13704,9 @@ function FolderPickerMenu({
|
|
|
13451
13704
|
onClick: () => setOpen((v) => !v)
|
|
13452
13705
|
}
|
|
13453
13706
|
),
|
|
13454
|
-
open2 ? /* @__PURE__ */ (0,
|
|
13455
|
-
/* @__PURE__ */ (0,
|
|
13456
|
-
destinations.map((d) => /* @__PURE__ */ (0,
|
|
13707
|
+
open2 ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(InlinePanelLayers, { panel, children: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-menu", role: "menu", "aria-label": label, style: { zIndex }, children: [
|
|
13708
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
|
|
13709
|
+
destinations.map((d) => /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(
|
|
13457
13710
|
"button",
|
|
13458
13711
|
{
|
|
13459
13712
|
type: "button",
|
|
@@ -13465,7 +13718,7 @@ function FolderPickerMenu({
|
|
|
13465
13718
|
setOpen(false);
|
|
13466
13719
|
},
|
|
13467
13720
|
children: [
|
|
13468
|
-
/* @__PURE__ */ (0,
|
|
13721
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
|
|
13469
13722
|
d.name
|
|
13470
13723
|
]
|
|
13471
13724
|
},
|
|
@@ -13475,8 +13728,8 @@ function FolderPickerMenu({
|
|
|
13475
13728
|
] });
|
|
13476
13729
|
}
|
|
13477
13730
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
13478
|
-
const [over, setOver] =
|
|
13479
|
-
const dragCounter =
|
|
13731
|
+
const [over, setOver] = React66.useState(false);
|
|
13732
|
+
const dragCounter = React66.useRef(0);
|
|
13480
13733
|
const dropHandlers = isDropTarget ? {
|
|
13481
13734
|
onDragEnter: (e) => {
|
|
13482
13735
|
if (!hasInternalPayload(e)) return;
|
|
@@ -13501,8 +13754,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
13501
13754
|
if (payload && onDropPayload) onDropPayload(payload);
|
|
13502
13755
|
}
|
|
13503
13756
|
} : {};
|
|
13504
|
-
return /* @__PURE__ */ (0,
|
|
13505
|
-
/* @__PURE__ */ (0,
|
|
13757
|
+
return /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
|
|
13758
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(
|
|
13506
13759
|
"button",
|
|
13507
13760
|
{
|
|
13508
13761
|
type: "button",
|
|
@@ -13511,26 +13764,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
13511
13764
|
draggable: !!draggableId,
|
|
13512
13765
|
onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
|
|
13513
13766
|
children: [
|
|
13514
|
-
/* @__PURE__ */ (0,
|
|
13515
|
-
/* @__PURE__ */ (0,
|
|
13516
|
-
/* @__PURE__ */ (0,
|
|
13517
|
-
meta ? /* @__PURE__ */ (0,
|
|
13767
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("i", { className: "ph ph-" + icon }) }),
|
|
13768
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("span", { className: "fd-fb-row-text", children: [
|
|
13769
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-fb-row-name", title: name, children: name }),
|
|
13770
|
+
meta ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-fb-row-meta", children: meta }) : null
|
|
13518
13771
|
] })
|
|
13519
13772
|
]
|
|
13520
13773
|
}
|
|
13521
13774
|
),
|
|
13522
|
-
actions ? /* @__PURE__ */ (0,
|
|
13775
|
+
actions ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-fb-row-actions", children: actions }) : null
|
|
13523
13776
|
] });
|
|
13524
13777
|
}
|
|
13525
13778
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
13526
13779
|
const kids = childrenOf(folders, folder.id);
|
|
13527
|
-
const [expanded, setExpanded] =
|
|
13528
|
-
|
|
13780
|
+
const [expanded, setExpanded] = React66.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
13781
|
+
React66.useEffect(() => {
|
|
13529
13782
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
13530
13783
|
}, [currentFolderId, folder.id, folders]);
|
|
13531
13784
|
const isCurrent = folder.id === currentFolderId;
|
|
13532
|
-
return /* @__PURE__ */ (0,
|
|
13533
|
-
/* @__PURE__ */ (0,
|
|
13785
|
+
return /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-tree-node", children: [
|
|
13786
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13534
13787
|
RowShell,
|
|
13535
13788
|
{
|
|
13536
13789
|
icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
|
|
@@ -13540,7 +13793,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
|
|
|
13540
13793
|
isDropTarget: canMove,
|
|
13541
13794
|
onDropPayload: (payload) => onMoveInto(payload, folder.id),
|
|
13542
13795
|
className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
|
|
13543
|
-
actions: kids.length ? /* @__PURE__ */ (0,
|
|
13796
|
+
actions: kids.length ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13544
13797
|
IconButton,
|
|
13545
13798
|
{
|
|
13546
13799
|
icon: expanded ? "caret-down" : "caret-right",
|
|
@@ -13552,7 +13805,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
|
|
|
13552
13805
|
) : void 0
|
|
13553
13806
|
}
|
|
13554
13807
|
),
|
|
13555
|
-
expanded && kids.length ? /* @__PURE__ */ (0,
|
|
13808
|
+
expanded && kids.length ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13556
13809
|
TreeNode,
|
|
13557
13810
|
{
|
|
13558
13811
|
folder: k,
|
|
@@ -13591,15 +13844,15 @@ function FileBrowser({
|
|
|
13591
13844
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
13592
13845
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
13593
13846
|
const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
|
|
13594
|
-
const [createOpen, setCreateOpen] =
|
|
13595
|
-
const [createName, setCreateName] =
|
|
13596
|
-
const [renameTarget, setRenameTarget] =
|
|
13597
|
-
const [renameValue, setRenameValue] =
|
|
13598
|
-
const [deleteTarget, setDeleteTarget] =
|
|
13599
|
-
const uploadInputRef =
|
|
13600
|
-
const crumbFolders =
|
|
13601
|
-
const subfolders =
|
|
13602
|
-
const currentFiles =
|
|
13847
|
+
const [createOpen, setCreateOpen] = React66.useState(false);
|
|
13848
|
+
const [createName, setCreateName] = React66.useState("");
|
|
13849
|
+
const [renameTarget, setRenameTarget] = React66.useState(null);
|
|
13850
|
+
const [renameValue, setRenameValue] = React66.useState("");
|
|
13851
|
+
const [deleteTarget, setDeleteTarget] = React66.useState(null);
|
|
13852
|
+
const uploadInputRef = React66.useRef(null);
|
|
13853
|
+
const crumbFolders = React66.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
13854
|
+
const subfolders = React66.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
13855
|
+
const currentFiles = React66.useMemo(
|
|
13603
13856
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
13604
13857
|
[files, currentFolderId]
|
|
13605
13858
|
);
|
|
@@ -13638,10 +13891,10 @@ function FileBrowser({
|
|
|
13638
13891
|
if (deleteTarget && onDeleteFolder) onDeleteFolder(deleteTarget);
|
|
13639
13892
|
setDeleteTarget(null);
|
|
13640
13893
|
};
|
|
13641
|
-
const content = /* @__PURE__ */ (0,
|
|
13642
|
-
/* @__PURE__ */ (0,
|
|
13643
|
-
/* @__PURE__ */ (0,
|
|
13644
|
-
/* @__PURE__ */ (0,
|
|
13894
|
+
const content = /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
|
|
13895
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-head", children: [
|
|
13896
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
|
|
13897
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13645
13898
|
BreadcrumbCrumb,
|
|
13646
13899
|
{
|
|
13647
13900
|
label: "Home",
|
|
@@ -13651,7 +13904,7 @@ function FileBrowser({
|
|
|
13651
13904
|
onDropPayload: (p) => moveIntoFolder(p, null)
|
|
13652
13905
|
}
|
|
13653
13906
|
),
|
|
13654
|
-
crumbFolders.map((f, i) => /* @__PURE__ */ (0,
|
|
13907
|
+
crumbFolders.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13655
13908
|
BreadcrumbCrumb,
|
|
13656
13909
|
{
|
|
13657
13910
|
label: f.name,
|
|
@@ -13663,11 +13916,11 @@ function FileBrowser({
|
|
|
13663
13916
|
f.id
|
|
13664
13917
|
))
|
|
13665
13918
|
] }),
|
|
13666
|
-
/* @__PURE__ */ (0,
|
|
13667
|
-
canCreateFolder ? /* @__PURE__ */ (0,
|
|
13668
|
-
canUpload ? /* @__PURE__ */ (0,
|
|
13669
|
-
/* @__PURE__ */ (0,
|
|
13670
|
-
/* @__PURE__ */ (0,
|
|
13919
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("span", { className: "fd-fb-actions", children: [
|
|
13920
|
+
canCreateFolder ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
|
|
13921
|
+
canUpload ? /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
|
|
13922
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
|
|
13923
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13671
13924
|
"input",
|
|
13672
13925
|
{
|
|
13673
13926
|
ref: uploadInputRef,
|
|
@@ -13685,9 +13938,9 @@ function FileBrowser({
|
|
|
13685
13938
|
] }) : null
|
|
13686
13939
|
] })
|
|
13687
13940
|
] }),
|
|
13688
|
-
/* @__PURE__ */ (0,
|
|
13689
|
-
/* @__PURE__ */ (0,
|
|
13690
|
-
/* @__PURE__ */ (0,
|
|
13941
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-body", children: [
|
|
13942
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
|
|
13943
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13691
13944
|
RowShell,
|
|
13692
13945
|
{
|
|
13693
13946
|
icon: "house-simple",
|
|
@@ -13698,7 +13951,7 @@ function FileBrowser({
|
|
|
13698
13951
|
className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
|
|
13699
13952
|
}
|
|
13700
13953
|
),
|
|
13701
|
-
childrenOf(folders, null).map((f) => /* @__PURE__ */ (0,
|
|
13954
|
+
childrenOf(folders, null).map((f) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13702
13955
|
TreeNode,
|
|
13703
13956
|
{
|
|
13704
13957
|
folder: f,
|
|
@@ -13712,18 +13965,18 @@ function FileBrowser({
|
|
|
13712
13965
|
f.id
|
|
13713
13966
|
))
|
|
13714
13967
|
] }),
|
|
13715
|
-
/* @__PURE__ */ (0,
|
|
13968
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13716
13969
|
LoadingRegion,
|
|
13717
13970
|
{
|
|
13718
13971
|
state: loading ? "loading" : "ready",
|
|
13719
13972
|
label: "Loading folder contents",
|
|
13720
|
-
skeleton: /* @__PURE__ */ (0,
|
|
13721
|
-
/* @__PURE__ */ (0,
|
|
13722
|
-
/* @__PURE__ */ (0,
|
|
13723
|
-
/* @__PURE__ */ (0,
|
|
13973
|
+
skeleton: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
|
|
13974
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Skeleton, { h: 44, radius: "10px" }),
|
|
13975
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Skeleton, { h: 44, radius: "10px" }),
|
|
13976
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Skeleton, { h: 44, radius: "10px" })
|
|
13724
13977
|
] }),
|
|
13725
|
-
children: isEmpty ? /* @__PURE__ */ (0,
|
|
13726
|
-
subfolders.map((f) => /* @__PURE__ */ (0,
|
|
13978
|
+
children: isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(EmptyState, { icon: "folder-open", title: "This folder is empty", children: canUpload ? "Drop files here, or use Upload above." : "Nothing has been filed here yet." }) : /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-list", children: [
|
|
13979
|
+
subfolders.map((f) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13727
13980
|
RowShell,
|
|
13728
13981
|
{
|
|
13729
13982
|
icon: "folder-simple",
|
|
@@ -13732,9 +13985,9 @@ function FileBrowser({
|
|
|
13732
13985
|
draggableId: canMove ? { kind: "folder", id: f.id } : void 0,
|
|
13733
13986
|
isDropTarget: canMove,
|
|
13734
13987
|
onDropPayload: (p) => moveIntoFolder(p, f.id),
|
|
13735
|
-
actions: /* @__PURE__ */ (0,
|
|
13736
|
-
canRenameFolder ? /* @__PURE__ */ (0,
|
|
13737
|
-
canMove ? /* @__PURE__ */ (0,
|
|
13988
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
|
|
13989
|
+
canRenameFolder ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
|
|
13990
|
+
canMove ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13738
13991
|
FolderPickerMenu,
|
|
13739
13992
|
{
|
|
13740
13993
|
label: "Move " + f.name,
|
|
@@ -13742,12 +13995,12 @@ function FileBrowser({
|
|
|
13742
13995
|
onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
|
|
13743
13996
|
}
|
|
13744
13997
|
) : null,
|
|
13745
|
-
canDeleteFolder ? /* @__PURE__ */ (0,
|
|
13998
|
+
canDeleteFolder ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
|
|
13746
13999
|
] })
|
|
13747
14000
|
},
|
|
13748
14001
|
f.id
|
|
13749
14002
|
)),
|
|
13750
|
-
currentFiles.map((file) => /* @__PURE__ */ (0,
|
|
14003
|
+
currentFiles.map((file) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13751
14004
|
RowShell,
|
|
13752
14005
|
{
|
|
13753
14006
|
icon: iconForMime(file.mime, file.name),
|
|
@@ -13755,8 +14008,8 @@ function FileBrowser({
|
|
|
13755
14008
|
meta: file.size ? formatBytes(file.size) : void 0,
|
|
13756
14009
|
onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
|
|
13757
14010
|
draggableId: canMove ? { kind: "file", id: file.id } : void 0,
|
|
13758
|
-
actions: /* @__PURE__ */ (0,
|
|
13759
|
-
canMove ? /* @__PURE__ */ (0,
|
|
14011
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
|
|
14012
|
+
canMove ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13760
14013
|
FolderPickerMenu,
|
|
13761
14014
|
{
|
|
13762
14015
|
label: "Move " + file.name,
|
|
@@ -13764,7 +14017,7 @@ function FileBrowser({
|
|
|
13764
14017
|
onPick: (target) => onMoveFile && onMoveFile(file.id, target)
|
|
13765
14018
|
}
|
|
13766
14019
|
) : null,
|
|
13767
|
-
canRemoveFile ? /* @__PURE__ */ (0,
|
|
14020
|
+
canRemoveFile ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
|
|
13768
14021
|
] })
|
|
13769
14022
|
},
|
|
13770
14023
|
file.id
|
|
@@ -13773,10 +14026,10 @@ function FileBrowser({
|
|
|
13773
14026
|
}
|
|
13774
14027
|
) })
|
|
13775
14028
|
] }),
|
|
13776
|
-
/* @__PURE__ */ (0,
|
|
13777
|
-
/* @__PURE__ */ (0,
|
|
13778
|
-
/* @__PURE__ */ (0,
|
|
13779
|
-
] }), children: /* @__PURE__ */ (0,
|
|
14029
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
|
|
14030
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
|
|
14031
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
|
|
14032
|
+
] }), children: /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13780
14033
|
"input",
|
|
13781
14034
|
{
|
|
13782
14035
|
className: "fd-fb-input",
|
|
@@ -13790,10 +14043,10 @@ function FileBrowser({
|
|
|
13790
14043
|
autoFocus: true
|
|
13791
14044
|
}
|
|
13792
14045
|
) }),
|
|
13793
|
-
/* @__PURE__ */ (0,
|
|
13794
|
-
/* @__PURE__ */ (0,
|
|
13795
|
-
/* @__PURE__ */ (0,
|
|
13796
|
-
] }), children: /* @__PURE__ */ (0,
|
|
14046
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
|
|
14047
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
|
|
14048
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
|
|
14049
|
+
] }), children: /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13797
14050
|
"input",
|
|
13798
14051
|
{
|
|
13799
14052
|
className: "fd-fb-input",
|
|
@@ -13807,22 +14060,22 @@ function FileBrowser({
|
|
|
13807
14060
|
autoFocus: true
|
|
13808
14061
|
}
|
|
13809
14062
|
) }),
|
|
13810
|
-
/* @__PURE__ */ (0,
|
|
14063
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13811
14064
|
Modal,
|
|
13812
14065
|
{
|
|
13813
14066
|
open: deleteTarget != null,
|
|
13814
14067
|
title: deleteTarget ? "Delete \u201C" + deleteTarget.name + "\u201D?" : "Delete folder?",
|
|
13815
14068
|
description: "This can't be undone. The folder must be empty.",
|
|
13816
14069
|
onClose: () => setDeleteTarget(null),
|
|
13817
|
-
footer: /* @__PURE__ */ (0,
|
|
13818
|
-
/* @__PURE__ */ (0,
|
|
13819
|
-
/* @__PURE__ */ (0,
|
|
14070
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
|
|
14071
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
|
|
14072
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
|
|
13820
14073
|
] })
|
|
13821
14074
|
}
|
|
13822
14075
|
)
|
|
13823
14076
|
] });
|
|
13824
14077
|
if (!canUpload) return content;
|
|
13825
|
-
return /* @__PURE__ */ (0,
|
|
14078
|
+
return /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
|
|
13826
14079
|
}
|
|
13827
14080
|
function BreadcrumbCrumb({
|
|
13828
14081
|
label,
|
|
@@ -13831,8 +14084,8 @@ function BreadcrumbCrumb({
|
|
|
13831
14084
|
isDropTarget,
|
|
13832
14085
|
onDropPayload
|
|
13833
14086
|
}) {
|
|
13834
|
-
const [over, setOver] =
|
|
13835
|
-
const dragCounter =
|
|
14087
|
+
const [over, setOver] = React66.useState(false);
|
|
14088
|
+
const dragCounter = React66.useRef(0);
|
|
13836
14089
|
const dropHandlers = isDropTarget ? {
|
|
13837
14090
|
onDragEnter: (e) => {
|
|
13838
14091
|
if (!hasInternalPayload(e)) return;
|
|
@@ -13857,11 +14110,11 @@ function BreadcrumbCrumb({
|
|
|
13857
14110
|
if (payload && onDropPayload) onDropPayload(payload);
|
|
13858
14111
|
}
|
|
13859
14112
|
} : {};
|
|
13860
|
-
return /* @__PURE__ */ (0,
|
|
14113
|
+
return /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
|
|
13861
14114
|
}
|
|
13862
14115
|
|
|
13863
14116
|
// src/kits/query.ts
|
|
13864
|
-
var
|
|
14117
|
+
var React67 = __toESM(require("react"), 1);
|
|
13865
14118
|
var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
|
|
13866
14119
|
var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
|
|
13867
14120
|
var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
|
|
@@ -13916,22 +14169,22 @@ function compare(a, b, dir) {
|
|
|
13916
14169
|
var API = null;
|
|
13917
14170
|
var PREFS = null;
|
|
13918
14171
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
13919
|
-
const [query, setQuery] =
|
|
14172
|
+
const [query, setQuery] = React67.useState(() => {
|
|
13920
14173
|
const store = PREFS || window.PlannerPrefs;
|
|
13921
14174
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
13922
14175
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
13923
14176
|
});
|
|
13924
|
-
const savePref =
|
|
14177
|
+
const savePref = React67.useCallback((patch2) => {
|
|
13925
14178
|
const store = PREFS || window.PlannerPrefs;
|
|
13926
14179
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
13927
14180
|
}, [prefsKey]);
|
|
13928
|
-
const [res, setRes] =
|
|
13929
|
-
const [loading, setLoading] =
|
|
13930
|
-
const seq2 =
|
|
14181
|
+
const [res, setRes] = React67.useState(null);
|
|
14182
|
+
const [loading, setLoading] = React67.useState(true);
|
|
14183
|
+
const seq2 = React67.useRef(0);
|
|
13931
14184
|
const depKey = (deps || []).join("|");
|
|
13932
14185
|
const paramKey = JSON.stringify(params || {});
|
|
13933
14186
|
const queryKey = JSON.stringify(query);
|
|
13934
|
-
|
|
14187
|
+
React67.useEffect(() => {
|
|
13935
14188
|
const id = ++seq2.current;
|
|
13936
14189
|
setLoading(true);
|
|
13937
14190
|
const t = setTimeout(() => {
|
|
@@ -14250,12 +14503,12 @@ function createVersionStore(initialState, options) {
|
|
|
14250
14503
|
}
|
|
14251
14504
|
|
|
14252
14505
|
// src/kits/documentTitle.ts
|
|
14253
|
-
var
|
|
14506
|
+
var React68 = __toESM(require("react"), 1);
|
|
14254
14507
|
function formatDocumentTitle(routeTitle, appName) {
|
|
14255
14508
|
return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
|
|
14256
14509
|
}
|
|
14257
14510
|
function useDocumentTitle(routeTitle, appName) {
|
|
14258
|
-
|
|
14511
|
+
React68.useEffect(() => {
|
|
14259
14512
|
if (typeof document === "undefined") return;
|
|
14260
14513
|
document.title = formatDocumentTitle(routeTitle, appName);
|
|
14261
14514
|
}, [routeTitle, appName]);
|
|
@@ -14298,6 +14551,7 @@ function useDocumentTitle(routeTitle, appName) {
|
|
|
14298
14551
|
Clamp,
|
|
14299
14552
|
ClockFace,
|
|
14300
14553
|
CodeBlock,
|
|
14554
|
+
CodeEditor,
|
|
14301
14555
|
Collapsible,
|
|
14302
14556
|
ComingSoon,
|
|
14303
14557
|
CsiBadge,
|