@flytedan/flytebot-design-system 0.19.0 → 0.21.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 +893 -698
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +62 -1
- package/dist/index.d.ts +62 -1
- package/dist/index.js +892 -698
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6376,11 +6376,204 @@ function ProfilePage({
|
|
|
6376
6376
|
] });
|
|
6377
6377
|
}
|
|
6378
6378
|
|
|
6379
|
+
// src/components/platform/SignInPage.tsx
|
|
6380
|
+
import * as React42 from "react";
|
|
6381
|
+
import { Fragment as Fragment18, jsx as jsx67, jsxs as jsxs61 } from "react/jsx-runtime";
|
|
6382
|
+
function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
6383
|
+
const [signingIn, setSigningIn] = React42.useState(false);
|
|
6384
|
+
const [resuming, setResuming] = React42.useState(false);
|
|
6385
|
+
function handleSignIn() {
|
|
6386
|
+
setSigningIn(true);
|
|
6387
|
+
onSignIn();
|
|
6388
|
+
}
|
|
6389
|
+
function handleContinue() {
|
|
6390
|
+
setResuming(true);
|
|
6391
|
+
continueAs.onContinue().finally(() => setResuming(false));
|
|
6392
|
+
}
|
|
6393
|
+
return /* @__PURE__ */ jsxs61(
|
|
6394
|
+
"div",
|
|
6395
|
+
{
|
|
6396
|
+
style: {
|
|
6397
|
+
position: "relative",
|
|
6398
|
+
display: "grid",
|
|
6399
|
+
placeItems: "center",
|
|
6400
|
+
minHeight: "100vh",
|
|
6401
|
+
padding: "24px 16px",
|
|
6402
|
+
boxSizing: "border-box",
|
|
6403
|
+
overflow: "hidden",
|
|
6404
|
+
background: "radial-gradient(circle at 15% 15%, var(--blue-700) 0%, transparent 45%), radial-gradient(circle at 85% 85%, var(--blue-600) 0%, transparent 40%), linear-gradient(160deg, var(--navy) 0%, var(--blue-950) 55%, var(--blue-900) 100%)"
|
|
6405
|
+
},
|
|
6406
|
+
children: [
|
|
6407
|
+
/* @__PURE__ */ jsx67(
|
|
6408
|
+
"div",
|
|
6409
|
+
{
|
|
6410
|
+
"aria-hidden": true,
|
|
6411
|
+
style: {
|
|
6412
|
+
position: "absolute",
|
|
6413
|
+
inset: 0,
|
|
6414
|
+
backgroundImage: "linear-gradient(rgba(255,255,255,0.05) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.05) 1px, transparent 1px)",
|
|
6415
|
+
backgroundSize: "48px 48px",
|
|
6416
|
+
maskImage: "radial-gradient(circle at 50% 40%, black, transparent 70%)"
|
|
6417
|
+
}
|
|
6418
|
+
}
|
|
6419
|
+
),
|
|
6420
|
+
/* @__PURE__ */ jsxs61(
|
|
6421
|
+
"div",
|
|
6422
|
+
{
|
|
6423
|
+
style: {
|
|
6424
|
+
position: "relative",
|
|
6425
|
+
width: "100%",
|
|
6426
|
+
maxWidth: 408,
|
|
6427
|
+
display: "flex",
|
|
6428
|
+
flexDirection: "column",
|
|
6429
|
+
alignItems: "center"
|
|
6430
|
+
},
|
|
6431
|
+
children: [
|
|
6432
|
+
/* @__PURE__ */ jsx67("div", { style: { marginBottom: "var(--s-32)" }, "data-theme": "dark", children: /* @__PURE__ */ jsx67(FlytedeskMark, { size: "lg" }) }),
|
|
6433
|
+
/* @__PURE__ */ jsxs61(
|
|
6434
|
+
"div",
|
|
6435
|
+
{
|
|
6436
|
+
style: {
|
|
6437
|
+
width: "100%",
|
|
6438
|
+
borderRadius: "var(--r-2xl)",
|
|
6439
|
+
overflow: "hidden",
|
|
6440
|
+
boxShadow: "0 24px 64px -12px rgba(2, 8, 20, 0.55), 0 2px 8px rgba(2, 8, 20, 0.3)"
|
|
6441
|
+
},
|
|
6442
|
+
children: [
|
|
6443
|
+
/* @__PURE__ */ jsx67(
|
|
6444
|
+
"div",
|
|
6445
|
+
{
|
|
6446
|
+
style: {
|
|
6447
|
+
height: 4,
|
|
6448
|
+
background: "linear-gradient(90deg, var(--blue-400), var(--blue-600), var(--navy))"
|
|
6449
|
+
}
|
|
6450
|
+
}
|
|
6451
|
+
),
|
|
6452
|
+
/* @__PURE__ */ jsx67(Card, { children: /* @__PURE__ */ jsxs61(
|
|
6453
|
+
"div",
|
|
6454
|
+
{
|
|
6455
|
+
style: {
|
|
6456
|
+
display: "flex",
|
|
6457
|
+
flexDirection: "column",
|
|
6458
|
+
gap: "var(--s-20)",
|
|
6459
|
+
alignItems: "center",
|
|
6460
|
+
textAlign: "center",
|
|
6461
|
+
padding: "var(--s-8) 0"
|
|
6462
|
+
},
|
|
6463
|
+
children: [
|
|
6464
|
+
/* @__PURE__ */ jsxs61("div", { children: [
|
|
6465
|
+
/* @__PURE__ */ jsx67("h1", { className: "fd-h3", style: { color: "var(--navy)" }, children: productName }),
|
|
6466
|
+
/* @__PURE__ */ jsx67("p", { className: "fd-body-sm fd-muted", style: { marginTop: "var(--s-4)" }, children: continueAs ? "Your session timed out, but you're likely still signed in" : "Sign in with your flytedesk workspace account" })
|
|
6467
|
+
] }),
|
|
6468
|
+
error ? /* @__PURE__ */ jsx67("div", { role: "alert", style: { width: "100%" }, children: /* @__PURE__ */ jsx67(Banner, { tone: "danger", title: error }) }) : null,
|
|
6469
|
+
continueAs ? /* @__PURE__ */ jsxs61(Fragment18, { children: [
|
|
6470
|
+
/* @__PURE__ */ jsx67(
|
|
6471
|
+
Button,
|
|
6472
|
+
{
|
|
6473
|
+
variant: "primary",
|
|
6474
|
+
style: { width: "100%" },
|
|
6475
|
+
loading: resuming,
|
|
6476
|
+
disabled: resuming,
|
|
6477
|
+
onClick: handleContinue,
|
|
6478
|
+
children: resuming ? "Resuming\u2026" : `Continue as ${continueAs.name}`
|
|
6479
|
+
}
|
|
6480
|
+
),
|
|
6481
|
+
/* @__PURE__ */ jsx67(
|
|
6482
|
+
"button",
|
|
6483
|
+
{
|
|
6484
|
+
type: "button",
|
|
6485
|
+
className: "fd-body-sm fd-muted",
|
|
6486
|
+
style: {
|
|
6487
|
+
background: "none",
|
|
6488
|
+
border: "none",
|
|
6489
|
+
cursor: "pointer",
|
|
6490
|
+
textDecoration: "underline",
|
|
6491
|
+
padding: 0
|
|
6492
|
+
},
|
|
6493
|
+
disabled: resuming,
|
|
6494
|
+
onClick: continueAs.onDecline,
|
|
6495
|
+
children: "Not you? Sign in with flytedesk ID"
|
|
6496
|
+
}
|
|
6497
|
+
)
|
|
6498
|
+
] }) : /* @__PURE__ */ jsx67(
|
|
6499
|
+
Button,
|
|
6500
|
+
{
|
|
6501
|
+
variant: "primary",
|
|
6502
|
+
style: { width: "100%" },
|
|
6503
|
+
loading: signingIn,
|
|
6504
|
+
disabled: signingIn,
|
|
6505
|
+
onClick: handleSignIn,
|
|
6506
|
+
children: /* @__PURE__ */ jsxs61(
|
|
6507
|
+
"span",
|
|
6508
|
+
{
|
|
6509
|
+
style: {
|
|
6510
|
+
display: "flex",
|
|
6511
|
+
flexDirection: "row",
|
|
6512
|
+
alignItems: "center",
|
|
6513
|
+
justifyContent: "center",
|
|
6514
|
+
gap: "var(--s-8)",
|
|
6515
|
+
flexWrap: "nowrap"
|
|
6516
|
+
},
|
|
6517
|
+
children: [
|
|
6518
|
+
/* @__PURE__ */ jsx67(GoogleGlyph, {}),
|
|
6519
|
+
/* @__PURE__ */ jsx67("span", { children: signingIn ? "Signing in\u2026" : "Sign in with flytedesk ID" })
|
|
6520
|
+
]
|
|
6521
|
+
}
|
|
6522
|
+
)
|
|
6523
|
+
}
|
|
6524
|
+
),
|
|
6525
|
+
/* @__PURE__ */ jsx67("p", { className: "fd-body-sm fd-muted", style: { fontSize: "12px" }, children: "One account, every flytedesk app." })
|
|
6526
|
+
]
|
|
6527
|
+
}
|
|
6528
|
+
) })
|
|
6529
|
+
]
|
|
6530
|
+
}
|
|
6531
|
+
)
|
|
6532
|
+
]
|
|
6533
|
+
}
|
|
6534
|
+
)
|
|
6535
|
+
]
|
|
6536
|
+
}
|
|
6537
|
+
);
|
|
6538
|
+
}
|
|
6539
|
+
function GoogleGlyph() {
|
|
6540
|
+
return /* @__PURE__ */ jsxs61("svg", { width: "18", height: "18", viewBox: "0 0 18 18", "aria-hidden": true, children: [
|
|
6541
|
+
/* @__PURE__ */ jsx67(
|
|
6542
|
+
"path",
|
|
6543
|
+
{
|
|
6544
|
+
fill: "#4285F4",
|
|
6545
|
+
d: "M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.87 2.68-6.62Z"
|
|
6546
|
+
}
|
|
6547
|
+
),
|
|
6548
|
+
/* @__PURE__ */ jsx67(
|
|
6549
|
+
"path",
|
|
6550
|
+
{
|
|
6551
|
+
fill: "#34A853",
|
|
6552
|
+
d: "M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.81.54-1.84.87-3.04.87-2.34 0-4.32-1.58-5.03-3.7H.96v2.33A9 9 0 0 0 9 18Z"
|
|
6553
|
+
}
|
|
6554
|
+
),
|
|
6555
|
+
/* @__PURE__ */ jsx67(
|
|
6556
|
+
"path",
|
|
6557
|
+
{
|
|
6558
|
+
fill: "#FBBC05",
|
|
6559
|
+
d: "M3.97 10.73A5.4 5.4 0 0 1 3.68 9c0-.6.1-1.19.29-1.73V4.94H.96A9 9 0 0 0 0 9c0 1.45.35 2.83.96 4.06l3.01-2.33Z"
|
|
6560
|
+
}
|
|
6561
|
+
),
|
|
6562
|
+
/* @__PURE__ */ jsx67(
|
|
6563
|
+
"path",
|
|
6564
|
+
{
|
|
6565
|
+
fill: "#EA4335",
|
|
6566
|
+
d: "M9 3.58c1.32 0 2.51.45 3.44 1.35l2.59-2.59C13.46.89 11.43 0 9 0A9 9 0 0 0 .96 4.94l3.01 2.33C4.68 5.16 6.66 3.58 9 3.58Z"
|
|
6567
|
+
}
|
|
6568
|
+
)
|
|
6569
|
+
] });
|
|
6570
|
+
}
|
|
6571
|
+
|
|
6379
6572
|
// src/components/platform/RoadmapTimeline.tsx
|
|
6380
|
-
import * as
|
|
6573
|
+
import * as React45 from "react";
|
|
6381
6574
|
|
|
6382
6575
|
// src/kits/session.ts
|
|
6383
|
-
import * as
|
|
6576
|
+
import * as React43 from "react";
|
|
6384
6577
|
var PERMISSION_CATALOG = [
|
|
6385
6578
|
{ group: "Plans", items: [
|
|
6386
6579
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -7947,8 +8140,8 @@ function roadmap(overrides) {
|
|
|
7947
8140
|
};
|
|
7948
8141
|
}
|
|
7949
8142
|
function useSession() {
|
|
7950
|
-
const [s, setS] =
|
|
7951
|
-
|
|
8143
|
+
const [s, setS] = React43.useState(getSession);
|
|
8144
|
+
React43.useEffect(() => subscribe(setS), []);
|
|
7952
8145
|
return s;
|
|
7953
8146
|
}
|
|
7954
8147
|
var SessionKit = {
|
|
@@ -7981,7 +8174,7 @@ var SessionKit = {
|
|
|
7981
8174
|
};
|
|
7982
8175
|
function DemoSessionProvider({ children }) {
|
|
7983
8176
|
const session = useSession();
|
|
7984
|
-
const value =
|
|
8177
|
+
const value = React43.useMemo(
|
|
7985
8178
|
() => ({
|
|
7986
8179
|
user: session.user,
|
|
7987
8180
|
roles: session.roles,
|
|
@@ -7997,11 +8190,11 @@ function DemoSessionProvider({ children }) {
|
|
|
7997
8190
|
}),
|
|
7998
8191
|
[session]
|
|
7999
8192
|
);
|
|
8000
|
-
return
|
|
8193
|
+
return React43.createElement(SessionProvider, { value }, children);
|
|
8001
8194
|
}
|
|
8002
8195
|
|
|
8003
8196
|
// src/kits/runtime.ts
|
|
8004
|
-
import * as
|
|
8197
|
+
import * as React44 from "react";
|
|
8005
8198
|
var WIRED_ENDPOINTS = [
|
|
8006
8199
|
// Nothing yet. Every id below would come from a real service:
|
|
8007
8200
|
// "plan.get", "placements.list", …
|
|
@@ -8172,8 +8365,8 @@ var RuntimeKit = {
|
|
|
8172
8365
|
};
|
|
8173
8366
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
8174
8367
|
function useRuntimeMode() {
|
|
8175
|
-
const [m, setM] =
|
|
8176
|
-
|
|
8368
|
+
const [m, setM] = React44.useState(RuntimeKit.getMode());
|
|
8369
|
+
React44.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
8177
8370
|
return m;
|
|
8178
8371
|
}
|
|
8179
8372
|
function useFeatureStatus(key) {
|
|
@@ -8192,7 +8385,7 @@ var UseRuntimeMode = useRuntimeMode;
|
|
|
8192
8385
|
var UseFeatureStatus = useFeatureStatus;
|
|
8193
8386
|
|
|
8194
8387
|
// src/components/platform/RoadmapTimeline.tsx
|
|
8195
|
-
import { jsx as
|
|
8388
|
+
import { jsx as jsx68, jsxs as jsxs62 } from "react/jsx-runtime";
|
|
8196
8389
|
var STATUS = {
|
|
8197
8390
|
shipped: { tone: "success", icon: "check-circle", label: "Wired" },
|
|
8198
8391
|
next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
|
|
@@ -8207,45 +8400,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
8207
8400
|
const s = STATUS[item.status] || STATUS.planned;
|
|
8208
8401
|
const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
|
|
8209
8402
|
const blocking = deps.filter((d) => !d.implemented);
|
|
8210
|
-
return /* @__PURE__ */
|
|
8211
|
-
/* @__PURE__ */
|
|
8212
|
-
/* @__PURE__ */
|
|
8213
|
-
/* @__PURE__ */
|
|
8214
|
-
/* @__PURE__ */
|
|
8403
|
+
return /* @__PURE__ */ jsx68(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs62("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
8404
|
+
/* @__PURE__ */ jsxs62("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
8405
|
+
/* @__PURE__ */ jsx68("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
|
|
8406
|
+
/* @__PURE__ */ jsx68(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
|
|
8407
|
+
/* @__PURE__ */ jsx68(Badge, { tone: s.tone, icon: s.icon, children: s.label })
|
|
8215
8408
|
] }),
|
|
8216
|
-
/* @__PURE__ */
|
|
8217
|
-
item.backend ? /* @__PURE__ */
|
|
8218
|
-
/* @__PURE__ */
|
|
8219
|
-
/* @__PURE__ */
|
|
8409
|
+
/* @__PURE__ */ jsx68("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
|
|
8410
|
+
item.backend ? /* @__PURE__ */ jsxs62("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
|
|
8411
|
+
/* @__PURE__ */ jsx68("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
|
|
8412
|
+
/* @__PURE__ */ jsx68("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
|
|
8220
8413
|
] }) : null,
|
|
8221
|
-
/* @__PURE__ */
|
|
8222
|
-
item.effort ? /* @__PURE__ */
|
|
8223
|
-
/* @__PURE__ */
|
|
8414
|
+
/* @__PURE__ */ jsxs62("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
8415
|
+
item.effort ? /* @__PURE__ */ jsxs62("span", { className: "fd-body-sm fd-muted", children: [
|
|
8416
|
+
/* @__PURE__ */ jsx68("i", { className: "ph ph-hourglass-medium" }),
|
|
8224
8417
|
" ",
|
|
8225
8418
|
item.effort
|
|
8226
8419
|
] }) : null,
|
|
8227
|
-
/* @__PURE__ */
|
|
8228
|
-
/* @__PURE__ */
|
|
8420
|
+
/* @__PURE__ */ jsxs62("span", { className: "fd-body-sm fd-muted", children: [
|
|
8421
|
+
/* @__PURE__ */ jsx68("i", { className: "ph ph-user" }),
|
|
8229
8422
|
" ",
|
|
8230
8423
|
item.owner
|
|
8231
8424
|
] }),
|
|
8232
|
-
item.screen ? /* @__PURE__ */
|
|
8233
|
-
/* @__PURE__ */
|
|
8234
|
-
/* @__PURE__ */
|
|
8425
|
+
item.screen ? /* @__PURE__ */ jsx68(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
|
|
8426
|
+
/* @__PURE__ */ jsx68("span", { style: { flex: 1 } }),
|
|
8427
|
+
/* @__PURE__ */ jsx68(
|
|
8235
8428
|
"button",
|
|
8236
8429
|
{
|
|
8237
8430
|
type: "button",
|
|
8238
8431
|
onClick: () => onOpenFlag && onOpenFlag(item.key),
|
|
8239
8432
|
style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
|
|
8240
|
-
children: /* @__PURE__ */
|
|
8433
|
+
children: /* @__PURE__ */ jsx68("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
|
|
8241
8434
|
}
|
|
8242
8435
|
)
|
|
8243
8436
|
] }),
|
|
8244
|
-
deps.length ? /* @__PURE__ */
|
|
8245
|
-
/* @__PURE__ */
|
|
8246
|
-
deps.map((d) => /* @__PURE__ */
|
|
8437
|
+
deps.length ? /* @__PURE__ */ jsxs62("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
|
|
8438
|
+
/* @__PURE__ */ jsx68("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
|
|
8439
|
+
deps.map((d) => /* @__PURE__ */ jsx68(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
|
|
8247
8440
|
] }) : null,
|
|
8248
|
-
blocking.length && !item.implemented ? /* @__PURE__ */
|
|
8441
|
+
blocking.length && !item.implemented ? /* @__PURE__ */ jsxs62("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
|
|
8249
8442
|
"Blocked until ",
|
|
8250
8443
|
blocking.map((d) => d.label).join(" and "),
|
|
8251
8444
|
" ",
|
|
@@ -8256,12 +8449,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
8256
8449
|
}
|
|
8257
8450
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
8258
8451
|
const session = SessionKit.useSession();
|
|
8259
|
-
const [project, setProject] =
|
|
8260
|
-
const [q, setQ] =
|
|
8261
|
-
const scrollRef =
|
|
8262
|
-
const nowRef =
|
|
8263
|
-
const rm =
|
|
8264
|
-
const byKey =
|
|
8452
|
+
const [project, setProject] = React45.useState("");
|
|
8453
|
+
const [q, setQ] = React45.useState("");
|
|
8454
|
+
const scrollRef = React45.useRef(null);
|
|
8455
|
+
const nowRef = React45.useRef(null);
|
|
8456
|
+
const rm = React45.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
8457
|
+
const byKey = React45.useMemo(() => {
|
|
8265
8458
|
const m = {};
|
|
8266
8459
|
rm.items.forEach((i) => {
|
|
8267
8460
|
m[i.key] = i;
|
|
@@ -8270,7 +8463,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
8270
8463
|
}, [rm]);
|
|
8271
8464
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
8272
8465
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
8273
|
-
|
|
8466
|
+
React45.useEffect(() => {
|
|
8274
8467
|
let raf1 = 0, raf2 = 0;
|
|
8275
8468
|
const place = () => {
|
|
8276
8469
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -8298,23 +8491,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
8298
8491
|
}, 0);
|
|
8299
8492
|
const nextPhase = items.find((i) => !i.implemented);
|
|
8300
8493
|
let lastPhase = null;
|
|
8301
|
-
return /* @__PURE__ */
|
|
8302
|
-
/* @__PURE__ */
|
|
8303
|
-
/* @__PURE__ */
|
|
8304
|
-
/* @__PURE__ */
|
|
8305
|
-
/* @__PURE__ */
|
|
8494
|
+
return /* @__PURE__ */ jsxs62("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
|
|
8495
|
+
/* @__PURE__ */ jsxs62("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
8496
|
+
/* @__PURE__ */ jsx68("span", { className: "fd-overline fd-muted", children: "Architecture" }),
|
|
8497
|
+
/* @__PURE__ */ jsx68("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
8498
|
+
/* @__PURE__ */ jsx68("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." })
|
|
8306
8499
|
] }),
|
|
8307
|
-
/* @__PURE__ */
|
|
8308
|
-
/* @__PURE__ */
|
|
8309
|
-
/* @__PURE__ */
|
|
8310
|
-
/* @__PURE__ */
|
|
8311
|
-
/* @__PURE__ */
|
|
8500
|
+
/* @__PURE__ */ jsxs62("div", { className: "fd-grid-stats is-thin", children: [
|
|
8501
|
+
/* @__PURE__ */ jsx68(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
|
|
8502
|
+
/* @__PURE__ */ jsx68(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
|
|
8503
|
+
/* @__PURE__ */ jsx68(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
|
|
8504
|
+
/* @__PURE__ */ jsx68(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
|
|
8312
8505
|
] }),
|
|
8313
|
-
/* @__PURE__ */
|
|
8314
|
-
/* @__PURE__ */
|
|
8315
|
-
/* @__PURE__ */
|
|
8316
|
-
/* @__PURE__ */
|
|
8317
|
-
/* @__PURE__ */
|
|
8506
|
+
/* @__PURE__ */ jsxs62("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
8507
|
+
/* @__PURE__ */ jsx68(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 } }),
|
|
8508
|
+
/* @__PURE__ */ jsx68(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
|
|
8509
|
+
/* @__PURE__ */ jsx68("span", { style: { flex: 1 } }),
|
|
8510
|
+
/* @__PURE__ */ jsx68(
|
|
8318
8511
|
Button,
|
|
8319
8512
|
{
|
|
8320
8513
|
size: "sm",
|
|
@@ -8328,7 +8521,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
8328
8521
|
}
|
|
8329
8522
|
)
|
|
8330
8523
|
] }),
|
|
8331
|
-
/* @__PURE__ */
|
|
8524
|
+
/* @__PURE__ */ jsx68(
|
|
8332
8525
|
Flag,
|
|
8333
8526
|
{
|
|
8334
8527
|
tone: "info",
|
|
@@ -8337,60 +8530,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
8337
8530
|
actions: null
|
|
8338
8531
|
}
|
|
8339
8532
|
),
|
|
8340
|
-
/* @__PURE__ */
|
|
8341
|
-
/* @__PURE__ */
|
|
8533
|
+
/* @__PURE__ */ jsx68("div", { className: "fd-rm", children: /* @__PURE__ */ jsx68("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs62("div", { className: "fd-rm-track", children: [
|
|
8534
|
+
/* @__PURE__ */ jsx68("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx68("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
|
|
8342
8535
|
items.map((item, n) => {
|
|
8343
8536
|
const showPhase = item.phase !== lastPhase;
|
|
8344
8537
|
lastPhase = item.phase;
|
|
8345
8538
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
8346
8539
|
const isBoundary = n === firstPending;
|
|
8347
|
-
return /* @__PURE__ */
|
|
8348
|
-
showPhase ? /* @__PURE__ */
|
|
8349
|
-
/* @__PURE__ */
|
|
8350
|
-
/* @__PURE__ */
|
|
8351
|
-
item.phase === 0 ? null : /* @__PURE__ */
|
|
8540
|
+
return /* @__PURE__ */ jsxs62(React45.Fragment, { children: [
|
|
8541
|
+
showPhase ? /* @__PURE__ */ jsxs62("div", { className: "fd-rm-era", children: [
|
|
8542
|
+
/* @__PURE__ */ jsxs62("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
8543
|
+
/* @__PURE__ */ jsx68("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
8544
|
+
item.phase === 0 ? null : /* @__PURE__ */ jsxs62("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
8352
8545
|
fmtDate(item.phaseStart),
|
|
8353
8546
|
" \u2013 ",
|
|
8354
8547
|
fmtDate(item.date)
|
|
8355
8548
|
] }),
|
|
8356
|
-
/* @__PURE__ */
|
|
8549
|
+
/* @__PURE__ */ jsxs62("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
8357
8550
|
"\xB7 ",
|
|
8358
8551
|
inPhase,
|
|
8359
8552
|
" feature",
|
|
8360
8553
|
inPhase === 1 ? "" : "s"
|
|
8361
8554
|
] })
|
|
8362
8555
|
] }),
|
|
8363
|
-
item.phaseWhy ? /* @__PURE__ */
|
|
8556
|
+
item.phaseWhy ? /* @__PURE__ */ jsx68("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
|
|
8364
8557
|
] }) : null,
|
|
8365
|
-
isBoundary ? /* @__PURE__ */
|
|
8366
|
-
/* @__PURE__ */
|
|
8558
|
+
isBoundary ? /* @__PURE__ */ jsx68("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs62("span", { className: "fd-rm-now-pill", children: [
|
|
8559
|
+
/* @__PURE__ */ jsx68("i", { className: "ph ph-map-pin" }),
|
|
8367
8560
|
" You are here \u2014 everything above is wired"
|
|
8368
8561
|
] }) }) : null,
|
|
8369
|
-
/* @__PURE__ */
|
|
8370
|
-
/* @__PURE__ */
|
|
8371
|
-
/* @__PURE__ */
|
|
8562
|
+
/* @__PURE__ */ jsxs62("div", { className: "fd-rm-row", children: [
|
|
8563
|
+
/* @__PURE__ */ jsx68("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
|
|
8564
|
+
/* @__PURE__ */ jsxs62("div", { className: "fd-rm-date", children: [
|
|
8372
8565
|
fmtDate(item.date),
|
|
8373
|
-
/* @__PURE__ */
|
|
8374
|
-
/* @__PURE__ */
|
|
8566
|
+
/* @__PURE__ */ jsx68("br", {}),
|
|
8567
|
+
/* @__PURE__ */ jsx68("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
|
|
8375
8568
|
] }),
|
|
8376
|
-
/* @__PURE__ */
|
|
8569
|
+
/* @__PURE__ */ jsx68(RoadmapCard, { item, byKey, onOpenFlag })
|
|
8377
8570
|
] })
|
|
8378
8571
|
] }, item.key);
|
|
8379
8572
|
}),
|
|
8380
|
-
!items.length ? /* @__PURE__ */
|
|
8573
|
+
!items.length ? /* @__PURE__ */ jsx68("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
|
|
8381
8574
|
] }) }) }),
|
|
8382
|
-
/* @__PURE__ */
|
|
8575
|
+
/* @__PURE__ */ jsxs62("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
|
|
8383
8576
|
"Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
|
|
8384
|
-
/* @__PURE__ */
|
|
8577
|
+
/* @__PURE__ */ jsx68("code", { className: "fd-mono", children: "implemented" }),
|
|
8385
8578
|
" field, so this page cannot drift from what the apps actually do."
|
|
8386
8579
|
] })
|
|
8387
8580
|
] });
|
|
8388
8581
|
}
|
|
8389
8582
|
|
|
8390
8583
|
// src/components/platform/ComingSoon.tsx
|
|
8391
|
-
import * as
|
|
8584
|
+
import * as React46 from "react";
|
|
8392
8585
|
import { createPortal as createPortal5 } from "react-dom";
|
|
8393
|
-
import { Fragment as
|
|
8586
|
+
import { Fragment as Fragment20, jsx as jsx69, jsxs as jsxs63 } from "react/jsx-runtime";
|
|
8394
8587
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
8395
8588
|
function readBypassed() {
|
|
8396
8589
|
try {
|
|
@@ -8406,8 +8599,8 @@ function writeBypassed(list) {
|
|
|
8406
8599
|
}
|
|
8407
8600
|
}
|
|
8408
8601
|
function useBypass(key) {
|
|
8409
|
-
const [on, setOn] =
|
|
8410
|
-
|
|
8602
|
+
const [on, setOn] = React46.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
8603
|
+
React46.useEffect(() => {
|
|
8411
8604
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
8412
8605
|
}, [key]);
|
|
8413
8606
|
const set = (next) => {
|
|
@@ -8420,43 +8613,43 @@ function useBypass(key) {
|
|
|
8420
8613
|
return [on, set];
|
|
8421
8614
|
}
|
|
8422
8615
|
function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
|
|
8423
|
-
return /* @__PURE__ */
|
|
8424
|
-
/* @__PURE__ */
|
|
8425
|
-
/* @__PURE__ */
|
|
8616
|
+
return /* @__PURE__ */ jsxs63(Fragment20, { children: [
|
|
8617
|
+
/* @__PURE__ */ jsxs63("span", { className: "fd-soon-badge", children: [
|
|
8618
|
+
/* @__PURE__ */ jsx69("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
8426
8619
|
label
|
|
8427
8620
|
] }),
|
|
8428
|
-
detail ? /* @__PURE__ */
|
|
8429
|
-
backend ? /* @__PURE__ */
|
|
8430
|
-
/* @__PURE__ */
|
|
8621
|
+
detail ? /* @__PURE__ */ jsx69("span", { className: "fd-soon-detail", children: detail }) : null,
|
|
8622
|
+
backend ? /* @__PURE__ */ jsxs63("span", { className: "fd-soon-backend", children: [
|
|
8623
|
+
/* @__PURE__ */ jsx69("span", { className: "fd-overline", children: "Needs" }),
|
|
8431
8624
|
" ",
|
|
8432
8625
|
backend
|
|
8433
8626
|
] }) : null,
|
|
8434
|
-
eta || effort || onRoadmap ? /* @__PURE__ */
|
|
8435
|
-
eta ? /* @__PURE__ */
|
|
8436
|
-
/* @__PURE__ */
|
|
8627
|
+
eta || effort || onRoadmap ? /* @__PURE__ */ jsxs63("span", { className: "fd-soon-meta", children: [
|
|
8628
|
+
eta ? /* @__PURE__ */ jsxs63("span", { children: [
|
|
8629
|
+
/* @__PURE__ */ jsx69("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
|
|
8437
8630
|
" ",
|
|
8438
8631
|
eta
|
|
8439
8632
|
] }) : null,
|
|
8440
|
-
effort ? /* @__PURE__ */
|
|
8441
|
-
/* @__PURE__ */
|
|
8633
|
+
effort ? /* @__PURE__ */ jsxs63("span", { children: [
|
|
8634
|
+
/* @__PURE__ */ jsx69("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
|
|
8442
8635
|
" ",
|
|
8443
8636
|
effort
|
|
8444
8637
|
] }) : null,
|
|
8445
|
-
onRoadmap ? /* @__PURE__ */
|
|
8638
|
+
onRoadmap ? /* @__PURE__ */ jsxs63("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
8446
8639
|
"See the roadmap ",
|
|
8447
|
-
/* @__PURE__ */
|
|
8640
|
+
/* @__PURE__ */ jsx69("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
8448
8641
|
] }) : null
|
|
8449
8642
|
] }) : null,
|
|
8450
|
-
allowed ? /* @__PURE__ */
|
|
8451
|
-
/* @__PURE__ */
|
|
8643
|
+
allowed ? /* @__PURE__ */ jsxs63("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
|
|
8644
|
+
/* @__PURE__ */ jsx69("i", { className: "ph ph-eye", "aria-hidden": "true" }),
|
|
8452
8645
|
" View and use it anyway"
|
|
8453
8646
|
] }) : null
|
|
8454
8647
|
] });
|
|
8455
8648
|
}
|
|
8456
8649
|
function useHoverCard(open) {
|
|
8457
|
-
const anchor =
|
|
8458
|
-
const [pos, setPos] =
|
|
8459
|
-
|
|
8650
|
+
const anchor = React46.useRef(null);
|
|
8651
|
+
const [pos, setPos] = React46.useState(null);
|
|
8652
|
+
React46.useLayoutEffect(() => {
|
|
8460
8653
|
if (!open || !anchor.current) {
|
|
8461
8654
|
setPos(null);
|
|
8462
8655
|
return;
|
|
@@ -8508,9 +8701,9 @@ function ComingSoon({
|
|
|
8508
8701
|
const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
|
|
8509
8702
|
if (inline) {
|
|
8510
8703
|
if (allowed && bypassed) {
|
|
8511
|
-
return /* @__PURE__ */
|
|
8704
|
+
return /* @__PURE__ */ jsxs63("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
|
|
8512
8705
|
children,
|
|
8513
|
-
/* @__PURE__ */
|
|
8706
|
+
/* @__PURE__ */ jsx69(
|
|
8514
8707
|
"button",
|
|
8515
8708
|
{
|
|
8516
8709
|
type: "button",
|
|
@@ -8518,12 +8711,12 @@ function ComingSoon({
|
|
|
8518
8711
|
title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
|
|
8519
8712
|
onClick: () => setBypassed(false),
|
|
8520
8713
|
"aria-label": "Re-blur this unwired feature",
|
|
8521
|
-
children: /* @__PURE__ */
|
|
8714
|
+
children: /* @__PURE__ */ jsx69("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
8522
8715
|
}
|
|
8523
8716
|
)
|
|
8524
8717
|
] });
|
|
8525
8718
|
}
|
|
8526
|
-
return /* @__PURE__ */
|
|
8719
|
+
return /* @__PURE__ */ jsx69(
|
|
8527
8720
|
InlineSoon,
|
|
8528
8721
|
{
|
|
8529
8722
|
label,
|
|
@@ -8543,20 +8736,20 @@ function ComingSoon({
|
|
|
8543
8736
|
);
|
|
8544
8737
|
}
|
|
8545
8738
|
if (allowed && bypassed) {
|
|
8546
|
-
return /* @__PURE__ */
|
|
8547
|
-
/* @__PURE__ */
|
|
8548
|
-
/* @__PURE__ */
|
|
8549
|
-
/* @__PURE__ */
|
|
8739
|
+
return /* @__PURE__ */ jsxs63("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
|
|
8740
|
+
/* @__PURE__ */ jsxs63("div", { className: "fd-soon-bar", role: "status", children: [
|
|
8741
|
+
/* @__PURE__ */ jsxs63("span", { className: "fd-soon-badge", children: [
|
|
8742
|
+
/* @__PURE__ */ jsx69("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
8550
8743
|
"Unwired feature \u2014 you are using it anyway"
|
|
8551
8744
|
] }),
|
|
8552
|
-
/* @__PURE__ */
|
|
8553
|
-
/* @__PURE__ */
|
|
8554
|
-
onRoadmap ? /* @__PURE__ */
|
|
8745
|
+
/* @__PURE__ */ jsx69("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
|
|
8746
|
+
/* @__PURE__ */ jsxs63("span", { className: "fd-soon-bar-actions", children: [
|
|
8747
|
+
onRoadmap ? /* @__PURE__ */ jsxs63("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
8555
8748
|
"Roadmap ",
|
|
8556
|
-
/* @__PURE__ */
|
|
8749
|
+
/* @__PURE__ */ jsx69("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
8557
8750
|
] }) : null,
|
|
8558
|
-
/* @__PURE__ */
|
|
8559
|
-
/* @__PURE__ */
|
|
8751
|
+
/* @__PURE__ */ jsxs63("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
|
|
8752
|
+
/* @__PURE__ */ jsx69("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
|
|
8560
8753
|
" Re-blur"
|
|
8561
8754
|
] })
|
|
8562
8755
|
] })
|
|
@@ -8564,10 +8757,10 @@ function ComingSoon({
|
|
|
8564
8757
|
children
|
|
8565
8758
|
] });
|
|
8566
8759
|
}
|
|
8567
|
-
return /* @__PURE__ */
|
|
8568
|
-
/* @__PURE__ */
|
|
8569
|
-
/* @__PURE__ */
|
|
8570
|
-
/* @__PURE__ */
|
|
8760
|
+
return /* @__PURE__ */ jsxs63("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
|
|
8761
|
+
/* @__PURE__ */ jsx69("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
8762
|
+
/* @__PURE__ */ jsx69("div", { className: "fd-soon-veil" }),
|
|
8763
|
+
/* @__PURE__ */ jsx69("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx69(
|
|
8571
8764
|
SoonCard,
|
|
8572
8765
|
{
|
|
8573
8766
|
label,
|
|
@@ -8583,10 +8776,10 @@ function ComingSoon({
|
|
|
8583
8776
|
] });
|
|
8584
8777
|
}
|
|
8585
8778
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
8586
|
-
const [open, setOpen] =
|
|
8779
|
+
const [open, setOpen] = React46.useState(false);
|
|
8587
8780
|
const [anchor, pos] = useHoverCard(open);
|
|
8588
8781
|
const zIndex = useOverlayLayer(open);
|
|
8589
|
-
const close =
|
|
8782
|
+
const close = React46.useRef(null);
|
|
8590
8783
|
const show = () => {
|
|
8591
8784
|
if (close.current) {
|
|
8592
8785
|
clearTimeout(close.current);
|
|
@@ -8602,10 +8795,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
8602
8795
|
setOpen(false);
|
|
8603
8796
|
}, 140);
|
|
8604
8797
|
};
|
|
8605
|
-
|
|
8798
|
+
React46.useEffect(() => () => {
|
|
8606
8799
|
if (close.current) clearTimeout(close.current);
|
|
8607
8800
|
}, []);
|
|
8608
|
-
return /* @__PURE__ */
|
|
8801
|
+
return /* @__PURE__ */ jsxs63(
|
|
8609
8802
|
"span",
|
|
8610
8803
|
{
|
|
8611
8804
|
ref: anchor,
|
|
@@ -8616,8 +8809,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
8616
8809
|
onBlur: hide,
|
|
8617
8810
|
...rest,
|
|
8618
8811
|
children: [
|
|
8619
|
-
/* @__PURE__ */
|
|
8620
|
-
/* @__PURE__ */
|
|
8812
|
+
/* @__PURE__ */ jsx69("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
8813
|
+
/* @__PURE__ */ jsx69(
|
|
8621
8814
|
"button",
|
|
8622
8815
|
{
|
|
8623
8816
|
type: "button",
|
|
@@ -8628,11 +8821,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
8628
8821
|
onFocus: show,
|
|
8629
8822
|
onBlur: hide,
|
|
8630
8823
|
onClick: () => open ? setOpen(false) : show(),
|
|
8631
|
-
children: /* @__PURE__ */
|
|
8824
|
+
children: /* @__PURE__ */ jsx69("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
8632
8825
|
}
|
|
8633
8826
|
),
|
|
8634
8827
|
open && pos ? createPortal5(
|
|
8635
|
-
/* @__PURE__ */
|
|
8828
|
+
/* @__PURE__ */ jsx69(LayerProvider, { zIndex, children: /* @__PURE__ */ jsx69(
|
|
8636
8829
|
"div",
|
|
8637
8830
|
{
|
|
8638
8831
|
className: "fd-soon-note fd-soon-hovercard",
|
|
@@ -8640,7 +8833,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
8640
8833
|
style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
|
|
8641
8834
|
onMouseEnter: show,
|
|
8642
8835
|
onMouseLeave: hide,
|
|
8643
|
-
children: /* @__PURE__ */
|
|
8836
|
+
children: /* @__PURE__ */ jsx69(
|
|
8644
8837
|
SoonCard,
|
|
8645
8838
|
{
|
|
8646
8839
|
label,
|
|
@@ -8670,10 +8863,10 @@ function formatEta(iso2) {
|
|
|
8670
8863
|
var FormatEta = formatEta;
|
|
8671
8864
|
|
|
8672
8865
|
// src/components/platform/Gate.tsx
|
|
8673
|
-
import { jsx as
|
|
8866
|
+
import { jsx as jsx70, jsxs as jsxs64 } from "react/jsx-runtime";
|
|
8674
8867
|
function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
|
|
8675
8868
|
const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
|
|
8676
|
-
return /* @__PURE__ */
|
|
8869
|
+
return /* @__PURE__ */ jsxs64(
|
|
8677
8870
|
"div",
|
|
8678
8871
|
{
|
|
8679
8872
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -8689,14 +8882,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
8689
8882
|
},
|
|
8690
8883
|
...rest,
|
|
8691
8884
|
children: [
|
|
8692
|
-
/* @__PURE__ */
|
|
8693
|
-
/* @__PURE__ */
|
|
8694
|
-
/* @__PURE__ */
|
|
8885
|
+
/* @__PURE__ */ jsxs64("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
8886
|
+
/* @__PURE__ */ jsx70("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
8887
|
+
/* @__PURE__ */ jsx70("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
|
|
8695
8888
|
] }),
|
|
8696
|
-
/* @__PURE__ */
|
|
8697
|
-
need.length ? /* @__PURE__ */
|
|
8698
|
-
/* @__PURE__ */
|
|
8699
|
-
need.map((p) => /* @__PURE__ */
|
|
8889
|
+
/* @__PURE__ */ jsx70("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." }),
|
|
8890
|
+
need.length ? /* @__PURE__ */ jsxs64("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
|
|
8891
|
+
/* @__PURE__ */ jsx70("span", { className: "fd-overline fd-muted", children: "Requires" }),
|
|
8892
|
+
need.map((p) => /* @__PURE__ */ jsx70("code", { className: "fd-mono", style: {
|
|
8700
8893
|
fontSize: 11.5,
|
|
8701
8894
|
padding: "2px 7px",
|
|
8702
8895
|
borderRadius: 5,
|
|
@@ -8717,7 +8910,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, compact: compact3 =
|
|
|
8717
8910
|
if (ok) return children;
|
|
8718
8911
|
if (fallback !== void 0) return fallback;
|
|
8719
8912
|
if (silent) return null;
|
|
8720
|
-
return /* @__PURE__ */
|
|
8913
|
+
return /* @__PURE__ */ jsx70(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
|
|
8721
8914
|
}
|
|
8722
8915
|
function FeatureGate({
|
|
8723
8916
|
flag,
|
|
@@ -8740,7 +8933,7 @@ function FeatureGate({
|
|
|
8740
8933
|
const f = SessionKit.findFlag(flag) || {};
|
|
8741
8934
|
const missing = rt.missing || [];
|
|
8742
8935
|
const canBypass = bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
|
|
8743
|
-
return /* @__PURE__ */
|
|
8936
|
+
return /* @__PURE__ */ jsx70(
|
|
8744
8937
|
ComingSoon,
|
|
8745
8938
|
{
|
|
8746
8939
|
label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
|
|
@@ -8761,26 +8954,26 @@ function FeatureGate({
|
|
|
8761
8954
|
function PermissionHint({ perm, children }) {
|
|
8762
8955
|
const { can: can2 } = useSessionContext();
|
|
8763
8956
|
if (can2(perm)) return children;
|
|
8764
|
-
return /* @__PURE__ */
|
|
8957
|
+
return /* @__PURE__ */ jsx70(
|
|
8765
8958
|
"span",
|
|
8766
8959
|
{
|
|
8767
8960
|
title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
|
|
8768
8961
|
style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
|
|
8769
8962
|
"aria-disabled": "true",
|
|
8770
|
-
children: /* @__PURE__ */
|
|
8963
|
+
children: /* @__PURE__ */ jsx70("span", { style: { pointerEvents: "none" }, children })
|
|
8771
8964
|
}
|
|
8772
8965
|
);
|
|
8773
8966
|
}
|
|
8774
8967
|
|
|
8775
8968
|
// src/components/platform/ModeSwitch.tsx
|
|
8776
|
-
import * as
|
|
8777
|
-
import { Fragment as
|
|
8969
|
+
import * as React47 from "react";
|
|
8970
|
+
import { Fragment as Fragment21, jsx as jsx71, jsxs as jsxs65 } from "react/jsx-runtime";
|
|
8778
8971
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
8779
8972
|
const mode2 = useRuntimeMode();
|
|
8780
|
-
const [open, setOpen] =
|
|
8973
|
+
const [open, setOpen] = React47.useState(false);
|
|
8781
8974
|
const zIndex = useOverlayLayer(open);
|
|
8782
|
-
const ref =
|
|
8783
|
-
|
|
8975
|
+
const ref = React47.useRef(null);
|
|
8976
|
+
React47.useEffect(() => {
|
|
8784
8977
|
if (!open) return;
|
|
8785
8978
|
const away = (e) => {
|
|
8786
8979
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -8802,8 +8995,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
8802
8995
|
RuntimeKit.setMode(next);
|
|
8803
8996
|
setOpen(false);
|
|
8804
8997
|
};
|
|
8805
|
-
return /* @__PURE__ */
|
|
8806
|
-
/* @__PURE__ */
|
|
8998
|
+
return /* @__PURE__ */ jsxs65("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
|
|
8999
|
+
/* @__PURE__ */ jsxs65(
|
|
8807
9000
|
"button",
|
|
8808
9001
|
{
|
|
8809
9002
|
type: "button",
|
|
@@ -8813,29 +9006,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
8813
9006
|
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.",
|
|
8814
9007
|
className: "fd-mode-btn" + (test ? " is-test" : "") + (open ? " is-open" : ""),
|
|
8815
9008
|
children: [
|
|
8816
|
-
/* @__PURE__ */
|
|
8817
|
-
test && requestCount ? /* @__PURE__ */
|
|
9009
|
+
/* @__PURE__ */ jsx71("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
|
|
9010
|
+
test && requestCount ? /* @__PURE__ */ jsx71("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
|
|
8818
9011
|
]
|
|
8819
9012
|
}
|
|
8820
9013
|
),
|
|
8821
|
-
open ? /* @__PURE__ */
|
|
8822
|
-
/* @__PURE__ */
|
|
8823
|
-
/* @__PURE__ */
|
|
8824
|
-
/* @__PURE__ */
|
|
9014
|
+
open ? /* @__PURE__ */ jsx71(LayerProvider, { zIndex, children: /* @__PURE__ */ jsxs65("span", { className: "fd-view-enter fd-mode-pop", style: { zIndex }, children: [
|
|
9015
|
+
/* @__PURE__ */ jsxs65("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
9016
|
+
/* @__PURE__ */ jsxs65("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
|
|
9017
|
+
/* @__PURE__ */ jsx71("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
|
|
8825
9018
|
test ? "Test mode" : "Live mode"
|
|
8826
9019
|
] }),
|
|
8827
|
-
test ? /* @__PURE__ */
|
|
9020
|
+
test ? /* @__PURE__ */ jsxs65("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
8828
9021
|
requestCount,
|
|
8829
9022
|
" simulated request",
|
|
8830
9023
|
requestCount === 1 ? "" : "s"
|
|
8831
9024
|
] }) : null,
|
|
8832
|
-
/* @__PURE__ */
|
|
8833
|
-
test && onClearLog ? /* @__PURE__ */
|
|
9025
|
+
/* @__PURE__ */ jsx71("span", { style: { flex: 1 } }),
|
|
9026
|
+
test && onClearLog ? /* @__PURE__ */ jsx71("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
|
|
8834
9027
|
] }),
|
|
8835
|
-
/* @__PURE__ */
|
|
8836
|
-
/* @__PURE__ */
|
|
8837
|
-
/* @__PURE__ */
|
|
8838
|
-
/* @__PURE__ */
|
|
9028
|
+
/* @__PURE__ */ jsxs65("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
9029
|
+
/* @__PURE__ */ jsx71("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." }),
|
|
9030
|
+
/* @__PURE__ */ jsxs65("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
|
|
9031
|
+
/* @__PURE__ */ jsxs65("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
8839
9032
|
s.endpointsWired,
|
|
8840
9033
|
" endpoint",
|
|
8841
9034
|
s.endpointsWired === 1 ? "" : "s",
|
|
@@ -8845,58 +9038,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
8845
9038
|
s.total,
|
|
8846
9039
|
" features complete"
|
|
8847
9040
|
] }),
|
|
8848
|
-
onOpenSpec ? /* @__PURE__ */
|
|
8849
|
-
/* @__PURE__ */
|
|
8850
|
-
/* @__PURE__ */
|
|
9041
|
+
onOpenSpec ? /* @__PURE__ */ jsxs65(Fragment21, { children: [
|
|
9042
|
+
/* @__PURE__ */ jsx71("span", { style: { flex: 1 } }),
|
|
9043
|
+
/* @__PURE__ */ jsxs65("button", { type: "button", className: "fd-soon-link", onClick: () => {
|
|
8851
9044
|
setOpen(false);
|
|
8852
9045
|
onOpenSpec();
|
|
8853
9046
|
}, children: [
|
|
8854
9047
|
"API spec ",
|
|
8855
|
-
/* @__PURE__ */
|
|
9048
|
+
/* @__PURE__ */ jsx71("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
8856
9049
|
] })
|
|
8857
9050
|
] }) : null
|
|
8858
9051
|
] })
|
|
8859
9052
|
] }),
|
|
8860
|
-
/* @__PURE__ */
|
|
8861
|
-
/* @__PURE__ */
|
|
8862
|
-
/* @__PURE__ */
|
|
8863
|
-
/* @__PURE__ */
|
|
8864
|
-
/* @__PURE__ */
|
|
8865
|
-
/* @__PURE__ */
|
|
9053
|
+
/* @__PURE__ */ jsxs65("span", { className: "fd-mode-choice", children: [
|
|
9054
|
+
/* @__PURE__ */ jsxs65("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
|
|
9055
|
+
/* @__PURE__ */ jsx71("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
9056
|
+
/* @__PURE__ */ jsxs65("span", { className: "fd-mode-opt-text", children: [
|
|
9057
|
+
/* @__PURE__ */ jsx71("span", { className: "fd-mode-opt-title", children: "Live mode" }),
|
|
9058
|
+
/* @__PURE__ */ jsx71("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
|
|
8866
9059
|
] }),
|
|
8867
|
-
!test ? /* @__PURE__ */
|
|
9060
|
+
!test ? /* @__PURE__ */ jsx71("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
8868
9061
|
] }),
|
|
8869
|
-
/* @__PURE__ */
|
|
8870
|
-
/* @__PURE__ */
|
|
8871
|
-
/* @__PURE__ */
|
|
8872
|
-
/* @__PURE__ */
|
|
8873
|
-
/* @__PURE__ */
|
|
9062
|
+
/* @__PURE__ */ jsxs65("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
|
|
9063
|
+
/* @__PURE__ */ jsx71("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
9064
|
+
/* @__PURE__ */ jsxs65("span", { className: "fd-mode-opt-text", children: [
|
|
9065
|
+
/* @__PURE__ */ jsx71("span", { className: "fd-mode-opt-title", children: "Test mode" }),
|
|
9066
|
+
/* @__PURE__ */ jsx71("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
|
|
8874
9067
|
] }),
|
|
8875
|
-
test ? /* @__PURE__ */
|
|
9068
|
+
test ? /* @__PURE__ */ jsx71("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
8876
9069
|
] })
|
|
8877
9070
|
] }),
|
|
8878
|
-
test && renderLog ? /* @__PURE__ */
|
|
9071
|
+
test && renderLog ? /* @__PURE__ */ jsx71("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
|
|
8879
9072
|
] }) }) : null
|
|
8880
9073
|
] });
|
|
8881
9074
|
}
|
|
8882
9075
|
function TestModeBar({ onExit }) {
|
|
8883
9076
|
const mode2 = useRuntimeMode();
|
|
8884
9077
|
if (mode2 !== "test") return null;
|
|
8885
|
-
return /* @__PURE__ */
|
|
8886
|
-
/* @__PURE__ */
|
|
8887
|
-
/* @__PURE__ */
|
|
9078
|
+
return /* @__PURE__ */ jsxs65("div", { className: "fd-testbar", role: "status", children: [
|
|
9079
|
+
/* @__PURE__ */ jsxs65("span", { className: "fd-badge fd-badge-warning", children: [
|
|
9080
|
+
/* @__PURE__ */ jsx71("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
8888
9081
|
"Test mode"
|
|
8889
9082
|
] }),
|
|
8890
|
-
/* @__PURE__ */
|
|
8891
|
-
/* @__PURE__ */
|
|
8892
|
-
/* @__PURE__ */
|
|
9083
|
+
/* @__PURE__ */ jsx71("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
|
|
9084
|
+
/* @__PURE__ */ jsxs65("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
|
|
9085
|
+
/* @__PURE__ */ jsx71("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
8893
9086
|
" Back to live mode"
|
|
8894
9087
|
] })
|
|
8895
9088
|
] });
|
|
8896
9089
|
}
|
|
8897
9090
|
|
|
8898
9091
|
// src/components/planner/ChannelMeta.tsx
|
|
8899
|
-
import { jsx as
|
|
9092
|
+
import { jsx as jsx72, jsxs as jsxs66 } from "react/jsx-runtime";
|
|
8900
9093
|
var CHANNEL_WEIGHTS = {
|
|
8901
9094
|
"OOH": 50,
|
|
8902
9095
|
"DOOH": 50,
|
|
@@ -8949,9 +9142,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
8949
9142
|
const m = ChannelMeta(channel);
|
|
8950
9143
|
const wt = channelWeightOf(channel || "");
|
|
8951
9144
|
if (dot) {
|
|
8952
|
-
return /* @__PURE__ */
|
|
9145
|
+
return /* @__PURE__ */ jsx72("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
|
|
8953
9146
|
}
|
|
8954
|
-
return /* @__PURE__ */
|
|
9147
|
+
return /* @__PURE__ */ jsxs66(
|
|
8955
9148
|
"span",
|
|
8956
9149
|
{
|
|
8957
9150
|
className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
|
|
@@ -8959,16 +9152,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
8959
9152
|
style: { "--chan": m.color },
|
|
8960
9153
|
...rest,
|
|
8961
9154
|
children: [
|
|
8962
|
-
/* @__PURE__ */
|
|
8963
|
-
showLabel ? /* @__PURE__ */
|
|
8964
|
-
weight ? /* @__PURE__ */
|
|
9155
|
+
/* @__PURE__ */ jsx72("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
|
|
9156
|
+
showLabel ? /* @__PURE__ */ jsx72("span", { className: "fd-chan-label", children: m.label }) : null,
|
|
9157
|
+
weight ? /* @__PURE__ */ jsx72("span", { className: "fd-chan-weight", children: wt || 0 }) : null
|
|
8965
9158
|
]
|
|
8966
9159
|
}
|
|
8967
9160
|
);
|
|
8968
9161
|
}
|
|
8969
9162
|
|
|
8970
9163
|
// src/components/planner/SaturationDistribution.tsx
|
|
8971
|
-
import { jsx as
|
|
9164
|
+
import { jsx as jsx73, jsxs as jsxs67 } from "react/jsx-runtime";
|
|
8972
9165
|
var BANDS2 = [
|
|
8973
9166
|
{ key: "weak", label: "Weak", n: 1, range: "< 50" },
|
|
8974
9167
|
{ key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
|
|
@@ -8979,24 +9172,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8979
9172
|
const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
|
|
8980
9173
|
const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
|
|
8981
9174
|
const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
|
|
8982
|
-
return /* @__PURE__ */
|
|
8983
|
-
/* @__PURE__ */
|
|
9175
|
+
return /* @__PURE__ */ jsxs67("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
9176
|
+
/* @__PURE__ */ jsx73("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
|
|
8984
9177
|
const mark = "var(--csi-" + g.n + "-mark)";
|
|
8985
9178
|
const active = selectedBand === g.key;
|
|
8986
|
-
return /* @__PURE__ */
|
|
9179
|
+
return /* @__PURE__ */ jsxs67(
|
|
8987
9180
|
"button",
|
|
8988
9181
|
{
|
|
8989
9182
|
type: "button",
|
|
8990
9183
|
onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
|
|
8991
9184
|
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)" },
|
|
8992
9185
|
children: [
|
|
8993
|
-
/* @__PURE__ */
|
|
9186
|
+
/* @__PURE__ */ jsx73("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx73("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
|
|
8994
9187
|
// `overflow: hidden` + `white-space: nowrap` only clips once the span
|
|
8995
9188
|
// actually HAS a bounded width to clip against (see the grid/flex
|
|
8996
9189
|
// `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
|
|
8997
9190
|
// that clip readable instead of a hard cut mid-letter; the full name
|
|
8998
9191
|
// is still one hover away via `title`.
|
|
8999
|
-
/* @__PURE__ */
|
|
9192
|
+
/* @__PURE__ */ jsx73(
|
|
9000
9193
|
"span",
|
|
9001
9194
|
{
|
|
9002
9195
|
title: c.name + " \xB7 " + c.crp,
|
|
@@ -9006,13 +9199,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
9006
9199
|
c.name
|
|
9007
9200
|
)
|
|
9008
9201
|
)) }),
|
|
9009
|
-
/* @__PURE__ */
|
|
9010
|
-
/* @__PURE__ */
|
|
9011
|
-
/* @__PURE__ */
|
|
9202
|
+
/* @__PURE__ */ jsxs67("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
|
|
9203
|
+
/* @__PURE__ */ jsx73("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
|
|
9204
|
+
/* @__PURE__ */ jsx73("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx73("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
|
|
9012
9205
|
] }),
|
|
9013
|
-
/* @__PURE__ */
|
|
9014
|
-
/* @__PURE__ */
|
|
9015
|
-
/* @__PURE__ */
|
|
9206
|
+
/* @__PURE__ */ jsxs67("span", { className: "fd-stack", style: { gap: 1 }, children: [
|
|
9207
|
+
/* @__PURE__ */ jsx73("span", { className: "fd-label-lg", children: g.label }),
|
|
9208
|
+
/* @__PURE__ */ jsxs67("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
|
|
9016
9209
|
"CRP ",
|
|
9017
9210
|
g.range
|
|
9018
9211
|
] })
|
|
@@ -9022,10 +9215,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
9022
9215
|
g.key
|
|
9023
9216
|
);
|
|
9024
9217
|
}) }),
|
|
9025
|
-
floorBand ? /* @__PURE__ */
|
|
9026
|
-
/* @__PURE__ */
|
|
9027
|
-
/* @__PURE__ */
|
|
9028
|
-
/* @__PURE__ */
|
|
9218
|
+
floorBand ? /* @__PURE__ */ jsxs67("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: [
|
|
9219
|
+
/* @__PURE__ */ jsx73("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx73("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
|
|
9220
|
+
/* @__PURE__ */ jsxs67("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
|
|
9221
|
+
/* @__PURE__ */ jsxs67("strong", { style: { color: "var(--text)" }, children: [
|
|
9029
9222
|
"Plan floor ",
|
|
9030
9223
|
floorScore
|
|
9031
9224
|
] }),
|
|
@@ -9036,8 +9229,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
9036
9229
|
}
|
|
9037
9230
|
|
|
9038
9231
|
// src/components/planner/MixGap.tsx
|
|
9039
|
-
import * as
|
|
9040
|
-
import { Fragment as
|
|
9232
|
+
import * as React48 from "react";
|
|
9233
|
+
import { Fragment as Fragment22, jsx as jsx74, jsxs as jsxs68 } from "react/jsx-runtime";
|
|
9041
9234
|
var MIX_GAP_LAYOUT = {
|
|
9042
9235
|
trackHeight: 30,
|
|
9043
9236
|
barHeight: 20,
|
|
@@ -9051,19 +9244,19 @@ function mixGapOffset(value, max) {
|
|
|
9051
9244
|
}
|
|
9052
9245
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
9053
9246
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
9054
|
-
const [hover, setHover] =
|
|
9247
|
+
const [hover, setHover] = React48.useState(null);
|
|
9055
9248
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
9056
9249
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
9057
9250
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
9058
9251
|
const barTop = (trackHeight - barHeight) / 2;
|
|
9059
|
-
return /* @__PURE__ */
|
|
9060
|
-
/* @__PURE__ */
|
|
9061
|
-
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */
|
|
9062
|
-
/* @__PURE__ */
|
|
9252
|
+
return /* @__PURE__ */ jsxs68("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
|
|
9253
|
+
/* @__PURE__ */ jsxs68("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
|
|
9254
|
+
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs68("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
9255
|
+
/* @__PURE__ */ jsx74("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
|
|
9063
9256
|
l
|
|
9064
9257
|
] }, l)),
|
|
9065
|
-
/* @__PURE__ */
|
|
9066
|
-
/* @__PURE__ */
|
|
9258
|
+
/* @__PURE__ */ jsxs68("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
9259
|
+
/* @__PURE__ */ jsx74("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
|
|
9067
9260
|
"Target"
|
|
9068
9261
|
] })
|
|
9069
9262
|
] }),
|
|
@@ -9072,7 +9265,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
9072
9265
|
const tone = toneOf(gap);
|
|
9073
9266
|
const tip = "Realized " + r.realized + "% vs " + r.target + "% target" + (gap < -1 ? " \xB7 " + Math.abs(gap).toFixed(0) + " pts short" : gap > 1 ? " \xB7 " + gap.toFixed(0) + " pts over" : " \xB7 on target") + (r.note ? " \u2014 " + r.note : "");
|
|
9074
9267
|
const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
|
|
9075
|
-
return /* @__PURE__ */
|
|
9268
|
+
return /* @__PURE__ */ jsxs68(
|
|
9076
9269
|
"div",
|
|
9077
9270
|
{
|
|
9078
9271
|
className: "fd-row",
|
|
@@ -9080,15 +9273,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
9080
9273
|
onMouseEnter: () => setHover(r.channel),
|
|
9081
9274
|
onMouseLeave: () => setHover(null),
|
|
9082
9275
|
children: [
|
|
9083
|
-
/* @__PURE__ */
|
|
9084
|
-
/* @__PURE__ */
|
|
9085
|
-
/* @__PURE__ */
|
|
9086
|
-
/* @__PURE__ */
|
|
9087
|
-
/* @__PURE__ */
|
|
9276
|
+
/* @__PURE__ */ jsx74("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx74(ChannelTag, { channel: r.channel, size: "sm" }) }),
|
|
9277
|
+
/* @__PURE__ */ jsx74("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx74("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs68(Fragment22, { children: [
|
|
9278
|
+
/* @__PURE__ */ jsx74("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)" } }),
|
|
9279
|
+
/* @__PURE__ */ jsx74("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 } }),
|
|
9280
|
+
/* @__PURE__ */ jsxs68("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: [
|
|
9088
9281
|
r.realized,
|
|
9089
9282
|
"%"
|
|
9090
9283
|
] }),
|
|
9091
|
-
hover === r.channel ? /* @__PURE__ */
|
|
9284
|
+
hover === r.channel ? /* @__PURE__ */ jsx74("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
|
|
9092
9285
|
] }) })
|
|
9093
9286
|
]
|
|
9094
9287
|
},
|
|
@@ -9099,7 +9292,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
9099
9292
|
}
|
|
9100
9293
|
|
|
9101
9294
|
// src/components/planner/ChannelContribution.tsx
|
|
9102
|
-
import { jsx as
|
|
9295
|
+
import { jsx as jsx75, jsxs as jsxs69 } from "react/jsx-runtime";
|
|
9103
9296
|
var money = (n) => "$" + Math.round(n).toLocaleString();
|
|
9104
9297
|
function ChannelContribution({
|
|
9105
9298
|
channels = [],
|
|
@@ -9115,9 +9308,9 @@ function ChannelContribution({
|
|
|
9115
9308
|
const grand = total !== void 0 ? total : base + bonus;
|
|
9116
9309
|
const pct = (v) => grand ? v / grand * 100 : 0;
|
|
9117
9310
|
const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
|
|
9118
|
-
return /* @__PURE__ */
|
|
9119
|
-
loading ? /* @__PURE__ */
|
|
9120
|
-
channels.map((c) => /* @__PURE__ */
|
|
9311
|
+
return /* @__PURE__ */ jsxs69("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
9312
|
+
loading ? /* @__PURE__ */ jsx75("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
|
|
9313
|
+
channels.map((c) => /* @__PURE__ */ jsx75(
|
|
9121
9314
|
"span",
|
|
9122
9315
|
{
|
|
9123
9316
|
title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
|
|
@@ -9126,7 +9319,7 @@ function ChannelContribution({
|
|
|
9126
9319
|
},
|
|
9127
9320
|
c.name
|
|
9128
9321
|
)),
|
|
9129
|
-
bonus > 0 ? /* @__PURE__ */
|
|
9322
|
+
bonus > 0 ? /* @__PURE__ */ jsx75(
|
|
9130
9323
|
"span",
|
|
9131
9324
|
{
|
|
9132
9325
|
title: "Surround-sound bonus +" + bonusPct + "%",
|
|
@@ -9135,18 +9328,18 @@ function ChannelContribution({
|
|
|
9135
9328
|
}
|
|
9136
9329
|
) : null
|
|
9137
9330
|
] }),
|
|
9138
|
-
showTable ? /* @__PURE__ */
|
|
9139
|
-
/* @__PURE__ */
|
|
9140
|
-
/* @__PURE__ */
|
|
9141
|
-
/* @__PURE__ */
|
|
9142
|
-
/* @__PURE__ */
|
|
9143
|
-
/* @__PURE__ */
|
|
9144
|
-
/* @__PURE__ */
|
|
9331
|
+
showTable ? /* @__PURE__ */ jsxs69("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
|
|
9332
|
+
/* @__PURE__ */ jsx75("thead", { children: /* @__PURE__ */ jsxs69("tr", { children: [
|
|
9333
|
+
/* @__PURE__ */ jsx75("th", { style: { width: "34%" }, children: "Channel" }),
|
|
9334
|
+
/* @__PURE__ */ jsx75("th", { style: { width: "16%" }, children: "Weight" }),
|
|
9335
|
+
/* @__PURE__ */ jsx75("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
|
|
9336
|
+
/* @__PURE__ */ jsx75("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
|
|
9337
|
+
/* @__PURE__ */ jsx75("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
|
|
9145
9338
|
] }) }),
|
|
9146
|
-
/* @__PURE__ */
|
|
9147
|
-
channels.map((c) => /* @__PURE__ */
|
|
9148
|
-
/* @__PURE__ */
|
|
9149
|
-
/* @__PURE__ */
|
|
9339
|
+
/* @__PURE__ */ jsxs69("tbody", { children: [
|
|
9340
|
+
channels.map((c) => /* @__PURE__ */ jsxs69("tr", { children: [
|
|
9341
|
+
/* @__PURE__ */ jsx75("td", { children: /* @__PURE__ */ jsx75(ChannelTag, { channel: c.name, size: "sm" }) }),
|
|
9342
|
+
/* @__PURE__ */ jsx75("td", { children: /* @__PURE__ */ jsx75(
|
|
9150
9343
|
"span",
|
|
9151
9344
|
{
|
|
9152
9345
|
className: "fd-badge fd-badge-neutral",
|
|
@@ -9155,38 +9348,38 @@ function ChannelContribution({
|
|
|
9155
9348
|
children: "weight " + (channelWeightOf(c.name) || 0)
|
|
9156
9349
|
}
|
|
9157
9350
|
) }),
|
|
9158
|
-
/* @__PURE__ */
|
|
9159
|
-
/* @__PURE__ */
|
|
9160
|
-
/* @__PURE__ */
|
|
9351
|
+
/* @__PURE__ */ jsx75("td", { className: "is-num", children: c.spend }),
|
|
9352
|
+
/* @__PURE__ */ jsx75("td", { className: "is-num", children: c.crp.toFixed(1) }),
|
|
9353
|
+
/* @__PURE__ */ jsxs69("td", { className: "is-num", children: [
|
|
9161
9354
|
pct(c.crp).toFixed(0),
|
|
9162
9355
|
"%"
|
|
9163
9356
|
] })
|
|
9164
9357
|
] }, c.name)),
|
|
9165
|
-
bonus > 0 ? /* @__PURE__ */
|
|
9166
|
-
/* @__PURE__ */
|
|
9167
|
-
/* @__PURE__ */
|
|
9358
|
+
bonus > 0 ? /* @__PURE__ */ jsxs69("tr", { children: [
|
|
9359
|
+
/* @__PURE__ */ jsx75("td", { children: /* @__PURE__ */ jsxs69("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
|
|
9360
|
+
/* @__PURE__ */ jsx75("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" } }),
|
|
9168
9361
|
"Surround-sound bonus"
|
|
9169
9362
|
] }) }),
|
|
9170
|
-
/* @__PURE__ */
|
|
9363
|
+
/* @__PURE__ */ jsx75("td", { children: /* @__PURE__ */ jsxs69("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
|
|
9171
9364
|
"+",
|
|
9172
9365
|
bonusPct,
|
|
9173
9366
|
"% of +",
|
|
9174
9367
|
bonusMax,
|
|
9175
9368
|
"%"
|
|
9176
9369
|
] }) }),
|
|
9177
|
-
/* @__PURE__ */
|
|
9178
|
-
/* @__PURE__ */
|
|
9179
|
-
/* @__PURE__ */
|
|
9370
|
+
/* @__PURE__ */ jsx75("td", { className: "is-num fd-muted", children: "\u2014" }),
|
|
9371
|
+
/* @__PURE__ */ jsx75("td", { className: "is-num", children: bonus.toFixed(1) }),
|
|
9372
|
+
/* @__PURE__ */ jsxs69("td", { className: "is-num", children: [
|
|
9180
9373
|
pct(bonus).toFixed(0),
|
|
9181
9374
|
"%"
|
|
9182
9375
|
] })
|
|
9183
9376
|
] }) : null,
|
|
9184
|
-
/* @__PURE__ */
|
|
9185
|
-
/* @__PURE__ */
|
|
9186
|
-
/* @__PURE__ */
|
|
9187
|
-
/* @__PURE__ */
|
|
9188
|
-
/* @__PURE__ */
|
|
9189
|
-
/* @__PURE__ */
|
|
9377
|
+
/* @__PURE__ */ jsxs69("tr", { style: { background: "var(--surface-2)" }, children: [
|
|
9378
|
+
/* @__PURE__ */ jsx75("td", { style: { fontWeight: 700 }, children: "Campus total" }),
|
|
9379
|
+
/* @__PURE__ */ jsx75("td", {}),
|
|
9380
|
+
/* @__PURE__ */ jsx75("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
|
|
9381
|
+
/* @__PURE__ */ jsx75("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
|
|
9382
|
+
/* @__PURE__ */ jsx75("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
|
|
9190
9383
|
] })
|
|
9191
9384
|
] })
|
|
9192
9385
|
] }) : null
|
|
@@ -9194,8 +9387,8 @@ function ChannelContribution({
|
|
|
9194
9387
|
}
|
|
9195
9388
|
|
|
9196
9389
|
// src/components/planner/BudgetReallocator.tsx
|
|
9197
|
-
import * as
|
|
9198
|
-
import { Fragment as
|
|
9390
|
+
import * as React49 from "react";
|
|
9391
|
+
import { Fragment as Fragment23, jsx as jsx76, jsxs as jsxs70 } from "react/jsx-runtime";
|
|
9199
9392
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
9200
9393
|
function BudgetReallocator({
|
|
9201
9394
|
campus,
|
|
@@ -9210,8 +9403,8 @@ function BudgetReallocator({
|
|
|
9210
9403
|
onCancel,
|
|
9211
9404
|
className = ""
|
|
9212
9405
|
}) {
|
|
9213
|
-
const [draft, setDraft] =
|
|
9214
|
-
|
|
9406
|
+
const [draft, setDraft] = React49.useState(spend);
|
|
9407
|
+
React49.useEffect(() => setDraft(spend), [spend]);
|
|
9215
9408
|
const dirty = draft !== spend;
|
|
9216
9409
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
9217
9410
|
const nextBand = bandFor(nextCrp);
|
|
@@ -9226,10 +9419,10 @@ function BudgetReallocator({
|
|
|
9226
9419
|
setDraft(spend);
|
|
9227
9420
|
if (onCancel) onCancel();
|
|
9228
9421
|
};
|
|
9229
|
-
const trackRef =
|
|
9230
|
-
const chipRef =
|
|
9231
|
-
const [chipLeft, setChipLeft] =
|
|
9232
|
-
|
|
9422
|
+
const trackRef = React49.useRef(null);
|
|
9423
|
+
const chipRef = React49.useRef(null);
|
|
9424
|
+
const [chipLeft, setChipLeft] = React49.useState(null);
|
|
9425
|
+
React49.useLayoutEffect(() => {
|
|
9233
9426
|
const track = trackRef.current;
|
|
9234
9427
|
if (!dirty || !track) {
|
|
9235
9428
|
setChipLeft(null);
|
|
@@ -9250,23 +9443,23 @@ function BudgetReallocator({
|
|
|
9250
9443
|
ro.observe(track);
|
|
9251
9444
|
return () => ro.disconnect();
|
|
9252
9445
|
}, [dirty, pct]);
|
|
9253
|
-
return /* @__PURE__ */
|
|
9446
|
+
return /* @__PURE__ */ jsxs70(
|
|
9254
9447
|
"div",
|
|
9255
9448
|
{
|
|
9256
9449
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
9257
9450
|
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)" },
|
|
9258
9451
|
children: [
|
|
9259
|
-
/* @__PURE__ */
|
|
9260
|
-
/* @__PURE__ */
|
|
9261
|
-
/* @__PURE__ */
|
|
9262
|
-
dirty ? /* @__PURE__ */
|
|
9263
|
-
/* @__PURE__ */
|
|
9264
|
-
/* @__PURE__ */
|
|
9452
|
+
/* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
9453
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
|
|
9454
|
+
/* @__PURE__ */ jsx76(CsiBadge, { band: nowBand, crp, size: "medium" }),
|
|
9455
|
+
dirty ? /* @__PURE__ */ jsxs70(Fragment23, { children: [
|
|
9456
|
+
/* @__PURE__ */ jsx76("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
|
|
9457
|
+
/* @__PURE__ */ jsx76(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
|
|
9265
9458
|
] }) : null
|
|
9266
9459
|
] }),
|
|
9267
|
-
/* @__PURE__ */
|
|
9268
|
-
/* @__PURE__ */
|
|
9269
|
-
dirty ? /* @__PURE__ */
|
|
9460
|
+
/* @__PURE__ */ jsxs70("div", { className: "fd-slider", ref: trackRef, children: [
|
|
9461
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
9462
|
+
dirty ? /* @__PURE__ */ jsx76(
|
|
9270
9463
|
"span",
|
|
9271
9464
|
{
|
|
9272
9465
|
ref: chipRef,
|
|
@@ -9278,7 +9471,7 @@ function BudgetReallocator({
|
|
|
9278
9471
|
children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
|
|
9279
9472
|
}
|
|
9280
9473
|
) : null,
|
|
9281
|
-
/* @__PURE__ */
|
|
9474
|
+
/* @__PURE__ */ jsx76(
|
|
9282
9475
|
"input",
|
|
9283
9476
|
{
|
|
9284
9477
|
type: "range",
|
|
@@ -9294,13 +9487,13 @@ function BudgetReallocator({
|
|
|
9294
9487
|
}
|
|
9295
9488
|
)
|
|
9296
9489
|
] }),
|
|
9297
|
-
/* @__PURE__ */
|
|
9298
|
-
/* @__PURE__ */
|
|
9299
|
-
/* @__PURE__ */
|
|
9300
|
-
/* @__PURE__ */
|
|
9490
|
+
/* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
9491
|
+
/* @__PURE__ */ jsxs70("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
|
|
9492
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
|
|
9493
|
+
/* @__PURE__ */ jsx76("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
|
|
9301
9494
|
] }),
|
|
9302
|
-
/* @__PURE__ */
|
|
9303
|
-
/* @__PURE__ */
|
|
9495
|
+
/* @__PURE__ */ jsx76("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
|
|
9496
|
+
/* @__PURE__ */ jsx76(
|
|
9304
9497
|
"button",
|
|
9305
9498
|
{
|
|
9306
9499
|
type: "button",
|
|
@@ -9319,7 +9512,7 @@ function BudgetReallocator({
|
|
|
9319
9512
|
}
|
|
9320
9513
|
|
|
9321
9514
|
// src/components/planner/SurroundSound.tsx
|
|
9322
|
-
import { jsx as
|
|
9515
|
+
import { jsx as jsx77, jsxs as jsxs71 } from "react/jsx-runtime";
|
|
9323
9516
|
var CATEGORIES = [
|
|
9324
9517
|
{ key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
|
|
9325
9518
|
{ key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
|
|
@@ -9331,26 +9524,26 @@ var CATEGORIES = [
|
|
|
9331
9524
|
function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
|
|
9332
9525
|
const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
|
|
9333
9526
|
const single = present.length <= 2;
|
|
9334
|
-
return /* @__PURE__ */
|
|
9335
|
-
/* @__PURE__ */
|
|
9527
|
+
return /* @__PURE__ */ jsxs71("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
|
|
9528
|
+
/* @__PURE__ */ jsx77("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
|
|
9336
9529
|
const on = present.includes(c.key);
|
|
9337
|
-
return /* @__PURE__ */
|
|
9530
|
+
return /* @__PURE__ */ jsxs71(
|
|
9338
9531
|
"span",
|
|
9339
9532
|
{
|
|
9340
9533
|
title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
|
|
9341
9534
|
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)" },
|
|
9342
9535
|
children: [
|
|
9343
|
-
/* @__PURE__ */
|
|
9344
|
-
/* @__PURE__ */
|
|
9536
|
+
/* @__PURE__ */ jsx77("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
9537
|
+
/* @__PURE__ */ jsx77("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
|
|
9345
9538
|
]
|
|
9346
9539
|
},
|
|
9347
9540
|
c.key
|
|
9348
9541
|
);
|
|
9349
9542
|
}) }),
|
|
9350
|
-
/* @__PURE__ */
|
|
9351
|
-
/* @__PURE__ */
|
|
9352
|
-
/* @__PURE__ */
|
|
9353
|
-
/* @__PURE__ */
|
|
9543
|
+
/* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
9544
|
+
/* @__PURE__ */ jsxs71("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
9545
|
+
/* @__PURE__ */ jsx77("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
|
|
9546
|
+
/* @__PURE__ */ jsxs71("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
|
|
9354
9547
|
"+",
|
|
9355
9548
|
bonusPct,
|
|
9356
9549
|
"% of +",
|
|
@@ -9358,8 +9551,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
9358
9551
|
"%"
|
|
9359
9552
|
] })
|
|
9360
9553
|
] }),
|
|
9361
|
-
/* @__PURE__ */
|
|
9362
|
-
/* @__PURE__ */
|
|
9554
|
+
/* @__PURE__ */ jsx77("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx77("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
|
|
9555
|
+
/* @__PURE__ */ jsxs71("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
|
|
9363
9556
|
present.length,
|
|
9364
9557
|
" of 6 channel categories present.",
|
|
9365
9558
|
" ",
|
|
@@ -9371,7 +9564,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
9371
9564
|
}
|
|
9372
9565
|
|
|
9373
9566
|
// src/components/planner/Importance.tsx
|
|
9374
|
-
import { jsx as
|
|
9567
|
+
import { jsx as jsx78, jsxs as jsxs72 } from "react/jsx-runtime";
|
|
9375
9568
|
var IMPORTANCE_LEVELS = [
|
|
9376
9569
|
{ id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
|
|
9377
9570
|
{ id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
|
|
@@ -9401,23 +9594,23 @@ function importanceTokens(id) {
|
|
|
9401
9594
|
function ImportanceTag({ level, showLabel = true, size = "sm", className = "" }) {
|
|
9402
9595
|
const lvl = importanceLevel(level);
|
|
9403
9596
|
const t = importanceTokens(level);
|
|
9404
|
-
return /* @__PURE__ */
|
|
9597
|
+
return /* @__PURE__ */ jsxs72(
|
|
9405
9598
|
"span",
|
|
9406
9599
|
{
|
|
9407
9600
|
className: ["fd-imp-tag", size === "md" ? "is-md" : "", className].filter(Boolean).join(" "),
|
|
9408
9601
|
style: { background: t.fill, borderColor: t.edge, color: t.text },
|
|
9409
9602
|
title: lvl.label + " \u2014 " + lvl.description,
|
|
9410
9603
|
children: [
|
|
9411
|
-
/* @__PURE__ */
|
|
9412
|
-
showLabel ? lvl.label : /* @__PURE__ */
|
|
9604
|
+
/* @__PURE__ */ jsx78("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
|
|
9605
|
+
showLabel ? lvl.label : /* @__PURE__ */ jsx78("span", { className: "fd-sr", children: lvl.label })
|
|
9413
9606
|
]
|
|
9414
9607
|
}
|
|
9415
9608
|
);
|
|
9416
9609
|
}
|
|
9417
9610
|
|
|
9418
9611
|
// src/components/planner/PreferenceMeter.tsx
|
|
9419
|
-
import * as
|
|
9420
|
-
import { jsx as
|
|
9612
|
+
import * as React50 from "react";
|
|
9613
|
+
import { jsx as jsx79, jsxs as jsxs73 } from "react/jsx-runtime";
|
|
9421
9614
|
function preferenceScore(criteria) {
|
|
9422
9615
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
9423
9616
|
const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
|
|
@@ -9446,8 +9639,8 @@ function PreferenceMeter({
|
|
|
9446
9639
|
className = ""
|
|
9447
9640
|
}) {
|
|
9448
9641
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
9449
|
-
const segments =
|
|
9450
|
-
return /* @__PURE__ */
|
|
9642
|
+
const segments = React50.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
9643
|
+
return /* @__PURE__ */ jsx79(
|
|
9451
9644
|
ScoreMeter,
|
|
9452
9645
|
{
|
|
9453
9646
|
score: value,
|
|
@@ -9459,22 +9652,22 @@ function PreferenceMeter({
|
|
|
9459
9652
|
placement,
|
|
9460
9653
|
className,
|
|
9461
9654
|
breakdownLabel: breakdownTitle,
|
|
9462
|
-
breakdown: /* @__PURE__ */
|
|
9463
|
-
/* @__PURE__ */
|
|
9464
|
-
/* @__PURE__ */
|
|
9465
|
-
/* @__PURE__ */
|
|
9655
|
+
breakdown: /* @__PURE__ */ jsxs73("div", { className: "fd-prefbreak", children: [
|
|
9656
|
+
/* @__PURE__ */ jsxs73("div", { className: "fd-prefbreak-head", children: [
|
|
9657
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-label-lg", children: breakdownTitle }),
|
|
9658
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
|
|
9466
9659
|
] }),
|
|
9467
|
-
/* @__PURE__ */
|
|
9660
|
+
/* @__PURE__ */ jsx79("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
|
|
9468
9661
|
const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
|
|
9469
|
-
return /* @__PURE__ */
|
|
9470
|
-
/* @__PURE__ */
|
|
9471
|
-
/* @__PURE__ */
|
|
9472
|
-
/* @__PURE__ */
|
|
9473
|
-
c.note ? /* @__PURE__ */
|
|
9662
|
+
return /* @__PURE__ */ jsxs73("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
|
|
9663
|
+
/* @__PURE__ */ jsx79(ImportanceTag, { level: c.importance }),
|
|
9664
|
+
/* @__PURE__ */ jsxs73("span", { className: "fd-prefbreak-text", children: [
|
|
9665
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-prefbreak-label", children: c.label }),
|
|
9666
|
+
c.note ? /* @__PURE__ */ jsx79("span", { className: "fd-prefbreak-note", children: c.note }) : null
|
|
9474
9667
|
] }),
|
|
9475
|
-
/* @__PURE__ */
|
|
9668
|
+
/* @__PURE__ */ jsxs73("span", { className: "fd-prefbreak-val fd-tabular", children: [
|
|
9476
9669
|
Math.round(Number(c.earned) || 0),
|
|
9477
|
-
/* @__PURE__ */
|
|
9670
|
+
/* @__PURE__ */ jsx79("span", { className: "fd-prefbreak-sep", children: "/" }),
|
|
9478
9671
|
Math.round(c.weight)
|
|
9479
9672
|
] })
|
|
9480
9673
|
] }, c.id);
|
|
@@ -9485,10 +9678,10 @@ function PreferenceMeter({
|
|
|
9485
9678
|
}
|
|
9486
9679
|
|
|
9487
9680
|
// src/components/chat/AgentChatPanel.tsx
|
|
9488
|
-
import * as
|
|
9681
|
+
import * as React56 from "react";
|
|
9489
9682
|
|
|
9490
9683
|
// src/components/chat/chatEngine.ts
|
|
9491
|
-
import * as
|
|
9684
|
+
import * as React51 from "react";
|
|
9492
9685
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
9493
9686
|
var JOB_PENDING = ["queued", "running"];
|
|
9494
9687
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -9542,22 +9735,22 @@ function useChatEngine(opts) {
|
|
|
9542
9735
|
onClear,
|
|
9543
9736
|
onFeedback
|
|
9544
9737
|
} = opts || {};
|
|
9545
|
-
const [status, setStatus] =
|
|
9546
|
-
const [threadId, setThreadId] =
|
|
9547
|
-
const [messages, setMessages] =
|
|
9548
|
-
const [queue, setQueue] =
|
|
9549
|
-
const [fatal, setFatal] =
|
|
9550
|
-
const [busy, setBusy] =
|
|
9551
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
9552
|
-
const listRef =
|
|
9553
|
-
const queueRef =
|
|
9554
|
-
const busyRef =
|
|
9555
|
-
const stoppedRef =
|
|
9556
|
-
const abortRef =
|
|
9557
|
-
const serverCount =
|
|
9558
|
-
const threadRef =
|
|
9559
|
-
const mounted =
|
|
9560
|
-
|
|
9738
|
+
const [status, setStatus] = React51.useState("idle");
|
|
9739
|
+
const [threadId, setThreadId] = React51.useState(null);
|
|
9740
|
+
const [messages, setMessages] = React51.useState([]);
|
|
9741
|
+
const [queue, setQueue] = React51.useState([]);
|
|
9742
|
+
const [fatal, setFatal] = React51.useState(null);
|
|
9743
|
+
const [busy, setBusy] = React51.useState(false);
|
|
9744
|
+
const [turnStartedAt, setTurnStartedAt] = React51.useState(null);
|
|
9745
|
+
const listRef = React51.useRef([]);
|
|
9746
|
+
const queueRef = React51.useRef([]);
|
|
9747
|
+
const busyRef = React51.useRef(false);
|
|
9748
|
+
const stoppedRef = React51.useRef(false);
|
|
9749
|
+
const abortRef = React51.useRef(null);
|
|
9750
|
+
const serverCount = React51.useRef(0);
|
|
9751
|
+
const threadRef = React51.useRef(null);
|
|
9752
|
+
const mounted = React51.useRef(true);
|
|
9753
|
+
React51.useEffect(() => {
|
|
9561
9754
|
mounted.current = true;
|
|
9562
9755
|
return () => {
|
|
9563
9756
|
mounted.current = false;
|
|
@@ -9579,14 +9772,14 @@ function useChatEngine(opts) {
|
|
|
9579
9772
|
}
|
|
9580
9773
|
return false;
|
|
9581
9774
|
};
|
|
9582
|
-
const loadThread =
|
|
9775
|
+
const loadThread = React51.useCallback(async (id) => {
|
|
9583
9776
|
const data = await apiAdapter.getThread(id);
|
|
9584
9777
|
const list = [...data && data.messages || []];
|
|
9585
9778
|
serverCount.current = list.length;
|
|
9586
9779
|
commit(list);
|
|
9587
9780
|
return list;
|
|
9588
9781
|
}, [apiAdapter]);
|
|
9589
|
-
|
|
9782
|
+
React51.useEffect(() => {
|
|
9590
9783
|
if (!apiAdapter) {
|
|
9591
9784
|
setStatus("idle");
|
|
9592
9785
|
setFatal(null);
|
|
@@ -9799,7 +9992,7 @@ function useChatEngine(opts) {
|
|
|
9799
9992
|
await dispatchTurn(turn);
|
|
9800
9993
|
}
|
|
9801
9994
|
}
|
|
9802
|
-
const send =
|
|
9995
|
+
const send = React51.useCallback((text, attachments) => {
|
|
9803
9996
|
const body = (text || "").trim();
|
|
9804
9997
|
if (!body && !(attachments && attachments.length)) return;
|
|
9805
9998
|
if (status === "disconnected") return;
|
|
@@ -9809,7 +10002,7 @@ function useChatEngine(opts) {
|
|
|
9809
10002
|
stoppedRef.current = false;
|
|
9810
10003
|
drain();
|
|
9811
10004
|
}, [status]);
|
|
9812
|
-
const stop =
|
|
10005
|
+
const stop = React51.useCallback(() => {
|
|
9813
10006
|
stoppedRef.current = true;
|
|
9814
10007
|
const ac = abortRef.current;
|
|
9815
10008
|
if (ac) {
|
|
@@ -9828,11 +10021,11 @@ function useChatEngine(opts) {
|
|
|
9828
10021
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
9829
10022
|
}
|
|
9830
10023
|
}, [apiAdapter]);
|
|
9831
|
-
const removeQueued =
|
|
10024
|
+
const removeQueued = React51.useCallback((id) => {
|
|
9832
10025
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
9833
10026
|
setQueue(queueRef.current.slice());
|
|
9834
10027
|
}, []);
|
|
9835
|
-
const retry =
|
|
10028
|
+
const retry = React51.useCallback(() => {
|
|
9836
10029
|
const list = listRef.current;
|
|
9837
10030
|
let at = -1;
|
|
9838
10031
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -9848,19 +10041,19 @@ function useChatEngine(opts) {
|
|
|
9848
10041
|
setQueue(queueRef.current.slice());
|
|
9849
10042
|
drain();
|
|
9850
10043
|
}, []);
|
|
9851
|
-
const clear =
|
|
10044
|
+
const clear = React51.useCallback(() => {
|
|
9852
10045
|
commit([]);
|
|
9853
10046
|
serverCount.current = 0;
|
|
9854
10047
|
queueRef.current = [];
|
|
9855
10048
|
setQueue([]);
|
|
9856
10049
|
onClear && onClear();
|
|
9857
10050
|
}, [onClear]);
|
|
9858
|
-
const setFeedback =
|
|
10051
|
+
const setFeedback = React51.useCallback((id, value) => {
|
|
9859
10052
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
9860
10053
|
const msg = listRef.current.find((m) => m.id === id);
|
|
9861
10054
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
9862
10055
|
}, [onFeedback]);
|
|
9863
|
-
const reload =
|
|
10056
|
+
const reload = React51.useCallback(async () => {
|
|
9864
10057
|
if (!threadRef.current) return;
|
|
9865
10058
|
setStatus("loading");
|
|
9866
10059
|
try {
|
|
@@ -9898,11 +10091,11 @@ var ChatKit = {
|
|
|
9898
10091
|
};
|
|
9899
10092
|
|
|
9900
10093
|
// src/components/chat/ChatTranscript.tsx
|
|
9901
|
-
import * as
|
|
10094
|
+
import * as React53 from "react";
|
|
9902
10095
|
|
|
9903
10096
|
// src/components/chat/ChatTurn.tsx
|
|
9904
|
-
import * as
|
|
9905
|
-
import { jsx as
|
|
10097
|
+
import * as React52 from "react";
|
|
10098
|
+
import { jsx as jsx80, jsxs as jsxs74 } from "react/jsx-runtime";
|
|
9906
10099
|
function JsonView({ value }) {
|
|
9907
10100
|
let text;
|
|
9908
10101
|
try {
|
|
@@ -9910,67 +10103,67 @@ function JsonView({ value }) {
|
|
|
9910
10103
|
} catch (e) {
|
|
9911
10104
|
text = String(value);
|
|
9912
10105
|
}
|
|
9913
|
-
return /* @__PURE__ */
|
|
10106
|
+
return /* @__PURE__ */ jsx80(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
|
|
9914
10107
|
}
|
|
9915
10108
|
function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
9916
10109
|
if (!packet) return null;
|
|
9917
10110
|
const s = schema || {};
|
|
9918
10111
|
const invalid = packet.valid === false;
|
|
9919
10112
|
const title = s.heading || packet.type;
|
|
9920
|
-
return /* @__PURE__ */
|
|
9921
|
-
/* @__PURE__ */
|
|
9922
|
-
/* @__PURE__ */
|
|
9923
|
-
/* @__PURE__ */
|
|
9924
|
-
packet.repaired ? /* @__PURE__ */
|
|
9925
|
-
invalid ? /* @__PURE__ */
|
|
10113
|
+
return /* @__PURE__ */ jsxs74("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
|
|
10114
|
+
/* @__PURE__ */ jsxs74("header", { className: "fdc-packet-head", children: [
|
|
10115
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
|
|
10116
|
+
/* @__PURE__ */ jsx80("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
|
|
10117
|
+
packet.repaired ? /* @__PURE__ */ jsx80("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
|
|
10118
|
+
invalid ? /* @__PURE__ */ jsx80("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
|
|
9926
10119
|
] }),
|
|
9927
|
-
invalid ? /* @__PURE__ */
|
|
9928
|
-
/* @__PURE__ */
|
|
9929
|
-
/* @__PURE__ */
|
|
9930
|
-
] }) : /* @__PURE__ */
|
|
9931
|
-
!invalid && onApply ? /* @__PURE__ */
|
|
9932
|
-
packet.repaired ? /* @__PURE__ */
|
|
9933
|
-
/* @__PURE__ */
|
|
9934
|
-
/* @__PURE__ */
|
|
10120
|
+
invalid ? /* @__PURE__ */ jsxs74("div", { className: "fdc-packet-alert", role: "alert", children: [
|
|
10121
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
10122
|
+
/* @__PURE__ */ jsx80("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
|
|
10123
|
+
] }) : /* @__PURE__ */ jsx80("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx80(JsonView, { value: packet.payload }) }),
|
|
10124
|
+
!invalid && onApply ? /* @__PURE__ */ jsxs74("footer", { className: "fdc-packet-foot", children: [
|
|
10125
|
+
packet.repaired ? /* @__PURE__ */ jsx80("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx80("span", {}),
|
|
10126
|
+
/* @__PURE__ */ jsxs74("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
|
|
10127
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
|
|
9935
10128
|
applied ? "Applied" : s.applyLabel || "Apply"
|
|
9936
10129
|
] })
|
|
9937
10130
|
] }) : null
|
|
9938
10131
|
] });
|
|
9939
10132
|
}
|
|
9940
10133
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
9941
|
-
const [open, setOpen] =
|
|
10134
|
+
const [open, setOpen] = React52.useState(defaultOpen);
|
|
9942
10135
|
if (!text) return null;
|
|
9943
|
-
return /* @__PURE__ */
|
|
9944
|
-
/* @__PURE__ */
|
|
9945
|
-
/* @__PURE__ */
|
|
9946
|
-
/* @__PURE__ */
|
|
9947
|
-
streaming ? /* @__PURE__ */
|
|
9948
|
-
/* @__PURE__ */
|
|
9949
|
-
/* @__PURE__ */
|
|
9950
|
-
/* @__PURE__ */
|
|
10136
|
+
return /* @__PURE__ */ jsxs74("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
|
|
10137
|
+
/* @__PURE__ */ jsxs74("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
10138
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-brain", "aria-hidden": "true" }),
|
|
10139
|
+
/* @__PURE__ */ jsx80("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
|
|
10140
|
+
streaming ? /* @__PURE__ */ jsxs74("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
10141
|
+
/* @__PURE__ */ jsx80("span", {}),
|
|
10142
|
+
/* @__PURE__ */ jsx80("span", {}),
|
|
10143
|
+
/* @__PURE__ */ jsx80("span", {})
|
|
9951
10144
|
] }) : null,
|
|
9952
|
-
/* @__PURE__ */
|
|
10145
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
|
|
9953
10146
|
] }),
|
|
9954
|
-
open ? /* @__PURE__ */
|
|
10147
|
+
open ? /* @__PURE__ */ jsx80("div", { className: "fdc-think-body", children: text }) : null
|
|
9955
10148
|
] });
|
|
9956
10149
|
}
|
|
9957
10150
|
function Citations({ items = [], onOpen }) {
|
|
9958
|
-
const [open, setOpen] =
|
|
10151
|
+
const [open, setOpen] = React52.useState(false);
|
|
9959
10152
|
if (!items.length) return null;
|
|
9960
|
-
return /* @__PURE__ */
|
|
9961
|
-
/* @__PURE__ */
|
|
9962
|
-
/* @__PURE__ */
|
|
9963
|
-
/* @__PURE__ */
|
|
10153
|
+
return /* @__PURE__ */ jsxs74("div", { className: "fdc-cites", children: [
|
|
10154
|
+
/* @__PURE__ */ jsxs74("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
10155
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
|
|
10156
|
+
/* @__PURE__ */ jsxs74("span", { children: [
|
|
9964
10157
|
items.length,
|
|
9965
10158
|
" source",
|
|
9966
10159
|
items.length === 1 ? "" : "s"
|
|
9967
10160
|
] }),
|
|
9968
|
-
/* @__PURE__ */
|
|
10161
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
|
|
9969
10162
|
] }),
|
|
9970
|
-
open ? /* @__PURE__ */
|
|
9971
|
-
/* @__PURE__ */
|
|
9972
|
-
c.url ? /* @__PURE__ */
|
|
9973
|
-
c.detail ? /* @__PURE__ */
|
|
10163
|
+
open ? /* @__PURE__ */ jsx80("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs74("li", { children: [
|
|
10164
|
+
/* @__PURE__ */ jsx80("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
|
|
10165
|
+
c.url ? /* @__PURE__ */ jsx80("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx80("span", { children: c.title || "Source" }),
|
|
10166
|
+
c.detail ? /* @__PURE__ */ jsx80("span", { className: "fdc-cite-detail", children: c.detail }) : null
|
|
9974
10167
|
] }, c.id || i)) }) : null
|
|
9975
10168
|
] });
|
|
9976
10169
|
}
|
|
@@ -9981,29 +10174,29 @@ function clampText(text, max) {
|
|
|
9981
10174
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
9982
10175
|
}
|
|
9983
10176
|
function MessageBody({ message: m, ctx }) {
|
|
9984
|
-
const [expanded, setExpanded] =
|
|
10177
|
+
const [expanded, setExpanded] = React52.useState(false);
|
|
9985
10178
|
const isUser = m.role === "user";
|
|
9986
10179
|
const raw = m.text || "";
|
|
9987
10180
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
9988
10181
|
const body = clamped != null ? clamped : raw;
|
|
9989
10182
|
const showMd = ctx.markdown && !isUser;
|
|
9990
|
-
return /* @__PURE__ */
|
|
9991
|
-
m.thinking && ctx.showThinking ? /* @__PURE__ */
|
|
9992
|
-
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */
|
|
9993
|
-
body ? /* @__PURE__ */
|
|
9994
|
-
showMd ? /* @__PURE__ */
|
|
9995
|
-
m.streaming ? /* @__PURE__ */
|
|
10183
|
+
return /* @__PURE__ */ jsxs74("div", { className: "fdc-body", children: [
|
|
10184
|
+
m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx80(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
|
|
10185
|
+
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx80(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
|
|
10186
|
+
body ? /* @__PURE__ */ jsxs74("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
|
|
10187
|
+
showMd ? /* @__PURE__ */ jsx80(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx80("div", { className: "fdc-plain", children: body }),
|
|
10188
|
+
m.streaming ? /* @__PURE__ */ jsx80("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
|
|
9996
10189
|
] }) : null,
|
|
9997
|
-
clamped != null ? /* @__PURE__ */
|
|
9998
|
-
/* @__PURE__ */
|
|
10190
|
+
clamped != null ? /* @__PURE__ */ jsxs74("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
|
|
10191
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
|
|
9999
10192
|
"Show more",
|
|
10000
|
-
/* @__PURE__ */
|
|
10001
|
-
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */
|
|
10002
|
-
/* @__PURE__ */
|
|
10193
|
+
/* @__PURE__ */ jsx80("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
|
|
10194
|
+
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs74("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
|
|
10195
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
|
|
10003
10196
|
"Show less"
|
|
10004
10197
|
] }) : null,
|
|
10005
|
-
m.attachments && m.attachments.length ? /* @__PURE__ */
|
|
10006
|
-
m.packet ? /* @__PURE__ */
|
|
10198
|
+
m.attachments && m.attachments.length ? /* @__PURE__ */ jsx80(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
|
|
10199
|
+
m.packet ? /* @__PURE__ */ jsx80(
|
|
10007
10200
|
PacketCard,
|
|
10008
10201
|
{
|
|
10009
10202
|
packet: m.packet,
|
|
@@ -10013,44 +10206,44 @@ function MessageBody({ message: m, ctx }) {
|
|
|
10013
10206
|
applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
|
|
10014
10207
|
}
|
|
10015
10208
|
) : null,
|
|
10016
|
-
m.citations && m.citations.length ? /* @__PURE__ */
|
|
10017
|
-
m.working ? /* @__PURE__ */
|
|
10018
|
-
/* @__PURE__ */
|
|
10019
|
-
/* @__PURE__ */
|
|
10020
|
-
/* @__PURE__ */
|
|
10021
|
-
/* @__PURE__ */
|
|
10209
|
+
m.citations && m.citations.length ? /* @__PURE__ */ jsx80(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
|
|
10210
|
+
m.working ? /* @__PURE__ */ jsxs74("div", { className: "fdc-working", role: "status", children: [
|
|
10211
|
+
/* @__PURE__ */ jsxs74("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
10212
|
+
/* @__PURE__ */ jsx80("span", {}),
|
|
10213
|
+
/* @__PURE__ */ jsx80("span", {}),
|
|
10214
|
+
/* @__PURE__ */ jsx80("span", {})
|
|
10022
10215
|
] }),
|
|
10023
|
-
/* @__PURE__ */
|
|
10216
|
+
/* @__PURE__ */ jsxs74("span", { className: "fdc-working-label", children: [
|
|
10024
10217
|
m.resumed ? "Resuming" : "Working",
|
|
10025
|
-
m.job && m.job.status ? /* @__PURE__ */
|
|
10218
|
+
m.job && m.job.status ? /* @__PURE__ */ jsxs74("span", { className: "fdc-working-job", children: [
|
|
10026
10219
|
" \xB7 ",
|
|
10027
10220
|
m.job.status
|
|
10028
10221
|
] }) : null,
|
|
10029
|
-
m.job && m.job.detail ? /* @__PURE__ */
|
|
10222
|
+
m.job && m.job.detail ? /* @__PURE__ */ jsxs74("span", { className: "fdc-working-job", children: [
|
|
10030
10223
|
" \xB7 ",
|
|
10031
10224
|
m.job.detail
|
|
10032
10225
|
] }) : null
|
|
10033
10226
|
] }),
|
|
10034
|
-
m.jobId ? /* @__PURE__ */
|
|
10227
|
+
m.jobId ? /* @__PURE__ */ jsx80("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
|
|
10035
10228
|
] }) : null,
|
|
10036
|
-
m.stopped ? /* @__PURE__ */
|
|
10037
|
-
/* @__PURE__ */
|
|
10229
|
+
m.stopped ? /* @__PURE__ */ jsxs74("div", { className: "fdc-stopped", children: [
|
|
10230
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
10038
10231
|
"Stopped"
|
|
10039
10232
|
] }) : null,
|
|
10040
|
-
m.error ? /* @__PURE__ */
|
|
10041
|
-
/* @__PURE__ */
|
|
10042
|
-
/* @__PURE__ */
|
|
10043
|
-
m.retryable && ctx.onRetry ? /* @__PURE__ */
|
|
10044
|
-
/* @__PURE__ */
|
|
10233
|
+
m.error ? /* @__PURE__ */ jsxs74("div", { className: "fdc-error", role: "alert", children: [
|
|
10234
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
10235
|
+
/* @__PURE__ */ jsx80("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
|
|
10236
|
+
m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs74("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
|
|
10237
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
10045
10238
|
"Retry"
|
|
10046
10239
|
] }) : null
|
|
10047
10240
|
] }) : null
|
|
10048
10241
|
] });
|
|
10049
10242
|
}
|
|
10050
10243
|
function useCopyRun() {
|
|
10051
|
-
const [done, setDone] =
|
|
10052
|
-
const t =
|
|
10053
|
-
|
|
10244
|
+
const [done, setDone] = React52.useState(false);
|
|
10245
|
+
const t = React52.useRef(null);
|
|
10246
|
+
React52.useEffect(() => () => {
|
|
10054
10247
|
if (t.current) clearTimeout(t.current);
|
|
10055
10248
|
}, []);
|
|
10056
10249
|
return [done, (text) => {
|
|
@@ -10070,16 +10263,16 @@ function RunActions({ group, ctx }) {
|
|
|
10070
10263
|
const isAssistant = group.role === "assistant";
|
|
10071
10264
|
const fb = last.feedback;
|
|
10072
10265
|
if (!ctx.messageActions) return null;
|
|
10073
|
-
return /* @__PURE__ */
|
|
10074
|
-
/* @__PURE__ */
|
|
10075
|
-
/* @__PURE__ */
|
|
10076
|
-
/* @__PURE__ */
|
|
10266
|
+
return /* @__PURE__ */ jsxs74("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
|
|
10267
|
+
/* @__PURE__ */ jsxs74("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
|
|
10268
|
+
/* @__PURE__ */ jsx80("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
|
|
10269
|
+
/* @__PURE__ */ jsx80("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
|
|
10077
10270
|
] }),
|
|
10078
|
-
isAssistant && ctx.onRetry ? /* @__PURE__ */
|
|
10079
|
-
group.role === "user" && ctx.onEdit ? /* @__PURE__ */
|
|
10080
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */
|
|
10081
|
-
/* @__PURE__ */
|
|
10082
|
-
/* @__PURE__ */
|
|
10271
|
+
isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx80("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx80("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
10272
|
+
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx80("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx80("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
10273
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs74(React52.Fragment, { children: [
|
|
10274
|
+
/* @__PURE__ */ jsx80("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__ */ jsx80("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
10275
|
+
/* @__PURE__ */ jsx80("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__ */ jsx80("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
10083
10276
|
] }) : null,
|
|
10084
10277
|
ctx.extraActions ? ctx.extraActions(group) : null
|
|
10085
10278
|
] });
|
|
@@ -10089,22 +10282,22 @@ function ChatTurn({ group, ctx }) {
|
|
|
10089
10282
|
const name = isUser ? ctx.userName : group.author || ctx.assistantName;
|
|
10090
10283
|
const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
|
|
10091
10284
|
const stamp = group.messages[0].timestamp;
|
|
10092
|
-
return /* @__PURE__ */
|
|
10093
|
-
/* @__PURE__ */
|
|
10094
|
-
ctx.showAvatars ? /* @__PURE__ */
|
|
10095
|
-
/* @__PURE__ */
|
|
10096
|
-
stamp ? /* @__PURE__ */
|
|
10097
|
-
group.messages.some((m) => m.model) ? /* @__PURE__ */
|
|
10285
|
+
return /* @__PURE__ */ jsxs74("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
|
|
10286
|
+
/* @__PURE__ */ jsxs74("div", { className: "fdc-turn-head", children: [
|
|
10287
|
+
ctx.showAvatars ? /* @__PURE__ */ jsx80("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx80("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx80("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx80("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
|
|
10288
|
+
/* @__PURE__ */ jsx80("span", { className: "fdc-who", children: name }),
|
|
10289
|
+
stamp ? /* @__PURE__ */ jsx80(RelativeTime, { className: "fdc-when", value: stamp }) : null,
|
|
10290
|
+
group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx80("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
|
|
10098
10291
|
] }),
|
|
10099
|
-
/* @__PURE__ */
|
|
10100
|
-
group.messages.map((m) => /* @__PURE__ */
|
|
10101
|
-
/* @__PURE__ */
|
|
10292
|
+
/* @__PURE__ */ jsxs74("div", { className: "fdc-turn-body", children: [
|
|
10293
|
+
group.messages.map((m) => /* @__PURE__ */ jsx80("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx80(MessageBody, { message: m, ctx }) }, m.id)),
|
|
10294
|
+
/* @__PURE__ */ jsx80(RunActions, { group, ctx })
|
|
10102
10295
|
] })
|
|
10103
10296
|
] });
|
|
10104
10297
|
}
|
|
10105
10298
|
|
|
10106
10299
|
// src/components/chat/ChatTranscript.tsx
|
|
10107
|
-
import { jsx as
|
|
10300
|
+
import { jsx as jsx81, jsxs as jsxs75 } from "react/jsx-runtime";
|
|
10108
10301
|
var GROUP_WINDOW = 6e4;
|
|
10109
10302
|
var STICK_PX = 100;
|
|
10110
10303
|
function groupMessages(list) {
|
|
@@ -10137,25 +10330,25 @@ function dayLabel(key) {
|
|
|
10137
10330
|
}
|
|
10138
10331
|
function Suggestions({ items = [], onPick }) {
|
|
10139
10332
|
if (!items.length) return null;
|
|
10140
|
-
return /* @__PURE__ */
|
|
10333
|
+
return /* @__PURE__ */ jsx81("div", { className: "fdc-suggest", children: items.map((s, i) => {
|
|
10141
10334
|
const it = typeof s === "string" ? { label: s, text: s } : s;
|
|
10142
|
-
return /* @__PURE__ */
|
|
10143
|
-
it.icon ? /* @__PURE__ */
|
|
10144
|
-
/* @__PURE__ */
|
|
10145
|
-
/* @__PURE__ */
|
|
10146
|
-
it.description ? /* @__PURE__ */
|
|
10335
|
+
return /* @__PURE__ */ jsxs75("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
|
|
10336
|
+
it.icon ? /* @__PURE__ */ jsx81("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
|
|
10337
|
+
/* @__PURE__ */ jsxs75("span", { className: "fdc-suggest-text", children: [
|
|
10338
|
+
/* @__PURE__ */ jsx81("span", { className: "fdc-suggest-label", children: it.label }),
|
|
10339
|
+
it.description ? /* @__PURE__ */ jsx81("span", { className: "fdc-suggest-desc", children: it.description }) : null
|
|
10147
10340
|
] }),
|
|
10148
|
-
/* @__PURE__ */
|
|
10341
|
+
/* @__PURE__ */ jsx81("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
|
|
10149
10342
|
] }, it.id || i);
|
|
10150
10343
|
}) });
|
|
10151
10344
|
}
|
|
10152
10345
|
function LoadingTurns() {
|
|
10153
|
-
return /* @__PURE__ */
|
|
10154
|
-
/* @__PURE__ */
|
|
10155
|
-
/* @__PURE__ */
|
|
10156
|
-
/* @__PURE__ */
|
|
10157
|
-
/* @__PURE__ */
|
|
10158
|
-
/* @__PURE__ */
|
|
10346
|
+
return /* @__PURE__ */ jsx81("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs75("div", { className: "fdc-skel-turn", children: [
|
|
10347
|
+
/* @__PURE__ */ jsx81("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
|
|
10348
|
+
/* @__PURE__ */ jsxs75("div", { className: "fdc-skel-lines", children: [
|
|
10349
|
+
/* @__PURE__ */ jsx81("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
|
|
10350
|
+
/* @__PURE__ */ jsx81("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
|
|
10351
|
+
/* @__PURE__ */ jsx81("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
|
|
10159
10352
|
] })
|
|
10160
10353
|
] }, i)) });
|
|
10161
10354
|
}
|
|
@@ -10172,10 +10365,10 @@ function ChatTranscript({
|
|
|
10172
10365
|
renderEmpty,
|
|
10173
10366
|
className = ""
|
|
10174
10367
|
}) {
|
|
10175
|
-
const scroller =
|
|
10176
|
-
const stick =
|
|
10177
|
-
const [pill, setPill] =
|
|
10178
|
-
const seen =
|
|
10368
|
+
const scroller = React53.useRef(null);
|
|
10369
|
+
const stick = React53.useRef(true);
|
|
10370
|
+
const [pill, setPill] = React53.useState(0);
|
|
10371
|
+
const seen = React53.useRef(0);
|
|
10179
10372
|
const toBottom = (smooth) => {
|
|
10180
10373
|
const el = scroller.current;
|
|
10181
10374
|
if (!el) return;
|
|
@@ -10194,7 +10387,7 @@ function ChatTranscript({
|
|
|
10194
10387
|
seen.current = messages.length;
|
|
10195
10388
|
}
|
|
10196
10389
|
};
|
|
10197
|
-
|
|
10390
|
+
React53.useLayoutEffect(() => {
|
|
10198
10391
|
const el = scroller.current;
|
|
10199
10392
|
if (!el) return;
|
|
10200
10393
|
if (stick.current) {
|
|
@@ -10202,7 +10395,7 @@ function ChatTranscript({
|
|
|
10202
10395
|
seen.current = messages.length;
|
|
10203
10396
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
10204
10397
|
}, [messages]);
|
|
10205
|
-
|
|
10398
|
+
React53.useEffect(() => {
|
|
10206
10399
|
const el = scroller.current;
|
|
10207
10400
|
const inner = el && el.firstChild;
|
|
10208
10401
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -10212,38 +10405,38 @@ function ChatTranscript({
|
|
|
10212
10405
|
ro.observe(inner);
|
|
10213
10406
|
return () => ro.disconnect();
|
|
10214
10407
|
}, []);
|
|
10215
|
-
const groups =
|
|
10408
|
+
const groups = React53.useMemo(() => groupMessages(messages), [messages]);
|
|
10216
10409
|
const empty = !messages.length && status === "ready";
|
|
10217
|
-
return /* @__PURE__ */
|
|
10218
|
-
/* @__PURE__ */
|
|
10219
|
-
status === "loading" || status === "resolving" ? /* @__PURE__ */
|
|
10220
|
-
status === "disconnected" ? /* @__PURE__ */
|
|
10221
|
-
/* @__PURE__ */
|
|
10222
|
-
/* @__PURE__ */
|
|
10223
|
-
/* @__PURE__ */
|
|
10224
|
-
ctx.onReconnect ? /* @__PURE__ */
|
|
10225
|
-
/* @__PURE__ */
|
|
10410
|
+
return /* @__PURE__ */ jsxs75("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
10411
|
+
/* @__PURE__ */ jsxs75("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
10412
|
+
status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx81(LoadingTurns, {}) : null,
|
|
10413
|
+
status === "disconnected" ? /* @__PURE__ */ jsxs75("div", { className: "fdc-dead", children: [
|
|
10414
|
+
/* @__PURE__ */ jsx81("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx81("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
|
|
10415
|
+
/* @__PURE__ */ jsx81("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
|
|
10416
|
+
/* @__PURE__ */ jsx81("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." }),
|
|
10417
|
+
ctx.onReconnect ? /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
|
|
10418
|
+
/* @__PURE__ */ jsx81("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
10226
10419
|
"Try again"
|
|
10227
10420
|
] }) : null
|
|
10228
10421
|
] }) : null,
|
|
10229
|
-
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */
|
|
10230
|
-
/* @__PURE__ */
|
|
10231
|
-
/* @__PURE__ */
|
|
10232
|
-
emptyDescription ? /* @__PURE__ */
|
|
10233
|
-
/* @__PURE__ */
|
|
10422
|
+
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs75("div", { className: "fdc-empty", children: [
|
|
10423
|
+
/* @__PURE__ */ jsx81("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx81("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
|
|
10424
|
+
/* @__PURE__ */ jsx81("h3", { className: "fdc-empty-title", children: emptyTitle }),
|
|
10425
|
+
emptyDescription ? /* @__PURE__ */ jsx81("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
|
|
10426
|
+
/* @__PURE__ */ jsx81(Suggestions, { items: suggestions, onPick })
|
|
10234
10427
|
] }) : null,
|
|
10235
10428
|
groups.map((g, i) => {
|
|
10236
10429
|
const prev = groups[i - 1];
|
|
10237
10430
|
const k = dayKey(g.messages[0].timestamp);
|
|
10238
10431
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
10239
|
-
return /* @__PURE__ */
|
|
10240
|
-
showDay ? /* @__PURE__ */
|
|
10241
|
-
/* @__PURE__ */
|
|
10432
|
+
return /* @__PURE__ */ jsxs75(React53.Fragment, { children: [
|
|
10433
|
+
showDay ? /* @__PURE__ */ jsx81("div", { className: "fdc-day", children: /* @__PURE__ */ jsx81("span", { children: dayLabel(k) }) }) : null,
|
|
10434
|
+
/* @__PURE__ */ jsx81(ChatTurn, { group: g, ctx })
|
|
10242
10435
|
] }, g.key || i);
|
|
10243
10436
|
})
|
|
10244
10437
|
] }),
|
|
10245
|
-
pill ? /* @__PURE__ */
|
|
10246
|
-
/* @__PURE__ */
|
|
10438
|
+
pill ? /* @__PURE__ */ jsxs75("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
|
|
10439
|
+
/* @__PURE__ */ jsx81("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
|
|
10247
10440
|
pill,
|
|
10248
10441
|
" new message",
|
|
10249
10442
|
pill === 1 ? "" : "s"
|
|
@@ -10253,8 +10446,8 @@ function ChatTranscript({
|
|
|
10253
10446
|
var TranscriptKit = { groupMessages };
|
|
10254
10447
|
|
|
10255
10448
|
// src/components/chat/ChatComposer.tsx
|
|
10256
|
-
import * as
|
|
10257
|
-
import { jsx as
|
|
10449
|
+
import * as React54 from "react";
|
|
10450
|
+
import { jsx as jsx82, jsxs as jsxs76 } from "react/jsx-runtime";
|
|
10258
10451
|
function ChatComposer({
|
|
10259
10452
|
onSubmit,
|
|
10260
10453
|
onStop,
|
|
@@ -10281,17 +10474,17 @@ function ChatComposer({
|
|
|
10281
10474
|
onReject,
|
|
10282
10475
|
onOpenAttachment
|
|
10283
10476
|
}) {
|
|
10284
|
-
const [text, setText] =
|
|
10285
|
-
const [trigger, setTrigger] =
|
|
10286
|
-
const [mentionItems, setMentionItems] =
|
|
10287
|
-
const [listening, setListening] =
|
|
10288
|
-
const [notice, setNotice] =
|
|
10289
|
-
const editor =
|
|
10290
|
-
const wrap =
|
|
10291
|
-
const stopVoice =
|
|
10477
|
+
const [text, setText] = React54.useState(draft || "");
|
|
10478
|
+
const [trigger, setTrigger] = React54.useState(null);
|
|
10479
|
+
const [mentionItems, setMentionItems] = React54.useState([]);
|
|
10480
|
+
const [listening, setListening] = React54.useState(false);
|
|
10481
|
+
const [notice, setNotice] = React54.useState(null);
|
|
10482
|
+
const editor = React54.useRef(null);
|
|
10483
|
+
const wrap = React54.useRef(null);
|
|
10484
|
+
const stopVoice = React54.useRef(null);
|
|
10292
10485
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
10293
10486
|
} });
|
|
10294
|
-
|
|
10487
|
+
React54.useEffect(() => {
|
|
10295
10488
|
if (draft != null && draft !== text) setText(draft);
|
|
10296
10489
|
}, [draft]);
|
|
10297
10490
|
const change = (v) => {
|
|
@@ -10327,7 +10520,7 @@ function ChatComposer({
|
|
|
10327
10520
|
e.preventDefault();
|
|
10328
10521
|
staged.add(found.files);
|
|
10329
10522
|
};
|
|
10330
|
-
|
|
10523
|
+
React54.useEffect(() => {
|
|
10331
10524
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
10332
10525
|
setMentionItems([]);
|
|
10333
10526
|
return;
|
|
@@ -10345,7 +10538,7 @@ function ChatComposer({
|
|
|
10345
10538
|
const q = (trigger.query || "").toLowerCase();
|
|
10346
10539
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
10347
10540
|
}, [trigger, mentionSources]);
|
|
10348
|
-
const slashItems =
|
|
10541
|
+
const slashItems = React54.useMemo(() => {
|
|
10349
10542
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
10350
10543
|
const q = (trigger.query || "").toLowerCase();
|
|
10351
10544
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -10359,7 +10552,7 @@ function ChatComposer({
|
|
|
10359
10552
|
description: it.description,
|
|
10360
10553
|
icon: it.icon,
|
|
10361
10554
|
meta: mention.meta,
|
|
10362
|
-
shortcut: slash.shortcut ? /* @__PURE__ */
|
|
10555
|
+
shortcut: slash.shortcut ? /* @__PURE__ */ jsx82(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
|
|
10363
10556
|
onSelect: () => {
|
|
10364
10557
|
const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
|
|
10365
10558
|
editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
|
|
@@ -10422,14 +10615,14 @@ function ChatComposer({
|
|
|
10422
10615
|
stopVoice.current = typeof res === "function" ? res : () => {
|
|
10423
10616
|
};
|
|
10424
10617
|
};
|
|
10425
|
-
return /* @__PURE__ */
|
|
10426
|
-
queue.length ? /* @__PURE__ */
|
|
10427
|
-
/* @__PURE__ */
|
|
10428
|
-
/* @__PURE__ */
|
|
10429
|
-
onRemoveQueued ? /* @__PURE__ */
|
|
10618
|
+
return /* @__PURE__ */ jsxs76("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
|
|
10619
|
+
queue.length ? /* @__PURE__ */ jsx82("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs76("div", { className: "fdc-queue-row", children: [
|
|
10620
|
+
/* @__PURE__ */ jsx82("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
|
|
10621
|
+
/* @__PURE__ */ jsx82("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)" : "") }),
|
|
10622
|
+
onRemoveQueued ? /* @__PURE__ */ jsx82("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx82("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
10430
10623
|
] }, q.id)) }) : null,
|
|
10431
10624
|
sessionBar,
|
|
10432
|
-
/* @__PURE__ */
|
|
10625
|
+
/* @__PURE__ */ jsx82(
|
|
10433
10626
|
Dropzone,
|
|
10434
10627
|
{
|
|
10435
10628
|
className: "fdc-field",
|
|
@@ -10443,9 +10636,9 @@ function ChatComposer({
|
|
|
10443
10636
|
disabled: !fileUploadHandler || disabled,
|
|
10444
10637
|
label: "Drop to attach",
|
|
10445
10638
|
hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
|
|
10446
|
-
children: /* @__PURE__ */
|
|
10447
|
-
staged.items.length ? /* @__PURE__ */
|
|
10448
|
-
/* @__PURE__ */
|
|
10639
|
+
children: /* @__PURE__ */ jsxs76("div", { ref: wrap, className: "fdc-field-inner", children: [
|
|
10640
|
+
staged.items.length ? /* @__PURE__ */ jsx82("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx82(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
|
|
10641
|
+
/* @__PURE__ */ jsx82(
|
|
10449
10642
|
MarkdownEditor,
|
|
10450
10643
|
{
|
|
10451
10644
|
ref: editor,
|
|
@@ -10464,33 +10657,33 @@ function ChatComposer({
|
|
|
10464
10657
|
ariaLabel: "Message"
|
|
10465
10658
|
}
|
|
10466
10659
|
),
|
|
10467
|
-
/* @__PURE__ */
|
|
10468
|
-
fileUploadHandler ? /* @__PURE__ */
|
|
10469
|
-
voiceHandler ? /* @__PURE__ */
|
|
10660
|
+
/* @__PURE__ */ jsxs76("div", { className: "fdc-tools", children: [
|
|
10661
|
+
fileUploadHandler ? /* @__PURE__ */ jsx82(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
|
|
10662
|
+
voiceHandler ? /* @__PURE__ */ jsx82("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx82("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
|
|
10470
10663
|
toolbarExtras,
|
|
10471
|
-
/* @__PURE__ */
|
|
10472
|
-
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */
|
|
10664
|
+
/* @__PURE__ */ jsx82("span", { className: "fdc-tools-gap" }),
|
|
10665
|
+
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs76("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
|
|
10473
10666
|
text.length,
|
|
10474
10667
|
"/",
|
|
10475
10668
|
maxLength
|
|
10476
10669
|
] }) : null,
|
|
10477
|
-
busy ? /* @__PURE__ */
|
|
10478
|
-
/* @__PURE__ */
|
|
10479
|
-
/* @__PURE__ */
|
|
10480
|
-
] }) : /* @__PURE__ */
|
|
10481
|
-
/* @__PURE__ */
|
|
10482
|
-
/* @__PURE__ */
|
|
10670
|
+
busy ? /* @__PURE__ */ jsxs76("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
|
|
10671
|
+
/* @__PURE__ */ jsx82("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
10672
|
+
/* @__PURE__ */ jsx82("span", { children: "Stop" })
|
|
10673
|
+
] }) : /* @__PURE__ */ jsxs76("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
|
|
10674
|
+
/* @__PURE__ */ jsx82("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
|
|
10675
|
+
/* @__PURE__ */ jsx82("span", { className: "fdc-send-label", children: "Send" })
|
|
10483
10676
|
] })
|
|
10484
10677
|
] })
|
|
10485
10678
|
] })
|
|
10486
10679
|
}
|
|
10487
10680
|
),
|
|
10488
|
-
notice ? /* @__PURE__ */
|
|
10489
|
-
/* @__PURE__ */
|
|
10681
|
+
notice ? /* @__PURE__ */ jsxs76("div", { className: "fdc-notice", role: "status", children: [
|
|
10682
|
+
/* @__PURE__ */ jsx82("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
10490
10683
|
notice
|
|
10491
10684
|
] }) : null,
|
|
10492
|
-
hint && !notice ? /* @__PURE__ */
|
|
10493
|
-
/* @__PURE__ */
|
|
10685
|
+
hint && !notice ? /* @__PURE__ */ jsx82("div", { className: "fdc-hint", children: hint }) : null,
|
|
10686
|
+
/* @__PURE__ */ jsx82(
|
|
10494
10687
|
Popover,
|
|
10495
10688
|
{
|
|
10496
10689
|
open: menuOpen,
|
|
@@ -10504,12 +10697,12 @@ function ChatComposer({
|
|
|
10504
10697
|
returnFocus: false,
|
|
10505
10698
|
closeOnOutside: true,
|
|
10506
10699
|
label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
|
|
10507
|
-
children: /* @__PURE__ */
|
|
10700
|
+
children: /* @__PURE__ */ jsx82(
|
|
10508
10701
|
Menu,
|
|
10509
10702
|
{
|
|
10510
10703
|
items: menuItems,
|
|
10511
10704
|
autoFocus: false,
|
|
10512
|
-
header: /* @__PURE__ */
|
|
10705
|
+
header: /* @__PURE__ */ jsx82("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
|
|
10513
10706
|
onClose: () => setTrigger(null)
|
|
10514
10707
|
}
|
|
10515
10708
|
)
|
|
@@ -10519,12 +10712,12 @@ function ChatComposer({
|
|
|
10519
10712
|
}
|
|
10520
10713
|
|
|
10521
10714
|
// src/components/chat/ChatSessionBar.tsx
|
|
10522
|
-
import * as
|
|
10523
|
-
import { jsx as
|
|
10715
|
+
import * as React55 from "react";
|
|
10716
|
+
import { jsx as jsx83, jsxs as jsxs77 } from "react/jsx-runtime";
|
|
10524
10717
|
var compact2 = meterFormats.compact;
|
|
10525
10718
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
10526
|
-
const [open, setOpen] =
|
|
10527
|
-
const anchor =
|
|
10719
|
+
const [open, setOpen] = React55.useState(false);
|
|
10720
|
+
const anchor = React55.useRef(null);
|
|
10528
10721
|
const stats = sessionStats || null;
|
|
10529
10722
|
const cu = contextUsage || null;
|
|
10530
10723
|
const limits = usageLimits || null;
|
|
@@ -10539,9 +10732,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
10539
10732
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
10540
10733
|
if (cu) bits.push(pct + "% context");
|
|
10541
10734
|
const expandable = !!(cu || limits);
|
|
10542
|
-
return /* @__PURE__ */
|
|
10543
|
-
/* @__PURE__ */
|
|
10544
|
-
/* @__PURE__ */
|
|
10735
|
+
return /* @__PURE__ */ jsxs77(React55.Fragment, { children: [
|
|
10736
|
+
/* @__PURE__ */ jsxs77("div", { className: "fdc-bar", children: [
|
|
10737
|
+
/* @__PURE__ */ jsxs77(
|
|
10545
10738
|
"button",
|
|
10546
10739
|
{
|
|
10547
10740
|
type: "button",
|
|
@@ -10552,15 +10745,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
10552
10745
|
"aria-expanded": expandable ? open : void 0,
|
|
10553
10746
|
"aria-label": expandable ? "Usage details" : void 0,
|
|
10554
10747
|
children: [
|
|
10555
|
-
cu ? /* @__PURE__ */
|
|
10556
|
-
/* @__PURE__ */
|
|
10557
|
-
expandable ? /* @__PURE__ */
|
|
10748
|
+
cu ? /* @__PURE__ */ jsx83("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx83(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
|
|
10749
|
+
/* @__PURE__ */ jsx83("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
|
|
10750
|
+
expandable ? /* @__PURE__ */ jsx83("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
|
|
10558
10751
|
]
|
|
10559
10752
|
}
|
|
10560
10753
|
),
|
|
10561
10754
|
extras
|
|
10562
10755
|
] }),
|
|
10563
|
-
/* @__PURE__ */
|
|
10756
|
+
/* @__PURE__ */ jsx83(
|
|
10564
10757
|
Popover,
|
|
10565
10758
|
{
|
|
10566
10759
|
open,
|
|
@@ -10571,15 +10764,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
10571
10764
|
maxHeight: 460,
|
|
10572
10765
|
padded: true,
|
|
10573
10766
|
label: "Usage",
|
|
10574
|
-
footer: onClear ? /* @__PURE__ */
|
|
10767
|
+
footer: onClear ? /* @__PURE__ */ jsxs77("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
|
|
10575
10768
|
setOpen(false);
|
|
10576
10769
|
onClear();
|
|
10577
10770
|
}, children: [
|
|
10578
|
-
/* @__PURE__ */
|
|
10771
|
+
/* @__PURE__ */ jsx83("i", { className: "ph ph-trash", "aria-hidden": "true" }),
|
|
10579
10772
|
"Clear conversation"
|
|
10580
10773
|
] }) : void 0,
|
|
10581
|
-
children: /* @__PURE__ */
|
|
10582
|
-
cu ? /* @__PURE__ */
|
|
10774
|
+
children: /* @__PURE__ */ jsxs77("div", { className: "fdc-usage", children: [
|
|
10775
|
+
cu ? /* @__PURE__ */ jsx83("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx83(
|
|
10583
10776
|
SegmentedMeter,
|
|
10584
10777
|
{
|
|
10585
10778
|
total,
|
|
@@ -10591,9 +10784,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
10591
10784
|
remainderLabel: "Free"
|
|
10592
10785
|
}
|
|
10593
10786
|
) }) : null,
|
|
10594
|
-
limits && limits.length ? /* @__PURE__ */
|
|
10595
|
-
/* @__PURE__ */
|
|
10596
|
-
/* @__PURE__ */
|
|
10787
|
+
limits && limits.length ? /* @__PURE__ */ jsxs77("section", { className: "fdc-usage-sec", children: [
|
|
10788
|
+
/* @__PURE__ */ jsx83("h4", { className: "fdc-usage-h", children: "Usage limits" }),
|
|
10789
|
+
/* @__PURE__ */ jsx83("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx83(
|
|
10597
10790
|
QuotaRow,
|
|
10598
10791
|
{
|
|
10599
10792
|
label: l.label,
|
|
@@ -10603,25 +10796,25 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
10603
10796
|
l.id
|
|
10604
10797
|
)) })
|
|
10605
10798
|
] }) : null,
|
|
10606
|
-
stats ? /* @__PURE__ */
|
|
10607
|
-
stats.elapsedMs ? /* @__PURE__ */
|
|
10608
|
-
/* @__PURE__ */
|
|
10609
|
-
/* @__PURE__ */
|
|
10799
|
+
stats ? /* @__PURE__ */ jsxs77("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
|
|
10800
|
+
stats.elapsedMs ? /* @__PURE__ */ jsxs77("div", { children: [
|
|
10801
|
+
/* @__PURE__ */ jsx83("span", { children: "Session" }),
|
|
10802
|
+
/* @__PURE__ */ jsx83("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
|
|
10610
10803
|
] }) : null,
|
|
10611
|
-
stats.tokens ? /* @__PURE__ */
|
|
10612
|
-
/* @__PURE__ */
|
|
10613
|
-
/* @__PURE__ */
|
|
10804
|
+
stats.tokens ? /* @__PURE__ */ jsxs77("div", { children: [
|
|
10805
|
+
/* @__PURE__ */ jsx83("span", { children: "Tokens" }),
|
|
10806
|
+
/* @__PURE__ */ jsx83("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
|
|
10614
10807
|
] }) : null,
|
|
10615
|
-
stats.costUsd != null ? /* @__PURE__ */
|
|
10616
|
-
/* @__PURE__ */
|
|
10617
|
-
/* @__PURE__ */
|
|
10808
|
+
stats.costUsd != null ? /* @__PURE__ */ jsxs77("div", { children: [
|
|
10809
|
+
/* @__PURE__ */ jsx83("span", { children: "Cost" }),
|
|
10810
|
+
/* @__PURE__ */ jsxs77("b", { className: "fd-tabular", children: [
|
|
10618
10811
|
"$",
|
|
10619
10812
|
Number(stats.costUsd).toFixed(3)
|
|
10620
10813
|
] })
|
|
10621
10814
|
] }) : null,
|
|
10622
|
-
stats.turns ? /* @__PURE__ */
|
|
10623
|
-
/* @__PURE__ */
|
|
10624
|
-
/* @__PURE__ */
|
|
10815
|
+
stats.turns ? /* @__PURE__ */ jsxs77("div", { children: [
|
|
10816
|
+
/* @__PURE__ */ jsx83("span", { children: "Turns" }),
|
|
10817
|
+
/* @__PURE__ */ jsx83("b", { className: "fd-tabular", children: stats.turns })
|
|
10625
10818
|
] }) : null
|
|
10626
10819
|
] }) : null
|
|
10627
10820
|
] })
|
|
@@ -10660,7 +10853,7 @@ function ModelControls({
|
|
|
10660
10853
|
disabled: m.disabled,
|
|
10661
10854
|
checked: m.id === (current2 && current2.id),
|
|
10662
10855
|
meta: m.meta,
|
|
10663
|
-
shortcut: m.shortcut ? /* @__PURE__ */
|
|
10856
|
+
shortcut: m.shortcut ? /* @__PURE__ */ jsx83(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
|
|
10664
10857
|
onSelect: () => onModelChange && onModelChange(m.id)
|
|
10665
10858
|
});
|
|
10666
10859
|
const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
|
|
@@ -10673,15 +10866,15 @@ function ModelControls({
|
|
|
10673
10866
|
items.push({ kind: "section", label: "Fast mode" });
|
|
10674
10867
|
items.push({
|
|
10675
10868
|
kind: "custom",
|
|
10676
|
-
render: () => /* @__PURE__ */
|
|
10677
|
-
/* @__PURE__ */
|
|
10678
|
-
/* @__PURE__ */
|
|
10679
|
-
/* @__PURE__ */
|
|
10869
|
+
render: () => /* @__PURE__ */ jsxs77("label", { className: "fdc-switchrow", children: [
|
|
10870
|
+
/* @__PURE__ */ jsx83("span", { children: fastModeLabel }),
|
|
10871
|
+
/* @__PURE__ */ jsx83("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
|
|
10872
|
+
/* @__PURE__ */ jsx83("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx83("span", { className: "fd-switch-thumb" }) })
|
|
10680
10873
|
] })
|
|
10681
10874
|
});
|
|
10682
10875
|
}
|
|
10683
|
-
return /* @__PURE__ */
|
|
10684
|
-
/* @__PURE__ */
|
|
10876
|
+
return /* @__PURE__ */ jsxs77(React55.Fragment, { children: [
|
|
10877
|
+
/* @__PURE__ */ jsx83(
|
|
10685
10878
|
MenuButton,
|
|
10686
10879
|
{
|
|
10687
10880
|
items,
|
|
@@ -10692,7 +10885,7 @@ function ModelControls({
|
|
|
10692
10885
|
title: "Choose a model"
|
|
10693
10886
|
}
|
|
10694
10887
|
),
|
|
10695
|
-
effortLevels && effortLevels.length ? /* @__PURE__ */
|
|
10888
|
+
effortLevels && effortLevels.length ? /* @__PURE__ */ jsx83(
|
|
10696
10889
|
MenuButton,
|
|
10697
10890
|
{
|
|
10698
10891
|
placement: "top-end",
|
|
@@ -10713,7 +10906,7 @@ function ModelControls({
|
|
|
10713
10906
|
}
|
|
10714
10907
|
|
|
10715
10908
|
// src/components/chat/AgentChatPanel.tsx
|
|
10716
|
-
import { jsx as
|
|
10909
|
+
import { jsx as jsx84, jsxs as jsxs78 } from "react/jsx-runtime";
|
|
10717
10910
|
var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
|
|
10718
10911
|
function AgentChatPanel({
|
|
10719
10912
|
/* required */
|
|
@@ -10797,11 +10990,11 @@ function AgentChatPanel({
|
|
|
10797
10990
|
onFeedback,
|
|
10798
10991
|
onEditMessage
|
|
10799
10992
|
}) {
|
|
10800
|
-
const [panelWidth, setPanelWidth] =
|
|
10801
|
-
const [applied, setApplied] =
|
|
10802
|
-
const [draft, setDraft] =
|
|
10803
|
-
const dragging =
|
|
10804
|
-
|
|
10993
|
+
const [panelWidth, setPanelWidth] = React56.useState(width);
|
|
10994
|
+
const [applied, setApplied] = React56.useState({});
|
|
10995
|
+
const [draft, setDraft] = React56.useState("");
|
|
10996
|
+
const dragging = React56.useRef(null);
|
|
10997
|
+
React56.useEffect(() => setPanelWidth(width), [width]);
|
|
10805
10998
|
const engine = useChatEngine({
|
|
10806
10999
|
contextType,
|
|
10807
11000
|
contextId,
|
|
@@ -10867,7 +11060,7 @@ function AgentChatPanel({
|
|
|
10867
11060
|
onReconnect: engine.reload,
|
|
10868
11061
|
deadTitle: "The assistant isn\u2019t reachable"
|
|
10869
11062
|
};
|
|
10870
|
-
const sessionBar = /* @__PURE__ */
|
|
11063
|
+
const sessionBar = /* @__PURE__ */ jsx84(
|
|
10871
11064
|
ChatSessionBar,
|
|
10872
11065
|
{
|
|
10873
11066
|
sessionStats,
|
|
@@ -10876,7 +11069,7 @@ function AgentChatPanel({
|
|
|
10876
11069
|
onClear: engine.visible.length ? engine.clear : void 0
|
|
10877
11070
|
}
|
|
10878
11071
|
);
|
|
10879
|
-
const modelControls = /* @__PURE__ */
|
|
11072
|
+
const modelControls = /* @__PURE__ */ jsx84(
|
|
10880
11073
|
ModelControls,
|
|
10881
11074
|
{
|
|
10882
11075
|
models,
|
|
@@ -10891,7 +11084,7 @@ function AgentChatPanel({
|
|
|
10891
11084
|
narrow
|
|
10892
11085
|
}
|
|
10893
11086
|
);
|
|
10894
|
-
const threadMenu = threads && threads.length ? /* @__PURE__ */
|
|
11087
|
+
const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx84(
|
|
10895
11088
|
MenuButton,
|
|
10896
11089
|
{
|
|
10897
11090
|
variant: "ghost",
|
|
@@ -10918,7 +11111,7 @@ function AgentChatPanel({
|
|
|
10918
11111
|
})))
|
|
10919
11112
|
}
|
|
10920
11113
|
) : null;
|
|
10921
|
-
return /* @__PURE__ */
|
|
11114
|
+
return /* @__PURE__ */ jsxs78(
|
|
10922
11115
|
"aside",
|
|
10923
11116
|
{
|
|
10924
11117
|
className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
|
|
@@ -10929,7 +11122,7 @@ function AgentChatPanel({
|
|
|
10929
11122
|
},
|
|
10930
11123
|
"aria-label": title,
|
|
10931
11124
|
children: [
|
|
10932
|
-
surface === "sidebar" && resizable ? /* @__PURE__ */
|
|
11125
|
+
surface === "sidebar" && resizable ? /* @__PURE__ */ jsx84(
|
|
10933
11126
|
"div",
|
|
10934
11127
|
{
|
|
10935
11128
|
className: "fdc-grip",
|
|
@@ -10944,20 +11137,20 @@ function AgentChatPanel({
|
|
|
10944
11137
|
}
|
|
10945
11138
|
}
|
|
10946
11139
|
) : null,
|
|
10947
|
-
showHeader ? /* @__PURE__ */
|
|
10948
|
-
/* @__PURE__ */
|
|
10949
|
-
/* @__PURE__ */
|
|
10950
|
-
/* @__PURE__ */
|
|
10951
|
-
subtitle ? /* @__PURE__ */
|
|
11140
|
+
showHeader ? /* @__PURE__ */ jsxs78("header", { className: "fdc-head", children: [
|
|
11141
|
+
/* @__PURE__ */ jsx84("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx84("i", { className: "ph ph-" + assistantIcon }) }),
|
|
11142
|
+
/* @__PURE__ */ jsxs78("span", { className: "fdc-head-titles", children: [
|
|
11143
|
+
/* @__PURE__ */ jsx84("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
|
|
11144
|
+
subtitle ? /* @__PURE__ */ jsx84("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
|
|
10952
11145
|
] }),
|
|
10953
|
-
/* @__PURE__ */
|
|
11146
|
+
/* @__PURE__ */ jsxs78("span", { className: "fdc-head-acts", children: [
|
|
10954
11147
|
headerActions,
|
|
10955
11148
|
threadMenu,
|
|
10956
|
-
onNewThread ? /* @__PURE__ */
|
|
10957
|
-
onClose ? /* @__PURE__ */
|
|
11149
|
+
onNewThread ? /* @__PURE__ */ jsx84("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx84("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
|
|
11150
|
+
onClose ? /* @__PURE__ */ jsx84("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx84("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
10958
11151
|
] })
|
|
10959
11152
|
] }) : null,
|
|
10960
|
-
/* @__PURE__ */
|
|
11153
|
+
/* @__PURE__ */ jsx84(
|
|
10961
11154
|
ChatTranscript,
|
|
10962
11155
|
{
|
|
10963
11156
|
messages: engine.visible,
|
|
@@ -10972,7 +11165,7 @@ function AgentChatPanel({
|
|
|
10972
11165
|
renderEmpty
|
|
10973
11166
|
}
|
|
10974
11167
|
),
|
|
10975
|
-
/* @__PURE__ */
|
|
11168
|
+
/* @__PURE__ */ jsx84(
|
|
10976
11169
|
ChatComposer,
|
|
10977
11170
|
{
|
|
10978
11171
|
onSubmit: (text, atts) => engine.send(text, atts),
|
|
@@ -11005,8 +11198,8 @@ function AgentChatPanel({
|
|
|
11005
11198
|
}
|
|
11006
11199
|
|
|
11007
11200
|
// src/components/files/FileViewer.tsx
|
|
11008
|
-
import * as
|
|
11009
|
-
import { jsx as
|
|
11201
|
+
import * as React57 from "react";
|
|
11202
|
+
import { jsx as jsx85, jsxs as jsxs79 } from "react/jsx-runtime";
|
|
11010
11203
|
function previewKindOf(file) {
|
|
11011
11204
|
const mime = (file.mime || "").toLowerCase();
|
|
11012
11205
|
const ext = extensionOf(file.name || "");
|
|
@@ -11062,13 +11255,13 @@ function parseDelimited(text, delimiter) {
|
|
|
11062
11255
|
return rows;
|
|
11063
11256
|
}
|
|
11064
11257
|
function usePreview(file, kind, resolveUrl) {
|
|
11065
|
-
const [state, setState] =
|
|
11066
|
-
const [attempt, setAttempt] =
|
|
11067
|
-
const resolveRef =
|
|
11068
|
-
|
|
11258
|
+
const [state, setState] = React57.useState({ status: "loading" });
|
|
11259
|
+
const [attempt, setAttempt] = React57.useState(0);
|
|
11260
|
+
const resolveRef = React57.useRef(resolveUrl);
|
|
11261
|
+
React57.useEffect(() => {
|
|
11069
11262
|
resolveRef.current = resolveUrl;
|
|
11070
11263
|
}, [resolveUrl]);
|
|
11071
|
-
|
|
11264
|
+
React57.useEffect(() => {
|
|
11072
11265
|
if (kind === "none") {
|
|
11073
11266
|
setState({ status: "ready" });
|
|
11074
11267
|
return;
|
|
@@ -11098,19 +11291,19 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
11098
11291
|
if (ac) ac.abort();
|
|
11099
11292
|
};
|
|
11100
11293
|
}, [file.id, kind, attempt]);
|
|
11101
|
-
return { ...state, retry:
|
|
11294
|
+
return { ...state, retry: React57.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
11102
11295
|
}
|
|
11103
11296
|
function PreviewBody({ file, kind, state }) {
|
|
11104
|
-
if (kind === "image") return /* @__PURE__ */
|
|
11105
|
-
if (kind === "pdf") return /* @__PURE__ */
|
|
11106
|
-
if (kind === "markdown") return /* @__PURE__ */
|
|
11297
|
+
if (kind === "image") return /* @__PURE__ */ jsx85("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
11298
|
+
if (kind === "pdf") return /* @__PURE__ */ jsx85("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
|
|
11299
|
+
if (kind === "markdown") return /* @__PURE__ */ jsx85(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
|
|
11107
11300
|
if (kind === "json") {
|
|
11108
11301
|
let pretty = state.text || "";
|
|
11109
11302
|
try {
|
|
11110
11303
|
pretty = JSON.stringify(JSON.parse(pretty), null, 2);
|
|
11111
11304
|
} catch {
|
|
11112
11305
|
}
|
|
11113
|
-
return /* @__PURE__ */
|
|
11306
|
+
return /* @__PURE__ */ jsx85(CodeBlock, { code: pretty, language: "json" });
|
|
11114
11307
|
}
|
|
11115
11308
|
if (kind === "csv") {
|
|
11116
11309
|
const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
|
|
@@ -11118,12 +11311,12 @@ function PreviewBody({ file, kind, state }) {
|
|
|
11118
11311
|
const head = rows[0] || [];
|
|
11119
11312
|
const dataRows = rows.slice(1);
|
|
11120
11313
|
const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
|
|
11121
|
-
return /* @__PURE__ */
|
|
11122
|
-
/* @__PURE__ */
|
|
11123
|
-
/* @__PURE__ */
|
|
11124
|
-
/* @__PURE__ */
|
|
11314
|
+
return /* @__PURE__ */ jsxs79("div", { className: "fd-fv-csv", children: [
|
|
11315
|
+
/* @__PURE__ */ jsxs79("table", { className: "fd-fv-csv-table", children: [
|
|
11316
|
+
/* @__PURE__ */ jsx85("thead", { children: /* @__PURE__ */ jsx85("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx85("th", { children: c }, i)) }) }),
|
|
11317
|
+
/* @__PURE__ */ jsx85("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx85("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx85("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
|
|
11125
11318
|
] }),
|
|
11126
|
-
dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */
|
|
11319
|
+
dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs79("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
|
|
11127
11320
|
"Showing the first ",
|
|
11128
11321
|
FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
|
|
11129
11322
|
" of ",
|
|
@@ -11132,24 +11325,24 @@ function PreviewBody({ file, kind, state }) {
|
|
|
11132
11325
|
] }) : null
|
|
11133
11326
|
] });
|
|
11134
11327
|
}
|
|
11135
|
-
if (kind === "text") return /* @__PURE__ */
|
|
11136
|
-
return /* @__PURE__ */
|
|
11137
|
-
/* @__PURE__ */
|
|
11138
|
-
/* @__PURE__ */
|
|
11139
|
-
/* @__PURE__ */
|
|
11328
|
+
if (kind === "text") return /* @__PURE__ */ jsx85(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
|
|
11329
|
+
return /* @__PURE__ */ jsxs79("div", { className: "fd-fv-fallback", children: [
|
|
11330
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx85("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
|
|
11331
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
|
|
11332
|
+
/* @__PURE__ */ jsxs79("span", { className: "fd-fv-fallback-meta", children: [
|
|
11140
11333
|
file.mime || "Unknown type",
|
|
11141
11334
|
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
11142
11335
|
] })
|
|
11143
11336
|
] });
|
|
11144
11337
|
}
|
|
11145
11338
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
11146
|
-
const kind =
|
|
11339
|
+
const kind = React57.useMemo(() => previewKindOf(file), [file]);
|
|
11147
11340
|
const preview = usePreview(file, kind, resolveUrl);
|
|
11148
|
-
const [tab, setTab] =
|
|
11149
|
-
const [downloading, setDownloading] =
|
|
11150
|
-
const [downloadError, setDownloadError] =
|
|
11341
|
+
const [tab, setTab] = React57.useState("preview");
|
|
11342
|
+
const [downloading, setDownloading] = React57.useState(false);
|
|
11343
|
+
const [downloadError, setDownloadError] = React57.useState(null);
|
|
11151
11344
|
const hasSide = sidePanel != null;
|
|
11152
|
-
|
|
11345
|
+
React57.useEffect(() => {
|
|
11153
11346
|
setTab("preview");
|
|
11154
11347
|
}, [file.id]);
|
|
11155
11348
|
const download = () => {
|
|
@@ -11165,29 +11358,29 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
11165
11358
|
a.remove();
|
|
11166
11359
|
}).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
|
|
11167
11360
|
};
|
|
11168
|
-
return /* @__PURE__ */
|
|
11361
|
+
return /* @__PURE__ */ jsxs79(
|
|
11169
11362
|
"section",
|
|
11170
11363
|
{
|
|
11171
11364
|
className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
|
|
11172
11365
|
"aria-label": file.name || "File",
|
|
11173
11366
|
children: [
|
|
11174
|
-
/* @__PURE__ */
|
|
11175
|
-
/* @__PURE__ */
|
|
11176
|
-
/* @__PURE__ */
|
|
11177
|
-
/* @__PURE__ */
|
|
11178
|
-
/* @__PURE__ */
|
|
11367
|
+
/* @__PURE__ */ jsxs79("header", { className: "fd-fv-head", children: [
|
|
11368
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx85("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
|
|
11369
|
+
/* @__PURE__ */ jsxs79("span", { className: "fd-fv-head-titles", children: [
|
|
11370
|
+
/* @__PURE__ */ jsx85("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
|
|
11371
|
+
/* @__PURE__ */ jsxs79("span", { className: "fd-fv-head-meta", children: [
|
|
11179
11372
|
file.mime || "Unknown type",
|
|
11180
11373
|
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
11181
11374
|
] })
|
|
11182
11375
|
] }),
|
|
11183
|
-
/* @__PURE__ */
|
|
11376
|
+
/* @__PURE__ */ jsxs79("span", { className: "fd-fv-head-actions", children: [
|
|
11184
11377
|
actions,
|
|
11185
|
-
/* @__PURE__ */
|
|
11186
|
-
onClose ? /* @__PURE__ */
|
|
11378
|
+
/* @__PURE__ */ jsx85(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
|
|
11379
|
+
onClose ? /* @__PURE__ */ jsx85(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
|
|
11187
11380
|
] })
|
|
11188
11381
|
] }),
|
|
11189
|
-
downloadError ? /* @__PURE__ */
|
|
11190
|
-
hasSide ? /* @__PURE__ */
|
|
11382
|
+
downloadError ? /* @__PURE__ */ jsx85("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
|
|
11383
|
+
hasSide ? /* @__PURE__ */ jsx85(
|
|
11191
11384
|
Tabs,
|
|
11192
11385
|
{
|
|
11193
11386
|
className: "fd-fv-tabs",
|
|
@@ -11196,19 +11389,19 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
11196
11389
|
onChange: (v) => setTab(v)
|
|
11197
11390
|
}
|
|
11198
11391
|
) : null,
|
|
11199
|
-
/* @__PURE__ */
|
|
11200
|
-
/* @__PURE__ */
|
|
11392
|
+
/* @__PURE__ */ jsxs79("div", { className: "fd-fv-body", children: [
|
|
11393
|
+
/* @__PURE__ */ jsx85("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx85(
|
|
11201
11394
|
LoadingRegion,
|
|
11202
11395
|
{
|
|
11203
11396
|
state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
|
|
11204
11397
|
error: preview.error,
|
|
11205
11398
|
label: "Loading preview of " + (file.name || "file"),
|
|
11206
11399
|
onRetry: preview.status === "error" ? preview.retry : void 0,
|
|
11207
|
-
skeleton: /* @__PURE__ */
|
|
11208
|
-
children: /* @__PURE__ */
|
|
11400
|
+
skeleton: /* @__PURE__ */ jsx85(Skeleton, { shape: "card", h: 220 }),
|
|
11401
|
+
children: /* @__PURE__ */ jsx85(PreviewBody, { file, kind, state: preview })
|
|
11209
11402
|
}
|
|
11210
11403
|
) }),
|
|
11211
|
-
hasSide ? /* @__PURE__ */
|
|
11404
|
+
hasSide ? /* @__PURE__ */ jsx85("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
|
|
11212
11405
|
] })
|
|
11213
11406
|
]
|
|
11214
11407
|
}
|
|
@@ -11216,8 +11409,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
11216
11409
|
}
|
|
11217
11410
|
|
|
11218
11411
|
// src/components/files/FileBrowser.tsx
|
|
11219
|
-
import * as
|
|
11220
|
-
import { Fragment as
|
|
11412
|
+
import * as React58 from "react";
|
|
11413
|
+
import { Fragment as Fragment27, jsx as jsx86, jsxs as jsxs80 } from "react/jsx-runtime";
|
|
11221
11414
|
function childrenOf(folders, parentId) {
|
|
11222
11415
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
11223
11416
|
}
|
|
@@ -11287,10 +11480,10 @@ function FolderPickerMenu({
|
|
|
11287
11480
|
destinations,
|
|
11288
11481
|
onPick
|
|
11289
11482
|
}) {
|
|
11290
|
-
const [open, setOpen] =
|
|
11483
|
+
const [open, setOpen] = React58.useState(false);
|
|
11291
11484
|
const zIndex = useOverlayLayer(open);
|
|
11292
|
-
const ref =
|
|
11293
|
-
|
|
11485
|
+
const ref = React58.useRef(null);
|
|
11486
|
+
React58.useEffect(() => {
|
|
11294
11487
|
if (!open) return;
|
|
11295
11488
|
const away = (e) => {
|
|
11296
11489
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -11305,8 +11498,8 @@ function FolderPickerMenu({
|
|
|
11305
11498
|
document.removeEventListener("keydown", esc);
|
|
11306
11499
|
};
|
|
11307
11500
|
}, [open]);
|
|
11308
|
-
return /* @__PURE__ */
|
|
11309
|
-
/* @__PURE__ */
|
|
11501
|
+
return /* @__PURE__ */ jsxs80("span", { className: "fd-fb-menu-anchor", ref, children: [
|
|
11502
|
+
/* @__PURE__ */ jsx86(
|
|
11310
11503
|
IconButton,
|
|
11311
11504
|
{
|
|
11312
11505
|
icon: "arrows-out-cardinal",
|
|
@@ -11318,9 +11511,9 @@ function FolderPickerMenu({
|
|
|
11318
11511
|
onClick: () => setOpen((v) => !v)
|
|
11319
11512
|
}
|
|
11320
11513
|
),
|
|
11321
|
-
open ? /* @__PURE__ */
|
|
11322
|
-
/* @__PURE__ */
|
|
11323
|
-
destinations.map((d) => /* @__PURE__ */
|
|
11514
|
+
open ? /* @__PURE__ */ jsx86(LayerProvider, { zIndex, children: /* @__PURE__ */ jsxs80("div", { className: "fd-fb-menu", role: "menu", "aria-label": label, style: { zIndex }, children: [
|
|
11515
|
+
/* @__PURE__ */ jsx86("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
|
|
11516
|
+
destinations.map((d) => /* @__PURE__ */ jsxs80(
|
|
11324
11517
|
"button",
|
|
11325
11518
|
{
|
|
11326
11519
|
type: "button",
|
|
@@ -11332,7 +11525,7 @@ function FolderPickerMenu({
|
|
|
11332
11525
|
setOpen(false);
|
|
11333
11526
|
},
|
|
11334
11527
|
children: [
|
|
11335
|
-
/* @__PURE__ */
|
|
11528
|
+
/* @__PURE__ */ jsx86("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
|
|
11336
11529
|
d.name
|
|
11337
11530
|
]
|
|
11338
11531
|
},
|
|
@@ -11342,8 +11535,8 @@ function FolderPickerMenu({
|
|
|
11342
11535
|
] });
|
|
11343
11536
|
}
|
|
11344
11537
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
11345
|
-
const [over, setOver] =
|
|
11346
|
-
const dragCounter =
|
|
11538
|
+
const [over, setOver] = React58.useState(false);
|
|
11539
|
+
const dragCounter = React58.useRef(0);
|
|
11347
11540
|
const dropHandlers = isDropTarget ? {
|
|
11348
11541
|
onDragEnter: (e) => {
|
|
11349
11542
|
if (!hasInternalPayload(e)) return;
|
|
@@ -11368,8 +11561,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
11368
11561
|
if (payload && onDropPayload) onDropPayload(payload);
|
|
11369
11562
|
}
|
|
11370
11563
|
} : {};
|
|
11371
|
-
return /* @__PURE__ */
|
|
11372
|
-
/* @__PURE__ */
|
|
11564
|
+
return /* @__PURE__ */ jsxs80("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
|
|
11565
|
+
/* @__PURE__ */ jsxs80(
|
|
11373
11566
|
"button",
|
|
11374
11567
|
{
|
|
11375
11568
|
type: "button",
|
|
@@ -11378,26 +11571,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
11378
11571
|
draggable: !!draggableId,
|
|
11379
11572
|
onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
|
|
11380
11573
|
children: [
|
|
11381
|
-
/* @__PURE__ */
|
|
11382
|
-
/* @__PURE__ */
|
|
11383
|
-
/* @__PURE__ */
|
|
11384
|
-
meta ? /* @__PURE__ */
|
|
11574
|
+
/* @__PURE__ */ jsx86("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx86("i", { className: "ph ph-" + icon }) }),
|
|
11575
|
+
/* @__PURE__ */ jsxs80("span", { className: "fd-fb-row-text", children: [
|
|
11576
|
+
/* @__PURE__ */ jsx86("span", { className: "fd-fb-row-name", title: name, children: name }),
|
|
11577
|
+
meta ? /* @__PURE__ */ jsx86("span", { className: "fd-fb-row-meta", children: meta }) : null
|
|
11385
11578
|
] })
|
|
11386
11579
|
]
|
|
11387
11580
|
}
|
|
11388
11581
|
),
|
|
11389
|
-
actions ? /* @__PURE__ */
|
|
11582
|
+
actions ? /* @__PURE__ */ jsx86("span", { className: "fd-fb-row-actions", children: actions }) : null
|
|
11390
11583
|
] });
|
|
11391
11584
|
}
|
|
11392
11585
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
11393
11586
|
const kids = childrenOf(folders, folder.id);
|
|
11394
|
-
const [expanded, setExpanded] =
|
|
11395
|
-
|
|
11587
|
+
const [expanded, setExpanded] = React58.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
11588
|
+
React58.useEffect(() => {
|
|
11396
11589
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
11397
11590
|
}, [currentFolderId, folder.id, folders]);
|
|
11398
11591
|
const isCurrent = folder.id === currentFolderId;
|
|
11399
|
-
return /* @__PURE__ */
|
|
11400
|
-
/* @__PURE__ */
|
|
11592
|
+
return /* @__PURE__ */ jsxs80("div", { className: "fd-fb-tree-node", children: [
|
|
11593
|
+
/* @__PURE__ */ jsx86(
|
|
11401
11594
|
RowShell,
|
|
11402
11595
|
{
|
|
11403
11596
|
icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
|
|
@@ -11407,7 +11600,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
|
|
|
11407
11600
|
isDropTarget: canMove,
|
|
11408
11601
|
onDropPayload: (payload) => onMoveInto(payload, folder.id),
|
|
11409
11602
|
className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
|
|
11410
|
-
actions: kids.length ? /* @__PURE__ */
|
|
11603
|
+
actions: kids.length ? /* @__PURE__ */ jsx86(
|
|
11411
11604
|
IconButton,
|
|
11412
11605
|
{
|
|
11413
11606
|
icon: expanded ? "caret-down" : "caret-right",
|
|
@@ -11419,7 +11612,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
|
|
|
11419
11612
|
) : void 0
|
|
11420
11613
|
}
|
|
11421
11614
|
),
|
|
11422
|
-
expanded && kids.length ? /* @__PURE__ */
|
|
11615
|
+
expanded && kids.length ? /* @__PURE__ */ jsx86("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx86(
|
|
11423
11616
|
TreeNode,
|
|
11424
11617
|
{
|
|
11425
11618
|
folder: k,
|
|
@@ -11458,15 +11651,15 @@ function FileBrowser({
|
|
|
11458
11651
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
11459
11652
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
11460
11653
|
const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
|
|
11461
|
-
const [createOpen, setCreateOpen] =
|
|
11462
|
-
const [createName, setCreateName] =
|
|
11463
|
-
const [renameTarget, setRenameTarget] =
|
|
11464
|
-
const [renameValue, setRenameValue] =
|
|
11465
|
-
const [deleteTarget, setDeleteTarget] =
|
|
11466
|
-
const uploadInputRef =
|
|
11467
|
-
const crumbFolders =
|
|
11468
|
-
const subfolders =
|
|
11469
|
-
const currentFiles =
|
|
11654
|
+
const [createOpen, setCreateOpen] = React58.useState(false);
|
|
11655
|
+
const [createName, setCreateName] = React58.useState("");
|
|
11656
|
+
const [renameTarget, setRenameTarget] = React58.useState(null);
|
|
11657
|
+
const [renameValue, setRenameValue] = React58.useState("");
|
|
11658
|
+
const [deleteTarget, setDeleteTarget] = React58.useState(null);
|
|
11659
|
+
const uploadInputRef = React58.useRef(null);
|
|
11660
|
+
const crumbFolders = React58.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
11661
|
+
const subfolders = React58.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
11662
|
+
const currentFiles = React58.useMemo(
|
|
11470
11663
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
11471
11664
|
[files, currentFolderId]
|
|
11472
11665
|
);
|
|
@@ -11505,10 +11698,10 @@ function FileBrowser({
|
|
|
11505
11698
|
if (deleteTarget && onDeleteFolder) onDeleteFolder(deleteTarget);
|
|
11506
11699
|
setDeleteTarget(null);
|
|
11507
11700
|
};
|
|
11508
|
-
const content = /* @__PURE__ */
|
|
11509
|
-
/* @__PURE__ */
|
|
11510
|
-
/* @__PURE__ */
|
|
11511
|
-
/* @__PURE__ */
|
|
11701
|
+
const content = /* @__PURE__ */ jsxs80("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
|
|
11702
|
+
/* @__PURE__ */ jsxs80("div", { className: "fd-fb-head", children: [
|
|
11703
|
+
/* @__PURE__ */ jsxs80("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
|
|
11704
|
+
/* @__PURE__ */ jsx86(
|
|
11512
11705
|
BreadcrumbCrumb,
|
|
11513
11706
|
{
|
|
11514
11707
|
label: "Home",
|
|
@@ -11518,7 +11711,7 @@ function FileBrowser({
|
|
|
11518
11711
|
onDropPayload: (p) => moveIntoFolder(p, null)
|
|
11519
11712
|
}
|
|
11520
11713
|
),
|
|
11521
|
-
crumbFolders.map((f, i) => /* @__PURE__ */
|
|
11714
|
+
crumbFolders.map((f, i) => /* @__PURE__ */ jsx86(
|
|
11522
11715
|
BreadcrumbCrumb,
|
|
11523
11716
|
{
|
|
11524
11717
|
label: f.name,
|
|
@@ -11530,11 +11723,11 @@ function FileBrowser({
|
|
|
11530
11723
|
f.id
|
|
11531
11724
|
))
|
|
11532
11725
|
] }),
|
|
11533
|
-
/* @__PURE__ */
|
|
11534
|
-
canCreateFolder ? /* @__PURE__ */
|
|
11535
|
-
canUpload ? /* @__PURE__ */
|
|
11536
|
-
/* @__PURE__ */
|
|
11537
|
-
/* @__PURE__ */
|
|
11726
|
+
/* @__PURE__ */ jsxs80("span", { className: "fd-fb-actions", children: [
|
|
11727
|
+
canCreateFolder ? /* @__PURE__ */ jsx86(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
|
|
11728
|
+
canUpload ? /* @__PURE__ */ jsxs80(Fragment27, { children: [
|
|
11729
|
+
/* @__PURE__ */ jsx86(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
|
|
11730
|
+
/* @__PURE__ */ jsx86(
|
|
11538
11731
|
"input",
|
|
11539
11732
|
{
|
|
11540
11733
|
ref: uploadInputRef,
|
|
@@ -11552,9 +11745,9 @@ function FileBrowser({
|
|
|
11552
11745
|
] }) : null
|
|
11553
11746
|
] })
|
|
11554
11747
|
] }),
|
|
11555
|
-
/* @__PURE__ */
|
|
11556
|
-
/* @__PURE__ */
|
|
11557
|
-
/* @__PURE__ */
|
|
11748
|
+
/* @__PURE__ */ jsxs80("div", { className: "fd-fb-body", children: [
|
|
11749
|
+
/* @__PURE__ */ jsxs80("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
|
|
11750
|
+
/* @__PURE__ */ jsx86(
|
|
11558
11751
|
RowShell,
|
|
11559
11752
|
{
|
|
11560
11753
|
icon: "house-simple",
|
|
@@ -11565,7 +11758,7 @@ function FileBrowser({
|
|
|
11565
11758
|
className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
|
|
11566
11759
|
}
|
|
11567
11760
|
),
|
|
11568
|
-
childrenOf(folders, null).map((f) => /* @__PURE__ */
|
|
11761
|
+
childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx86(
|
|
11569
11762
|
TreeNode,
|
|
11570
11763
|
{
|
|
11571
11764
|
folder: f,
|
|
@@ -11579,18 +11772,18 @@ function FileBrowser({
|
|
|
11579
11772
|
f.id
|
|
11580
11773
|
))
|
|
11581
11774
|
] }),
|
|
11582
|
-
/* @__PURE__ */
|
|
11775
|
+
/* @__PURE__ */ jsx86("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx86(
|
|
11583
11776
|
LoadingRegion,
|
|
11584
11777
|
{
|
|
11585
11778
|
state: loading ? "loading" : "ready",
|
|
11586
11779
|
label: "Loading folder contents",
|
|
11587
|
-
skeleton: /* @__PURE__ */
|
|
11588
|
-
/* @__PURE__ */
|
|
11589
|
-
/* @__PURE__ */
|
|
11590
|
-
/* @__PURE__ */
|
|
11780
|
+
skeleton: /* @__PURE__ */ jsxs80("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
|
|
11781
|
+
/* @__PURE__ */ jsx86(Skeleton, { h: 44, radius: "10px" }),
|
|
11782
|
+
/* @__PURE__ */ jsx86(Skeleton, { h: 44, radius: "10px" }),
|
|
11783
|
+
/* @__PURE__ */ jsx86(Skeleton, { h: 44, radius: "10px" })
|
|
11591
11784
|
] }),
|
|
11592
|
-
children: isEmpty ? /* @__PURE__ */
|
|
11593
|
-
subfolders.map((f) => /* @__PURE__ */
|
|
11785
|
+
children: isEmpty ? /* @__PURE__ */ jsx86(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__ */ jsxs80("div", { className: "fd-fb-list", children: [
|
|
11786
|
+
subfolders.map((f) => /* @__PURE__ */ jsx86(
|
|
11594
11787
|
RowShell,
|
|
11595
11788
|
{
|
|
11596
11789
|
icon: "folder-simple",
|
|
@@ -11599,9 +11792,9 @@ function FileBrowser({
|
|
|
11599
11792
|
draggableId: canMove ? { kind: "folder", id: f.id } : void 0,
|
|
11600
11793
|
isDropTarget: canMove,
|
|
11601
11794
|
onDropPayload: (p) => moveIntoFolder(p, f.id),
|
|
11602
|
-
actions: /* @__PURE__ */
|
|
11603
|
-
canRenameFolder ? /* @__PURE__ */
|
|
11604
|
-
canMove ? /* @__PURE__ */
|
|
11795
|
+
actions: /* @__PURE__ */ jsxs80(Fragment27, { children: [
|
|
11796
|
+
canRenameFolder ? /* @__PURE__ */ jsx86(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
|
|
11797
|
+
canMove ? /* @__PURE__ */ jsx86(
|
|
11605
11798
|
FolderPickerMenu,
|
|
11606
11799
|
{
|
|
11607
11800
|
label: "Move " + f.name,
|
|
@@ -11609,12 +11802,12 @@ function FileBrowser({
|
|
|
11609
11802
|
onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
|
|
11610
11803
|
}
|
|
11611
11804
|
) : null,
|
|
11612
|
-
canDeleteFolder ? /* @__PURE__ */
|
|
11805
|
+
canDeleteFolder ? /* @__PURE__ */ jsx86(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
|
|
11613
11806
|
] })
|
|
11614
11807
|
},
|
|
11615
11808
|
f.id
|
|
11616
11809
|
)),
|
|
11617
|
-
currentFiles.map((file) => /* @__PURE__ */
|
|
11810
|
+
currentFiles.map((file) => /* @__PURE__ */ jsx86(
|
|
11618
11811
|
RowShell,
|
|
11619
11812
|
{
|
|
11620
11813
|
icon: iconForMime(file.mime, file.name),
|
|
@@ -11622,8 +11815,8 @@ function FileBrowser({
|
|
|
11622
11815
|
meta: file.size ? formatBytes(file.size) : void 0,
|
|
11623
11816
|
onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
|
|
11624
11817
|
draggableId: canMove ? { kind: "file", id: file.id } : void 0,
|
|
11625
|
-
actions: /* @__PURE__ */
|
|
11626
|
-
canMove ? /* @__PURE__ */
|
|
11818
|
+
actions: /* @__PURE__ */ jsxs80(Fragment27, { children: [
|
|
11819
|
+
canMove ? /* @__PURE__ */ jsx86(
|
|
11627
11820
|
FolderPickerMenu,
|
|
11628
11821
|
{
|
|
11629
11822
|
label: "Move " + file.name,
|
|
@@ -11631,7 +11824,7 @@ function FileBrowser({
|
|
|
11631
11824
|
onPick: (target) => onMoveFile && onMoveFile(file.id, target)
|
|
11632
11825
|
}
|
|
11633
11826
|
) : null,
|
|
11634
|
-
canRemoveFile ? /* @__PURE__ */
|
|
11827
|
+
canRemoveFile ? /* @__PURE__ */ jsx86(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
|
|
11635
11828
|
] })
|
|
11636
11829
|
},
|
|
11637
11830
|
file.id
|
|
@@ -11640,10 +11833,10 @@ function FileBrowser({
|
|
|
11640
11833
|
}
|
|
11641
11834
|
) })
|
|
11642
11835
|
] }),
|
|
11643
|
-
/* @__PURE__ */
|
|
11644
|
-
/* @__PURE__ */
|
|
11645
|
-
/* @__PURE__ */
|
|
11646
|
-
] }), children: /* @__PURE__ */
|
|
11836
|
+
/* @__PURE__ */ jsx86(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs80(Fragment27, { children: [
|
|
11837
|
+
/* @__PURE__ */ jsx86(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
|
|
11838
|
+
/* @__PURE__ */ jsx86(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
|
|
11839
|
+
] }), children: /* @__PURE__ */ jsx86(
|
|
11647
11840
|
"input",
|
|
11648
11841
|
{
|
|
11649
11842
|
className: "fd-fb-input",
|
|
@@ -11657,10 +11850,10 @@ function FileBrowser({
|
|
|
11657
11850
|
autoFocus: true
|
|
11658
11851
|
}
|
|
11659
11852
|
) }),
|
|
11660
|
-
/* @__PURE__ */
|
|
11661
|
-
/* @__PURE__ */
|
|
11662
|
-
/* @__PURE__ */
|
|
11663
|
-
] }), children: /* @__PURE__ */
|
|
11853
|
+
/* @__PURE__ */ jsx86(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs80(Fragment27, { children: [
|
|
11854
|
+
/* @__PURE__ */ jsx86(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
|
|
11855
|
+
/* @__PURE__ */ jsx86(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
|
|
11856
|
+
] }), children: /* @__PURE__ */ jsx86(
|
|
11664
11857
|
"input",
|
|
11665
11858
|
{
|
|
11666
11859
|
className: "fd-fb-input",
|
|
@@ -11674,22 +11867,22 @@ function FileBrowser({
|
|
|
11674
11867
|
autoFocus: true
|
|
11675
11868
|
}
|
|
11676
11869
|
) }),
|
|
11677
|
-
/* @__PURE__ */
|
|
11870
|
+
/* @__PURE__ */ jsx86(
|
|
11678
11871
|
Modal,
|
|
11679
11872
|
{
|
|
11680
11873
|
open: deleteTarget != null,
|
|
11681
11874
|
title: deleteTarget ? "Delete \u201C" + deleteTarget.name + "\u201D?" : "Delete folder?",
|
|
11682
11875
|
description: "This can't be undone. The folder must be empty.",
|
|
11683
11876
|
onClose: () => setDeleteTarget(null),
|
|
11684
|
-
footer: /* @__PURE__ */
|
|
11685
|
-
/* @__PURE__ */
|
|
11686
|
-
/* @__PURE__ */
|
|
11877
|
+
footer: /* @__PURE__ */ jsxs80(Fragment27, { children: [
|
|
11878
|
+
/* @__PURE__ */ jsx86(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
|
|
11879
|
+
/* @__PURE__ */ jsx86(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
|
|
11687
11880
|
] })
|
|
11688
11881
|
}
|
|
11689
11882
|
)
|
|
11690
11883
|
] });
|
|
11691
11884
|
if (!canUpload) return content;
|
|
11692
|
-
return /* @__PURE__ */
|
|
11885
|
+
return /* @__PURE__ */ jsx86(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
|
|
11693
11886
|
}
|
|
11694
11887
|
function BreadcrumbCrumb({
|
|
11695
11888
|
label,
|
|
@@ -11698,8 +11891,8 @@ function BreadcrumbCrumb({
|
|
|
11698
11891
|
isDropTarget,
|
|
11699
11892
|
onDropPayload
|
|
11700
11893
|
}) {
|
|
11701
|
-
const [over, setOver] =
|
|
11702
|
-
const dragCounter =
|
|
11894
|
+
const [over, setOver] = React58.useState(false);
|
|
11895
|
+
const dragCounter = React58.useRef(0);
|
|
11703
11896
|
const dropHandlers = isDropTarget ? {
|
|
11704
11897
|
onDragEnter: (e) => {
|
|
11705
11898
|
if (!hasInternalPayload(e)) return;
|
|
@@ -11724,11 +11917,11 @@ function BreadcrumbCrumb({
|
|
|
11724
11917
|
if (payload && onDropPayload) onDropPayload(payload);
|
|
11725
11918
|
}
|
|
11726
11919
|
} : {};
|
|
11727
|
-
return /* @__PURE__ */
|
|
11920
|
+
return /* @__PURE__ */ jsx86("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx86("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx86("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
|
|
11728
11921
|
}
|
|
11729
11922
|
|
|
11730
11923
|
// src/kits/query.ts
|
|
11731
|
-
import * as
|
|
11924
|
+
import * as React59 from "react";
|
|
11732
11925
|
function eqFilter(get2) {
|
|
11733
11926
|
return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
|
|
11734
11927
|
}
|
|
@@ -11760,22 +11953,22 @@ function compare(a, b, dir) {
|
|
|
11760
11953
|
var API = null;
|
|
11761
11954
|
var PREFS = null;
|
|
11762
11955
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
11763
|
-
const [query, setQuery] =
|
|
11956
|
+
const [query, setQuery] = React59.useState(() => {
|
|
11764
11957
|
const store = PREFS || window.PlannerPrefs;
|
|
11765
11958
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
11766
11959
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
11767
11960
|
});
|
|
11768
|
-
const savePref =
|
|
11961
|
+
const savePref = React59.useCallback((patch2) => {
|
|
11769
11962
|
const store = PREFS || window.PlannerPrefs;
|
|
11770
11963
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
11771
11964
|
}, [prefsKey]);
|
|
11772
|
-
const [res, setRes] =
|
|
11773
|
-
const [loading, setLoading] =
|
|
11774
|
-
const seq2 =
|
|
11965
|
+
const [res, setRes] = React59.useState(null);
|
|
11966
|
+
const [loading, setLoading] = React59.useState(true);
|
|
11967
|
+
const seq2 = React59.useRef(0);
|
|
11775
11968
|
const depKey = (deps || []).join("|");
|
|
11776
11969
|
const paramKey = JSON.stringify(params || {});
|
|
11777
11970
|
const queryKey = JSON.stringify(query);
|
|
11778
|
-
|
|
11971
|
+
React59.useEffect(() => {
|
|
11779
11972
|
const id = ++seq2.current;
|
|
11780
11973
|
setLoading(true);
|
|
11781
11974
|
const t = setTimeout(() => {
|
|
@@ -12074,12 +12267,12 @@ function createVersionStore(initialState, options) {
|
|
|
12074
12267
|
}
|
|
12075
12268
|
|
|
12076
12269
|
// src/kits/documentTitle.ts
|
|
12077
|
-
import * as
|
|
12270
|
+
import * as React60 from "react";
|
|
12078
12271
|
function formatDocumentTitle(routeTitle, appName) {
|
|
12079
12272
|
return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
|
|
12080
12273
|
}
|
|
12081
12274
|
function useDocumentTitle(routeTitle, appName) {
|
|
12082
|
-
|
|
12275
|
+
React60.useEffect(() => {
|
|
12083
12276
|
if (typeof document === "undefined") return;
|
|
12084
12277
|
document.title = formatDocumentTitle(routeTitle, appName);
|
|
12085
12278
|
}, [routeTitle, appName]);
|
|
@@ -12201,6 +12394,7 @@ export {
|
|
|
12201
12394
|
SessionKit,
|
|
12202
12395
|
SessionProvider,
|
|
12203
12396
|
SidebarNav,
|
|
12397
|
+
SignInPage,
|
|
12204
12398
|
Skeleton,
|
|
12205
12399
|
SkeletonText,
|
|
12206
12400
|
Slider,
|