@flytedan/flytebot-design-system 0.58.0 → 0.59.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 +899 -876
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +60 -21
- package/dist/index.d.ts +60 -21
- package/dist/index.js +665 -646
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8059,7 +8059,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
8059
8059
|
}
|
|
8060
8060
|
|
|
8061
8061
|
// src/components/platform/AppearanceMenu.tsx
|
|
8062
|
-
import * as
|
|
8062
|
+
import * as React53 from "react";
|
|
8063
8063
|
|
|
8064
8064
|
// src/kits/appearance.ts
|
|
8065
8065
|
import * as React51 from "react";
|
|
@@ -8156,20 +8156,25 @@ function applyPrefs(prefs, root = document.documentElement) {
|
|
|
8156
8156
|
if (prefs.reduceMotion) root.setAttribute("data-motion", "reduce");
|
|
8157
8157
|
else root.removeAttribute("data-motion");
|
|
8158
8158
|
}
|
|
8159
|
+
function applyAppearance(store, root = document.documentElement) {
|
|
8160
|
+
applyPrefs(store.getSnapshot(), root);
|
|
8161
|
+
}
|
|
8162
|
+
function watchAppearance(store, root = document.documentElement) {
|
|
8163
|
+
const apply = () => applyAppearance(store, root);
|
|
8164
|
+
apply();
|
|
8165
|
+
const unsubscribe = store.subscribe(apply);
|
|
8166
|
+
const mq = typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia("(prefers-color-scheme: dark)") : null;
|
|
8167
|
+
const onSchemeChange = () => {
|
|
8168
|
+
if (store.getSnapshot().theme === "system") apply();
|
|
8169
|
+
};
|
|
8170
|
+
mq?.addEventListener("change", onSchemeChange);
|
|
8171
|
+
return () => {
|
|
8172
|
+
unsubscribe();
|
|
8173
|
+
mq?.removeEventListener("change", onSchemeChange);
|
|
8174
|
+
};
|
|
8175
|
+
}
|
|
8159
8176
|
function useAppearancePrefs(store) {
|
|
8160
8177
|
const prefs = React51.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
8161
|
-
React51.useEffect(() => {
|
|
8162
|
-
applyPrefs(prefs);
|
|
8163
|
-
}, [prefs]);
|
|
8164
|
-
React51.useEffect(() => {
|
|
8165
|
-
if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
8166
|
-
return;
|
|
8167
|
-
}
|
|
8168
|
-
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
8169
|
-
const onChange = () => applyPrefs(prefs);
|
|
8170
|
-
mq.addEventListener("change", onChange);
|
|
8171
|
-
return () => mq.removeEventListener("change", onChange);
|
|
8172
|
-
}, [prefs]);
|
|
8173
8178
|
const update = React51.useCallback(
|
|
8174
8179
|
(patch) => {
|
|
8175
8180
|
store.write({ ...store.getSnapshot(), ...patch });
|
|
@@ -8179,8 +8184,22 @@ function useAppearancePrefs(store) {
|
|
|
8179
8184
|
return [prefs, update];
|
|
8180
8185
|
}
|
|
8181
8186
|
|
|
8187
|
+
// src/components/platform/AppearanceProvider.tsx
|
|
8188
|
+
import * as React52 from "react";
|
|
8189
|
+
import { jsx as jsx77 } from "react/jsx-runtime";
|
|
8190
|
+
var AppearanceStoreContext = React52.createContext(null);
|
|
8191
|
+
function AppearanceProvider({ store, children }) {
|
|
8192
|
+
React52.useLayoutEffect(() => watchAppearance(store), [store]);
|
|
8193
|
+
return /* @__PURE__ */ jsx77(AppearanceStoreContext.Provider, { value: store, children });
|
|
8194
|
+
}
|
|
8195
|
+
function useAppearanceStore() {
|
|
8196
|
+
const store = React52.useContext(AppearanceStoreContext);
|
|
8197
|
+
if (!store) throw new Error("AppearanceMenu and useAppearanceStore must be rendered inside an <AppearanceProvider>.");
|
|
8198
|
+
return store;
|
|
8199
|
+
}
|
|
8200
|
+
|
|
8182
8201
|
// src/components/platform/AppearanceMenu.tsx
|
|
8183
|
-
import { jsx as
|
|
8202
|
+
import { jsx as jsx78, jsxs as jsxs68 } from "react/jsx-runtime";
|
|
8184
8203
|
var THEME_OPTIONS = [
|
|
8185
8204
|
{ value: "light", label: "Light" },
|
|
8186
8205
|
{ value: "dark", label: "Dark" },
|
|
@@ -8192,17 +8211,13 @@ var TEXT_SCALE_OPTIONS = [
|
|
|
8192
8211
|
{ value: "lg", label: "L" },
|
|
8193
8212
|
{ value: "xl", label: "XL" }
|
|
8194
8213
|
];
|
|
8195
|
-
function AppearanceMenu({ className = ""
|
|
8196
|
-
const
|
|
8197
|
-
|
|
8198
|
-
|
|
8199
|
-
);
|
|
8200
|
-
const [prefs, update] = useAppearancePrefs(store);
|
|
8201
|
-
const [open2, setOpen] = React52.useState(false);
|
|
8202
|
-
const anchorRef = React52.useRef(null);
|
|
8214
|
+
function AppearanceMenu({ className = "" }) {
|
|
8215
|
+
const [prefs, update] = useAppearancePrefs(useAppearanceStore());
|
|
8216
|
+
const [open2, setOpen] = React53.useState(false);
|
|
8217
|
+
const anchorRef = React53.useRef(null);
|
|
8203
8218
|
const patch = (p) => update(p);
|
|
8204
|
-
return /* @__PURE__ */ jsxs68(
|
|
8205
|
-
/* @__PURE__ */
|
|
8219
|
+
return /* @__PURE__ */ jsxs68(React53.Fragment, { children: [
|
|
8220
|
+
/* @__PURE__ */ jsx78("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx78(
|
|
8206
8221
|
IconButton,
|
|
8207
8222
|
{
|
|
8208
8223
|
icon: "circle-half",
|
|
@@ -8210,7 +8225,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
8210
8225
|
onClick: () => setOpen((v) => !v)
|
|
8211
8226
|
}
|
|
8212
8227
|
) }),
|
|
8213
|
-
/* @__PURE__ */
|
|
8228
|
+
/* @__PURE__ */ jsx78(
|
|
8214
8229
|
Popover,
|
|
8215
8230
|
{
|
|
8216
8231
|
open: open2,
|
|
@@ -8222,8 +8237,8 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
8222
8237
|
label: "Appearance settings",
|
|
8223
8238
|
children: /* @__PURE__ */ jsxs68("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
|
|
8224
8239
|
/* @__PURE__ */ jsxs68("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
8225
|
-
/* @__PURE__ */
|
|
8226
|
-
/* @__PURE__ */
|
|
8240
|
+
/* @__PURE__ */ jsx78("span", { className: "fd-field-label", children: "Theme" }),
|
|
8241
|
+
/* @__PURE__ */ jsx78(
|
|
8227
8242
|
SegmentedControl,
|
|
8228
8243
|
{
|
|
8229
8244
|
options: THEME_OPTIONS,
|
|
@@ -8234,8 +8249,8 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
8234
8249
|
)
|
|
8235
8250
|
] }),
|
|
8236
8251
|
/* @__PURE__ */ jsxs68("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
8237
|
-
/* @__PURE__ */
|
|
8238
|
-
/* @__PURE__ */
|
|
8252
|
+
/* @__PURE__ */ jsx78("span", { className: "fd-field-label", children: "Text size" }),
|
|
8253
|
+
/* @__PURE__ */ jsx78(
|
|
8239
8254
|
SegmentedControl,
|
|
8240
8255
|
{
|
|
8241
8256
|
options: TEXT_SCALE_OPTIONS,
|
|
@@ -8245,7 +8260,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
8245
8260
|
}
|
|
8246
8261
|
)
|
|
8247
8262
|
] }),
|
|
8248
|
-
/* @__PURE__ */
|
|
8263
|
+
/* @__PURE__ */ jsx78(
|
|
8249
8264
|
Switch,
|
|
8250
8265
|
{
|
|
8251
8266
|
label: "High contrast",
|
|
@@ -8254,7 +8269,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
8254
8269
|
onChange: (e) => patch({ highContrast: e.target.checked })
|
|
8255
8270
|
}
|
|
8256
8271
|
),
|
|
8257
|
-
/* @__PURE__ */
|
|
8272
|
+
/* @__PURE__ */ jsx78(
|
|
8258
8273
|
Switch,
|
|
8259
8274
|
{
|
|
8260
8275
|
label: "Reduce motion",
|
|
@@ -8270,14 +8285,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
8270
8285
|
}
|
|
8271
8286
|
|
|
8272
8287
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
8273
|
-
import * as
|
|
8274
|
-
import { jsx as
|
|
8288
|
+
import * as React54 from "react";
|
|
8289
|
+
import { jsx as jsx79, jsxs as jsxs69 } from "react/jsx-runtime";
|
|
8275
8290
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
8276
8291
|
function Json({ obj }) {
|
|
8277
|
-
return /* @__PURE__ */
|
|
8292
|
+
return /* @__PURE__ */ jsx79("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
8278
8293
|
}
|
|
8279
8294
|
function Endpoint({ s, onRequest }) {
|
|
8280
|
-
const [tried, setTried] =
|
|
8295
|
+
const [tried, setTried] = React54.useState(null);
|
|
8281
8296
|
const run = async () => {
|
|
8282
8297
|
setTried("busy");
|
|
8283
8298
|
const t0 = (window.performance || Date).now();
|
|
@@ -8288,50 +8303,50 @@ function Endpoint({ s, onRequest }) {
|
|
|
8288
8303
|
setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
|
|
8289
8304
|
}
|
|
8290
8305
|
};
|
|
8291
|
-
return /* @__PURE__ */
|
|
8306
|
+
return /* @__PURE__ */ jsx79(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
8292
8307
|
/* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
|
|
8293
|
-
/* @__PURE__ */
|
|
8294
|
-
/* @__PURE__ */
|
|
8295
|
-
s.isList ? /* @__PURE__ */
|
|
8296
|
-
/* @__PURE__ */
|
|
8308
|
+
/* @__PURE__ */ jsx79(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
|
|
8309
|
+
/* @__PURE__ */ jsx79("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
|
|
8310
|
+
s.isList ? /* @__PURE__ */ jsx79(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
|
|
8311
|
+
/* @__PURE__ */ jsx79("span", { style: { flex: 1 } }),
|
|
8297
8312
|
/* @__PURE__ */ jsxs69("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
8298
8313
|
s.latency[0],
|
|
8299
8314
|
"\u2013",
|
|
8300
8315
|
s.latency[1],
|
|
8301
8316
|
"ms"
|
|
8302
8317
|
] }),
|
|
8303
|
-
/* @__PURE__ */
|
|
8318
|
+
/* @__PURE__ */ jsx79(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
|
|
8304
8319
|
] }),
|
|
8305
8320
|
/* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
|
|
8306
8321
|
/* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8307
|
-
/* @__PURE__ */
|
|
8308
|
-
/* @__PURE__ */
|
|
8309
|
-
s.usedBy && s.usedBy.length ? /* @__PURE__ */
|
|
8322
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
|
|
8323
|
+
/* @__PURE__ */ jsx79("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
|
|
8324
|
+
s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx79("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx79(Tag, { children: u }, u)) }) : null
|
|
8310
8325
|
] }),
|
|
8311
8326
|
/* @__PURE__ */ jsxs69("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
|
|
8312
8327
|
s.request ? /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8313
|
-
/* @__PURE__ */
|
|
8314
|
-
/* @__PURE__ */
|
|
8328
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Request body" }),
|
|
8329
|
+
/* @__PURE__ */ jsx79(Json, { obj: s.request })
|
|
8315
8330
|
] }) : null,
|
|
8316
8331
|
s.query ? /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8317
|
-
/* @__PURE__ */
|
|
8318
|
-
/* @__PURE__ */
|
|
8332
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Query" }),
|
|
8333
|
+
/* @__PURE__ */ jsx79(Json, { obj: s.query })
|
|
8319
8334
|
] }) : null,
|
|
8320
8335
|
/* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8321
|
-
/* @__PURE__ */
|
|
8322
|
-
/* @__PURE__ */
|
|
8336
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Response 200" }),
|
|
8337
|
+
/* @__PURE__ */ jsx79(Json, { obj: s.response })
|
|
8323
8338
|
] })
|
|
8324
8339
|
] }),
|
|
8325
|
-
s.notes ? /* @__PURE__ */
|
|
8340
|
+
s.notes ? /* @__PURE__ */ jsx79(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
|
|
8326
8341
|
tried && tried !== "busy" ? /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
8327
8342
|
/* @__PURE__ */ jsxs69("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
8328
|
-
/* @__PURE__ */
|
|
8343
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
|
|
8329
8344
|
/* @__PURE__ */ jsxs69(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
|
|
8330
8345
|
tried.ms,
|
|
8331
8346
|
"ms"
|
|
8332
8347
|
] })
|
|
8333
8348
|
] }),
|
|
8334
|
-
/* @__PURE__ */
|
|
8349
|
+
/* @__PURE__ */ jsx79(Json, { obj: tried.error ? { error: tried.error } : tried.data })
|
|
8335
8350
|
] }) : null
|
|
8336
8351
|
] })
|
|
8337
8352
|
] }) });
|
|
@@ -8350,10 +8365,10 @@ function ApiSpecBrowser({
|
|
|
8350
8365
|
className = "",
|
|
8351
8366
|
...rest
|
|
8352
8367
|
}) {
|
|
8353
|
-
const [q, setQ] =
|
|
8354
|
-
const [method, setMethod] =
|
|
8355
|
-
const [mod, setMod] =
|
|
8356
|
-
const [listOnly, setListOnly] =
|
|
8368
|
+
const [q, setQ] = React54.useState("");
|
|
8369
|
+
const [method, setMethod] = React54.useState(null);
|
|
8370
|
+
const [mod, setMod] = React54.useState(null);
|
|
8371
|
+
const [listOnly, setListOnly] = React54.useState(false);
|
|
8357
8372
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
8358
8373
|
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())));
|
|
8359
8374
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
@@ -8361,46 +8376,46 @@ function ApiSpecBrowser({
|
|
|
8361
8376
|
const listCount = spec.filter((s) => s.isList).length;
|
|
8362
8377
|
return /* @__PURE__ */ jsxs69("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
|
|
8363
8378
|
/* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
8364
|
-
kicker ? /* @__PURE__ */
|
|
8365
|
-
/* @__PURE__ */
|
|
8366
|
-
lede ? /* @__PURE__ */
|
|
8379
|
+
kicker ? /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: kicker }) : null,
|
|
8380
|
+
/* @__PURE__ */ jsx79("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
8381
|
+
lede ? /* @__PURE__ */ jsx79("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
|
|
8367
8382
|
] }),
|
|
8368
8383
|
modules && modules.length ? /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
8369
|
-
/* @__PURE__ */
|
|
8384
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
|
|
8370
8385
|
/* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
8371
8386
|
/* @__PURE__ */ jsxs69(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
|
|
8372
8387
|
"All screens ",
|
|
8373
|
-
/* @__PURE__ */
|
|
8388
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-mono", children: spec.length })
|
|
8374
8389
|
] }),
|
|
8375
8390
|
modules.map((m) => /* @__PURE__ */ jsxs69(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
|
|
8376
8391
|
m.label,
|
|
8377
8392
|
" ",
|
|
8378
|
-
/* @__PURE__ */
|
|
8393
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-mono", children: m.endpoints.length })
|
|
8379
8394
|
] }, m.id))
|
|
8380
8395
|
] }),
|
|
8381
|
-
activeModule ? /* @__PURE__ */
|
|
8396
|
+
activeModule ? /* @__PURE__ */ jsx79(
|
|
8382
8397
|
Flag,
|
|
8383
8398
|
{
|
|
8384
8399
|
tone: "info",
|
|
8385
8400
|
statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
|
|
8386
8401
|
cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
|
|
8387
|
-
actions: /* @__PURE__ */
|
|
8402
|
+
actions: /* @__PURE__ */ jsx79(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
|
|
8388
8403
|
}
|
|
8389
8404
|
) : null
|
|
8390
8405
|
] }) : null,
|
|
8391
|
-
sourceNote ? /* @__PURE__ */
|
|
8406
|
+
sourceNote ? /* @__PURE__ */ jsx79(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
|
|
8392
8407
|
/* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
8393
|
-
/* @__PURE__ */
|
|
8408
|
+
/* @__PURE__ */ jsx79(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
|
|
8394
8409
|
methods.map((m) => /* @__PURE__ */ jsxs69(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
|
|
8395
8410
|
m,
|
|
8396
8411
|
" ",
|
|
8397
|
-
/* @__PURE__ */
|
|
8412
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
|
|
8398
8413
|
] }, m)),
|
|
8399
8414
|
listCount ? /* @__PURE__ */ jsxs69(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
|
|
8400
8415
|
"Paged lists ",
|
|
8401
|
-
/* @__PURE__ */
|
|
8416
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-mono", children: listCount })
|
|
8402
8417
|
] }) : null,
|
|
8403
|
-
/* @__PURE__ */
|
|
8418
|
+
/* @__PURE__ */ jsx79("span", { style: { flex: 1 } }),
|
|
8404
8419
|
/* @__PURE__ */ jsxs69("span", { className: "fd-body-sm fd-muted", children: [
|
|
8405
8420
|
hits.length,
|
|
8406
8421
|
" of ",
|
|
@@ -8409,31 +8424,31 @@ function ApiSpecBrowser({
|
|
|
8409
8424
|
listCount ? " \xB7 " + listCount + " paged" : ""
|
|
8410
8425
|
] })
|
|
8411
8426
|
] }),
|
|
8412
|
-
hits.length === 0 ? /* @__PURE__ */
|
|
8427
|
+
hits.length === 0 ? /* @__PURE__ */ jsx79(Card, { elevation: "flat", children: /* @__PURE__ */ jsx79("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
|
|
8413
8428
|
const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
|
|
8414
8429
|
if (!items.length) return null;
|
|
8415
8430
|
return /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 12 }, children: [
|
|
8416
|
-
/* @__PURE__ */
|
|
8417
|
-
items.map((s) => /* @__PURE__ */
|
|
8431
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-label-lg", children: g }),
|
|
8432
|
+
items.map((s) => /* @__PURE__ */ jsx79(Endpoint, { s, onRequest }, s.id))
|
|
8418
8433
|
] }, g);
|
|
8419
8434
|
}),
|
|
8420
|
-
conventions && conventions.length ? /* @__PURE__ */
|
|
8421
|
-
/* @__PURE__ */
|
|
8422
|
-
/* @__PURE__ */
|
|
8435
|
+
conventions && conventions.length ? /* @__PURE__ */ jsx79(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx79("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
|
|
8436
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
|
|
8437
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
|
|
8423
8438
|
] }, k)) }) }) : null,
|
|
8424
|
-
openQuestions && openQuestions.length ? /* @__PURE__ */
|
|
8425
|
-
/* @__PURE__ */
|
|
8439
|
+
openQuestions && openQuestions.length ? /* @__PURE__ */ jsx79(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx79("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
|
|
8440
|
+
/* @__PURE__ */ jsx79(Badge, { tone: "danger", children: id }),
|
|
8426
8441
|
/* @__PURE__ */ jsxs69("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
|
|
8427
|
-
/* @__PURE__ */
|
|
8428
|
-
/* @__PURE__ */
|
|
8442
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
|
|
8443
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-body-sm fd-muted", children: why })
|
|
8429
8444
|
] })
|
|
8430
8445
|
] }, id)) }) }) : null
|
|
8431
8446
|
] });
|
|
8432
8447
|
}
|
|
8433
8448
|
|
|
8434
8449
|
// src/components/platform/ProfilePage.tsx
|
|
8435
|
-
import * as
|
|
8436
|
-
import { jsx as
|
|
8450
|
+
import * as React55 from "react";
|
|
8451
|
+
import { jsx as jsx80, jsxs as jsxs70 } from "react/jsx-runtime";
|
|
8437
8452
|
function fieldInitialValue(field, user) {
|
|
8438
8453
|
if (field.value) return field.value(user);
|
|
8439
8454
|
const raw = user[field.key];
|
|
@@ -8468,21 +8483,21 @@ function ProfilePage({
|
|
|
8468
8483
|
}) {
|
|
8469
8484
|
const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
|
|
8470
8485
|
const user = userProp || sessionUser;
|
|
8471
|
-
const initialFieldValues =
|
|
8486
|
+
const initialFieldValues = React55.useMemo(() => {
|
|
8472
8487
|
const values2 = {};
|
|
8473
8488
|
for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
|
|
8474
8489
|
return values2;
|
|
8475
8490
|
}, [user.id, fields]);
|
|
8476
|
-
const initialNotify =
|
|
8491
|
+
const initialNotify = React55.useMemo(() => {
|
|
8477
8492
|
const values2 = {};
|
|
8478
8493
|
for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
|
|
8479
8494
|
return values2;
|
|
8480
8495
|
}, [user.id, notifications]);
|
|
8481
|
-
const [values, setValues] =
|
|
8482
|
-
const [notify, setNotify] =
|
|
8483
|
-
const [saving, setSaving] =
|
|
8484
|
-
const [saved, setSaved] =
|
|
8485
|
-
const [prevUserId, setPrevUserId] =
|
|
8496
|
+
const [values, setValues] = React55.useState(initialFieldValues);
|
|
8497
|
+
const [notify, setNotify] = React55.useState(initialNotify);
|
|
8498
|
+
const [saving, setSaving] = React55.useState(false);
|
|
8499
|
+
const [saved, setSaved] = React55.useState(false);
|
|
8500
|
+
const [prevUserId, setPrevUserId] = React55.useState(user.id);
|
|
8486
8501
|
if (user.id !== prevUserId) {
|
|
8487
8502
|
setPrevUserId(user.id);
|
|
8488
8503
|
setValues(initialFieldValues);
|
|
@@ -8521,35 +8536,35 @@ function ProfilePage({
|
|
|
8521
8536
|
const fieldGroups = groupFields(fields);
|
|
8522
8537
|
return /* @__PURE__ */ jsxs70("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
|
|
8523
8538
|
/* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
8524
|
-
/* @__PURE__ */
|
|
8525
|
-
/* @__PURE__ */
|
|
8526
|
-
/* @__PURE__ */
|
|
8539
|
+
/* @__PURE__ */ jsx80("span", { className: "fd-overline fd-muted", children: "Account" }),
|
|
8540
|
+
/* @__PURE__ */ jsx80("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
|
|
8541
|
+
/* @__PURE__ */ jsx80("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." })
|
|
8527
8542
|
] }),
|
|
8528
|
-
/* @__PURE__ */
|
|
8529
|
-
/* @__PURE__ */
|
|
8543
|
+
/* @__PURE__ */ jsx80(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
|
|
8544
|
+
/* @__PURE__ */ jsx80(Avatar, { name: displayName, size: "lg" }),
|
|
8530
8545
|
/* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
|
|
8531
|
-
/* @__PURE__ */
|
|
8546
|
+
/* @__PURE__ */ jsx80("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
|
|
8532
8547
|
/* @__PURE__ */ jsxs70("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
|
|
8533
|
-
roles.map((r) => /* @__PURE__ */
|
|
8534
|
-
user.sso ? /* @__PURE__ */
|
|
8548
|
+
roles.map((r) => /* @__PURE__ */ jsx80(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
|
|
8549
|
+
user.sso ? /* @__PURE__ */ jsx80(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
|
|
8535
8550
|
] })
|
|
8536
8551
|
] }),
|
|
8537
|
-
onChangePhoto ? /* @__PURE__ */
|
|
8552
|
+
onChangePhoto ? /* @__PURE__ */ jsx80(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
|
|
8538
8553
|
] }) }),
|
|
8539
|
-
fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */
|
|
8554
|
+
fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ jsx80(
|
|
8540
8555
|
Card,
|
|
8541
8556
|
{
|
|
8542
8557
|
title: description ? /* @__PURE__ */ jsxs70("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
8543
|
-
/* @__PURE__ */
|
|
8544
|
-
/* @__PURE__ */
|
|
8558
|
+
/* @__PURE__ */ jsx80("span", { children: group }),
|
|
8559
|
+
/* @__PURE__ */ jsx80("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
|
|
8545
8560
|
] }) : group,
|
|
8546
8561
|
elevation: "flat",
|
|
8547
8562
|
children: /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 14 }, children: [
|
|
8548
|
-
/* @__PURE__ */
|
|
8563
|
+
/* @__PURE__ */ jsx80("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
|
|
8549
8564
|
const help = typeof field.help === "function" ? field.help(user) : field.help;
|
|
8550
8565
|
const readOnly = field.readOnly || field.type === "readonly";
|
|
8551
8566
|
if (field.type === "select") {
|
|
8552
|
-
return /* @__PURE__ */
|
|
8567
|
+
return /* @__PURE__ */ jsx80(
|
|
8553
8568
|
Select,
|
|
8554
8569
|
{
|
|
8555
8570
|
label: field.label,
|
|
@@ -8563,7 +8578,7 @@ function ProfilePage({
|
|
|
8563
8578
|
field.key
|
|
8564
8579
|
);
|
|
8565
8580
|
}
|
|
8566
|
-
return /* @__PURE__ */
|
|
8581
|
+
return /* @__PURE__ */ jsx80(
|
|
8567
8582
|
Input,
|
|
8568
8583
|
{
|
|
8569
8584
|
label: field.label,
|
|
@@ -8579,7 +8594,7 @@ function ProfilePage({
|
|
|
8579
8594
|
}) }),
|
|
8580
8595
|
groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
|
|
8581
8596
|
const help = typeof field.help === "function" ? field.help(user) : field.help;
|
|
8582
|
-
return /* @__PURE__ */
|
|
8597
|
+
return /* @__PURE__ */ jsx80(
|
|
8583
8598
|
Textarea,
|
|
8584
8599
|
{
|
|
8585
8600
|
label: field.label,
|
|
@@ -8599,16 +8614,16 @@ function ProfilePage({
|
|
|
8599
8614
|
group
|
|
8600
8615
|
)),
|
|
8601
8616
|
extra,
|
|
8602
|
-
notifications.length > 0 ? /* @__PURE__ */
|
|
8617
|
+
notifications.length > 0 ? /* @__PURE__ */ jsx80(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ jsx80("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ jsx80(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
|
|
8603
8618
|
/* @__PURE__ */ jsxs70(
|
|
8604
8619
|
Card,
|
|
8605
8620
|
{
|
|
8606
8621
|
title: /* @__PURE__ */ jsxs70("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
8607
|
-
/* @__PURE__ */
|
|
8608
|
-
/* @__PURE__ */
|
|
8622
|
+
/* @__PURE__ */ jsx80("span", { children: "Access" }),
|
|
8623
|
+
/* @__PURE__ */ jsx80("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
|
|
8609
8624
|
] }),
|
|
8610
8625
|
elevation: "flat",
|
|
8611
|
-
action: /* @__PURE__ */
|
|
8626
|
+
action: /* @__PURE__ */ jsx80(
|
|
8612
8627
|
Button,
|
|
8613
8628
|
{
|
|
8614
8629
|
size: "sm",
|
|
@@ -8620,34 +8635,34 @@ function ProfilePage({
|
|
|
8620
8635
|
),
|
|
8621
8636
|
children: [
|
|
8622
8637
|
/* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
8623
|
-
/* @__PURE__ */
|
|
8638
|
+
/* @__PURE__ */ jsx80(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
|
|
8624
8639
|
/* @__PURE__ */ jsxs70(CardRow, { label: "Permissions", children: [
|
|
8625
8640
|
permissions.length,
|
|
8626
8641
|
" granted"
|
|
8627
8642
|
] }),
|
|
8628
|
-
/* @__PURE__ */
|
|
8643
|
+
/* @__PURE__ */ jsx80(CardRow, { label: "Member since", children: user.joined || "\u2014" })
|
|
8629
8644
|
] }),
|
|
8630
|
-
/* @__PURE__ */
|
|
8645
|
+
/* @__PURE__ */ jsx80("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." })
|
|
8631
8646
|
]
|
|
8632
8647
|
}
|
|
8633
8648
|
),
|
|
8634
|
-
sessions ? /* @__PURE__ */
|
|
8649
|
+
sessions ? /* @__PURE__ */ jsx80(
|
|
8635
8650
|
Card,
|
|
8636
8651
|
{
|
|
8637
8652
|
title: "Signed-in devices",
|
|
8638
8653
|
elevation: "flat",
|
|
8639
|
-
action: /* @__PURE__ */
|
|
8640
|
-
children: /* @__PURE__ */
|
|
8641
|
-
/* @__PURE__ */
|
|
8654
|
+
action: /* @__PURE__ */ jsx80(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
|
|
8655
|
+
children: /* @__PURE__ */ jsx80("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ jsx80("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
|
|
8656
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
8642
8657
|
/* @__PURE__ */ jsxs70("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
|
|
8643
|
-
/* @__PURE__ */
|
|
8658
|
+
/* @__PURE__ */ jsx80("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
|
|
8644
8659
|
/* @__PURE__ */ jsxs70("span", { className: "fd-body-sm fd-muted", children: [
|
|
8645
8660
|
s.where,
|
|
8646
8661
|
" \xB7 ",
|
|
8647
8662
|
s.when
|
|
8648
8663
|
] })
|
|
8649
8664
|
] }),
|
|
8650
|
-
s.current ? /* @__PURE__ */
|
|
8665
|
+
s.current ? /* @__PURE__ */ jsx80(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx80(Button, { size: "sm", variant: "ghost", children: "Revoke" })
|
|
8651
8666
|
] }, s.id)) })
|
|
8652
8667
|
}
|
|
8653
8668
|
) : null,
|
|
@@ -8662,16 +8677,16 @@ function ProfilePage({
|
|
|
8662
8677
|
border: "1px solid var(--border)",
|
|
8663
8678
|
boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
|
|
8664
8679
|
}, children: [
|
|
8665
|
-
/* @__PURE__ */
|
|
8666
|
-
/* @__PURE__ */
|
|
8667
|
-
/* @__PURE__ */
|
|
8680
|
+
/* @__PURE__ */ jsx80("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
|
|
8681
|
+
/* @__PURE__ */ jsx80(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
|
|
8682
|
+
/* @__PURE__ */ jsx80(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
|
|
8668
8683
|
] })
|
|
8669
8684
|
] });
|
|
8670
8685
|
}
|
|
8671
8686
|
|
|
8672
8687
|
// src/components/platform/SessionScreen.tsx
|
|
8673
|
-
import * as
|
|
8674
|
-
import { Fragment as Fragment20, jsx as
|
|
8688
|
+
import * as React56 from "react";
|
|
8689
|
+
import { Fragment as Fragment20, jsx as jsx81, jsxs as jsxs71 } from "react/jsx-runtime";
|
|
8675
8690
|
var COPY = {
|
|
8676
8691
|
"signing-in": { busy: "Signing you in\u2026" },
|
|
8677
8692
|
"session-expired": { busy: "Your session expired \u2014 signing you back in\u2026" },
|
|
@@ -8684,28 +8699,28 @@ function SessionScreen({ kind, error, onRetry, productName }) {
|
|
|
8684
8699
|
const copy = COPY[kind];
|
|
8685
8700
|
const busyMessage = "busy" in copy ? copy.busy : null;
|
|
8686
8701
|
const failureTitle = "failure" in copy ? copy.failure : null;
|
|
8687
|
-
const [announced, setAnnounced] =
|
|
8688
|
-
|
|
8702
|
+
const [announced, setAnnounced] = React56.useState("");
|
|
8703
|
+
React56.useEffect(() => {
|
|
8689
8704
|
setAnnounced(busyMessage ?? "");
|
|
8690
8705
|
}, [busyMessage]);
|
|
8691
|
-
const titleRef =
|
|
8706
|
+
const titleRef = React56.useRef(null);
|
|
8692
8707
|
const failed = failureTitle !== null;
|
|
8693
|
-
|
|
8708
|
+
React56.useEffect(() => {
|
|
8694
8709
|
titleRef.current?.focus({ preventScroll: true });
|
|
8695
8710
|
}, [failed]);
|
|
8696
|
-
return /* @__PURE__ */
|
|
8697
|
-
/* @__PURE__ */
|
|
8711
|
+
return /* @__PURE__ */ jsx81("main", { className: "fd-session-screen", children: /* @__PURE__ */ jsxs71("div", { className: "fd-session-screen-inner", children: [
|
|
8712
|
+
/* @__PURE__ */ jsx81("div", { className: "fd-session-screen-mark", "data-theme": "dark", children: /* @__PURE__ */ jsx81(FlytedeskMark, { size: "lg" }) }),
|
|
8698
8713
|
/* @__PURE__ */ jsxs71("div", { className: "fd-session-screen-frame", children: [
|
|
8699
|
-
/* @__PURE__ */
|
|
8700
|
-
/* @__PURE__ */
|
|
8701
|
-
/* @__PURE__ */
|
|
8702
|
-
/* @__PURE__ */
|
|
8703
|
-
/* @__PURE__ */
|
|
8704
|
-
/* @__PURE__ */
|
|
8714
|
+
/* @__PURE__ */ jsx81("div", { className: "fd-session-screen-stripe" }),
|
|
8715
|
+
/* @__PURE__ */ jsx81(Card, { children: /* @__PURE__ */ jsxs71("div", { className: "fd-session-screen-body", children: [
|
|
8716
|
+
/* @__PURE__ */ jsx81("h1", { ref: titleRef, tabIndex: -1, className: "fd-h3 fd-session-screen-title", children: productName }),
|
|
8717
|
+
/* @__PURE__ */ jsx81("div", { role: "status", "aria-live": "polite", className: "fd-session-screen-status", children: busyMessage !== null ? /* @__PURE__ */ jsxs71(Fragment20, { children: [
|
|
8718
|
+
/* @__PURE__ */ jsx81("span", { className: "fd-spinner fd-spinner-lg fd-session-screen-spinner", "aria-hidden": "true" }),
|
|
8719
|
+
/* @__PURE__ */ jsx81("p", { className: "fd-body fd-session-screen-message", children: announced })
|
|
8705
8720
|
] }) : null }),
|
|
8706
8721
|
failureTitle !== null ? /* @__PURE__ */ jsxs71("div", { className: "fd-session-screen-failure", children: [
|
|
8707
|
-
/* @__PURE__ */
|
|
8708
|
-
onRetry !== null ? /* @__PURE__ */
|
|
8722
|
+
/* @__PURE__ */ jsx81(Banner, { tone: "danger", title: failureTitle, detail: error ?? void 0 }),
|
|
8723
|
+
onRetry !== null ? /* @__PURE__ */ jsx81(Button, { variant: "primary", block: true, onClick: onRetry, children: "Try again" }) : null
|
|
8709
8724
|
] }) : null
|
|
8710
8725
|
] }) })
|
|
8711
8726
|
] })
|
|
@@ -8713,10 +8728,10 @@ function SessionScreen({ kind, error, onRetry, productName }) {
|
|
|
8713
8728
|
}
|
|
8714
8729
|
|
|
8715
8730
|
// src/components/platform/RoadmapTimeline.tsx
|
|
8716
|
-
import * as
|
|
8731
|
+
import * as React59 from "react";
|
|
8717
8732
|
|
|
8718
8733
|
// src/kits/session.ts
|
|
8719
|
-
import * as
|
|
8734
|
+
import * as React57 from "react";
|
|
8720
8735
|
var PERMISSION_CATALOG = [
|
|
8721
8736
|
{ group: "Plans", items: [
|
|
8722
8737
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -10283,8 +10298,8 @@ function roadmap(overrides) {
|
|
|
10283
10298
|
};
|
|
10284
10299
|
}
|
|
10285
10300
|
function useSession() {
|
|
10286
|
-
const [s, setS] =
|
|
10287
|
-
|
|
10301
|
+
const [s, setS] = React57.useState(getSession);
|
|
10302
|
+
React57.useEffect(() => subscribe(setS), []);
|
|
10288
10303
|
return s;
|
|
10289
10304
|
}
|
|
10290
10305
|
var SessionKit = {
|
|
@@ -10317,7 +10332,7 @@ var SessionKit = {
|
|
|
10317
10332
|
};
|
|
10318
10333
|
function DemoSessionProvider({ children }) {
|
|
10319
10334
|
const session = useSession();
|
|
10320
|
-
const value =
|
|
10335
|
+
const value = React57.useMemo(
|
|
10321
10336
|
() => ({
|
|
10322
10337
|
user: session.user,
|
|
10323
10338
|
roles: session.roles,
|
|
@@ -10333,11 +10348,11 @@ function DemoSessionProvider({ children }) {
|
|
|
10333
10348
|
}),
|
|
10334
10349
|
[session]
|
|
10335
10350
|
);
|
|
10336
|
-
return
|
|
10351
|
+
return React57.createElement(SessionProvider, { value }, children);
|
|
10337
10352
|
}
|
|
10338
10353
|
|
|
10339
10354
|
// src/kits/runtime.ts
|
|
10340
|
-
import * as
|
|
10355
|
+
import * as React58 from "react";
|
|
10341
10356
|
var WIRED_ENDPOINTS = [
|
|
10342
10357
|
// Nothing yet. Every id below would come from a real service:
|
|
10343
10358
|
// "plan.get", "placements.list", …
|
|
@@ -10508,8 +10523,8 @@ var RuntimeKit = {
|
|
|
10508
10523
|
};
|
|
10509
10524
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
10510
10525
|
function useRuntimeMode() {
|
|
10511
|
-
const [m, setM] =
|
|
10512
|
-
|
|
10526
|
+
const [m, setM] = React58.useState(RuntimeKit.getMode());
|
|
10527
|
+
React58.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
10513
10528
|
return m;
|
|
10514
10529
|
}
|
|
10515
10530
|
function useFeatureStatus(key) {
|
|
@@ -10528,7 +10543,7 @@ var UseRuntimeMode = useRuntimeMode;
|
|
|
10528
10543
|
var UseFeatureStatus = useFeatureStatus;
|
|
10529
10544
|
|
|
10530
10545
|
// src/components/platform/RoadmapTimeline.tsx
|
|
10531
|
-
import { jsx as
|
|
10546
|
+
import { jsx as jsx82, jsxs as jsxs72 } from "react/jsx-runtime";
|
|
10532
10547
|
var STATUS = {
|
|
10533
10548
|
shipped: { tone: "success", icon: "check-circle", label: "Wired" },
|
|
10534
10549
|
next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
|
|
@@ -10543,43 +10558,43 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
10543
10558
|
const s = STATUS[item.status] || STATUS.planned;
|
|
10544
10559
|
const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
|
|
10545
10560
|
const blocking = deps.filter((d) => !d.implemented);
|
|
10546
|
-
return /* @__PURE__ */
|
|
10561
|
+
return /* @__PURE__ */ jsx82(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
10547
10562
|
/* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
10548
|
-
/* @__PURE__ */
|
|
10549
|
-
/* @__PURE__ */
|
|
10550
|
-
/* @__PURE__ */
|
|
10563
|
+
/* @__PURE__ */ jsx82("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
|
|
10564
|
+
/* @__PURE__ */ jsx82(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
|
|
10565
|
+
/* @__PURE__ */ jsx82(Badge, { tone: s.tone, icon: s.icon, children: s.label })
|
|
10551
10566
|
] }),
|
|
10552
|
-
/* @__PURE__ */
|
|
10567
|
+
/* @__PURE__ */ jsx82("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
|
|
10553
10568
|
item.backend ? /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
|
|
10554
|
-
/* @__PURE__ */
|
|
10555
|
-
/* @__PURE__ */
|
|
10569
|
+
/* @__PURE__ */ jsx82("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
|
|
10570
|
+
/* @__PURE__ */ jsx82("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
|
|
10556
10571
|
] }) : null,
|
|
10557
10572
|
/* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
10558
10573
|
item.effort ? /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted", children: [
|
|
10559
|
-
/* @__PURE__ */
|
|
10574
|
+
/* @__PURE__ */ jsx82("i", { className: "ph ph-hourglass-medium" }),
|
|
10560
10575
|
" ",
|
|
10561
10576
|
item.effort
|
|
10562
10577
|
] }) : null,
|
|
10563
10578
|
/* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted", children: [
|
|
10564
|
-
/* @__PURE__ */
|
|
10579
|
+
/* @__PURE__ */ jsx82("i", { className: "ph ph-user" }),
|
|
10565
10580
|
" ",
|
|
10566
10581
|
item.owner
|
|
10567
10582
|
] }),
|
|
10568
|
-
item.screen ? /* @__PURE__ */
|
|
10569
|
-
/* @__PURE__ */
|
|
10570
|
-
/* @__PURE__ */
|
|
10583
|
+
item.screen ? /* @__PURE__ */ jsx82(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
|
|
10584
|
+
/* @__PURE__ */ jsx82("span", { style: { flex: 1 } }),
|
|
10585
|
+
/* @__PURE__ */ jsx82(
|
|
10571
10586
|
"button",
|
|
10572
10587
|
{
|
|
10573
10588
|
type: "button",
|
|
10574
10589
|
onClick: () => onOpenFlag && onOpenFlag(item.key),
|
|
10575
10590
|
style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
|
|
10576
|
-
children: /* @__PURE__ */
|
|
10591
|
+
children: /* @__PURE__ */ jsx82("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
|
|
10577
10592
|
}
|
|
10578
10593
|
)
|
|
10579
10594
|
] }),
|
|
10580
10595
|
deps.length ? /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
|
|
10581
|
-
/* @__PURE__ */
|
|
10582
|
-
deps.map((d) => /* @__PURE__ */
|
|
10596
|
+
/* @__PURE__ */ jsx82("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
|
|
10597
|
+
deps.map((d) => /* @__PURE__ */ jsx82(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
|
|
10583
10598
|
] }) : null,
|
|
10584
10599
|
blocking.length && !item.implemented ? /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
|
|
10585
10600
|
"Blocked until ",
|
|
@@ -10592,12 +10607,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
10592
10607
|
}
|
|
10593
10608
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
10594
10609
|
const session = SessionKit.useSession();
|
|
10595
|
-
const [project, setProject] =
|
|
10596
|
-
const [q, setQ] =
|
|
10597
|
-
const scrollRef =
|
|
10598
|
-
const nowRef =
|
|
10599
|
-
const rm =
|
|
10600
|
-
const byKey =
|
|
10610
|
+
const [project, setProject] = React59.useState("");
|
|
10611
|
+
const [q, setQ] = React59.useState("");
|
|
10612
|
+
const scrollRef = React59.useRef(null);
|
|
10613
|
+
const nowRef = React59.useRef(null);
|
|
10614
|
+
const rm = React59.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
10615
|
+
const byKey = React59.useMemo(() => {
|
|
10601
10616
|
const m = {};
|
|
10602
10617
|
rm.items.forEach((i) => {
|
|
10603
10618
|
m[i.key] = i;
|
|
@@ -10606,7 +10621,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10606
10621
|
}, [rm]);
|
|
10607
10622
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
10608
10623
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
10609
|
-
|
|
10624
|
+
React59.useEffect(() => {
|
|
10610
10625
|
let raf1 = 0, raf2 = 0;
|
|
10611
10626
|
const place = () => {
|
|
10612
10627
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -10636,21 +10651,21 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10636
10651
|
let lastPhase = null;
|
|
10637
10652
|
return /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
|
|
10638
10653
|
/* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
10639
|
-
/* @__PURE__ */
|
|
10640
|
-
/* @__PURE__ */
|
|
10641
|
-
/* @__PURE__ */
|
|
10654
|
+
/* @__PURE__ */ jsx82("span", { className: "fd-overline fd-muted", children: "Architecture" }),
|
|
10655
|
+
/* @__PURE__ */ jsx82("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
10656
|
+
/* @__PURE__ */ jsx82("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." })
|
|
10642
10657
|
] }),
|
|
10643
10658
|
/* @__PURE__ */ jsxs72("div", { className: "fd-grid-stats is-thin", children: [
|
|
10644
|
-
/* @__PURE__ */
|
|
10645
|
-
/* @__PURE__ */
|
|
10646
|
-
/* @__PURE__ */
|
|
10647
|
-
/* @__PURE__ */
|
|
10659
|
+
/* @__PURE__ */ jsx82(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
|
|
10660
|
+
/* @__PURE__ */ jsx82(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
|
|
10661
|
+
/* @__PURE__ */ jsx82(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
|
|
10662
|
+
/* @__PURE__ */ jsx82(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
|
|
10648
10663
|
] }),
|
|
10649
10664
|
/* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
10650
|
-
/* @__PURE__ */
|
|
10651
|
-
/* @__PURE__ */
|
|
10652
|
-
/* @__PURE__ */
|
|
10653
|
-
/* @__PURE__ */
|
|
10665
|
+
/* @__PURE__ */ jsx82(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 } }),
|
|
10666
|
+
/* @__PURE__ */ jsx82(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
|
|
10667
|
+
/* @__PURE__ */ jsx82("span", { style: { flex: 1 } }),
|
|
10668
|
+
/* @__PURE__ */ jsx82(
|
|
10654
10669
|
Button,
|
|
10655
10670
|
{
|
|
10656
10671
|
size: "sm",
|
|
@@ -10664,7 +10679,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10664
10679
|
}
|
|
10665
10680
|
)
|
|
10666
10681
|
] }),
|
|
10667
|
-
/* @__PURE__ */
|
|
10682
|
+
/* @__PURE__ */ jsx82(
|
|
10668
10683
|
Flag,
|
|
10669
10684
|
{
|
|
10670
10685
|
tone: "info",
|
|
@@ -10673,17 +10688,17 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10673
10688
|
actions: null
|
|
10674
10689
|
}
|
|
10675
10690
|
),
|
|
10676
|
-
/* @__PURE__ */
|
|
10677
|
-
/* @__PURE__ */
|
|
10691
|
+
/* @__PURE__ */ jsx82("div", { className: "fd-rm", children: /* @__PURE__ */ jsx82("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs72("div", { className: "fd-rm-track", children: [
|
|
10692
|
+
/* @__PURE__ */ jsx82("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx82("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
|
|
10678
10693
|
items.map((item, n) => {
|
|
10679
10694
|
const showPhase = item.phase !== lastPhase;
|
|
10680
10695
|
lastPhase = item.phase;
|
|
10681
10696
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
10682
10697
|
const isBoundary = n === firstPending;
|
|
10683
|
-
return /* @__PURE__ */ jsxs72(
|
|
10698
|
+
return /* @__PURE__ */ jsxs72(React59.Fragment, { children: [
|
|
10684
10699
|
showPhase ? /* @__PURE__ */ jsxs72("div", { className: "fd-rm-era", children: [
|
|
10685
10700
|
/* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
10686
|
-
/* @__PURE__ */
|
|
10701
|
+
/* @__PURE__ */ jsx82("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
10687
10702
|
item.phase === 0 ? null : /* @__PURE__ */ jsxs72("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
10688
10703
|
fmtDate(item.phaseStart),
|
|
10689
10704
|
" \u2013 ",
|
|
@@ -10696,37 +10711,37 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10696
10711
|
inPhase === 1 ? "" : "s"
|
|
10697
10712
|
] })
|
|
10698
10713
|
] }),
|
|
10699
|
-
item.phaseWhy ? /* @__PURE__ */
|
|
10714
|
+
item.phaseWhy ? /* @__PURE__ */ jsx82("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
|
|
10700
10715
|
] }) : null,
|
|
10701
|
-
isBoundary ? /* @__PURE__ */
|
|
10702
|
-
/* @__PURE__ */
|
|
10716
|
+
isBoundary ? /* @__PURE__ */ jsx82("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs72("span", { className: "fd-rm-now-pill", children: [
|
|
10717
|
+
/* @__PURE__ */ jsx82("i", { className: "ph ph-map-pin" }),
|
|
10703
10718
|
" You are here \u2014 everything above is wired"
|
|
10704
10719
|
] }) }) : null,
|
|
10705
10720
|
/* @__PURE__ */ jsxs72("div", { className: "fd-rm-row", children: [
|
|
10706
|
-
/* @__PURE__ */
|
|
10721
|
+
/* @__PURE__ */ jsx82("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
|
|
10707
10722
|
/* @__PURE__ */ jsxs72("div", { className: "fd-rm-date", children: [
|
|
10708
10723
|
fmtDate(item.date),
|
|
10709
|
-
/* @__PURE__ */
|
|
10710
|
-
/* @__PURE__ */
|
|
10724
|
+
/* @__PURE__ */ jsx82("br", {}),
|
|
10725
|
+
/* @__PURE__ */ jsx82("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
|
|
10711
10726
|
] }),
|
|
10712
|
-
/* @__PURE__ */
|
|
10727
|
+
/* @__PURE__ */ jsx82(RoadmapCard, { item, byKey, onOpenFlag })
|
|
10713
10728
|
] })
|
|
10714
10729
|
] }, item.key);
|
|
10715
10730
|
}),
|
|
10716
|
-
!items.length ? /* @__PURE__ */
|
|
10731
|
+
!items.length ? /* @__PURE__ */ jsx82("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
|
|
10717
10732
|
] }) }) }),
|
|
10718
10733
|
/* @__PURE__ */ jsxs72("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
|
|
10719
10734
|
"Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
|
|
10720
|
-
/* @__PURE__ */
|
|
10735
|
+
/* @__PURE__ */ jsx82("code", { className: "fd-mono", children: "implemented" }),
|
|
10721
10736
|
" field, so this page cannot drift from what the apps actually do."
|
|
10722
10737
|
] })
|
|
10723
10738
|
] });
|
|
10724
10739
|
}
|
|
10725
10740
|
|
|
10726
10741
|
// src/components/platform/ComingSoon.tsx
|
|
10727
|
-
import * as
|
|
10742
|
+
import * as React60 from "react";
|
|
10728
10743
|
import { createPortal as createPortal6 } from "react-dom";
|
|
10729
|
-
import { Fragment as Fragment22, jsx as
|
|
10744
|
+
import { Fragment as Fragment22, jsx as jsx83, jsxs as jsxs73 } from "react/jsx-runtime";
|
|
10730
10745
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
10731
10746
|
function readBypassed() {
|
|
10732
10747
|
try {
|
|
@@ -10742,8 +10757,8 @@ function writeBypassed(list) {
|
|
|
10742
10757
|
}
|
|
10743
10758
|
}
|
|
10744
10759
|
function useBypass(key) {
|
|
10745
|
-
const [on, setOn] =
|
|
10746
|
-
|
|
10760
|
+
const [on, setOn] = React60.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
10761
|
+
React60.useEffect(() => {
|
|
10747
10762
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
10748
10763
|
}, [key]);
|
|
10749
10764
|
const set = (next) => {
|
|
@@ -10758,41 +10773,41 @@ function useBypass(key) {
|
|
|
10758
10773
|
function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
|
|
10759
10774
|
return /* @__PURE__ */ jsxs73(Fragment22, { children: [
|
|
10760
10775
|
/* @__PURE__ */ jsxs73("span", { className: "fd-soon-badge", children: [
|
|
10761
|
-
/* @__PURE__ */
|
|
10776
|
+
/* @__PURE__ */ jsx83("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
10762
10777
|
label
|
|
10763
10778
|
] }),
|
|
10764
|
-
detail ? /* @__PURE__ */
|
|
10779
|
+
detail ? /* @__PURE__ */ jsx83("span", { className: "fd-soon-detail", children: detail }) : null,
|
|
10765
10780
|
backend ? /* @__PURE__ */ jsxs73("span", { className: "fd-soon-backend", children: [
|
|
10766
|
-
/* @__PURE__ */
|
|
10781
|
+
/* @__PURE__ */ jsx83("span", { className: "fd-overline", children: "Needs" }),
|
|
10767
10782
|
" ",
|
|
10768
10783
|
backend
|
|
10769
10784
|
] }) : null,
|
|
10770
10785
|
eta || effort || onRoadmap ? /* @__PURE__ */ jsxs73("span", { className: "fd-soon-meta", children: [
|
|
10771
10786
|
eta ? /* @__PURE__ */ jsxs73("span", { children: [
|
|
10772
|
-
/* @__PURE__ */
|
|
10787
|
+
/* @__PURE__ */ jsx83("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
|
|
10773
10788
|
" ",
|
|
10774
10789
|
eta
|
|
10775
10790
|
] }) : null,
|
|
10776
10791
|
effort ? /* @__PURE__ */ jsxs73("span", { children: [
|
|
10777
|
-
/* @__PURE__ */
|
|
10792
|
+
/* @__PURE__ */ jsx83("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
|
|
10778
10793
|
" ",
|
|
10779
10794
|
effort
|
|
10780
10795
|
] }) : null,
|
|
10781
10796
|
onRoadmap ? /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
10782
10797
|
"See the roadmap ",
|
|
10783
|
-
/* @__PURE__ */
|
|
10798
|
+
/* @__PURE__ */ jsx83("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
10784
10799
|
] }) : null
|
|
10785
10800
|
] }) : null,
|
|
10786
10801
|
allowed ? /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
|
|
10787
|
-
/* @__PURE__ */
|
|
10802
|
+
/* @__PURE__ */ jsx83("i", { className: "ph ph-eye", "aria-hidden": "true" }),
|
|
10788
10803
|
" View and use it anyway"
|
|
10789
10804
|
] }) : null
|
|
10790
10805
|
] });
|
|
10791
10806
|
}
|
|
10792
10807
|
function useHoverCard(open2) {
|
|
10793
|
-
const anchor =
|
|
10794
|
-
const [pos, setPos] =
|
|
10795
|
-
|
|
10808
|
+
const anchor = React60.useRef(null);
|
|
10809
|
+
const [pos, setPos] = React60.useState(null);
|
|
10810
|
+
React60.useLayoutEffect(() => {
|
|
10796
10811
|
if (!open2 || !anchor.current) {
|
|
10797
10812
|
setPos(null);
|
|
10798
10813
|
return;
|
|
@@ -10846,7 +10861,7 @@ function ComingSoon({
|
|
|
10846
10861
|
if (allowed && bypassed) {
|
|
10847
10862
|
return /* @__PURE__ */ jsxs73("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
|
|
10848
10863
|
children,
|
|
10849
|
-
/* @__PURE__ */
|
|
10864
|
+
/* @__PURE__ */ jsx83(
|
|
10850
10865
|
"button",
|
|
10851
10866
|
{
|
|
10852
10867
|
type: "button",
|
|
@@ -10854,12 +10869,12 @@ function ComingSoon({
|
|
|
10854
10869
|
title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
|
|
10855
10870
|
onClick: () => setBypassed(false),
|
|
10856
10871
|
"aria-label": "Re-blur this unwired feature",
|
|
10857
|
-
children: /* @__PURE__ */
|
|
10872
|
+
children: /* @__PURE__ */ jsx83("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
10858
10873
|
}
|
|
10859
10874
|
)
|
|
10860
10875
|
] });
|
|
10861
10876
|
}
|
|
10862
|
-
return /* @__PURE__ */
|
|
10877
|
+
return /* @__PURE__ */ jsx83(
|
|
10863
10878
|
InlineSoon,
|
|
10864
10879
|
{
|
|
10865
10880
|
label,
|
|
@@ -10882,17 +10897,17 @@ function ComingSoon({
|
|
|
10882
10897
|
return /* @__PURE__ */ jsxs73("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
|
|
10883
10898
|
/* @__PURE__ */ jsxs73("div", { className: "fd-soon-bar", role: "status", children: [
|
|
10884
10899
|
/* @__PURE__ */ jsxs73("span", { className: "fd-soon-badge", children: [
|
|
10885
|
-
/* @__PURE__ */
|
|
10900
|
+
/* @__PURE__ */ jsx83("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
10886
10901
|
"Unwired feature \u2014 you are using it anyway"
|
|
10887
10902
|
] }),
|
|
10888
|
-
/* @__PURE__ */
|
|
10903
|
+
/* @__PURE__ */ jsx83("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
|
|
10889
10904
|
/* @__PURE__ */ jsxs73("span", { className: "fd-soon-bar-actions", children: [
|
|
10890
10905
|
onRoadmap ? /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
10891
10906
|
"Roadmap ",
|
|
10892
|
-
/* @__PURE__ */
|
|
10907
|
+
/* @__PURE__ */ jsx83("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
10893
10908
|
] }) : null,
|
|
10894
10909
|
/* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
|
|
10895
|
-
/* @__PURE__ */
|
|
10910
|
+
/* @__PURE__ */ jsx83("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
|
|
10896
10911
|
" Re-blur"
|
|
10897
10912
|
] })
|
|
10898
10913
|
] })
|
|
@@ -10901,9 +10916,9 @@ function ComingSoon({
|
|
|
10901
10916
|
] });
|
|
10902
10917
|
}
|
|
10903
10918
|
return /* @__PURE__ */ jsxs73("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
|
|
10904
|
-
/* @__PURE__ */
|
|
10905
|
-
/* @__PURE__ */
|
|
10906
|
-
/* @__PURE__ */
|
|
10919
|
+
/* @__PURE__ */ jsx83("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
10920
|
+
/* @__PURE__ */ jsx83("div", { className: "fd-soon-veil" }),
|
|
10921
|
+
/* @__PURE__ */ jsx83("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx83(
|
|
10907
10922
|
SoonCard,
|
|
10908
10923
|
{
|
|
10909
10924
|
label,
|
|
@@ -10919,12 +10934,12 @@ function ComingSoon({
|
|
|
10919
10934
|
] });
|
|
10920
10935
|
}
|
|
10921
10936
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
10922
|
-
const [open2, setOpen] =
|
|
10937
|
+
const [open2, setOpen] = React60.useState(false);
|
|
10923
10938
|
const [anchor, pos] = useHoverCard(open2);
|
|
10924
|
-
const hoverCardRef =
|
|
10939
|
+
const hoverCardRef = React60.useRef(null);
|
|
10925
10940
|
const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
|
|
10926
10941
|
const zIndex = useLayerZIndex(hoverLayer);
|
|
10927
|
-
const close2 =
|
|
10942
|
+
const close2 = React60.useRef(null);
|
|
10928
10943
|
const show = () => {
|
|
10929
10944
|
if (close2.current) {
|
|
10930
10945
|
clearTimeout(close2.current);
|
|
@@ -10940,7 +10955,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10940
10955
|
setOpen(false);
|
|
10941
10956
|
}, 140);
|
|
10942
10957
|
};
|
|
10943
|
-
|
|
10958
|
+
React60.useEffect(() => () => {
|
|
10944
10959
|
if (close2.current) clearTimeout(close2.current);
|
|
10945
10960
|
}, []);
|
|
10946
10961
|
return /* @__PURE__ */ jsxs73(
|
|
@@ -10954,8 +10969,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10954
10969
|
onBlur: hide,
|
|
10955
10970
|
...rest,
|
|
10956
10971
|
children: [
|
|
10957
|
-
/* @__PURE__ */
|
|
10958
|
-
/* @__PURE__ */
|
|
10972
|
+
/* @__PURE__ */ jsx83("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
10973
|
+
/* @__PURE__ */ jsx83(
|
|
10959
10974
|
"button",
|
|
10960
10975
|
{
|
|
10961
10976
|
type: "button",
|
|
@@ -10966,11 +10981,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10966
10981
|
onFocus: show,
|
|
10967
10982
|
onBlur: hide,
|
|
10968
10983
|
onClick: () => open2 ? setOpen(false) : show(),
|
|
10969
|
-
children: /* @__PURE__ */
|
|
10984
|
+
children: /* @__PURE__ */ jsx83("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
10970
10985
|
}
|
|
10971
10986
|
),
|
|
10972
10987
|
open2 && pos ? createPortal6(
|
|
10973
|
-
/* @__PURE__ */
|
|
10988
|
+
/* @__PURE__ */ jsx83(
|
|
10974
10989
|
"div",
|
|
10975
10990
|
{
|
|
10976
10991
|
ref: hoverCardRef,
|
|
@@ -10979,7 +10994,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10979
10994
|
style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
|
|
10980
10995
|
onMouseEnter: show,
|
|
10981
10996
|
onMouseLeave: hide,
|
|
10982
|
-
children: /* @__PURE__ */
|
|
10997
|
+
children: /* @__PURE__ */ jsx83(
|
|
10983
10998
|
SoonCard,
|
|
10984
10999
|
{
|
|
10985
11000
|
label,
|
|
@@ -11009,7 +11024,7 @@ function formatEta(iso2) {
|
|
|
11009
11024
|
var FormatEta = formatEta;
|
|
11010
11025
|
|
|
11011
11026
|
// src/components/platform/Gate.tsx
|
|
11012
|
-
import { jsx as
|
|
11027
|
+
import { jsx as jsx84, jsxs as jsxs74 } from "react/jsx-runtime";
|
|
11013
11028
|
function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
|
|
11014
11029
|
const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
|
|
11015
11030
|
return /* @__PURE__ */ jsxs74(
|
|
@@ -11029,13 +11044,13 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
11029
11044
|
...rest,
|
|
11030
11045
|
children: [
|
|
11031
11046
|
/* @__PURE__ */ jsxs74("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
11032
|
-
/* @__PURE__ */
|
|
11033
|
-
/* @__PURE__ */
|
|
11047
|
+
/* @__PURE__ */ jsx84("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
11048
|
+
/* @__PURE__ */ jsx84("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
|
|
11034
11049
|
] }),
|
|
11035
|
-
/* @__PURE__ */
|
|
11050
|
+
/* @__PURE__ */ jsx84("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." }),
|
|
11036
11051
|
need.length ? /* @__PURE__ */ jsxs74("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
|
|
11037
|
-
/* @__PURE__ */
|
|
11038
|
-
need.map((p) => /* @__PURE__ */
|
|
11052
|
+
/* @__PURE__ */ jsx84("span", { className: "fd-overline fd-muted", children: "Requires" }),
|
|
11053
|
+
need.map((p) => /* @__PURE__ */ jsx84("code", { className: "fd-mono", style: {
|
|
11039
11054
|
fontSize: 11.5,
|
|
11040
11055
|
padding: "2px 7px",
|
|
11041
11056
|
borderRadius: 5,
|
|
@@ -11065,10 +11080,10 @@ function GatePending({ compact: compact3 = false, className = "" }) {
|
|
|
11065
11080
|
},
|
|
11066
11081
|
children: [
|
|
11067
11082
|
/* @__PURE__ */ jsxs74("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
11068
|
-
/* @__PURE__ */
|
|
11069
|
-
/* @__PURE__ */
|
|
11083
|
+
/* @__PURE__ */ jsx84("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
11084
|
+
/* @__PURE__ */ jsx84("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
|
|
11070
11085
|
] }),
|
|
11071
|
-
/* @__PURE__ */
|
|
11086
|
+
/* @__PURE__ */ jsx84("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." })
|
|
11072
11087
|
]
|
|
11073
11088
|
}
|
|
11074
11089
|
);
|
|
@@ -11078,7 +11093,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
|
|
|
11078
11093
|
if (pending) {
|
|
11079
11094
|
if (pendingFallback !== void 0) return pendingFallback;
|
|
11080
11095
|
if (silent) return null;
|
|
11081
|
-
return /* @__PURE__ */
|
|
11096
|
+
return /* @__PURE__ */ jsx84(GatePending, { compact: compact3 });
|
|
11082
11097
|
}
|
|
11083
11098
|
let ok = true;
|
|
11084
11099
|
if (perm) ok = ok && can2(perm);
|
|
@@ -11087,7 +11102,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
|
|
|
11087
11102
|
if (ok) return children;
|
|
11088
11103
|
if (fallback !== void 0) return fallback;
|
|
11089
11104
|
if (silent) return null;
|
|
11090
|
-
return /* @__PURE__ */
|
|
11105
|
+
return /* @__PURE__ */ jsx84(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
|
|
11091
11106
|
}
|
|
11092
11107
|
function FeatureGate({
|
|
11093
11108
|
flag,
|
|
@@ -11110,7 +11125,7 @@ function FeatureGate({
|
|
|
11110
11125
|
const f = SessionKit.findFlag(flag) || {};
|
|
11111
11126
|
const missing = rt.missing || [];
|
|
11112
11127
|
const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
|
|
11113
|
-
return /* @__PURE__ */
|
|
11128
|
+
return /* @__PURE__ */ jsx84(
|
|
11114
11129
|
ComingSoon,
|
|
11115
11130
|
{
|
|
11116
11131
|
label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
|
|
@@ -11131,22 +11146,22 @@ function FeatureGate({
|
|
|
11131
11146
|
function PermissionHint({ perm, children }) {
|
|
11132
11147
|
const { can: can2, pending } = useSessionContext();
|
|
11133
11148
|
if (pending) {
|
|
11134
|
-
return /* @__PURE__ */
|
|
11149
|
+
return /* @__PURE__ */ jsx84("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ jsx84("span", { style: { pointerEvents: "none" }, children }) });
|
|
11135
11150
|
}
|
|
11136
11151
|
if (can2(perm)) return children;
|
|
11137
|
-
return /* @__PURE__ */
|
|
11152
|
+
return /* @__PURE__ */ jsx84(
|
|
11138
11153
|
"span",
|
|
11139
11154
|
{
|
|
11140
11155
|
title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
|
|
11141
11156
|
style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
|
|
11142
11157
|
"aria-disabled": "true",
|
|
11143
|
-
children: /* @__PURE__ */
|
|
11158
|
+
children: /* @__PURE__ */ jsx84("span", { style: { pointerEvents: "none" }, children })
|
|
11144
11159
|
}
|
|
11145
11160
|
);
|
|
11146
11161
|
}
|
|
11147
11162
|
|
|
11148
11163
|
// src/components/platform/ModeSwitch.tsx
|
|
11149
|
-
import { Fragment as Fragment23, jsx as
|
|
11164
|
+
import { Fragment as Fragment23, jsx as jsx85, jsxs as jsxs75 } from "react/jsx-runtime";
|
|
11150
11165
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
11151
11166
|
const mode2 = useRuntimeMode();
|
|
11152
11167
|
const panel = useInlinePanel();
|
|
@@ -11169,15 +11184,15 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
11169
11184
|
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.",
|
|
11170
11185
|
className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
|
|
11171
11186
|
children: [
|
|
11172
|
-
/* @__PURE__ */
|
|
11173
|
-
test && requestCount ? /* @__PURE__ */
|
|
11187
|
+
/* @__PURE__ */ jsx85("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
|
|
11188
|
+
test && requestCount ? /* @__PURE__ */ jsx85("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
|
|
11174
11189
|
]
|
|
11175
11190
|
}
|
|
11176
11191
|
),
|
|
11177
11192
|
/* @__PURE__ */ jsxs75(InlinePanelSurface, { panel, align: "right", offset: 8, width: 400, className: "fd-mode-pop", label: test ? "Test mode" : "Live mode", children: [
|
|
11178
11193
|
/* @__PURE__ */ jsxs75("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
11179
11194
|
/* @__PURE__ */ jsxs75("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
|
|
11180
|
-
/* @__PURE__ */
|
|
11195
|
+
/* @__PURE__ */ jsx85("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
|
|
11181
11196
|
test ? "Test mode" : "Live mode"
|
|
11182
11197
|
] }),
|
|
11183
11198
|
test ? /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
@@ -11185,11 +11200,11 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
11185
11200
|
" simulated request",
|
|
11186
11201
|
requestCount === 1 ? "" : "s"
|
|
11187
11202
|
] }) : null,
|
|
11188
|
-
/* @__PURE__ */
|
|
11189
|
-
test && onClearLog ? /* @__PURE__ */
|
|
11203
|
+
/* @__PURE__ */ jsx85("span", { style: { flex: 1 } }),
|
|
11204
|
+
test && onClearLog ? /* @__PURE__ */ jsx85("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
|
|
11190
11205
|
] }),
|
|
11191
11206
|
/* @__PURE__ */ jsxs75("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
11192
|
-
/* @__PURE__ */
|
|
11207
|
+
/* @__PURE__ */ jsx85("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." }),
|
|
11193
11208
|
/* @__PURE__ */ jsxs75("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
|
|
11194
11209
|
/* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
11195
11210
|
s.endpointsWired,
|
|
@@ -11202,36 +11217,36 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
11202
11217
|
" features complete"
|
|
11203
11218
|
] }),
|
|
11204
11219
|
onOpenSpec ? /* @__PURE__ */ jsxs75(Fragment23, { children: [
|
|
11205
|
-
/* @__PURE__ */
|
|
11220
|
+
/* @__PURE__ */ jsx85("span", { style: { flex: 1 } }),
|
|
11206
11221
|
/* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-soon-link", onClick: () => {
|
|
11207
11222
|
setOpen(false);
|
|
11208
11223
|
onOpenSpec();
|
|
11209
11224
|
}, children: [
|
|
11210
11225
|
"API spec ",
|
|
11211
|
-
/* @__PURE__ */
|
|
11226
|
+
/* @__PURE__ */ jsx85("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
11212
11227
|
] })
|
|
11213
11228
|
] }) : null
|
|
11214
11229
|
] })
|
|
11215
11230
|
] }),
|
|
11216
11231
|
/* @__PURE__ */ jsxs75("span", { className: "fd-mode-choice", children: [
|
|
11217
11232
|
/* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
|
|
11218
|
-
/* @__PURE__ */
|
|
11233
|
+
/* @__PURE__ */ jsx85("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
11219
11234
|
/* @__PURE__ */ jsxs75("span", { className: "fd-mode-opt-text", children: [
|
|
11220
|
-
/* @__PURE__ */
|
|
11221
|
-
/* @__PURE__ */
|
|
11235
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-mode-opt-title", children: "Live mode" }),
|
|
11236
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
|
|
11222
11237
|
] }),
|
|
11223
|
-
!test ? /* @__PURE__ */
|
|
11238
|
+
!test ? /* @__PURE__ */ jsx85("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
11224
11239
|
] }),
|
|
11225
11240
|
/* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
|
|
11226
|
-
/* @__PURE__ */
|
|
11241
|
+
/* @__PURE__ */ jsx85("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
11227
11242
|
/* @__PURE__ */ jsxs75("span", { className: "fd-mode-opt-text", children: [
|
|
11228
|
-
/* @__PURE__ */
|
|
11229
|
-
/* @__PURE__ */
|
|
11243
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-mode-opt-title", children: "Test mode" }),
|
|
11244
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
|
|
11230
11245
|
] }),
|
|
11231
|
-
test ? /* @__PURE__ */
|
|
11246
|
+
test ? /* @__PURE__ */ jsx85("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
11232
11247
|
] })
|
|
11233
11248
|
] }),
|
|
11234
|
-
test && renderLog ? /* @__PURE__ */
|
|
11249
|
+
test && renderLog ? /* @__PURE__ */ jsx85("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
|
|
11235
11250
|
] })
|
|
11236
11251
|
] });
|
|
11237
11252
|
}
|
|
@@ -11240,19 +11255,19 @@ function TestModeBar({ onExit }) {
|
|
|
11240
11255
|
if (mode2 !== "test") return null;
|
|
11241
11256
|
return /* @__PURE__ */ jsxs75("div", { className: "fd-testbar", role: "status", children: [
|
|
11242
11257
|
/* @__PURE__ */ jsxs75("span", { className: "fd-badge fd-badge-warning", children: [
|
|
11243
|
-
/* @__PURE__ */
|
|
11258
|
+
/* @__PURE__ */ jsx85("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
11244
11259
|
"Test mode"
|
|
11245
11260
|
] }),
|
|
11246
|
-
/* @__PURE__ */
|
|
11261
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
|
|
11247
11262
|
/* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
|
|
11248
|
-
/* @__PURE__ */
|
|
11263
|
+
/* @__PURE__ */ jsx85("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
11249
11264
|
" Back to live mode"
|
|
11250
11265
|
] })
|
|
11251
11266
|
] });
|
|
11252
11267
|
}
|
|
11253
11268
|
|
|
11254
11269
|
// src/components/planner/ChannelMeta.tsx
|
|
11255
|
-
import { jsx as
|
|
11270
|
+
import { jsx as jsx86, jsxs as jsxs76 } from "react/jsx-runtime";
|
|
11256
11271
|
var CHANNEL_WEIGHTS = {
|
|
11257
11272
|
"OOH": 50,
|
|
11258
11273
|
"DOOH": 50,
|
|
@@ -11305,7 +11320,7 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
11305
11320
|
const m = ChannelMeta(channel);
|
|
11306
11321
|
const wt = channelWeightOf(channel || "");
|
|
11307
11322
|
if (dot) {
|
|
11308
|
-
return /* @__PURE__ */
|
|
11323
|
+
return /* @__PURE__ */ jsx86("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
|
|
11309
11324
|
}
|
|
11310
11325
|
return /* @__PURE__ */ jsxs76(
|
|
11311
11326
|
"span",
|
|
@@ -11315,16 +11330,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
11315
11330
|
style: { "--chan": m.color },
|
|
11316
11331
|
...rest,
|
|
11317
11332
|
children: [
|
|
11318
|
-
/* @__PURE__ */
|
|
11319
|
-
showLabel ? /* @__PURE__ */
|
|
11320
|
-
weight ? /* @__PURE__ */
|
|
11333
|
+
/* @__PURE__ */ jsx86("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
|
|
11334
|
+
showLabel ? /* @__PURE__ */ jsx86("span", { className: "fd-chan-label", children: m.label }) : null,
|
|
11335
|
+
weight ? /* @__PURE__ */ jsx86("span", { className: "fd-chan-weight", children: wt || 0 }) : null
|
|
11321
11336
|
]
|
|
11322
11337
|
}
|
|
11323
11338
|
);
|
|
11324
11339
|
}
|
|
11325
11340
|
|
|
11326
11341
|
// src/components/planner/SaturationDistribution.tsx
|
|
11327
|
-
import { jsx as
|
|
11342
|
+
import { jsx as jsx87, jsxs as jsxs77 } from "react/jsx-runtime";
|
|
11328
11343
|
var BANDS2 = [
|
|
11329
11344
|
{ key: "weak", label: "Weak", n: 1, range: "< 50" },
|
|
11330
11345
|
{ key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
|
|
@@ -11336,7 +11351,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11336
11351
|
const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
|
|
11337
11352
|
const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
|
|
11338
11353
|
return /* @__PURE__ */ jsxs77("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
11339
|
-
/* @__PURE__ */
|
|
11354
|
+
/* @__PURE__ */ jsx87("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
|
|
11340
11355
|
const mark = "var(--csi-" + g.n + "-mark)";
|
|
11341
11356
|
const active = selectedBand === g.key;
|
|
11342
11357
|
return /* @__PURE__ */ jsxs77(
|
|
@@ -11346,13 +11361,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11346
11361
|
onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
|
|
11347
11362
|
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)" },
|
|
11348
11363
|
children: [
|
|
11349
|
-
/* @__PURE__ */
|
|
11364
|
+
/* @__PURE__ */ jsx87("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx87("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
|
|
11350
11365
|
// `overflow: hidden` + `white-space: nowrap` only clips once the span
|
|
11351
11366
|
// actually HAS a bounded width to clip against (see the grid/flex
|
|
11352
11367
|
// `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
|
|
11353
11368
|
// that clip readable instead of a hard cut mid-letter; the full name
|
|
11354
11369
|
// is still one hover away via `title`.
|
|
11355
|
-
/* @__PURE__ */
|
|
11370
|
+
/* @__PURE__ */ jsx87(
|
|
11356
11371
|
"span",
|
|
11357
11372
|
{
|
|
11358
11373
|
title: c.name + " \xB7 " + c.crp,
|
|
@@ -11363,11 +11378,11 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11363
11378
|
)
|
|
11364
11379
|
)) }),
|
|
11365
11380
|
/* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
|
|
11366
|
-
/* @__PURE__ */
|
|
11367
|
-
/* @__PURE__ */
|
|
11381
|
+
/* @__PURE__ */ jsx87("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
|
|
11382
|
+
/* @__PURE__ */ jsx87("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx87("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
|
|
11368
11383
|
] }),
|
|
11369
11384
|
/* @__PURE__ */ jsxs77("span", { className: "fd-stack", style: { gap: 1 }, children: [
|
|
11370
|
-
/* @__PURE__ */
|
|
11385
|
+
/* @__PURE__ */ jsx87("span", { className: "fd-label-lg", children: g.label }),
|
|
11371
11386
|
/* @__PURE__ */ jsxs77("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
|
|
11372
11387
|
"CRP ",
|
|
11373
11388
|
g.range
|
|
@@ -11379,7 +11394,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11379
11394
|
);
|
|
11380
11395
|
}) }),
|
|
11381
11396
|
floorBand ? /* @__PURE__ */ jsxs77("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: [
|
|
11382
|
-
/* @__PURE__ */
|
|
11397
|
+
/* @__PURE__ */ jsx87("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx87("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
|
|
11383
11398
|
/* @__PURE__ */ jsxs77("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
|
|
11384
11399
|
/* @__PURE__ */ jsxs77("strong", { style: { color: "var(--text)" }, children: [
|
|
11385
11400
|
"Plan floor ",
|
|
@@ -11392,8 +11407,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
11392
11407
|
}
|
|
11393
11408
|
|
|
11394
11409
|
// src/components/planner/MixGap.tsx
|
|
11395
|
-
import * as
|
|
11396
|
-
import { Fragment as Fragment24, jsx as
|
|
11410
|
+
import * as React61 from "react";
|
|
11411
|
+
import { Fragment as Fragment24, jsx as jsx88, jsxs as jsxs78 } from "react/jsx-runtime";
|
|
11397
11412
|
var MIX_GAP_LAYOUT = {
|
|
11398
11413
|
trackHeight: 30,
|
|
11399
11414
|
barHeight: 20,
|
|
@@ -11407,7 +11422,7 @@ function mixGapOffset(value, max) {
|
|
|
11407
11422
|
}
|
|
11408
11423
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
11409
11424
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
11410
|
-
const [hover, setHover] =
|
|
11425
|
+
const [hover, setHover] = React61.useState(null);
|
|
11411
11426
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
11412
11427
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
11413
11428
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
@@ -11415,11 +11430,11 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11415
11430
|
return /* @__PURE__ */ jsxs78("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
|
|
11416
11431
|
/* @__PURE__ */ jsxs78("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
|
|
11417
11432
|
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs78("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
11418
|
-
/* @__PURE__ */
|
|
11433
|
+
/* @__PURE__ */ jsx88("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
|
|
11419
11434
|
l
|
|
11420
11435
|
] }, l)),
|
|
11421
11436
|
/* @__PURE__ */ jsxs78("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
11422
|
-
/* @__PURE__ */
|
|
11437
|
+
/* @__PURE__ */ jsx88("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
|
|
11423
11438
|
"Target"
|
|
11424
11439
|
] })
|
|
11425
11440
|
] }),
|
|
@@ -11436,15 +11451,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11436
11451
|
onMouseEnter: () => setHover(r.channel),
|
|
11437
11452
|
onMouseLeave: () => setHover(null),
|
|
11438
11453
|
children: [
|
|
11439
|
-
/* @__PURE__ */
|
|
11440
|
-
/* @__PURE__ */
|
|
11441
|
-
/* @__PURE__ */
|
|
11442
|
-
/* @__PURE__ */
|
|
11454
|
+
/* @__PURE__ */ jsx88("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx88(ChannelTag, { channel: r.channel, size: "sm" }) }),
|
|
11455
|
+
/* @__PURE__ */ jsx88("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx88("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs78(Fragment24, { children: [
|
|
11456
|
+
/* @__PURE__ */ jsx88("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)" } }),
|
|
11457
|
+
/* @__PURE__ */ jsx88("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 } }),
|
|
11443
11458
|
/* @__PURE__ */ jsxs78("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: [
|
|
11444
11459
|
r.realized,
|
|
11445
11460
|
"%"
|
|
11446
11461
|
] }),
|
|
11447
|
-
hover === r.channel ? /* @__PURE__ */
|
|
11462
|
+
hover === r.channel ? /* @__PURE__ */ jsx88("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
|
|
11448
11463
|
] }) })
|
|
11449
11464
|
]
|
|
11450
11465
|
},
|
|
@@ -11455,7 +11470,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
11455
11470
|
}
|
|
11456
11471
|
|
|
11457
11472
|
// src/components/planner/ChannelContribution.tsx
|
|
11458
|
-
import { jsx as
|
|
11473
|
+
import { jsx as jsx89, jsxs as jsxs79 } from "react/jsx-runtime";
|
|
11459
11474
|
var money = (n) => "$" + Math.round(n).toLocaleString();
|
|
11460
11475
|
function ChannelContribution({
|
|
11461
11476
|
channels = [],
|
|
@@ -11472,8 +11487,8 @@ function ChannelContribution({
|
|
|
11472
11487
|
const pct = (v) => grand ? v / grand * 100 : 0;
|
|
11473
11488
|
const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
|
|
11474
11489
|
return /* @__PURE__ */ jsxs79("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
11475
|
-
loading ? /* @__PURE__ */
|
|
11476
|
-
channels.map((c) => /* @__PURE__ */
|
|
11490
|
+
loading ? /* @__PURE__ */ jsx89("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs79("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
|
|
11491
|
+
channels.map((c) => /* @__PURE__ */ jsx89(
|
|
11477
11492
|
"span",
|
|
11478
11493
|
{
|
|
11479
11494
|
title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
|
|
@@ -11482,7 +11497,7 @@ function ChannelContribution({
|
|
|
11482
11497
|
},
|
|
11483
11498
|
c.name
|
|
11484
11499
|
)),
|
|
11485
|
-
bonus > 0 ? /* @__PURE__ */
|
|
11500
|
+
bonus > 0 ? /* @__PURE__ */ jsx89(
|
|
11486
11501
|
"span",
|
|
11487
11502
|
{
|
|
11488
11503
|
title: "Surround-sound bonus +" + bonusPct + "%",
|
|
@@ -11492,17 +11507,17 @@ function ChannelContribution({
|
|
|
11492
11507
|
) : null
|
|
11493
11508
|
] }),
|
|
11494
11509
|
showTable ? /* @__PURE__ */ jsxs79("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
|
|
11495
|
-
/* @__PURE__ */
|
|
11496
|
-
/* @__PURE__ */
|
|
11497
|
-
/* @__PURE__ */
|
|
11498
|
-
/* @__PURE__ */
|
|
11499
|
-
/* @__PURE__ */
|
|
11500
|
-
/* @__PURE__ */
|
|
11510
|
+
/* @__PURE__ */ jsx89("thead", { children: /* @__PURE__ */ jsxs79("tr", { children: [
|
|
11511
|
+
/* @__PURE__ */ jsx89("th", { style: { width: "34%" }, children: "Channel" }),
|
|
11512
|
+
/* @__PURE__ */ jsx89("th", { style: { width: "16%" }, children: "Weight" }),
|
|
11513
|
+
/* @__PURE__ */ jsx89("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
|
|
11514
|
+
/* @__PURE__ */ jsx89("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
|
|
11515
|
+
/* @__PURE__ */ jsx89("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
|
|
11501
11516
|
] }) }),
|
|
11502
11517
|
/* @__PURE__ */ jsxs79("tbody", { children: [
|
|
11503
11518
|
channels.map((c) => /* @__PURE__ */ jsxs79("tr", { children: [
|
|
11504
|
-
/* @__PURE__ */
|
|
11505
|
-
/* @__PURE__ */
|
|
11519
|
+
/* @__PURE__ */ jsx89("td", { children: /* @__PURE__ */ jsx89(ChannelTag, { channel: c.name, size: "sm" }) }),
|
|
11520
|
+
/* @__PURE__ */ jsx89("td", { children: /* @__PURE__ */ jsx89(
|
|
11506
11521
|
"span",
|
|
11507
11522
|
{
|
|
11508
11523
|
className: "fd-badge fd-badge-neutral",
|
|
@@ -11511,38 +11526,38 @@ function ChannelContribution({
|
|
|
11511
11526
|
children: "weight " + (channelWeightOf(c.name) || 0)
|
|
11512
11527
|
}
|
|
11513
11528
|
) }),
|
|
11514
|
-
/* @__PURE__ */
|
|
11515
|
-
/* @__PURE__ */
|
|
11529
|
+
/* @__PURE__ */ jsx89("td", { className: "is-num", children: c.spend }),
|
|
11530
|
+
/* @__PURE__ */ jsx89("td", { className: "is-num", children: c.crp.toFixed(1) }),
|
|
11516
11531
|
/* @__PURE__ */ jsxs79("td", { className: "is-num", children: [
|
|
11517
11532
|
pct(c.crp).toFixed(0),
|
|
11518
11533
|
"%"
|
|
11519
11534
|
] })
|
|
11520
11535
|
] }, c.name)),
|
|
11521
11536
|
bonus > 0 ? /* @__PURE__ */ jsxs79("tr", { children: [
|
|
11522
|
-
/* @__PURE__ */
|
|
11523
|
-
/* @__PURE__ */
|
|
11537
|
+
/* @__PURE__ */ jsx89("td", { children: /* @__PURE__ */ jsxs79("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
|
|
11538
|
+
/* @__PURE__ */ jsx89("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" } }),
|
|
11524
11539
|
"Surround-sound bonus"
|
|
11525
11540
|
] }) }),
|
|
11526
|
-
/* @__PURE__ */
|
|
11541
|
+
/* @__PURE__ */ jsx89("td", { children: /* @__PURE__ */ jsxs79("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
|
|
11527
11542
|
"+",
|
|
11528
11543
|
bonusPct,
|
|
11529
11544
|
"% of +",
|
|
11530
11545
|
bonusMax,
|
|
11531
11546
|
"%"
|
|
11532
11547
|
] }) }),
|
|
11533
|
-
/* @__PURE__ */
|
|
11534
|
-
/* @__PURE__ */
|
|
11548
|
+
/* @__PURE__ */ jsx89("td", { className: "is-num fd-muted", children: "\u2014" }),
|
|
11549
|
+
/* @__PURE__ */ jsx89("td", { className: "is-num", children: bonus.toFixed(1) }),
|
|
11535
11550
|
/* @__PURE__ */ jsxs79("td", { className: "is-num", children: [
|
|
11536
11551
|
pct(bonus).toFixed(0),
|
|
11537
11552
|
"%"
|
|
11538
11553
|
] })
|
|
11539
11554
|
] }) : null,
|
|
11540
11555
|
/* @__PURE__ */ jsxs79("tr", { style: { background: "var(--surface-2)" }, children: [
|
|
11541
|
-
/* @__PURE__ */
|
|
11542
|
-
/* @__PURE__ */
|
|
11543
|
-
/* @__PURE__ */
|
|
11544
|
-
/* @__PURE__ */
|
|
11545
|
-
/* @__PURE__ */
|
|
11556
|
+
/* @__PURE__ */ jsx89("td", { style: { fontWeight: 700 }, children: "Campus total" }),
|
|
11557
|
+
/* @__PURE__ */ jsx89("td", {}),
|
|
11558
|
+
/* @__PURE__ */ jsx89("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
|
|
11559
|
+
/* @__PURE__ */ jsx89("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
|
|
11560
|
+
/* @__PURE__ */ jsx89("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
|
|
11546
11561
|
] })
|
|
11547
11562
|
] })
|
|
11548
11563
|
] }) : null
|
|
@@ -11550,8 +11565,8 @@ function ChannelContribution({
|
|
|
11550
11565
|
}
|
|
11551
11566
|
|
|
11552
11567
|
// src/components/planner/BudgetReallocator.tsx
|
|
11553
|
-
import * as
|
|
11554
|
-
import { Fragment as Fragment25, jsx as
|
|
11568
|
+
import * as React62 from "react";
|
|
11569
|
+
import { Fragment as Fragment25, jsx as jsx90, jsxs as jsxs80 } from "react/jsx-runtime";
|
|
11555
11570
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
11556
11571
|
function BudgetReallocator({
|
|
11557
11572
|
campus,
|
|
@@ -11566,8 +11581,8 @@ function BudgetReallocator({
|
|
|
11566
11581
|
onCancel,
|
|
11567
11582
|
className = ""
|
|
11568
11583
|
}) {
|
|
11569
|
-
const [draft, setDraft] =
|
|
11570
|
-
|
|
11584
|
+
const [draft, setDraft] = React62.useState(spend);
|
|
11585
|
+
React62.useEffect(() => setDraft(spend), [spend]);
|
|
11571
11586
|
const dirty = draft !== spend;
|
|
11572
11587
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
11573
11588
|
const nextBand = bandFor(nextCrp);
|
|
@@ -11582,10 +11597,10 @@ function BudgetReallocator({
|
|
|
11582
11597
|
setDraft(spend);
|
|
11583
11598
|
if (onCancel) onCancel();
|
|
11584
11599
|
};
|
|
11585
|
-
const trackRef =
|
|
11586
|
-
const chipRef =
|
|
11587
|
-
const [chipLeft, setChipLeft] =
|
|
11588
|
-
|
|
11600
|
+
const trackRef = React62.useRef(null);
|
|
11601
|
+
const chipRef = React62.useRef(null);
|
|
11602
|
+
const [chipLeft, setChipLeft] = React62.useState(null);
|
|
11603
|
+
React62.useLayoutEffect(() => {
|
|
11589
11604
|
const track = trackRef.current;
|
|
11590
11605
|
if (!dirty || !track) {
|
|
11591
11606
|
setChipLeft(null);
|
|
@@ -11613,16 +11628,16 @@ function BudgetReallocator({
|
|
|
11613
11628
|
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)" },
|
|
11614
11629
|
children: [
|
|
11615
11630
|
/* @__PURE__ */ jsxs80("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
11616
|
-
/* @__PURE__ */
|
|
11617
|
-
/* @__PURE__ */
|
|
11631
|
+
/* @__PURE__ */ jsx90("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
|
|
11632
|
+
/* @__PURE__ */ jsx90(CsiBadge, { band: nowBand, crp, size: "medium" }),
|
|
11618
11633
|
dirty ? /* @__PURE__ */ jsxs80(Fragment25, { children: [
|
|
11619
|
-
/* @__PURE__ */
|
|
11620
|
-
/* @__PURE__ */
|
|
11634
|
+
/* @__PURE__ */ jsx90("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
|
|
11635
|
+
/* @__PURE__ */ jsx90(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
|
|
11621
11636
|
] }) : null
|
|
11622
11637
|
] }),
|
|
11623
11638
|
/* @__PURE__ */ jsxs80("div", { className: "fd-slider", ref: trackRef, children: [
|
|
11624
|
-
/* @__PURE__ */
|
|
11625
|
-
dirty ? /* @__PURE__ */
|
|
11639
|
+
/* @__PURE__ */ jsx90("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
11640
|
+
dirty ? /* @__PURE__ */ jsx90(
|
|
11626
11641
|
"span",
|
|
11627
11642
|
{
|
|
11628
11643
|
ref: chipRef,
|
|
@@ -11634,7 +11649,7 @@ function BudgetReallocator({
|
|
|
11634
11649
|
children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
|
|
11635
11650
|
}
|
|
11636
11651
|
) : null,
|
|
11637
|
-
/* @__PURE__ */
|
|
11652
|
+
/* @__PURE__ */ jsx90(
|
|
11638
11653
|
"input",
|
|
11639
11654
|
{
|
|
11640
11655
|
type: "range",
|
|
@@ -11652,11 +11667,11 @@ function BudgetReallocator({
|
|
|
11652
11667
|
] }),
|
|
11653
11668
|
/* @__PURE__ */ jsxs80("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
11654
11669
|
/* @__PURE__ */ jsxs80("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
|
|
11655
|
-
/* @__PURE__ */
|
|
11656
|
-
/* @__PURE__ */
|
|
11670
|
+
/* @__PURE__ */ jsx90("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
|
|
11671
|
+
/* @__PURE__ */ jsx90("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
|
|
11657
11672
|
] }),
|
|
11658
|
-
/* @__PURE__ */
|
|
11659
|
-
/* @__PURE__ */
|
|
11673
|
+
/* @__PURE__ */ jsx90("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
|
|
11674
|
+
/* @__PURE__ */ jsx90(
|
|
11660
11675
|
"button",
|
|
11661
11676
|
{
|
|
11662
11677
|
type: "button",
|
|
@@ -11675,7 +11690,7 @@ function BudgetReallocator({
|
|
|
11675
11690
|
}
|
|
11676
11691
|
|
|
11677
11692
|
// src/components/planner/SurroundSound.tsx
|
|
11678
|
-
import { jsx as
|
|
11693
|
+
import { jsx as jsx91, jsxs as jsxs81 } from "react/jsx-runtime";
|
|
11679
11694
|
var CATEGORIES = [
|
|
11680
11695
|
{ key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
|
|
11681
11696
|
{ key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
|
|
@@ -11688,7 +11703,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
11688
11703
|
const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
|
|
11689
11704
|
const single = present.length <= 2;
|
|
11690
11705
|
return /* @__PURE__ */ jsxs81("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
|
|
11691
|
-
/* @__PURE__ */
|
|
11706
|
+
/* @__PURE__ */ jsx91("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
|
|
11692
11707
|
const on = present.includes(c.key);
|
|
11693
11708
|
return /* @__PURE__ */ jsxs81(
|
|
11694
11709
|
"span",
|
|
@@ -11696,8 +11711,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
11696
11711
|
title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
|
|
11697
11712
|
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)" },
|
|
11698
11713
|
children: [
|
|
11699
|
-
/* @__PURE__ */
|
|
11700
|
-
/* @__PURE__ */
|
|
11714
|
+
/* @__PURE__ */ jsx91("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
11715
|
+
/* @__PURE__ */ jsx91("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
|
|
11701
11716
|
]
|
|
11702
11717
|
},
|
|
11703
11718
|
c.key
|
|
@@ -11705,7 +11720,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
11705
11720
|
}) }),
|
|
11706
11721
|
/* @__PURE__ */ jsxs81("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
11707
11722
|
/* @__PURE__ */ jsxs81("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
11708
|
-
/* @__PURE__ */
|
|
11723
|
+
/* @__PURE__ */ jsx91("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
|
|
11709
11724
|
/* @__PURE__ */ jsxs81("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
|
|
11710
11725
|
"+",
|
|
11711
11726
|
bonusPct,
|
|
@@ -11714,7 +11729,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
11714
11729
|
"%"
|
|
11715
11730
|
] })
|
|
11716
11731
|
] }),
|
|
11717
|
-
/* @__PURE__ */
|
|
11732
|
+
/* @__PURE__ */ jsx91("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx91("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
|
|
11718
11733
|
/* @__PURE__ */ jsxs81("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
|
|
11719
11734
|
present.length,
|
|
11720
11735
|
" of 6 channel categories present.",
|
|
@@ -11727,7 +11742,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
11727
11742
|
}
|
|
11728
11743
|
|
|
11729
11744
|
// src/components/planner/Importance.tsx
|
|
11730
|
-
import { jsx as
|
|
11745
|
+
import { jsx as jsx92, jsxs as jsxs82 } from "react/jsx-runtime";
|
|
11731
11746
|
var IMPORTANCE_LEVELS = [
|
|
11732
11747
|
{ id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
|
|
11733
11748
|
{ id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
|
|
@@ -11765,16 +11780,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
|
|
|
11765
11780
|
title: lvl.label + " \u2014 " + lvl.description,
|
|
11766
11781
|
"aria-disabled": disabled ? "true" : void 0,
|
|
11767
11782
|
children: [
|
|
11768
|
-
/* @__PURE__ */
|
|
11769
|
-
showLabel ? lvl.label : /* @__PURE__ */
|
|
11783
|
+
/* @__PURE__ */ jsx92("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
|
|
11784
|
+
showLabel ? lvl.label : /* @__PURE__ */ jsx92("span", { className: "fd-sr", children: lvl.label })
|
|
11770
11785
|
]
|
|
11771
11786
|
}
|
|
11772
11787
|
);
|
|
11773
11788
|
}
|
|
11774
11789
|
|
|
11775
11790
|
// src/components/planner/PreferenceMeter.tsx
|
|
11776
|
-
import * as
|
|
11777
|
-
import { jsx as
|
|
11791
|
+
import * as React63 from "react";
|
|
11792
|
+
import { jsx as jsx93, jsxs as jsxs83 } from "react/jsx-runtime";
|
|
11778
11793
|
function preferenceScore(criteria) {
|
|
11779
11794
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
11780
11795
|
const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
|
|
@@ -11803,8 +11818,8 @@ function PreferenceMeter({
|
|
|
11803
11818
|
className = ""
|
|
11804
11819
|
}) {
|
|
11805
11820
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
11806
|
-
const segments =
|
|
11807
|
-
return /* @__PURE__ */
|
|
11821
|
+
const segments = React63.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
11822
|
+
return /* @__PURE__ */ jsx93(
|
|
11808
11823
|
ScoreMeter,
|
|
11809
11824
|
{
|
|
11810
11825
|
score: value,
|
|
@@ -11818,20 +11833,20 @@ function PreferenceMeter({
|
|
|
11818
11833
|
breakdownLabel: breakdownTitle,
|
|
11819
11834
|
breakdown: /* @__PURE__ */ jsxs83("div", { className: "fd-prefbreak", children: [
|
|
11820
11835
|
/* @__PURE__ */ jsxs83("div", { className: "fd-prefbreak-head", children: [
|
|
11821
|
-
/* @__PURE__ */
|
|
11822
|
-
/* @__PURE__ */
|
|
11836
|
+
/* @__PURE__ */ jsx93("span", { className: "fd-label-lg", children: breakdownTitle }),
|
|
11837
|
+
/* @__PURE__ */ jsx93("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
|
|
11823
11838
|
] }),
|
|
11824
|
-
/* @__PURE__ */
|
|
11839
|
+
/* @__PURE__ */ jsx93("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
|
|
11825
11840
|
const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
|
|
11826
11841
|
return /* @__PURE__ */ jsxs83("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
|
|
11827
|
-
/* @__PURE__ */
|
|
11842
|
+
/* @__PURE__ */ jsx93(ImportanceTag, { level: c.importance }),
|
|
11828
11843
|
/* @__PURE__ */ jsxs83("span", { className: "fd-prefbreak-text", children: [
|
|
11829
|
-
/* @__PURE__ */
|
|
11830
|
-
c.note ? /* @__PURE__ */
|
|
11844
|
+
/* @__PURE__ */ jsx93("span", { className: "fd-prefbreak-label", children: c.label }),
|
|
11845
|
+
c.note ? /* @__PURE__ */ jsx93("span", { className: "fd-prefbreak-note", children: c.note }) : null
|
|
11831
11846
|
] }),
|
|
11832
11847
|
/* @__PURE__ */ jsxs83("span", { className: "fd-prefbreak-val fd-tabular", children: [
|
|
11833
11848
|
Math.round(Number(c.earned) || 0),
|
|
11834
|
-
/* @__PURE__ */
|
|
11849
|
+
/* @__PURE__ */ jsx93("span", { className: "fd-prefbreak-sep", children: "/" }),
|
|
11835
11850
|
Math.round(c.weight)
|
|
11836
11851
|
] })
|
|
11837
11852
|
] }, c.id);
|
|
@@ -11842,10 +11857,10 @@ function PreferenceMeter({
|
|
|
11842
11857
|
}
|
|
11843
11858
|
|
|
11844
11859
|
// src/components/chat/AgentChatPanel.tsx
|
|
11845
|
-
import * as
|
|
11860
|
+
import * as React69 from "react";
|
|
11846
11861
|
|
|
11847
11862
|
// src/components/chat/chatEngine.ts
|
|
11848
|
-
import * as
|
|
11863
|
+
import * as React64 from "react";
|
|
11849
11864
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
11850
11865
|
var JOB_PENDING = ["queued", "running"];
|
|
11851
11866
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -11899,22 +11914,22 @@ function useChatEngine(opts) {
|
|
|
11899
11914
|
onClear,
|
|
11900
11915
|
onFeedback
|
|
11901
11916
|
} = opts || {};
|
|
11902
|
-
const [status, setStatus] =
|
|
11903
|
-
const [threadId, setThreadId] =
|
|
11904
|
-
const [messages, setMessages] =
|
|
11905
|
-
const [queue, setQueue] =
|
|
11906
|
-
const [fatal, setFatal] =
|
|
11907
|
-
const [busy, setBusy] =
|
|
11908
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
11909
|
-
const listRef =
|
|
11910
|
-
const queueRef =
|
|
11911
|
-
const busyRef =
|
|
11912
|
-
const stoppedRef =
|
|
11913
|
-
const abortRef =
|
|
11914
|
-
const serverCount =
|
|
11915
|
-
const threadRef =
|
|
11916
|
-
const mounted =
|
|
11917
|
-
|
|
11917
|
+
const [status, setStatus] = React64.useState("idle");
|
|
11918
|
+
const [threadId, setThreadId] = React64.useState(null);
|
|
11919
|
+
const [messages, setMessages] = React64.useState([]);
|
|
11920
|
+
const [queue, setQueue] = React64.useState([]);
|
|
11921
|
+
const [fatal, setFatal] = React64.useState(null);
|
|
11922
|
+
const [busy, setBusy] = React64.useState(false);
|
|
11923
|
+
const [turnStartedAt, setTurnStartedAt] = React64.useState(null);
|
|
11924
|
+
const listRef = React64.useRef([]);
|
|
11925
|
+
const queueRef = React64.useRef([]);
|
|
11926
|
+
const busyRef = React64.useRef(false);
|
|
11927
|
+
const stoppedRef = React64.useRef(false);
|
|
11928
|
+
const abortRef = React64.useRef(null);
|
|
11929
|
+
const serverCount = React64.useRef(0);
|
|
11930
|
+
const threadRef = React64.useRef(null);
|
|
11931
|
+
const mounted = React64.useRef(true);
|
|
11932
|
+
React64.useEffect(() => {
|
|
11918
11933
|
mounted.current = true;
|
|
11919
11934
|
return () => {
|
|
11920
11935
|
mounted.current = false;
|
|
@@ -11936,14 +11951,14 @@ function useChatEngine(opts) {
|
|
|
11936
11951
|
}
|
|
11937
11952
|
return false;
|
|
11938
11953
|
};
|
|
11939
|
-
const loadThread =
|
|
11954
|
+
const loadThread = React64.useCallback(async (id) => {
|
|
11940
11955
|
const data = await apiAdapter.getThread(id);
|
|
11941
11956
|
const list = [...data && data.messages || []];
|
|
11942
11957
|
serverCount.current = list.length;
|
|
11943
11958
|
commit(list);
|
|
11944
11959
|
return list;
|
|
11945
11960
|
}, [apiAdapter]);
|
|
11946
|
-
|
|
11961
|
+
React64.useEffect(() => {
|
|
11947
11962
|
if (!apiAdapter) {
|
|
11948
11963
|
setStatus("idle");
|
|
11949
11964
|
setFatal(null);
|
|
@@ -12156,7 +12171,7 @@ function useChatEngine(opts) {
|
|
|
12156
12171
|
await dispatchTurn(turn);
|
|
12157
12172
|
}
|
|
12158
12173
|
}
|
|
12159
|
-
const send =
|
|
12174
|
+
const send = React64.useCallback((text, attachments) => {
|
|
12160
12175
|
const body = (text || "").trim();
|
|
12161
12176
|
if (!body && !(attachments && attachments.length)) return;
|
|
12162
12177
|
if (status === "disconnected") return;
|
|
@@ -12166,7 +12181,7 @@ function useChatEngine(opts) {
|
|
|
12166
12181
|
stoppedRef.current = false;
|
|
12167
12182
|
drain();
|
|
12168
12183
|
}, [status]);
|
|
12169
|
-
const stop =
|
|
12184
|
+
const stop = React64.useCallback(() => {
|
|
12170
12185
|
stoppedRef.current = true;
|
|
12171
12186
|
const ac = abortRef.current;
|
|
12172
12187
|
if (ac) {
|
|
@@ -12185,11 +12200,11 @@ function useChatEngine(opts) {
|
|
|
12185
12200
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
12186
12201
|
}
|
|
12187
12202
|
}, [apiAdapter]);
|
|
12188
|
-
const removeQueued =
|
|
12203
|
+
const removeQueued = React64.useCallback((id) => {
|
|
12189
12204
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
12190
12205
|
setQueue(queueRef.current.slice());
|
|
12191
12206
|
}, []);
|
|
12192
|
-
const retry =
|
|
12207
|
+
const retry = React64.useCallback(() => {
|
|
12193
12208
|
const list = listRef.current;
|
|
12194
12209
|
let at = -1;
|
|
12195
12210
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -12205,19 +12220,19 @@ function useChatEngine(opts) {
|
|
|
12205
12220
|
setQueue(queueRef.current.slice());
|
|
12206
12221
|
drain();
|
|
12207
12222
|
}, []);
|
|
12208
|
-
const clear =
|
|
12223
|
+
const clear = React64.useCallback(() => {
|
|
12209
12224
|
commit([]);
|
|
12210
12225
|
serverCount.current = 0;
|
|
12211
12226
|
queueRef.current = [];
|
|
12212
12227
|
setQueue([]);
|
|
12213
12228
|
onClear && onClear();
|
|
12214
12229
|
}, [onClear]);
|
|
12215
|
-
const setFeedback =
|
|
12230
|
+
const setFeedback = React64.useCallback((id, value) => {
|
|
12216
12231
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
12217
12232
|
const msg = listRef.current.find((m) => m.id === id);
|
|
12218
12233
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
12219
12234
|
}, [onFeedback]);
|
|
12220
|
-
const reload =
|
|
12235
|
+
const reload = React64.useCallback(async () => {
|
|
12221
12236
|
if (!threadRef.current) return;
|
|
12222
12237
|
setStatus("loading");
|
|
12223
12238
|
try {
|
|
@@ -12255,11 +12270,11 @@ var ChatKit = {
|
|
|
12255
12270
|
};
|
|
12256
12271
|
|
|
12257
12272
|
// src/components/chat/ChatTranscript.tsx
|
|
12258
|
-
import * as
|
|
12273
|
+
import * as React66 from "react";
|
|
12259
12274
|
|
|
12260
12275
|
// src/components/chat/ChatTurn.tsx
|
|
12261
|
-
import * as
|
|
12262
|
-
import { jsx as
|
|
12276
|
+
import * as React65 from "react";
|
|
12277
|
+
import { jsx as jsx94, jsxs as jsxs84 } from "react/jsx-runtime";
|
|
12263
12278
|
function JsonView({ value }) {
|
|
12264
12279
|
let text;
|
|
12265
12280
|
try {
|
|
@@ -12267,7 +12282,7 @@ function JsonView({ value }) {
|
|
|
12267
12282
|
} catch (e) {
|
|
12268
12283
|
text = String(value);
|
|
12269
12284
|
}
|
|
12270
|
-
return /* @__PURE__ */
|
|
12285
|
+
return /* @__PURE__ */ jsx94(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
|
|
12271
12286
|
}
|
|
12272
12287
|
function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
12273
12288
|
if (!packet) return null;
|
|
@@ -12276,58 +12291,58 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
|
12276
12291
|
const title = s.heading || packet.type;
|
|
12277
12292
|
return /* @__PURE__ */ jsxs84("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
|
|
12278
12293
|
/* @__PURE__ */ jsxs84("header", { className: "fdc-packet-head", children: [
|
|
12279
|
-
/* @__PURE__ */
|
|
12280
|
-
/* @__PURE__ */
|
|
12281
|
-
packet.repaired ? /* @__PURE__ */
|
|
12282
|
-
invalid ? /* @__PURE__ */
|
|
12294
|
+
/* @__PURE__ */ jsx94("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
|
|
12295
|
+
/* @__PURE__ */ jsx94("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
|
|
12296
|
+
packet.repaired ? /* @__PURE__ */ jsx94("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
|
|
12297
|
+
invalid ? /* @__PURE__ */ jsx94("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
|
|
12283
12298
|
] }),
|
|
12284
12299
|
invalid ? /* @__PURE__ */ jsxs84("div", { className: "fdc-packet-alert", role: "alert", children: [
|
|
12285
|
-
/* @__PURE__ */
|
|
12286
|
-
/* @__PURE__ */
|
|
12287
|
-
] }) : /* @__PURE__ */
|
|
12300
|
+
/* @__PURE__ */ jsx94("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
12301
|
+
/* @__PURE__ */ jsx94("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
|
|
12302
|
+
] }) : /* @__PURE__ */ jsx94("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx94(JsonView, { value: packet.payload }) }),
|
|
12288
12303
|
!invalid && onApply ? /* @__PURE__ */ jsxs84("footer", { className: "fdc-packet-foot", children: [
|
|
12289
|
-
packet.repaired ? /* @__PURE__ */
|
|
12304
|
+
packet.repaired ? /* @__PURE__ */ jsx94("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx94("span", {}),
|
|
12290
12305
|
/* @__PURE__ */ jsxs84("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
|
|
12291
|
-
/* @__PURE__ */
|
|
12306
|
+
/* @__PURE__ */ jsx94("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
|
|
12292
12307
|
applied ? "Applied" : s.applyLabel || "Apply"
|
|
12293
12308
|
] })
|
|
12294
12309
|
] }) : null
|
|
12295
12310
|
] });
|
|
12296
12311
|
}
|
|
12297
12312
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
12298
|
-
const [open2, setOpen] =
|
|
12313
|
+
const [open2, setOpen] = React65.useState(defaultOpen);
|
|
12299
12314
|
if (!text) return null;
|
|
12300
12315
|
return /* @__PURE__ */ jsxs84("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
|
|
12301
12316
|
/* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
12302
|
-
/* @__PURE__ */
|
|
12303
|
-
/* @__PURE__ */
|
|
12317
|
+
/* @__PURE__ */ jsx94("i", { className: "ph ph-brain", "aria-hidden": "true" }),
|
|
12318
|
+
/* @__PURE__ */ jsx94("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
|
|
12304
12319
|
streaming ? /* @__PURE__ */ jsxs84("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
12305
|
-
/* @__PURE__ */
|
|
12306
|
-
/* @__PURE__ */
|
|
12307
|
-
/* @__PURE__ */
|
|
12320
|
+
/* @__PURE__ */ jsx94("span", {}),
|
|
12321
|
+
/* @__PURE__ */ jsx94("span", {}),
|
|
12322
|
+
/* @__PURE__ */ jsx94("span", {})
|
|
12308
12323
|
] }) : null,
|
|
12309
|
-
/* @__PURE__ */
|
|
12324
|
+
/* @__PURE__ */ jsx94("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
|
|
12310
12325
|
] }),
|
|
12311
|
-
open2 ? /* @__PURE__ */
|
|
12326
|
+
open2 ? /* @__PURE__ */ jsx94("div", { className: "fdc-think-body", children: text }) : null
|
|
12312
12327
|
] });
|
|
12313
12328
|
}
|
|
12314
12329
|
function Citations({ items = [], onOpen }) {
|
|
12315
|
-
const [open2, setOpen] =
|
|
12330
|
+
const [open2, setOpen] = React65.useState(false);
|
|
12316
12331
|
if (!items.length) return null;
|
|
12317
12332
|
return /* @__PURE__ */ jsxs84("div", { className: "fdc-cites", children: [
|
|
12318
12333
|
/* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
|
|
12319
|
-
/* @__PURE__ */
|
|
12334
|
+
/* @__PURE__ */ jsx94("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
|
|
12320
12335
|
/* @__PURE__ */ jsxs84("span", { children: [
|
|
12321
12336
|
items.length,
|
|
12322
12337
|
" source",
|
|
12323
12338
|
items.length === 1 ? "" : "s"
|
|
12324
12339
|
] }),
|
|
12325
|
-
/* @__PURE__ */
|
|
12340
|
+
/* @__PURE__ */ jsx94("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
|
|
12326
12341
|
] }),
|
|
12327
|
-
open2 ? /* @__PURE__ */
|
|
12328
|
-
/* @__PURE__ */
|
|
12329
|
-
c.url ? /* @__PURE__ */
|
|
12330
|
-
c.detail ? /* @__PURE__ */
|
|
12342
|
+
open2 ? /* @__PURE__ */ jsx94("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs84("li", { children: [
|
|
12343
|
+
/* @__PURE__ */ jsx94("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
|
|
12344
|
+
c.url ? /* @__PURE__ */ jsx94("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx94("span", { children: c.title || "Source" }),
|
|
12345
|
+
c.detail ? /* @__PURE__ */ jsx94("span", { className: "fdc-cite-detail", children: c.detail }) : null
|
|
12331
12346
|
] }, c.id || i)) }) : null
|
|
12332
12347
|
] });
|
|
12333
12348
|
}
|
|
@@ -12338,29 +12353,29 @@ function clampText(text, max) {
|
|
|
12338
12353
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
12339
12354
|
}
|
|
12340
12355
|
function MessageBody({ message: m, ctx }) {
|
|
12341
|
-
const [expanded, setExpanded] =
|
|
12356
|
+
const [expanded, setExpanded] = React65.useState(false);
|
|
12342
12357
|
const isUser = m.role === "user";
|
|
12343
12358
|
const raw = m.text || "";
|
|
12344
12359
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
12345
12360
|
const body = clamped != null ? clamped : raw;
|
|
12346
12361
|
const showMd = ctx.markdown && !isUser;
|
|
12347
12362
|
return /* @__PURE__ */ jsxs84("div", { className: "fdc-body", children: [
|
|
12348
|
-
m.thinking && ctx.showThinking ? /* @__PURE__ */
|
|
12349
|
-
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */
|
|
12363
|
+
m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx94(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
|
|
12364
|
+
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx94(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
|
|
12350
12365
|
body ? /* @__PURE__ */ jsxs84("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
|
|
12351
|
-
showMd ? /* @__PURE__ */
|
|
12352
|
-
m.streaming ? /* @__PURE__ */
|
|
12366
|
+
showMd ? /* @__PURE__ */ jsx94(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx94("div", { className: "fdc-plain", children: body }),
|
|
12367
|
+
m.streaming ? /* @__PURE__ */ jsx94("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
|
|
12353
12368
|
] }) : null,
|
|
12354
12369
|
clamped != null ? /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
|
|
12355
|
-
/* @__PURE__ */
|
|
12370
|
+
/* @__PURE__ */ jsx94("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
|
|
12356
12371
|
"Show more",
|
|
12357
|
-
/* @__PURE__ */
|
|
12372
|
+
/* @__PURE__ */ jsx94("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
|
|
12358
12373
|
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
|
|
12359
|
-
/* @__PURE__ */
|
|
12374
|
+
/* @__PURE__ */ jsx94("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
|
|
12360
12375
|
"Show less"
|
|
12361
12376
|
] }) : null,
|
|
12362
|
-
m.attachments && m.attachments.length ? /* @__PURE__ */
|
|
12363
|
-
m.packet ? /* @__PURE__ */
|
|
12377
|
+
m.attachments && m.attachments.length ? /* @__PURE__ */ jsx94(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
|
|
12378
|
+
m.packet ? /* @__PURE__ */ jsx94(
|
|
12364
12379
|
PacketCard,
|
|
12365
12380
|
{
|
|
12366
12381
|
packet: m.packet,
|
|
@@ -12370,12 +12385,12 @@ function MessageBody({ message: m, ctx }) {
|
|
|
12370
12385
|
applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
|
|
12371
12386
|
}
|
|
12372
12387
|
) : null,
|
|
12373
|
-
m.citations && m.citations.length ? /* @__PURE__ */
|
|
12388
|
+
m.citations && m.citations.length ? /* @__PURE__ */ jsx94(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
|
|
12374
12389
|
m.working ? /* @__PURE__ */ jsxs84("div", { className: "fdc-working", role: "status", children: [
|
|
12375
12390
|
/* @__PURE__ */ jsxs84("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
12376
|
-
/* @__PURE__ */
|
|
12377
|
-
/* @__PURE__ */
|
|
12378
|
-
/* @__PURE__ */
|
|
12391
|
+
/* @__PURE__ */ jsx94("span", {}),
|
|
12392
|
+
/* @__PURE__ */ jsx94("span", {}),
|
|
12393
|
+
/* @__PURE__ */ jsx94("span", {})
|
|
12379
12394
|
] }),
|
|
12380
12395
|
/* @__PURE__ */ jsxs84("span", { className: "fdc-working-label", children: [
|
|
12381
12396
|
m.resumed ? "Resuming" : "Working",
|
|
@@ -12388,17 +12403,17 @@ function MessageBody({ message: m, ctx }) {
|
|
|
12388
12403
|
m.job.detail
|
|
12389
12404
|
] }) : null
|
|
12390
12405
|
] }),
|
|
12391
|
-
m.jobId ? /* @__PURE__ */
|
|
12406
|
+
m.jobId ? /* @__PURE__ */ jsx94("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
|
|
12392
12407
|
] }) : null,
|
|
12393
12408
|
m.stopped ? /* @__PURE__ */ jsxs84("div", { className: "fdc-stopped", children: [
|
|
12394
|
-
/* @__PURE__ */
|
|
12409
|
+
/* @__PURE__ */ jsx94("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
12395
12410
|
"Stopped"
|
|
12396
12411
|
] }) : null,
|
|
12397
12412
|
m.error ? /* @__PURE__ */ jsxs84("div", { className: "fdc-error", role: "alert", children: [
|
|
12398
|
-
/* @__PURE__ */
|
|
12399
|
-
/* @__PURE__ */
|
|
12413
|
+
/* @__PURE__ */ jsx94("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
12414
|
+
/* @__PURE__ */ jsx94("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
|
|
12400
12415
|
m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
|
|
12401
|
-
/* @__PURE__ */
|
|
12416
|
+
/* @__PURE__ */ jsx94("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
12402
12417
|
"Retry"
|
|
12403
12418
|
] }) : null
|
|
12404
12419
|
] }) : null
|
|
@@ -12413,14 +12428,14 @@ function RunActions({ group, ctx }) {
|
|
|
12413
12428
|
if (!ctx.messageActions) return null;
|
|
12414
12429
|
return /* @__PURE__ */ jsxs84("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
|
|
12415
12430
|
/* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
|
|
12416
|
-
/* @__PURE__ */
|
|
12417
|
-
/* @__PURE__ */
|
|
12431
|
+
/* @__PURE__ */ jsx94("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
|
|
12432
|
+
/* @__PURE__ */ jsx94("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
|
|
12418
12433
|
] }),
|
|
12419
|
-
isAssistant && ctx.onRetry ? /* @__PURE__ */
|
|
12420
|
-
group.role === "user" && ctx.onEdit ? /* @__PURE__ */
|
|
12421
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs84(
|
|
12422
|
-
/* @__PURE__ */
|
|
12423
|
-
/* @__PURE__ */
|
|
12434
|
+
isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx94("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx94("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
12435
|
+
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx94("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx94("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
12436
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs84(React65.Fragment, { children: [
|
|
12437
|
+
/* @__PURE__ */ jsx94("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__ */ jsx94("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
12438
|
+
/* @__PURE__ */ jsx94("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__ */ jsx94("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
12424
12439
|
] }) : null,
|
|
12425
12440
|
ctx.extraActions ? ctx.extraActions(group) : null
|
|
12426
12441
|
] });
|
|
@@ -12432,20 +12447,20 @@ function ChatTurn({ group, ctx }) {
|
|
|
12432
12447
|
const stamp = group.messages[0].timestamp;
|
|
12433
12448
|
return /* @__PURE__ */ jsxs84("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
|
|
12434
12449
|
/* @__PURE__ */ jsxs84("div", { className: "fdc-turn-head", children: [
|
|
12435
|
-
ctx.showAvatars ? /* @__PURE__ */
|
|
12436
|
-
/* @__PURE__ */
|
|
12437
|
-
stamp ? /* @__PURE__ */
|
|
12438
|
-
group.messages.some((m) => m.model) ? /* @__PURE__ */
|
|
12450
|
+
ctx.showAvatars ? /* @__PURE__ */ jsx94("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx94("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx94("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx94("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
|
|
12451
|
+
/* @__PURE__ */ jsx94("span", { className: "fdc-who", children: name }),
|
|
12452
|
+
stamp ? /* @__PURE__ */ jsx94(RelativeTime, { className: "fdc-when", value: stamp }) : null,
|
|
12453
|
+
group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx94("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
|
|
12439
12454
|
] }),
|
|
12440
12455
|
/* @__PURE__ */ jsxs84("div", { className: "fdc-turn-body", children: [
|
|
12441
|
-
group.messages.map((m) => /* @__PURE__ */
|
|
12442
|
-
/* @__PURE__ */
|
|
12456
|
+
group.messages.map((m) => /* @__PURE__ */ jsx94("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx94(MessageBody, { message: m, ctx }) }, m.id)),
|
|
12457
|
+
/* @__PURE__ */ jsx94(RunActions, { group, ctx })
|
|
12443
12458
|
] })
|
|
12444
12459
|
] });
|
|
12445
12460
|
}
|
|
12446
12461
|
|
|
12447
12462
|
// src/components/chat/ChatTranscript.tsx
|
|
12448
|
-
import { jsx as
|
|
12463
|
+
import { jsx as jsx95, jsxs as jsxs85 } from "react/jsx-runtime";
|
|
12449
12464
|
var GROUP_WINDOW = 6e4;
|
|
12450
12465
|
var STICK_PX = 100;
|
|
12451
12466
|
function groupMessages(list) {
|
|
@@ -12478,25 +12493,25 @@ function dayLabel(key) {
|
|
|
12478
12493
|
}
|
|
12479
12494
|
function Suggestions({ items = [], onPick }) {
|
|
12480
12495
|
if (!items.length) return null;
|
|
12481
|
-
return /* @__PURE__ */
|
|
12496
|
+
return /* @__PURE__ */ jsx95("div", { className: "fdc-suggest", children: items.map((s, i) => {
|
|
12482
12497
|
const it = typeof s === "string" ? { label: s, text: s } : s;
|
|
12483
12498
|
return /* @__PURE__ */ jsxs85("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
|
|
12484
|
-
it.icon ? /* @__PURE__ */
|
|
12499
|
+
it.icon ? /* @__PURE__ */ jsx95("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
|
|
12485
12500
|
/* @__PURE__ */ jsxs85("span", { className: "fdc-suggest-text", children: [
|
|
12486
|
-
/* @__PURE__ */
|
|
12487
|
-
it.description ? /* @__PURE__ */
|
|
12501
|
+
/* @__PURE__ */ jsx95("span", { className: "fdc-suggest-label", children: it.label }),
|
|
12502
|
+
it.description ? /* @__PURE__ */ jsx95("span", { className: "fdc-suggest-desc", children: it.description }) : null
|
|
12488
12503
|
] }),
|
|
12489
|
-
/* @__PURE__ */
|
|
12504
|
+
/* @__PURE__ */ jsx95("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
|
|
12490
12505
|
] }, it.id || i);
|
|
12491
12506
|
}) });
|
|
12492
12507
|
}
|
|
12493
12508
|
function LoadingTurns() {
|
|
12494
|
-
return /* @__PURE__ */
|
|
12495
|
-
/* @__PURE__ */
|
|
12509
|
+
return /* @__PURE__ */ jsx95("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs85("div", { className: "fdc-skel-turn", children: [
|
|
12510
|
+
/* @__PURE__ */ jsx95("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
|
|
12496
12511
|
/* @__PURE__ */ jsxs85("div", { className: "fdc-skel-lines", children: [
|
|
12497
|
-
/* @__PURE__ */
|
|
12498
|
-
/* @__PURE__ */
|
|
12499
|
-
/* @__PURE__ */
|
|
12512
|
+
/* @__PURE__ */ jsx95("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
|
|
12513
|
+
/* @__PURE__ */ jsx95("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
|
|
12514
|
+
/* @__PURE__ */ jsx95("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
|
|
12500
12515
|
] })
|
|
12501
12516
|
] }, i)) });
|
|
12502
12517
|
}
|
|
@@ -12513,10 +12528,10 @@ function ChatTranscript({
|
|
|
12513
12528
|
renderEmpty,
|
|
12514
12529
|
className = ""
|
|
12515
12530
|
}) {
|
|
12516
|
-
const scroller =
|
|
12517
|
-
const stick =
|
|
12518
|
-
const [pill, setPill] =
|
|
12519
|
-
const seen =
|
|
12531
|
+
const scroller = React66.useRef(null);
|
|
12532
|
+
const stick = React66.useRef(true);
|
|
12533
|
+
const [pill, setPill] = React66.useState(0);
|
|
12534
|
+
const seen = React66.useRef(0);
|
|
12520
12535
|
const toBottom = (smooth) => {
|
|
12521
12536
|
const el = scroller.current;
|
|
12522
12537
|
if (!el) return;
|
|
@@ -12535,7 +12550,7 @@ function ChatTranscript({
|
|
|
12535
12550
|
seen.current = messages.length;
|
|
12536
12551
|
}
|
|
12537
12552
|
};
|
|
12538
|
-
|
|
12553
|
+
React66.useLayoutEffect(() => {
|
|
12539
12554
|
const el = scroller.current;
|
|
12540
12555
|
if (!el) return;
|
|
12541
12556
|
if (stick.current) {
|
|
@@ -12543,7 +12558,7 @@ function ChatTranscript({
|
|
|
12543
12558
|
seen.current = messages.length;
|
|
12544
12559
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
12545
12560
|
}, [messages]);
|
|
12546
|
-
|
|
12561
|
+
React66.useEffect(() => {
|
|
12547
12562
|
const el = scroller.current;
|
|
12548
12563
|
const inner = el && el.firstChild;
|
|
12549
12564
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -12553,38 +12568,38 @@ function ChatTranscript({
|
|
|
12553
12568
|
ro.observe(inner);
|
|
12554
12569
|
return () => ro.disconnect();
|
|
12555
12570
|
}, []);
|
|
12556
|
-
const groups =
|
|
12571
|
+
const groups = React66.useMemo(() => groupMessages(messages), [messages]);
|
|
12557
12572
|
const empty = !messages.length && status === "ready";
|
|
12558
12573
|
return /* @__PURE__ */ jsxs85("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
12559
12574
|
/* @__PURE__ */ jsxs85("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
12560
|
-
status === "loading" || status === "resolving" ? /* @__PURE__ */
|
|
12575
|
+
status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx95(LoadingTurns, {}) : null,
|
|
12561
12576
|
status === "disconnected" ? /* @__PURE__ */ jsxs85("div", { className: "fdc-dead", children: [
|
|
12562
|
-
/* @__PURE__ */
|
|
12563
|
-
/* @__PURE__ */
|
|
12564
|
-
/* @__PURE__ */
|
|
12577
|
+
/* @__PURE__ */ jsx95("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
|
|
12578
|
+
/* @__PURE__ */ jsx95("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
|
|
12579
|
+
/* @__PURE__ */ jsx95("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." }),
|
|
12565
12580
|
ctx.onReconnect ? /* @__PURE__ */ jsxs85("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
|
|
12566
|
-
/* @__PURE__ */
|
|
12581
|
+
/* @__PURE__ */ jsx95("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
12567
12582
|
"Try again"
|
|
12568
12583
|
] }) : null
|
|
12569
12584
|
] }) : null,
|
|
12570
12585
|
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs85("div", { className: "fdc-empty", children: [
|
|
12571
|
-
/* @__PURE__ */
|
|
12572
|
-
/* @__PURE__ */
|
|
12573
|
-
emptyDescription ? /* @__PURE__ */
|
|
12574
|
-
/* @__PURE__ */
|
|
12586
|
+
/* @__PURE__ */ jsx95("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
|
|
12587
|
+
/* @__PURE__ */ jsx95("h3", { className: "fdc-empty-title", children: emptyTitle }),
|
|
12588
|
+
emptyDescription ? /* @__PURE__ */ jsx95("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
|
|
12589
|
+
/* @__PURE__ */ jsx95(Suggestions, { items: suggestions, onPick })
|
|
12575
12590
|
] }) : null,
|
|
12576
12591
|
groups.map((g, i) => {
|
|
12577
12592
|
const prev = groups[i - 1];
|
|
12578
12593
|
const k = dayKey(g.messages[0].timestamp);
|
|
12579
12594
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
12580
|
-
return /* @__PURE__ */ jsxs85(
|
|
12581
|
-
showDay ? /* @__PURE__ */
|
|
12582
|
-
/* @__PURE__ */
|
|
12595
|
+
return /* @__PURE__ */ jsxs85(React66.Fragment, { children: [
|
|
12596
|
+
showDay ? /* @__PURE__ */ jsx95("div", { className: "fdc-day", children: /* @__PURE__ */ jsx95("span", { children: dayLabel(k) }) }) : null,
|
|
12597
|
+
/* @__PURE__ */ jsx95(ChatTurn, { group: g, ctx })
|
|
12583
12598
|
] }, g.key || i);
|
|
12584
12599
|
})
|
|
12585
12600
|
] }),
|
|
12586
12601
|
pill ? /* @__PURE__ */ jsxs85("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
|
|
12587
|
-
/* @__PURE__ */
|
|
12602
|
+
/* @__PURE__ */ jsx95("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
|
|
12588
12603
|
pill,
|
|
12589
12604
|
" new message",
|
|
12590
12605
|
pill === 1 ? "" : "s"
|
|
@@ -12594,8 +12609,8 @@ function ChatTranscript({
|
|
|
12594
12609
|
var TranscriptKit = { groupMessages };
|
|
12595
12610
|
|
|
12596
12611
|
// src/components/chat/ChatComposer.tsx
|
|
12597
|
-
import * as
|
|
12598
|
-
import { jsx as
|
|
12612
|
+
import * as React67 from "react";
|
|
12613
|
+
import { jsx as jsx96, jsxs as jsxs86 } from "react/jsx-runtime";
|
|
12599
12614
|
function ChatComposer({
|
|
12600
12615
|
onSubmit,
|
|
12601
12616
|
onStop,
|
|
@@ -12622,17 +12637,17 @@ function ChatComposer({
|
|
|
12622
12637
|
onReject,
|
|
12623
12638
|
onOpenAttachment
|
|
12624
12639
|
}) {
|
|
12625
|
-
const [text, setText] =
|
|
12626
|
-
const [trigger, setTrigger] =
|
|
12627
|
-
const [mentionItems, setMentionItems] =
|
|
12628
|
-
const [listening, setListening] =
|
|
12629
|
-
const [notice, setNotice] =
|
|
12630
|
-
const editor =
|
|
12631
|
-
const wrap =
|
|
12632
|
-
const stopVoice =
|
|
12640
|
+
const [text, setText] = React67.useState(draft || "");
|
|
12641
|
+
const [trigger, setTrigger] = React67.useState(null);
|
|
12642
|
+
const [mentionItems, setMentionItems] = React67.useState([]);
|
|
12643
|
+
const [listening, setListening] = React67.useState(false);
|
|
12644
|
+
const [notice, setNotice] = React67.useState(null);
|
|
12645
|
+
const editor = React67.useRef(null);
|
|
12646
|
+
const wrap = React67.useRef(null);
|
|
12647
|
+
const stopVoice = React67.useRef(null);
|
|
12633
12648
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
12634
12649
|
} });
|
|
12635
|
-
|
|
12650
|
+
React67.useEffect(() => {
|
|
12636
12651
|
if (draft != null && draft !== text) setText(draft);
|
|
12637
12652
|
}, [draft]);
|
|
12638
12653
|
const change = (v) => {
|
|
@@ -12668,7 +12683,7 @@ function ChatComposer({
|
|
|
12668
12683
|
e.preventDefault();
|
|
12669
12684
|
staged.add(found.files);
|
|
12670
12685
|
};
|
|
12671
|
-
|
|
12686
|
+
React67.useEffect(() => {
|
|
12672
12687
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
12673
12688
|
setMentionItems([]);
|
|
12674
12689
|
return;
|
|
@@ -12686,7 +12701,7 @@ function ChatComposer({
|
|
|
12686
12701
|
const q = (trigger.query || "").toLowerCase();
|
|
12687
12702
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
12688
12703
|
}, [trigger, mentionSources]);
|
|
12689
|
-
const slashItems =
|
|
12704
|
+
const slashItems = React67.useMemo(() => {
|
|
12690
12705
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
12691
12706
|
const q = (trigger.query || "").toLowerCase();
|
|
12692
12707
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -12700,7 +12715,7 @@ function ChatComposer({
|
|
|
12700
12715
|
description: it.description,
|
|
12701
12716
|
icon: it.icon,
|
|
12702
12717
|
meta: mention.meta,
|
|
12703
|
-
shortcut: slash.shortcut ? /* @__PURE__ */
|
|
12718
|
+
shortcut: slash.shortcut ? /* @__PURE__ */ jsx96(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
|
|
12704
12719
|
onSelect: () => {
|
|
12705
12720
|
const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
|
|
12706
12721
|
editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
|
|
@@ -12760,13 +12775,13 @@ function ChatComposer({
|
|
|
12760
12775
|
};
|
|
12761
12776
|
};
|
|
12762
12777
|
return /* @__PURE__ */ jsxs86("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
|
|
12763
|
-
queue.length ? /* @__PURE__ */
|
|
12764
|
-
/* @__PURE__ */
|
|
12765
|
-
/* @__PURE__ */
|
|
12766
|
-
onRemoveQueued ? /* @__PURE__ */
|
|
12778
|
+
queue.length ? /* @__PURE__ */ jsx96("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs86("div", { className: "fdc-queue-row", children: [
|
|
12779
|
+
/* @__PURE__ */ jsx96("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
|
|
12780
|
+
/* @__PURE__ */ jsx96("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)" : "") }),
|
|
12781
|
+
onRemoveQueued ? /* @__PURE__ */ jsx96("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx96("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
12767
12782
|
] }, q.id)) }) : null,
|
|
12768
12783
|
sessionBar,
|
|
12769
|
-
/* @__PURE__ */
|
|
12784
|
+
/* @__PURE__ */ jsx96(
|
|
12770
12785
|
Dropzone,
|
|
12771
12786
|
{
|
|
12772
12787
|
className: "fdc-field",
|
|
@@ -12781,8 +12796,8 @@ function ChatComposer({
|
|
|
12781
12796
|
label: "Drop to attach",
|
|
12782
12797
|
hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
|
|
12783
12798
|
children: /* @__PURE__ */ jsxs86("div", { ref: wrap, className: "fdc-field-inner", children: [
|
|
12784
|
-
staged.items.length ? /* @__PURE__ */
|
|
12785
|
-
/* @__PURE__ */
|
|
12799
|
+
staged.items.length ? /* @__PURE__ */ jsx96("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx96(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
|
|
12800
|
+
/* @__PURE__ */ jsx96(
|
|
12786
12801
|
MarkdownEditor,
|
|
12787
12802
|
{
|
|
12788
12803
|
ref: editor,
|
|
@@ -12802,32 +12817,32 @@ function ChatComposer({
|
|
|
12802
12817
|
}
|
|
12803
12818
|
),
|
|
12804
12819
|
/* @__PURE__ */ jsxs86("div", { className: "fdc-tools", children: [
|
|
12805
|
-
fileUploadHandler ? /* @__PURE__ */
|
|
12806
|
-
voiceHandler ? /* @__PURE__ */
|
|
12820
|
+
fileUploadHandler ? /* @__PURE__ */ jsx96(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
|
|
12821
|
+
voiceHandler ? /* @__PURE__ */ jsx96("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx96("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
|
|
12807
12822
|
toolbarExtras,
|
|
12808
|
-
/* @__PURE__ */
|
|
12823
|
+
/* @__PURE__ */ jsx96("span", { className: "fdc-tools-gap" }),
|
|
12809
12824
|
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs86("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
|
|
12810
12825
|
text.length,
|
|
12811
12826
|
"/",
|
|
12812
12827
|
maxLength
|
|
12813
12828
|
] }) : null,
|
|
12814
12829
|
busy ? /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
|
|
12815
|
-
/* @__PURE__ */
|
|
12816
|
-
/* @__PURE__ */
|
|
12830
|
+
/* @__PURE__ */ jsx96("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
12831
|
+
/* @__PURE__ */ jsx96("span", { children: "Stop" })
|
|
12817
12832
|
] }) : /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
|
|
12818
|
-
/* @__PURE__ */
|
|
12819
|
-
/* @__PURE__ */
|
|
12833
|
+
/* @__PURE__ */ jsx96("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
|
|
12834
|
+
/* @__PURE__ */ jsx96("span", { className: "fdc-send-label", children: "Send" })
|
|
12820
12835
|
] })
|
|
12821
12836
|
] })
|
|
12822
12837
|
] })
|
|
12823
12838
|
}
|
|
12824
12839
|
),
|
|
12825
12840
|
notice ? /* @__PURE__ */ jsxs86("div", { className: "fdc-notice", role: "status", children: [
|
|
12826
|
-
/* @__PURE__ */
|
|
12841
|
+
/* @__PURE__ */ jsx96("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
12827
12842
|
notice
|
|
12828
12843
|
] }) : null,
|
|
12829
|
-
hint && !notice ? /* @__PURE__ */
|
|
12830
|
-
/* @__PURE__ */
|
|
12844
|
+
hint && !notice ? /* @__PURE__ */ jsx96("div", { className: "fdc-hint", children: hint }) : null,
|
|
12845
|
+
/* @__PURE__ */ jsx96(
|
|
12831
12846
|
Popover,
|
|
12832
12847
|
{
|
|
12833
12848
|
open: menuOpen,
|
|
@@ -12841,12 +12856,12 @@ function ChatComposer({
|
|
|
12841
12856
|
returnFocus: false,
|
|
12842
12857
|
closeOnOutside: true,
|
|
12843
12858
|
label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
|
|
12844
|
-
children: /* @__PURE__ */
|
|
12859
|
+
children: /* @__PURE__ */ jsx96(
|
|
12845
12860
|
Menu,
|
|
12846
12861
|
{
|
|
12847
12862
|
items: menuItems,
|
|
12848
12863
|
autoFocus: false,
|
|
12849
|
-
header: /* @__PURE__ */
|
|
12864
|
+
header: /* @__PURE__ */ jsx96("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
|
|
12850
12865
|
onClose: () => setTrigger(null)
|
|
12851
12866
|
}
|
|
12852
12867
|
)
|
|
@@ -12856,12 +12871,12 @@ function ChatComposer({
|
|
|
12856
12871
|
}
|
|
12857
12872
|
|
|
12858
12873
|
// src/components/chat/ChatSessionBar.tsx
|
|
12859
|
-
import * as
|
|
12860
|
-
import { jsx as
|
|
12874
|
+
import * as React68 from "react";
|
|
12875
|
+
import { jsx as jsx97, jsxs as jsxs87 } from "react/jsx-runtime";
|
|
12861
12876
|
var compact2 = meterFormats.compact;
|
|
12862
12877
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
12863
|
-
const [open2, setOpen] =
|
|
12864
|
-
const anchor =
|
|
12878
|
+
const [open2, setOpen] = React68.useState(false);
|
|
12879
|
+
const anchor = React68.useRef(null);
|
|
12865
12880
|
const stats = sessionStats || null;
|
|
12866
12881
|
const cu = contextUsage || null;
|
|
12867
12882
|
const limits = usageLimits || null;
|
|
@@ -12876,7 +12891,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12876
12891
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
12877
12892
|
if (cu) bits.push(pct + "% context");
|
|
12878
12893
|
const expandable = !!(cu || limits);
|
|
12879
|
-
return /* @__PURE__ */ jsxs87(
|
|
12894
|
+
return /* @__PURE__ */ jsxs87(React68.Fragment, { children: [
|
|
12880
12895
|
/* @__PURE__ */ jsxs87("div", { className: "fdc-bar", children: [
|
|
12881
12896
|
/* @__PURE__ */ jsxs87(
|
|
12882
12897
|
"button",
|
|
@@ -12889,15 +12904,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12889
12904
|
"aria-expanded": expandable ? open2 : void 0,
|
|
12890
12905
|
"aria-label": expandable ? "Usage details" : void 0,
|
|
12891
12906
|
children: [
|
|
12892
|
-
cu ? /* @__PURE__ */
|
|
12893
|
-
/* @__PURE__ */
|
|
12894
|
-
expandable ? /* @__PURE__ */
|
|
12907
|
+
cu ? /* @__PURE__ */ jsx97("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx97(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
|
|
12908
|
+
/* @__PURE__ */ jsx97("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
|
|
12909
|
+
expandable ? /* @__PURE__ */ jsx97("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
|
|
12895
12910
|
]
|
|
12896
12911
|
}
|
|
12897
12912
|
),
|
|
12898
12913
|
extras
|
|
12899
12914
|
] }),
|
|
12900
|
-
/* @__PURE__ */
|
|
12915
|
+
/* @__PURE__ */ jsx97(
|
|
12901
12916
|
Popover,
|
|
12902
12917
|
{
|
|
12903
12918
|
open: open2,
|
|
@@ -12912,11 +12927,11 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12912
12927
|
setOpen(false);
|
|
12913
12928
|
onClear();
|
|
12914
12929
|
}, children: [
|
|
12915
|
-
/* @__PURE__ */
|
|
12930
|
+
/* @__PURE__ */ jsx97("i", { className: "ph ph-trash", "aria-hidden": "true" }),
|
|
12916
12931
|
"Clear conversation"
|
|
12917
12932
|
] }) : void 0,
|
|
12918
12933
|
children: /* @__PURE__ */ jsxs87("div", { className: "fdc-usage", children: [
|
|
12919
|
-
cu ? /* @__PURE__ */
|
|
12934
|
+
cu ? /* @__PURE__ */ jsx97("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx97(
|
|
12920
12935
|
SegmentedMeter,
|
|
12921
12936
|
{
|
|
12922
12937
|
total,
|
|
@@ -12929,8 +12944,8 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12929
12944
|
}
|
|
12930
12945
|
) }) : null,
|
|
12931
12946
|
limits && limits.length ? /* @__PURE__ */ jsxs87("section", { className: "fdc-usage-sec", children: [
|
|
12932
|
-
/* @__PURE__ */
|
|
12933
|
-
/* @__PURE__ */
|
|
12947
|
+
/* @__PURE__ */ jsx97("h4", { className: "fdc-usage-h", children: "Usage limits" }),
|
|
12948
|
+
/* @__PURE__ */ jsx97("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx97(
|
|
12934
12949
|
QuotaRow,
|
|
12935
12950
|
{
|
|
12936
12951
|
label: l.label,
|
|
@@ -12942,23 +12957,23 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12942
12957
|
] }) : null,
|
|
12943
12958
|
stats ? /* @__PURE__ */ jsxs87("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
|
|
12944
12959
|
stats.elapsedMs ? /* @__PURE__ */ jsxs87("div", { children: [
|
|
12945
|
-
/* @__PURE__ */
|
|
12946
|
-
/* @__PURE__ */
|
|
12960
|
+
/* @__PURE__ */ jsx97("span", { children: "Session" }),
|
|
12961
|
+
/* @__PURE__ */ jsx97("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
|
|
12947
12962
|
] }) : null,
|
|
12948
12963
|
stats.tokens ? /* @__PURE__ */ jsxs87("div", { children: [
|
|
12949
|
-
/* @__PURE__ */
|
|
12950
|
-
/* @__PURE__ */
|
|
12964
|
+
/* @__PURE__ */ jsx97("span", { children: "Tokens" }),
|
|
12965
|
+
/* @__PURE__ */ jsx97("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
|
|
12951
12966
|
] }) : null,
|
|
12952
12967
|
stats.costUsd != null ? /* @__PURE__ */ jsxs87("div", { children: [
|
|
12953
|
-
/* @__PURE__ */
|
|
12968
|
+
/* @__PURE__ */ jsx97("span", { children: "Cost" }),
|
|
12954
12969
|
/* @__PURE__ */ jsxs87("b", { className: "fd-tabular", children: [
|
|
12955
12970
|
"$",
|
|
12956
12971
|
Number(stats.costUsd).toFixed(3)
|
|
12957
12972
|
] })
|
|
12958
12973
|
] }) : null,
|
|
12959
12974
|
stats.turns ? /* @__PURE__ */ jsxs87("div", { children: [
|
|
12960
|
-
/* @__PURE__ */
|
|
12961
|
-
/* @__PURE__ */
|
|
12975
|
+
/* @__PURE__ */ jsx97("span", { children: "Turns" }),
|
|
12976
|
+
/* @__PURE__ */ jsx97("b", { className: "fd-tabular", children: stats.turns })
|
|
12962
12977
|
] }) : null
|
|
12963
12978
|
] }) : null
|
|
12964
12979
|
] })
|
|
@@ -12997,7 +13012,7 @@ function ModelControls({
|
|
|
12997
13012
|
disabled: m.disabled,
|
|
12998
13013
|
checked: m.id === (current2 && current2.id),
|
|
12999
13014
|
meta: m.meta,
|
|
13000
|
-
shortcut: m.shortcut ? /* @__PURE__ */
|
|
13015
|
+
shortcut: m.shortcut ? /* @__PURE__ */ jsx97(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
|
|
13001
13016
|
onSelect: () => onModelChange && onModelChange(m.id)
|
|
13002
13017
|
});
|
|
13003
13018
|
const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
|
|
@@ -13011,14 +13026,14 @@ function ModelControls({
|
|
|
13011
13026
|
items.push({
|
|
13012
13027
|
kind: "custom",
|
|
13013
13028
|
render: () => /* @__PURE__ */ jsxs87("label", { className: "fdc-switchrow", children: [
|
|
13014
|
-
/* @__PURE__ */
|
|
13015
|
-
/* @__PURE__ */
|
|
13016
|
-
/* @__PURE__ */
|
|
13029
|
+
/* @__PURE__ */ jsx97("span", { children: fastModeLabel }),
|
|
13030
|
+
/* @__PURE__ */ jsx97("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
|
|
13031
|
+
/* @__PURE__ */ jsx97("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx97("span", { className: "fd-switch-thumb" }) })
|
|
13017
13032
|
] })
|
|
13018
13033
|
});
|
|
13019
13034
|
}
|
|
13020
|
-
return /* @__PURE__ */ jsxs87(
|
|
13021
|
-
/* @__PURE__ */
|
|
13035
|
+
return /* @__PURE__ */ jsxs87(React68.Fragment, { children: [
|
|
13036
|
+
/* @__PURE__ */ jsx97(
|
|
13022
13037
|
MenuButton,
|
|
13023
13038
|
{
|
|
13024
13039
|
items,
|
|
@@ -13029,7 +13044,7 @@ function ModelControls({
|
|
|
13029
13044
|
title: "Choose a model"
|
|
13030
13045
|
}
|
|
13031
13046
|
),
|
|
13032
|
-
effortLevels && effortLevels.length ? /* @__PURE__ */
|
|
13047
|
+
effortLevels && effortLevels.length ? /* @__PURE__ */ jsx97(
|
|
13033
13048
|
MenuButton,
|
|
13034
13049
|
{
|
|
13035
13050
|
placement: "top-end",
|
|
@@ -13050,7 +13065,7 @@ function ModelControls({
|
|
|
13050
13065
|
}
|
|
13051
13066
|
|
|
13052
13067
|
// src/components/chat/AgentChatPanel.tsx
|
|
13053
|
-
import { jsx as
|
|
13068
|
+
import { jsx as jsx98, jsxs as jsxs88 } from "react/jsx-runtime";
|
|
13054
13069
|
var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
|
|
13055
13070
|
function AgentChatPanel({
|
|
13056
13071
|
/* required */
|
|
@@ -13134,11 +13149,11 @@ function AgentChatPanel({
|
|
|
13134
13149
|
onFeedback,
|
|
13135
13150
|
onEditMessage
|
|
13136
13151
|
}) {
|
|
13137
|
-
const [panelWidth, setPanelWidth] =
|
|
13138
|
-
const [applied, setApplied] =
|
|
13139
|
-
const [draft, setDraft] =
|
|
13140
|
-
const dragging =
|
|
13141
|
-
|
|
13152
|
+
const [panelWidth, setPanelWidth] = React69.useState(width);
|
|
13153
|
+
const [applied, setApplied] = React69.useState({});
|
|
13154
|
+
const [draft, setDraft] = React69.useState("");
|
|
13155
|
+
const dragging = React69.useRef(null);
|
|
13156
|
+
React69.useEffect(() => setPanelWidth(width), [width]);
|
|
13142
13157
|
const engine = useChatEngine({
|
|
13143
13158
|
contextType,
|
|
13144
13159
|
contextId,
|
|
@@ -13204,7 +13219,7 @@ function AgentChatPanel({
|
|
|
13204
13219
|
onReconnect: engine.reload,
|
|
13205
13220
|
deadTitle: "The assistant isn\u2019t reachable"
|
|
13206
13221
|
};
|
|
13207
|
-
const sessionBar = /* @__PURE__ */
|
|
13222
|
+
const sessionBar = /* @__PURE__ */ jsx98(
|
|
13208
13223
|
ChatSessionBar,
|
|
13209
13224
|
{
|
|
13210
13225
|
sessionStats,
|
|
@@ -13213,7 +13228,7 @@ function AgentChatPanel({
|
|
|
13213
13228
|
onClear: engine.visible.length ? engine.clear : void 0
|
|
13214
13229
|
}
|
|
13215
13230
|
);
|
|
13216
|
-
const modelControls = /* @__PURE__ */
|
|
13231
|
+
const modelControls = /* @__PURE__ */ jsx98(
|
|
13217
13232
|
ModelControls,
|
|
13218
13233
|
{
|
|
13219
13234
|
models,
|
|
@@ -13228,7 +13243,7 @@ function AgentChatPanel({
|
|
|
13228
13243
|
narrow
|
|
13229
13244
|
}
|
|
13230
13245
|
);
|
|
13231
|
-
const threadMenu = threads && threads.length ? /* @__PURE__ */
|
|
13246
|
+
const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx98(
|
|
13232
13247
|
MenuButton,
|
|
13233
13248
|
{
|
|
13234
13249
|
variant: "ghost",
|
|
@@ -13266,7 +13281,7 @@ function AgentChatPanel({
|
|
|
13266
13281
|
},
|
|
13267
13282
|
"aria-label": title,
|
|
13268
13283
|
children: [
|
|
13269
|
-
surface === "sidebar" && resizable ? /* @__PURE__ */
|
|
13284
|
+
surface === "sidebar" && resizable ? /* @__PURE__ */ jsx98(
|
|
13270
13285
|
"div",
|
|
13271
13286
|
{
|
|
13272
13287
|
className: "fdc-grip",
|
|
@@ -13282,19 +13297,19 @@ function AgentChatPanel({
|
|
|
13282
13297
|
}
|
|
13283
13298
|
) : null,
|
|
13284
13299
|
showHeader ? /* @__PURE__ */ jsxs88("header", { className: "fdc-head", children: [
|
|
13285
|
-
/* @__PURE__ */
|
|
13300
|
+
/* @__PURE__ */ jsx98("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx98("i", { className: "ph ph-" + assistantIcon }) }),
|
|
13286
13301
|
/* @__PURE__ */ jsxs88("span", { className: "fdc-head-titles", children: [
|
|
13287
|
-
/* @__PURE__ */
|
|
13288
|
-
subtitle ? /* @__PURE__ */
|
|
13302
|
+
/* @__PURE__ */ jsx98("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
|
|
13303
|
+
subtitle ? /* @__PURE__ */ jsx98("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
|
|
13289
13304
|
] }),
|
|
13290
13305
|
/* @__PURE__ */ jsxs88("span", { className: "fdc-head-acts", children: [
|
|
13291
13306
|
headerActions,
|
|
13292
13307
|
threadMenu,
|
|
13293
|
-
onNewThread ? /* @__PURE__ */
|
|
13294
|
-
onClose ? /* @__PURE__ */
|
|
13308
|
+
onNewThread ? /* @__PURE__ */ jsx98("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx98("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
|
|
13309
|
+
onClose ? /* @__PURE__ */ jsx98("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx98("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
13295
13310
|
] })
|
|
13296
13311
|
] }) : null,
|
|
13297
|
-
/* @__PURE__ */
|
|
13312
|
+
/* @__PURE__ */ jsx98(
|
|
13298
13313
|
ChatTranscript,
|
|
13299
13314
|
{
|
|
13300
13315
|
messages: engine.visible,
|
|
@@ -13309,7 +13324,7 @@ function AgentChatPanel({
|
|
|
13309
13324
|
renderEmpty
|
|
13310
13325
|
}
|
|
13311
13326
|
),
|
|
13312
|
-
/* @__PURE__ */
|
|
13327
|
+
/* @__PURE__ */ jsx98(
|
|
13313
13328
|
ChatComposer,
|
|
13314
13329
|
{
|
|
13315
13330
|
onSubmit: (text, atts) => engine.send(text, atts),
|
|
@@ -13342,8 +13357,8 @@ function AgentChatPanel({
|
|
|
13342
13357
|
}
|
|
13343
13358
|
|
|
13344
13359
|
// src/components/files/FileViewer.tsx
|
|
13345
|
-
import * as
|
|
13346
|
-
import { jsx as
|
|
13360
|
+
import * as React70 from "react";
|
|
13361
|
+
import { jsx as jsx99, jsxs as jsxs89 } from "react/jsx-runtime";
|
|
13347
13362
|
function previewKindOf(file) {
|
|
13348
13363
|
const mime = (file.mime || "").toLowerCase();
|
|
13349
13364
|
const ext = extensionOf(file.name || "");
|
|
@@ -13399,13 +13414,13 @@ function parseDelimited(text, delimiter) {
|
|
|
13399
13414
|
return rows;
|
|
13400
13415
|
}
|
|
13401
13416
|
function usePreview(file, kind, resolveUrl) {
|
|
13402
|
-
const [state, setState] =
|
|
13403
|
-
const [attempt, setAttempt] =
|
|
13404
|
-
const resolveRef =
|
|
13405
|
-
|
|
13417
|
+
const [state, setState] = React70.useState({ status: "loading" });
|
|
13418
|
+
const [attempt, setAttempt] = React70.useState(0);
|
|
13419
|
+
const resolveRef = React70.useRef(resolveUrl);
|
|
13420
|
+
React70.useEffect(() => {
|
|
13406
13421
|
resolveRef.current = resolveUrl;
|
|
13407
13422
|
}, [resolveUrl]);
|
|
13408
|
-
|
|
13423
|
+
React70.useEffect(() => {
|
|
13409
13424
|
if (kind === "none") {
|
|
13410
13425
|
setState({ status: "ready" });
|
|
13411
13426
|
return;
|
|
@@ -13435,19 +13450,19 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
13435
13450
|
if (ac) ac.abort();
|
|
13436
13451
|
};
|
|
13437
13452
|
}, [file.id, kind, attempt]);
|
|
13438
|
-
return { ...state, retry:
|
|
13453
|
+
return { ...state, retry: React70.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
13439
13454
|
}
|
|
13440
13455
|
function PreviewBody({ file, kind, state }) {
|
|
13441
|
-
if (kind === "image") return /* @__PURE__ */
|
|
13442
|
-
if (kind === "pdf") return /* @__PURE__ */
|
|
13443
|
-
if (kind === "markdown") return /* @__PURE__ */
|
|
13456
|
+
if (kind === "image") return /* @__PURE__ */ jsx99("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
13457
|
+
if (kind === "pdf") return /* @__PURE__ */ jsx99("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
|
|
13458
|
+
if (kind === "markdown") return /* @__PURE__ */ jsx99(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
|
|
13444
13459
|
if (kind === "json") {
|
|
13445
13460
|
let pretty = state.text || "";
|
|
13446
13461
|
try {
|
|
13447
13462
|
pretty = JSON.stringify(JSON.parse(pretty), null, 2);
|
|
13448
13463
|
} catch {
|
|
13449
13464
|
}
|
|
13450
|
-
return /* @__PURE__ */
|
|
13465
|
+
return /* @__PURE__ */ jsx99(CodeBlock, { code: pretty, language: "json" });
|
|
13451
13466
|
}
|
|
13452
13467
|
if (kind === "csv") {
|
|
13453
13468
|
const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
|
|
@@ -13457,8 +13472,8 @@ function PreviewBody({ file, kind, state }) {
|
|
|
13457
13472
|
const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
|
|
13458
13473
|
return /* @__PURE__ */ jsxs89("div", { className: "fd-fv-csv", children: [
|
|
13459
13474
|
/* @__PURE__ */ jsxs89("table", { className: "fd-fv-csv-table", children: [
|
|
13460
|
-
/* @__PURE__ */
|
|
13461
|
-
/* @__PURE__ */
|
|
13475
|
+
/* @__PURE__ */ jsx99("thead", { children: /* @__PURE__ */ jsx99("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx99("th", { children: c }, i)) }) }),
|
|
13476
|
+
/* @__PURE__ */ jsx99("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx99("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx99("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
|
|
13462
13477
|
] }),
|
|
13463
13478
|
dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs89("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
|
|
13464
13479
|
"Showing the first ",
|
|
@@ -13469,10 +13484,10 @@ function PreviewBody({ file, kind, state }) {
|
|
|
13469
13484
|
] }) : null
|
|
13470
13485
|
] });
|
|
13471
13486
|
}
|
|
13472
|
-
if (kind === "text") return /* @__PURE__ */
|
|
13487
|
+
if (kind === "text") return /* @__PURE__ */ jsx99(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
|
|
13473
13488
|
return /* @__PURE__ */ jsxs89("div", { className: "fd-fv-fallback", children: [
|
|
13474
|
-
/* @__PURE__ */
|
|
13475
|
-
/* @__PURE__ */
|
|
13489
|
+
/* @__PURE__ */ jsx99("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx99("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
|
|
13490
|
+
/* @__PURE__ */ jsx99("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
|
|
13476
13491
|
/* @__PURE__ */ jsxs89("span", { className: "fd-fv-fallback-meta", children: [
|
|
13477
13492
|
file.mime || "Unknown type",
|
|
13478
13493
|
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
@@ -13480,13 +13495,13 @@ function PreviewBody({ file, kind, state }) {
|
|
|
13480
13495
|
] });
|
|
13481
13496
|
}
|
|
13482
13497
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
13483
|
-
const kind =
|
|
13498
|
+
const kind = React70.useMemo(() => previewKindOf(file), [file]);
|
|
13484
13499
|
const preview = usePreview(file, kind, resolveUrl);
|
|
13485
|
-
const [tab, setTab] =
|
|
13486
|
-
const [downloading, setDownloading] =
|
|
13487
|
-
const [downloadError, setDownloadError] =
|
|
13500
|
+
const [tab, setTab] = React70.useState("preview");
|
|
13501
|
+
const [downloading, setDownloading] = React70.useState(false);
|
|
13502
|
+
const [downloadError, setDownloadError] = React70.useState(null);
|
|
13488
13503
|
const hasSide = sidePanel != null;
|
|
13489
|
-
|
|
13504
|
+
React70.useEffect(() => {
|
|
13490
13505
|
setTab("preview");
|
|
13491
13506
|
}, [file.id]);
|
|
13492
13507
|
const download = () => {
|
|
@@ -13509,9 +13524,9 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13509
13524
|
"aria-label": file.name || "File",
|
|
13510
13525
|
children: [
|
|
13511
13526
|
/* @__PURE__ */ jsxs89("header", { className: "fd-fv-head", children: [
|
|
13512
|
-
/* @__PURE__ */
|
|
13527
|
+
/* @__PURE__ */ jsx99("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx99("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
|
|
13513
13528
|
/* @__PURE__ */ jsxs89("span", { className: "fd-fv-head-titles", children: [
|
|
13514
|
-
/* @__PURE__ */
|
|
13529
|
+
/* @__PURE__ */ jsx99("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
|
|
13515
13530
|
/* @__PURE__ */ jsxs89("span", { className: "fd-fv-head-meta", children: [
|
|
13516
13531
|
file.mime || "Unknown type",
|
|
13517
13532
|
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
@@ -13519,12 +13534,12 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13519
13534
|
] }),
|
|
13520
13535
|
/* @__PURE__ */ jsxs89("span", { className: "fd-fv-head-actions", children: [
|
|
13521
13536
|
actions,
|
|
13522
|
-
/* @__PURE__ */
|
|
13523
|
-
onClose ? /* @__PURE__ */
|
|
13537
|
+
/* @__PURE__ */ jsx99(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
|
|
13538
|
+
onClose ? /* @__PURE__ */ jsx99(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
|
|
13524
13539
|
] })
|
|
13525
13540
|
] }),
|
|
13526
|
-
downloadError ? /* @__PURE__ */
|
|
13527
|
-
hasSide ? /* @__PURE__ */
|
|
13541
|
+
downloadError ? /* @__PURE__ */ jsx99("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
|
|
13542
|
+
hasSide ? /* @__PURE__ */ jsx99(
|
|
13528
13543
|
Tabs,
|
|
13529
13544
|
{
|
|
13530
13545
|
className: "fd-fv-tabs",
|
|
@@ -13534,18 +13549,18 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13534
13549
|
}
|
|
13535
13550
|
) : null,
|
|
13536
13551
|
/* @__PURE__ */ jsxs89("div", { className: "fd-fv-body", children: [
|
|
13537
|
-
/* @__PURE__ */
|
|
13552
|
+
/* @__PURE__ */ jsx99("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx99(
|
|
13538
13553
|
LoadingRegion,
|
|
13539
13554
|
{
|
|
13540
13555
|
state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
|
|
13541
13556
|
error: preview.error,
|
|
13542
13557
|
label: "Loading preview of " + (file.name || "file"),
|
|
13543
13558
|
onRetry: preview.status === "error" ? preview.retry : void 0,
|
|
13544
|
-
skeleton: /* @__PURE__ */
|
|
13545
|
-
children: /* @__PURE__ */
|
|
13559
|
+
skeleton: /* @__PURE__ */ jsx99(Skeleton, { shape: "card", h: 220 }),
|
|
13560
|
+
children: /* @__PURE__ */ jsx99(PreviewBody, { file, kind, state: preview })
|
|
13546
13561
|
}
|
|
13547
13562
|
) }),
|
|
13548
|
-
hasSide ? /* @__PURE__ */
|
|
13563
|
+
hasSide ? /* @__PURE__ */ jsx99("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
|
|
13549
13564
|
] })
|
|
13550
13565
|
]
|
|
13551
13566
|
}
|
|
@@ -13553,8 +13568,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
13553
13568
|
}
|
|
13554
13569
|
|
|
13555
13570
|
// src/components/files/FileBrowser.tsx
|
|
13556
|
-
import * as
|
|
13557
|
-
import { Fragment as Fragment29, jsx as
|
|
13571
|
+
import * as React71 from "react";
|
|
13572
|
+
import { Fragment as Fragment29, jsx as jsx100, jsxs as jsxs90 } from "react/jsx-runtime";
|
|
13558
13573
|
function childrenOf(folders, parentId) {
|
|
13559
13574
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
13560
13575
|
}
|
|
@@ -13627,7 +13642,7 @@ function FolderPickerMenu({
|
|
|
13627
13642
|
const panel = useInlinePanel();
|
|
13628
13643
|
const { open: open2, setOpen, ref } = panel;
|
|
13629
13644
|
return /* @__PURE__ */ jsxs90("span", { className: "fd-fb-menu-anchor", ref, children: [
|
|
13630
|
-
/* @__PURE__ */
|
|
13645
|
+
/* @__PURE__ */ jsx100(
|
|
13631
13646
|
IconButton,
|
|
13632
13647
|
{
|
|
13633
13648
|
icon: "arrows-out-cardinal",
|
|
@@ -13639,8 +13654,8 @@ function FolderPickerMenu({
|
|
|
13639
13654
|
onClick: () => setOpen((v) => !v)
|
|
13640
13655
|
}
|
|
13641
13656
|
),
|
|
13642
|
-
/* @__PURE__ */
|
|
13643
|
-
/* @__PURE__ */
|
|
13657
|
+
/* @__PURE__ */ jsx100(InlinePanelSurface, { panel, align: "right", offset: 4, width: 220, maxHeight: 280, role: "menu", label, children: /* @__PURE__ */ jsxs90("div", { className: "fd-fb-menu", children: [
|
|
13658
|
+
/* @__PURE__ */ jsx100("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
|
|
13644
13659
|
destinations.map((d) => /* @__PURE__ */ jsxs90(
|
|
13645
13660
|
"button",
|
|
13646
13661
|
{
|
|
@@ -13653,7 +13668,7 @@ function FolderPickerMenu({
|
|
|
13653
13668
|
setOpen(false);
|
|
13654
13669
|
},
|
|
13655
13670
|
children: [
|
|
13656
|
-
/* @__PURE__ */
|
|
13671
|
+
/* @__PURE__ */ jsx100("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
|
|
13657
13672
|
d.name
|
|
13658
13673
|
]
|
|
13659
13674
|
},
|
|
@@ -13663,8 +13678,8 @@ function FolderPickerMenu({
|
|
|
13663
13678
|
] });
|
|
13664
13679
|
}
|
|
13665
13680
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
13666
|
-
const [over, setOver] =
|
|
13667
|
-
const dragCounter =
|
|
13681
|
+
const [over, setOver] = React71.useState(false);
|
|
13682
|
+
const dragCounter = React71.useRef(0);
|
|
13668
13683
|
const dropHandlers = isDropTarget ? {
|
|
13669
13684
|
onDragEnter: (e) => {
|
|
13670
13685
|
if (!hasInternalPayload(e)) return;
|
|
@@ -13699,26 +13714,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
13699
13714
|
draggable: !!draggableId,
|
|
13700
13715
|
onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
|
|
13701
13716
|
children: [
|
|
13702
|
-
/* @__PURE__ */
|
|
13717
|
+
/* @__PURE__ */ jsx100("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx100("i", { className: "ph ph-" + icon }) }),
|
|
13703
13718
|
/* @__PURE__ */ jsxs90("span", { className: "fd-fb-row-text", children: [
|
|
13704
|
-
/* @__PURE__ */
|
|
13705
|
-
meta ? /* @__PURE__ */
|
|
13719
|
+
/* @__PURE__ */ jsx100("span", { className: "fd-fb-row-name", title: name, children: name }),
|
|
13720
|
+
meta ? /* @__PURE__ */ jsx100("span", { className: "fd-fb-row-meta", children: meta }) : null
|
|
13706
13721
|
] })
|
|
13707
13722
|
]
|
|
13708
13723
|
}
|
|
13709
13724
|
),
|
|
13710
|
-
actions ? /* @__PURE__ */
|
|
13725
|
+
actions ? /* @__PURE__ */ jsx100("span", { className: "fd-fb-row-actions", children: actions }) : null
|
|
13711
13726
|
] });
|
|
13712
13727
|
}
|
|
13713
13728
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
13714
13729
|
const kids = childrenOf(folders, folder.id);
|
|
13715
|
-
const [expanded, setExpanded] =
|
|
13716
|
-
|
|
13730
|
+
const [expanded, setExpanded] = React71.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
13731
|
+
React71.useEffect(() => {
|
|
13717
13732
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
13718
13733
|
}, [currentFolderId, folder.id, folders]);
|
|
13719
13734
|
const isCurrent = folder.id === currentFolderId;
|
|
13720
13735
|
return /* @__PURE__ */ jsxs90("div", { className: "fd-fb-tree-node", children: [
|
|
13721
|
-
/* @__PURE__ */
|
|
13736
|
+
/* @__PURE__ */ jsx100(
|
|
13722
13737
|
RowShell,
|
|
13723
13738
|
{
|
|
13724
13739
|
icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
|
|
@@ -13728,7 +13743,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
|
|
|
13728
13743
|
isDropTarget: canMove,
|
|
13729
13744
|
onDropPayload: (payload) => onMoveInto(payload, folder.id),
|
|
13730
13745
|
className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
|
|
13731
|
-
actions: kids.length ? /* @__PURE__ */
|
|
13746
|
+
actions: kids.length ? /* @__PURE__ */ jsx100(
|
|
13732
13747
|
IconButton,
|
|
13733
13748
|
{
|
|
13734
13749
|
icon: expanded ? "caret-down" : "caret-right",
|
|
@@ -13740,7 +13755,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
|
|
|
13740
13755
|
) : void 0
|
|
13741
13756
|
}
|
|
13742
13757
|
),
|
|
13743
|
-
expanded && kids.length ? /* @__PURE__ */
|
|
13758
|
+
expanded && kids.length ? /* @__PURE__ */ jsx100("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx100(
|
|
13744
13759
|
TreeNode,
|
|
13745
13760
|
{
|
|
13746
13761
|
folder: k,
|
|
@@ -13779,15 +13794,15 @@ function FileBrowser({
|
|
|
13779
13794
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
13780
13795
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
13781
13796
|
const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
|
|
13782
|
-
const [createOpen, setCreateOpen] =
|
|
13783
|
-
const [createName, setCreateName] =
|
|
13784
|
-
const [renameTarget, setRenameTarget] =
|
|
13785
|
-
const [renameValue, setRenameValue] =
|
|
13786
|
-
const [deleteTarget, setDeleteTarget] =
|
|
13787
|
-
const uploadInputRef =
|
|
13788
|
-
const crumbFolders =
|
|
13789
|
-
const subfolders =
|
|
13790
|
-
const currentFiles =
|
|
13797
|
+
const [createOpen, setCreateOpen] = React71.useState(false);
|
|
13798
|
+
const [createName, setCreateName] = React71.useState("");
|
|
13799
|
+
const [renameTarget, setRenameTarget] = React71.useState(null);
|
|
13800
|
+
const [renameValue, setRenameValue] = React71.useState("");
|
|
13801
|
+
const [deleteTarget, setDeleteTarget] = React71.useState(null);
|
|
13802
|
+
const uploadInputRef = React71.useRef(null);
|
|
13803
|
+
const crumbFolders = React71.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
13804
|
+
const subfolders = React71.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
13805
|
+
const currentFiles = React71.useMemo(
|
|
13791
13806
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
13792
13807
|
[files, currentFolderId]
|
|
13793
13808
|
);
|
|
@@ -13829,7 +13844,7 @@ function FileBrowser({
|
|
|
13829
13844
|
const content = /* @__PURE__ */ jsxs90("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
|
|
13830
13845
|
/* @__PURE__ */ jsxs90("div", { className: "fd-fb-head", children: [
|
|
13831
13846
|
/* @__PURE__ */ jsxs90("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
|
|
13832
|
-
/* @__PURE__ */
|
|
13847
|
+
/* @__PURE__ */ jsx100(
|
|
13833
13848
|
BreadcrumbCrumb,
|
|
13834
13849
|
{
|
|
13835
13850
|
label: "Home",
|
|
@@ -13839,7 +13854,7 @@ function FileBrowser({
|
|
|
13839
13854
|
onDropPayload: (p) => moveIntoFolder(p, null)
|
|
13840
13855
|
}
|
|
13841
13856
|
),
|
|
13842
|
-
crumbFolders.map((f, i) => /* @__PURE__ */
|
|
13857
|
+
crumbFolders.map((f, i) => /* @__PURE__ */ jsx100(
|
|
13843
13858
|
BreadcrumbCrumb,
|
|
13844
13859
|
{
|
|
13845
13860
|
label: f.name,
|
|
@@ -13852,10 +13867,10 @@ function FileBrowser({
|
|
|
13852
13867
|
))
|
|
13853
13868
|
] }),
|
|
13854
13869
|
/* @__PURE__ */ jsxs90("span", { className: "fd-fb-actions", children: [
|
|
13855
|
-
canCreateFolder ? /* @__PURE__ */
|
|
13870
|
+
canCreateFolder ? /* @__PURE__ */ jsx100(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
|
|
13856
13871
|
canUpload ? /* @__PURE__ */ jsxs90(Fragment29, { children: [
|
|
13857
|
-
/* @__PURE__ */
|
|
13858
|
-
/* @__PURE__ */
|
|
13872
|
+
/* @__PURE__ */ jsx100(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
|
|
13873
|
+
/* @__PURE__ */ jsx100(
|
|
13859
13874
|
"input",
|
|
13860
13875
|
{
|
|
13861
13876
|
ref: uploadInputRef,
|
|
@@ -13875,7 +13890,7 @@ function FileBrowser({
|
|
|
13875
13890
|
] }),
|
|
13876
13891
|
/* @__PURE__ */ jsxs90("div", { className: "fd-fb-body", children: [
|
|
13877
13892
|
/* @__PURE__ */ jsxs90("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
|
|
13878
|
-
/* @__PURE__ */
|
|
13893
|
+
/* @__PURE__ */ jsx100(
|
|
13879
13894
|
RowShell,
|
|
13880
13895
|
{
|
|
13881
13896
|
icon: "house-simple",
|
|
@@ -13886,7 +13901,7 @@ function FileBrowser({
|
|
|
13886
13901
|
className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
|
|
13887
13902
|
}
|
|
13888
13903
|
),
|
|
13889
|
-
childrenOf(folders, null).map((f) => /* @__PURE__ */
|
|
13904
|
+
childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx100(
|
|
13890
13905
|
TreeNode,
|
|
13891
13906
|
{
|
|
13892
13907
|
folder: f,
|
|
@@ -13900,18 +13915,18 @@ function FileBrowser({
|
|
|
13900
13915
|
f.id
|
|
13901
13916
|
))
|
|
13902
13917
|
] }),
|
|
13903
|
-
/* @__PURE__ */
|
|
13918
|
+
/* @__PURE__ */ jsx100("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx100(
|
|
13904
13919
|
LoadingRegion,
|
|
13905
13920
|
{
|
|
13906
13921
|
state: loading ? "loading" : "ready",
|
|
13907
13922
|
label: "Loading folder contents",
|
|
13908
13923
|
skeleton: /* @__PURE__ */ jsxs90("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
|
|
13909
|
-
/* @__PURE__ */
|
|
13910
|
-
/* @__PURE__ */
|
|
13911
|
-
/* @__PURE__ */
|
|
13924
|
+
/* @__PURE__ */ jsx100(Skeleton, { h: 44, radius: "10px" }),
|
|
13925
|
+
/* @__PURE__ */ jsx100(Skeleton, { h: 44, radius: "10px" }),
|
|
13926
|
+
/* @__PURE__ */ jsx100(Skeleton, { h: 44, radius: "10px" })
|
|
13912
13927
|
] }),
|
|
13913
|
-
children: isEmpty ? /* @__PURE__ */
|
|
13914
|
-
subfolders.map((f) => /* @__PURE__ */
|
|
13928
|
+
children: isEmpty ? /* @__PURE__ */ jsx100(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__ */ jsxs90("div", { className: "fd-fb-list", children: [
|
|
13929
|
+
subfolders.map((f) => /* @__PURE__ */ jsx100(
|
|
13915
13930
|
RowShell,
|
|
13916
13931
|
{
|
|
13917
13932
|
icon: "folder-simple",
|
|
@@ -13921,8 +13936,8 @@ function FileBrowser({
|
|
|
13921
13936
|
isDropTarget: canMove,
|
|
13922
13937
|
onDropPayload: (p) => moveIntoFolder(p, f.id),
|
|
13923
13938
|
actions: /* @__PURE__ */ jsxs90(Fragment29, { children: [
|
|
13924
|
-
canRenameFolder ? /* @__PURE__ */
|
|
13925
|
-
canMove ? /* @__PURE__ */
|
|
13939
|
+
canRenameFolder ? /* @__PURE__ */ jsx100(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
|
|
13940
|
+
canMove ? /* @__PURE__ */ jsx100(
|
|
13926
13941
|
FolderPickerMenu,
|
|
13927
13942
|
{
|
|
13928
13943
|
label: "Move " + f.name,
|
|
@@ -13930,12 +13945,12 @@ function FileBrowser({
|
|
|
13930
13945
|
onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
|
|
13931
13946
|
}
|
|
13932
13947
|
) : null,
|
|
13933
|
-
canDeleteFolder ? /* @__PURE__ */
|
|
13948
|
+
canDeleteFolder ? /* @__PURE__ */ jsx100(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
|
|
13934
13949
|
] })
|
|
13935
13950
|
},
|
|
13936
13951
|
f.id
|
|
13937
13952
|
)),
|
|
13938
|
-
currentFiles.map((file) => /* @__PURE__ */
|
|
13953
|
+
currentFiles.map((file) => /* @__PURE__ */ jsx100(
|
|
13939
13954
|
RowShell,
|
|
13940
13955
|
{
|
|
13941
13956
|
icon: iconForMime(file.mime, file.name),
|
|
@@ -13944,7 +13959,7 @@ function FileBrowser({
|
|
|
13944
13959
|
onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
|
|
13945
13960
|
draggableId: canMove ? { kind: "file", id: file.id } : void 0,
|
|
13946
13961
|
actions: /* @__PURE__ */ jsxs90(Fragment29, { children: [
|
|
13947
|
-
canMove ? /* @__PURE__ */
|
|
13962
|
+
canMove ? /* @__PURE__ */ jsx100(
|
|
13948
13963
|
FolderPickerMenu,
|
|
13949
13964
|
{
|
|
13950
13965
|
label: "Move " + file.name,
|
|
@@ -13952,7 +13967,7 @@ function FileBrowser({
|
|
|
13952
13967
|
onPick: (target) => onMoveFile && onMoveFile(file.id, target)
|
|
13953
13968
|
}
|
|
13954
13969
|
) : null,
|
|
13955
|
-
canRemoveFile ? /* @__PURE__ */
|
|
13970
|
+
canRemoveFile ? /* @__PURE__ */ jsx100(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
|
|
13956
13971
|
] })
|
|
13957
13972
|
},
|
|
13958
13973
|
file.id
|
|
@@ -13961,10 +13976,10 @@ function FileBrowser({
|
|
|
13961
13976
|
}
|
|
13962
13977
|
) })
|
|
13963
13978
|
] }),
|
|
13964
|
-
/* @__PURE__ */
|
|
13965
|
-
/* @__PURE__ */
|
|
13966
|
-
/* @__PURE__ */
|
|
13967
|
-
] }), children: /* @__PURE__ */
|
|
13979
|
+
/* @__PURE__ */ jsx100(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs90(Fragment29, { children: [
|
|
13980
|
+
/* @__PURE__ */ jsx100(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
|
|
13981
|
+
/* @__PURE__ */ jsx100(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
|
|
13982
|
+
] }), children: /* @__PURE__ */ jsx100(
|
|
13968
13983
|
"input",
|
|
13969
13984
|
{
|
|
13970
13985
|
className: "fd-fb-input",
|
|
@@ -13978,10 +13993,10 @@ function FileBrowser({
|
|
|
13978
13993
|
autoFocus: true
|
|
13979
13994
|
}
|
|
13980
13995
|
) }),
|
|
13981
|
-
/* @__PURE__ */
|
|
13982
|
-
/* @__PURE__ */
|
|
13983
|
-
/* @__PURE__ */
|
|
13984
|
-
] }), children: /* @__PURE__ */
|
|
13996
|
+
/* @__PURE__ */ jsx100(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs90(Fragment29, { children: [
|
|
13997
|
+
/* @__PURE__ */ jsx100(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
|
|
13998
|
+
/* @__PURE__ */ jsx100(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
|
|
13999
|
+
] }), children: /* @__PURE__ */ jsx100(
|
|
13985
14000
|
"input",
|
|
13986
14001
|
{
|
|
13987
14002
|
className: "fd-fb-input",
|
|
@@ -13995,7 +14010,7 @@ function FileBrowser({
|
|
|
13995
14010
|
autoFocus: true
|
|
13996
14011
|
}
|
|
13997
14012
|
) }),
|
|
13998
|
-
/* @__PURE__ */
|
|
14013
|
+
/* @__PURE__ */ jsx100(
|
|
13999
14014
|
Modal,
|
|
14000
14015
|
{
|
|
14001
14016
|
open: deleteTarget != null,
|
|
@@ -14003,14 +14018,14 @@ function FileBrowser({
|
|
|
14003
14018
|
description: "This can't be undone. The folder must be empty.",
|
|
14004
14019
|
onClose: () => setDeleteTarget(null),
|
|
14005
14020
|
footer: /* @__PURE__ */ jsxs90(Fragment29, { children: [
|
|
14006
|
-
/* @__PURE__ */
|
|
14007
|
-
/* @__PURE__ */
|
|
14021
|
+
/* @__PURE__ */ jsx100(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
|
|
14022
|
+
/* @__PURE__ */ jsx100(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
|
|
14008
14023
|
] })
|
|
14009
14024
|
}
|
|
14010
14025
|
)
|
|
14011
14026
|
] });
|
|
14012
14027
|
if (!canUpload) return content;
|
|
14013
|
-
return /* @__PURE__ */
|
|
14028
|
+
return /* @__PURE__ */ jsx100(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
|
|
14014
14029
|
}
|
|
14015
14030
|
function BreadcrumbCrumb({
|
|
14016
14031
|
label,
|
|
@@ -14019,8 +14034,8 @@ function BreadcrumbCrumb({
|
|
|
14019
14034
|
isDropTarget,
|
|
14020
14035
|
onDropPayload
|
|
14021
14036
|
}) {
|
|
14022
|
-
const [over, setOver] =
|
|
14023
|
-
const dragCounter =
|
|
14037
|
+
const [over, setOver] = React71.useState(false);
|
|
14038
|
+
const dragCounter = React71.useRef(0);
|
|
14024
14039
|
const dropHandlers = isDropTarget ? {
|
|
14025
14040
|
onDragEnter: (e) => {
|
|
14026
14041
|
if (!hasInternalPayload(e)) return;
|
|
@@ -14045,11 +14060,11 @@ function BreadcrumbCrumb({
|
|
|
14045
14060
|
if (payload && onDropPayload) onDropPayload(payload);
|
|
14046
14061
|
}
|
|
14047
14062
|
} : {};
|
|
14048
|
-
return /* @__PURE__ */
|
|
14063
|
+
return /* @__PURE__ */ jsx100("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx100("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx100("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
|
|
14049
14064
|
}
|
|
14050
14065
|
|
|
14051
14066
|
// src/kits/query.ts
|
|
14052
|
-
import * as
|
|
14067
|
+
import * as React72 from "react";
|
|
14053
14068
|
var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
|
|
14054
14069
|
var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
|
|
14055
14070
|
var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
|
|
@@ -14104,22 +14119,22 @@ function compare(a, b, dir) {
|
|
|
14104
14119
|
var API = null;
|
|
14105
14120
|
var PREFS = null;
|
|
14106
14121
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
14107
|
-
const [query, setQuery] =
|
|
14122
|
+
const [query, setQuery] = React72.useState(() => {
|
|
14108
14123
|
const store = PREFS || window.PlannerPrefs;
|
|
14109
14124
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
14110
14125
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
14111
14126
|
});
|
|
14112
|
-
const savePref =
|
|
14127
|
+
const savePref = React72.useCallback((patch2) => {
|
|
14113
14128
|
const store = PREFS || window.PlannerPrefs;
|
|
14114
14129
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
14115
14130
|
}, [prefsKey]);
|
|
14116
|
-
const [res, setRes] =
|
|
14117
|
-
const [loading, setLoading] =
|
|
14118
|
-
const seq2 =
|
|
14131
|
+
const [res, setRes] = React72.useState(null);
|
|
14132
|
+
const [loading, setLoading] = React72.useState(true);
|
|
14133
|
+
const seq2 = React72.useRef(0);
|
|
14119
14134
|
const depKey = (deps || []).join("|");
|
|
14120
14135
|
const paramKey = JSON.stringify(params || {});
|
|
14121
14136
|
const queryKey = JSON.stringify(query);
|
|
14122
|
-
|
|
14137
|
+
React72.useEffect(() => {
|
|
14123
14138
|
const id = ++seq2.current;
|
|
14124
14139
|
setLoading(true);
|
|
14125
14140
|
const t = setTimeout(() => {
|
|
@@ -14438,12 +14453,12 @@ function createVersionStore(initialState, options) {
|
|
|
14438
14453
|
}
|
|
14439
14454
|
|
|
14440
14455
|
// src/kits/documentTitle.ts
|
|
14441
|
-
import * as
|
|
14456
|
+
import * as React73 from "react";
|
|
14442
14457
|
function formatDocumentTitle(routeTitle, appName) {
|
|
14443
14458
|
return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
|
|
14444
14459
|
}
|
|
14445
14460
|
function useDocumentTitle(routeTitle, appName) {
|
|
14446
|
-
|
|
14461
|
+
React73.useEffect(() => {
|
|
14447
14462
|
if (typeof document === "undefined") return;
|
|
14448
14463
|
document.title = formatDocumentTitle(routeTitle, appName);
|
|
14449
14464
|
}, [routeTitle, appName]);
|
|
@@ -14457,6 +14472,7 @@ export {
|
|
|
14457
14472
|
AppShell,
|
|
14458
14473
|
AppSwitcher,
|
|
14459
14474
|
AppearanceMenu,
|
|
14475
|
+
AppearanceProvider,
|
|
14460
14476
|
Avatar,
|
|
14461
14477
|
AvatarStack,
|
|
14462
14478
|
Badge,
|
|
@@ -14612,6 +14628,7 @@ export {
|
|
|
14612
14628
|
__resetLayerStackForTests,
|
|
14613
14629
|
acceptMatches,
|
|
14614
14630
|
anyOfFilter,
|
|
14631
|
+
applyAppearance,
|
|
14615
14632
|
applyPrefs,
|
|
14616
14633
|
channelWeightOf,
|
|
14617
14634
|
computeNeedMore,
|
|
@@ -14657,6 +14674,7 @@ export {
|
|
|
14657
14674
|
toAttachment,
|
|
14658
14675
|
tokenize,
|
|
14659
14676
|
useAppearancePrefs,
|
|
14677
|
+
useAppearanceStore,
|
|
14660
14678
|
useChatEngine,
|
|
14661
14679
|
useCopyToClipboard,
|
|
14662
14680
|
useCornerStackSlot,
|
|
@@ -14672,6 +14690,7 @@ export {
|
|
|
14672
14690
|
useStagedFiles,
|
|
14673
14691
|
useToast,
|
|
14674
14692
|
validateFilterValue,
|
|
14675
|
-
visibleMessages
|
|
14693
|
+
visibleMessages,
|
|
14694
|
+
watchAppearance
|
|
14676
14695
|
};
|
|
14677
14696
|
//# sourceMappingURL=index.js.map
|