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