@flytedan/flytebot-design-system 0.48.1 → 0.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1172 -933
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +46 -1
- package/dist/index.d.ts +46 -1
- package/dist/index.js +1171 -933
- package/dist/index.js.map +1 -1
- package/package.json +7 -1
- package/styles/components.css +69 -0
package/dist/index.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,
|
|
@@ -4885,7 +4886,7 @@ function CodeBlock({
|
|
|
4885
4886
|
code = "",
|
|
4886
4887
|
language,
|
|
4887
4888
|
filename,
|
|
4888
|
-
lineNumbers = false,
|
|
4889
|
+
lineNumbers: lineNumbers2 = false,
|
|
4889
4890
|
wrap: wrapDefault = false,
|
|
4890
4891
|
collapseAfter = 26,
|
|
4891
4892
|
copyable = true,
|
|
@@ -4912,7 +4913,7 @@ function CodeBlock({
|
|
|
4912
4913
|
] }) : null
|
|
4913
4914
|
] }),
|
|
4914
4915
|
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-code-body", children: [
|
|
4915
|
-
|
|
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,
|
|
4916
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 }) }) })
|
|
4917
4918
|
] }),
|
|
4918
4919
|
foldable ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("button", { type: "button", className: "fd-code-fold", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
@@ -7495,17 +7496,254 @@ var MarkdownEditor = React42.forwardRef(function MarkdownEditor2({
|
|
|
7495
7496
|
] });
|
|
7496
7497
|
});
|
|
7497
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
|
+
|
|
7498
7736
|
// src/components/platform/AccountMenu.tsx
|
|
7499
|
-
var
|
|
7737
|
+
var React45 = __toESM(require("react"), 1);
|
|
7500
7738
|
|
|
7501
7739
|
// src/kits/sessionContext.tsx
|
|
7502
|
-
var
|
|
7503
|
-
var SessionContext =
|
|
7740
|
+
var React44 = __toESM(require("react"), 1);
|
|
7741
|
+
var SessionContext = React44.createContext(null);
|
|
7504
7742
|
function SessionProvider({ value, children }) {
|
|
7505
|
-
return
|
|
7743
|
+
return React44.createElement(SessionContext.Provider, { value }, children);
|
|
7506
7744
|
}
|
|
7507
7745
|
function useSessionContext() {
|
|
7508
|
-
const ctx =
|
|
7746
|
+
const ctx = React44.useContext(SessionContext);
|
|
7509
7747
|
if (!ctx) {
|
|
7510
7748
|
throw new Error(
|
|
7511
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."
|
|
@@ -7515,11 +7753,11 @@ function useSessionContext() {
|
|
|
7515
7753
|
}
|
|
7516
7754
|
|
|
7517
7755
|
// src/components/platform/AccountMenu.tsx
|
|
7518
|
-
var
|
|
7756
|
+
var import_jsx_runtime74 = require("react/jsx-runtime");
|
|
7519
7757
|
var DEFAULT_LINKS = [];
|
|
7520
7758
|
var DEFAULT_GROUPS = [];
|
|
7521
7759
|
function Item({ item, onPick }) {
|
|
7522
|
-
return /* @__PURE__ */ (0,
|
|
7760
|
+
return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
|
|
7523
7761
|
"button",
|
|
7524
7762
|
{
|
|
7525
7763
|
type: "button",
|
|
@@ -7527,9 +7765,9 @@ function Item({ item, onPick }) {
|
|
|
7527
7765
|
className: "fd-acct-item",
|
|
7528
7766
|
onClick: () => onPick(item),
|
|
7529
7767
|
children: [
|
|
7530
|
-
item.icon ? /* @__PURE__ */ (0,
|
|
7531
|
-
/* @__PURE__ */ (0,
|
|
7532
|
-
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
|
|
7533
7771
|
]
|
|
7534
7772
|
}
|
|
7535
7773
|
);
|
|
@@ -7545,11 +7783,11 @@ function AccountMenu({
|
|
|
7545
7783
|
...rest
|
|
7546
7784
|
}) {
|
|
7547
7785
|
const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
|
|
7548
|
-
const [open2, setOpen] =
|
|
7549
|
-
const [switching, setSwitching] =
|
|
7550
|
-
const [signingOut, setSigningOut] =
|
|
7551
|
-
const [signOutError, setSignOutError] =
|
|
7552
|
-
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);
|
|
7553
7791
|
const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
|
|
7554
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);
|
|
7555
7793
|
const closeMenu = () => {
|
|
@@ -7577,8 +7815,8 @@ function AccountMenu({
|
|
|
7577
7815
|
}
|
|
7578
7816
|
};
|
|
7579
7817
|
const showSwitcher = allowUserSwitch && !!demo;
|
|
7580
|
-
return /* @__PURE__ */ (0,
|
|
7581
|
-
/* @__PURE__ */ (0,
|
|
7818
|
+
return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(import_jsx_runtime74.Fragment, { children: [
|
|
7819
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
|
|
7582
7820
|
"button",
|
|
7583
7821
|
{
|
|
7584
7822
|
type: "button",
|
|
@@ -7590,12 +7828,12 @@ function AccountMenu({
|
|
|
7590
7828
|
onClick: () => open2 ? closeMenu() : setOpen(true),
|
|
7591
7829
|
...rest,
|
|
7592
7830
|
children: [
|
|
7593
|
-
/* @__PURE__ */ (0,
|
|
7594
|
-
/* @__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)" } })
|
|
7595
7833
|
]
|
|
7596
7834
|
}
|
|
7597
7835
|
),
|
|
7598
|
-
/* @__PURE__ */ (0,
|
|
7836
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
|
|
7599
7837
|
Popover,
|
|
7600
7838
|
{
|
|
7601
7839
|
open: open2,
|
|
@@ -7603,27 +7841,27 @@ function AccountMenu({
|
|
|
7603
7841
|
onClose: closeMenu,
|
|
7604
7842
|
placement: "bottom-end",
|
|
7605
7843
|
width: 272,
|
|
7606
|
-
children: /* @__PURE__ */ (0,
|
|
7607
|
-
/* @__PURE__ */ (0,
|
|
7608
|
-
/* @__PURE__ */ (0,
|
|
7609
|
-
/* @__PURE__ */ (0,
|
|
7610
|
-
/* @__PURE__ */ (0,
|
|
7611
|
-
/* @__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 })
|
|
7612
7850
|
] })
|
|
7613
7851
|
] }),
|
|
7614
|
-
showRoles && roles.length ? /* @__PURE__ */ (0,
|
|
7615
|
-
visibleLinks.length ? /* @__PURE__ */ (0,
|
|
7616
|
-
visibleGroups.map((g) => /* @__PURE__ */ (0,
|
|
7617
|
-
/* @__PURE__ */ (0,
|
|
7618
|
-
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))
|
|
7619
7857
|
] }, g.label)),
|
|
7620
|
-
showSwitcher && demo ? /* @__PURE__ */ (0,
|
|
7621
|
-
/* @__PURE__ */ (0,
|
|
7622
|
-
/* @__PURE__ */ (0,
|
|
7623
|
-
/* @__PURE__ */ (0,
|
|
7624
|
-
/* @__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 } })
|
|
7625
7863
|
] }),
|
|
7626
|
-
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)(
|
|
7627
7865
|
"button",
|
|
7628
7866
|
{
|
|
7629
7867
|
type: "button",
|
|
@@ -7635,19 +7873,19 @@ function AccountMenu({
|
|
|
7635
7873
|
setSwitching(false);
|
|
7636
7874
|
},
|
|
7637
7875
|
children: [
|
|
7638
|
-
/* @__PURE__ */ (0,
|
|
7639
|
-
/* @__PURE__ */ (0,
|
|
7640
|
-
/* @__PURE__ */ (0,
|
|
7641
|
-
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
|
|
7642
7880
|
] }),
|
|
7643
|
-
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
|
|
7644
7882
|
]
|
|
7645
7883
|
},
|
|
7646
7884
|
u.id
|
|
7647
7885
|
)) }) : null
|
|
7648
7886
|
] }) : null,
|
|
7649
|
-
/* @__PURE__ */ (0,
|
|
7650
|
-
/* @__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)(
|
|
7651
7889
|
"button",
|
|
7652
7890
|
{
|
|
7653
7891
|
type: "button",
|
|
@@ -7657,14 +7895,14 @@ function AccountMenu({
|
|
|
7657
7895
|
disabled: signingOut,
|
|
7658
7896
|
onClick: signOut,
|
|
7659
7897
|
children: [
|
|
7660
|
-
signingOut ? /* @__PURE__ */ (0,
|
|
7661
|
-
/* @__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" })
|
|
7662
7900
|
]
|
|
7663
7901
|
}
|
|
7664
7902
|
),
|
|
7665
|
-
signOutError ? /* @__PURE__ */ (0,
|
|
7666
|
-
/* @__PURE__ */ (0,
|
|
7667
|
-
/* @__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" })
|
|
7668
7906
|
] }) : null
|
|
7669
7907
|
] })
|
|
7670
7908
|
] })
|
|
@@ -7674,13 +7912,13 @@ function AccountMenu({
|
|
|
7674
7912
|
}
|
|
7675
7913
|
|
|
7676
7914
|
// src/components/platform/AppSwitcher.tsx
|
|
7677
|
-
var
|
|
7678
|
-
var
|
|
7915
|
+
var React46 = __toESM(require("react"), 1);
|
|
7916
|
+
var import_jsx_runtime75 = require("react/jsx-runtime");
|
|
7679
7917
|
function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
7680
7918
|
const { apps: contextApps } = useSessionContext();
|
|
7681
7919
|
const apps = appsProp ?? contextApps ?? [];
|
|
7682
|
-
const [open2, setOpen] =
|
|
7683
|
-
const anchorRef =
|
|
7920
|
+
const [open2, setOpen] = React46.useState(false);
|
|
7921
|
+
const anchorRef = React46.useRef(null);
|
|
7684
7922
|
if (!apps.length) return null;
|
|
7685
7923
|
const items = apps.map((app) => ({
|
|
7686
7924
|
id: app.key,
|
|
@@ -7694,8 +7932,8 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7694
7932
|
window.location.href = app.url;
|
|
7695
7933
|
}
|
|
7696
7934
|
}));
|
|
7697
|
-
return /* @__PURE__ */ (0,
|
|
7698
|
-
/* @__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)(
|
|
7699
7937
|
IconButton,
|
|
7700
7938
|
{
|
|
7701
7939
|
icon: "squares-four",
|
|
@@ -7705,7 +7943,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7705
7943
|
onClick: () => setOpen((v) => !v)
|
|
7706
7944
|
}
|
|
7707
7945
|
) }),
|
|
7708
|
-
/* @__PURE__ */ (0,
|
|
7946
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
|
|
7709
7947
|
Popover,
|
|
7710
7948
|
{
|
|
7711
7949
|
open: open2,
|
|
@@ -7716,17 +7954,17 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7716
7954
|
label: "All flytedesk apps",
|
|
7717
7955
|
width: 240,
|
|
7718
7956
|
maxHeight: 360,
|
|
7719
|
-
children: /* @__PURE__ */ (0,
|
|
7957
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(Menu, { items, onClose: () => setOpen(false) })
|
|
7720
7958
|
}
|
|
7721
7959
|
)
|
|
7722
7960
|
] });
|
|
7723
7961
|
}
|
|
7724
7962
|
|
|
7725
7963
|
// src/components/platform/AppearanceMenu.tsx
|
|
7726
|
-
var
|
|
7964
|
+
var React48 = __toESM(require("react"), 1);
|
|
7727
7965
|
|
|
7728
7966
|
// src/kits/appearance.ts
|
|
7729
|
-
var
|
|
7967
|
+
var React47 = __toESM(require("react"), 1);
|
|
7730
7968
|
var DEFAULT_STORAGE_KEY = "fd-appearance";
|
|
7731
7969
|
var DEFAULT_PREFS = {
|
|
7732
7970
|
theme: "system",
|
|
@@ -7821,11 +8059,11 @@ function applyPrefs(prefs, root = document.documentElement) {
|
|
|
7821
8059
|
else root.removeAttribute("data-motion");
|
|
7822
8060
|
}
|
|
7823
8061
|
function useAppearancePrefs(store) {
|
|
7824
|
-
const prefs =
|
|
7825
|
-
|
|
8062
|
+
const prefs = React47.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
8063
|
+
React47.useEffect(() => {
|
|
7826
8064
|
applyPrefs(prefs);
|
|
7827
8065
|
}, [prefs]);
|
|
7828
|
-
|
|
8066
|
+
React47.useEffect(() => {
|
|
7829
8067
|
if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
7830
8068
|
return;
|
|
7831
8069
|
}
|
|
@@ -7834,7 +8072,7 @@ function useAppearancePrefs(store) {
|
|
|
7834
8072
|
mq.addEventListener("change", onChange);
|
|
7835
8073
|
return () => mq.removeEventListener("change", onChange);
|
|
7836
8074
|
}, [prefs]);
|
|
7837
|
-
const update =
|
|
8075
|
+
const update = React47.useCallback(
|
|
7838
8076
|
(patch) => {
|
|
7839
8077
|
store.write({ ...store.getSnapshot(), ...patch });
|
|
7840
8078
|
},
|
|
@@ -7844,7 +8082,7 @@ function useAppearancePrefs(store) {
|
|
|
7844
8082
|
}
|
|
7845
8083
|
|
|
7846
8084
|
// src/components/platform/AppearanceMenu.tsx
|
|
7847
|
-
var
|
|
8085
|
+
var import_jsx_runtime76 = require("react/jsx-runtime");
|
|
7848
8086
|
var THEME_OPTIONS = [
|
|
7849
8087
|
{ value: "light", label: "Light" },
|
|
7850
8088
|
{ value: "dark", label: "Dark" },
|
|
@@ -7857,16 +8095,16 @@ var TEXT_SCALE_OPTIONS = [
|
|
|
7857
8095
|
{ value: "xl", label: "XL" }
|
|
7858
8096
|
];
|
|
7859
8097
|
function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
|
|
7860
|
-
const store =
|
|
8098
|
+
const store = React48.useMemo(
|
|
7861
8099
|
() => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
|
|
7862
8100
|
[storeProp, storageKey, storage, defaults]
|
|
7863
8101
|
);
|
|
7864
8102
|
const [prefs, update] = useAppearancePrefs(store);
|
|
7865
|
-
const [open2, setOpen] =
|
|
7866
|
-
const anchorRef =
|
|
8103
|
+
const [open2, setOpen] = React48.useState(false);
|
|
8104
|
+
const anchorRef = React48.useRef(null);
|
|
7867
8105
|
const patch = (p) => update(p);
|
|
7868
|
-
return /* @__PURE__ */ (0,
|
|
7869
|
-
/* @__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)(
|
|
7870
8108
|
IconButton,
|
|
7871
8109
|
{
|
|
7872
8110
|
icon: "circle-half",
|
|
@@ -7874,7 +8112,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7874
8112
|
onClick: () => setOpen((v) => !v)
|
|
7875
8113
|
}
|
|
7876
8114
|
) }),
|
|
7877
|
-
/* @__PURE__ */ (0,
|
|
8115
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
7878
8116
|
Popover,
|
|
7879
8117
|
{
|
|
7880
8118
|
open: open2,
|
|
@@ -7884,10 +8122,10 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7884
8122
|
padded: true,
|
|
7885
8123
|
width: 260,
|
|
7886
8124
|
label: "Appearance settings",
|
|
7887
|
-
children: /* @__PURE__ */ (0,
|
|
7888
|
-
/* @__PURE__ */ (0,
|
|
7889
|
-
/* @__PURE__ */ (0,
|
|
7890
|
-
/* @__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)(
|
|
7891
8129
|
SegmentedControl,
|
|
7892
8130
|
{
|
|
7893
8131
|
options: THEME_OPTIONS,
|
|
@@ -7897,9 +8135,9 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7897
8135
|
}
|
|
7898
8136
|
)
|
|
7899
8137
|
] }),
|
|
7900
|
-
/* @__PURE__ */ (0,
|
|
7901
|
-
/* @__PURE__ */ (0,
|
|
7902
|
-
/* @__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)(
|
|
7903
8141
|
SegmentedControl,
|
|
7904
8142
|
{
|
|
7905
8143
|
options: TEXT_SCALE_OPTIONS,
|
|
@@ -7909,7 +8147,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7909
8147
|
}
|
|
7910
8148
|
)
|
|
7911
8149
|
] }),
|
|
7912
|
-
/* @__PURE__ */ (0,
|
|
8150
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
7913
8151
|
Switch,
|
|
7914
8152
|
{
|
|
7915
8153
|
label: "High contrast",
|
|
@@ -7918,7 +8156,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7918
8156
|
onChange: (e) => patch({ highContrast: e.target.checked })
|
|
7919
8157
|
}
|
|
7920
8158
|
),
|
|
7921
|
-
/* @__PURE__ */ (0,
|
|
8159
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
7922
8160
|
Switch,
|
|
7923
8161
|
{
|
|
7924
8162
|
label: "Reduce motion",
|
|
@@ -7934,14 +8172,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7934
8172
|
}
|
|
7935
8173
|
|
|
7936
8174
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
7937
|
-
var
|
|
7938
|
-
var
|
|
8175
|
+
var React49 = __toESM(require("react"), 1);
|
|
8176
|
+
var import_jsx_runtime77 = require("react/jsx-runtime");
|
|
7939
8177
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
7940
8178
|
function Json({ obj }) {
|
|
7941
|
-
return /* @__PURE__ */ (0,
|
|
8179
|
+
return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
7942
8180
|
}
|
|
7943
8181
|
function Endpoint({ s, onRequest }) {
|
|
7944
|
-
const [tried, setTried] =
|
|
8182
|
+
const [tried, setTried] = React49.useState(null);
|
|
7945
8183
|
const run = async () => {
|
|
7946
8184
|
setTried("busy");
|
|
7947
8185
|
const t0 = (window.performance || Date).now();
|
|
@@ -7952,50 +8190,50 @@ function Endpoint({ s, onRequest }) {
|
|
|
7952
8190
|
setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
|
|
7953
8191
|
}
|
|
7954
8192
|
};
|
|
7955
|
-
return /* @__PURE__ */ (0,
|
|
7956
|
-
/* @__PURE__ */ (0,
|
|
7957
|
-
/* @__PURE__ */ (0,
|
|
7958
|
-
/* @__PURE__ */ (0,
|
|
7959
|
-
s.isList ? /* @__PURE__ */ (0,
|
|
7960
|
-
/* @__PURE__ */ (0,
|
|
7961
|
-
/* @__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: [
|
|
7962
8200
|
s.latency[0],
|
|
7963
8201
|
"\u2013",
|
|
7964
8202
|
s.latency[1],
|
|
7965
8203
|
"ms"
|
|
7966
8204
|
] }),
|
|
7967
|
-
/* @__PURE__ */ (0,
|
|
8205
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
|
|
7968
8206
|
] }),
|
|
7969
|
-
/* @__PURE__ */ (0,
|
|
7970
|
-
/* @__PURE__ */ (0,
|
|
7971
|
-
/* @__PURE__ */ (0,
|
|
7972
|
-
/* @__PURE__ */ (0,
|
|
7973
|
-
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
|
|
7974
8212
|
] }),
|
|
7975
|
-
/* @__PURE__ */ (0,
|
|
7976
|
-
s.request ? /* @__PURE__ */ (0,
|
|
7977
|
-
/* @__PURE__ */ (0,
|
|
7978
|
-
/* @__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 })
|
|
7979
8217
|
] }) : null,
|
|
7980
|
-
s.query ? /* @__PURE__ */ (0,
|
|
7981
|
-
/* @__PURE__ */ (0,
|
|
7982
|
-
/* @__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 })
|
|
7983
8221
|
] }) : null,
|
|
7984
|
-
/* @__PURE__ */ (0,
|
|
7985
|
-
/* @__PURE__ */ (0,
|
|
7986
|
-
/* @__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 })
|
|
7987
8225
|
] })
|
|
7988
8226
|
] }),
|
|
7989
|
-
s.notes ? /* @__PURE__ */ (0,
|
|
7990
|
-
tried && tried !== "busy" ? /* @__PURE__ */ (0,
|
|
7991
|
-
/* @__PURE__ */ (0,
|
|
7992
|
-
/* @__PURE__ */ (0,
|
|
7993
|
-
/* @__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: [
|
|
7994
8232
|
tried.ms,
|
|
7995
8233
|
"ms"
|
|
7996
8234
|
] })
|
|
7997
8235
|
] }),
|
|
7998
|
-
/* @__PURE__ */ (0,
|
|
8236
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
|
|
7999
8237
|
] }) : null
|
|
8000
8238
|
] })
|
|
8001
8239
|
] }) });
|
|
@@ -8014,58 +8252,58 @@ function ApiSpecBrowser({
|
|
|
8014
8252
|
className = "",
|
|
8015
8253
|
...rest
|
|
8016
8254
|
}) {
|
|
8017
|
-
const [q, setQ] =
|
|
8018
|
-
const [method, setMethod] =
|
|
8019
|
-
const [mod, setMod] =
|
|
8020
|
-
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);
|
|
8021
8259
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
8022
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())));
|
|
8023
8261
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
8024
8262
|
const methods = [...new Set(spec.map((s) => s.method))];
|
|
8025
8263
|
const listCount = spec.filter((s) => s.isList).length;
|
|
8026
|
-
return /* @__PURE__ */ (0,
|
|
8027
|
-
/* @__PURE__ */ (0,
|
|
8028
|
-
kicker ? /* @__PURE__ */ (0,
|
|
8029
|
-
/* @__PURE__ */ (0,
|
|
8030
|
-
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
|
|
8031
8269
|
] }),
|
|
8032
|
-
modules && modules.length ? /* @__PURE__ */ (0,
|
|
8033
|
-
/* @__PURE__ */ (0,
|
|
8034
|
-
/* @__PURE__ */ (0,
|
|
8035
|
-
/* @__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: [
|
|
8036
8274
|
"All screens ",
|
|
8037
|
-
/* @__PURE__ */ (0,
|
|
8275
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-mono", children: spec.length })
|
|
8038
8276
|
] }),
|
|
8039
|
-
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: [
|
|
8040
8278
|
m.label,
|
|
8041
8279
|
" ",
|
|
8042
|
-
/* @__PURE__ */ (0,
|
|
8280
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
|
|
8043
8281
|
] }, m.id))
|
|
8044
8282
|
] }),
|
|
8045
|
-
activeModule ? /* @__PURE__ */ (0,
|
|
8283
|
+
activeModule ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
8046
8284
|
Flag,
|
|
8047
8285
|
{
|
|
8048
8286
|
tone: "info",
|
|
8049
8287
|
statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
|
|
8050
8288
|
cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
|
|
8051
|
-
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" })
|
|
8052
8290
|
}
|
|
8053
8291
|
) : null
|
|
8054
8292
|
] }) : null,
|
|
8055
|
-
sourceNote ? /* @__PURE__ */ (0,
|
|
8056
|
-
/* @__PURE__ */ (0,
|
|
8057
|
-
/* @__PURE__ */ (0,
|
|
8058
|
-
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: [
|
|
8059
8297
|
m,
|
|
8060
8298
|
" ",
|
|
8061
|
-
/* @__PURE__ */ (0,
|
|
8299
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
|
|
8062
8300
|
] }, m)),
|
|
8063
|
-
listCount ? /* @__PURE__ */ (0,
|
|
8301
|
+
listCount ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
|
|
8064
8302
|
"Paged lists ",
|
|
8065
|
-
/* @__PURE__ */ (0,
|
|
8303
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-mono", children: listCount })
|
|
8066
8304
|
] }) : null,
|
|
8067
|
-
/* @__PURE__ */ (0,
|
|
8068
|
-
/* @__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: [
|
|
8069
8307
|
hits.length,
|
|
8070
8308
|
" of ",
|
|
8071
8309
|
spec.length,
|
|
@@ -8073,31 +8311,31 @@ function ApiSpecBrowser({
|
|
|
8073
8311
|
listCount ? " \xB7 " + listCount + " paged" : ""
|
|
8074
8312
|
] })
|
|
8075
8313
|
] }),
|
|
8076
|
-
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]) => {
|
|
8077
8315
|
const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
|
|
8078
8316
|
if (!items.length) return null;
|
|
8079
|
-
return /* @__PURE__ */ (0,
|
|
8080
|
-
/* @__PURE__ */ (0,
|
|
8081
|
-
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))
|
|
8082
8320
|
] }, g);
|
|
8083
8321
|
}),
|
|
8084
|
-
conventions && conventions.length ? /* @__PURE__ */ (0,
|
|
8085
|
-
/* @__PURE__ */ (0,
|
|
8086
|
-
/* @__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 })
|
|
8087
8325
|
] }, k)) }) }) : null,
|
|
8088
|
-
openQuestions && openQuestions.length ? /* @__PURE__ */ (0,
|
|
8089
|
-
/* @__PURE__ */ (0,
|
|
8090
|
-
/* @__PURE__ */ (0,
|
|
8091
|
-
/* @__PURE__ */ (0,
|
|
8092
|
-
/* @__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 })
|
|
8093
8331
|
] })
|
|
8094
8332
|
] }, id)) }) }) : null
|
|
8095
8333
|
] });
|
|
8096
8334
|
}
|
|
8097
8335
|
|
|
8098
8336
|
// src/components/platform/ProfilePage.tsx
|
|
8099
|
-
var
|
|
8100
|
-
var
|
|
8337
|
+
var React50 = __toESM(require("react"), 1);
|
|
8338
|
+
var import_jsx_runtime78 = require("react/jsx-runtime");
|
|
8101
8339
|
function fieldInitialValue(field, user) {
|
|
8102
8340
|
if (field.value) return field.value(user);
|
|
8103
8341
|
const raw = user[field.key];
|
|
@@ -8132,21 +8370,21 @@ function ProfilePage({
|
|
|
8132
8370
|
}) {
|
|
8133
8371
|
const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
|
|
8134
8372
|
const user = userProp || sessionUser;
|
|
8135
|
-
const initialFieldValues =
|
|
8373
|
+
const initialFieldValues = React50.useMemo(() => {
|
|
8136
8374
|
const values2 = {};
|
|
8137
8375
|
for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
|
|
8138
8376
|
return values2;
|
|
8139
8377
|
}, [user.id, fields]);
|
|
8140
|
-
const initialNotify =
|
|
8378
|
+
const initialNotify = React50.useMemo(() => {
|
|
8141
8379
|
const values2 = {};
|
|
8142
8380
|
for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
|
|
8143
8381
|
return values2;
|
|
8144
8382
|
}, [user.id, notifications]);
|
|
8145
|
-
const [values, setValues] =
|
|
8146
|
-
const [notify, setNotify] =
|
|
8147
|
-
const [saving, setSaving] =
|
|
8148
|
-
const [saved, setSaved] =
|
|
8149
|
-
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);
|
|
8150
8388
|
if (user.id !== prevUserId) {
|
|
8151
8389
|
setPrevUserId(user.id);
|
|
8152
8390
|
setValues(initialFieldValues);
|
|
@@ -8183,37 +8421,37 @@ function ProfilePage({
|
|
|
8183
8421
|
};
|
|
8184
8422
|
const displayName = fields.some((f) => f.key === "name") ? values.name || user.name : user.name;
|
|
8185
8423
|
const fieldGroups = groupFields(fields);
|
|
8186
|
-
return /* @__PURE__ */ (0,
|
|
8187
|
-
/* @__PURE__ */ (0,
|
|
8188
|
-
/* @__PURE__ */ (0,
|
|
8189
|
-
/* @__PURE__ */ (0,
|
|
8190
|
-
/* @__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." })
|
|
8191
8429
|
] }),
|
|
8192
|
-
/* @__PURE__ */ (0,
|
|
8193
|
-
/* @__PURE__ */ (0,
|
|
8194
|
-
/* @__PURE__ */ (0,
|
|
8195
|
-
/* @__PURE__ */ (0,
|
|
8196
|
-
/* @__PURE__ */ (0,
|
|
8197
|
-
roles.map((r) => /* @__PURE__ */ (0,
|
|
8198
|
-
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
|
|
8199
8437
|
] })
|
|
8200
8438
|
] }),
|
|
8201
|
-
onChangePhoto ? /* @__PURE__ */ (0,
|
|
8439
|
+
onChangePhoto ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
|
|
8202
8440
|
] }) }),
|
|
8203
|
-
fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ (0,
|
|
8441
|
+
fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
8204
8442
|
Card,
|
|
8205
8443
|
{
|
|
8206
|
-
title: description ? /* @__PURE__ */ (0,
|
|
8207
|
-
/* @__PURE__ */ (0,
|
|
8208
|
-
/* @__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 })
|
|
8209
8447
|
] }) : group,
|
|
8210
8448
|
elevation: "flat",
|
|
8211
|
-
children: /* @__PURE__ */ (0,
|
|
8212
|
-
/* @__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) => {
|
|
8213
8451
|
const help = typeof field.help === "function" ? field.help(user) : field.help;
|
|
8214
8452
|
const readOnly = field.readOnly || field.type === "readonly";
|
|
8215
8453
|
if (field.type === "select") {
|
|
8216
|
-
return /* @__PURE__ */ (0,
|
|
8454
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
8217
8455
|
Select,
|
|
8218
8456
|
{
|
|
8219
8457
|
label: field.label,
|
|
@@ -8227,7 +8465,7 @@ function ProfilePage({
|
|
|
8227
8465
|
field.key
|
|
8228
8466
|
);
|
|
8229
8467
|
}
|
|
8230
|
-
return /* @__PURE__ */ (0,
|
|
8468
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
8231
8469
|
Input,
|
|
8232
8470
|
{
|
|
8233
8471
|
label: field.label,
|
|
@@ -8243,7 +8481,7 @@ function ProfilePage({
|
|
|
8243
8481
|
}) }),
|
|
8244
8482
|
groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
|
|
8245
8483
|
const help = typeof field.help === "function" ? field.help(user) : field.help;
|
|
8246
|
-
return /* @__PURE__ */ (0,
|
|
8484
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
8247
8485
|
Textarea,
|
|
8248
8486
|
{
|
|
8249
8487
|
label: field.label,
|
|
@@ -8263,16 +8501,16 @@ function ProfilePage({
|
|
|
8263
8501
|
group
|
|
8264
8502
|
)),
|
|
8265
8503
|
extra,
|
|
8266
|
-
notifications.length > 0 ? /* @__PURE__ */ (0,
|
|
8267
|
-
/* @__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)(
|
|
8268
8506
|
Card,
|
|
8269
8507
|
{
|
|
8270
|
-
title: /* @__PURE__ */ (0,
|
|
8271
|
-
/* @__PURE__ */ (0,
|
|
8272
|
-
/* @__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" })
|
|
8273
8511
|
] }),
|
|
8274
8512
|
elevation: "flat",
|
|
8275
|
-
action: /* @__PURE__ */ (0,
|
|
8513
|
+
action: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
8276
8514
|
Button,
|
|
8277
8515
|
{
|
|
8278
8516
|
size: "sm",
|
|
@@ -8283,39 +8521,39 @@ function ProfilePage({
|
|
|
8283
8521
|
}
|
|
8284
8522
|
),
|
|
8285
8523
|
children: [
|
|
8286
|
-
/* @__PURE__ */ (0,
|
|
8287
|
-
/* @__PURE__ */ (0,
|
|
8288
|
-
/* @__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: [
|
|
8289
8527
|
permissions.length,
|
|
8290
8528
|
" granted"
|
|
8291
8529
|
] }),
|
|
8292
|
-
/* @__PURE__ */ (0,
|
|
8530
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
|
|
8293
8531
|
] }),
|
|
8294
|
-
/* @__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." })
|
|
8295
8533
|
]
|
|
8296
8534
|
}
|
|
8297
8535
|
),
|
|
8298
|
-
sessions ? /* @__PURE__ */ (0,
|
|
8536
|
+
sessions ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
8299
8537
|
Card,
|
|
8300
8538
|
{
|
|
8301
8539
|
title: "Signed-in devices",
|
|
8302
8540
|
elevation: "flat",
|
|
8303
|
-
action: /* @__PURE__ */ (0,
|
|
8304
|
-
children: /* @__PURE__ */ (0,
|
|
8305
|
-
/* @__PURE__ */ (0,
|
|
8306
|
-
/* @__PURE__ */ (0,
|
|
8307
|
-
/* @__PURE__ */ (0,
|
|
8308
|
-
/* @__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: [
|
|
8309
8547
|
s.where,
|
|
8310
8548
|
" \xB7 ",
|
|
8311
8549
|
s.when
|
|
8312
8550
|
] })
|
|
8313
8551
|
] }),
|
|
8314
|
-
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" })
|
|
8315
8553
|
] }, s.id)) })
|
|
8316
8554
|
}
|
|
8317
8555
|
) : null,
|
|
8318
|
-
/* @__PURE__ */ (0,
|
|
8556
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-row", style: {
|
|
8319
8557
|
gap: 10,
|
|
8320
8558
|
flexWrap: "wrap",
|
|
8321
8559
|
position: "sticky",
|
|
@@ -8326,19 +8564,19 @@ function ProfilePage({
|
|
|
8326
8564
|
border: "1px solid var(--border)",
|
|
8327
8565
|
boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
|
|
8328
8566
|
}, children: [
|
|
8329
|
-
/* @__PURE__ */ (0,
|
|
8330
|
-
/* @__PURE__ */ (0,
|
|
8331
|
-
/* @__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" })
|
|
8332
8570
|
] })
|
|
8333
8571
|
] });
|
|
8334
8572
|
}
|
|
8335
8573
|
|
|
8336
8574
|
// src/components/platform/SignInPage.tsx
|
|
8337
|
-
var
|
|
8338
|
-
var
|
|
8575
|
+
var React51 = __toESM(require("react"), 1);
|
|
8576
|
+
var import_jsx_runtime79 = require("react/jsx-runtime");
|
|
8339
8577
|
function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
8340
|
-
const [signingIn, setSigningIn] =
|
|
8341
|
-
const [resuming, setResuming] =
|
|
8578
|
+
const [signingIn, setSigningIn] = React51.useState(false);
|
|
8579
|
+
const [resuming, setResuming] = React51.useState(false);
|
|
8342
8580
|
function handleSignIn() {
|
|
8343
8581
|
setSigningIn(true);
|
|
8344
8582
|
onSignIn();
|
|
@@ -8347,7 +8585,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8347
8585
|
setResuming(true);
|
|
8348
8586
|
continueAs.onContinue().finally(() => setResuming(false));
|
|
8349
8587
|
}
|
|
8350
|
-
return /* @__PURE__ */ (0,
|
|
8588
|
+
return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
|
|
8351
8589
|
"div",
|
|
8352
8590
|
{
|
|
8353
8591
|
style: {
|
|
@@ -8361,7 +8599,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8361
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%)"
|
|
8362
8600
|
},
|
|
8363
8601
|
children: [
|
|
8364
|
-
/* @__PURE__ */ (0,
|
|
8602
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8365
8603
|
"div",
|
|
8366
8604
|
{
|
|
8367
8605
|
"aria-hidden": true,
|
|
@@ -8374,7 +8612,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8374
8612
|
}
|
|
8375
8613
|
}
|
|
8376
8614
|
),
|
|
8377
|
-
/* @__PURE__ */ (0,
|
|
8615
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
|
|
8378
8616
|
"div",
|
|
8379
8617
|
{
|
|
8380
8618
|
style: {
|
|
@@ -8386,8 +8624,8 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8386
8624
|
alignItems: "center"
|
|
8387
8625
|
},
|
|
8388
8626
|
children: [
|
|
8389
|
-
/* @__PURE__ */ (0,
|
|
8390
|
-
/* @__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)(
|
|
8391
8629
|
"div",
|
|
8392
8630
|
{
|
|
8393
8631
|
style: {
|
|
@@ -8397,7 +8635,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8397
8635
|
boxShadow: "0 24px 64px -12px rgba(2, 8, 20, 0.55), 0 2px 8px rgba(2, 8, 20, 0.3)"
|
|
8398
8636
|
},
|
|
8399
8637
|
children: [
|
|
8400
|
-
/* @__PURE__ */ (0,
|
|
8638
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8401
8639
|
"div",
|
|
8402
8640
|
{
|
|
8403
8641
|
style: {
|
|
@@ -8406,7 +8644,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8406
8644
|
}
|
|
8407
8645
|
}
|
|
8408
8646
|
),
|
|
8409
|
-
/* @__PURE__ */ (0,
|
|
8647
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
|
|
8410
8648
|
"div",
|
|
8411
8649
|
{
|
|
8412
8650
|
style: {
|
|
@@ -8418,13 +8656,13 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8418
8656
|
padding: "var(--s-8) 0"
|
|
8419
8657
|
},
|
|
8420
8658
|
children: [
|
|
8421
|
-
/* @__PURE__ */ (0,
|
|
8422
|
-
/* @__PURE__ */ (0,
|
|
8423
|
-
/* @__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" })
|
|
8424
8662
|
] }),
|
|
8425
|
-
error ? /* @__PURE__ */ (0,
|
|
8426
|
-
continueAs ? /* @__PURE__ */ (0,
|
|
8427
|
-
/* @__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)(
|
|
8428
8666
|
Button,
|
|
8429
8667
|
{
|
|
8430
8668
|
variant: "primary",
|
|
@@ -8435,7 +8673,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8435
8673
|
children: resuming ? "Resuming\u2026" : `Continue as ${continueAs.name}`
|
|
8436
8674
|
}
|
|
8437
8675
|
),
|
|
8438
|
-
/* @__PURE__ */ (0,
|
|
8676
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8439
8677
|
"button",
|
|
8440
8678
|
{
|
|
8441
8679
|
type: "button",
|
|
@@ -8452,7 +8690,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8452
8690
|
children: "Not you? Sign in with flytedesk ID"
|
|
8453
8691
|
}
|
|
8454
8692
|
)
|
|
8455
|
-
] }) : /* @__PURE__ */ (0,
|
|
8693
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8456
8694
|
Button,
|
|
8457
8695
|
{
|
|
8458
8696
|
variant: "primary",
|
|
@@ -8460,7 +8698,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8460
8698
|
loading: signingIn,
|
|
8461
8699
|
disabled: signingIn,
|
|
8462
8700
|
onClick: handleSignIn,
|
|
8463
|
-
children: /* @__PURE__ */ (0,
|
|
8701
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
|
|
8464
8702
|
"span",
|
|
8465
8703
|
{
|
|
8466
8704
|
style: {
|
|
@@ -8472,14 +8710,14 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8472
8710
|
flexWrap: "nowrap"
|
|
8473
8711
|
},
|
|
8474
8712
|
children: [
|
|
8475
|
-
/* @__PURE__ */ (0,
|
|
8476
|
-
/* @__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" })
|
|
8477
8715
|
]
|
|
8478
8716
|
}
|
|
8479
8717
|
)
|
|
8480
8718
|
}
|
|
8481
8719
|
),
|
|
8482
|
-
/* @__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." })
|
|
8483
8721
|
]
|
|
8484
8722
|
}
|
|
8485
8723
|
) })
|
|
@@ -8494,29 +8732,29 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
|
8494
8732
|
);
|
|
8495
8733
|
}
|
|
8496
8734
|
function GoogleGlyph() {
|
|
8497
|
-
return /* @__PURE__ */ (0,
|
|
8498
|
-
/* @__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)(
|
|
8499
8737
|
"path",
|
|
8500
8738
|
{
|
|
8501
8739
|
fill: "#4285F4",
|
|
8502
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"
|
|
8503
8741
|
}
|
|
8504
8742
|
),
|
|
8505
|
-
/* @__PURE__ */ (0,
|
|
8743
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8506
8744
|
"path",
|
|
8507
8745
|
{
|
|
8508
8746
|
fill: "#34A853",
|
|
8509
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"
|
|
8510
8748
|
}
|
|
8511
8749
|
),
|
|
8512
|
-
/* @__PURE__ */ (0,
|
|
8750
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8513
8751
|
"path",
|
|
8514
8752
|
{
|
|
8515
8753
|
fill: "#FBBC05",
|
|
8516
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"
|
|
8517
8755
|
}
|
|
8518
8756
|
),
|
|
8519
|
-
/* @__PURE__ */ (0,
|
|
8757
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8520
8758
|
"path",
|
|
8521
8759
|
{
|
|
8522
8760
|
fill: "#EA4335",
|
|
@@ -8527,10 +8765,10 @@ function GoogleGlyph() {
|
|
|
8527
8765
|
}
|
|
8528
8766
|
|
|
8529
8767
|
// src/components/platform/RoadmapTimeline.tsx
|
|
8530
|
-
var
|
|
8768
|
+
var React54 = __toESM(require("react"), 1);
|
|
8531
8769
|
|
|
8532
8770
|
// src/kits/session.ts
|
|
8533
|
-
var
|
|
8771
|
+
var React52 = __toESM(require("react"), 1);
|
|
8534
8772
|
var PERMISSION_CATALOG = [
|
|
8535
8773
|
{ group: "Plans", items: [
|
|
8536
8774
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -10097,8 +10335,8 @@ function roadmap(overrides) {
|
|
|
10097
10335
|
};
|
|
10098
10336
|
}
|
|
10099
10337
|
function useSession() {
|
|
10100
|
-
const [s, setS] =
|
|
10101
|
-
|
|
10338
|
+
const [s, setS] = React52.useState(getSession);
|
|
10339
|
+
React52.useEffect(() => subscribe(setS), []);
|
|
10102
10340
|
return s;
|
|
10103
10341
|
}
|
|
10104
10342
|
var SessionKit = {
|
|
@@ -10131,7 +10369,7 @@ var SessionKit = {
|
|
|
10131
10369
|
};
|
|
10132
10370
|
function DemoSessionProvider({ children }) {
|
|
10133
10371
|
const session = useSession();
|
|
10134
|
-
const value =
|
|
10372
|
+
const value = React52.useMemo(
|
|
10135
10373
|
() => ({
|
|
10136
10374
|
user: session.user,
|
|
10137
10375
|
roles: session.roles,
|
|
@@ -10147,11 +10385,11 @@ function DemoSessionProvider({ children }) {
|
|
|
10147
10385
|
}),
|
|
10148
10386
|
[session]
|
|
10149
10387
|
);
|
|
10150
|
-
return
|
|
10388
|
+
return React52.createElement(SessionProvider, { value }, children);
|
|
10151
10389
|
}
|
|
10152
10390
|
|
|
10153
10391
|
// src/kits/runtime.ts
|
|
10154
|
-
var
|
|
10392
|
+
var React53 = __toESM(require("react"), 1);
|
|
10155
10393
|
var WIRED_ENDPOINTS = [
|
|
10156
10394
|
// Nothing yet. Every id below would come from a real service:
|
|
10157
10395
|
// "plan.get", "placements.list", …
|
|
@@ -10322,8 +10560,8 @@ var RuntimeKit = {
|
|
|
10322
10560
|
};
|
|
10323
10561
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
10324
10562
|
function useRuntimeMode() {
|
|
10325
|
-
const [m, setM] =
|
|
10326
|
-
|
|
10563
|
+
const [m, setM] = React53.useState(RuntimeKit.getMode());
|
|
10564
|
+
React53.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
10327
10565
|
return m;
|
|
10328
10566
|
}
|
|
10329
10567
|
function useFeatureStatus(key) {
|
|
@@ -10342,7 +10580,7 @@ var UseRuntimeMode = useRuntimeMode;
|
|
|
10342
10580
|
var UseFeatureStatus = useFeatureStatus;
|
|
10343
10581
|
|
|
10344
10582
|
// src/components/platform/RoadmapTimeline.tsx
|
|
10345
|
-
var
|
|
10583
|
+
var import_jsx_runtime80 = require("react/jsx-runtime");
|
|
10346
10584
|
var STATUS = {
|
|
10347
10585
|
shipped: { tone: "success", icon: "check-circle", label: "Wired" },
|
|
10348
10586
|
next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
|
|
@@ -10357,45 +10595,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
10357
10595
|
const s = STATUS[item.status] || STATUS.planned;
|
|
10358
10596
|
const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
|
|
10359
10597
|
const blocking = deps.filter((d) => !d.implemented);
|
|
10360
|
-
return /* @__PURE__ */ (0,
|
|
10361
|
-
/* @__PURE__ */ (0,
|
|
10362
|
-
/* @__PURE__ */ (0,
|
|
10363
|
-
/* @__PURE__ */ (0,
|
|
10364
|
-
/* @__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 })
|
|
10365
10603
|
] }),
|
|
10366
|
-
/* @__PURE__ */ (0,
|
|
10367
|
-
item.backend ? /* @__PURE__ */ (0,
|
|
10368
|
-
/* @__PURE__ */ (0,
|
|
10369
|
-
/* @__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 })
|
|
10370
10608
|
] }) : null,
|
|
10371
|
-
/* @__PURE__ */ (0,
|
|
10372
|
-
item.effort ? /* @__PURE__ */ (0,
|
|
10373
|
-
/* @__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" }),
|
|
10374
10612
|
" ",
|
|
10375
10613
|
item.effort
|
|
10376
10614
|
] }) : null,
|
|
10377
|
-
/* @__PURE__ */ (0,
|
|
10378
|
-
/* @__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" }),
|
|
10379
10617
|
" ",
|
|
10380
10618
|
item.owner
|
|
10381
10619
|
] }),
|
|
10382
|
-
item.screen ? /* @__PURE__ */ (0,
|
|
10383
|
-
/* @__PURE__ */ (0,
|
|
10384
|
-
/* @__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)(
|
|
10385
10623
|
"button",
|
|
10386
10624
|
{
|
|
10387
10625
|
type: "button",
|
|
10388
10626
|
onClick: () => onOpenFlag && onOpenFlag(item.key),
|
|
10389
10627
|
style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
|
|
10390
|
-
children: /* @__PURE__ */ (0,
|
|
10628
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
|
|
10391
10629
|
}
|
|
10392
10630
|
)
|
|
10393
10631
|
] }),
|
|
10394
|
-
deps.length ? /* @__PURE__ */ (0,
|
|
10395
|
-
/* @__PURE__ */ (0,
|
|
10396
|
-
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))
|
|
10397
10635
|
] }) : null,
|
|
10398
|
-
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: [
|
|
10399
10637
|
"Blocked until ",
|
|
10400
10638
|
blocking.map((d) => d.label).join(" and "),
|
|
10401
10639
|
" ",
|
|
@@ -10406,12 +10644,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
10406
10644
|
}
|
|
10407
10645
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
10408
10646
|
const session = SessionKit.useSession();
|
|
10409
|
-
const [project, setProject] =
|
|
10410
|
-
const [q, setQ] =
|
|
10411
|
-
const scrollRef =
|
|
10412
|
-
const nowRef =
|
|
10413
|
-
const rm =
|
|
10414
|
-
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(() => {
|
|
10415
10653
|
const m = {};
|
|
10416
10654
|
rm.items.forEach((i) => {
|
|
10417
10655
|
m[i.key] = i;
|
|
@@ -10420,7 +10658,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10420
10658
|
}, [rm]);
|
|
10421
10659
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
10422
10660
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
10423
|
-
|
|
10661
|
+
React54.useEffect(() => {
|
|
10424
10662
|
let raf1 = 0, raf2 = 0;
|
|
10425
10663
|
const place = () => {
|
|
10426
10664
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -10448,23 +10686,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10448
10686
|
}, 0);
|
|
10449
10687
|
const nextPhase = items.find((i) => !i.implemented);
|
|
10450
10688
|
let lastPhase = null;
|
|
10451
|
-
return /* @__PURE__ */ (0,
|
|
10452
|
-
/* @__PURE__ */ (0,
|
|
10453
|
-
/* @__PURE__ */ (0,
|
|
10454
|
-
/* @__PURE__ */ (0,
|
|
10455
|
-
/* @__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." })
|
|
10456
10694
|
] }),
|
|
10457
|
-
/* @__PURE__ */ (0,
|
|
10458
|
-
/* @__PURE__ */ (0,
|
|
10459
|
-
/* @__PURE__ */ (0,
|
|
10460
|
-
/* @__PURE__ */ (0,
|
|
10461
|
-
/* @__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" })
|
|
10462
10700
|
] }),
|
|
10463
|
-
/* @__PURE__ */ (0,
|
|
10464
|
-
/* @__PURE__ */ (0,
|
|
10465
|
-
/* @__PURE__ */ (0,
|
|
10466
|
-
/* @__PURE__ */ (0,
|
|
10467
|
-
/* @__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)(
|
|
10468
10706
|
Button,
|
|
10469
10707
|
{
|
|
10470
10708
|
size: "sm",
|
|
@@ -10478,7 +10716,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10478
10716
|
}
|
|
10479
10717
|
)
|
|
10480
10718
|
] }),
|
|
10481
|
-
/* @__PURE__ */ (0,
|
|
10719
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
|
|
10482
10720
|
Flag,
|
|
10483
10721
|
{
|
|
10484
10722
|
tone: "info",
|
|
@@ -10487,60 +10725,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10487
10725
|
actions: null
|
|
10488
10726
|
}
|
|
10489
10727
|
),
|
|
10490
|
-
/* @__PURE__ */ (0,
|
|
10491
|
-
/* @__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%" } }) }),
|
|
10492
10730
|
items.map((item, n) => {
|
|
10493
10731
|
const showPhase = item.phase !== lastPhase;
|
|
10494
10732
|
lastPhase = item.phase;
|
|
10495
10733
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
10496
10734
|
const isBoundary = n === firstPending;
|
|
10497
|
-
return /* @__PURE__ */ (0,
|
|
10498
|
-
showPhase ? /* @__PURE__ */ (0,
|
|
10499
|
-
/* @__PURE__ */ (0,
|
|
10500
|
-
/* @__PURE__ */ (0,
|
|
10501
|
-
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: [
|
|
10502
10740
|
fmtDate(item.phaseStart),
|
|
10503
10741
|
" \u2013 ",
|
|
10504
10742
|
fmtDate(item.date)
|
|
10505
10743
|
] }),
|
|
10506
|
-
/* @__PURE__ */ (0,
|
|
10744
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
10507
10745
|
"\xB7 ",
|
|
10508
10746
|
inPhase,
|
|
10509
10747
|
" feature",
|
|
10510
10748
|
inPhase === 1 ? "" : "s"
|
|
10511
10749
|
] })
|
|
10512
10750
|
] }),
|
|
10513
|
-
item.phaseWhy ? /* @__PURE__ */ (0,
|
|
10751
|
+
item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
|
|
10514
10752
|
] }) : null,
|
|
10515
|
-
isBoundary ? /* @__PURE__ */ (0,
|
|
10516
|
-
/* @__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" }),
|
|
10517
10755
|
" You are here \u2014 everything above is wired"
|
|
10518
10756
|
] }) }) : null,
|
|
10519
|
-
/* @__PURE__ */ (0,
|
|
10520
|
-
/* @__PURE__ */ (0,
|
|
10521
|
-
/* @__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: [
|
|
10522
10760
|
fmtDate(item.date),
|
|
10523
|
-
/* @__PURE__ */ (0,
|
|
10524
|
-
/* @__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 })
|
|
10525
10763
|
] }),
|
|
10526
|
-
/* @__PURE__ */ (0,
|
|
10764
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
|
|
10527
10765
|
] })
|
|
10528
10766
|
] }, item.key);
|
|
10529
10767
|
}),
|
|
10530
|
-
!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
|
|
10531
10769
|
] }) }) }),
|
|
10532
|
-
/* @__PURE__ */ (0,
|
|
10770
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
|
|
10533
10771
|
"Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
|
|
10534
|
-
/* @__PURE__ */ (0,
|
|
10772
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("code", { className: "fd-mono", children: "implemented" }),
|
|
10535
10773
|
" field, so this page cannot drift from what the apps actually do."
|
|
10536
10774
|
] })
|
|
10537
10775
|
] });
|
|
10538
10776
|
}
|
|
10539
10777
|
|
|
10540
10778
|
// src/components/platform/ComingSoon.tsx
|
|
10541
|
-
var
|
|
10779
|
+
var React55 = __toESM(require("react"), 1);
|
|
10542
10780
|
var import_react_dom6 = require("react-dom");
|
|
10543
|
-
var
|
|
10781
|
+
var import_jsx_runtime81 = require("react/jsx-runtime");
|
|
10544
10782
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
10545
10783
|
function readBypassed() {
|
|
10546
10784
|
try {
|
|
@@ -10556,8 +10794,8 @@ function writeBypassed(list) {
|
|
|
10556
10794
|
}
|
|
10557
10795
|
}
|
|
10558
10796
|
function useBypass(key) {
|
|
10559
|
-
const [on, setOn] =
|
|
10560
|
-
|
|
10797
|
+
const [on, setOn] = React55.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
10798
|
+
React55.useEffect(() => {
|
|
10561
10799
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
10562
10800
|
}, [key]);
|
|
10563
10801
|
const set = (next) => {
|
|
@@ -10570,43 +10808,43 @@ function useBypass(key) {
|
|
|
10570
10808
|
return [on, set];
|
|
10571
10809
|
}
|
|
10572
10810
|
function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
|
|
10573
|
-
return /* @__PURE__ */ (0,
|
|
10574
|
-
/* @__PURE__ */ (0,
|
|
10575
|
-
/* @__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" }),
|
|
10576
10814
|
label
|
|
10577
10815
|
] }),
|
|
10578
|
-
detail ? /* @__PURE__ */ (0,
|
|
10579
|
-
backend ? /* @__PURE__ */ (0,
|
|
10580
|
-
/* @__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" }),
|
|
10581
10819
|
" ",
|
|
10582
10820
|
backend
|
|
10583
10821
|
] }) : null,
|
|
10584
|
-
eta || effort || onRoadmap ? /* @__PURE__ */ (0,
|
|
10585
|
-
eta ? /* @__PURE__ */ (0,
|
|
10586
|
-
/* @__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" }),
|
|
10587
10825
|
" ",
|
|
10588
10826
|
eta
|
|
10589
10827
|
] }) : null,
|
|
10590
|
-
effort ? /* @__PURE__ */ (0,
|
|
10591
|
-
/* @__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" }),
|
|
10592
10830
|
" ",
|
|
10593
10831
|
effort
|
|
10594
10832
|
] }) : null,
|
|
10595
|
-
onRoadmap ? /* @__PURE__ */ (0,
|
|
10833
|
+
onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
10596
10834
|
"See the roadmap ",
|
|
10597
|
-
/* @__PURE__ */ (0,
|
|
10835
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
10598
10836
|
] }) : null
|
|
10599
10837
|
] }) : null,
|
|
10600
|
-
allowed ? /* @__PURE__ */ (0,
|
|
10601
|
-
/* @__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" }),
|
|
10602
10840
|
" View and use it anyway"
|
|
10603
10841
|
] }) : null
|
|
10604
10842
|
] });
|
|
10605
10843
|
}
|
|
10606
10844
|
function useHoverCard(open2) {
|
|
10607
|
-
const anchor =
|
|
10608
|
-
const [pos, setPos] =
|
|
10609
|
-
|
|
10845
|
+
const anchor = React55.useRef(null);
|
|
10846
|
+
const [pos, setPos] = React55.useState(null);
|
|
10847
|
+
React55.useLayoutEffect(() => {
|
|
10610
10848
|
if (!open2 || !anchor.current) {
|
|
10611
10849
|
setPos(null);
|
|
10612
10850
|
return;
|
|
@@ -10658,9 +10896,9 @@ function ComingSoon({
|
|
|
10658
10896
|
const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
|
|
10659
10897
|
if (inline) {
|
|
10660
10898
|
if (allowed && bypassed) {
|
|
10661
|
-
return /* @__PURE__ */ (0,
|
|
10899
|
+
return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
|
|
10662
10900
|
children,
|
|
10663
|
-
/* @__PURE__ */ (0,
|
|
10901
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
10664
10902
|
"button",
|
|
10665
10903
|
{
|
|
10666
10904
|
type: "button",
|
|
@@ -10668,12 +10906,12 @@ function ComingSoon({
|
|
|
10668
10906
|
title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
|
|
10669
10907
|
onClick: () => setBypassed(false),
|
|
10670
10908
|
"aria-label": "Re-blur this unwired feature",
|
|
10671
|
-
children: /* @__PURE__ */ (0,
|
|
10909
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
10672
10910
|
}
|
|
10673
10911
|
)
|
|
10674
10912
|
] });
|
|
10675
10913
|
}
|
|
10676
|
-
return /* @__PURE__ */ (0,
|
|
10914
|
+
return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
10677
10915
|
InlineSoon,
|
|
10678
10916
|
{
|
|
10679
10917
|
label,
|
|
@@ -10693,20 +10931,20 @@ function ComingSoon({
|
|
|
10693
10931
|
);
|
|
10694
10932
|
}
|
|
10695
10933
|
if (allowed && bypassed) {
|
|
10696
|
-
return /* @__PURE__ */ (0,
|
|
10697
|
-
/* @__PURE__ */ (0,
|
|
10698
|
-
/* @__PURE__ */ (0,
|
|
10699
|
-
/* @__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" }),
|
|
10700
10938
|
"Unwired feature \u2014 you are using it anyway"
|
|
10701
10939
|
] }),
|
|
10702
|
-
/* @__PURE__ */ (0,
|
|
10703
|
-
/* @__PURE__ */ (0,
|
|
10704
|
-
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: [
|
|
10705
10943
|
"Roadmap ",
|
|
10706
|
-
/* @__PURE__ */ (0,
|
|
10944
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
10707
10945
|
] }) : null,
|
|
10708
|
-
/* @__PURE__ */ (0,
|
|
10709
|
-
/* @__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" }),
|
|
10710
10948
|
" Re-blur"
|
|
10711
10949
|
] })
|
|
10712
10950
|
] })
|
|
@@ -10714,10 +10952,10 @@ function ComingSoon({
|
|
|
10714
10952
|
children
|
|
10715
10953
|
] });
|
|
10716
10954
|
}
|
|
10717
|
-
return /* @__PURE__ */ (0,
|
|
10718
|
-
/* @__PURE__ */ (0,
|
|
10719
|
-
/* @__PURE__ */ (0,
|
|
10720
|
-
/* @__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)(
|
|
10721
10959
|
SoonCard,
|
|
10722
10960
|
{
|
|
10723
10961
|
label,
|
|
@@ -10733,10 +10971,10 @@ function ComingSoon({
|
|
|
10733
10971
|
] });
|
|
10734
10972
|
}
|
|
10735
10973
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
10736
|
-
const [open2, setOpen] =
|
|
10974
|
+
const [open2, setOpen] = React55.useState(false);
|
|
10737
10975
|
const [anchor, pos] = useHoverCard(open2);
|
|
10738
10976
|
const zIndex = useOverlayLayer(open2);
|
|
10739
|
-
const close2 =
|
|
10977
|
+
const close2 = React55.useRef(null);
|
|
10740
10978
|
const show = () => {
|
|
10741
10979
|
if (close2.current) {
|
|
10742
10980
|
clearTimeout(close2.current);
|
|
@@ -10752,10 +10990,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10752
10990
|
setOpen(false);
|
|
10753
10991
|
}, 140);
|
|
10754
10992
|
};
|
|
10755
|
-
|
|
10993
|
+
React55.useEffect(() => () => {
|
|
10756
10994
|
if (close2.current) clearTimeout(close2.current);
|
|
10757
10995
|
}, []);
|
|
10758
|
-
return /* @__PURE__ */ (0,
|
|
10996
|
+
return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
|
|
10759
10997
|
"span",
|
|
10760
10998
|
{
|
|
10761
10999
|
ref: anchor,
|
|
@@ -10766,8 +11004,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10766
11004
|
onBlur: hide,
|
|
10767
11005
|
...rest,
|
|
10768
11006
|
children: [
|
|
10769
|
-
/* @__PURE__ */ (0,
|
|
10770
|
-
/* @__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)(
|
|
10771
11009
|
"button",
|
|
10772
11010
|
{
|
|
10773
11011
|
type: "button",
|
|
@@ -10778,11 +11016,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10778
11016
|
onFocus: show,
|
|
10779
11017
|
onBlur: hide,
|
|
10780
11018
|
onClick: () => open2 ? setOpen(false) : show(),
|
|
10781
|
-
children: /* @__PURE__ */ (0,
|
|
11019
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
10782
11020
|
}
|
|
10783
11021
|
),
|
|
10784
11022
|
open2 && pos ? (0, import_react_dom6.createPortal)(
|
|
10785
|
-
/* @__PURE__ */ (0,
|
|
11023
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
10786
11024
|
"div",
|
|
10787
11025
|
{
|
|
10788
11026
|
className: "fd-soon-note fd-soon-hovercard",
|
|
@@ -10790,7 +11028,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10790
11028
|
style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
|
|
10791
11029
|
onMouseEnter: show,
|
|
10792
11030
|
onMouseLeave: hide,
|
|
10793
|
-
children: /* @__PURE__ */ (0,
|
|
11031
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
10794
11032
|
SoonCard,
|
|
10795
11033
|
{
|
|
10796
11034
|
label,
|
|
@@ -10820,10 +11058,10 @@ function formatEta(iso2) {
|
|
|
10820
11058
|
var FormatEta = formatEta;
|
|
10821
11059
|
|
|
10822
11060
|
// src/components/platform/Gate.tsx
|
|
10823
|
-
var
|
|
11061
|
+
var import_jsx_runtime82 = require("react/jsx-runtime");
|
|
10824
11062
|
function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
|
|
10825
11063
|
const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
|
|
10826
|
-
return /* @__PURE__ */ (0,
|
|
11064
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
|
|
10827
11065
|
"div",
|
|
10828
11066
|
{
|
|
10829
11067
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -10839,14 +11077,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
10839
11077
|
},
|
|
10840
11078
|
...rest,
|
|
10841
11079
|
children: [
|
|
10842
|
-
/* @__PURE__ */ (0,
|
|
10843
|
-
/* @__PURE__ */ (0,
|
|
10844
|
-
/* @__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" })
|
|
10845
11083
|
] }),
|
|
10846
|
-
/* @__PURE__ */ (0,
|
|
10847
|
-
need.length ? /* @__PURE__ */ (0,
|
|
10848
|
-
/* @__PURE__ */ (0,
|
|
10849
|
-
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: {
|
|
10850
11088
|
fontSize: 11.5,
|
|
10851
11089
|
padding: "2px 7px",
|
|
10852
11090
|
borderRadius: 5,
|
|
@@ -10859,7 +11097,7 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
10859
11097
|
);
|
|
10860
11098
|
}
|
|
10861
11099
|
function GatePending({ compact: compact3 = false, className = "" }) {
|
|
10862
|
-
return /* @__PURE__ */ (0,
|
|
11100
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
|
|
10863
11101
|
"div",
|
|
10864
11102
|
{
|
|
10865
11103
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -10875,11 +11113,11 @@ function GatePending({ compact: compact3 = false, className = "" }) {
|
|
|
10875
11113
|
textAlign: "left"
|
|
10876
11114
|
},
|
|
10877
11115
|
children: [
|
|
10878
|
-
/* @__PURE__ */ (0,
|
|
10879
|
-
/* @__PURE__ */ (0,
|
|
10880
|
-
/* @__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" })
|
|
10881
11119
|
] }),
|
|
10882
|
-
/* @__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." })
|
|
10883
11121
|
]
|
|
10884
11122
|
}
|
|
10885
11123
|
);
|
|
@@ -10889,7 +11127,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
|
|
|
10889
11127
|
if (pending) {
|
|
10890
11128
|
if (pendingFallback !== void 0) return pendingFallback;
|
|
10891
11129
|
if (silent) return null;
|
|
10892
|
-
return /* @__PURE__ */ (0,
|
|
11130
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(GatePending, { compact: compact3 });
|
|
10893
11131
|
}
|
|
10894
11132
|
let ok = true;
|
|
10895
11133
|
if (perm) ok = ok && can2(perm);
|
|
@@ -10898,7 +11136,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
|
|
|
10898
11136
|
if (ok) return children;
|
|
10899
11137
|
if (fallback !== void 0) return fallback;
|
|
10900
11138
|
if (silent) return null;
|
|
10901
|
-
return /* @__PURE__ */ (0,
|
|
11139
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
|
|
10902
11140
|
}
|
|
10903
11141
|
function FeatureGate({
|
|
10904
11142
|
flag,
|
|
@@ -10921,7 +11159,7 @@ function FeatureGate({
|
|
|
10921
11159
|
const f = SessionKit.findFlag(flag) || {};
|
|
10922
11160
|
const missing = rt.missing || [];
|
|
10923
11161
|
const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
|
|
10924
|
-
return /* @__PURE__ */ (0,
|
|
11162
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
10925
11163
|
ComingSoon,
|
|
10926
11164
|
{
|
|
10927
11165
|
label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
|
|
@@ -10942,22 +11180,22 @@ function FeatureGate({
|
|
|
10942
11180
|
function PermissionHint({ perm, children }) {
|
|
10943
11181
|
const { can: can2, pending } = useSessionContext();
|
|
10944
11182
|
if (pending) {
|
|
10945
|
-
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 }) });
|
|
10946
11184
|
}
|
|
10947
11185
|
if (can2(perm)) return children;
|
|
10948
|
-
return /* @__PURE__ */ (0,
|
|
11186
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
10949
11187
|
"span",
|
|
10950
11188
|
{
|
|
10951
11189
|
title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
|
|
10952
11190
|
style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
|
|
10953
11191
|
"aria-disabled": "true",
|
|
10954
|
-
children: /* @__PURE__ */ (0,
|
|
11192
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { pointerEvents: "none" }, children })
|
|
10955
11193
|
}
|
|
10956
11194
|
);
|
|
10957
11195
|
}
|
|
10958
11196
|
|
|
10959
11197
|
// src/components/platform/ModeSwitch.tsx
|
|
10960
|
-
var
|
|
11198
|
+
var import_jsx_runtime83 = require("react/jsx-runtime");
|
|
10961
11199
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
10962
11200
|
const mode2 = useRuntimeMode();
|
|
10963
11201
|
const panel = useInlinePanel();
|
|
@@ -10969,8 +11207,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
10969
11207
|
RuntimeKit.setMode(next);
|
|
10970
11208
|
setOpen(false);
|
|
10971
11209
|
};
|
|
10972
|
-
return /* @__PURE__ */ (0,
|
|
10973
|
-
/* @__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)(
|
|
10974
11212
|
"button",
|
|
10975
11213
|
{
|
|
10976
11214
|
type: "button",
|
|
@@ -10980,29 +11218,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
10980
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.",
|
|
10981
11219
|
className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
|
|
10982
11220
|
children: [
|
|
10983
|
-
/* @__PURE__ */ (0,
|
|
10984
|
-
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
|
|
10985
11223
|
]
|
|
10986
11224
|
}
|
|
10987
11225
|
),
|
|
10988
|
-
open2 ? /* @__PURE__ */ (0,
|
|
10989
|
-
/* @__PURE__ */ (0,
|
|
10990
|
-
/* @__PURE__ */ (0,
|
|
10991
|
-
/* @__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" }),
|
|
10992
11230
|
test ? "Test mode" : "Live mode"
|
|
10993
11231
|
] }),
|
|
10994
|
-
test ? /* @__PURE__ */ (0,
|
|
11232
|
+
test ? /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
10995
11233
|
requestCount,
|
|
10996
11234
|
" simulated request",
|
|
10997
11235
|
requestCount === 1 ? "" : "s"
|
|
10998
11236
|
] }) : null,
|
|
10999
|
-
/* @__PURE__ */ (0,
|
|
11000
|
-
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
|
|
11001
11239
|
] }),
|
|
11002
|
-
/* @__PURE__ */ (0,
|
|
11003
|
-
/* @__PURE__ */ (0,
|
|
11004
|
-
/* @__PURE__ */ (0,
|
|
11005
|
-
/* @__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: [
|
|
11006
11244
|
s.endpointsWired,
|
|
11007
11245
|
" endpoint",
|
|
11008
11246
|
s.endpointsWired === 1 ? "" : "s",
|
|
@@ -11012,58 +11250,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
11012
11250
|
s.total,
|
|
11013
11251
|
" features complete"
|
|
11014
11252
|
] }),
|
|
11015
|
-
onOpenSpec ? /* @__PURE__ */ (0,
|
|
11016
|
-
/* @__PURE__ */ (0,
|
|
11017
|
-
/* @__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: () => {
|
|
11018
11256
|
setOpen(false);
|
|
11019
11257
|
onOpenSpec();
|
|
11020
11258
|
}, children: [
|
|
11021
11259
|
"API spec ",
|
|
11022
|
-
/* @__PURE__ */ (0,
|
|
11260
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
11023
11261
|
] })
|
|
11024
11262
|
] }) : null
|
|
11025
11263
|
] })
|
|
11026
11264
|
] }),
|
|
11027
|
-
/* @__PURE__ */ (0,
|
|
11028
|
-
/* @__PURE__ */ (0,
|
|
11029
|
-
/* @__PURE__ */ (0,
|
|
11030
|
-
/* @__PURE__ */ (0,
|
|
11031
|
-
/* @__PURE__ */ (0,
|
|
11032
|
-
/* @__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" })
|
|
11033
11271
|
] }),
|
|
11034
|
-
!test ? /* @__PURE__ */ (0,
|
|
11272
|
+
!test ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
11035
11273
|
] }),
|
|
11036
|
-
/* @__PURE__ */ (0,
|
|
11037
|
-
/* @__PURE__ */ (0,
|
|
11038
|
-
/* @__PURE__ */ (0,
|
|
11039
|
-
/* @__PURE__ */ (0,
|
|
11040
|
-
/* @__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" })
|
|
11041
11279
|
] }),
|
|
11042
|
-
test ? /* @__PURE__ */ (0,
|
|
11280
|
+
test ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
11043
11281
|
] })
|
|
11044
11282
|
] }),
|
|
11045
|
-
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
|
|
11046
11284
|
] }) }) : null
|
|
11047
11285
|
] });
|
|
11048
11286
|
}
|
|
11049
11287
|
function TestModeBar({ onExit }) {
|
|
11050
11288
|
const mode2 = useRuntimeMode();
|
|
11051
11289
|
if (mode2 !== "test") return null;
|
|
11052
|
-
return /* @__PURE__ */ (0,
|
|
11053
|
-
/* @__PURE__ */ (0,
|
|
11054
|
-
/* @__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" }),
|
|
11055
11293
|
"Test mode"
|
|
11056
11294
|
] }),
|
|
11057
|
-
/* @__PURE__ */ (0,
|
|
11058
|
-
/* @__PURE__ */ (0,
|
|
11059
|
-
/* @__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" }),
|
|
11060
11298
|
" Back to live mode"
|
|
11061
11299
|
] })
|
|
11062
11300
|
] });
|
|
11063
11301
|
}
|
|
11064
11302
|
|
|
11065
11303
|
// src/components/planner/ChannelMeta.tsx
|
|
11066
|
-
var
|
|
11304
|
+
var import_jsx_runtime84 = require("react/jsx-runtime");
|
|
11067
11305
|
var CHANNEL_WEIGHTS = {
|
|
11068
11306
|
"OOH": 50,
|
|
11069
11307
|
"DOOH": 50,
|
|
@@ -11116,9 +11354,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
11116
11354
|
const m = ChannelMeta(channel);
|
|
11117
11355
|
const wt = channelWeightOf(channel || "");
|
|
11118
11356
|
if (dot) {
|
|
11119
|
-
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 });
|
|
11120
11358
|
}
|
|
11121
|
-
return /* @__PURE__ */ (0,
|
|
11359
|
+
return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(
|
|
11122
11360
|
"span",
|
|
11123
11361
|
{
|
|
11124
11362
|
className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
|
|
@@ -11126,16 +11364,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
11126
11364
|
style: { "--chan": m.color },
|
|
11127
11365
|
...rest,
|
|
11128
11366
|
children: [
|
|
11129
|
-
/* @__PURE__ */ (0,
|
|
11130
|
-
showLabel ? /* @__PURE__ */ (0,
|
|
11131
|
-
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
|
|
11132
11370
|
]
|
|
11133
11371
|
}
|
|
11134
11372
|
);
|
|
11135
11373
|
}
|
|
11136
11374
|
|
|
11137
11375
|
// src/components/planner/SaturationDistribution.tsx
|
|
11138
|
-
var
|
|
11376
|
+
var import_jsx_runtime85 = require("react/jsx-runtime");
|
|
11139
11377
|
var BANDS2 = [
|
|
11140
11378
|
{ key: "weak", label: "Weak", n: 1, range: "< 50" },
|
|
11141
11379
|
{ key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
|
|
@@ -11146,24 +11384,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11146
11384
|
const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
|
|
11147
11385
|
const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
|
|
11148
11386
|
const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
|
|
11149
|
-
return /* @__PURE__ */ (0,
|
|
11150
|
-
/* @__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) => {
|
|
11151
11389
|
const mark = "var(--csi-" + g.n + "-mark)";
|
|
11152
11390
|
const active = selectedBand === g.key;
|
|
11153
|
-
return /* @__PURE__ */ (0,
|
|
11391
|
+
return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
|
|
11154
11392
|
"button",
|
|
11155
11393
|
{
|
|
11156
11394
|
type: "button",
|
|
11157
11395
|
onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
|
|
11158
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)" },
|
|
11159
11397
|
children: [
|
|
11160
|
-
/* @__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) => (
|
|
11161
11399
|
// `overflow: hidden` + `white-space: nowrap` only clips once the span
|
|
11162
11400
|
// actually HAS a bounded width to clip against (see the grid/flex
|
|
11163
11401
|
// `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
|
|
11164
11402
|
// that clip readable instead of a hard cut mid-letter; the full name
|
|
11165
11403
|
// is still one hover away via `title`.
|
|
11166
|
-
/* @__PURE__ */ (0,
|
|
11404
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
|
|
11167
11405
|
"span",
|
|
11168
11406
|
{
|
|
11169
11407
|
title: c.name + " \xB7 " + c.crp,
|
|
@@ -11173,13 +11411,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11173
11411
|
c.name
|
|
11174
11412
|
)
|
|
11175
11413
|
)) }),
|
|
11176
|
-
/* @__PURE__ */ (0,
|
|
11177
|
-
/* @__PURE__ */ (0,
|
|
11178
|
-
/* @__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)) })
|
|
11179
11417
|
] }),
|
|
11180
|
-
/* @__PURE__ */ (0,
|
|
11181
|
-
/* @__PURE__ */ (0,
|
|
11182
|
-
/* @__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: [
|
|
11183
11421
|
"CRP ",
|
|
11184
11422
|
g.range
|
|
11185
11423
|
] })
|
|
@@ -11189,10 +11427,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11189
11427
|
g.key
|
|
11190
11428
|
);
|
|
11191
11429
|
}) }),
|
|
11192
|
-
floorBand ? /* @__PURE__ */ (0,
|
|
11193
|
-
/* @__PURE__ */ (0,
|
|
11194
|
-
/* @__PURE__ */ (0,
|
|
11195
|
-
/* @__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: [
|
|
11196
11434
|
"Plan floor ",
|
|
11197
11435
|
floorScore
|
|
11198
11436
|
] }),
|
|
@@ -11203,8 +11441,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11203
11441
|
}
|
|
11204
11442
|
|
|
11205
11443
|
// src/components/planner/MixGap.tsx
|
|
11206
|
-
var
|
|
11207
|
-
var
|
|
11444
|
+
var React56 = __toESM(require("react"), 1);
|
|
11445
|
+
var import_jsx_runtime86 = require("react/jsx-runtime");
|
|
11208
11446
|
var MIX_GAP_LAYOUT = {
|
|
11209
11447
|
trackHeight: 30,
|
|
11210
11448
|
barHeight: 20,
|
|
@@ -11218,19 +11456,19 @@ function mixGapOffset(value, max) {
|
|
|
11218
11456
|
}
|
|
11219
11457
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
11220
11458
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
11221
|
-
const [hover, setHover] =
|
|
11459
|
+
const [hover, setHover] = React56.useState(null);
|
|
11222
11460
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
11223
11461
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
11224
11462
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
11225
11463
|
const barTop = (trackHeight - barHeight) / 2;
|
|
11226
|
-
return /* @__PURE__ */ (0,
|
|
11227
|
-
/* @__PURE__ */ (0,
|
|
11228
|
-
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0,
|
|
11229
|
-
/* @__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 } }),
|
|
11230
11468
|
l
|
|
11231
11469
|
] }, l)),
|
|
11232
|
-
/* @__PURE__ */ (0,
|
|
11233
|
-
/* @__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 } }),
|
|
11234
11472
|
"Target"
|
|
11235
11473
|
] })
|
|
11236
11474
|
] }),
|
|
@@ -11239,7 +11477,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11239
11477
|
const tone = toneOf(gap);
|
|
11240
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 : "");
|
|
11241
11479
|
const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
|
|
11242
|
-
return /* @__PURE__ */ (0,
|
|
11480
|
+
return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
|
|
11243
11481
|
"div",
|
|
11244
11482
|
{
|
|
11245
11483
|
className: "fd-row",
|
|
@@ -11247,15 +11485,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11247
11485
|
onMouseEnter: () => setHover(r.channel),
|
|
11248
11486
|
onMouseLeave: () => setHover(null),
|
|
11249
11487
|
children: [
|
|
11250
|
-
/* @__PURE__ */ (0,
|
|
11251
|
-
/* @__PURE__ */ (0,
|
|
11252
|
-
/* @__PURE__ */ (0,
|
|
11253
|
-
/* @__PURE__ */ (0,
|
|
11254
|
-
/* @__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: [
|
|
11255
11493
|
r.realized,
|
|
11256
11494
|
"%"
|
|
11257
11495
|
] }),
|
|
11258
|
-
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
|
|
11259
11497
|
] }) })
|
|
11260
11498
|
]
|
|
11261
11499
|
},
|
|
@@ -11266,7 +11504,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11266
11504
|
}
|
|
11267
11505
|
|
|
11268
11506
|
// src/components/planner/ChannelContribution.tsx
|
|
11269
|
-
var
|
|
11507
|
+
var import_jsx_runtime87 = require("react/jsx-runtime");
|
|
11270
11508
|
var money = (n) => "$" + Math.round(n).toLocaleString();
|
|
11271
11509
|
function ChannelContribution({
|
|
11272
11510
|
channels = [],
|
|
@@ -11282,9 +11520,9 @@ function ChannelContribution({
|
|
|
11282
11520
|
const grand = total !== void 0 ? total : base + bonus;
|
|
11283
11521
|
const pct = (v) => grand ? v / grand * 100 : 0;
|
|
11284
11522
|
const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
|
|
11285
|
-
return /* @__PURE__ */ (0,
|
|
11286
|
-
loading ? /* @__PURE__ */ (0,
|
|
11287
|
-
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)(
|
|
11288
11526
|
"span",
|
|
11289
11527
|
{
|
|
11290
11528
|
title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
|
|
@@ -11293,7 +11531,7 @@ function ChannelContribution({
|
|
|
11293
11531
|
},
|
|
11294
11532
|
c.name
|
|
11295
11533
|
)),
|
|
11296
|
-
bonus > 0 ? /* @__PURE__ */ (0,
|
|
11534
|
+
bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
|
|
11297
11535
|
"span",
|
|
11298
11536
|
{
|
|
11299
11537
|
title: "Surround-sound bonus +" + bonusPct + "%",
|
|
@@ -11302,18 +11540,18 @@ function ChannelContribution({
|
|
|
11302
11540
|
}
|
|
11303
11541
|
) : null
|
|
11304
11542
|
] }),
|
|
11305
|
-
showTable ? /* @__PURE__ */ (0,
|
|
11306
|
-
/* @__PURE__ */ (0,
|
|
11307
|
-
/* @__PURE__ */ (0,
|
|
11308
|
-
/* @__PURE__ */ (0,
|
|
11309
|
-
/* @__PURE__ */ (0,
|
|
11310
|
-
/* @__PURE__ */ (0,
|
|
11311
|
-
/* @__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" })
|
|
11312
11550
|
] }) }),
|
|
11313
|
-
/* @__PURE__ */ (0,
|
|
11314
|
-
channels.map((c) => /* @__PURE__ */ (0,
|
|
11315
|
-
/* @__PURE__ */ (0,
|
|
11316
|
-
/* @__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)(
|
|
11317
11555
|
"span",
|
|
11318
11556
|
{
|
|
11319
11557
|
className: "fd-badge fd-badge-neutral",
|
|
@@ -11322,38 +11560,38 @@ function ChannelContribution({
|
|
|
11322
11560
|
children: "weight " + (channelWeightOf(c.name) || 0)
|
|
11323
11561
|
}
|
|
11324
11562
|
) }),
|
|
11325
|
-
/* @__PURE__ */ (0,
|
|
11326
|
-
/* @__PURE__ */ (0,
|
|
11327
|
-
/* @__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: [
|
|
11328
11566
|
pct(c.crp).toFixed(0),
|
|
11329
11567
|
"%"
|
|
11330
11568
|
] })
|
|
11331
11569
|
] }, c.name)),
|
|
11332
|
-
bonus > 0 ? /* @__PURE__ */ (0,
|
|
11333
|
-
/* @__PURE__ */ (0,
|
|
11334
|
-
/* @__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" } }),
|
|
11335
11573
|
"Surround-sound bonus"
|
|
11336
11574
|
] }) }),
|
|
11337
|
-
/* @__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: [
|
|
11338
11576
|
"+",
|
|
11339
11577
|
bonusPct,
|
|
11340
11578
|
"% of +",
|
|
11341
11579
|
bonusMax,
|
|
11342
11580
|
"%"
|
|
11343
11581
|
] }) }),
|
|
11344
|
-
/* @__PURE__ */ (0,
|
|
11345
|
-
/* @__PURE__ */ (0,
|
|
11346
|
-
/* @__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: [
|
|
11347
11585
|
pct(bonus).toFixed(0),
|
|
11348
11586
|
"%"
|
|
11349
11587
|
] })
|
|
11350
11588
|
] }) : null,
|
|
11351
|
-
/* @__PURE__ */ (0,
|
|
11352
|
-
/* @__PURE__ */ (0,
|
|
11353
|
-
/* @__PURE__ */ (0,
|
|
11354
|
-
/* @__PURE__ */ (0,
|
|
11355
|
-
/* @__PURE__ */ (0,
|
|
11356
|
-
/* @__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%" })
|
|
11357
11595
|
] })
|
|
11358
11596
|
] })
|
|
11359
11597
|
] }) : null
|
|
@@ -11361,8 +11599,8 @@ function ChannelContribution({
|
|
|
11361
11599
|
}
|
|
11362
11600
|
|
|
11363
11601
|
// src/components/planner/BudgetReallocator.tsx
|
|
11364
|
-
var
|
|
11365
|
-
var
|
|
11602
|
+
var React57 = __toESM(require("react"), 1);
|
|
11603
|
+
var import_jsx_runtime88 = require("react/jsx-runtime");
|
|
11366
11604
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
11367
11605
|
function BudgetReallocator({
|
|
11368
11606
|
campus,
|
|
@@ -11377,8 +11615,8 @@ function BudgetReallocator({
|
|
|
11377
11615
|
onCancel,
|
|
11378
11616
|
className = ""
|
|
11379
11617
|
}) {
|
|
11380
|
-
const [draft, setDraft] =
|
|
11381
|
-
|
|
11618
|
+
const [draft, setDraft] = React57.useState(spend);
|
|
11619
|
+
React57.useEffect(() => setDraft(spend), [spend]);
|
|
11382
11620
|
const dirty = draft !== spend;
|
|
11383
11621
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
11384
11622
|
const nextBand = bandFor(nextCrp);
|
|
@@ -11393,10 +11631,10 @@ function BudgetReallocator({
|
|
|
11393
11631
|
setDraft(spend);
|
|
11394
11632
|
if (onCancel) onCancel();
|
|
11395
11633
|
};
|
|
11396
|
-
const trackRef =
|
|
11397
|
-
const chipRef =
|
|
11398
|
-
const [chipLeft, setChipLeft] =
|
|
11399
|
-
|
|
11634
|
+
const trackRef = React57.useRef(null);
|
|
11635
|
+
const chipRef = React57.useRef(null);
|
|
11636
|
+
const [chipLeft, setChipLeft] = React57.useState(null);
|
|
11637
|
+
React57.useLayoutEffect(() => {
|
|
11400
11638
|
const track = trackRef.current;
|
|
11401
11639
|
if (!dirty || !track) {
|
|
11402
11640
|
setChipLeft(null);
|
|
@@ -11417,23 +11655,23 @@ function BudgetReallocator({
|
|
|
11417
11655
|
ro.observe(track);
|
|
11418
11656
|
return () => ro.disconnect();
|
|
11419
11657
|
}, [dirty, pct]);
|
|
11420
|
-
return /* @__PURE__ */ (0,
|
|
11658
|
+
return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(
|
|
11421
11659
|
"div",
|
|
11422
11660
|
{
|
|
11423
11661
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
11424
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)" },
|
|
11425
11663
|
children: [
|
|
11426
|
-
/* @__PURE__ */ (0,
|
|
11427
|
-
/* @__PURE__ */ (0,
|
|
11428
|
-
/* @__PURE__ */ (0,
|
|
11429
|
-
dirty ? /* @__PURE__ */ (0,
|
|
11430
|
-
/* @__PURE__ */ (0,
|
|
11431
|
-
/* @__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 })
|
|
11432
11670
|
] }) : null
|
|
11433
11671
|
] }),
|
|
11434
|
-
/* @__PURE__ */ (0,
|
|
11435
|
-
/* @__PURE__ */ (0,
|
|
11436
|
-
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)(
|
|
11437
11675
|
"span",
|
|
11438
11676
|
{
|
|
11439
11677
|
ref: chipRef,
|
|
@@ -11445,7 +11683,7 @@ function BudgetReallocator({
|
|
|
11445
11683
|
children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
|
|
11446
11684
|
}
|
|
11447
11685
|
) : null,
|
|
11448
|
-
/* @__PURE__ */ (0,
|
|
11686
|
+
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
|
|
11449
11687
|
"input",
|
|
11450
11688
|
{
|
|
11451
11689
|
type: "range",
|
|
@@ -11461,13 +11699,13 @@ function BudgetReallocator({
|
|
|
11461
11699
|
}
|
|
11462
11700
|
)
|
|
11463
11701
|
] }),
|
|
11464
|
-
/* @__PURE__ */ (0,
|
|
11465
|
-
/* @__PURE__ */ (0,
|
|
11466
|
-
/* @__PURE__ */ (0,
|
|
11467
|
-
/* @__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." })
|
|
11468
11706
|
] }),
|
|
11469
|
-
/* @__PURE__ */ (0,
|
|
11470
|
-
/* @__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)(
|
|
11471
11709
|
"button",
|
|
11472
11710
|
{
|
|
11473
11711
|
type: "button",
|
|
@@ -11486,7 +11724,7 @@ function BudgetReallocator({
|
|
|
11486
11724
|
}
|
|
11487
11725
|
|
|
11488
11726
|
// src/components/planner/SurroundSound.tsx
|
|
11489
|
-
var
|
|
11727
|
+
var import_jsx_runtime89 = require("react/jsx-runtime");
|
|
11490
11728
|
var CATEGORIES = [
|
|
11491
11729
|
{ key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
|
|
11492
11730
|
{ key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
|
|
@@ -11498,26 +11736,26 @@ var CATEGORIES = [
|
|
|
11498
11736
|
function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
|
|
11499
11737
|
const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
|
|
11500
11738
|
const single = present.length <= 2;
|
|
11501
|
-
return /* @__PURE__ */ (0,
|
|
11502
|
-
/* @__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) => {
|
|
11503
11741
|
const on = present.includes(c.key);
|
|
11504
|
-
return /* @__PURE__ */ (0,
|
|
11742
|
+
return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
|
|
11505
11743
|
"span",
|
|
11506
11744
|
{
|
|
11507
11745
|
title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
|
|
11508
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)" },
|
|
11509
11747
|
children: [
|
|
11510
|
-
/* @__PURE__ */ (0,
|
|
11511
|
-
/* @__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 })
|
|
11512
11750
|
]
|
|
11513
11751
|
},
|
|
11514
11752
|
c.key
|
|
11515
11753
|
);
|
|
11516
11754
|
}) }),
|
|
11517
|
-
/* @__PURE__ */ (0,
|
|
11518
|
-
/* @__PURE__ */ (0,
|
|
11519
|
-
/* @__PURE__ */ (0,
|
|
11520
|
-
/* @__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: [
|
|
11521
11759
|
"+",
|
|
11522
11760
|
bonusPct,
|
|
11523
11761
|
"% of +",
|
|
@@ -11525,8 +11763,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
11525
11763
|
"%"
|
|
11526
11764
|
] })
|
|
11527
11765
|
] }),
|
|
11528
|
-
/* @__PURE__ */ (0,
|
|
11529
|
-
/* @__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: [
|
|
11530
11768
|
present.length,
|
|
11531
11769
|
" of 6 channel categories present.",
|
|
11532
11770
|
" ",
|
|
@@ -11538,7 +11776,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
11538
11776
|
}
|
|
11539
11777
|
|
|
11540
11778
|
// src/components/planner/Importance.tsx
|
|
11541
|
-
var
|
|
11779
|
+
var import_jsx_runtime90 = require("react/jsx-runtime");
|
|
11542
11780
|
var IMPORTANCE_LEVELS = [
|
|
11543
11781
|
{ id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
|
|
11544
11782
|
{ id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
|
|
@@ -11568,7 +11806,7 @@ function importanceTokens(id) {
|
|
|
11568
11806
|
function ImportanceTag({ level, showLabel = true, size = "sm", className = "", disabled = false }) {
|
|
11569
11807
|
const lvl = importanceLevel(level);
|
|
11570
11808
|
const t = importanceTokens(level);
|
|
11571
|
-
return /* @__PURE__ */ (0,
|
|
11809
|
+
return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(
|
|
11572
11810
|
"span",
|
|
11573
11811
|
{
|
|
11574
11812
|
className: ["fd-imp-tag", size === "md" ? "is-md" : "", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "),
|
|
@@ -11576,16 +11814,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
|
|
|
11576
11814
|
title: lvl.label + " \u2014 " + lvl.description,
|
|
11577
11815
|
"aria-disabled": disabled ? "true" : void 0,
|
|
11578
11816
|
children: [
|
|
11579
|
-
/* @__PURE__ */ (0,
|
|
11580
|
-
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 })
|
|
11581
11819
|
]
|
|
11582
11820
|
}
|
|
11583
11821
|
);
|
|
11584
11822
|
}
|
|
11585
11823
|
|
|
11586
11824
|
// src/components/planner/PreferenceMeter.tsx
|
|
11587
|
-
var
|
|
11588
|
-
var
|
|
11825
|
+
var React58 = __toESM(require("react"), 1);
|
|
11826
|
+
var import_jsx_runtime91 = require("react/jsx-runtime");
|
|
11589
11827
|
function preferenceScore(criteria) {
|
|
11590
11828
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
11591
11829
|
const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
|
|
@@ -11614,8 +11852,8 @@ function PreferenceMeter({
|
|
|
11614
11852
|
className = ""
|
|
11615
11853
|
}) {
|
|
11616
11854
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
11617
|
-
const segments =
|
|
11618
|
-
return /* @__PURE__ */ (0,
|
|
11855
|
+
const segments = React58.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
11856
|
+
return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
|
|
11619
11857
|
ScoreMeter,
|
|
11620
11858
|
{
|
|
11621
11859
|
score: value,
|
|
@@ -11627,22 +11865,22 @@ function PreferenceMeter({
|
|
|
11627
11865
|
placement,
|
|
11628
11866
|
className,
|
|
11629
11867
|
breakdownLabel: breakdownTitle,
|
|
11630
|
-
breakdown: /* @__PURE__ */ (0,
|
|
11631
|
-
/* @__PURE__ */ (0,
|
|
11632
|
-
/* @__PURE__ */ (0,
|
|
11633
|
-
/* @__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) })
|
|
11634
11872
|
] }),
|
|
11635
|
-
/* @__PURE__ */ (0,
|
|
11873
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
|
|
11636
11874
|
const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
|
|
11637
|
-
return /* @__PURE__ */ (0,
|
|
11638
|
-
/* @__PURE__ */ (0,
|
|
11639
|
-
/* @__PURE__ */ (0,
|
|
11640
|
-
/* @__PURE__ */ (0,
|
|
11641
|
-
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
|
|
11642
11880
|
] }),
|
|
11643
|
-
/* @__PURE__ */ (0,
|
|
11881
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fd-prefbreak-val fd-tabular", children: [
|
|
11644
11882
|
Math.round(Number(c.earned) || 0),
|
|
11645
|
-
/* @__PURE__ */ (0,
|
|
11883
|
+
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-prefbreak-sep", children: "/" }),
|
|
11646
11884
|
Math.round(c.weight)
|
|
11647
11885
|
] })
|
|
11648
11886
|
] }, c.id);
|
|
@@ -11653,10 +11891,10 @@ function PreferenceMeter({
|
|
|
11653
11891
|
}
|
|
11654
11892
|
|
|
11655
11893
|
// src/components/chat/AgentChatPanel.tsx
|
|
11656
|
-
var
|
|
11894
|
+
var React64 = __toESM(require("react"), 1);
|
|
11657
11895
|
|
|
11658
11896
|
// src/components/chat/chatEngine.ts
|
|
11659
|
-
var
|
|
11897
|
+
var React59 = __toESM(require("react"), 1);
|
|
11660
11898
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
11661
11899
|
var JOB_PENDING = ["queued", "running"];
|
|
11662
11900
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -11710,22 +11948,22 @@ function useChatEngine(opts) {
|
|
|
11710
11948
|
onClear,
|
|
11711
11949
|
onFeedback
|
|
11712
11950
|
} = opts || {};
|
|
11713
|
-
const [status, setStatus] =
|
|
11714
|
-
const [threadId, setThreadId] =
|
|
11715
|
-
const [messages, setMessages] =
|
|
11716
|
-
const [queue, setQueue] =
|
|
11717
|
-
const [fatal, setFatal] =
|
|
11718
|
-
const [busy, setBusy] =
|
|
11719
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
11720
|
-
const listRef =
|
|
11721
|
-
const queueRef =
|
|
11722
|
-
const busyRef =
|
|
11723
|
-
const stoppedRef =
|
|
11724
|
-
const abortRef =
|
|
11725
|
-
const serverCount =
|
|
11726
|
-
const threadRef =
|
|
11727
|
-
const mounted =
|
|
11728
|
-
|
|
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(() => {
|
|
11729
11967
|
mounted.current = true;
|
|
11730
11968
|
return () => {
|
|
11731
11969
|
mounted.current = false;
|
|
@@ -11747,14 +11985,14 @@ function useChatEngine(opts) {
|
|
|
11747
11985
|
}
|
|
11748
11986
|
return false;
|
|
11749
11987
|
};
|
|
11750
|
-
const loadThread =
|
|
11988
|
+
const loadThread = React59.useCallback(async (id) => {
|
|
11751
11989
|
const data = await apiAdapter.getThread(id);
|
|
11752
11990
|
const list = [...data && data.messages || []];
|
|
11753
11991
|
serverCount.current = list.length;
|
|
11754
11992
|
commit(list);
|
|
11755
11993
|
return list;
|
|
11756
11994
|
}, [apiAdapter]);
|
|
11757
|
-
|
|
11995
|
+
React59.useEffect(() => {
|
|
11758
11996
|
if (!apiAdapter) {
|
|
11759
11997
|
setStatus("idle");
|
|
11760
11998
|
setFatal(null);
|
|
@@ -11967,7 +12205,7 @@ function useChatEngine(opts) {
|
|
|
11967
12205
|
await dispatchTurn(turn);
|
|
11968
12206
|
}
|
|
11969
12207
|
}
|
|
11970
|
-
const send =
|
|
12208
|
+
const send = React59.useCallback((text, attachments) => {
|
|
11971
12209
|
const body = (text || "").trim();
|
|
11972
12210
|
if (!body && !(attachments && attachments.length)) return;
|
|
11973
12211
|
if (status === "disconnected") return;
|
|
@@ -11977,7 +12215,7 @@ function useChatEngine(opts) {
|
|
|
11977
12215
|
stoppedRef.current = false;
|
|
11978
12216
|
drain();
|
|
11979
12217
|
}, [status]);
|
|
11980
|
-
const stop =
|
|
12218
|
+
const stop = React59.useCallback(() => {
|
|
11981
12219
|
stoppedRef.current = true;
|
|
11982
12220
|
const ac = abortRef.current;
|
|
11983
12221
|
if (ac) {
|
|
@@ -11996,11 +12234,11 @@ function useChatEngine(opts) {
|
|
|
11996
12234
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
11997
12235
|
}
|
|
11998
12236
|
}, [apiAdapter]);
|
|
11999
|
-
const removeQueued =
|
|
12237
|
+
const removeQueued = React59.useCallback((id) => {
|
|
12000
12238
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
12001
12239
|
setQueue(queueRef.current.slice());
|
|
12002
12240
|
}, []);
|
|
12003
|
-
const retry =
|
|
12241
|
+
const retry = React59.useCallback(() => {
|
|
12004
12242
|
const list = listRef.current;
|
|
12005
12243
|
let at = -1;
|
|
12006
12244
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -12016,19 +12254,19 @@ function useChatEngine(opts) {
|
|
|
12016
12254
|
setQueue(queueRef.current.slice());
|
|
12017
12255
|
drain();
|
|
12018
12256
|
}, []);
|
|
12019
|
-
const clear =
|
|
12257
|
+
const clear = React59.useCallback(() => {
|
|
12020
12258
|
commit([]);
|
|
12021
12259
|
serverCount.current = 0;
|
|
12022
12260
|
queueRef.current = [];
|
|
12023
12261
|
setQueue([]);
|
|
12024
12262
|
onClear && onClear();
|
|
12025
12263
|
}, [onClear]);
|
|
12026
|
-
const setFeedback =
|
|
12264
|
+
const setFeedback = React59.useCallback((id, value) => {
|
|
12027
12265
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
12028
12266
|
const msg = listRef.current.find((m) => m.id === id);
|
|
12029
12267
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
12030
12268
|
}, [onFeedback]);
|
|
12031
|
-
const reload =
|
|
12269
|
+
const reload = React59.useCallback(async () => {
|
|
12032
12270
|
if (!threadRef.current) return;
|
|
12033
12271
|
setStatus("loading");
|
|
12034
12272
|
try {
|
|
@@ -12066,11 +12304,11 @@ var ChatKit = {
|
|
|
12066
12304
|
};
|
|
12067
12305
|
|
|
12068
12306
|
// src/components/chat/ChatTranscript.tsx
|
|
12069
|
-
var
|
|
12307
|
+
var React61 = __toESM(require("react"), 1);
|
|
12070
12308
|
|
|
12071
12309
|
// src/components/chat/ChatTurn.tsx
|
|
12072
|
-
var
|
|
12073
|
-
var
|
|
12310
|
+
var React60 = __toESM(require("react"), 1);
|
|
12311
|
+
var import_jsx_runtime92 = require("react/jsx-runtime");
|
|
12074
12312
|
function JsonView({ value }) {
|
|
12075
12313
|
let text;
|
|
12076
12314
|
try {
|
|
@@ -12078,67 +12316,67 @@ function JsonView({ value }) {
|
|
|
12078
12316
|
} catch (e) {
|
|
12079
12317
|
text = String(value);
|
|
12080
12318
|
}
|
|
12081
|
-
return /* @__PURE__ */ (0,
|
|
12319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
|
|
12082
12320
|
}
|
|
12083
12321
|
function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
12084
12322
|
if (!packet) return null;
|
|
12085
12323
|
const s = schema || {};
|
|
12086
12324
|
const invalid = packet.valid === false;
|
|
12087
12325
|
const title = s.heading || packet.type;
|
|
12088
|
-
return /* @__PURE__ */ (0,
|
|
12089
|
-
/* @__PURE__ */ (0,
|
|
12090
|
-
/* @__PURE__ */ (0,
|
|
12091
|
-
/* @__PURE__ */ (0,
|
|
12092
|
-
packet.repaired ? /* @__PURE__ */ (0,
|
|
12093
|
-
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
|
|
12094
12332
|
] }),
|
|
12095
|
-
invalid ? /* @__PURE__ */ (0,
|
|
12096
|
-
/* @__PURE__ */ (0,
|
|
12097
|
-
/* @__PURE__ */ (0,
|
|
12098
|
-
] }) : /* @__PURE__ */ (0,
|
|
12099
|
-
!invalid && onApply ? /* @__PURE__ */ (0,
|
|
12100
|
-
packet.repaired ? /* @__PURE__ */ (0,
|
|
12101
|
-
/* @__PURE__ */ (0,
|
|
12102
|
-
/* @__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" }),
|
|
12103
12341
|
applied ? "Applied" : s.applyLabel || "Apply"
|
|
12104
12342
|
] })
|
|
12105
12343
|
] }) : null
|
|
12106
12344
|
] });
|
|
12107
12345
|
}
|
|
12108
12346
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
12109
|
-
const [open2, setOpen] =
|
|
12347
|
+
const [open2, setOpen] = React60.useState(defaultOpen);
|
|
12110
12348
|
if (!text) return null;
|
|
12111
|
-
return /* @__PURE__ */ (0,
|
|
12112
|
-
/* @__PURE__ */ (0,
|
|
12113
|
-
/* @__PURE__ */ (0,
|
|
12114
|
-
/* @__PURE__ */ (0,
|
|
12115
|
-
streaming ? /* @__PURE__ */ (0,
|
|
12116
|
-
/* @__PURE__ */ (0,
|
|
12117
|
-
/* @__PURE__ */ (0,
|
|
12118
|
-
/* @__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", {})
|
|
12119
12357
|
] }) : null,
|
|
12120
|
-
/* @__PURE__ */ (0,
|
|
12358
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
|
|
12121
12359
|
] }),
|
|
12122
|
-
open2 ? /* @__PURE__ */ (0,
|
|
12360
|
+
open2 ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-think-body", children: text }) : null
|
|
12123
12361
|
] });
|
|
12124
12362
|
}
|
|
12125
12363
|
function Citations({ items = [], onOpen }) {
|
|
12126
|
-
const [open2, setOpen] =
|
|
12364
|
+
const [open2, setOpen] = React60.useState(false);
|
|
12127
12365
|
if (!items.length) return null;
|
|
12128
|
-
return /* @__PURE__ */ (0,
|
|
12129
|
-
/* @__PURE__ */ (0,
|
|
12130
|
-
/* @__PURE__ */ (0,
|
|
12131
|
-
/* @__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: [
|
|
12132
12370
|
items.length,
|
|
12133
12371
|
" source",
|
|
12134
12372
|
items.length === 1 ? "" : "s"
|
|
12135
12373
|
] }),
|
|
12136
|
-
/* @__PURE__ */ (0,
|
|
12374
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
|
|
12137
12375
|
] }),
|
|
12138
|
-
open2 ? /* @__PURE__ */ (0,
|
|
12139
|
-
/* @__PURE__ */ (0,
|
|
12140
|
-
c.url ? /* @__PURE__ */ (0,
|
|
12141
|
-
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
|
|
12142
12380
|
] }, c.id || i)) }) : null
|
|
12143
12381
|
] });
|
|
12144
12382
|
}
|
|
@@ -12149,29 +12387,29 @@ function clampText(text, max) {
|
|
|
12149
12387
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
12150
12388
|
}
|
|
12151
12389
|
function MessageBody({ message: m, ctx }) {
|
|
12152
|
-
const [expanded, setExpanded] =
|
|
12390
|
+
const [expanded, setExpanded] = React60.useState(false);
|
|
12153
12391
|
const isUser = m.role === "user";
|
|
12154
12392
|
const raw = m.text || "";
|
|
12155
12393
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
12156
12394
|
const body = clamped != null ? clamped : raw;
|
|
12157
12395
|
const showMd = ctx.markdown && !isUser;
|
|
12158
|
-
return /* @__PURE__ */ (0,
|
|
12159
|
-
m.thinking && ctx.showThinking ? /* @__PURE__ */ (0,
|
|
12160
|
-
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0,
|
|
12161
|
-
body ? /* @__PURE__ */ (0,
|
|
12162
|
-
showMd ? /* @__PURE__ */ (0,
|
|
12163
|
-
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
|
|
12164
12402
|
] }) : null,
|
|
12165
|
-
clamped != null ? /* @__PURE__ */ (0,
|
|
12166
|
-
/* @__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" }),
|
|
12167
12405
|
"Show more",
|
|
12168
|
-
/* @__PURE__ */ (0,
|
|
12169
|
-
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0,
|
|
12170
|
-
/* @__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" }),
|
|
12171
12409
|
"Show less"
|
|
12172
12410
|
] }) : null,
|
|
12173
|
-
m.attachments && m.attachments.length ? /* @__PURE__ */ (0,
|
|
12174
|
-
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)(
|
|
12175
12413
|
PacketCard,
|
|
12176
12414
|
{
|
|
12177
12415
|
packet: m.packet,
|
|
@@ -12181,44 +12419,44 @@ function MessageBody({ message: m, ctx }) {
|
|
|
12181
12419
|
applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
|
|
12182
12420
|
}
|
|
12183
12421
|
) : null,
|
|
12184
|
-
m.citations && m.citations.length ? /* @__PURE__ */ (0,
|
|
12185
|
-
m.working ? /* @__PURE__ */ (0,
|
|
12186
|
-
/* @__PURE__ */ (0,
|
|
12187
|
-
/* @__PURE__ */ (0,
|
|
12188
|
-
/* @__PURE__ */ (0,
|
|
12189
|
-
/* @__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", {})
|
|
12190
12428
|
] }),
|
|
12191
|
-
/* @__PURE__ */ (0,
|
|
12429
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-working-label", children: [
|
|
12192
12430
|
m.resumed ? "Resuming" : "Working",
|
|
12193
|
-
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: [
|
|
12194
12432
|
" \xB7 ",
|
|
12195
12433
|
m.job.status
|
|
12196
12434
|
] }) : null,
|
|
12197
|
-
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: [
|
|
12198
12436
|
" \xB7 ",
|
|
12199
12437
|
m.job.detail
|
|
12200
12438
|
] }) : null
|
|
12201
12439
|
] }),
|
|
12202
|
-
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
|
|
12203
12441
|
] }) : null,
|
|
12204
|
-
m.stopped ? /* @__PURE__ */ (0,
|
|
12205
|
-
/* @__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" }),
|
|
12206
12444
|
"Stopped"
|
|
12207
12445
|
] }) : null,
|
|
12208
|
-
m.error ? /* @__PURE__ */ (0,
|
|
12209
|
-
/* @__PURE__ */ (0,
|
|
12210
|
-
/* @__PURE__ */ (0,
|
|
12211
|
-
m.retryable && ctx.onRetry ? /* @__PURE__ */ (0,
|
|
12212
|
-
/* @__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" }),
|
|
12213
12451
|
"Retry"
|
|
12214
12452
|
] }) : null
|
|
12215
12453
|
] }) : null
|
|
12216
12454
|
] });
|
|
12217
12455
|
}
|
|
12218
12456
|
function useCopyRun() {
|
|
12219
|
-
const [done, setDone] =
|
|
12220
|
-
const t =
|
|
12221
|
-
|
|
12457
|
+
const [done, setDone] = React60.useState(false);
|
|
12458
|
+
const t = React60.useRef(null);
|
|
12459
|
+
React60.useEffect(() => () => {
|
|
12222
12460
|
if (t.current) clearTimeout(t.current);
|
|
12223
12461
|
}, []);
|
|
12224
12462
|
return [done, (text) => {
|
|
@@ -12238,16 +12476,16 @@ function RunActions({ group, ctx }) {
|
|
|
12238
12476
|
const isAssistant = group.role === "assistant";
|
|
12239
12477
|
const fb = last.feedback;
|
|
12240
12478
|
if (!ctx.messageActions) return null;
|
|
12241
|
-
return /* @__PURE__ */ (0,
|
|
12242
|
-
/* @__PURE__ */ (0,
|
|
12243
|
-
/* @__PURE__ */ (0,
|
|
12244
|
-
/* @__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" })
|
|
12245
12483
|
] }),
|
|
12246
|
-
isAssistant && ctx.onRetry ? /* @__PURE__ */ (0,
|
|
12247
|
-
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0,
|
|
12248
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0,
|
|
12249
|
-
/* @__PURE__ */ (0,
|
|
12250
|
-
/* @__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" }) })
|
|
12251
12489
|
] }) : null,
|
|
12252
12490
|
ctx.extraActions ? ctx.extraActions(group) : null
|
|
12253
12491
|
] });
|
|
@@ -12257,22 +12495,22 @@ function ChatTurn({ group, ctx }) {
|
|
|
12257
12495
|
const name = isUser ? ctx.userName : group.author || ctx.assistantName;
|
|
12258
12496
|
const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
|
|
12259
12497
|
const stamp = group.messages[0].timestamp;
|
|
12260
|
-
return /* @__PURE__ */ (0,
|
|
12261
|
-
/* @__PURE__ */ (0,
|
|
12262
|
-
ctx.showAvatars ? /* @__PURE__ */ (0,
|
|
12263
|
-
/* @__PURE__ */ (0,
|
|
12264
|
-
stamp ? /* @__PURE__ */ (0,
|
|
12265
|
-
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
|
|
12266
12504
|
] }),
|
|
12267
|
-
/* @__PURE__ */ (0,
|
|
12268
|
-
group.messages.map((m) => /* @__PURE__ */ (0,
|
|
12269
|
-
/* @__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 })
|
|
12270
12508
|
] })
|
|
12271
12509
|
] });
|
|
12272
12510
|
}
|
|
12273
12511
|
|
|
12274
12512
|
// src/components/chat/ChatTranscript.tsx
|
|
12275
|
-
var
|
|
12513
|
+
var import_jsx_runtime93 = require("react/jsx-runtime");
|
|
12276
12514
|
var GROUP_WINDOW = 6e4;
|
|
12277
12515
|
var STICK_PX = 100;
|
|
12278
12516
|
function groupMessages(list) {
|
|
@@ -12305,25 +12543,25 @@ function dayLabel(key) {
|
|
|
12305
12543
|
}
|
|
12306
12544
|
function Suggestions({ items = [], onPick }) {
|
|
12307
12545
|
if (!items.length) return null;
|
|
12308
|
-
return /* @__PURE__ */ (0,
|
|
12546
|
+
return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
|
|
12309
12547
|
const it = typeof s === "string" ? { label: s, text: s } : s;
|
|
12310
|
-
return /* @__PURE__ */ (0,
|
|
12311
|
-
it.icon ? /* @__PURE__ */ (0,
|
|
12312
|
-
/* @__PURE__ */ (0,
|
|
12313
|
-
/* @__PURE__ */ (0,
|
|
12314
|
-
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
|
|
12315
12553
|
] }),
|
|
12316
|
-
/* @__PURE__ */ (0,
|
|
12554
|
+
/* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
|
|
12317
12555
|
] }, it.id || i);
|
|
12318
12556
|
}) });
|
|
12319
12557
|
}
|
|
12320
12558
|
function LoadingTurns() {
|
|
12321
|
-
return /* @__PURE__ */ (0,
|
|
12322
|
-
/* @__PURE__ */ (0,
|
|
12323
|
-
/* @__PURE__ */ (0,
|
|
12324
|
-
/* @__PURE__ */ (0,
|
|
12325
|
-
/* @__PURE__ */ (0,
|
|
12326
|
-
/* @__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 } })
|
|
12327
12565
|
] })
|
|
12328
12566
|
] }, i)) });
|
|
12329
12567
|
}
|
|
@@ -12340,10 +12578,10 @@ function ChatTranscript({
|
|
|
12340
12578
|
renderEmpty,
|
|
12341
12579
|
className = ""
|
|
12342
12580
|
}) {
|
|
12343
|
-
const scroller =
|
|
12344
|
-
const stick =
|
|
12345
|
-
const [pill, setPill] =
|
|
12346
|
-
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);
|
|
12347
12585
|
const toBottom = (smooth) => {
|
|
12348
12586
|
const el = scroller.current;
|
|
12349
12587
|
if (!el) return;
|
|
@@ -12362,7 +12600,7 @@ function ChatTranscript({
|
|
|
12362
12600
|
seen.current = messages.length;
|
|
12363
12601
|
}
|
|
12364
12602
|
};
|
|
12365
|
-
|
|
12603
|
+
React61.useLayoutEffect(() => {
|
|
12366
12604
|
const el = scroller.current;
|
|
12367
12605
|
if (!el) return;
|
|
12368
12606
|
if (stick.current) {
|
|
@@ -12370,7 +12608,7 @@ function ChatTranscript({
|
|
|
12370
12608
|
seen.current = messages.length;
|
|
12371
12609
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
12372
12610
|
}, [messages]);
|
|
12373
|
-
|
|
12611
|
+
React61.useEffect(() => {
|
|
12374
12612
|
const el = scroller.current;
|
|
12375
12613
|
const inner = el && el.firstChild;
|
|
12376
12614
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -12380,38 +12618,38 @@ function ChatTranscript({
|
|
|
12380
12618
|
ro.observe(inner);
|
|
12381
12619
|
return () => ro.disconnect();
|
|
12382
12620
|
}, []);
|
|
12383
|
-
const groups =
|
|
12621
|
+
const groups = React61.useMemo(() => groupMessages(messages), [messages]);
|
|
12384
12622
|
const empty = !messages.length && status === "ready";
|
|
12385
|
-
return /* @__PURE__ */ (0,
|
|
12386
|
-
/* @__PURE__ */ (0,
|
|
12387
|
-
status === "loading" || status === "resolving" ? /* @__PURE__ */ (0,
|
|
12388
|
-
status === "disconnected" ? /* @__PURE__ */ (0,
|
|
12389
|
-
/* @__PURE__ */ (0,
|
|
12390
|
-
/* @__PURE__ */ (0,
|
|
12391
|
-
/* @__PURE__ */ (0,
|
|
12392
|
-
ctx.onReconnect ? /* @__PURE__ */ (0,
|
|
12393
|
-
/* @__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" }),
|
|
12394
12632
|
"Try again"
|
|
12395
12633
|
] }) : null
|
|
12396
12634
|
] }) : null,
|
|
12397
|
-
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0,
|
|
12398
|
-
/* @__PURE__ */ (0,
|
|
12399
|
-
/* @__PURE__ */ (0,
|
|
12400
|
-
emptyDescription ? /* @__PURE__ */ (0,
|
|
12401
|
-
/* @__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 })
|
|
12402
12640
|
] }) : null,
|
|
12403
12641
|
groups.map((g, i) => {
|
|
12404
12642
|
const prev = groups[i - 1];
|
|
12405
12643
|
const k = dayKey(g.messages[0].timestamp);
|
|
12406
12644
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
12407
|
-
return /* @__PURE__ */ (0,
|
|
12408
|
-
showDay ? /* @__PURE__ */ (0,
|
|
12409
|
-
/* @__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 })
|
|
12410
12648
|
] }, g.key || i);
|
|
12411
12649
|
})
|
|
12412
12650
|
] }),
|
|
12413
|
-
pill ? /* @__PURE__ */ (0,
|
|
12414
|
-
/* @__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" }),
|
|
12415
12653
|
pill,
|
|
12416
12654
|
" new message",
|
|
12417
12655
|
pill === 1 ? "" : "s"
|
|
@@ -12421,8 +12659,8 @@ function ChatTranscript({
|
|
|
12421
12659
|
var TranscriptKit = { groupMessages };
|
|
12422
12660
|
|
|
12423
12661
|
// src/components/chat/ChatComposer.tsx
|
|
12424
|
-
var
|
|
12425
|
-
var
|
|
12662
|
+
var React62 = __toESM(require("react"), 1);
|
|
12663
|
+
var import_jsx_runtime94 = require("react/jsx-runtime");
|
|
12426
12664
|
function ChatComposer({
|
|
12427
12665
|
onSubmit,
|
|
12428
12666
|
onStop,
|
|
@@ -12449,17 +12687,17 @@ function ChatComposer({
|
|
|
12449
12687
|
onReject,
|
|
12450
12688
|
onOpenAttachment
|
|
12451
12689
|
}) {
|
|
12452
|
-
const [text, setText] =
|
|
12453
|
-
const [trigger, setTrigger] =
|
|
12454
|
-
const [mentionItems, setMentionItems] =
|
|
12455
|
-
const [listening, setListening] =
|
|
12456
|
-
const [notice, setNotice] =
|
|
12457
|
-
const editor =
|
|
12458
|
-
const wrap =
|
|
12459
|
-
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);
|
|
12460
12698
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
12461
12699
|
} });
|
|
12462
|
-
|
|
12700
|
+
React62.useEffect(() => {
|
|
12463
12701
|
if (draft != null && draft !== text) setText(draft);
|
|
12464
12702
|
}, [draft]);
|
|
12465
12703
|
const change = (v) => {
|
|
@@ -12495,7 +12733,7 @@ function ChatComposer({
|
|
|
12495
12733
|
e.preventDefault();
|
|
12496
12734
|
staged.add(found.files);
|
|
12497
12735
|
};
|
|
12498
|
-
|
|
12736
|
+
React62.useEffect(() => {
|
|
12499
12737
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
12500
12738
|
setMentionItems([]);
|
|
12501
12739
|
return;
|
|
@@ -12513,7 +12751,7 @@ function ChatComposer({
|
|
|
12513
12751
|
const q = (trigger.query || "").toLowerCase();
|
|
12514
12752
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
12515
12753
|
}, [trigger, mentionSources]);
|
|
12516
|
-
const slashItems =
|
|
12754
|
+
const slashItems = React62.useMemo(() => {
|
|
12517
12755
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
12518
12756
|
const q = (trigger.query || "").toLowerCase();
|
|
12519
12757
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -12527,7 +12765,7 @@ function ChatComposer({
|
|
|
12527
12765
|
description: it.description,
|
|
12528
12766
|
icon: it.icon,
|
|
12529
12767
|
meta: mention.meta,
|
|
12530
|
-
shortcut: slash.shortcut ? /* @__PURE__ */ (0,
|
|
12768
|
+
shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
|
|
12531
12769
|
onSelect: () => {
|
|
12532
12770
|
const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
|
|
12533
12771
|
editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
|
|
@@ -12586,14 +12824,14 @@ function ChatComposer({
|
|
|
12586
12824
|
stopVoice.current = typeof res === "function" ? res : () => {
|
|
12587
12825
|
};
|
|
12588
12826
|
};
|
|
12589
|
-
return /* @__PURE__ */ (0,
|
|
12590
|
-
queue.length ? /* @__PURE__ */ (0,
|
|
12591
|
-
/* @__PURE__ */ (0,
|
|
12592
|
-
/* @__PURE__ */ (0,
|
|
12593
|
-
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
|
|
12594
12832
|
] }, q.id)) }) : null,
|
|
12595
12833
|
sessionBar,
|
|
12596
|
-
/* @__PURE__ */ (0,
|
|
12834
|
+
/* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
|
|
12597
12835
|
Dropzone,
|
|
12598
12836
|
{
|
|
12599
12837
|
className: "fdc-field",
|
|
@@ -12607,9 +12845,9 @@ function ChatComposer({
|
|
|
12607
12845
|
disabled: !fileUploadHandler || disabled,
|
|
12608
12846
|
label: "Drop to attach",
|
|
12609
12847
|
hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
|
|
12610
|
-
children: /* @__PURE__ */ (0,
|
|
12611
|
-
staged.items.length ? /* @__PURE__ */ (0,
|
|
12612
|
-
/* @__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)(
|
|
12613
12851
|
MarkdownEditor,
|
|
12614
12852
|
{
|
|
12615
12853
|
ref: editor,
|
|
@@ -12628,33 +12866,33 @@ function ChatComposer({
|
|
|
12628
12866
|
ariaLabel: "Message"
|
|
12629
12867
|
}
|
|
12630
12868
|
),
|
|
12631
|
-
/* @__PURE__ */ (0,
|
|
12632
|
-
fileUploadHandler ? /* @__PURE__ */ (0,
|
|
12633
|
-
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,
|
|
12634
12872
|
toolbarExtras,
|
|
12635
|
-
/* @__PURE__ */ (0,
|
|
12636
|
-
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: [
|
|
12637
12875
|
text.length,
|
|
12638
12876
|
"/",
|
|
12639
12877
|
maxLength
|
|
12640
12878
|
] }) : null,
|
|
12641
|
-
busy ? /* @__PURE__ */ (0,
|
|
12642
|
-
/* @__PURE__ */ (0,
|
|
12643
|
-
/* @__PURE__ */ (0,
|
|
12644
|
-
] }) : /* @__PURE__ */ (0,
|
|
12645
|
-
/* @__PURE__ */ (0,
|
|
12646
|
-
/* @__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" })
|
|
12647
12885
|
] })
|
|
12648
12886
|
] })
|
|
12649
12887
|
] })
|
|
12650
12888
|
}
|
|
12651
12889
|
),
|
|
12652
|
-
notice ? /* @__PURE__ */ (0,
|
|
12653
|
-
/* @__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" }),
|
|
12654
12892
|
notice
|
|
12655
12893
|
] }) : null,
|
|
12656
|
-
hint && !notice ? /* @__PURE__ */ (0,
|
|
12657
|
-
/* @__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)(
|
|
12658
12896
|
Popover,
|
|
12659
12897
|
{
|
|
12660
12898
|
open: menuOpen,
|
|
@@ -12668,12 +12906,12 @@ function ChatComposer({
|
|
|
12668
12906
|
returnFocus: false,
|
|
12669
12907
|
closeOnOutside: true,
|
|
12670
12908
|
label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
|
|
12671
|
-
children: /* @__PURE__ */ (0,
|
|
12909
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
|
|
12672
12910
|
Menu,
|
|
12673
12911
|
{
|
|
12674
12912
|
items: menuItems,
|
|
12675
12913
|
autoFocus: false,
|
|
12676
|
-
header: /* @__PURE__ */ (0,
|
|
12914
|
+
header: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
|
|
12677
12915
|
onClose: () => setTrigger(null)
|
|
12678
12916
|
}
|
|
12679
12917
|
)
|
|
@@ -12683,12 +12921,12 @@ function ChatComposer({
|
|
|
12683
12921
|
}
|
|
12684
12922
|
|
|
12685
12923
|
// src/components/chat/ChatSessionBar.tsx
|
|
12686
|
-
var
|
|
12687
|
-
var
|
|
12924
|
+
var React63 = __toESM(require("react"), 1);
|
|
12925
|
+
var import_jsx_runtime95 = require("react/jsx-runtime");
|
|
12688
12926
|
var compact2 = meterFormats.compact;
|
|
12689
12927
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
12690
|
-
const [open2, setOpen] =
|
|
12691
|
-
const anchor =
|
|
12928
|
+
const [open2, setOpen] = React63.useState(false);
|
|
12929
|
+
const anchor = React63.useRef(null);
|
|
12692
12930
|
const stats = sessionStats || null;
|
|
12693
12931
|
const cu = contextUsage || null;
|
|
12694
12932
|
const limits = usageLimits || null;
|
|
@@ -12703,9 +12941,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12703
12941
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
12704
12942
|
if (cu) bits.push(pct + "% context");
|
|
12705
12943
|
const expandable = !!(cu || limits);
|
|
12706
|
-
return /* @__PURE__ */ (0,
|
|
12707
|
-
/* @__PURE__ */ (0,
|
|
12708
|
-
/* @__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)(
|
|
12709
12947
|
"button",
|
|
12710
12948
|
{
|
|
12711
12949
|
type: "button",
|
|
@@ -12716,15 +12954,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12716
12954
|
"aria-expanded": expandable ? open2 : void 0,
|
|
12717
12955
|
"aria-label": expandable ? "Usage details" : void 0,
|
|
12718
12956
|
children: [
|
|
12719
|
-
cu ? /* @__PURE__ */ (0,
|
|
12720
|
-
/* @__PURE__ */ (0,
|
|
12721
|
-
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
|
|
12722
12960
|
]
|
|
12723
12961
|
}
|
|
12724
12962
|
),
|
|
12725
12963
|
extras
|
|
12726
12964
|
] }),
|
|
12727
|
-
/* @__PURE__ */ (0,
|
|
12965
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
|
|
12728
12966
|
Popover,
|
|
12729
12967
|
{
|
|
12730
12968
|
open: open2,
|
|
@@ -12735,15 +12973,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12735
12973
|
maxHeight: 460,
|
|
12736
12974
|
padded: true,
|
|
12737
12975
|
label: "Usage",
|
|
12738
|
-
footer: onClear ? /* @__PURE__ */ (0,
|
|
12976
|
+
footer: onClear ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
|
|
12739
12977
|
setOpen(false);
|
|
12740
12978
|
onClear();
|
|
12741
12979
|
}, children: [
|
|
12742
|
-
/* @__PURE__ */ (0,
|
|
12980
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
|
|
12743
12981
|
"Clear conversation"
|
|
12744
12982
|
] }) : void 0,
|
|
12745
|
-
children: /* @__PURE__ */ (0,
|
|
12746
|
-
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)(
|
|
12747
12985
|
SegmentedMeter,
|
|
12748
12986
|
{
|
|
12749
12987
|
total,
|
|
@@ -12755,9 +12993,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12755
12993
|
remainderLabel: "Free"
|
|
12756
12994
|
}
|
|
12757
12995
|
) }) : null,
|
|
12758
|
-
limits && limits.length ? /* @__PURE__ */ (0,
|
|
12759
|
-
/* @__PURE__ */ (0,
|
|
12760
|
-
/* @__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)(
|
|
12761
12999
|
QuotaRow,
|
|
12762
13000
|
{
|
|
12763
13001
|
label: l.label,
|
|
@@ -12767,25 +13005,25 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12767
13005
|
l.id
|
|
12768
13006
|
)) })
|
|
12769
13007
|
] }) : null,
|
|
12770
|
-
stats ? /* @__PURE__ */ (0,
|
|
12771
|
-
stats.elapsedMs ? /* @__PURE__ */ (0,
|
|
12772
|
-
/* @__PURE__ */ (0,
|
|
12773
|
-
/* @__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) })
|
|
12774
13012
|
] }) : null,
|
|
12775
|
-
stats.tokens ? /* @__PURE__ */ (0,
|
|
12776
|
-
/* @__PURE__ */ (0,
|
|
12777
|
-
/* @__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() })
|
|
12778
13016
|
] }) : null,
|
|
12779
|
-
stats.costUsd != null ? /* @__PURE__ */ (0,
|
|
12780
|
-
/* @__PURE__ */ (0,
|
|
12781
|
-
/* @__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: [
|
|
12782
13020
|
"$",
|
|
12783
13021
|
Number(stats.costUsd).toFixed(3)
|
|
12784
13022
|
] })
|
|
12785
13023
|
] }) : null,
|
|
12786
|
-
stats.turns ? /* @__PURE__ */ (0,
|
|
12787
|
-
/* @__PURE__ */ (0,
|
|
12788
|
-
/* @__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 })
|
|
12789
13027
|
] }) : null
|
|
12790
13028
|
] }) : null
|
|
12791
13029
|
] })
|
|
@@ -12824,7 +13062,7 @@ function ModelControls({
|
|
|
12824
13062
|
disabled: m.disabled,
|
|
12825
13063
|
checked: m.id === (current2 && current2.id),
|
|
12826
13064
|
meta: m.meta,
|
|
12827
|
-
shortcut: m.shortcut ? /* @__PURE__ */ (0,
|
|
13065
|
+
shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
|
|
12828
13066
|
onSelect: () => onModelChange && onModelChange(m.id)
|
|
12829
13067
|
});
|
|
12830
13068
|
const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
|
|
@@ -12837,15 +13075,15 @@ function ModelControls({
|
|
|
12837
13075
|
items.push({ kind: "section", label: "Fast mode" });
|
|
12838
13076
|
items.push({
|
|
12839
13077
|
kind: "custom",
|
|
12840
|
-
render: () => /* @__PURE__ */ (0,
|
|
12841
|
-
/* @__PURE__ */ (0,
|
|
12842
|
-
/* @__PURE__ */ (0,
|
|
12843
|
-
/* @__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" }) })
|
|
12844
13082
|
] })
|
|
12845
13083
|
});
|
|
12846
13084
|
}
|
|
12847
|
-
return /* @__PURE__ */ (0,
|
|
12848
|
-
/* @__PURE__ */ (0,
|
|
13085
|
+
return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(React63.Fragment, { children: [
|
|
13086
|
+
/* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
|
|
12849
13087
|
MenuButton,
|
|
12850
13088
|
{
|
|
12851
13089
|
items,
|
|
@@ -12856,7 +13094,7 @@ function ModelControls({
|
|
|
12856
13094
|
title: "Choose a model"
|
|
12857
13095
|
}
|
|
12858
13096
|
),
|
|
12859
|
-
effortLevels && effortLevels.length ? /* @__PURE__ */ (0,
|
|
13097
|
+
effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
|
|
12860
13098
|
MenuButton,
|
|
12861
13099
|
{
|
|
12862
13100
|
placement: "top-end",
|
|
@@ -12877,7 +13115,7 @@ function ModelControls({
|
|
|
12877
13115
|
}
|
|
12878
13116
|
|
|
12879
13117
|
// src/components/chat/AgentChatPanel.tsx
|
|
12880
|
-
var
|
|
13118
|
+
var import_jsx_runtime96 = require("react/jsx-runtime");
|
|
12881
13119
|
var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
|
|
12882
13120
|
function AgentChatPanel({
|
|
12883
13121
|
/* required */
|
|
@@ -12961,11 +13199,11 @@ function AgentChatPanel({
|
|
|
12961
13199
|
onFeedback,
|
|
12962
13200
|
onEditMessage
|
|
12963
13201
|
}) {
|
|
12964
|
-
const [panelWidth, setPanelWidth] =
|
|
12965
|
-
const [applied, setApplied] =
|
|
12966
|
-
const [draft, setDraft] =
|
|
12967
|
-
const dragging =
|
|
12968
|
-
|
|
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]);
|
|
12969
13207
|
const engine = useChatEngine({
|
|
12970
13208
|
contextType,
|
|
12971
13209
|
contextId,
|
|
@@ -13031,7 +13269,7 @@ function AgentChatPanel({
|
|
|
13031
13269
|
onReconnect: engine.reload,
|
|
13032
13270
|
deadTitle: "The assistant isn\u2019t reachable"
|
|
13033
13271
|
};
|
|
13034
|
-
const sessionBar = /* @__PURE__ */ (0,
|
|
13272
|
+
const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
|
|
13035
13273
|
ChatSessionBar,
|
|
13036
13274
|
{
|
|
13037
13275
|
sessionStats,
|
|
@@ -13040,7 +13278,7 @@ function AgentChatPanel({
|
|
|
13040
13278
|
onClear: engine.visible.length ? engine.clear : void 0
|
|
13041
13279
|
}
|
|
13042
13280
|
);
|
|
13043
|
-
const modelControls = /* @__PURE__ */ (0,
|
|
13281
|
+
const modelControls = /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
|
|
13044
13282
|
ModelControls,
|
|
13045
13283
|
{
|
|
13046
13284
|
models,
|
|
@@ -13055,7 +13293,7 @@ function AgentChatPanel({
|
|
|
13055
13293
|
narrow
|
|
13056
13294
|
}
|
|
13057
13295
|
);
|
|
13058
|
-
const threadMenu = threads && threads.length ? /* @__PURE__ */ (0,
|
|
13296
|
+
const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
|
|
13059
13297
|
MenuButton,
|
|
13060
13298
|
{
|
|
13061
13299
|
variant: "ghost",
|
|
@@ -13082,7 +13320,7 @@ function AgentChatPanel({
|
|
|
13082
13320
|
})))
|
|
13083
13321
|
}
|
|
13084
13322
|
) : null;
|
|
13085
|
-
return /* @__PURE__ */ (0,
|
|
13323
|
+
return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)(
|
|
13086
13324
|
"aside",
|
|
13087
13325
|
{
|
|
13088
13326
|
className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
|
|
@@ -13093,7 +13331,7 @@ function AgentChatPanel({
|
|
|
13093
13331
|
},
|
|
13094
13332
|
"aria-label": title,
|
|
13095
13333
|
children: [
|
|
13096
|
-
surface === "sidebar" && resizable ? /* @__PURE__ */ (0,
|
|
13334
|
+
surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
|
|
13097
13335
|
"div",
|
|
13098
13336
|
{
|
|
13099
13337
|
className: "fdc-grip",
|
|
@@ -13108,20 +13346,20 @@ function AgentChatPanel({
|
|
|
13108
13346
|
}
|
|
13109
13347
|
}
|
|
13110
13348
|
) : null,
|
|
13111
|
-
showHeader ? /* @__PURE__ */ (0,
|
|
13112
|
-
/* @__PURE__ */ (0,
|
|
13113
|
-
/* @__PURE__ */ (0,
|
|
13114
|
-
/* @__PURE__ */ (0,
|
|
13115
|
-
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
|
|
13116
13354
|
] }),
|
|
13117
|
-
/* @__PURE__ */ (0,
|
|
13355
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fdc-head-acts", children: [
|
|
13118
13356
|
headerActions,
|
|
13119
13357
|
threadMenu,
|
|
13120
|
-
onNewThread ? /* @__PURE__ */ (0,
|
|
13121
|
-
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
|
|
13122
13360
|
] })
|
|
13123
13361
|
] }) : null,
|
|
13124
|
-
/* @__PURE__ */ (0,
|
|
13362
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
|
|
13125
13363
|
ChatTranscript,
|
|
13126
13364
|
{
|
|
13127
13365
|
messages: engine.visible,
|
|
@@ -13136,7 +13374,7 @@ function AgentChatPanel({
|
|
|
13136
13374
|
renderEmpty
|
|
13137
13375
|
}
|
|
13138
13376
|
),
|
|
13139
|
-
/* @__PURE__ */ (0,
|
|
13377
|
+
/* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
|
|
13140
13378
|
ChatComposer,
|
|
13141
13379
|
{
|
|
13142
13380
|
onSubmit: (text, atts) => engine.send(text, atts),
|
|
@@ -13169,8 +13407,8 @@ function AgentChatPanel({
|
|
|
13169
13407
|
}
|
|
13170
13408
|
|
|
13171
13409
|
// src/components/files/FileViewer.tsx
|
|
13172
|
-
var
|
|
13173
|
-
var
|
|
13410
|
+
var React65 = __toESM(require("react"), 1);
|
|
13411
|
+
var import_jsx_runtime97 = require("react/jsx-runtime");
|
|
13174
13412
|
function previewKindOf(file) {
|
|
13175
13413
|
const mime = (file.mime || "").toLowerCase();
|
|
13176
13414
|
const ext = extensionOf(file.name || "");
|
|
@@ -13226,13 +13464,13 @@ function parseDelimited(text, delimiter) {
|
|
|
13226
13464
|
return rows;
|
|
13227
13465
|
}
|
|
13228
13466
|
function usePreview(file, kind, resolveUrl) {
|
|
13229
|
-
const [state, setState] =
|
|
13230
|
-
const [attempt, setAttempt] =
|
|
13231
|
-
const resolveRef =
|
|
13232
|
-
|
|
13467
|
+
const [state, setState] = React65.useState({ status: "loading" });
|
|
13468
|
+
const [attempt, setAttempt] = React65.useState(0);
|
|
13469
|
+
const resolveRef = React65.useRef(resolveUrl);
|
|
13470
|
+
React65.useEffect(() => {
|
|
13233
13471
|
resolveRef.current = resolveUrl;
|
|
13234
13472
|
}, [resolveUrl]);
|
|
13235
|
-
|
|
13473
|
+
React65.useEffect(() => {
|
|
13236
13474
|
if (kind === "none") {
|
|
13237
13475
|
setState({ status: "ready" });
|
|
13238
13476
|
return;
|
|
@@ -13262,19 +13500,19 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
13262
13500
|
if (ac) ac.abort();
|
|
13263
13501
|
};
|
|
13264
13502
|
}, [file.id, kind, attempt]);
|
|
13265
|
-
return { ...state, retry:
|
|
13503
|
+
return { ...state, retry: React65.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
13266
13504
|
}
|
|
13267
13505
|
function PreviewBody({ file, kind, state }) {
|
|
13268
|
-
if (kind === "image") return /* @__PURE__ */ (0,
|
|
13269
|
-
if (kind === "pdf") return /* @__PURE__ */ (0,
|
|
13270
|
-
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 || "" });
|
|
13271
13509
|
if (kind === "json") {
|
|
13272
13510
|
let pretty = state.text || "";
|
|
13273
13511
|
try {
|
|
13274
13512
|
pretty = JSON.stringify(JSON.parse(pretty), null, 2);
|
|
13275
13513
|
} catch {
|
|
13276
13514
|
}
|
|
13277
|
-
return /* @__PURE__ */ (0,
|
|
13515
|
+
return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(CodeBlock, { code: pretty, language: "json" });
|
|
13278
13516
|
}
|
|
13279
13517
|
if (kind === "csv") {
|
|
13280
13518
|
const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
|
|
@@ -13282,12 +13520,12 @@ function PreviewBody({ file, kind, state }) {
|
|
|
13282
13520
|
const head = rows[0] || [];
|
|
13283
13521
|
const dataRows = rows.slice(1);
|
|
13284
13522
|
const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
|
|
13285
|
-
return /* @__PURE__ */ (0,
|
|
13286
|
-
/* @__PURE__ */ (0,
|
|
13287
|
-
/* @__PURE__ */ (0,
|
|
13288
|
-
/* @__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)) })
|
|
13289
13527
|
] }),
|
|
13290
|
-
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: [
|
|
13291
13529
|
"Showing the first ",
|
|
13292
13530
|
FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
|
|
13293
13531
|
" of ",
|
|
@@ -13296,24 +13534,24 @@ function PreviewBody({ file, kind, state }) {
|
|
|
13296
13534
|
] }) : null
|
|
13297
13535
|
] });
|
|
13298
13536
|
}
|
|
13299
|
-
if (kind === "text") return /* @__PURE__ */ (0,
|
|
13300
|
-
return /* @__PURE__ */ (0,
|
|
13301
|
-
/* @__PURE__ */ (0,
|
|
13302
|
-
/* @__PURE__ */ (0,
|
|
13303
|
-
/* @__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: [
|
|
13304
13542
|
file.mime || "Unknown type",
|
|
13305
13543
|
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
13306
13544
|
] })
|
|
13307
13545
|
] });
|
|
13308
13546
|
}
|
|
13309
13547
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
13310
|
-
const kind =
|
|
13548
|
+
const kind = React65.useMemo(() => previewKindOf(file), [file]);
|
|
13311
13549
|
const preview = usePreview(file, kind, resolveUrl);
|
|
13312
|
-
const [tab, setTab] =
|
|
13313
|
-
const [downloading, setDownloading] =
|
|
13314
|
-
const [downloadError, setDownloadError] =
|
|
13550
|
+
const [tab, setTab] = React65.useState("preview");
|
|
13551
|
+
const [downloading, setDownloading] = React65.useState(false);
|
|
13552
|
+
const [downloadError, setDownloadError] = React65.useState(null);
|
|
13315
13553
|
const hasSide = sidePanel != null;
|
|
13316
|
-
|
|
13554
|
+
React65.useEffect(() => {
|
|
13317
13555
|
setTab("preview");
|
|
13318
13556
|
}, [file.id]);
|
|
13319
13557
|
const download = () => {
|
|
@@ -13329,29 +13567,29 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13329
13567
|
a.remove();
|
|
13330
13568
|
}).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
|
|
13331
13569
|
};
|
|
13332
|
-
return /* @__PURE__ */ (0,
|
|
13570
|
+
return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(
|
|
13333
13571
|
"section",
|
|
13334
13572
|
{
|
|
13335
13573
|
className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
|
|
13336
13574
|
"aria-label": file.name || "File",
|
|
13337
13575
|
children: [
|
|
13338
|
-
/* @__PURE__ */ (0,
|
|
13339
|
-
/* @__PURE__ */ (0,
|
|
13340
|
-
/* @__PURE__ */ (0,
|
|
13341
|
-
/* @__PURE__ */ (0,
|
|
13342
|
-
/* @__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: [
|
|
13343
13581
|
file.mime || "Unknown type",
|
|
13344
13582
|
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
13345
13583
|
] })
|
|
13346
13584
|
] }),
|
|
13347
|
-
/* @__PURE__ */ (0,
|
|
13585
|
+
/* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fv-head-actions", children: [
|
|
13348
13586
|
actions,
|
|
13349
|
-
/* @__PURE__ */ (0,
|
|
13350
|
-
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
|
|
13351
13589
|
] })
|
|
13352
13590
|
] }),
|
|
13353
|
-
downloadError ? /* @__PURE__ */ (0,
|
|
13354
|
-
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)(
|
|
13355
13593
|
Tabs,
|
|
13356
13594
|
{
|
|
13357
13595
|
className: "fd-fv-tabs",
|
|
@@ -13360,19 +13598,19 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13360
13598
|
onChange: (v) => setTab(v)
|
|
13361
13599
|
}
|
|
13362
13600
|
) : null,
|
|
13363
|
-
/* @__PURE__ */ (0,
|
|
13364
|
-
/* @__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)(
|
|
13365
13603
|
LoadingRegion,
|
|
13366
13604
|
{
|
|
13367
13605
|
state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
|
|
13368
13606
|
error: preview.error,
|
|
13369
13607
|
label: "Loading preview of " + (file.name || "file"),
|
|
13370
13608
|
onRetry: preview.status === "error" ? preview.retry : void 0,
|
|
13371
|
-
skeleton: /* @__PURE__ */ (0,
|
|
13372
|
-
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 })
|
|
13373
13611
|
}
|
|
13374
13612
|
) }),
|
|
13375
|
-
hasSide ? /* @__PURE__ */ (0,
|
|
13613
|
+
hasSide ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
|
|
13376
13614
|
] })
|
|
13377
13615
|
]
|
|
13378
13616
|
}
|
|
@@ -13380,8 +13618,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13380
13618
|
}
|
|
13381
13619
|
|
|
13382
13620
|
// src/components/files/FileBrowser.tsx
|
|
13383
|
-
var
|
|
13384
|
-
var
|
|
13621
|
+
var React66 = __toESM(require("react"), 1);
|
|
13622
|
+
var import_jsx_runtime98 = require("react/jsx-runtime");
|
|
13385
13623
|
function childrenOf(folders, parentId) {
|
|
13386
13624
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
13387
13625
|
}
|
|
@@ -13453,8 +13691,8 @@ function FolderPickerMenu({
|
|
|
13453
13691
|
}) {
|
|
13454
13692
|
const panel = useInlinePanel();
|
|
13455
13693
|
const { open: open2, setOpen, ref, zIndex } = panel;
|
|
13456
|
-
return /* @__PURE__ */ (0,
|
|
13457
|
-
/* @__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)(
|
|
13458
13696
|
IconButton,
|
|
13459
13697
|
{
|
|
13460
13698
|
icon: "arrows-out-cardinal",
|
|
@@ -13466,9 +13704,9 @@ function FolderPickerMenu({
|
|
|
13466
13704
|
onClick: () => setOpen((v) => !v)
|
|
13467
13705
|
}
|
|
13468
13706
|
),
|
|
13469
|
-
open2 ? /* @__PURE__ */ (0,
|
|
13470
|
-
/* @__PURE__ */ (0,
|
|
13471
|
-
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)(
|
|
13472
13710
|
"button",
|
|
13473
13711
|
{
|
|
13474
13712
|
type: "button",
|
|
@@ -13480,7 +13718,7 @@ function FolderPickerMenu({
|
|
|
13480
13718
|
setOpen(false);
|
|
13481
13719
|
},
|
|
13482
13720
|
children: [
|
|
13483
|
-
/* @__PURE__ */ (0,
|
|
13721
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
|
|
13484
13722
|
d.name
|
|
13485
13723
|
]
|
|
13486
13724
|
},
|
|
@@ -13490,8 +13728,8 @@ function FolderPickerMenu({
|
|
|
13490
13728
|
] });
|
|
13491
13729
|
}
|
|
13492
13730
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
13493
|
-
const [over, setOver] =
|
|
13494
|
-
const dragCounter =
|
|
13731
|
+
const [over, setOver] = React66.useState(false);
|
|
13732
|
+
const dragCounter = React66.useRef(0);
|
|
13495
13733
|
const dropHandlers = isDropTarget ? {
|
|
13496
13734
|
onDragEnter: (e) => {
|
|
13497
13735
|
if (!hasInternalPayload(e)) return;
|
|
@@ -13516,8 +13754,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
13516
13754
|
if (payload && onDropPayload) onDropPayload(payload);
|
|
13517
13755
|
}
|
|
13518
13756
|
} : {};
|
|
13519
|
-
return /* @__PURE__ */ (0,
|
|
13520
|
-
/* @__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)(
|
|
13521
13759
|
"button",
|
|
13522
13760
|
{
|
|
13523
13761
|
type: "button",
|
|
@@ -13526,26 +13764,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
13526
13764
|
draggable: !!draggableId,
|
|
13527
13765
|
onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
|
|
13528
13766
|
children: [
|
|
13529
|
-
/* @__PURE__ */ (0,
|
|
13530
|
-
/* @__PURE__ */ (0,
|
|
13531
|
-
/* @__PURE__ */ (0,
|
|
13532
|
-
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
|
|
13533
13771
|
] })
|
|
13534
13772
|
]
|
|
13535
13773
|
}
|
|
13536
13774
|
),
|
|
13537
|
-
actions ? /* @__PURE__ */ (0,
|
|
13775
|
+
actions ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-fb-row-actions", children: actions }) : null
|
|
13538
13776
|
] });
|
|
13539
13777
|
}
|
|
13540
13778
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
13541
13779
|
const kids = childrenOf(folders, folder.id);
|
|
13542
|
-
const [expanded, setExpanded] =
|
|
13543
|
-
|
|
13780
|
+
const [expanded, setExpanded] = React66.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
13781
|
+
React66.useEffect(() => {
|
|
13544
13782
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
13545
13783
|
}, [currentFolderId, folder.id, folders]);
|
|
13546
13784
|
const isCurrent = folder.id === currentFolderId;
|
|
13547
|
-
return /* @__PURE__ */ (0,
|
|
13548
|
-
/* @__PURE__ */ (0,
|
|
13785
|
+
return /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-tree-node", children: [
|
|
13786
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13549
13787
|
RowShell,
|
|
13550
13788
|
{
|
|
13551
13789
|
icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
|
|
@@ -13555,7 +13793,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
|
|
|
13555
13793
|
isDropTarget: canMove,
|
|
13556
13794
|
onDropPayload: (payload) => onMoveInto(payload, folder.id),
|
|
13557
13795
|
className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
|
|
13558
|
-
actions: kids.length ? /* @__PURE__ */ (0,
|
|
13796
|
+
actions: kids.length ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13559
13797
|
IconButton,
|
|
13560
13798
|
{
|
|
13561
13799
|
icon: expanded ? "caret-down" : "caret-right",
|
|
@@ -13567,7 +13805,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
|
|
|
13567
13805
|
) : void 0
|
|
13568
13806
|
}
|
|
13569
13807
|
),
|
|
13570
|
-
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)(
|
|
13571
13809
|
TreeNode,
|
|
13572
13810
|
{
|
|
13573
13811
|
folder: k,
|
|
@@ -13606,15 +13844,15 @@ function FileBrowser({
|
|
|
13606
13844
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
13607
13845
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
13608
13846
|
const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
|
|
13609
|
-
const [createOpen, setCreateOpen] =
|
|
13610
|
-
const [createName, setCreateName] =
|
|
13611
|
-
const [renameTarget, setRenameTarget] =
|
|
13612
|
-
const [renameValue, setRenameValue] =
|
|
13613
|
-
const [deleteTarget, setDeleteTarget] =
|
|
13614
|
-
const uploadInputRef =
|
|
13615
|
-
const crumbFolders =
|
|
13616
|
-
const subfolders =
|
|
13617
|
-
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(
|
|
13618
13856
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
13619
13857
|
[files, currentFolderId]
|
|
13620
13858
|
);
|
|
@@ -13653,10 +13891,10 @@ function FileBrowser({
|
|
|
13653
13891
|
if (deleteTarget && onDeleteFolder) onDeleteFolder(deleteTarget);
|
|
13654
13892
|
setDeleteTarget(null);
|
|
13655
13893
|
};
|
|
13656
|
-
const content = /* @__PURE__ */ (0,
|
|
13657
|
-
/* @__PURE__ */ (0,
|
|
13658
|
-
/* @__PURE__ */ (0,
|
|
13659
|
-
/* @__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)(
|
|
13660
13898
|
BreadcrumbCrumb,
|
|
13661
13899
|
{
|
|
13662
13900
|
label: "Home",
|
|
@@ -13666,7 +13904,7 @@ function FileBrowser({
|
|
|
13666
13904
|
onDropPayload: (p) => moveIntoFolder(p, null)
|
|
13667
13905
|
}
|
|
13668
13906
|
),
|
|
13669
|
-
crumbFolders.map((f, i) => /* @__PURE__ */ (0,
|
|
13907
|
+
crumbFolders.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13670
13908
|
BreadcrumbCrumb,
|
|
13671
13909
|
{
|
|
13672
13910
|
label: f.name,
|
|
@@ -13678,11 +13916,11 @@ function FileBrowser({
|
|
|
13678
13916
|
f.id
|
|
13679
13917
|
))
|
|
13680
13918
|
] }),
|
|
13681
|
-
/* @__PURE__ */ (0,
|
|
13682
|
-
canCreateFolder ? /* @__PURE__ */ (0,
|
|
13683
|
-
canUpload ? /* @__PURE__ */ (0,
|
|
13684
|
-
/* @__PURE__ */ (0,
|
|
13685
|
-
/* @__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)(
|
|
13686
13924
|
"input",
|
|
13687
13925
|
{
|
|
13688
13926
|
ref: uploadInputRef,
|
|
@@ -13700,9 +13938,9 @@ function FileBrowser({
|
|
|
13700
13938
|
] }) : null
|
|
13701
13939
|
] })
|
|
13702
13940
|
] }),
|
|
13703
|
-
/* @__PURE__ */ (0,
|
|
13704
|
-
/* @__PURE__ */ (0,
|
|
13705
|
-
/* @__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)(
|
|
13706
13944
|
RowShell,
|
|
13707
13945
|
{
|
|
13708
13946
|
icon: "house-simple",
|
|
@@ -13713,7 +13951,7 @@ function FileBrowser({
|
|
|
13713
13951
|
className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
|
|
13714
13952
|
}
|
|
13715
13953
|
),
|
|
13716
|
-
childrenOf(folders, null).map((f) => /* @__PURE__ */ (0,
|
|
13954
|
+
childrenOf(folders, null).map((f) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13717
13955
|
TreeNode,
|
|
13718
13956
|
{
|
|
13719
13957
|
folder: f,
|
|
@@ -13727,18 +13965,18 @@ function FileBrowser({
|
|
|
13727
13965
|
f.id
|
|
13728
13966
|
))
|
|
13729
13967
|
] }),
|
|
13730
|
-
/* @__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)(
|
|
13731
13969
|
LoadingRegion,
|
|
13732
13970
|
{
|
|
13733
13971
|
state: loading ? "loading" : "ready",
|
|
13734
13972
|
label: "Loading folder contents",
|
|
13735
|
-
skeleton: /* @__PURE__ */ (0,
|
|
13736
|
-
/* @__PURE__ */ (0,
|
|
13737
|
-
/* @__PURE__ */ (0,
|
|
13738
|
-
/* @__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" })
|
|
13739
13977
|
] }),
|
|
13740
|
-
children: isEmpty ? /* @__PURE__ */ (0,
|
|
13741
|
-
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)(
|
|
13742
13980
|
RowShell,
|
|
13743
13981
|
{
|
|
13744
13982
|
icon: "folder-simple",
|
|
@@ -13747,9 +13985,9 @@ function FileBrowser({
|
|
|
13747
13985
|
draggableId: canMove ? { kind: "folder", id: f.id } : void 0,
|
|
13748
13986
|
isDropTarget: canMove,
|
|
13749
13987
|
onDropPayload: (p) => moveIntoFolder(p, f.id),
|
|
13750
|
-
actions: /* @__PURE__ */ (0,
|
|
13751
|
-
canRenameFolder ? /* @__PURE__ */ (0,
|
|
13752
|
-
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)(
|
|
13753
13991
|
FolderPickerMenu,
|
|
13754
13992
|
{
|
|
13755
13993
|
label: "Move " + f.name,
|
|
@@ -13757,12 +13995,12 @@ function FileBrowser({
|
|
|
13757
13995
|
onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
|
|
13758
13996
|
}
|
|
13759
13997
|
) : null,
|
|
13760
|
-
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
|
|
13761
13999
|
] })
|
|
13762
14000
|
},
|
|
13763
14001
|
f.id
|
|
13764
14002
|
)),
|
|
13765
|
-
currentFiles.map((file) => /* @__PURE__ */ (0,
|
|
14003
|
+
currentFiles.map((file) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13766
14004
|
RowShell,
|
|
13767
14005
|
{
|
|
13768
14006
|
icon: iconForMime(file.mime, file.name),
|
|
@@ -13770,8 +14008,8 @@ function FileBrowser({
|
|
|
13770
14008
|
meta: file.size ? formatBytes(file.size) : void 0,
|
|
13771
14009
|
onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
|
|
13772
14010
|
draggableId: canMove ? { kind: "file", id: file.id } : void 0,
|
|
13773
|
-
actions: /* @__PURE__ */ (0,
|
|
13774
|
-
canMove ? /* @__PURE__ */ (0,
|
|
14011
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
|
|
14012
|
+
canMove ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13775
14013
|
FolderPickerMenu,
|
|
13776
14014
|
{
|
|
13777
14015
|
label: "Move " + file.name,
|
|
@@ -13779,7 +14017,7 @@ function FileBrowser({
|
|
|
13779
14017
|
onPick: (target) => onMoveFile && onMoveFile(file.id, target)
|
|
13780
14018
|
}
|
|
13781
14019
|
) : null,
|
|
13782
|
-
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
|
|
13783
14021
|
] })
|
|
13784
14022
|
},
|
|
13785
14023
|
file.id
|
|
@@ -13788,10 +14026,10 @@ function FileBrowser({
|
|
|
13788
14026
|
}
|
|
13789
14027
|
) })
|
|
13790
14028
|
] }),
|
|
13791
|
-
/* @__PURE__ */ (0,
|
|
13792
|
-
/* @__PURE__ */ (0,
|
|
13793
|
-
/* @__PURE__ */ (0,
|
|
13794
|
-
] }), 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)(
|
|
13795
14033
|
"input",
|
|
13796
14034
|
{
|
|
13797
14035
|
className: "fd-fb-input",
|
|
@@ -13805,10 +14043,10 @@ function FileBrowser({
|
|
|
13805
14043
|
autoFocus: true
|
|
13806
14044
|
}
|
|
13807
14045
|
) }),
|
|
13808
|
-
/* @__PURE__ */ (0,
|
|
13809
|
-
/* @__PURE__ */ (0,
|
|
13810
|
-
/* @__PURE__ */ (0,
|
|
13811
|
-
] }), 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)(
|
|
13812
14050
|
"input",
|
|
13813
14051
|
{
|
|
13814
14052
|
className: "fd-fb-input",
|
|
@@ -13822,22 +14060,22 @@ function FileBrowser({
|
|
|
13822
14060
|
autoFocus: true
|
|
13823
14061
|
}
|
|
13824
14062
|
) }),
|
|
13825
|
-
/* @__PURE__ */ (0,
|
|
14063
|
+
/* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
|
|
13826
14064
|
Modal,
|
|
13827
14065
|
{
|
|
13828
14066
|
open: deleteTarget != null,
|
|
13829
14067
|
title: deleteTarget ? "Delete \u201C" + deleteTarget.name + "\u201D?" : "Delete folder?",
|
|
13830
14068
|
description: "This can't be undone. The folder must be empty.",
|
|
13831
14069
|
onClose: () => setDeleteTarget(null),
|
|
13832
|
-
footer: /* @__PURE__ */ (0,
|
|
13833
|
-
/* @__PURE__ */ (0,
|
|
13834
|
-
/* @__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" })
|
|
13835
14073
|
] })
|
|
13836
14074
|
}
|
|
13837
14075
|
)
|
|
13838
14076
|
] });
|
|
13839
14077
|
if (!canUpload) return content;
|
|
13840
|
-
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 });
|
|
13841
14079
|
}
|
|
13842
14080
|
function BreadcrumbCrumb({
|
|
13843
14081
|
label,
|
|
@@ -13846,8 +14084,8 @@ function BreadcrumbCrumb({
|
|
|
13846
14084
|
isDropTarget,
|
|
13847
14085
|
onDropPayload
|
|
13848
14086
|
}) {
|
|
13849
|
-
const [over, setOver] =
|
|
13850
|
-
const dragCounter =
|
|
14087
|
+
const [over, setOver] = React66.useState(false);
|
|
14088
|
+
const dragCounter = React66.useRef(0);
|
|
13851
14089
|
const dropHandlers = isDropTarget ? {
|
|
13852
14090
|
onDragEnter: (e) => {
|
|
13853
14091
|
if (!hasInternalPayload(e)) return;
|
|
@@ -13872,11 +14110,11 @@ function BreadcrumbCrumb({
|
|
|
13872
14110
|
if (payload && onDropPayload) onDropPayload(payload);
|
|
13873
14111
|
}
|
|
13874
14112
|
} : {};
|
|
13875
|
-
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 }) });
|
|
13876
14114
|
}
|
|
13877
14115
|
|
|
13878
14116
|
// src/kits/query.ts
|
|
13879
|
-
var
|
|
14117
|
+
var React67 = __toESM(require("react"), 1);
|
|
13880
14118
|
var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
|
|
13881
14119
|
var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
|
|
13882
14120
|
var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
|
|
@@ -13931,22 +14169,22 @@ function compare(a, b, dir) {
|
|
|
13931
14169
|
var API = null;
|
|
13932
14170
|
var PREFS = null;
|
|
13933
14171
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
13934
|
-
const [query, setQuery] =
|
|
14172
|
+
const [query, setQuery] = React67.useState(() => {
|
|
13935
14173
|
const store = PREFS || window.PlannerPrefs;
|
|
13936
14174
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
13937
14175
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
13938
14176
|
});
|
|
13939
|
-
const savePref =
|
|
14177
|
+
const savePref = React67.useCallback((patch2) => {
|
|
13940
14178
|
const store = PREFS || window.PlannerPrefs;
|
|
13941
14179
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
13942
14180
|
}, [prefsKey]);
|
|
13943
|
-
const [res, setRes] =
|
|
13944
|
-
const [loading, setLoading] =
|
|
13945
|
-
const seq2 =
|
|
14181
|
+
const [res, setRes] = React67.useState(null);
|
|
14182
|
+
const [loading, setLoading] = React67.useState(true);
|
|
14183
|
+
const seq2 = React67.useRef(0);
|
|
13946
14184
|
const depKey = (deps || []).join("|");
|
|
13947
14185
|
const paramKey = JSON.stringify(params || {});
|
|
13948
14186
|
const queryKey = JSON.stringify(query);
|
|
13949
|
-
|
|
14187
|
+
React67.useEffect(() => {
|
|
13950
14188
|
const id = ++seq2.current;
|
|
13951
14189
|
setLoading(true);
|
|
13952
14190
|
const t = setTimeout(() => {
|
|
@@ -14265,12 +14503,12 @@ function createVersionStore(initialState, options) {
|
|
|
14265
14503
|
}
|
|
14266
14504
|
|
|
14267
14505
|
// src/kits/documentTitle.ts
|
|
14268
|
-
var
|
|
14506
|
+
var React68 = __toESM(require("react"), 1);
|
|
14269
14507
|
function formatDocumentTitle(routeTitle, appName) {
|
|
14270
14508
|
return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
|
|
14271
14509
|
}
|
|
14272
14510
|
function useDocumentTitle(routeTitle, appName) {
|
|
14273
|
-
|
|
14511
|
+
React68.useEffect(() => {
|
|
14274
14512
|
if (typeof document === "undefined") return;
|
|
14275
14513
|
document.title = formatDocumentTitle(routeTitle, appName);
|
|
14276
14514
|
}, [routeTitle, appName]);
|
|
@@ -14313,6 +14551,7 @@ function useDocumentTitle(routeTitle, appName) {
|
|
|
14313
14551
|
Clamp,
|
|
14314
14552
|
ClockFace,
|
|
14315
14553
|
CodeBlock,
|
|
14554
|
+
CodeEditor,
|
|
14316
14555
|
Collapsible,
|
|
14317
14556
|
ComingSoon,
|
|
14318
14557
|
CsiBadge,
|