@flytedan/flytebot-design-system 0.12.5 → 0.12.7
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 +324 -306
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -3
- package/dist/index.d.ts +8 -3
- package/dist/index.js +805 -788
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/styles/components.css +55 -0
package/dist/index.js
CHANGED
|
@@ -50,8 +50,13 @@ function Button({
|
|
|
50
50
|
);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
// src/components/actions/overflowRowContext.ts
|
|
54
|
+
import * as React from "react";
|
|
55
|
+
var OverflowRowContext = React.createContext(false);
|
|
56
|
+
var useOverflowRow = () => React.useContext(OverflowRowContext);
|
|
57
|
+
|
|
53
58
|
// src/components/actions/IconButton.tsx
|
|
54
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
59
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
55
60
|
function IconButton({
|
|
56
61
|
icon,
|
|
57
62
|
label,
|
|
@@ -63,21 +68,26 @@ function IconButton({
|
|
|
63
68
|
className = "",
|
|
64
69
|
...rest
|
|
65
70
|
}) {
|
|
71
|
+
const overflowRow = useOverflowRow();
|
|
66
72
|
const cls = [
|
|
67
73
|
"fd-btn-icon",
|
|
68
74
|
variant === "outline" ? "fd-btn-icon-outline" : variant === "solid" ? "fd-btn-icon-solid" : "",
|
|
69
75
|
tone !== "neutral" ? "is-" + tone : "",
|
|
70
76
|
size === "sm" ? "fd-btn-icon-sm" : size === "lg" ? "fd-btn-icon-lg" : "",
|
|
71
77
|
round ? "fd-btn-icon-round" : "",
|
|
78
|
+
overflowRow ? "fd-btn-icon-row" : "",
|
|
72
79
|
className
|
|
73
80
|
].filter(Boolean).join(" ");
|
|
74
|
-
return /* @__PURE__ */
|
|
81
|
+
return /* @__PURE__ */ jsxs2("button", { type: "button", className: cls, "aria-label": label, title: label, disabled, ...rest, children: [
|
|
82
|
+
/* @__PURE__ */ jsx2("i", { className: "ph ph-" + icon, "aria-hidden": "true" }),
|
|
83
|
+
overflowRow ? /* @__PURE__ */ jsx2("span", { className: "fd-btn-icon-row-label", children: label }) : null
|
|
84
|
+
] });
|
|
75
85
|
}
|
|
76
86
|
|
|
77
87
|
// src/components/actions/Popover.tsx
|
|
78
|
-
import * as
|
|
88
|
+
import * as React2 from "react";
|
|
79
89
|
import { createPortal } from "react-dom";
|
|
80
|
-
import { jsx as jsx3, jsxs as
|
|
90
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
81
91
|
var MARGIN = 8;
|
|
82
92
|
var parsePlacement = (p) => {
|
|
83
93
|
const [side, align = "start"] = String(p || "bottom-start").split("-");
|
|
@@ -107,12 +117,12 @@ function measureLayer(el) {
|
|
|
107
117
|
function usePopoverPosition(open, anchorRef, opts) {
|
|
108
118
|
const o = opts || {};
|
|
109
119
|
const { side: wantSide, align } = parsePlacement(o.placement);
|
|
110
|
-
const [pos, setPos] =
|
|
111
|
-
const posRef =
|
|
112
|
-
const detachRef =
|
|
120
|
+
const [pos, setPos] = React2.useState(null);
|
|
121
|
+
const posRef = React2.useRef(null);
|
|
122
|
+
const detachRef = React2.useRef(o.onDetach);
|
|
113
123
|
detachRef.current = o.onDetach;
|
|
114
124
|
const layerRef = o.layerRef;
|
|
115
|
-
|
|
125
|
+
React2.useLayoutEffect(() => {
|
|
116
126
|
if (!open || !anchorRef || !anchorRef.current) {
|
|
117
127
|
posRef.current = null;
|
|
118
128
|
setPos(null);
|
|
@@ -187,8 +197,8 @@ var portal = (node) => {
|
|
|
187
197
|
};
|
|
188
198
|
var ROOT_LAYER = 0;
|
|
189
199
|
var LAYER_STEP = 10;
|
|
190
|
-
var LayerContext =
|
|
191
|
-
var useLayer = () =>
|
|
200
|
+
var LayerContext = React2.createContext(ROOT_LAYER);
|
|
201
|
+
var useLayer = () => React2.useContext(LayerContext);
|
|
192
202
|
var useOverlayLayer = (base) => {
|
|
193
203
|
const parent = useLayer();
|
|
194
204
|
return parent === ROOT_LAYER ? base : parent + LAYER_STEP;
|
|
@@ -218,7 +228,7 @@ function Popover({
|
|
|
218
228
|
footer,
|
|
219
229
|
children
|
|
220
230
|
}) {
|
|
221
|
-
const ref =
|
|
231
|
+
const ref = React2.useRef(null);
|
|
222
232
|
const pos = usePopoverPosition(!!open, anchorRef, {
|
|
223
233
|
placement,
|
|
224
234
|
offset,
|
|
@@ -230,9 +240,9 @@ function Popover({
|
|
|
230
240
|
onDetach: onClose,
|
|
231
241
|
layerRef: ref
|
|
232
242
|
});
|
|
233
|
-
const restore =
|
|
243
|
+
const restore = React2.useRef(null);
|
|
234
244
|
const zIndex = useOverlayLayer(POPOVER_BASE);
|
|
235
|
-
|
|
245
|
+
React2.useEffect(() => {
|
|
236
246
|
if (!open) return;
|
|
237
247
|
restore.current = typeof document !== "undefined" ? document.activeElement : null;
|
|
238
248
|
return () => {
|
|
@@ -244,7 +254,7 @@ function Popover({
|
|
|
244
254
|
}
|
|
245
255
|
};
|
|
246
256
|
}, [open, returnFocus]);
|
|
247
|
-
|
|
257
|
+
React2.useEffect(() => {
|
|
248
258
|
if (!open) return;
|
|
249
259
|
const away = (e) => {
|
|
250
260
|
if (!closeOnOutside) return;
|
|
@@ -270,7 +280,7 @@ function Popover({
|
|
|
270
280
|
}, [open, closeOnOutside, closeOnEscape, onClose, anchorRef, triggerRef]);
|
|
271
281
|
if (!open || !pos) return null;
|
|
272
282
|
return portal(
|
|
273
|
-
/* @__PURE__ */ jsx3(LayerProvider, { zIndex, children: /* @__PURE__ */
|
|
283
|
+
/* @__PURE__ */ jsx3(LayerProvider, { zIndex, children: /* @__PURE__ */ jsxs3(
|
|
274
284
|
"div",
|
|
275
285
|
{
|
|
276
286
|
ref,
|
|
@@ -318,12 +328,12 @@ function Popover({
|
|
|
318
328
|
}
|
|
319
329
|
var isItem = (it) => !!it && it.kind !== "separator" && it.kind !== "section" && it.kind !== "custom" && !it.disabled;
|
|
320
330
|
function Menu({ items = [], onSelect, onClose, autoFocus = true, className = "", footer, header }) {
|
|
321
|
-
const listRef =
|
|
322
|
-
const [active, setActive] =
|
|
323
|
-
const [openSub, setOpenSub] =
|
|
324
|
-
const subAnchor =
|
|
325
|
-
const typed =
|
|
326
|
-
|
|
331
|
+
const listRef = React2.useRef(null);
|
|
332
|
+
const [active, setActive] = React2.useState(() => items.findIndex(isItem));
|
|
333
|
+
const [openSub, setOpenSub] = React2.useState(null);
|
|
334
|
+
const subAnchor = React2.useRef(null);
|
|
335
|
+
const typed = React2.useRef({ s: "", t: 0 });
|
|
336
|
+
React2.useEffect(() => {
|
|
327
337
|
if (autoFocus && listRef.current) listRef.current.focus({ preventScroll: true });
|
|
328
338
|
}, [autoFocus]);
|
|
329
339
|
const move = (dir) => {
|
|
@@ -385,8 +395,8 @@ function Menu({ items = [], onSelect, onClose, autoFocus = true, className = "",
|
|
|
385
395
|
}
|
|
386
396
|
};
|
|
387
397
|
const sub = openSub != null ? items[openSub] : null;
|
|
388
|
-
return /* @__PURE__ */
|
|
389
|
-
/* @__PURE__ */
|
|
398
|
+
return /* @__PURE__ */ jsxs3(React2.Fragment, { children: [
|
|
399
|
+
/* @__PURE__ */ jsxs3("div", { className: "fd-menu-frame", children: [
|
|
390
400
|
header != null ? /* @__PURE__ */ jsx3("div", { className: "fd-menu-header", children: header }) : null,
|
|
391
401
|
/* @__PURE__ */ jsx3(
|
|
392
402
|
"div",
|
|
@@ -402,7 +412,7 @@ function Menu({ items = [], onSelect, onClose, autoFocus = true, className = "",
|
|
|
402
412
|
if (it.kind === "section") return /* @__PURE__ */ jsx3("div", { className: "fd-pop-group", role: "presentation", children: it.label }, "h" + i);
|
|
403
413
|
if (it.kind === "custom") return /* @__PURE__ */ jsx3("div", { className: "fd-menu-custom", children: it.render ? it.render() : null }, "c" + i);
|
|
404
414
|
const on = !!it.checked;
|
|
405
|
-
const row = /* @__PURE__ */
|
|
415
|
+
const row = /* @__PURE__ */ jsxs3(
|
|
406
416
|
"button",
|
|
407
417
|
{
|
|
408
418
|
type: "button",
|
|
@@ -420,7 +430,7 @@ function Menu({ items = [], onSelect, onClose, autoFocus = true, className = "",
|
|
|
420
430
|
onClick: () => choose(it, i),
|
|
421
431
|
children: [
|
|
422
432
|
it.icon ? /* @__PURE__ */ jsx3("span", { className: "fd-menu-icon", children: /* @__PURE__ */ jsx3("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) }) : null,
|
|
423
|
-
/* @__PURE__ */
|
|
433
|
+
/* @__PURE__ */ jsxs3("span", { className: "fd-menu-text", children: [
|
|
424
434
|
/* @__PURE__ */ jsx3("span", { className: "fd-opt-label", children: it.label }),
|
|
425
435
|
it.description ? /* @__PURE__ */ jsx3("span", { className: "fd-opt-desc", children: it.description }) : null
|
|
426
436
|
] }),
|
|
@@ -434,7 +444,7 @@ function Menu({ items = [], onSelect, onClose, autoFocus = true, className = "",
|
|
|
434
444
|
);
|
|
435
445
|
const ta = it.trailingAction;
|
|
436
446
|
if (!ta) return row;
|
|
437
|
-
return /* @__PURE__ */
|
|
447
|
+
return /* @__PURE__ */ jsxs3("div", { className: "fd-menu-row", onMouseEnter: () => setActive(i), children: [
|
|
438
448
|
row,
|
|
439
449
|
/* @__PURE__ */ jsx3(
|
|
440
450
|
"button",
|
|
@@ -499,10 +509,10 @@ function MenuButton({
|
|
|
499
509
|
header,
|
|
500
510
|
footer
|
|
501
511
|
}) {
|
|
502
|
-
const [open, setOpen] =
|
|
503
|
-
const ref =
|
|
504
|
-
return /* @__PURE__ */
|
|
505
|
-
/* @__PURE__ */
|
|
512
|
+
const [open, setOpen] = React2.useState(false);
|
|
513
|
+
const ref = React2.useRef(null);
|
|
514
|
+
return /* @__PURE__ */ jsxs3(React2.Fragment, { children: [
|
|
515
|
+
/* @__PURE__ */ jsxs3(
|
|
506
516
|
"button",
|
|
507
517
|
{
|
|
508
518
|
type: "button",
|
|
@@ -559,7 +569,7 @@ function SegmentedControl({ options = [], value, onChange, className = "", ...re
|
|
|
559
569
|
}
|
|
560
570
|
|
|
561
571
|
// src/components/surfaces/Card.tsx
|
|
562
|
-
import { jsx as jsx5, jsxs as
|
|
572
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
563
573
|
function Card({
|
|
564
574
|
title,
|
|
565
575
|
action,
|
|
@@ -577,8 +587,8 @@ function Card({
|
|
|
577
587
|
hoverable ? "fd-card-hoverable" : "",
|
|
578
588
|
className
|
|
579
589
|
].filter(Boolean).join(" ");
|
|
580
|
-
return /* @__PURE__ */
|
|
581
|
-
title ? /* @__PURE__ */
|
|
590
|
+
return /* @__PURE__ */ jsxs4("div", { className: cls, ...rest, children: [
|
|
591
|
+
title ? /* @__PURE__ */ jsxs4("div", { className: "fd-card-head", children: [
|
|
582
592
|
/* @__PURE__ */ jsx5("span", { className: "fd-card-head-title", children: title }),
|
|
583
593
|
action
|
|
584
594
|
] }) : null,
|
|
@@ -587,15 +597,15 @@ function Card({
|
|
|
587
597
|
] });
|
|
588
598
|
}
|
|
589
599
|
function CardRow({ label, children, className = "" }) {
|
|
590
|
-
return /* @__PURE__ */
|
|
600
|
+
return /* @__PURE__ */ jsxs4("div", { className: ["fd-card-row", className].filter(Boolean).join(" "), children: [
|
|
591
601
|
/* @__PURE__ */ jsx5("span", { className: "fd-card-row-label", children: label }),
|
|
592
602
|
/* @__PURE__ */ jsx5("span", { className: "fd-card-row-value", children })
|
|
593
603
|
] });
|
|
594
604
|
}
|
|
595
605
|
|
|
596
606
|
// src/components/surfaces/Collapsible.tsx
|
|
597
|
-
import * as
|
|
598
|
-
import { jsx as jsx6, jsxs as
|
|
607
|
+
import * as React3 from "react";
|
|
608
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
599
609
|
function Collapsible({
|
|
600
610
|
title,
|
|
601
611
|
subtitle,
|
|
@@ -608,16 +618,16 @@ function Collapsible({
|
|
|
608
618
|
className = "",
|
|
609
619
|
...rest
|
|
610
620
|
}) {
|
|
611
|
-
const [internal, setInternal] =
|
|
621
|
+
const [internal, setInternal] = React3.useState(defaultOpen);
|
|
612
622
|
const isOpen = open === void 0 ? internal : open;
|
|
613
623
|
const toggle = () => {
|
|
614
624
|
if (open === void 0) setInternal(!isOpen);
|
|
615
625
|
if (onToggle) onToggle(!isOpen);
|
|
616
626
|
};
|
|
617
|
-
return /* @__PURE__ */
|
|
618
|
-
/* @__PURE__ */
|
|
627
|
+
return /* @__PURE__ */ jsxs5("div", { className: ["fd-coll", className].filter(Boolean).join(" "), "data-open": isOpen ? "true" : "false", ...rest, children: [
|
|
628
|
+
/* @__PURE__ */ jsxs5("button", { type: "button", className: "fd-coll-trigger", "aria-expanded": isOpen, onClick: toggle, children: [
|
|
619
629
|
icon ? /* @__PURE__ */ jsx6("span", { className: "fd-coll-caret", style: { background: "var(--brand-soft)", color: "var(--brand)", transform: "none" }, children: /* @__PURE__ */ jsx6("i", { className: "ph ph-" + icon, "aria-hidden": "true" }) }) : null,
|
|
620
|
-
/* @__PURE__ */
|
|
630
|
+
/* @__PURE__ */ jsxs5("span", { style: { flex: 1, minWidth: 0 }, children: [
|
|
621
631
|
/* @__PURE__ */ jsx6("span", { className: "fd-coll-title", style: { display: "block" }, children: title }),
|
|
622
632
|
subtitle ? /* @__PURE__ */ jsx6("span", { className: "fd-coll-sub", style: { display: "block" }, children: subtitle }) : null
|
|
623
633
|
] }),
|
|
@@ -629,19 +639,19 @@ function Collapsible({
|
|
|
629
639
|
}
|
|
630
640
|
|
|
631
641
|
// src/components/surfaces/Drawer.tsx
|
|
632
|
-
import * as
|
|
642
|
+
import * as React4 from "react";
|
|
633
643
|
import { createPortal as createPortal2 } from "react-dom";
|
|
634
|
-
import { jsx as jsx7, jsxs as
|
|
644
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
635
645
|
var DRAWER_BASE = 90;
|
|
636
646
|
function Drawer({ open = true, title, onClose, footer, children, className = "", ...rest }) {
|
|
637
647
|
const zIndex = useOverlayLayer(DRAWER_BASE);
|
|
638
|
-
const [closing, setClosing] =
|
|
639
|
-
const close =
|
|
648
|
+
const [closing, setClosing] = React4.useState(false);
|
|
649
|
+
const close = React4.useCallback(() => {
|
|
640
650
|
if (!onClose) return;
|
|
641
651
|
setClosing(true);
|
|
642
652
|
setTimeout(onClose, 210);
|
|
643
653
|
}, [onClose]);
|
|
644
|
-
|
|
654
|
+
React4.useEffect(() => {
|
|
645
655
|
if (!open || !onClose) return;
|
|
646
656
|
const h = (e) => {
|
|
647
657
|
if (e.key === "Escape") close();
|
|
@@ -651,10 +661,10 @@ function Drawer({ open = true, title, onClose, footer, children, className = "",
|
|
|
651
661
|
}, [open, onClose, close]);
|
|
652
662
|
if (!open) return null;
|
|
653
663
|
return createPortal2(
|
|
654
|
-
/* @__PURE__ */
|
|
664
|
+
/* @__PURE__ */ jsxs6(LayerProvider, { zIndex, children: [
|
|
655
665
|
/* @__PURE__ */ jsx7("div", { className: "fd-scrim" + (closing ? " is-closing" : ""), style: { display: "block", zIndex: zIndex - LAYER_STEP }, onClick: close }),
|
|
656
|
-
/* @__PURE__ */
|
|
657
|
-
/* @__PURE__ */
|
|
666
|
+
/* @__PURE__ */ jsxs6("aside", { className: ["fd-drawer", closing ? "is-closing" : "", className].filter(Boolean).join(" "), role: "dialog", "aria-modal": "true", ...rest, style: { zIndex }, children: [
|
|
667
|
+
/* @__PURE__ */ jsxs6("div", { className: "fd-card-head", style: { flex: "none" }, children: [
|
|
658
668
|
/* @__PURE__ */ jsx7("span", { className: "fd-card-head-title", children: title }),
|
|
659
669
|
onClose ? /* @__PURE__ */ jsx7("button", { type: "button", className: "fd-btn-icon", "aria-label": "Close", onClick: close, children: /* @__PURE__ */ jsx7("i", { className: "ph ph-x" }) }) : null
|
|
660
670
|
] }),
|
|
@@ -667,17 +677,17 @@ function Drawer({ open = true, title, onClose, footer, children, className = "",
|
|
|
667
677
|
}
|
|
668
678
|
|
|
669
679
|
// src/components/surfaces/Modal.tsx
|
|
670
|
-
import * as
|
|
680
|
+
import * as React5 from "react";
|
|
671
681
|
import { createPortal as createPortal3 } from "react-dom";
|
|
672
|
-
import { jsx as jsx8, jsxs as
|
|
682
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
673
683
|
function Modal({ open = true, title, description, onClose, footer, wide = false, children, className = "", ...rest }) {
|
|
674
|
-
const [closing, setClosing] =
|
|
675
|
-
const close =
|
|
684
|
+
const [closing, setClosing] = React5.useState(false);
|
|
685
|
+
const close = React5.useCallback(() => {
|
|
676
686
|
if (!onClose) return;
|
|
677
687
|
setClosing(true);
|
|
678
688
|
setTimeout(onClose, 190);
|
|
679
689
|
}, [onClose]);
|
|
680
|
-
|
|
690
|
+
React5.useEffect(() => {
|
|
681
691
|
if (!open || !onClose) return;
|
|
682
692
|
const h = (e) => {
|
|
683
693
|
if (e.key === "Escape") close();
|
|
@@ -694,7 +704,7 @@ function Modal({ open = true, title, description, onClose, footer, wide = false,
|
|
|
694
704
|
onClick: onClose ? (e) => {
|
|
695
705
|
if (e.target === e.currentTarget) close();
|
|
696
706
|
} : void 0,
|
|
697
|
-
children: /* @__PURE__ */
|
|
707
|
+
children: /* @__PURE__ */ jsxs7(
|
|
698
708
|
"div",
|
|
699
709
|
{
|
|
700
710
|
className: ["fd-modal", closing ? "is-closing" : "", wide ? "fd-modal-wide" : "", className].filter(Boolean).join(" "),
|
|
@@ -703,8 +713,8 @@ function Modal({ open = true, title, description, onClose, footer, wide = false,
|
|
|
703
713
|
"aria-label": typeof title === "string" ? title : void 0,
|
|
704
714
|
...rest,
|
|
705
715
|
children: [
|
|
706
|
-
title ? /* @__PURE__ */
|
|
707
|
-
/* @__PURE__ */
|
|
716
|
+
title ? /* @__PURE__ */ jsxs7("div", { className: "fd-modal-head", children: [
|
|
717
|
+
/* @__PURE__ */ jsxs7("span", { style: { flex: 1, minWidth: 0 }, children: [
|
|
708
718
|
/* @__PURE__ */ jsx8("span", { className: "fd-modal-title", style: { display: "block" }, children: title }),
|
|
709
719
|
description ? /* @__PURE__ */ jsx8("span", { className: "fd-body-sm fd-secondary", style: { display: "block", marginTop: 6 }, children: description }) : null
|
|
710
720
|
] }),
|
|
@@ -722,7 +732,7 @@ function Modal({ open = true, title, description, onClose, footer, wide = false,
|
|
|
722
732
|
}
|
|
723
733
|
|
|
724
734
|
// src/components/loading/LoadingRegion.tsx
|
|
725
|
-
import { jsx as jsx9, jsxs as
|
|
735
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
726
736
|
function LoadingRegion({
|
|
727
737
|
state = "ready",
|
|
728
738
|
skeleton,
|
|
@@ -734,7 +744,7 @@ function LoadingRegion({
|
|
|
734
744
|
...rest
|
|
735
745
|
}) {
|
|
736
746
|
if (state === "empty" || state === "error") {
|
|
737
|
-
return /* @__PURE__ */
|
|
747
|
+
return /* @__PURE__ */ jsxs8("div", { className: ["fd-empty", className].filter(Boolean).join(" "), ...rest, children: [
|
|
738
748
|
/* @__PURE__ */ jsx9("span", { className: "fd-empty-icon", children: /* @__PURE__ */ jsx9("i", { className: state === "error" ? "ph ph-warning" : "ph ph-tray", "aria-hidden": "true" }) }),
|
|
739
749
|
/* @__PURE__ */ jsx9("span", { className: "fd-empty-title", children: state === "error" ? "That didn't load" : "Nothing here yet" }),
|
|
740
750
|
/* @__PURE__ */ jsx9("span", { className: "fd-empty-body", children: error || "Data will appear here once it exists." }),
|
|
@@ -742,7 +752,7 @@ function LoadingRegion({
|
|
|
742
752
|
] });
|
|
743
753
|
}
|
|
744
754
|
if (state === "loading") {
|
|
745
|
-
return /* @__PURE__ */
|
|
755
|
+
return /* @__PURE__ */ jsxs8("div", { className, role: "status", "aria-busy": "true", "aria-label": label, ...rest, children: [
|
|
746
756
|
/* @__PURE__ */ jsx9("span", { className: "fd-sr", children: label }),
|
|
747
757
|
skeleton
|
|
748
758
|
] });
|
|
@@ -760,14 +770,14 @@ function LoadingRegion({
|
|
|
760
770
|
}
|
|
761
771
|
|
|
762
772
|
// src/components/loading/ProgressBar.tsx
|
|
763
|
-
import { jsx as jsx10, jsxs as
|
|
773
|
+
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
764
774
|
function ProgressBar({ value, label, showValue = false, className = "", ...rest }) {
|
|
765
775
|
const indeterminate = value === void 0 || value === null;
|
|
766
776
|
const pct = indeterminate ? 0 : Math.max(0, Math.min(100, value));
|
|
767
|
-
return /* @__PURE__ */
|
|
768
|
-
label || showValue ? /* @__PURE__ */
|
|
777
|
+
return /* @__PURE__ */ jsxs9("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 8 }, children: [
|
|
778
|
+
label || showValue ? /* @__PURE__ */ jsxs9("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
769
779
|
label ? /* @__PURE__ */ jsx10("span", { className: "fd-label-lg", children: label }) : /* @__PURE__ */ jsx10("span", {}),
|
|
770
|
-
showValue && !indeterminate ? /* @__PURE__ */
|
|
780
|
+
showValue && !indeterminate ? /* @__PURE__ */ jsxs9("span", { className: "fd-num fd-secondary", children: [
|
|
771
781
|
pct,
|
|
772
782
|
"%"
|
|
773
783
|
] }) : null
|
|
@@ -833,16 +843,16 @@ function Spinner({ size = "md", label = "Loading", className = "", style, ...res
|
|
|
833
843
|
}
|
|
834
844
|
|
|
835
845
|
// src/components/navigation/SidebarNav.tsx
|
|
836
|
-
import { jsx as jsx13, jsxs as
|
|
846
|
+
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
837
847
|
function Tip({ label, children }) {
|
|
838
848
|
return /* @__PURE__ */ jsx13("span", { title: label, style: { display: "inline-flex", flex: "none" }, children });
|
|
839
849
|
}
|
|
840
850
|
function SidebarNav({ brand, groups = [], current: current2, onNavigate, footer, open = false, className = "", ...rest }) {
|
|
841
|
-
return /* @__PURE__ */
|
|
851
|
+
return /* @__PURE__ */ jsxs10("nav", { className: ["fd-side", className].filter(Boolean).join(" "), "data-open": open ? "true" : "false", ...rest, children: [
|
|
842
852
|
brand ? /* @__PURE__ */ jsx13("div", { style: { height: "var(--topbar-h)", display: "flex", alignItems: "center", padding: "0 18px", borderBottom: "1px solid var(--border)", flex: "none", overflow: "hidden" }, children: brand }) : null,
|
|
843
|
-
/* @__PURE__ */ jsx13("div", { style: { flex: 1, overflow: "auto", padding: "4px 10px 18px" }, children: groups.map((g, gi) => /* @__PURE__ */
|
|
853
|
+
/* @__PURE__ */ jsx13("div", { style: { flex: 1, overflow: "auto", padding: "4px 10px 18px" }, children: groups.map((g, gi) => /* @__PURE__ */ jsxs10("div", { children: [
|
|
844
854
|
g.label ? /* @__PURE__ */ jsx13("div", { className: "fd-side-group", children: g.label }) : null,
|
|
845
|
-
/* @__PURE__ */ jsx13("div", { className: "fd-stack", style: { gap: 2 }, children: g.items.map((it) => /* @__PURE__ */
|
|
855
|
+
/* @__PURE__ */ jsx13("div", { className: "fd-stack", style: { gap: 2 }, children: g.items.map((it) => /* @__PURE__ */ jsxs10(
|
|
846
856
|
"button",
|
|
847
857
|
{
|
|
848
858
|
type: "button",
|
|
@@ -866,26 +876,26 @@ function SidebarNav({ brand, groups = [], current: current2, onNavigate, footer,
|
|
|
866
876
|
}
|
|
867
877
|
|
|
868
878
|
// src/components/navigation/FlytedeskBrand.tsx
|
|
869
|
-
import { jsx as jsx14, jsxs as
|
|
879
|
+
import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
870
880
|
var LOGO_SRC = "https://cdn.prod.website-files.com/69a96def413819b7db64de8c/69ac8ec2ed84b986a5fb76dc_Logo%20(dark)%202.svg";
|
|
871
881
|
function FlytedeskMark({ size = "md", className = "", ...rest }) {
|
|
872
882
|
return /* @__PURE__ */ jsx14("span", { className: ["fd-brand-mark", size !== "md" ? "fd-brand-mark-" + size : "", className].filter(Boolean).join(" "), ...rest, children: /* @__PURE__ */ jsx14("img", { src: LOGO_SRC, alt: "flytedesk" }) });
|
|
873
883
|
}
|
|
874
884
|
function FlytedeskBrand({ appName, size = "md", className = "", ...rest }) {
|
|
875
|
-
return /* @__PURE__ */
|
|
885
|
+
return /* @__PURE__ */ jsxs11("span", { className: ["fd-brand", size !== "md" ? "fd-brand-" + size : "", className].filter(Boolean).join(" "), ...rest, children: [
|
|
876
886
|
/* @__PURE__ */ jsx14(FlytedeskMark, { size }),
|
|
877
887
|
/* @__PURE__ */ jsx14("span", { className: "fd-overline fd-muted", children: appName })
|
|
878
888
|
] });
|
|
879
889
|
}
|
|
880
890
|
|
|
881
891
|
// src/components/navigation/Tabs.tsx
|
|
882
|
-
import { jsx as jsx15, jsxs as
|
|
892
|
+
import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
883
893
|
function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
|
|
884
894
|
return /* @__PURE__ */ jsx15("div", { className: ["fd-tabs", className].filter(Boolean).join(" "), role: "tablist", ...rest, children: tabs.map((t) => {
|
|
885
895
|
const v = typeof t === "string" ? t : t.value;
|
|
886
896
|
const label = typeof t === "string" ? t : t.label;
|
|
887
897
|
const count = typeof t === "string" ? void 0 : t.count;
|
|
888
|
-
return /* @__PURE__ */
|
|
898
|
+
return /* @__PURE__ */ jsxs12(
|
|
889
899
|
"button",
|
|
890
900
|
{
|
|
891
901
|
type: "button",
|
|
@@ -904,13 +914,13 @@ function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
|
|
|
904
914
|
}
|
|
905
915
|
|
|
906
916
|
// src/components/navigation/Topbar.tsx
|
|
907
|
-
import * as
|
|
908
|
-
import { Fragment as Fragment3, jsx as jsx16, jsxs as
|
|
917
|
+
import * as React6 from "react";
|
|
918
|
+
import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
909
919
|
function useIsNarrow(breakpoint) {
|
|
910
|
-
const [narrow, setNarrow] =
|
|
920
|
+
const [narrow, setNarrow] = React6.useState(
|
|
911
921
|
() => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
|
|
912
922
|
);
|
|
913
|
-
|
|
923
|
+
React6.useEffect(() => {
|
|
914
924
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
915
925
|
const mq = window.matchMedia(`(max-width: ${breakpoint}px)`);
|
|
916
926
|
const apply = () => setNarrow(mq.matches);
|
|
@@ -931,11 +941,11 @@ function Topbar({
|
|
|
931
941
|
...rest
|
|
932
942
|
}) {
|
|
933
943
|
const narrow = useIsNarrow(overflowBreakpoint);
|
|
934
|
-
const [moreOpen, setMoreOpen] =
|
|
935
|
-
const moreRef =
|
|
936
|
-
return /* @__PURE__ */
|
|
944
|
+
const [moreOpen, setMoreOpen] = React6.useState(false);
|
|
945
|
+
const moreRef = React6.useRef(null);
|
|
946
|
+
return /* @__PURE__ */ jsxs13("header", { className: ["fd-topbar", narrow ? "is-narrow" : "", className].filter(Boolean).join(" "), ...rest, children: [
|
|
937
947
|
onMenu ? /* @__PURE__ */ jsx16("button", { type: "button", className: "fd-btn-icon", "aria-label": "Menu", onClick: onMenu, children: /* @__PURE__ */ jsx16("i", { className: "ph ph-list" }) }) : null,
|
|
938
|
-
/* @__PURE__ */ jsx16("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */
|
|
948
|
+
/* @__PURE__ */ jsx16("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ jsxs13(React6.Fragment, { children: [
|
|
939
949
|
i > 0 ? /* @__PURE__ */ jsx16("i", { className: "ph ph-caret-right", style: { fontSize: 11, opacity: 0.6 }, "aria-hidden": "true" }) : null,
|
|
940
950
|
i === crumbs.length - 1 ? /* @__PURE__ */ jsx16("span", { className: "fd-crumb-current", children: c.label }) : /* @__PURE__ */ jsx16(
|
|
941
951
|
"a",
|
|
@@ -950,7 +960,7 @@ function Topbar({
|
|
|
950
960
|
)
|
|
951
961
|
] }, i)) }),
|
|
952
962
|
/* @__PURE__ */ jsx16("span", { style: { flex: 1 } }),
|
|
953
|
-
overflowActions != null ? narrow ? /* @__PURE__ */
|
|
963
|
+
overflowActions != null ? narrow ? /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
954
964
|
/* @__PURE__ */ jsx16(
|
|
955
965
|
"button",
|
|
956
966
|
{
|
|
@@ -974,7 +984,7 @@ function Topbar({
|
|
|
974
984
|
padded: true,
|
|
975
985
|
label: "More actions",
|
|
976
986
|
className: "fd-topbar-overflow",
|
|
977
|
-
children: /* @__PURE__ */ jsx16("div", { className: "fd-stack fd-topbar-overflow-list", children: overflowActions })
|
|
987
|
+
children: /* @__PURE__ */ jsx16("div", { className: "fd-stack fd-topbar-overflow-list", children: /* @__PURE__ */ jsx16(OverflowRowContext.Provider, { value: true, children: overflowActions }) })
|
|
978
988
|
}
|
|
979
989
|
)
|
|
980
990
|
] }) : overflowActions : null,
|
|
@@ -984,7 +994,7 @@ function Topbar({
|
|
|
984
994
|
}
|
|
985
995
|
|
|
986
996
|
// src/components/feedback/Avatar.tsx
|
|
987
|
-
import { jsx as jsx17, jsxs as
|
|
997
|
+
import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
988
998
|
function Avatar({ name = "", src, size = "md", className = "", ...rest }) {
|
|
989
999
|
const initials = name.split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0]).join("").toUpperCase();
|
|
990
1000
|
return /* @__PURE__ */ jsx17(
|
|
@@ -1000,17 +1010,17 @@ function Avatar({ name = "", src, size = "md", className = "", ...rest }) {
|
|
|
1000
1010
|
function AvatarStack({ people = [], size = "sm", max = 4, className = "" }) {
|
|
1001
1011
|
const shown = people.slice(0, max);
|
|
1002
1012
|
const rest = people.length - shown.length;
|
|
1003
|
-
return /* @__PURE__ */
|
|
1013
|
+
return /* @__PURE__ */ jsxs14("span", { className: ["fd-avatar-stack", className].filter(Boolean).join(" "), children: [
|
|
1004
1014
|
shown.map((p, i) => /* @__PURE__ */ jsx17(Avatar, { name: typeof p === "string" ? p : p.name, src: typeof p === "string" ? void 0 : p.src, size }, i)),
|
|
1005
1015
|
rest > 0 ? /* @__PURE__ */ jsx17(Avatar, { name: "+" + rest, size }) : null
|
|
1006
1016
|
] });
|
|
1007
1017
|
}
|
|
1008
1018
|
|
|
1009
1019
|
// src/components/feedback/Badge.tsx
|
|
1010
|
-
import { jsx as jsx18, jsxs as
|
|
1020
|
+
import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1011
1021
|
var TONES = { neutral: "fd-badge-neutral", info: "fd-badge-info", success: "fd-badge-success", warning: "fd-badge-warning", danger: "fd-badge-danger", live: "fd-badge-live", approved: "fd-badge-approved", count: "fd-badge-count" };
|
|
1012
1022
|
function Badge({ children, tone = "neutral", dot = false, icon, className = "", ...rest }) {
|
|
1013
|
-
return /* @__PURE__ */
|
|
1023
|
+
return /* @__PURE__ */ jsxs15("span", { className: ["fd-badge", TONES[tone] || TONES.neutral, className].filter(Boolean).join(" "), ...rest, children: [
|
|
1014
1024
|
dot ? /* @__PURE__ */ jsx18("span", { className: "fd-badge-dot", "aria-hidden": "true" }) : null,
|
|
1015
1025
|
icon ? /* @__PURE__ */ jsx18("i", { className: "ph ph-" + icon, "aria-hidden": "true" }) : null,
|
|
1016
1026
|
children
|
|
@@ -1018,9 +1028,9 @@ function Badge({ children, tone = "neutral", dot = false, icon, className = "",
|
|
|
1018
1028
|
}
|
|
1019
1029
|
|
|
1020
1030
|
// src/components/feedback/EmptyState.tsx
|
|
1021
|
-
import { jsx as jsx19, jsxs as
|
|
1031
|
+
import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1022
1032
|
function EmptyState({ icon = "tray", title, children, action, className = "", ...rest }) {
|
|
1023
|
-
return /* @__PURE__ */
|
|
1033
|
+
return /* @__PURE__ */ jsxs16("div", { className: ["fd-empty", className].filter(Boolean).join(" "), ...rest, children: [
|
|
1024
1034
|
/* @__PURE__ */ jsx19("span", { className: "fd-empty-icon", children: /* @__PURE__ */ jsx19("i", { className: "ph ph-" + icon, "aria-hidden": "true" }) }),
|
|
1025
1035
|
/* @__PURE__ */ jsx19("span", { className: "fd-empty-title", children: title }),
|
|
1026
1036
|
children ? /* @__PURE__ */ jsx19("span", { className: "fd-empty-body", children }) : null,
|
|
@@ -1029,12 +1039,12 @@ function EmptyState({ icon = "tray", title, children, action, className = "", ..
|
|
|
1029
1039
|
}
|
|
1030
1040
|
|
|
1031
1041
|
// src/components/feedback/Flag.tsx
|
|
1032
|
-
import { Fragment as Fragment4, jsx as jsx20, jsxs as
|
|
1042
|
+
import { Fragment as Fragment4, jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1033
1043
|
function Flag({ statement, cost, actions, tone = "warning", className = "", ...rest }) {
|
|
1034
|
-
return /* @__PURE__ */
|
|
1035
|
-
/* @__PURE__ */
|
|
1044
|
+
return /* @__PURE__ */ jsxs17("div", { className: ["fd-flag", "fd-flag-" + tone, className].filter(Boolean).join(" "), role: "status", ...rest, children: [
|
|
1045
|
+
/* @__PURE__ */ jsxs17("span", { className: "fd-flag-text", children: [
|
|
1036
1046
|
statement,
|
|
1037
|
-
cost ? /* @__PURE__ */
|
|
1047
|
+
cost ? /* @__PURE__ */ jsxs17(Fragment4, { children: [
|
|
1038
1048
|
" ",
|
|
1039
1049
|
/* @__PURE__ */ jsx20("span", { className: "fd-flag-cost", children: cost })
|
|
1040
1050
|
] }) : null
|
|
@@ -1086,10 +1096,10 @@ function hasModifier(e) {
|
|
|
1086
1096
|
}
|
|
1087
1097
|
|
|
1088
1098
|
// src/components/feedback/Tag.tsx
|
|
1089
|
-
import { jsx as jsx22, jsxs as
|
|
1099
|
+
import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1090
1100
|
var TONES2 = { info: "fd-tag-info", success: "fd-tag-success", warning: "fd-tag-warning", danger: "fd-tag-danger" };
|
|
1091
1101
|
function Tag({ children, icon, selected = false, tone = "neutral", onRemove, onClick, className = "", ...rest }) {
|
|
1092
|
-
return /* @__PURE__ */
|
|
1102
|
+
return /* @__PURE__ */ jsxs18(
|
|
1093
1103
|
"button",
|
|
1094
1104
|
{
|
|
1095
1105
|
type: "button",
|
|
@@ -1119,7 +1129,7 @@ function Tag({ children, icon, selected = false, tone = "neutral", onRemove, onC
|
|
|
1119
1129
|
}
|
|
1120
1130
|
|
|
1121
1131
|
// src/components/feedback/Toast.tsx
|
|
1122
|
-
import { jsx as jsx23, jsxs as
|
|
1132
|
+
import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1123
1133
|
var ICON = {
|
|
1124
1134
|
success: { i: "check", bg: "var(--ok-solid)" },
|
|
1125
1135
|
error: { i: "x", bg: "var(--danger-solid)" },
|
|
@@ -1128,9 +1138,9 @@ var ICON = {
|
|
|
1128
1138
|
};
|
|
1129
1139
|
function Toast({ title, children, tone = "success", onUndo, onDismiss, className = "", ...rest }) {
|
|
1130
1140
|
const ic = ICON[tone] || ICON.info;
|
|
1131
|
-
return /* @__PURE__ */
|
|
1141
|
+
return /* @__PURE__ */ jsxs19("div", { className: ["fd-toast", className].filter(Boolean).join(" "), role: "status", ...rest, children: [
|
|
1132
1142
|
/* @__PURE__ */ jsx23("span", { className: "fd-toast-icon", style: { background: ic.bg }, "aria-hidden": "true", children: tone === "loading" ? /* @__PURE__ */ jsx23("span", { className: "fd-spinner", style: { width: 12, height: 12, borderWidth: 2, color: "#fff" } }) : /* @__PURE__ */ jsx23("i", { className: "ph ph-" + ic.i }) }),
|
|
1133
|
-
/* @__PURE__ */
|
|
1143
|
+
/* @__PURE__ */ jsxs19("span", { className: "fd-toast-body", children: [
|
|
1134
1144
|
/* @__PURE__ */ jsx23("span", { className: "fd-toast-title", style: { display: "block" }, children: title }),
|
|
1135
1145
|
children ? /* @__PURE__ */ jsx23("span", { className: "fd-secondary", style: { display: "block", marginTop: 2 }, children }) : null,
|
|
1136
1146
|
onUndo ? /* @__PURE__ */ jsx23("button", { type: "button", className: "fd-btn fd-btn-link", style: { marginTop: 8 }, onClick: onUndo, children: "Undo" }) : null
|
|
@@ -1140,19 +1150,19 @@ function Toast({ title, children, tone = "success", onUndo, onDismiss, className
|
|
|
1140
1150
|
}
|
|
1141
1151
|
|
|
1142
1152
|
// src/components/feedback/Tooltip.tsx
|
|
1143
|
-
import * as
|
|
1144
|
-
import { jsx as jsx24, jsxs as
|
|
1153
|
+
import * as React7 from "react";
|
|
1154
|
+
import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1145
1155
|
var TOOLTIP_BASE = 150;
|
|
1146
1156
|
var CLOSE_DELAY_MS = 120;
|
|
1147
1157
|
function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
1148
|
-
const anchorRef =
|
|
1149
|
-
const bubbleRef =
|
|
1150
|
-
const [reason, setReason] =
|
|
1151
|
-
const closeTimer =
|
|
1152
|
-
const id =
|
|
1158
|
+
const anchorRef = React7.useRef(null);
|
|
1159
|
+
const bubbleRef = React7.useRef(null);
|
|
1160
|
+
const [reason, setReason] = React7.useState(null);
|
|
1161
|
+
const closeTimer = React7.useRef(null);
|
|
1162
|
+
const id = React7.useId();
|
|
1153
1163
|
const descId = id + "-desc";
|
|
1154
1164
|
const open = reason != null;
|
|
1155
|
-
const cancelClose =
|
|
1165
|
+
const cancelClose = React7.useCallback(() => {
|
|
1156
1166
|
if (closeTimer.current) {
|
|
1157
1167
|
clearTimeout(closeTimer.current);
|
|
1158
1168
|
closeTimer.current = null;
|
|
@@ -1162,7 +1172,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1162
1172
|
cancelClose();
|
|
1163
1173
|
setReason(why);
|
|
1164
1174
|
};
|
|
1165
|
-
const hide =
|
|
1175
|
+
const hide = React7.useCallback(() => {
|
|
1166
1176
|
cancelClose();
|
|
1167
1177
|
setReason(null);
|
|
1168
1178
|
}, [cancelClose]);
|
|
@@ -1177,7 +1187,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1177
1187
|
setReason((r) => r === "hover" ? null : r);
|
|
1178
1188
|
}, CLOSE_DELAY_MS);
|
|
1179
1189
|
};
|
|
1180
|
-
|
|
1190
|
+
React7.useEffect(() => cancelClose, [cancelClose]);
|
|
1181
1191
|
const pos = usePopoverPosition(open, anchorRef, {
|
|
1182
1192
|
placement: placement === "bottom" ? "bottom-center" : "top-center",
|
|
1183
1193
|
offset: 8,
|
|
@@ -1187,7 +1197,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1187
1197
|
onDetach: hide
|
|
1188
1198
|
});
|
|
1189
1199
|
const zIndex = useOverlayLayer(TOOLTIP_BASE);
|
|
1190
|
-
|
|
1200
|
+
React7.useEffect(() => {
|
|
1191
1201
|
if (!open) return;
|
|
1192
1202
|
const key = (e) => {
|
|
1193
1203
|
if (e.key === "Escape") hide();
|
|
@@ -1215,15 +1225,15 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1215
1225
|
}
|
|
1216
1226
|
if (keyboard) show("focus");
|
|
1217
1227
|
};
|
|
1218
|
-
const described =
|
|
1228
|
+
const described = React7.isValidElement(children) ? React7.cloneElement(children, {
|
|
1219
1229
|
"aria-describedby": [children.props["aria-describedby"], descId].filter(Boolean).join(" ")
|
|
1220
1230
|
}) : children;
|
|
1221
|
-
return /* @__PURE__ */
|
|
1231
|
+
return /* @__PURE__ */ jsxs20(
|
|
1222
1232
|
"span",
|
|
1223
1233
|
{
|
|
1224
1234
|
ref: anchorRef,
|
|
1225
1235
|
className: "fd-tooltip-anchor",
|
|
1226
|
-
"aria-describedby":
|
|
1236
|
+
"aria-describedby": React7.isValidElement(children) ? void 0 : descId,
|
|
1227
1237
|
onPointerEnter: (e) => {
|
|
1228
1238
|
if (isMouse(e)) hover();
|
|
1229
1239
|
},
|
|
@@ -1267,8 +1277,8 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
|
1267
1277
|
}
|
|
1268
1278
|
|
|
1269
1279
|
// src/components/data/Clamp.tsx
|
|
1270
|
-
import * as
|
|
1271
|
-
import { jsx as jsx25, jsxs as
|
|
1280
|
+
import * as React8 from "react";
|
|
1281
|
+
import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1272
1282
|
function Clamp({
|
|
1273
1283
|
children,
|
|
1274
1284
|
text,
|
|
@@ -1279,16 +1289,16 @@ function Clamp({
|
|
|
1279
1289
|
onToggle,
|
|
1280
1290
|
className = ""
|
|
1281
1291
|
}) {
|
|
1282
|
-
const [open, setOpen] =
|
|
1283
|
-
const [overflows, setOverflows] =
|
|
1284
|
-
const bodyRef =
|
|
1285
|
-
const charClamped =
|
|
1292
|
+
const [open, setOpen] = React8.useState(false);
|
|
1293
|
+
const [overflows, setOverflows] = React8.useState(false);
|
|
1294
|
+
const bodyRef = React8.useRef(null);
|
|
1295
|
+
const charClamped = React8.useMemo(() => {
|
|
1286
1296
|
if (open || !maxChars || typeof text !== "string" || text.length <= maxChars) return null;
|
|
1287
1297
|
const cut = text.slice(0, maxChars);
|
|
1288
1298
|
const at = cut.lastIndexOf(" ");
|
|
1289
1299
|
return (at > maxChars * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
1290
1300
|
}, [text, maxChars, open]);
|
|
1291
|
-
|
|
1301
|
+
React8.useLayoutEffect(() => {
|
|
1292
1302
|
const node = bodyRef.current;
|
|
1293
1303
|
if (maxChars || !node || !maxHeight) return;
|
|
1294
1304
|
const measure = () => {
|
|
@@ -1309,9 +1319,9 @@ function Clamp({
|
|
|
1309
1319
|
return !v;
|
|
1310
1320
|
});
|
|
1311
1321
|
};
|
|
1312
|
-
return /* @__PURE__ */
|
|
1322
|
+
return /* @__PURE__ */ jsxs21("div", { className: ["fd-clamp", clamped ? "is-clamped" : "", className].filter(Boolean).join(" "), children: [
|
|
1313
1323
|
/* @__PURE__ */ jsx25("div", { className: "fd-clamp-body", ref: bodyRef, style: !maxChars && clamped ? { maxHeight } : void 0, children: maxChars ? charClamped != null ? charClamped : text != null ? text : children : children }),
|
|
1314
|
-
(maxChars ? charClamped != null || open : overflows) ? /* @__PURE__ */
|
|
1324
|
+
(maxChars ? charClamped != null || open : overflows) ? /* @__PURE__ */ jsxs21("button", { type: "button", className: "fd-clamp-more", onClick: toggle, "aria-expanded": open, children: [
|
|
1315
1325
|
/* @__PURE__ */ jsx25("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" }),
|
|
1316
1326
|
open ? lessLabel : moreLabel
|
|
1317
1327
|
] }) : null
|
|
@@ -1319,7 +1329,7 @@ function Clamp({
|
|
|
1319
1329
|
}
|
|
1320
1330
|
|
|
1321
1331
|
// src/components/data/CsiBadge.tsx
|
|
1322
|
-
import { jsx as jsx26, jsxs as
|
|
1332
|
+
import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1323
1333
|
var BANDS = {
|
|
1324
1334
|
weak: { n: 1, label: "Weak" },
|
|
1325
1335
|
adequate: { n: 2, label: "Adequate" },
|
|
@@ -1342,7 +1352,7 @@ function CsiMeter({ band = "weak", size = 4, width = 5, gap = 2 }) {
|
|
|
1342
1352
|
}
|
|
1343
1353
|
function CsiBadge({ band = "weak", crp, size = "compact", preview = false, alert = false, className = "", ...rest }) {
|
|
1344
1354
|
const b = BANDS[band] || BANDS.weak;
|
|
1345
|
-
return /* @__PURE__ */
|
|
1355
|
+
return /* @__PURE__ */ jsxs22(
|
|
1346
1356
|
"span",
|
|
1347
1357
|
{
|
|
1348
1358
|
className: ["fd-csi", "fd-csi-" + b.n, size === "medium" ? "fd-csi-medium" : "fd-csi-compact", preview ? "fd-csi-preview" : "", className].filter(Boolean).join(" "),
|
|
@@ -1359,7 +1369,7 @@ function CsiBadge({ band = "weak", crp, size = "compact", preview = false, alert
|
|
|
1359
1369
|
function CsiHero({ band = "weak", crp, label, className = "" }) {
|
|
1360
1370
|
const b = BANDS[band] || BANDS.weak;
|
|
1361
1371
|
const mark = "var(--csi-" + b.n + "-mark)";
|
|
1362
|
-
return /* @__PURE__ */
|
|
1372
|
+
return /* @__PURE__ */ jsxs22("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 10 }, children: [
|
|
1363
1373
|
/* @__PURE__ */ jsx26("span", { className: "fd-csi-hero-num", style: { color: mark }, children: crp !== void 0 && crp !== null ? formatCrp(crp) : "" }),
|
|
1364
1374
|
/* @__PURE__ */ jsx26("span", { className: "fd-label-lg", style: { color: "var(--text-2)" }, children: label || b.label }),
|
|
1365
1375
|
/* @__PURE__ */ jsx26("span", { className: "fd-meter", style: { gap: 3, color: mark, width: 120 }, children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx26("span", { className: "fd-meter-seg" + (i <= b.n ? " is-on" : ""), style: { height: 6, flex: 1 } }, i)) })
|
|
@@ -1367,7 +1377,7 @@ function CsiHero({ band = "weak", crp, label, className = "" }) {
|
|
|
1367
1377
|
}
|
|
1368
1378
|
|
|
1369
1379
|
// src/components/data/DataTable.tsx
|
|
1370
|
-
import { jsx as jsx27, jsxs as
|
|
1380
|
+
import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1371
1381
|
function DataTable({
|
|
1372
1382
|
columns = [],
|
|
1373
1383
|
rows = [],
|
|
@@ -1384,14 +1394,14 @@ function DataTable({
|
|
|
1384
1394
|
...rest
|
|
1385
1395
|
}) {
|
|
1386
1396
|
const stale = refreshing && !loading;
|
|
1387
|
-
return /* @__PURE__ */
|
|
1397
|
+
return /* @__PURE__ */ jsxs23("div", { className: "fd-table-host", children: [
|
|
1388
1398
|
/* @__PURE__ */ jsx27(
|
|
1389
1399
|
"div",
|
|
1390
1400
|
{
|
|
1391
1401
|
className: ["fd-table-wrap", className].filter(Boolean).join(" "),
|
|
1392
1402
|
"aria-busy": loading || refreshing ? "true" : void 0,
|
|
1393
1403
|
...rest,
|
|
1394
|
-
children: /* @__PURE__ */
|
|
1404
|
+
children: /* @__PURE__ */ jsxs23("table", { className: ["fd-table", compact3 ? "fd-table-compact" : ""].filter(Boolean).join(" "), children: [
|
|
1395
1405
|
/* @__PURE__ */ jsx27("thead", { children: /* @__PURE__ */ jsx27("tr", { children: columns.map((c) => /* @__PURE__ */ jsx27(
|
|
1396
1406
|
"th",
|
|
1397
1407
|
{
|
|
@@ -1399,7 +1409,7 @@ function DataTable({
|
|
|
1399
1409
|
style: { width: c.width },
|
|
1400
1410
|
className: [c.numeric ? "is-num" : "", sort && sort.key === c.key ? "is-sorted" : ""].filter(Boolean).join(" "),
|
|
1401
1411
|
"aria-sort": sort && sort.key === c.key ? sort.dir === "asc" ? "ascending" : "descending" : void 0,
|
|
1402
|
-
children: c.sortable && onSort ? /* @__PURE__ */
|
|
1412
|
+
children: c.sortable && onSort ? /* @__PURE__ */ jsxs23("button", { type: "button", onClick: () => onSort(c.key), children: [
|
|
1403
1413
|
c.label,
|
|
1404
1414
|
sort && sort.key === c.key ? /* @__PURE__ */ jsx27("i", { className: "ph fd-caret ph-caret-" + (sort.dir === "asc" ? "up" : "down") }) : null
|
|
1405
1415
|
] }) : c.label
|
|
@@ -1419,7 +1429,7 @@ function DataTable({
|
|
|
1419
1429
|
] })
|
|
1420
1430
|
}
|
|
1421
1431
|
),
|
|
1422
|
-
stale ? /* @__PURE__ */ jsx27("div", { className: "fd-table-stale", children: /* @__PURE__ */
|
|
1432
|
+
stale ? /* @__PURE__ */ jsx27("div", { className: "fd-table-stale", children: /* @__PURE__ */ jsxs23("span", { className: "fd-table-stale-pill", role: "status", children: [
|
|
1423
1433
|
/* @__PURE__ */ jsx27("span", { className: "fd-spinner", "aria-hidden": "true" }),
|
|
1424
1434
|
" Updating\u2026"
|
|
1425
1435
|
] }) }) : null
|
|
@@ -1427,19 +1437,19 @@ function DataTable({
|
|
|
1427
1437
|
}
|
|
1428
1438
|
|
|
1429
1439
|
// src/components/data/FilterBar.tsx
|
|
1430
|
-
import * as
|
|
1431
|
-
import { jsx as jsx28, jsxs as
|
|
1440
|
+
import * as React9 from "react";
|
|
1441
|
+
import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1432
1442
|
var FILTER_BAR_BASE = 120;
|
|
1433
1443
|
var isSet = (v) => !(v == null || v === "" || v === false);
|
|
1434
1444
|
function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align = "left", className = "", ...rest }) {
|
|
1435
|
-
const [panel, setPanel] =
|
|
1445
|
+
const [panel, setPanel] = React9.useState(null);
|
|
1436
1446
|
const zIndex = useOverlayLayer(FILTER_BAR_BASE);
|
|
1437
|
-
const rootRef =
|
|
1438
|
-
const textInputRef =
|
|
1439
|
-
const optionsRef =
|
|
1447
|
+
const rootRef = React9.useRef(null);
|
|
1448
|
+
const textInputRef = React9.useRef(null);
|
|
1449
|
+
const optionsRef = React9.useRef(null);
|
|
1440
1450
|
const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
|
|
1441
1451
|
const dismissible = !!panel && (panel.kind === "add" || panel.kind === "edit" && editingField?.type === "select");
|
|
1442
|
-
|
|
1452
|
+
React9.useEffect(() => {
|
|
1443
1453
|
if (!dismissible) return;
|
|
1444
1454
|
const away = (e) => {
|
|
1445
1455
|
if (rootRef.current && !rootRef.current.contains(e.target)) setPanel(null);
|
|
@@ -1454,7 +1464,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
1454
1464
|
document.removeEventListener("keydown", esc);
|
|
1455
1465
|
};
|
|
1456
1466
|
}, [dismissible]);
|
|
1457
|
-
|
|
1467
|
+
React9.useEffect(() => {
|
|
1458
1468
|
if (!panel || panel.kind !== "edit") return;
|
|
1459
1469
|
if (editingField?.type === "text") {
|
|
1460
1470
|
textInputRef.current?.focus();
|
|
@@ -1465,12 +1475,12 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
1465
1475
|
}, [panel]);
|
|
1466
1476
|
const addableFields = fields.filter((f) => !isSet(filters[f.key]));
|
|
1467
1477
|
const startEditing = (key) => setPanel({ kind: "edit", key });
|
|
1468
|
-
return /* @__PURE__ */
|
|
1478
|
+
return /* @__PURE__ */ jsxs24("span", { className, style: { position: "relative", display: "inline-flex", flexWrap: "wrap", alignItems: "center", gap: 8 }, ref: rootRef, ...rest, children: [
|
|
1469
1479
|
fields.map((field) => {
|
|
1470
1480
|
const value = filters[field.key];
|
|
1471
1481
|
const editing = panel?.kind === "edit" && panel.key === field.key;
|
|
1472
1482
|
if (editing && field.type === "text") {
|
|
1473
|
-
return /* @__PURE__ */
|
|
1483
|
+
return /* @__PURE__ */ jsxs24(
|
|
1474
1484
|
"span",
|
|
1475
1485
|
{
|
|
1476
1486
|
className: "fd-tag",
|
|
@@ -1516,8 +1526,8 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
1516
1526
|
}
|
|
1517
1527
|
if (editing && field.type === "select") {
|
|
1518
1528
|
const chosen = field.options.find((o) => o.value === value);
|
|
1519
|
-
return /* @__PURE__ */
|
|
1520
|
-
/* @__PURE__ */
|
|
1529
|
+
return /* @__PURE__ */ jsxs24("span", { style: { position: "relative", display: "inline-flex" }, children: [
|
|
1530
|
+
/* @__PURE__ */ jsxs24(Tag, { selected: true, onClick: () => setPanel(null), onRemove: () => {
|
|
1521
1531
|
if (isSet(value)) onFilterRemove(field.key);
|
|
1522
1532
|
setPanel(null);
|
|
1523
1533
|
}, children: [
|
|
@@ -1555,7 +1565,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
1555
1565
|
if (isSet(value)) {
|
|
1556
1566
|
const chosen = field.type === "select" ? field.options.find((o) => o.value === value) : void 0;
|
|
1557
1567
|
const display = chosen ? chosen.label : String(value);
|
|
1558
|
-
return /* @__PURE__ */
|
|
1568
|
+
return /* @__PURE__ */ jsxs24(Tag, { selected: true, onClick: () => startEditing(field.key), onRemove: () => onFilterRemove(field.key), children: [
|
|
1559
1569
|
field.label,
|
|
1560
1570
|
": ",
|
|
1561
1571
|
display
|
|
@@ -1563,7 +1573,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
1563
1573
|
}
|
|
1564
1574
|
return null;
|
|
1565
1575
|
}),
|
|
1566
|
-
addableFields.length > 0 ? /* @__PURE__ */
|
|
1576
|
+
addableFields.length > 0 ? /* @__PURE__ */ jsxs24("span", { style: { position: "relative", display: "inline-flex" }, children: [
|
|
1567
1577
|
/* @__PURE__ */ jsx28(
|
|
1568
1578
|
Button,
|
|
1569
1579
|
{
|
|
@@ -1581,7 +1591,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
1581
1591
|
{
|
|
1582
1592
|
className: "fd-view-enter",
|
|
1583
1593
|
style: { position: "absolute", top: "calc(100% + 6px)", [align]: 0, zIndex, width: 220, maxWidth: "calc(100vw - 32px)", display: "block", background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 10, boxShadow: "0 16px 44px rgba(11,13,17,.18)", padding: 8 },
|
|
1584
|
-
children: /* @__PURE__ */
|
|
1594
|
+
children: /* @__PURE__ */ jsxs24("span", { className: "fd-stack", role: "menu", "aria-label": "Add filter", style: { gap: 2 }, children: [
|
|
1585
1595
|
/* @__PURE__ */ jsx28("span", { className: "fd-overline fd-muted", style: { padding: "4px 8px 6px" }, children: "Add filter" }),
|
|
1586
1596
|
addableFields.map((f) => /* @__PURE__ */ jsx28(
|
|
1587
1597
|
"button",
|
|
@@ -1603,12 +1613,12 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
1603
1613
|
}
|
|
1604
1614
|
|
|
1605
1615
|
// src/components/data/StatTile.tsx
|
|
1606
|
-
import { jsx as jsx29, jsxs as
|
|
1616
|
+
import { jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1607
1617
|
function StatTile({ label, value, sub, delta, loading = false, compact: compact3 = false, className = "", ...rest }) {
|
|
1608
|
-
return /* @__PURE__ */
|
|
1609
|
-
loading ? /* @__PURE__ */ jsx29("span", { className: "fd-skel fd-skel-text", style: { display: "block", height: compact3 ? 20 : 28, width: "62%" } }) : /* @__PURE__ */
|
|
1618
|
+
return /* @__PURE__ */ jsxs25("div", { className: ["fd-stat", compact3 ? "fd-stat-compact" : "", className].filter(Boolean).join(" "), ...rest, children: [
|
|
1619
|
+
loading ? /* @__PURE__ */ jsx29("span", { className: "fd-skel fd-skel-text", style: { display: "block", height: compact3 ? 20 : 28, width: "62%" } }) : /* @__PURE__ */ jsxs25("span", { className: "fd-stat-top", children: [
|
|
1610
1620
|
/* @__PURE__ */ jsx29("span", { className: "fd-stat-figure", children: value }),
|
|
1611
|
-
delta ? /* @__PURE__ */
|
|
1621
|
+
delta ? /* @__PURE__ */ jsxs25("span", { className: delta.startsWith("-") ? "fd-stat-delta-down" : "fd-stat-delta-up", style: { fontWeight: 600, fontSize: "var(--body-sm-size)", flex: "none" }, children: [
|
|
1612
1622
|
/* @__PURE__ */ jsx29("i", { className: "ph ph-arrow-" + (delta.startsWith("-") ? "down" : "up") + "-right", "aria-hidden": "true" }),
|
|
1613
1623
|
" ",
|
|
1614
1624
|
delta
|
|
@@ -1620,8 +1630,8 @@ function StatTile({ label, value, sub, delta, loading = false, compact: compact3
|
|
|
1620
1630
|
}
|
|
1621
1631
|
|
|
1622
1632
|
// src/components/data/CodeBlock.tsx
|
|
1623
|
-
import * as
|
|
1624
|
-
import { Fragment as Fragment5, jsx as jsx30, jsxs as
|
|
1633
|
+
import * as React10 from "react";
|
|
1634
|
+
import { Fragment as Fragment5, jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
1625
1635
|
var JS_KW = /^(?:const|let|var|function|return|if|else|for|while|do|new|class|extends|import|from|export|default|await|async|try|catch|finally|throw|typeof|instanceof|of|in|switch|case|break|continue|delete|void|yield|static|get|set|this|super|interface|type|enum|implements|public|private|protected|readonly|abstract|as|satisfies|declare|namespace)$/;
|
|
1626
1636
|
var RULES = {
|
|
1627
1637
|
js: [
|
|
@@ -1776,13 +1786,13 @@ function tokenize(src, lang) {
|
|
|
1776
1786
|
return out;
|
|
1777
1787
|
}
|
|
1778
1788
|
function Highlighted({ code, lang }) {
|
|
1779
|
-
const toks =
|
|
1789
|
+
const toks = React10.useMemo(() => tokenize(code, lang), [code, lang]);
|
|
1780
1790
|
return /* @__PURE__ */ jsx30(Fragment5, { children: toks.map((tk, i) => tk.c ? /* @__PURE__ */ jsx30("span", { className: "tok-" + tk.c, children: tk.t }, i) : tk.t) });
|
|
1781
1791
|
}
|
|
1782
1792
|
function useCopy() {
|
|
1783
|
-
const [done, setDone] =
|
|
1784
|
-
const timer =
|
|
1785
|
-
|
|
1793
|
+
const [done, setDone] = React10.useState(false);
|
|
1794
|
+
const timer = React10.useRef(null);
|
|
1795
|
+
React10.useEffect(() => () => {
|
|
1786
1796
|
if (timer.current) clearTimeout(timer.current);
|
|
1787
1797
|
}, []);
|
|
1788
1798
|
const copy = (text) => {
|
|
@@ -1818,37 +1828,37 @@ function CodeBlock({
|
|
|
1818
1828
|
actions,
|
|
1819
1829
|
className = ""
|
|
1820
1830
|
}) {
|
|
1821
|
-
const [wrap, setWrap] =
|
|
1822
|
-
const [open, setOpen] =
|
|
1831
|
+
const [wrap, setWrap] = React10.useState(!!wrapDefault);
|
|
1832
|
+
const [open, setOpen] = React10.useState(false);
|
|
1823
1833
|
const [copied, copy] = useCopy();
|
|
1824
1834
|
const body = String(code).replace(/\n$/, "");
|
|
1825
1835
|
const lines = body.split("\n");
|
|
1826
1836
|
const foldable = collapseAfter > 0 && lines.length > collapseAfter + 6;
|
|
1827
1837
|
const shown = foldable && !open ? lines.slice(0, collapseAfter).join("\n") : body;
|
|
1828
|
-
return /* @__PURE__ */
|
|
1829
|
-
/* @__PURE__ */
|
|
1838
|
+
return /* @__PURE__ */ jsxs26("div", { className: ["fd-code", wrap ? "is-wrap" : "", className].filter(Boolean).join(" "), children: [
|
|
1839
|
+
/* @__PURE__ */ jsxs26("div", { className: "fd-code-head", children: [
|
|
1830
1840
|
filename ? /* @__PURE__ */ jsx30("span", { className: "fd-code-file", children: filename }) : null,
|
|
1831
1841
|
/* @__PURE__ */ jsx30("span", { className: "fd-code-lang", children: languageLabel(language) }),
|
|
1832
1842
|
/* @__PURE__ */ jsx30("span", { className: "fd-code-spacer" }),
|
|
1833
1843
|
actions,
|
|
1834
1844
|
/* @__PURE__ */ jsx30("button", { type: "button", className: "fd-code-act", onClick: () => setWrap((v) => !v), "aria-pressed": wrap, title: wrap ? "No wrap" : "Soft wrap", children: /* @__PURE__ */ jsx30("i", { className: "ph ph-text-" + (wrap ? "columns" : "align-left"), "aria-hidden": "true" }) }),
|
|
1835
|
-
copyable ? /* @__PURE__ */
|
|
1845
|
+
copyable ? /* @__PURE__ */ jsxs26("button", { type: "button", className: "fd-code-act" + (copied ? " is-done" : ""), onClick: () => copy(body), children: [
|
|
1836
1846
|
/* @__PURE__ */ jsx30("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
|
|
1837
1847
|
/* @__PURE__ */ jsx30("span", { children: copied ? "Copied" : "Copy" })
|
|
1838
1848
|
] }) : null
|
|
1839
1849
|
] }),
|
|
1840
|
-
/* @__PURE__ */
|
|
1850
|
+
/* @__PURE__ */ jsxs26("div", { className: "fd-code-body", children: [
|
|
1841
1851
|
lineNumbers ? /* @__PURE__ */ jsx30("pre", { className: "fd-code-gutter", "aria-hidden": "true", children: shown.split("\n").map((_, i) => i + 1 + "\n").join("") }) : null,
|
|
1842
1852
|
/* @__PURE__ */ jsx30("pre", { className: "fd-code-pre", tabIndex: 0, children: /* @__PURE__ */ jsx30("code", { children: /* @__PURE__ */ jsx30(Highlighted, { code: shown, lang: language }) }) })
|
|
1843
1853
|
] }),
|
|
1844
|
-
foldable ? /* @__PURE__ */
|
|
1854
|
+
foldable ? /* @__PURE__ */ jsxs26("button", { type: "button", className: "fd-code-fold", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
1845
1855
|
/* @__PURE__ */ jsx30("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" }),
|
|
1846
1856
|
open ? "Collapse" : "Show all " + lines.length + " lines"
|
|
1847
1857
|
] }) : null
|
|
1848
1858
|
] });
|
|
1849
1859
|
}
|
|
1850
1860
|
function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
|
|
1851
|
-
const [open, setOpen] =
|
|
1861
|
+
const [open, setOpen] = React10.useState(false);
|
|
1852
1862
|
const [copied, copy] = useCopy();
|
|
1853
1863
|
const raw = String(diff).replace(/\n$/, "");
|
|
1854
1864
|
const all = raw.split("\n").map((line) => {
|
|
@@ -1862,31 +1872,31 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
|
|
|
1862
1872
|
const dels = all.filter((l) => l.k === "del").length;
|
|
1863
1873
|
const foldable = collapseAfter > 0 && all.length > collapseAfter + 6;
|
|
1864
1874
|
const rows = foldable && !open ? all.slice(0, collapseAfter) : all;
|
|
1865
|
-
return /* @__PURE__ */
|
|
1866
|
-
/* @__PURE__ */
|
|
1875
|
+
return /* @__PURE__ */ jsxs26("div", { className: ["fd-code", "fd-diff", className].filter(Boolean).join(" "), children: [
|
|
1876
|
+
/* @__PURE__ */ jsxs26("div", { className: "fd-code-head", children: [
|
|
1867
1877
|
/* @__PURE__ */ jsx30("i", { className: "ph ph-git-diff fd-code-icon", "aria-hidden": "true" }),
|
|
1868
1878
|
filename ? /* @__PURE__ */ jsx30("span", { className: "fd-code-file", children: filename }) : /* @__PURE__ */ jsx30("span", { className: "fd-code-lang", children: "Diff" }),
|
|
1869
|
-
/* @__PURE__ */
|
|
1870
|
-
/* @__PURE__ */
|
|
1879
|
+
/* @__PURE__ */ jsxs26("span", { className: "fd-diff-stat fd-tabular", children: [
|
|
1880
|
+
/* @__PURE__ */ jsxs26("span", { className: "is-add", children: [
|
|
1871
1881
|
"+",
|
|
1872
1882
|
adds
|
|
1873
1883
|
] }),
|
|
1874
|
-
/* @__PURE__ */
|
|
1884
|
+
/* @__PURE__ */ jsxs26("span", { className: "is-del", children: [
|
|
1875
1885
|
"\u2212",
|
|
1876
1886
|
dels
|
|
1877
1887
|
] })
|
|
1878
1888
|
] }),
|
|
1879
1889
|
/* @__PURE__ */ jsx30("span", { className: "fd-code-spacer" }),
|
|
1880
|
-
/* @__PURE__ */
|
|
1890
|
+
/* @__PURE__ */ jsxs26("button", { type: "button", className: "fd-code-act" + (copied ? " is-done" : ""), onClick: () => copy(raw), children: [
|
|
1881
1891
|
/* @__PURE__ */ jsx30("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
|
|
1882
1892
|
/* @__PURE__ */ jsx30("span", { children: copied ? "Copied" : "Copy" })
|
|
1883
1893
|
] })
|
|
1884
1894
|
] }),
|
|
1885
|
-
/* @__PURE__ */ jsx30("div", { className: "fd-diff-body", children: rows.map((r, i) => /* @__PURE__ */
|
|
1895
|
+
/* @__PURE__ */ jsx30("div", { className: "fd-diff-body", children: rows.map((r, i) => /* @__PURE__ */ jsxs26("div", { className: "fd-diff-line is-" + r.k, children: [
|
|
1886
1896
|
/* @__PURE__ */ jsx30("span", { className: "fd-diff-mark", "aria-hidden": "true", children: r.k === "add" ? "+" : r.k === "del" ? "\u2212" : "" }),
|
|
1887
1897
|
/* @__PURE__ */ jsx30("code", { children: r.k === "add" || r.k === "del" ? r.line.slice(1) : r.line })
|
|
1888
1898
|
] }, i)) }),
|
|
1889
|
-
foldable ? /* @__PURE__ */
|
|
1899
|
+
foldable ? /* @__PURE__ */ jsxs26("button", { type: "button", className: "fd-code-fold", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
1890
1900
|
/* @__PURE__ */ jsx30("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" }),
|
|
1891
1901
|
open ? "Collapse" : "Show all " + all.length + " lines"
|
|
1892
1902
|
] }) : null
|
|
@@ -1894,8 +1904,8 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
|
|
|
1894
1904
|
}
|
|
1895
1905
|
|
|
1896
1906
|
// src/components/data/Markdown.tsx
|
|
1897
|
-
import * as
|
|
1898
|
-
import { jsx as jsx31, jsxs as
|
|
1907
|
+
import * as React11 from "react";
|
|
1908
|
+
import { jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
1899
1909
|
var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
|
|
1900
1910
|
var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
|
|
1901
1911
|
var INLINE = [
|
|
@@ -1933,7 +1943,7 @@ function inlineNodes(src, ctx, keyBase) {
|
|
|
1933
1943
|
const href = safeHref(g(2));
|
|
1934
1944
|
out.push(href ? /* @__PURE__ */ jsx31("a", { href, title: g(3) || void 0, target: /^https?:/i.test(href) ? "_blank" : void 0, rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: inlineNodes(g(1), ctx, key()) }, key()) : /* @__PURE__ */ jsx31("span", { children: g(1) }, key()));
|
|
1935
1945
|
} else if (kind === "cite") {
|
|
1936
|
-
out.push(ctx.renderCitation ? /* @__PURE__ */ jsx31(
|
|
1946
|
+
out.push(ctx.renderCitation ? /* @__PURE__ */ jsx31(React11.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ jsx31("sup", { className: "fd-md-cite", children: g(1) }, key()));
|
|
1937
1947
|
} else if (kind === "strongem") out.push(/* @__PURE__ */ jsx31("strong", { children: /* @__PURE__ */ jsx31("em", { children: inlineNodes(g(1), ctx, key()) }) }, key()));
|
|
1938
1948
|
else if (kind === "strong") out.push(/* @__PURE__ */ jsx31("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
1939
1949
|
else if (kind === "em") out.push(/* @__PURE__ */ jsx31("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
@@ -2073,13 +2083,13 @@ function renderBlocks(blocks, ctx, path) {
|
|
|
2073
2083
|
case "list": {
|
|
2074
2084
|
const Tag2 = b.ordered ? "ol" : "ul";
|
|
2075
2085
|
const isTask = b.items.some((it) => it.checked != null);
|
|
2076
|
-
return /* @__PURE__ */ jsx31(Tag2, { className: "fd-md-list" + (isTask ? " is-task" : ""), start: b.ordered && b.start !== 1 ? b.start : void 0, children: b.items.map((it, j) => /* @__PURE__ */
|
|
2086
|
+
return /* @__PURE__ */ jsx31(Tag2, { className: "fd-md-list" + (isTask ? " is-task" : ""), start: b.ordered && b.start !== 1 ? b.start : void 0, children: b.items.map((it, j) => /* @__PURE__ */ jsxs27("li", { className: it.checked != null ? it.checked ? "is-done" : "is-todo" : void 0, children: [
|
|
2077
2087
|
it.checked != null ? /* @__PURE__ */ jsx31("span", { className: "fd-md-task", "aria-hidden": "true", children: /* @__PURE__ */ jsx31("i", { className: "ph ph-" + (it.checked ? "check-square" : "square") }) }) : null,
|
|
2078
2088
|
/* @__PURE__ */ jsx31("span", { className: "fd-md-li", children: renderBlocks(it.children, ctx, k + "-" + j) })
|
|
2079
2089
|
] }, k + "-" + j)) }, k);
|
|
2080
2090
|
}
|
|
2081
2091
|
case "table":
|
|
2082
|
-
return /* @__PURE__ */ jsx31("div", { className: "fd-md-tablewrap", children: /* @__PURE__ */
|
|
2092
|
+
return /* @__PURE__ */ jsx31("div", { className: "fd-md-tablewrap", children: /* @__PURE__ */ jsxs27("table", { className: "fd-md-table", children: [
|
|
2083
2093
|
/* @__PURE__ */ jsx31("thead", { children: /* @__PURE__ */ jsx31("tr", { children: b.head.map((c, j) => /* @__PURE__ */ jsx31("th", { style: { textAlign: b.align[j] || "left" }, children: inlineNodes(c, ctx, k + "h" + j) }, j)) }) }),
|
|
2084
2094
|
/* @__PURE__ */ jsx31("tbody", { children: b.rows.map((r, ri) => /* @__PURE__ */ jsx31("tr", { children: b.head.map((_, ci) => /* @__PURE__ */ jsx31("td", { style: { textAlign: b.align[ci] || "left" }, children: inlineNodes(r[ci] || "", ctx, k + ri + "c" + ci) }, ci)) }, ri)) })
|
|
2085
2095
|
] }) }, k);
|
|
@@ -2098,7 +2108,7 @@ function Markdown({
|
|
|
2098
2108
|
onLinkClick
|
|
2099
2109
|
}) {
|
|
2100
2110
|
const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
|
|
2101
|
-
const blocks =
|
|
2111
|
+
const blocks = React11.useMemo(() => parseBlocks(source), [source]);
|
|
2102
2112
|
return /* @__PURE__ */ jsx31("div", { className: ["fd-md", className].filter(Boolean).join(" "), children: renderBlocks(blocks, ctx, "b") });
|
|
2103
2113
|
}
|
|
2104
2114
|
function MarkdownInline({ source = "", className = "", onLinkClick }) {
|
|
@@ -2109,13 +2119,13 @@ function markdownToText(src) {
|
|
|
2109
2119
|
}
|
|
2110
2120
|
|
|
2111
2121
|
// src/components/data/Meter.tsx
|
|
2112
|
-
import { jsx as jsx32, jsxs as
|
|
2122
|
+
import { jsx as jsx32, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2113
2123
|
function Meter({ segments = [], unallocated = 0, height = 8, label, legend = false, className = "" }) {
|
|
2114
2124
|
const total = segments.reduce((s, x) => s + x.value, 0) + unallocated;
|
|
2115
2125
|
const pct = (v) => total ? v / total * 100 : 0;
|
|
2116
|
-
return /* @__PURE__ */
|
|
2126
|
+
return /* @__PURE__ */ jsxs28("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 8 }, children: [
|
|
2117
2127
|
label ? /* @__PURE__ */ jsx32("span", { className: "fd-label-lg fd-secondary", children: label }) : null,
|
|
2118
|
-
/* @__PURE__ */
|
|
2128
|
+
/* @__PURE__ */ jsxs28("div", { className: "fd-meterbar", style: { height }, children: [
|
|
2119
2129
|
segments.map((s, i) => /* @__PURE__ */ jsx32(
|
|
2120
2130
|
"span",
|
|
2121
2131
|
{
|
|
@@ -2127,12 +2137,12 @@ function Meter({ segments = [], unallocated = 0, height = 8, label, legend = fal
|
|
|
2127
2137
|
)),
|
|
2128
2138
|
unallocated > 0 ? /* @__PURE__ */ jsx32("span", { className: "fd-meterbar-seg fd-meterbar-unallocated", title: "Unallocated", style: { width: pct(unallocated) + "%" } }) : null
|
|
2129
2139
|
] }),
|
|
2130
|
-
legend ? /* @__PURE__ */
|
|
2131
|
-
segments.map((s, i) => /* @__PURE__ */
|
|
2140
|
+
legend ? /* @__PURE__ */ jsxs28("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap" }, children: [
|
|
2141
|
+
segments.map((s, i) => /* @__PURE__ */ jsxs28("span", { className: "fd-row fd-body-sm fd-secondary", style: { gap: 7 }, children: [
|
|
2132
2142
|
/* @__PURE__ */ jsx32("span", { style: { width: 9, height: 9, borderRadius: 2, background: s.color || "var(--chart-" + (i % 8 + 1) + ")" } }),
|
|
2133
2143
|
s.label
|
|
2134
2144
|
] }, i)),
|
|
2135
|
-
unallocated > 0 ? /* @__PURE__ */
|
|
2145
|
+
unallocated > 0 ? /* @__PURE__ */ jsxs28("span", { className: "fd-row fd-body-sm fd-secondary", style: { gap: 7 }, children: [
|
|
2136
2146
|
/* @__PURE__ */ jsx32("span", { className: "fd-meterbar-unallocated", style: { width: 9, height: 9, borderRadius: 2 } }),
|
|
2137
2147
|
"Unallocated"
|
|
2138
2148
|
] }) : null
|
|
@@ -2141,7 +2151,11 @@ function Meter({ segments = [], unallocated = 0, height = 8, label, legend = fal
|
|
|
2141
2151
|
}
|
|
2142
2152
|
|
|
2143
2153
|
// src/components/data/Pagination.tsx
|
|
2144
|
-
import { Fragment as Fragment7, jsx as jsx33, jsxs as
|
|
2154
|
+
import { Fragment as Fragment7, jsx as jsx33, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2155
|
+
var unitPluralRules = new Intl.PluralRules("en-US");
|
|
2156
|
+
function pluralizeUnit(n, singular, irregularPlural) {
|
|
2157
|
+
return unitPluralRules.select(n) === "one" ? singular : irregularPlural ?? `${singular}s`;
|
|
2158
|
+
}
|
|
2145
2159
|
function Pagination({
|
|
2146
2160
|
page = 1,
|
|
2147
2161
|
pageSize = 25,
|
|
@@ -2150,7 +2164,8 @@ function Pagination({
|
|
|
2150
2164
|
onPageChange,
|
|
2151
2165
|
onPageSizeChange,
|
|
2152
2166
|
loading = false,
|
|
2153
|
-
unit = "
|
|
2167
|
+
unit = "row",
|
|
2168
|
+
unitPlural,
|
|
2154
2169
|
className = "",
|
|
2155
2170
|
...rest
|
|
2156
2171
|
}) {
|
|
@@ -2160,18 +2175,19 @@ function Pagination({
|
|
|
2160
2175
|
const go = (p) => {
|
|
2161
2176
|
if (onPageChange && p >= 1 && p <= totalPages && p !== page) onPageChange(p);
|
|
2162
2177
|
};
|
|
2178
|
+
const unitLabel = pluralizeUnit(total, unit, unitPlural);
|
|
2163
2179
|
const nums = [];
|
|
2164
2180
|
const span = 1;
|
|
2165
2181
|
for (let i = 1; i <= totalPages; i++) {
|
|
2166
2182
|
if (i === 1 || i === totalPages || Math.abs(i - page) <= span) nums.push(i);
|
|
2167
2183
|
else if (nums[nums.length - 1] !== "\u2026") nums.push("\u2026");
|
|
2168
2184
|
}
|
|
2169
|
-
return /* @__PURE__ */
|
|
2170
|
-
/* @__PURE__ */ jsx33("span", { className: "fd-pag-count", children: loading ? /* @__PURE__ */ jsx33("span", { className: "fd-skel fd-skel-text", style: { display: "inline-block", height: 12, width: 108 } }) : total === 0 ? /* @__PURE__ */
|
|
2185
|
+
return /* @__PURE__ */ jsxs29("div", { className: ["fd-pag", className].filter(Boolean).join(" "), ...rest, children: [
|
|
2186
|
+
/* @__PURE__ */ jsx33("span", { className: "fd-pag-count", children: loading ? /* @__PURE__ */ jsx33("span", { className: "fd-skel fd-skel-text", style: { display: "inline-block", height: 12, width: 108 } }) : total === 0 ? /* @__PURE__ */ jsxs29(Fragment7, { children: [
|
|
2171
2187
|
"No ",
|
|
2172
|
-
|
|
2173
|
-
] }) : /* @__PURE__ */
|
|
2174
|
-
/* @__PURE__ */
|
|
2188
|
+
unitLabel
|
|
2189
|
+
] }) : /* @__PURE__ */ jsxs29(Fragment7, { children: [
|
|
2190
|
+
/* @__PURE__ */ jsxs29("strong", { children: [
|
|
2175
2191
|
from.toLocaleString(),
|
|
2176
2192
|
"\u2013",
|
|
2177
2193
|
to.toLocaleString()
|
|
@@ -2179,13 +2195,13 @@ function Pagination({
|
|
|
2179
2195
|
" of ",
|
|
2180
2196
|
total.toLocaleString(),
|
|
2181
2197
|
" ",
|
|
2182
|
-
|
|
2198
|
+
unitLabel
|
|
2183
2199
|
] }) }),
|
|
2184
|
-
onPageSizeChange ? /* @__PURE__ */
|
|
2200
|
+
onPageSizeChange ? /* @__PURE__ */ jsxs29("label", { className: "fd-pag-size", children: [
|
|
2185
2201
|
/* @__PURE__ */ jsx33("span", { children: "Rows" }),
|
|
2186
2202
|
/* @__PURE__ */ jsx33("select", { value: pageSize, onChange: (e) => onPageSizeChange(Number(e.target.value)), "aria-label": "Rows per page", children: pageSizes.map((n) => /* @__PURE__ */ jsx33("option", { value: n, children: n }, n)) })
|
|
2187
2203
|
] }) : null,
|
|
2188
|
-
/* @__PURE__ */
|
|
2204
|
+
/* @__PURE__ */ jsxs29("span", { className: "fd-pag-nav", children: [
|
|
2189
2205
|
/* @__PURE__ */ jsx33("button", { type: "button", onClick: () => go(1), disabled: page <= 1, "aria-label": "First page", children: /* @__PURE__ */ jsx33("i", { className: "ph ph-caret-double-left" }) }),
|
|
2190
2206
|
/* @__PURE__ */ jsx33("button", { type: "button", onClick: () => go(page - 1), disabled: page <= 1, "aria-label": "Previous page", children: /* @__PURE__ */ jsx33("i", { className: "ph ph-caret-left" }) }),
|
|
2191
2207
|
nums.map((n, i) => n === "\u2026" ? /* @__PURE__ */ jsx33("span", { className: "fd-pag-gap", "aria-hidden": "true", children: "\u2026" }, "e" + i) : /* @__PURE__ */ jsx33(
|
|
@@ -2206,8 +2222,8 @@ function Pagination({
|
|
|
2206
2222
|
}
|
|
2207
2223
|
|
|
2208
2224
|
// src/components/data/RelativeTime.tsx
|
|
2209
|
-
import * as
|
|
2210
|
-
import { jsxs as
|
|
2225
|
+
import * as React12 from "react";
|
|
2226
|
+
import { jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2211
2227
|
var MIN = 6e4;
|
|
2212
2228
|
var HOUR = 36e5;
|
|
2213
2229
|
var DAY = 864e5;
|
|
@@ -2258,9 +2274,9 @@ function formatDuration(ms) {
|
|
|
2258
2274
|
return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
|
|
2259
2275
|
}
|
|
2260
2276
|
function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
|
|
2261
|
-
const [, force] =
|
|
2277
|
+
const [, force] = React12.useState(0);
|
|
2262
2278
|
const t = value instanceof Date ? value.getTime() : Date.parse(value);
|
|
2263
|
-
|
|
2279
|
+
React12.useEffect(() => {
|
|
2264
2280
|
if (!refresh2 || !t || isNaN(t)) return;
|
|
2265
2281
|
const abs = Math.abs(t - Date.now());
|
|
2266
2282
|
if (abs > DAY) return;
|
|
@@ -2269,17 +2285,17 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
|
|
|
2269
2285
|
return () => clearInterval(id);
|
|
2270
2286
|
}, [t, refresh2]);
|
|
2271
2287
|
if (!t || isNaN(t)) return null;
|
|
2272
|
-
return /* @__PURE__ */
|
|
2288
|
+
return /* @__PURE__ */ jsxs30("time", { className, dateTime: new Date(t).toISOString(), title: formatAbsolute(new Date(t)), ...rest, children: [
|
|
2273
2289
|
prefix ? prefix + " " : "",
|
|
2274
2290
|
formatRelative(new Date(t))
|
|
2275
2291
|
] });
|
|
2276
2292
|
}
|
|
2277
2293
|
|
|
2278
2294
|
// src/components/data/ScoreMeter.tsx
|
|
2279
|
-
import * as
|
|
2295
|
+
import * as React14 from "react";
|
|
2280
2296
|
|
|
2281
2297
|
// src/components/data/SegmentedMeter.tsx
|
|
2282
|
-
import * as
|
|
2298
|
+
import * as React13 from "react";
|
|
2283
2299
|
|
|
2284
2300
|
// src/kits/files.ts
|
|
2285
2301
|
function formatBytes(n) {
|
|
@@ -2439,7 +2455,7 @@ var FileKit = {
|
|
|
2439
2455
|
};
|
|
2440
2456
|
|
|
2441
2457
|
// src/components/data/SegmentedMeter.tsx
|
|
2442
|
-
import { jsx as jsx34, jsxs as
|
|
2458
|
+
import { jsx as jsx34, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2443
2459
|
var VARIANT_FILL = {
|
|
2444
2460
|
brand: "var(--brand)",
|
|
2445
2461
|
neutral: "var(--n-400)",
|
|
@@ -2484,16 +2500,16 @@ function SegmentedMeter({
|
|
|
2484
2500
|
const pct = safeTotal ? Math.min(100, Math.round(used / safeTotal * 100)) : 0;
|
|
2485
2501
|
const w = (v) => safeTotal ? Math.max(0, Math.min(100, Number(v) / safeTotal * 100)) : 0;
|
|
2486
2502
|
const fill = (s, i) => s.color || (s.variant ? VARIANT_FILL[s.variant] : void 0) || CHART[i % CHART.length];
|
|
2487
|
-
const generatedId =
|
|
2503
|
+
const generatedId = React13.useId();
|
|
2488
2504
|
const uid2 = id || generatedId;
|
|
2489
|
-
return /* @__PURE__ */
|
|
2490
|
-
label || showTotal ? /* @__PURE__ */
|
|
2505
|
+
return /* @__PURE__ */ jsxs31("div", { className: ["fd-segmeter", className].filter(Boolean).join(" "), onClick, children: [
|
|
2506
|
+
label || showTotal ? /* @__PURE__ */ jsxs31("div", { className: "fd-segmeter-head", children: [
|
|
2491
2507
|
label ? /* @__PURE__ */ jsx34("span", { className: "fd-segmeter-label", id: uid2 + "-l", children: label }) : /* @__PURE__ */ jsx34("span", {}),
|
|
2492
|
-
showTotal ? /* @__PURE__ */
|
|
2508
|
+
showTotal ? /* @__PURE__ */ jsxs31("span", { className: "fd-segmeter-total fd-tabular", children: [
|
|
2493
2509
|
format(used),
|
|
2494
2510
|
/* @__PURE__ */ jsx34("span", { className: "fd-segmeter-sep", children: " / " }),
|
|
2495
2511
|
safeTotal ? format(safeTotal) : "\u2014",
|
|
2496
|
-
showPercent ? /* @__PURE__ */
|
|
2512
|
+
showPercent ? /* @__PURE__ */ jsxs31("span", { className: "fd-segmeter-pct", children: [
|
|
2497
2513
|
" (",
|
|
2498
2514
|
pct,
|
|
2499
2515
|
"%)"
|
|
@@ -2523,13 +2539,13 @@ function SegmentedMeter({
|
|
|
2523
2539
|
))
|
|
2524
2540
|
}
|
|
2525
2541
|
),
|
|
2526
|
-
legend ? /* @__PURE__ */
|
|
2527
|
-
items.map((s, i) => /* @__PURE__ */
|
|
2542
|
+
legend ? /* @__PURE__ */ jsxs31("ul", { className: "fd-segmeter-legend", children: [
|
|
2543
|
+
items.map((s, i) => /* @__PURE__ */ jsxs31("li", { children: [
|
|
2528
2544
|
/* @__PURE__ */ jsx34("span", { className: "fd-segmeter-dot", style: { background: fill(s, i) }, "aria-hidden": "true" }),
|
|
2529
2545
|
/* @__PURE__ */ jsx34("span", { className: "fd-segmeter-key", children: s.label }),
|
|
2530
2546
|
/* @__PURE__ */ jsx34("span", { className: "fd-segmeter-val fd-tabular", children: format(s.value) })
|
|
2531
2547
|
] }, s.id || s.label || i)),
|
|
2532
|
-
safeTotal && used < safeTotal ? /* @__PURE__ */
|
|
2548
|
+
safeTotal && used < safeTotal ? /* @__PURE__ */ jsxs31("li", { className: "is-remainder", children: [
|
|
2533
2549
|
/* @__PURE__ */ jsx34("span", { className: "fd-segmeter-dot is-empty", "aria-hidden": "true" }),
|
|
2534
2550
|
/* @__PURE__ */ jsx34("span", { className: "fd-segmeter-key", children: remainderLabel }),
|
|
2535
2551
|
/* @__PURE__ */ jsx34("span", { className: "fd-segmeter-val fd-tabular", children: format(safeTotal - used) })
|
|
@@ -2540,11 +2556,11 @@ function SegmentedMeter({
|
|
|
2540
2556
|
function QuotaRow({ label, percent = 0, note, tone, className = "" }) {
|
|
2541
2557
|
const p = Math.max(0, Math.min(100, Math.round(Number(percent) || 0)));
|
|
2542
2558
|
const auto = p >= 90 ? "danger" : p >= 70 ? "warn" : "brand";
|
|
2543
|
-
return /* @__PURE__ */
|
|
2544
|
-
/* @__PURE__ */
|
|
2559
|
+
return /* @__PURE__ */ jsxs31("div", { className: ["fd-quota", className].filter(Boolean).join(" "), children: [
|
|
2560
|
+
/* @__PURE__ */ jsxs31("div", { className: "fd-quota-head", children: [
|
|
2545
2561
|
/* @__PURE__ */ jsx34("span", { className: "fd-quota-label", children: label }),
|
|
2546
2562
|
note ? /* @__PURE__ */ jsx34("span", { className: "fd-quota-note", children: note }) : null,
|
|
2547
|
-
/* @__PURE__ */
|
|
2563
|
+
/* @__PURE__ */ jsxs31("span", { className: "fd-quota-pct fd-tabular", children: [
|
|
2548
2564
|
p,
|
|
2549
2565
|
"%"
|
|
2550
2566
|
] })
|
|
@@ -2554,7 +2570,7 @@ function QuotaRow({ label, percent = 0, note, tone, className = "" }) {
|
|
|
2554
2570
|
}
|
|
2555
2571
|
|
|
2556
2572
|
// src/components/data/ScoreMeter.tsx
|
|
2557
|
-
import { jsx as jsx35, jsxs as
|
|
2573
|
+
import { jsx as jsx35, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
2558
2574
|
function ScoreMeter({
|
|
2559
2575
|
score,
|
|
2560
2576
|
segments,
|
|
@@ -2568,10 +2584,10 @@ function ScoreMeter({
|
|
|
2568
2584
|
breakdownWidth = 280,
|
|
2569
2585
|
className = ""
|
|
2570
2586
|
}) {
|
|
2571
|
-
const [open, setOpen] =
|
|
2572
|
-
const ref =
|
|
2587
|
+
const [open, setOpen] = React14.useState(false);
|
|
2588
|
+
const ref = React14.useRef(null);
|
|
2573
2589
|
const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
|
|
2574
|
-
const body = /* @__PURE__ */
|
|
2590
|
+
const body = /* @__PURE__ */ jsxs32(React14.Fragment, { children: [
|
|
2575
2591
|
/* @__PURE__ */ jsx35("span", { className: "fd-scoremeter-rail", style: { width }, "aria-hidden": "true", children: /* @__PURE__ */ jsx35(SegmentedMeter, { total: 100, segments, height, showTotal: false, showPercent: false, legend: false }) }),
|
|
2576
2592
|
showScore ? /* @__PURE__ */ jsx35("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
|
|
2577
2593
|
] });
|
|
@@ -2590,7 +2606,7 @@ function ScoreMeter({
|
|
|
2590
2606
|
}
|
|
2591
2607
|
);
|
|
2592
2608
|
}
|
|
2593
|
-
return /* @__PURE__ */
|
|
2609
|
+
return /* @__PURE__ */ jsxs32(React14.Fragment, { children: [
|
|
2594
2610
|
/* @__PURE__ */ jsx35(
|
|
2595
2611
|
"button",
|
|
2596
2612
|
{
|
|
@@ -2621,14 +2637,14 @@ function ScoreMeter({
|
|
|
2621
2637
|
}
|
|
2622
2638
|
|
|
2623
2639
|
// src/components/data/SortMenu.tsx
|
|
2624
|
-
import * as
|
|
2625
|
-
import { jsx as jsx36, jsxs as
|
|
2640
|
+
import * as React15 from "react";
|
|
2641
|
+
import { jsx as jsx36, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2626
2642
|
var SORT_MENU_BASE = 120;
|
|
2627
2643
|
function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", className = "", ...rest }) {
|
|
2628
|
-
const [open, setOpen] =
|
|
2644
|
+
const [open, setOpen] = React15.useState(false);
|
|
2629
2645
|
const zIndex = useOverlayLayer(SORT_MENU_BASE);
|
|
2630
|
-
const ref =
|
|
2631
|
-
|
|
2646
|
+
const ref = React15.useRef(null);
|
|
2647
|
+
React15.useEffect(() => {
|
|
2632
2648
|
if (!open) return;
|
|
2633
2649
|
const away = (e) => {
|
|
2634
2650
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -2670,16 +2686,16 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
|
|
|
2670
2686
|
}
|
|
2671
2687
|
);
|
|
2672
2688
|
};
|
|
2673
|
-
return /* @__PURE__ */
|
|
2674
|
-
/* @__PURE__ */
|
|
2689
|
+
return /* @__PURE__ */ jsxs33("span", { className, style: { position: "relative", display: "inline-flex" }, ref, ...rest, children: [
|
|
2690
|
+
/* @__PURE__ */ jsxs33(Button, { size, variant: "secondary", icon: dir === "asc" ? "sort-ascending" : "sort-descending", onClick: () => setOpen(!open), children: [
|
|
2675
2691
|
cur ? cur.label : "Unsorted",
|
|
2676
2692
|
/* @__PURE__ */ jsx36("i", { className: "ph ph-" + (dir === "asc" ? "arrow-up" : "arrow-down"), style: { fontSize: 12, marginLeft: 6, opacity: 0.75 } })
|
|
2677
2693
|
] }),
|
|
2678
|
-
open ? /* @__PURE__ */ jsx36(LayerProvider, { zIndex, children: /* @__PURE__ */ jsx36("span", { className: "fd-view-enter", style: { position: "absolute", top: "calc(100% + 6px)", [align]: 0, zIndex, width: 280, maxWidth: "calc(100vw - 32px)", display: "block", background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 10, boxShadow: "0 16px 44px rgba(11,13,17,.18)", padding: 8 }, children: /* @__PURE__ */
|
|
2694
|
+
open ? /* @__PURE__ */ jsx36(LayerProvider, { zIndex, children: /* @__PURE__ */ jsx36("span", { className: "fd-view-enter", style: { position: "absolute", top: "calc(100% + 6px)", [align]: 0, zIndex, width: 280, maxWidth: "calc(100vw - 32px)", display: "block", background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 10, boxShadow: "0 16px 44px rgba(11,13,17,.18)", padding: 8 }, children: /* @__PURE__ */ jsxs33("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
2679
2695
|
/* @__PURE__ */ jsx36("span", { className: "fd-overline fd-muted", style: { padding: "4px 8px 6px" }, children: "Sort by" }),
|
|
2680
2696
|
fields.map((f) => {
|
|
2681
2697
|
const active = cur && cur.key === f.key;
|
|
2682
|
-
return /* @__PURE__ */
|
|
2698
|
+
return /* @__PURE__ */ jsxs33("span", { className: "fd-row", style: { gap: 8, padding: "4px 8px", borderRadius: 7, background: active ? "var(--surface-brand)" : "transparent" }, children: [
|
|
2683
2699
|
/* @__PURE__ */ jsx36("span", { className: "fd-body-sm", style: { flex: 1, fontWeight: active ? 700 : 500, color: active ? "var(--text-on-surface-brand)" : "var(--text)" }, children: f.label }),
|
|
2684
2700
|
arrow(f, "asc"),
|
|
2685
2701
|
arrow(f, "desc")
|
|
@@ -2690,8 +2706,8 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
|
|
|
2690
2706
|
}
|
|
2691
2707
|
|
|
2692
2708
|
// src/components/data/StepList.tsx
|
|
2693
|
-
import * as
|
|
2694
|
-
import { jsx as jsx37, jsxs as
|
|
2709
|
+
import * as React16 from "react";
|
|
2710
|
+
import { jsx as jsx37, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2695
2711
|
var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
|
|
2696
2712
|
function StepList({
|
|
2697
2713
|
steps = [],
|
|
@@ -2703,9 +2719,9 @@ function StepList({
|
|
|
2703
2719
|
dense = false,
|
|
2704
2720
|
className = ""
|
|
2705
2721
|
}) {
|
|
2706
|
-
const [openState, setOpenState] =
|
|
2722
|
+
const [openState, setOpenState] = React16.useState(defaultOpen);
|
|
2707
2723
|
const open = openProp == null ? openState : openProp;
|
|
2708
|
-
const [expanded, setExpanded] =
|
|
2724
|
+
const [expanded, setExpanded] = React16.useState({});
|
|
2709
2725
|
if (!steps.length) return null;
|
|
2710
2726
|
const running = steps.some((s) => s.status === "running");
|
|
2711
2727
|
const failed = steps.filter((s) => s.status === "error").length;
|
|
@@ -2717,15 +2733,15 @@ function StepList({
|
|
|
2717
2733
|
if (openProp == null) setOpenState(next);
|
|
2718
2734
|
onToggle && onToggle(next);
|
|
2719
2735
|
};
|
|
2720
|
-
return /* @__PURE__ */
|
|
2721
|
-
/* @__PURE__ */
|
|
2736
|
+
return /* @__PURE__ */ jsxs34("div", { className: ["fd-steps", dense ? "is-dense" : "", open ? "is-open" : "", className].filter(Boolean).join(" "), children: [
|
|
2737
|
+
/* @__PURE__ */ jsxs34("button", { type: "button", className: "fd-steps-head", onClick: toggle, "aria-expanded": open, children: [
|
|
2722
2738
|
running ? /* @__PURE__ */ jsx37("span", { className: "fd-steps-spin", "aria-hidden": "true" }) : /* @__PURE__ */ jsx37("i", { className: "ph ph-" + (failed ? "warning-circle" : "check-circle"), "aria-hidden": "true" }),
|
|
2723
2739
|
/* @__PURE__ */ jsx37("span", { className: "fd-steps-title", children: summary }),
|
|
2724
|
-
/* @__PURE__ */
|
|
2740
|
+
/* @__PURE__ */ jsxs34("span", { className: "fd-steps-count fd-tabular", children: [
|
|
2725
2741
|
steps.length,
|
|
2726
2742
|
" step",
|
|
2727
2743
|
steps.length === 1 ? "" : "s",
|
|
2728
|
-
failed ? /* @__PURE__ */
|
|
2744
|
+
failed ? /* @__PURE__ */ jsxs34("span", { className: "fd-steps-failed", children: [
|
|
2729
2745
|
" \xB7 ",
|
|
2730
2746
|
failed,
|
|
2731
2747
|
" failed"
|
|
@@ -2737,10 +2753,10 @@ function StepList({
|
|
|
2737
2753
|
const id = s.id || i;
|
|
2738
2754
|
const isOpen = !!expanded[id];
|
|
2739
2755
|
const icon = KIND_ICON[s.kind || ""] || "dot-outline";
|
|
2740
|
-
return /* @__PURE__ */
|
|
2741
|
-
/* @__PURE__ */
|
|
2756
|
+
return /* @__PURE__ */ jsxs34("li", { className: "fd-step is-" + (s.status || "ok"), children: [
|
|
2757
|
+
/* @__PURE__ */ jsxs34("div", { className: "fd-step-row", children: [
|
|
2742
2758
|
/* @__PURE__ */ jsx37("span", { className: "fd-step-icon", "aria-hidden": "true", children: s.status === "running" ? /* @__PURE__ */ jsx37("span", { className: "fd-steps-spin" }) : /* @__PURE__ */ jsx37("i", { className: "ph ph-" + icon }) }),
|
|
2743
|
-
s.detail ? /* @__PURE__ */
|
|
2759
|
+
s.detail ? /* @__PURE__ */ jsxs34(
|
|
2744
2760
|
"button",
|
|
2745
2761
|
{
|
|
2746
2762
|
type: "button",
|
|
@@ -2763,8 +2779,8 @@ function StepList({
|
|
|
2763
2779
|
}
|
|
2764
2780
|
|
|
2765
2781
|
// src/components/data/VirtualList.tsx
|
|
2766
|
-
import * as
|
|
2767
|
-
import { jsx as jsx38, jsxs as
|
|
2782
|
+
import * as React17 from "react";
|
|
2783
|
+
import { jsx as jsx38, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2768
2784
|
var VIRTUAL_LIST_BUFFER_ROWS = 20;
|
|
2769
2785
|
var VIRTUAL_LIST_ROW_GAP = 6;
|
|
2770
2786
|
function computeVirtualWindow(opts) {
|
|
@@ -2815,35 +2831,35 @@ function VirtualList({
|
|
|
2815
2831
|
className = "",
|
|
2816
2832
|
style
|
|
2817
2833
|
}) {
|
|
2818
|
-
const [scrollTop, setScrollTop] =
|
|
2819
|
-
const loaded =
|
|
2834
|
+
const [scrollTop, setScrollTop] = React17.useState(0);
|
|
2835
|
+
const loaded = React17.useMemo(
|
|
2820
2836
|
() => ({ firstItemIndex, count: items.length }),
|
|
2821
2837
|
[firstItemIndex, items.length]
|
|
2822
2838
|
);
|
|
2823
2839
|
const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
|
|
2824
2840
|
const bandKey = firstItemIndex + ":" + items.length;
|
|
2825
|
-
const win =
|
|
2841
|
+
const win = React17.useMemo(
|
|
2826
2842
|
() => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
|
|
2827
2843
|
[scrollTop, height, itemHeight, total, loaded]
|
|
2828
2844
|
);
|
|
2829
|
-
const need =
|
|
2845
|
+
const need = React17.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
|
|
2830
2846
|
const wantStart = need.start && hasMore?.start !== false;
|
|
2831
2847
|
const wantEnd = need.end && hasMore?.end !== false;
|
|
2832
2848
|
const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
|
|
2833
2849
|
const askKey = bandKey + "@" + bucket2;
|
|
2834
|
-
const asked =
|
|
2835
|
-
|
|
2850
|
+
const asked = React17.useRef({ start: null, end: null });
|
|
2851
|
+
React17.useEffect(() => {
|
|
2836
2852
|
if (loading || !wantStart || asked.current.start === askKey) return;
|
|
2837
2853
|
asked.current.start = askKey;
|
|
2838
2854
|
onNeedMore("start", win);
|
|
2839
2855
|
}, [wantStart, loading, askKey, onNeedMore, win]);
|
|
2840
|
-
|
|
2856
|
+
React17.useEffect(() => {
|
|
2841
2857
|
if (loading || !wantEnd || asked.current.end === askKey) return;
|
|
2842
2858
|
asked.current.end = askKey;
|
|
2843
2859
|
onNeedMore("end", win);
|
|
2844
2860
|
}, [wantEnd, loading, askKey, onNeedMore, win]);
|
|
2845
|
-
const lastKeysRef =
|
|
2846
|
-
const newKeys =
|
|
2861
|
+
const lastKeysRef = React17.useRef(null);
|
|
2862
|
+
const newKeys = React17.useMemo(() => {
|
|
2847
2863
|
const prev = lastKeysRef.current;
|
|
2848
2864
|
if (!prev) return /* @__PURE__ */ new Set();
|
|
2849
2865
|
const fresh = /* @__PURE__ */ new Set();
|
|
@@ -2853,7 +2869,7 @@ function VirtualList({
|
|
|
2853
2869
|
}
|
|
2854
2870
|
return fresh;
|
|
2855
2871
|
}, [items]);
|
|
2856
|
-
|
|
2872
|
+
React17.useEffect(() => {
|
|
2857
2873
|
lastKeysRef.current = new Set(items.map(keyOf));
|
|
2858
2874
|
}, [items]);
|
|
2859
2875
|
const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
|
|
@@ -2877,8 +2893,8 @@ function VirtualList({
|
|
|
2877
2893
|
)
|
|
2878
2894
|
);
|
|
2879
2895
|
}
|
|
2880
|
-
return /* @__PURE__ */
|
|
2881
|
-
/* @__PURE__ */
|
|
2896
|
+
return /* @__PURE__ */ jsxs35("div", { className: ["fd-vlist-wrap", className].filter(Boolean).join(" "), style: { height, position: "relative", ...gapStyle, ...style }, children: [
|
|
2897
|
+
/* @__PURE__ */ jsxs35(
|
|
2882
2898
|
"div",
|
|
2883
2899
|
{
|
|
2884
2900
|
className: "fd-vlist fd-scrollbar",
|
|
@@ -2890,7 +2906,7 @@ function VirtualList({
|
|
|
2890
2906
|
]
|
|
2891
2907
|
}
|
|
2892
2908
|
),
|
|
2893
|
-
refreshing ? /* @__PURE__ */ jsx38("div", { className: "fd-vlist-refresh-scrim", children: /* @__PURE__ */
|
|
2909
|
+
refreshing ? /* @__PURE__ */ jsx38("div", { className: "fd-vlist-refresh-scrim", children: /* @__PURE__ */ jsxs35("div", { className: "fd-vlist-refresh-card", children: [
|
|
2894
2910
|
/* @__PURE__ */ jsx38("span", { className: "fd-spinner", "aria-hidden": "true" }),
|
|
2895
2911
|
/* @__PURE__ */ jsx38("span", { className: "fd-body-sm", children: refreshingLabel })
|
|
2896
2912
|
] }) }) : null
|
|
@@ -2898,8 +2914,8 @@ function VirtualList({
|
|
|
2898
2914
|
}
|
|
2899
2915
|
|
|
2900
2916
|
// src/components/data/EntityRow.tsx
|
|
2901
|
-
import * as
|
|
2902
|
-
import { jsx as jsx39, jsxs as
|
|
2917
|
+
import * as React18 from "react";
|
|
2918
|
+
import { jsx as jsx39, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
2903
2919
|
var ENTITY_ROW_METRIC_WIDTH = 74;
|
|
2904
2920
|
var METRIC_TONE_COLOR = {
|
|
2905
2921
|
default: "var(--text-2)",
|
|
@@ -2911,7 +2927,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
|
|
|
2911
2927
|
const key = m.id || m.label || i;
|
|
2912
2928
|
const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
|
|
2913
2929
|
const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
|
|
2914
|
-
const content = /* @__PURE__ */
|
|
2930
|
+
const content = /* @__PURE__ */ jsxs36(React18.Fragment, { children: [
|
|
2915
2931
|
m.icon ? /* @__PURE__ */ jsx39("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
|
|
2916
2932
|
/* @__PURE__ */ jsx39("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
|
|
2917
2933
|
/* @__PURE__ */ jsx39("span", { className: "fd-sr", children: " " + m.label })
|
|
@@ -2932,7 +2948,7 @@ function EntityRow({
|
|
|
2932
2948
|
className = ""
|
|
2933
2949
|
}) {
|
|
2934
2950
|
const hasStrip = metrics && metrics.length > 0 || accessory != null;
|
|
2935
|
-
return /* @__PURE__ */
|
|
2951
|
+
return /* @__PURE__ */ jsxs36(
|
|
2936
2952
|
"div",
|
|
2937
2953
|
{
|
|
2938
2954
|
onPointerDown,
|
|
@@ -2951,12 +2967,12 @@ function EntityRow({
|
|
|
2951
2967
|
},
|
|
2952
2968
|
children: [
|
|
2953
2969
|
draggable ? /* @__PURE__ */ jsx39("i", { className: "ph ph-dots-six-vertical", "aria-hidden": "true", style: { fontSize: 14, flex: "none", color: "var(--text-muted)" } }) : null,
|
|
2954
|
-
/* @__PURE__ */
|
|
2955
|
-
/* @__PURE__ */
|
|
2970
|
+
/* @__PURE__ */ jsxs36("span", { className: "fd-erow-body", children: [
|
|
2971
|
+
/* @__PURE__ */ jsxs36("span", { className: "fd-erow-titleline", children: [
|
|
2956
2972
|
/* @__PURE__ */ jsx39("span", { className: "fd-erow-title fd-body-sm", children: title }),
|
|
2957
2973
|
meta ? /* @__PURE__ */ jsx39("span", { className: "fd-erow-meta", children: meta }) : null
|
|
2958
2974
|
] }),
|
|
2959
|
-
hasStrip ? /* @__PURE__ */
|
|
2975
|
+
hasStrip ? /* @__PURE__ */ jsxs36("span", { className: "fd-erow-strip", children: [
|
|
2960
2976
|
metrics && metrics.length ? /* @__PURE__ */ jsx39(EntityRowMetrics, { metrics }) : null,
|
|
2961
2977
|
accessory ? /* @__PURE__ */ jsx39("span", { className: "fd-erow-accessory", children: accessory }) : null
|
|
2962
2978
|
] }) : null
|
|
@@ -2979,18 +2995,18 @@ function EntityRow({
|
|
|
2979
2995
|
}
|
|
2980
2996
|
|
|
2981
2997
|
// src/components/data/TransferList.tsx
|
|
2982
|
-
import * as
|
|
2998
|
+
import * as React20 from "react";
|
|
2983
2999
|
import { createPortal as createPortal4 } from "react-dom";
|
|
2984
3000
|
|
|
2985
3001
|
// src/components/forms/field.tsx
|
|
2986
|
-
import * as
|
|
2987
|
-
import { jsx as jsx40, jsxs as
|
|
3002
|
+
import * as React19 from "react";
|
|
3003
|
+
import { jsx as jsx40, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
2988
3004
|
function useFieldId(id) {
|
|
2989
|
-
const generated =
|
|
3005
|
+
const generated = React19.useId();
|
|
2990
3006
|
return id || generated;
|
|
2991
3007
|
}
|
|
2992
3008
|
function FieldLabel({ htmlFor, id, required = false, onClick, children }) {
|
|
2993
|
-
return /* @__PURE__ */
|
|
3009
|
+
return /* @__PURE__ */ jsxs37("label", { className: "fd-field-label", htmlFor, id, onClick, children: [
|
|
2994
3010
|
children,
|
|
2995
3011
|
required ? /* @__PURE__ */ jsx40("span", { className: "fd-field-req", "aria-hidden": "true", children: "*" }) : null
|
|
2996
3012
|
] });
|
|
@@ -3002,7 +3018,7 @@ function useTriggerLabelling(label, id) {
|
|
|
3002
3018
|
}
|
|
3003
3019
|
|
|
3004
3020
|
// src/components/forms/Input.tsx
|
|
3005
|
-
import { jsx as jsx41, jsxs as
|
|
3021
|
+
import { jsx as jsx41, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
3006
3022
|
function Input({
|
|
3007
3023
|
label,
|
|
3008
3024
|
help,
|
|
@@ -3029,16 +3045,16 @@ function Input({
|
|
|
3029
3045
|
disabled ? "fd-input-disabled" : "",
|
|
3030
3046
|
size === "lg" ? "fd-input-lg" : ""
|
|
3031
3047
|
].filter(Boolean).join(" ");
|
|
3032
|
-
return /* @__PURE__ */
|
|
3048
|
+
return /* @__PURE__ */ jsxs38("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
|
|
3033
3049
|
label ? /* @__PURE__ */ jsx41(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
|
|
3034
|
-
/* @__PURE__ */
|
|
3050
|
+
/* @__PURE__ */ jsxs38("div", { className: box, children: [
|
|
3035
3051
|
icon ? /* @__PURE__ */ jsx41("span", { className: "fd-input-icon", children: /* @__PURE__ */ jsx41("i", { className: "ph ph-" + icon, "aria-hidden": "true" }) }) : null,
|
|
3036
3052
|
prefix ? /* @__PURE__ */ jsx41("span", { className: "fd-input-affix", children: prefix }) : null,
|
|
3037
3053
|
/* @__PURE__ */ jsx41("input", { id: fieldId, disabled, style: inputStyle, "aria-invalid": error ? "true" : void 0, ...rest }),
|
|
3038
3054
|
loading ? /* @__PURE__ */ jsx41("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading" }) : null,
|
|
3039
3055
|
suffix && !loading ? /* @__PURE__ */ jsx41("span", { className: "fd-input-affix", children: suffix }) : null
|
|
3040
3056
|
] }),
|
|
3041
|
-
error ? /* @__PURE__ */
|
|
3057
|
+
error ? /* @__PURE__ */ jsxs38("span", { className: "fd-field-error", children: [
|
|
3042
3058
|
/* @__PURE__ */ jsx41("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3043
3059
|
error
|
|
3044
3060
|
] }) : help ? /* @__PURE__ */ jsx41("span", { className: "fd-field-help", children: help }) : null
|
|
@@ -3090,7 +3106,7 @@ function SearchField({
|
|
|
3090
3106
|
}
|
|
3091
3107
|
|
|
3092
3108
|
// src/components/data/TransferList.tsx
|
|
3093
|
-
import { jsx as jsx43, jsxs as
|
|
3109
|
+
import { jsx as jsx43, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
3094
3110
|
var emptyHasMore = {};
|
|
3095
3111
|
var DRAG_THRESHOLD_PX = 5;
|
|
3096
3112
|
function TransferList({
|
|
@@ -3104,12 +3120,12 @@ function TransferList({
|
|
|
3104
3120
|
listHeight = 440,
|
|
3105
3121
|
className = ""
|
|
3106
3122
|
}) {
|
|
3107
|
-
const [drag, setDrag] =
|
|
3108
|
-
const [dragOverSide, setDragOverSide] =
|
|
3109
|
-
const dragRef =
|
|
3110
|
-
const armedRef =
|
|
3111
|
-
const sideRefs =
|
|
3112
|
-
const hitTestSide =
|
|
3123
|
+
const [drag, setDrag] = React20.useState(null);
|
|
3124
|
+
const [dragOverSide, setDragOverSide] = React20.useState(null);
|
|
3125
|
+
const dragRef = React20.useRef(null);
|
|
3126
|
+
const armedRef = React20.useRef(null);
|
|
3127
|
+
const sideRefs = React20.useRef({ left: null, right: null });
|
|
3128
|
+
const hitTestSide = React20.useCallback((x, y) => {
|
|
3113
3129
|
for (const side of ["left", "right"]) {
|
|
3114
3130
|
const el = sideRefs.current[side];
|
|
3115
3131
|
if (!el) continue;
|
|
@@ -3118,7 +3134,7 @@ function TransferList({
|
|
|
3118
3134
|
}
|
|
3119
3135
|
return null;
|
|
3120
3136
|
}, []);
|
|
3121
|
-
const findItem =
|
|
3137
|
+
const findItem = React20.useCallback(
|
|
3122
3138
|
(side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
|
|
3123
3139
|
[left.items, right.items, keyOf]
|
|
3124
3140
|
);
|
|
@@ -3140,7 +3156,7 @@ function TransferList({
|
|
|
3140
3156
|
height: rect.height
|
|
3141
3157
|
};
|
|
3142
3158
|
};
|
|
3143
|
-
|
|
3159
|
+
React20.useEffect(() => {
|
|
3144
3160
|
const onMovePointer = (e) => {
|
|
3145
3161
|
const armed = armedRef.current;
|
|
3146
3162
|
if (!armed || e.pointerId !== armed.pointerId) return;
|
|
@@ -3193,7 +3209,7 @@ function TransferList({
|
|
|
3193
3209
|
window.removeEventListener("pointercancel", endDrag);
|
|
3194
3210
|
};
|
|
3195
3211
|
}, [hitTestSide, findItem, onMove]);
|
|
3196
|
-
|
|
3212
|
+
React20.useEffect(() => {
|
|
3197
3213
|
if (!drag || typeof document === "undefined") return;
|
|
3198
3214
|
const prev = document.body.style.userSelect;
|
|
3199
3215
|
document.body.style.userSelect = "none";
|
|
@@ -3203,7 +3219,7 @@ function TransferList({
|
|
|
3203
3219
|
}, [drag]);
|
|
3204
3220
|
const renderSide = (side, cfg, opposite) => {
|
|
3205
3221
|
const showOverlay = drag != null && dragOverSide === side;
|
|
3206
|
-
return /* @__PURE__ */
|
|
3222
|
+
return /* @__PURE__ */ jsxs39(
|
|
3207
3223
|
"div",
|
|
3208
3224
|
{
|
|
3209
3225
|
ref: (el) => {
|
|
@@ -3211,12 +3227,12 @@ function TransferList({
|
|
|
3211
3227
|
},
|
|
3212
3228
|
className: ["fd-tlist-side", dragOverSide === side ? "is-drop-target" : ""].filter(Boolean).join(" "),
|
|
3213
3229
|
children: [
|
|
3214
|
-
cfg.label ? /* @__PURE__ */
|
|
3230
|
+
cfg.label ? /* @__PURE__ */ jsxs39("span", { className: "fd-overline fd-muted", children: [
|
|
3215
3231
|
cfg.label,
|
|
3216
3232
|
cfg.total != null ? " (" + cfg.total.toLocaleString() + ")" : ""
|
|
3217
3233
|
] }) : null,
|
|
3218
3234
|
cfg.header ? /* @__PURE__ */ jsx43("div", { className: "fd-tlist-header", children: cfg.header }) : null,
|
|
3219
|
-
/* @__PURE__ */
|
|
3235
|
+
/* @__PURE__ */ jsxs39("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
3220
3236
|
/* @__PURE__ */ jsx43(SearchField, { value: cfg.search, onChange: cfg.onSearchChange, placeholder: "Search", "aria-label": (cfg.label || side) + " search", style: { flex: 1 } }),
|
|
3221
3237
|
/* @__PURE__ */ jsx43(SortMenu, { fields: cfg.sortFields, sort: cfg.sort, onSort: cfg.onSort, align: side === "left" ? "left" : "right" })
|
|
3222
3238
|
] }),
|
|
@@ -3263,7 +3279,7 @@ function TransferList({
|
|
|
3263
3279
|
}
|
|
3264
3280
|
),
|
|
3265
3281
|
cfg.footer ? /* @__PURE__ */ jsx43("div", { className: "fd-tlist-footer", children: cfg.footer }) : null,
|
|
3266
|
-
showOverlay ? /* @__PURE__ */ jsx43("div", { className: "fd-tlist-drop-overlay", "aria-hidden": "true", children: /* @__PURE__ */
|
|
3282
|
+
showOverlay ? /* @__PURE__ */ jsx43("div", { className: "fd-tlist-drop-overlay", "aria-hidden": "true", children: /* @__PURE__ */ jsxs39("span", { className: "fd-tlist-drop-card", children: [
|
|
3267
3283
|
/* @__PURE__ */ jsx43("i", { className: "ph ph-tray-arrow-down", style: { fontSize: 18 }, "aria-hidden": "true" }),
|
|
3268
3284
|
/* @__PURE__ */ jsx43("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: cfg.dropLabel || "Drop here" + (cfg.label ? " \u2014 " + cfg.label : "") })
|
|
3269
3285
|
] }) }) : null
|
|
@@ -3271,8 +3287,8 @@ function TransferList({
|
|
|
3271
3287
|
}
|
|
3272
3288
|
);
|
|
3273
3289
|
};
|
|
3274
|
-
return /* @__PURE__ */
|
|
3275
|
-
/* @__PURE__ */
|
|
3290
|
+
return /* @__PURE__ */ jsxs39("div", { className: ["fd-tlist", className].filter(Boolean).join(" "), children: [
|
|
3291
|
+
/* @__PURE__ */ jsxs39("div", { className: "fd-tlist-panes", children: [
|
|
3276
3292
|
renderSide("left", left, "right"),
|
|
3277
3293
|
renderSide("right", right, "left")
|
|
3278
3294
|
] }),
|
|
@@ -3301,19 +3317,19 @@ function TransferList({
|
|
|
3301
3317
|
}
|
|
3302
3318
|
|
|
3303
3319
|
// src/components/forms/Checkbox.tsx
|
|
3304
|
-
import * as
|
|
3305
|
-
import { jsx as jsx44, jsxs as
|
|
3320
|
+
import * as React21 from "react";
|
|
3321
|
+
import { jsx as jsx44, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
3306
3322
|
function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
|
|
3307
|
-
const ref =
|
|
3308
|
-
|
|
3323
|
+
const ref = React21.useRef(null);
|
|
3324
|
+
React21.useEffect(() => {
|
|
3309
3325
|
if (ref.current) ref.current.indeterminate = indeterminate;
|
|
3310
3326
|
}, [indeterminate]);
|
|
3311
|
-
return /* @__PURE__ */
|
|
3312
|
-
/* @__PURE__ */
|
|
3327
|
+
return /* @__PURE__ */ jsxs40("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
3328
|
+
/* @__PURE__ */ jsxs40("span", { className: "fd-choice-input", children: [
|
|
3313
3329
|
/* @__PURE__ */ jsx44("input", { ref, type: "checkbox", ...rest }),
|
|
3314
3330
|
/* @__PURE__ */ jsx44("span", { className: "fd-choice-box", "aria-hidden": "true", children: /* @__PURE__ */ jsx44("i", { className: indeterminate ? "ph ph-minus" : "ph ph-check" }) })
|
|
3315
3331
|
] }),
|
|
3316
|
-
/* @__PURE__ */
|
|
3332
|
+
/* @__PURE__ */ jsxs40("span", { className: "fd-choice-text", children: [
|
|
3317
3333
|
/* @__PURE__ */ jsx44("span", { className: "fd-choice-title", children: label }),
|
|
3318
3334
|
description ? /* @__PURE__ */ jsx44("span", { className: "fd-choice-desc", children: description }) : null
|
|
3319
3335
|
] })
|
|
@@ -3321,14 +3337,14 @@ function Checkbox({ label, description, card = false, indeterminate = false, cla
|
|
|
3321
3337
|
}
|
|
3322
3338
|
|
|
3323
3339
|
// src/components/forms/Radio.tsx
|
|
3324
|
-
import { jsx as jsx45, jsxs as
|
|
3340
|
+
import { jsx as jsx45, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
3325
3341
|
function Radio({ label, description, card = false, className = "", ...rest }) {
|
|
3326
|
-
return /* @__PURE__ */
|
|
3327
|
-
/* @__PURE__ */
|
|
3342
|
+
return /* @__PURE__ */ jsxs41("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
3343
|
+
/* @__PURE__ */ jsxs41("span", { className: "fd-choice-input", children: [
|
|
3328
3344
|
/* @__PURE__ */ jsx45("input", { type: "radio", ...rest }),
|
|
3329
3345
|
/* @__PURE__ */ jsx45("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ jsx45("span", { className: "fd-choice-dot" }) })
|
|
3330
3346
|
] }),
|
|
3331
|
-
/* @__PURE__ */
|
|
3347
|
+
/* @__PURE__ */ jsxs41("span", { className: "fd-choice-text", children: [
|
|
3332
3348
|
/* @__PURE__ */ jsx45("span", { className: "fd-choice-title", children: label }),
|
|
3333
3349
|
description ? /* @__PURE__ */ jsx45("span", { className: "fd-choice-desc", children: description }) : null
|
|
3334
3350
|
] })
|
|
@@ -3336,12 +3352,12 @@ function Radio({ label, description, card = false, className = "", ...rest }) {
|
|
|
3336
3352
|
}
|
|
3337
3353
|
|
|
3338
3354
|
// src/components/forms/Switch.tsx
|
|
3339
|
-
import { jsx as jsx46, jsxs as
|
|
3355
|
+
import { jsx as jsx46, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
3340
3356
|
function Switch({ label, description, className = "", ...rest }) {
|
|
3341
|
-
return /* @__PURE__ */
|
|
3357
|
+
return /* @__PURE__ */ jsxs42("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
|
|
3342
3358
|
/* @__PURE__ */ jsx46("input", { type: "checkbox", role: "switch", ...rest }),
|
|
3343
3359
|
/* @__PURE__ */ jsx46("span", { className: "fd-switch-track", children: /* @__PURE__ */ jsx46("span", { className: "fd-switch-thumb" }) }),
|
|
3344
|
-
label ? /* @__PURE__ */
|
|
3360
|
+
label ? /* @__PURE__ */ jsxs42("span", { className: "fd-choice-text", children: [
|
|
3345
3361
|
/* @__PURE__ */ jsx46("span", { className: "fd-switch-label", children: label }),
|
|
3346
3362
|
description ? /* @__PURE__ */ jsx46("span", { className: "fd-choice-desc", children: description }) : null
|
|
3347
3363
|
] }) : null
|
|
@@ -3349,14 +3365,14 @@ function Switch({ label, description, className = "", ...rest }) {
|
|
|
3349
3365
|
}
|
|
3350
3366
|
|
|
3351
3367
|
// src/components/forms/Textarea.tsx
|
|
3352
|
-
import { jsx as jsx47, jsxs as
|
|
3368
|
+
import { jsx as jsx47, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
3353
3369
|
function Textarea({ label, help, error, required = false, rows = 4, disabled = false, id, className = "", style, ...rest }) {
|
|
3354
3370
|
const fieldId = useFieldId(id);
|
|
3355
3371
|
const box = ["fd-input", "fd-input-textarea", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
3356
|
-
return /* @__PURE__ */
|
|
3372
|
+
return /* @__PURE__ */ jsxs43("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
|
|
3357
3373
|
label ? /* @__PURE__ */ jsx47(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
|
|
3358
3374
|
/* @__PURE__ */ jsx47("div", { className: box, children: /* @__PURE__ */ jsx47("textarea", { id: fieldId, rows, disabled, "aria-invalid": error ? "true" : void 0, ...rest }) }),
|
|
3359
|
-
error ? /* @__PURE__ */
|
|
3375
|
+
error ? /* @__PURE__ */ jsxs43("span", { className: "fd-field-error", children: [
|
|
3360
3376
|
/* @__PURE__ */ jsx47("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3361
3377
|
error
|
|
3362
3378
|
] }) : help ? /* @__PURE__ */ jsx47("span", { className: "fd-field-help", children: help }) : null
|
|
@@ -3364,8 +3380,8 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
|
|
|
3364
3380
|
}
|
|
3365
3381
|
|
|
3366
3382
|
// src/components/forms/NumberInput.tsx
|
|
3367
|
-
import * as
|
|
3368
|
-
import { jsx as jsx48, jsxs as
|
|
3383
|
+
import * as React22 from "react";
|
|
3384
|
+
import { jsx as jsx48, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
3369
3385
|
function NumberInput({
|
|
3370
3386
|
label,
|
|
3371
3387
|
help,
|
|
@@ -3392,10 +3408,10 @@ function NumberInput({
|
|
|
3392
3408
|
const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
|
|
3393
3409
|
return isNaN(n) ? null : n;
|
|
3394
3410
|
};
|
|
3395
|
-
const [text, setText] =
|
|
3396
|
-
const [editing, setEditing] =
|
|
3397
|
-
const timer =
|
|
3398
|
-
|
|
3411
|
+
const [text, setText] = React22.useState(value == null || value === "" ? "" : String(value));
|
|
3412
|
+
const [editing, setEditing] = React22.useState(false);
|
|
3413
|
+
const timer = React22.useRef(null);
|
|
3414
|
+
React22.useEffect(() => {
|
|
3399
3415
|
if (!editing) setText(value == null || value === "" ? "" : String(value));
|
|
3400
3416
|
}, [value, editing]);
|
|
3401
3417
|
const clamp = (n) => Math.min(max, Math.max(min, n));
|
|
@@ -3419,7 +3435,7 @@ function NumberInput({
|
|
|
3419
3435
|
const release = () => {
|
|
3420
3436
|
if (timer.current) clearTimeout(timer.current);
|
|
3421
3437
|
};
|
|
3422
|
-
|
|
3438
|
+
React22.useEffect(() => () => {
|
|
3423
3439
|
if (timer.current) clearTimeout(timer.current);
|
|
3424
3440
|
}, []);
|
|
3425
3441
|
const shown = editing ? text : (() => {
|
|
@@ -3429,9 +3445,9 @@ function NumberInput({
|
|
|
3429
3445
|
const box = ["fd-input", "fd-input-num", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
3430
3446
|
const fieldName = label || ariaLabel;
|
|
3431
3447
|
const stepperName = (verb) => fieldName ? verb + " " + fieldName : verb;
|
|
3432
|
-
return /* @__PURE__ */
|
|
3448
|
+
return /* @__PURE__ */ jsxs44("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
|
|
3433
3449
|
label ? /* @__PURE__ */ jsx48(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
|
|
3434
|
-
/* @__PURE__ */
|
|
3450
|
+
/* @__PURE__ */ jsxs44("div", { className: box, style: { gap: 8 }, children: [
|
|
3435
3451
|
prefix ? /* @__PURE__ */ jsx48("span", { className: "fd-input-affix", children: prefix }) : null,
|
|
3436
3452
|
/* @__PURE__ */ jsx48(
|
|
3437
3453
|
"input",
|
|
@@ -3469,7 +3485,7 @@ function NumberInput({
|
|
|
3469
3485
|
}
|
|
3470
3486
|
),
|
|
3471
3487
|
suffix ? /* @__PURE__ */ jsx48("span", { className: "fd-input-affix", children: suffix }) : null,
|
|
3472
|
-
/* @__PURE__ */
|
|
3488
|
+
/* @__PURE__ */ jsxs44("span", { className: "fd-row", style: { gap: 4, flex: "none" }, children: [
|
|
3473
3489
|
/* @__PURE__ */ jsx48(
|
|
3474
3490
|
"button",
|
|
3475
3491
|
{
|
|
@@ -3498,7 +3514,7 @@ function NumberInput({
|
|
|
3498
3514
|
)
|
|
3499
3515
|
] })
|
|
3500
3516
|
] }),
|
|
3501
|
-
error ? /* @__PURE__ */
|
|
3517
|
+
error ? /* @__PURE__ */ jsxs44("span", { className: "fd-field-error", children: [
|
|
3502
3518
|
/* @__PURE__ */ jsx48("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3503
3519
|
error
|
|
3504
3520
|
] }) : help ? /* @__PURE__ */ jsx48("span", { className: "fd-field-help", children: help }) : null
|
|
@@ -3506,8 +3522,8 @@ function NumberInput({
|
|
|
3506
3522
|
}
|
|
3507
3523
|
|
|
3508
3524
|
// src/components/forms/Select.tsx
|
|
3509
|
-
import * as
|
|
3510
|
-
import { jsx as jsx49, jsxs as
|
|
3525
|
+
import * as React23 from "react";
|
|
3526
|
+
import { jsx as jsx49, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
3511
3527
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
3512
3528
|
function Select({
|
|
3513
3529
|
label,
|
|
@@ -3533,13 +3549,13 @@ function Select({
|
|
|
3533
3549
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
3534
3550
|
const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
|
|
3535
3551
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
3536
|
-
const [open, setOpen] =
|
|
3537
|
-
const [q, setQ] =
|
|
3538
|
-
const [active, setActive] =
|
|
3539
|
-
const rootRef =
|
|
3540
|
-
const boxRef =
|
|
3541
|
-
const listRef =
|
|
3542
|
-
const typeBuf =
|
|
3552
|
+
const [open, setOpen] = React23.useState(false);
|
|
3553
|
+
const [q, setQ] = React23.useState("");
|
|
3554
|
+
const [active, setActive] = React23.useState(-1);
|
|
3555
|
+
const rootRef = React23.useRef(null);
|
|
3556
|
+
const boxRef = React23.useRef(null);
|
|
3557
|
+
const listRef = React23.useRef(null);
|
|
3558
|
+
const typeBuf = React23.useRef({ s: "", t: 0 });
|
|
3543
3559
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
3544
3560
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
3545
3561
|
const boxText = multiple ? chosen.length === 0 ? placeholder : chosen.length === 1 ? chosen[0].label : summary ? summary(chosen.map((o) => o.value)) : chosen.length + " selected" : selected ? selected.label : placeholder;
|
|
@@ -3564,7 +3580,7 @@ function Select({
|
|
|
3564
3580
|
}
|
|
3565
3581
|
setOpen(!open);
|
|
3566
3582
|
};
|
|
3567
|
-
|
|
3583
|
+
React23.useEffect(() => {
|
|
3568
3584
|
if (!open || active < 0 || !listRef.current) return;
|
|
3569
3585
|
const el = listRef.current.querySelector('[data-i="' + active + '"]');
|
|
3570
3586
|
if (el) {
|
|
@@ -3617,10 +3633,10 @@ function Select({
|
|
|
3617
3633
|
else last.items.push({ o, i });
|
|
3618
3634
|
});
|
|
3619
3635
|
const box = ["fd-input", "fd-select", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
3620
|
-
return /* @__PURE__ */
|
|
3636
|
+
return /* @__PURE__ */ jsxs45("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
3621
3637
|
label ? /* @__PURE__ */ jsx49(FieldLabel, { id: labelId, required, onClick: toggle, children: label }) : null,
|
|
3622
|
-
/* @__PURE__ */
|
|
3623
|
-
/* @__PURE__ */
|
|
3638
|
+
/* @__PURE__ */ jsxs45("div", { className: box, style: { cursor: disabled ? "not-allowed" : "pointer" }, ref: boxRef, children: [
|
|
3639
|
+
/* @__PURE__ */ jsxs45(
|
|
3624
3640
|
"button",
|
|
3625
3641
|
{
|
|
3626
3642
|
type: "button",
|
|
@@ -3668,7 +3684,7 @@ function Select({
|
|
|
3668
3684
|
minWidth: 260,
|
|
3669
3685
|
role: "presentation",
|
|
3670
3686
|
style: { maxWidth: 380 },
|
|
3671
|
-
header: hasSearch ? /* @__PURE__ */
|
|
3687
|
+
header: hasSearch ? /* @__PURE__ */ jsxs45("div", { className: "fd-pop-search", children: [
|
|
3672
3688
|
/* @__PURE__ */ jsx49("i", { className: "ph ph-magnifying-glass", style: { color: "var(--text-muted)", fontSize: 14 } }),
|
|
3673
3689
|
/* @__PURE__ */ jsx49(
|
|
3674
3690
|
"input",
|
|
@@ -3685,7 +3701,7 @@ function Select({
|
|
|
3685
3701
|
),
|
|
3686
3702
|
q ? /* @__PURE__ */ jsx49("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
3687
3703
|
] }) : void 0,
|
|
3688
|
-
footer: multiple ? /* @__PURE__ */
|
|
3704
|
+
footer: multiple ? /* @__PURE__ */ jsxs45(React23.Fragment, { children: [
|
|
3689
3705
|
/* @__PURE__ */ jsx49(
|
|
3690
3706
|
"button",
|
|
3691
3707
|
{
|
|
@@ -3696,7 +3712,7 @@ function Select({
|
|
|
3696
3712
|
}
|
|
3697
3713
|
),
|
|
3698
3714
|
/* @__PURE__ */ jsx49("span", { style: { flex: 1 } }),
|
|
3699
|
-
/* @__PURE__ */
|
|
3715
|
+
/* @__PURE__ */ jsxs45("span", { className: "fd-body-sm fd-muted", children: [
|
|
3700
3716
|
vals.length,
|
|
3701
3717
|
" of ",
|
|
3702
3718
|
opts.length
|
|
@@ -3712,13 +3728,13 @@ function Select({
|
|
|
3712
3728
|
}
|
|
3713
3729
|
)
|
|
3714
3730
|
] }) : void 0,
|
|
3715
|
-
children: /* @__PURE__ */ jsx49("div", { className: "fd-pop-list", role: "listbox", "aria-multiselectable": multiple || void 0, ref: listRef, children: visible.length === 0 ? /* @__PURE__ */
|
|
3731
|
+
children: /* @__PURE__ */ jsx49("div", { className: "fd-pop-list", role: "listbox", "aria-multiselectable": multiple || void 0, ref: listRef, children: visible.length === 0 ? /* @__PURE__ */ jsxs45("div", { className: "fd-pop-empty", children: [
|
|
3716
3732
|
'Nothing matches "',
|
|
3717
3733
|
q,
|
|
3718
3734
|
'".'
|
|
3719
|
-
] }) : groups.map((grp) => /* @__PURE__ */
|
|
3735
|
+
] }) : groups.map((grp) => /* @__PURE__ */ jsxs45(React23.Fragment, { children: [
|
|
3720
3736
|
grp.g ? /* @__PURE__ */ jsx49("div", { className: "fd-pop-group", children: grp.g }) : null,
|
|
3721
|
-
grp.items.map(({ o, i }) => /* @__PURE__ */
|
|
3737
|
+
grp.items.map(({ o, i }) => /* @__PURE__ */ jsxs45(
|
|
3722
3738
|
"button",
|
|
3723
3739
|
{
|
|
3724
3740
|
type: "button",
|
|
@@ -3732,7 +3748,7 @@ function Select({
|
|
|
3732
3748
|
children: [
|
|
3733
3749
|
multiple ? /* @__PURE__ */ jsx49("span", { "aria-hidden": "true", style: { flex: "none", display: "grid", placeItems: "center", width: 16, height: 16, borderRadius: 4, border: "1.5px solid " + (isOn(o.value) ? "var(--brand)" : "var(--border-strong, var(--border))"), background: isOn(o.value) ? "var(--brand)" : "var(--surface)", color: "#fff" }, children: isOn(o.value) ? /* @__PURE__ */ jsx49("i", { className: "ph ph-check", style: { fontSize: 11 } }) : null }) : null,
|
|
3734
3750
|
o.icon ? /* @__PURE__ */ jsx49("span", { className: "fd-opt-icon", children: /* @__PURE__ */ jsx49("i", { className: "ph ph-" + o.icon }) }) : null,
|
|
3735
|
-
/* @__PURE__ */
|
|
3751
|
+
/* @__PURE__ */ jsxs45("span", { style: { flex: 1, minWidth: 0 }, children: [
|
|
3736
3752
|
/* @__PURE__ */ jsx49("span", { className: "fd-opt-label", children: o.label }),
|
|
3737
3753
|
o.description ? /* @__PURE__ */ jsx49("span", { className: "fd-opt-desc", children: o.description }) : null
|
|
3738
3754
|
] }),
|
|
@@ -3745,7 +3761,7 @@ function Select({
|
|
|
3745
3761
|
] }, grp.g || "_")) })
|
|
3746
3762
|
}
|
|
3747
3763
|
),
|
|
3748
|
-
error ? /* @__PURE__ */
|
|
3764
|
+
error ? /* @__PURE__ */ jsxs45("span", { className: "fd-field-error", children: [
|
|
3749
3765
|
/* @__PURE__ */ jsx49("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3750
3766
|
error
|
|
3751
3767
|
] }) : help ? /* @__PURE__ */ jsx49("span", { className: "fd-field-help", children: help }) : null
|
|
@@ -3753,8 +3769,8 @@ function Select({
|
|
|
3753
3769
|
}
|
|
3754
3770
|
|
|
3755
3771
|
// src/components/forms/DatePicker.tsx
|
|
3756
|
-
import * as
|
|
3757
|
-
import { jsx as jsx50, jsxs as
|
|
3772
|
+
import * as React24 from "react";
|
|
3773
|
+
import { jsx as jsx50, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
3758
3774
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
3759
3775
|
var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
3760
3776
|
var iso = (d) => d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
|
|
@@ -3771,10 +3787,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3771
3787
|
const today = /* @__PURE__ */ new Date();
|
|
3772
3788
|
const sel = range ? value || {} : { start: value, end: value };
|
|
3773
3789
|
const anchor = parse(sel.start) || parse(initialMonth) || today;
|
|
3774
|
-
const [vy, setVy] =
|
|
3775
|
-
const [vm, setVm] =
|
|
3776
|
-
const [mode2, setMode] =
|
|
3777
|
-
const [hover, setHover] =
|
|
3790
|
+
const [vy, setVy] = React24.useState(anchor.getFullYear());
|
|
3791
|
+
const [vm, setVm] = React24.useState(anchor.getMonth());
|
|
3792
|
+
const [mode2, setMode] = React24.useState("days");
|
|
3793
|
+
const [hover, setHover] = React24.useState(null);
|
|
3778
3794
|
const s = parse(sel.start), e = parse(sel.end);
|
|
3779
3795
|
const hoverEnd = range && s && !e && hover ? parse(hover) : null;
|
|
3780
3796
|
const inRange = (d) => {
|
|
@@ -3811,7 +3827,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3811
3827
|
const startPad = new Date(y, m, 1).getDay();
|
|
3812
3828
|
const cells = [];
|
|
3813
3829
|
for (let i = 0; i < 42; i++) cells.push(new Date(y, m, i - startPad + 1));
|
|
3814
|
-
return /* @__PURE__ */
|
|
3830
|
+
return /* @__PURE__ */ jsxs46("div", { className: "fd-cal-grid", style: { width: months > 1 ? 252 : "auto", flex: "none" }, onMouseLeave: () => setHover(null), children: [
|
|
3815
3831
|
DOW.map((d) => /* @__PURE__ */ jsx50("span", { className: "fd-cal-dow", children: d }, d)),
|
|
3816
3832
|
cells.map((d, i) => /* @__PURE__ */ jsx50(
|
|
3817
3833
|
"button",
|
|
@@ -3827,17 +3843,17 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3827
3843
|
] });
|
|
3828
3844
|
};
|
|
3829
3845
|
const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
|
|
3830
|
-
return /* @__PURE__ */
|
|
3831
|
-
/* @__PURE__ */
|
|
3846
|
+
return /* @__PURE__ */ jsxs46("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, children: [
|
|
3847
|
+
/* @__PURE__ */ jsxs46("div", { className: "fd-cal-head", children: [
|
|
3832
3848
|
/* @__PURE__ */ jsx50("button", { type: "button", className: "fd-btn-icon", "aria-label": "Previous", onClick: () => mode2 === "years" ? setVy(vy - 12) : mode2 === "months" ? setVy(vy - 1) : nav(-1), children: /* @__PURE__ */ jsx50("i", { className: "ph ph-caret-left" }) }),
|
|
3833
|
-
/* @__PURE__ */
|
|
3849
|
+
/* @__PURE__ */ jsxs46("button", { type: "button", className: "fd-cal-title", onClick: () => setMode(mode2 === "days" ? "months" : mode2 === "months" ? "years" : "days"), children: [
|
|
3834
3850
|
mode2 === "days" ? MONTHS[vm] + " " + vy : mode2 === "months" ? vy : vy - 5 + " \u2013 " + (vy + 6),
|
|
3835
3851
|
/* @__PURE__ */ jsx50("i", { className: "ph ph-caret-down", style: { fontSize: 10, marginLeft: 6, color: "var(--text-muted)" } })
|
|
3836
3852
|
] }),
|
|
3837
3853
|
months > 1 && mode2 === "days" ? /* @__PURE__ */ jsx50("span", { className: "fd-cal-title", style: { cursor: "default", background: "none" }, children: MONTHS[nextM] + " " + nextY }) : null,
|
|
3838
3854
|
/* @__PURE__ */ jsx50("button", { type: "button", className: "fd-btn-icon", "aria-label": "Next", onClick: () => mode2 === "years" ? setVy(vy + 12) : mode2 === "months" ? setVy(vy + 1) : nav(1), children: /* @__PURE__ */ jsx50("i", { className: "ph ph-caret-right" }) })
|
|
3839
3855
|
] }),
|
|
3840
|
-
mode2 === "days" ? /* @__PURE__ */
|
|
3856
|
+
mode2 === "days" ? /* @__PURE__ */ jsxs46("div", { style: { display: "flex", gap: 18 }, children: [
|
|
3841
3857
|
monthGrid(vy, vm),
|
|
3842
3858
|
months > 1 ? monthGrid(nextY, nextM) : null
|
|
3843
3859
|
] }) : mode2 === "months" ? /* @__PURE__ */ jsx50("div", { className: "fd-cal-grid-months", children: MONTHS.map((m, i) => /* @__PURE__ */ jsx50(
|
|
@@ -3865,7 +3881,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3865
3881
|
},
|
|
3866
3882
|
y
|
|
3867
3883
|
)) }),
|
|
3868
|
-
/* @__PURE__ */
|
|
3884
|
+
/* @__PURE__ */ jsxs46("div", { className: "fd-cal-foot", children: [
|
|
3869
3885
|
/* @__PURE__ */ jsx50(
|
|
3870
3886
|
"button",
|
|
3871
3887
|
{
|
|
@@ -3881,7 +3897,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3881
3897
|
}
|
|
3882
3898
|
),
|
|
3883
3899
|
/* @__PURE__ */ jsx50("span", { style: { flex: 1 } }),
|
|
3884
|
-
range && sel.start ? /* @__PURE__ */
|
|
3900
|
+
range && sel.start ? /* @__PURE__ */ jsxs46("span", { className: "fd-body-sm fd-muted", children: [
|
|
3885
3901
|
fmt(sel.start),
|
|
3886
3902
|
sel.end ? " \u2192 " + fmt(sel.end) : " \u2192 pick an end"
|
|
3887
3903
|
] }) : null
|
|
@@ -3890,16 +3906,16 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3890
3906
|
}
|
|
3891
3907
|
function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, ...rest }) {
|
|
3892
3908
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
3893
|
-
const [open, setOpen] =
|
|
3894
|
-
const rootRef =
|
|
3895
|
-
const boxRef =
|
|
3909
|
+
const [open, setOpen] = React24.useState(false);
|
|
3910
|
+
const rootRef = React24.useRef(null);
|
|
3911
|
+
const boxRef = React24.useRef(null);
|
|
3896
3912
|
const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
|
|
3897
3913
|
const toggle = () => {
|
|
3898
3914
|
if (!disabled) setOpen(!open);
|
|
3899
3915
|
};
|
|
3900
|
-
return /* @__PURE__ */
|
|
3916
|
+
return /* @__PURE__ */ jsxs46("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
3901
3917
|
label ? /* @__PURE__ */ jsx50(FieldLabel, { id: labelId, required, onClick: toggle, children: label }) : null,
|
|
3902
|
-
/* @__PURE__ */
|
|
3918
|
+
/* @__PURE__ */ jsxs46("div", { className: ["fd-input", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" "), style: { cursor: disabled ? "not-allowed" : "pointer" }, onClick: toggle, ref: boxRef, children: [
|
|
3903
3919
|
/* @__PURE__ */ jsx50("span", { className: "fd-input-icon", children: /* @__PURE__ */ jsx50("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }) }),
|
|
3904
3920
|
/* @__PURE__ */ jsx50(
|
|
3905
3921
|
"button",
|
|
@@ -3946,7 +3962,7 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3946
3962
|
)
|
|
3947
3963
|
}
|
|
3948
3964
|
),
|
|
3949
|
-
error ? /* @__PURE__ */
|
|
3965
|
+
error ? /* @__PURE__ */ jsxs46("span", { className: "fd-field-error", children: [
|
|
3950
3966
|
/* @__PURE__ */ jsx50("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3951
3967
|
error
|
|
3952
3968
|
] }) : help ? /* @__PURE__ */ jsx50("span", { className: "fd-field-help", children: help }) : null
|
|
@@ -3954,8 +3970,8 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3954
3970
|
}
|
|
3955
3971
|
|
|
3956
3972
|
// src/components/forms/TimePicker.tsx
|
|
3957
|
-
import * as
|
|
3958
|
-
import { jsx as jsx51, jsxs as
|
|
3973
|
+
import * as React25 from "react";
|
|
3974
|
+
import { jsx as jsx51, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
3959
3975
|
var pad = (n) => String(n).padStart(2, "0");
|
|
3960
3976
|
function ClockFace({ value = "09:00", onChange }) {
|
|
3961
3977
|
let [h24, m] = value.split(":").map(Number);
|
|
@@ -3963,9 +3979,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3963
3979
|
if (isNaN(m)) m = 0;
|
|
3964
3980
|
const pm = h24 >= 12;
|
|
3965
3981
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
3966
|
-
const [mode2, setMode] =
|
|
3967
|
-
const faceRef =
|
|
3968
|
-
const dragging =
|
|
3982
|
+
const [mode2, setMode] = React25.useState("h");
|
|
3983
|
+
const faceRef = React25.useRef(null);
|
|
3984
|
+
const dragging = React25.useRef(false);
|
|
3969
3985
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
3970
3986
|
const R = 108, NR = 80;
|
|
3971
3987
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -4000,8 +4016,8 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
4000
4016
|
};
|
|
4001
4017
|
const handAngle = mode2 === "h" ? h12 % 12 * 30 : m * 6;
|
|
4002
4018
|
const minuteOff = mode2 === "m" && m % 5 !== 0;
|
|
4003
|
-
return /* @__PURE__ */
|
|
4004
|
-
/* @__PURE__ */
|
|
4019
|
+
return /* @__PURE__ */ jsxs47("div", { style: { padding: "4px 14px 14px" }, children: [
|
|
4020
|
+
/* @__PURE__ */ jsxs47("div", { className: "fd-clock-digits", children: [
|
|
4005
4021
|
/* @__PURE__ */ jsx51("button", { type: "button", className: "fd-clock-digit" + (mode2 === "h" ? " is-active" : ""), onClick: () => setMode("h"), children: pad(h12) }),
|
|
4006
4022
|
/* @__PURE__ */ jsx51("span", { style: { fontSize: 24, fontWeight: 700, color: "var(--text-muted)" }, children: ":" }),
|
|
4007
4023
|
/* @__PURE__ */ jsx51("button", { type: "button", className: "fd-clock-digit" + (mode2 === "m" ? " is-active" : ""), onClick: () => setMode("m"), children: pad(m) }),
|
|
@@ -4016,7 +4032,7 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
4016
4032
|
ap
|
|
4017
4033
|
)) })
|
|
4018
4034
|
] }),
|
|
4019
|
-
/* @__PURE__ */
|
|
4035
|
+
/* @__PURE__ */ jsxs47("div", { className: "fd-clock", ref: faceRef, onPointerDown: down, onPointerMove: move, onPointerUp: upH, children: [
|
|
4020
4036
|
/* @__PURE__ */ jsx51("span", { className: "fd-clock-hand", style: { height: NR - (minuteOff ? 14 : 16), transform: "translateX(-50%) rotate(" + handAngle + "deg)", bottom: "50%" } }),
|
|
4021
4037
|
/* @__PURE__ */ jsx51("span", { className: "fd-clock-pivot" }),
|
|
4022
4038
|
minuteOff ? /* @__PURE__ */ jsx51("span", { style: { position: "absolute", left: "50%", top: "50%", width: 10, height: 10, margin: -5, borderRadius: "50%", border: "2px solid var(--brand)", background: "var(--surface)", transform: "rotate(" + handAngle + "deg) translateY(-" + (NR - 6) + "px)", transformOrigin: "center", pointerEvents: "none" } }) : null,
|
|
@@ -4038,9 +4054,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
4038
4054
|
}
|
|
4039
4055
|
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
|
|
4040
4056
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
4041
|
-
const [open, setOpen] =
|
|
4042
|
-
const rootRef =
|
|
4043
|
-
const boxRef =
|
|
4057
|
+
const [open, setOpen] = React25.useState(false);
|
|
4058
|
+
const rootRef = React25.useRef(null);
|
|
4059
|
+
const boxRef = React25.useRef(null);
|
|
4044
4060
|
const disp = () => {
|
|
4045
4061
|
if (!value) return "";
|
|
4046
4062
|
const [h, m] = value.split(":").map(Number);
|
|
@@ -4049,9 +4065,9 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4049
4065
|
const toggle = () => {
|
|
4050
4066
|
if (!disabled) setOpen(!open);
|
|
4051
4067
|
};
|
|
4052
|
-
return /* @__PURE__ */
|
|
4068
|
+
return /* @__PURE__ */ jsxs47("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
4053
4069
|
label ? /* @__PURE__ */ jsx51(FieldLabel, { id: labelId, required, onClick: toggle, children: label }) : null,
|
|
4054
|
-
/* @__PURE__ */
|
|
4070
|
+
/* @__PURE__ */ jsxs47("div", { className: ["fd-input", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" "), style: { cursor: disabled ? "not-allowed" : "pointer" }, onClick: toggle, ref: boxRef, children: [
|
|
4055
4071
|
/* @__PURE__ */ jsx51("span", { className: "fd-input-icon", children: /* @__PURE__ */ jsx51("i", { className: "ph ph-clock", "aria-hidden": "true" }) }),
|
|
4056
4072
|
/* @__PURE__ */ jsx51(
|
|
4057
4073
|
"button",
|
|
@@ -4083,7 +4099,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4083
4099
|
offset: 6,
|
|
4084
4100
|
width: 262,
|
|
4085
4101
|
role: "presentation",
|
|
4086
|
-
footer: /* @__PURE__ */
|
|
4102
|
+
footer: /* @__PURE__ */ jsxs47(React25.Fragment, { children: [
|
|
4087
4103
|
/* @__PURE__ */ jsx51(
|
|
4088
4104
|
"button",
|
|
4089
4105
|
{
|
|
@@ -4103,7 +4119,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4103
4119
|
children: /* @__PURE__ */ jsx51(ClockFace, { value: value || "09:00", onChange: (v) => onChange && onChange({ target: { value: v } }) })
|
|
4104
4120
|
}
|
|
4105
4121
|
),
|
|
4106
|
-
error ? /* @__PURE__ */
|
|
4122
|
+
error ? /* @__PURE__ */ jsxs47("span", { className: "fd-field-error", children: [
|
|
4107
4123
|
/* @__PURE__ */ jsx51("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
4108
4124
|
error
|
|
4109
4125
|
] }) : help ? /* @__PURE__ */ jsx51("span", { className: "fd-field-help", children: help }) : null
|
|
@@ -4111,8 +4127,8 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4111
4127
|
}
|
|
4112
4128
|
|
|
4113
4129
|
// src/components/forms/Slider.tsx
|
|
4114
|
-
import * as
|
|
4115
|
-
import { jsx as jsx52, jsxs as
|
|
4130
|
+
import * as React26 from "react";
|
|
4131
|
+
import { jsx as jsx52, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
4116
4132
|
function Slider({
|
|
4117
4133
|
label,
|
|
4118
4134
|
min = 0,
|
|
@@ -4129,15 +4145,15 @@ function Slider({
|
|
|
4129
4145
|
...rest
|
|
4130
4146
|
}) {
|
|
4131
4147
|
const fieldId = useFieldId(id);
|
|
4132
|
-
const [dragging, setDragging] =
|
|
4148
|
+
const [dragging, setDragging] = React26.useState(false);
|
|
4133
4149
|
const v = value === void 0 ? min : Number(value);
|
|
4134
4150
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
4135
|
-
return /* @__PURE__ */
|
|
4136
|
-
label ? /* @__PURE__ */
|
|
4151
|
+
return /* @__PURE__ */ jsxs48("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
|
|
4152
|
+
label ? /* @__PURE__ */ jsxs48("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
4137
4153
|
/* @__PURE__ */ jsx52(FieldLabel, { htmlFor: fieldId, children: label }),
|
|
4138
4154
|
/* @__PURE__ */ jsx52("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: format(v) })
|
|
4139
4155
|
] }) : null,
|
|
4140
|
-
/* @__PURE__ */
|
|
4156
|
+
/* @__PURE__ */ jsxs48("div", { className: "fd-slider", children: [
|
|
4141
4157
|
/* @__PURE__ */ jsx52("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
4142
4158
|
showChip && dragging ? /* @__PURE__ */ jsx52("span", { className: "fd-slider-chip", style: { left: pct + "%" }, children: format(v) }) : null,
|
|
4143
4159
|
/* @__PURE__ */ jsx52(
|
|
@@ -4163,8 +4179,8 @@ function Slider({
|
|
|
4163
4179
|
}
|
|
4164
4180
|
|
|
4165
4181
|
// src/components/forms/RangeSlider.tsx
|
|
4166
|
-
import * as
|
|
4167
|
-
import { jsx as jsx53, jsxs as
|
|
4182
|
+
import * as React27 from "react";
|
|
4183
|
+
import { jsx as jsx53, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
4168
4184
|
function RangeSlider({
|
|
4169
4185
|
label,
|
|
4170
4186
|
min = 0,
|
|
@@ -4183,9 +4199,9 @@ function RangeSlider({
|
|
|
4183
4199
|
}) {
|
|
4184
4200
|
const fmt2 = format || ((v) => String(v));
|
|
4185
4201
|
const [a, b] = value || [min, max];
|
|
4186
|
-
const [drag, setDrag] =
|
|
4187
|
-
const [focus, setFocus] =
|
|
4188
|
-
const railRef =
|
|
4202
|
+
const [drag, setDrag] = React27.useState(null);
|
|
4203
|
+
const [focus, setFocus] = React27.useState(null);
|
|
4204
|
+
const railRef = React27.useRef(null);
|
|
4189
4205
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
4190
4206
|
const clampPair = (i, v) => {
|
|
4191
4207
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -4200,7 +4216,7 @@ function RangeSlider({
|
|
|
4200
4216
|
const r = railRef.current.getBoundingClientRect();
|
|
4201
4217
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
4202
4218
|
};
|
|
4203
|
-
|
|
4219
|
+
React27.useEffect(() => {
|
|
4204
4220
|
if (drag === null) return;
|
|
4205
4221
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
4206
4222
|
const upH = () => setDrag(null);
|
|
@@ -4269,19 +4285,19 @@ function RangeSlider({
|
|
|
4269
4285
|
};
|
|
4270
4286
|
const showChip = (i) => drag === i || focus === i;
|
|
4271
4287
|
const hasLabels = marks.some((m) => m.label);
|
|
4272
|
-
return /* @__PURE__ */
|
|
4273
|
-
label ? /* @__PURE__ */
|
|
4288
|
+
return /* @__PURE__ */ jsxs49("div", { className: ["fd-field", className].filter(Boolean).join(" "), ...rest, children: [
|
|
4289
|
+
label ? /* @__PURE__ */ jsxs49("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
4274
4290
|
/* @__PURE__ */ jsx53("span", { className: "fd-field-label", children: label }),
|
|
4275
|
-
/* @__PURE__ */
|
|
4291
|
+
/* @__PURE__ */ jsxs49("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: [
|
|
4276
4292
|
fmt2(a),
|
|
4277
4293
|
" \u2013 ",
|
|
4278
4294
|
fmt2(b)
|
|
4279
4295
|
] })
|
|
4280
4296
|
] }) : null,
|
|
4281
|
-
/* @__PURE__ */
|
|
4297
|
+
/* @__PURE__ */ jsxs49("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
|
|
4282
4298
|
/* @__PURE__ */ jsx53("span", { className: "fd-range-rail", ref: railRef }),
|
|
4283
4299
|
/* @__PURE__ */ jsx53("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
|
|
4284
|
-
marks.map((m) => /* @__PURE__ */
|
|
4300
|
+
marks.map((m) => /* @__PURE__ */ jsxs49(React27.Fragment, { children: [
|
|
4285
4301
|
/* @__PURE__ */ jsx53("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
|
|
4286
4302
|
m.label ? /* @__PURE__ */ jsx53("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
|
|
4287
4303
|
] }, m.value)),
|
|
@@ -4310,8 +4326,8 @@ function RangeSlider({
|
|
|
4310
4326
|
}
|
|
4311
4327
|
|
|
4312
4328
|
// src/components/forms/Dropzone.tsx
|
|
4313
|
-
import * as
|
|
4314
|
-
import { jsx as jsx54, jsxs as
|
|
4329
|
+
import * as React28 from "react";
|
|
4330
|
+
import { jsx as jsx54, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
4315
4331
|
function Dropzone({
|
|
4316
4332
|
onFiles,
|
|
4317
4333
|
onReject,
|
|
@@ -4325,8 +4341,8 @@ function Dropzone({
|
|
|
4325
4341
|
className = "",
|
|
4326
4342
|
style
|
|
4327
4343
|
}) {
|
|
4328
|
-
const [over, setOver] =
|
|
4329
|
-
const depth =
|
|
4344
|
+
const [over, setOver] = React28.useState(false);
|
|
4345
|
+
const depth = React28.useRef(0);
|
|
4330
4346
|
const has = (e) => {
|
|
4331
4347
|
const dt = e.dataTransfer;
|
|
4332
4348
|
if (!dt) return false;
|
|
@@ -4356,7 +4372,7 @@ function Dropzone({
|
|
|
4356
4372
|
if (rejected.length && onReject) onReject(rejected);
|
|
4357
4373
|
if (accepted.length && onFiles) onFiles(accepted);
|
|
4358
4374
|
};
|
|
4359
|
-
return /* @__PURE__ */
|
|
4375
|
+
return /* @__PURE__ */ jsxs50(
|
|
4360
4376
|
"div",
|
|
4361
4377
|
{
|
|
4362
4378
|
className: ["fd-dropzone", over ? "is-over" : "", className].filter(Boolean).join(" "),
|
|
@@ -4367,7 +4383,7 @@ function Dropzone({
|
|
|
4367
4383
|
onDrop: drop,
|
|
4368
4384
|
children: [
|
|
4369
4385
|
children,
|
|
4370
|
-
over ? /* @__PURE__ */ jsx54("div", { className: "fd-dropzone-veil", "aria-hidden": "true", children: /* @__PURE__ */
|
|
4386
|
+
over ? /* @__PURE__ */ jsx54("div", { className: "fd-dropzone-veil", "aria-hidden": "true", children: /* @__PURE__ */ jsxs50("div", { className: "fd-dropzone-card", children: [
|
|
4371
4387
|
/* @__PURE__ */ jsx54("i", { className: "ph ph-tray-arrow-down" }),
|
|
4372
4388
|
/* @__PURE__ */ jsx54("span", { className: "fd-dropzone-label", children: label }),
|
|
4373
4389
|
hint ? /* @__PURE__ */ jsx54("span", { className: "fd-dropzone-hint", children: hint }) : null
|
|
@@ -4388,8 +4404,8 @@ function FilePickButton({
|
|
|
4388
4404
|
className = "",
|
|
4389
4405
|
children
|
|
4390
4406
|
}) {
|
|
4391
|
-
const ref =
|
|
4392
|
-
return /* @__PURE__ */
|
|
4407
|
+
const ref = React28.useRef(null);
|
|
4408
|
+
return /* @__PURE__ */ jsxs50(React28.Fragment, { children: [
|
|
4393
4409
|
/* @__PURE__ */ jsx54(
|
|
4394
4410
|
"button",
|
|
4395
4411
|
{
|
|
@@ -4422,10 +4438,10 @@ function FilePickButton({
|
|
|
4422
4438
|
}
|
|
4423
4439
|
function useStagedFiles(upload, opts) {
|
|
4424
4440
|
const o = opts || {};
|
|
4425
|
-
const [items, setItems] =
|
|
4426
|
-
const controllers =
|
|
4441
|
+
const [items, setItems] = React28.useState([]);
|
|
4442
|
+
const controllers = React28.useRef({});
|
|
4427
4443
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
4428
|
-
const run =
|
|
4444
|
+
const run = React28.useCallback((att) => {
|
|
4429
4445
|
if (!upload) return;
|
|
4430
4446
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
4431
4447
|
controllers.current[att.id] = ac;
|
|
@@ -4442,14 +4458,14 @@ function useStagedFiles(upload, opts) {
|
|
|
4442
4458
|
delete controllers.current[att.id];
|
|
4443
4459
|
});
|
|
4444
4460
|
}, [upload]);
|
|
4445
|
-
const add =
|
|
4461
|
+
const add = React28.useCallback((files) => {
|
|
4446
4462
|
if (!upload) return [];
|
|
4447
4463
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
4448
4464
|
setItems((list) => list.concat(atts));
|
|
4449
4465
|
atts.forEach(run);
|
|
4450
4466
|
return atts;
|
|
4451
4467
|
}, [upload, run]);
|
|
4452
|
-
const remove =
|
|
4468
|
+
const remove = React28.useCallback((att) => {
|
|
4453
4469
|
const ac = controllers.current[att.id];
|
|
4454
4470
|
if (ac) {
|
|
4455
4471
|
try {
|
|
@@ -4460,10 +4476,10 @@ function useStagedFiles(upload, opts) {
|
|
|
4460
4476
|
}
|
|
4461
4477
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
4462
4478
|
}, []);
|
|
4463
|
-
const retry =
|
|
4479
|
+
const retry = React28.useCallback((att) => {
|
|
4464
4480
|
run(att);
|
|
4465
4481
|
}, [run]);
|
|
4466
|
-
const clear =
|
|
4482
|
+
const clear = React28.useCallback(() => {
|
|
4467
4483
|
Object.values(controllers.current).forEach((ac) => {
|
|
4468
4484
|
try {
|
|
4469
4485
|
ac && ac.abort();
|
|
@@ -4479,7 +4495,7 @@ function useStagedFiles(upload, opts) {
|
|
|
4479
4495
|
var DropzoneKit = { useStagedFiles };
|
|
4480
4496
|
|
|
4481
4497
|
// src/components/forms/FileGrid.tsx
|
|
4482
|
-
import { jsx as jsx55, jsxs as
|
|
4498
|
+
import { jsx as jsx55, jsxs as jsxs51 } from "react/jsx-runtime";
|
|
4483
4499
|
var truncateMiddle = (name, max = 34) => {
|
|
4484
4500
|
if (!name || name.length <= max) return name;
|
|
4485
4501
|
const ext = /\.[A-Za-z0-9]+$/.exec(name);
|
|
@@ -4497,8 +4513,8 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
4497
4513
|
const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
|
|
4498
4514
|
const meta = file.meta || (file.size ? formatBytes(file.size) : "");
|
|
4499
4515
|
const clickable = !!onOpen && !uploading;
|
|
4500
|
-
return /* @__PURE__ */
|
|
4501
|
-
/* @__PURE__ */
|
|
4516
|
+
return /* @__PURE__ */ jsxs51("div", { className: ["fd-file", compact3 ? "is-compact" : "", file.error ? "is-error" : "", uploading ? "is-uploading" : "", className].filter(Boolean).join(" "), children: [
|
|
4517
|
+
/* @__PURE__ */ jsxs51(
|
|
4502
4518
|
"button",
|
|
4503
4519
|
{
|
|
4504
4520
|
type: "button",
|
|
@@ -4507,16 +4523,16 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
4507
4523
|
onClick: clickable ? () => onOpen(file) : void 0,
|
|
4508
4524
|
title: file.name + (meta ? " \xB7 " + meta : ""),
|
|
4509
4525
|
children: [
|
|
4510
|
-
/* @__PURE__ */
|
|
4526
|
+
/* @__PURE__ */ jsxs51("span", { className: "fd-file-icon", children: [
|
|
4511
4527
|
thumb ? /* @__PURE__ */ jsx55("img", { src: thumb, alt: "" }) : /* @__PURE__ */ jsx55("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
|
|
4512
4528
|
(file.mime || "").startsWith("video/") ? /* @__PURE__ */ jsx55("i", { className: "ph ph-play fd-file-play", "aria-hidden": "true" }) : null
|
|
4513
4529
|
] }),
|
|
4514
|
-
/* @__PURE__ */
|
|
4530
|
+
/* @__PURE__ */ jsxs51("span", { className: "fd-file-text", children: [
|
|
4515
4531
|
/* @__PURE__ */ jsx55("span", { className: "fd-file-name", children: truncateMiddle(file.name, compact3 ? 26 : 40) }),
|
|
4516
|
-
/* @__PURE__ */ jsx55("span", { className: "fd-file-meta", children: file.error ? /* @__PURE__ */
|
|
4532
|
+
/* @__PURE__ */ jsx55("span", { className: "fd-file-meta", children: file.error ? /* @__PURE__ */ jsxs51("span", { className: "fd-file-err", children: [
|
|
4517
4533
|
/* @__PURE__ */ jsx55("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
4518
4534
|
file.error
|
|
4519
|
-
] }) : uploading ? /* @__PURE__ */
|
|
4535
|
+
] }) : uploading ? /* @__PURE__ */ jsxs51("span", { className: "fd-tabular", children: [
|
|
4520
4536
|
Math.round(file.progress),
|
|
4521
4537
|
"% uploaded"
|
|
4522
4538
|
] }) : meta })
|
|
@@ -4533,10 +4549,10 @@ function FileTile({ file, onOpen, onRemove, maxHeight = 200, className = "" }) {
|
|
|
4533
4549
|
if (!file) return null;
|
|
4534
4550
|
const src = file.thumb && file.thumb.url || file.blobUrl || file.url;
|
|
4535
4551
|
const uploading = file.progress != null && file.progress < 100 && !file.error;
|
|
4536
|
-
return /* @__PURE__ */
|
|
4552
|
+
return /* @__PURE__ */ jsxs51("figure", { className: ["fd-tile", uploading ? "is-uploading" : "", file.error ? "is-error" : "", className].filter(Boolean).join(" "), children: [
|
|
4537
4553
|
/* @__PURE__ */ jsx55("button", { type: "button", className: "fd-tile-btn", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen, children: src ? /* @__PURE__ */ jsx55("img", { src, alt: file.name || "", style: { maxHeight }, loading: "lazy" }) : /* @__PURE__ */ jsx55("span", { className: "fd-tile-fallback", children: /* @__PURE__ */ jsx55("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }) }) }),
|
|
4538
4554
|
uploading ? /* @__PURE__ */ jsx55(Progress, { value: file.progress }) : null,
|
|
4539
|
-
file.error ? /* @__PURE__ */
|
|
4555
|
+
file.error ? /* @__PURE__ */ jsxs51("figcaption", { className: "fd-tile-err", children: [
|
|
4540
4556
|
/* @__PURE__ */ jsx55("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
4541
4557
|
file.error
|
|
4542
4558
|
] }) : null,
|
|
@@ -4560,9 +4576,9 @@ function FileCell({ file, onOpen, onRemove, onRetry }) {
|
|
|
4560
4576
|
const image = isImage(file.mime, file.name);
|
|
4561
4577
|
const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
|
|
4562
4578
|
const label = file.name + (file.size ? " \xB7 " + formatBytes(file.size) : "");
|
|
4563
|
-
return /* @__PURE__ */
|
|
4564
|
-
/* @__PURE__ */
|
|
4565
|
-
thumb ? /* @__PURE__ */ jsx55("img", { src: thumb, alt: "" }) : /* @__PURE__ */
|
|
4579
|
+
return /* @__PURE__ */ jsxs51("div", { className: ["fd-cell", file.error ? "is-error" : "", uploading ? "is-uploading" : ""].filter(Boolean).join(" "), title: file.error ? file.name + " \u2014 " + file.error : label, children: [
|
|
4580
|
+
/* @__PURE__ */ jsxs51("button", { type: "button", className: "fd-cell-main", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen || uploading, "aria-label": "Open " + file.name, children: [
|
|
4581
|
+
thumb ? /* @__PURE__ */ jsx55("img", { src: thumb, alt: "" }) : /* @__PURE__ */ jsxs51("span", { className: "fd-cell-doc", children: [
|
|
4566
4582
|
/* @__PURE__ */ jsx55("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
|
|
4567
4583
|
/* @__PURE__ */ jsx55("span", { className: "fd-cell-name", children: shortName(file.name) }),
|
|
4568
4584
|
/* @__PURE__ */ jsx55("span", { className: "fd-cell-size", children: file.meta || formatBytes(file.size) })
|
|
@@ -4580,15 +4596,15 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
4580
4596
|
if (!list.length) return null;
|
|
4581
4597
|
const pics = tiles ? list.filter((f) => isImage(f.mime, f.name)) : [];
|
|
4582
4598
|
const rest = list.filter((f) => pics.indexOf(f) === -1);
|
|
4583
|
-
return /* @__PURE__ */
|
|
4599
|
+
return /* @__PURE__ */ jsxs51("div", { className: ["fd-filegrid", className].filter(Boolean).join(" "), children: [
|
|
4584
4600
|
pics.length ? /* @__PURE__ */ jsx55("div", { className: "fd-filegrid-tiles", children: pics.map((f) => /* @__PURE__ */ jsx55(FileTile, { file: f, onOpen, onRemove, maxHeight }, f.id || f.name)) }) : null,
|
|
4585
4601
|
rest.length ? /* @__PURE__ */ jsx55("div", { className: "fd-filegrid-chips", children: rest.map((f) => /* @__PURE__ */ jsx55(FileChip, { file: f, onOpen, onRemove, onRetry, compact: compact3 }, f.id || f.name)) }) : null
|
|
4586
4602
|
] });
|
|
4587
4603
|
}
|
|
4588
4604
|
|
|
4589
4605
|
// src/components/forms/MarkdownEditor.tsx
|
|
4590
|
-
import * as
|
|
4591
|
-
import { jsx as jsx56, jsxs as
|
|
4606
|
+
import * as React29 from "react";
|
|
4607
|
+
import { jsx as jsx56, jsxs as jsxs52 } from "react/jsx-runtime";
|
|
4592
4608
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
4593
4609
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
4594
4610
|
function inlineParts(text) {
|
|
@@ -4801,7 +4817,7 @@ function syncDom(root, value) {
|
|
|
4801
4817
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
4802
4818
|
}
|
|
4803
4819
|
var LIST_CONT = RE_LI;
|
|
4804
|
-
var MarkdownEditor =
|
|
4820
|
+
var MarkdownEditor = React29.forwardRef(function MarkdownEditor2({
|
|
4805
4821
|
value = "",
|
|
4806
4822
|
onChange,
|
|
4807
4823
|
onSubmit,
|
|
@@ -4820,10 +4836,10 @@ var MarkdownEditor = React28.forwardRef(function MarkdownEditor2({
|
|
|
4820
4836
|
className = "",
|
|
4821
4837
|
id
|
|
4822
4838
|
}, ref) {
|
|
4823
|
-
const boxRef =
|
|
4824
|
-
const composing =
|
|
4825
|
-
const pendingCaret =
|
|
4826
|
-
|
|
4839
|
+
const boxRef = React29.useRef(null);
|
|
4840
|
+
const composing = React29.useRef(false);
|
|
4841
|
+
const pendingCaret = React29.useRef(null);
|
|
4842
|
+
React29.useLayoutEffect(() => {
|
|
4827
4843
|
const root = boxRef.current;
|
|
4828
4844
|
if (!root || composing.current) return;
|
|
4829
4845
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -4832,7 +4848,7 @@ var MarkdownEditor = React28.forwardRef(function MarkdownEditor2({
|
|
|
4832
4848
|
pendingCaret.current = null;
|
|
4833
4849
|
if (active && caret != null) placeCaret(root, caret);
|
|
4834
4850
|
}, [value]);
|
|
4835
|
-
|
|
4851
|
+
React29.useEffect(() => {
|
|
4836
4852
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
4837
4853
|
}, [autoFocus]);
|
|
4838
4854
|
const caretNow = () => {
|
|
@@ -4899,7 +4915,7 @@ var MarkdownEditor = React28.forwardRef(function MarkdownEditor2({
|
|
|
4899
4915
|
api.replaceRange(from, to, next, from + next.length);
|
|
4900
4916
|
}
|
|
4901
4917
|
};
|
|
4902
|
-
|
|
4918
|
+
React29.useImperativeHandle(ref, () => api);
|
|
4903
4919
|
function detect(text, caret) {
|
|
4904
4920
|
if (!onTrigger) return;
|
|
4905
4921
|
const upto = text.slice(0, caret);
|
|
@@ -5012,7 +5028,7 @@ var MarkdownEditor = React28.forwardRef(function MarkdownEditor2({
|
|
|
5012
5028
|
api.replaceRange(s.start, s.end, text.replace(/\r\n?/g, "\n"));
|
|
5013
5029
|
};
|
|
5014
5030
|
const lh = 1.55;
|
|
5015
|
-
return /* @__PURE__ */
|
|
5031
|
+
return /* @__PURE__ */ jsxs52("div", { className: ["fd-rme-wrap", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "), children: [
|
|
5016
5032
|
/* @__PURE__ */ jsx56(
|
|
5017
5033
|
"div",
|
|
5018
5034
|
{
|
|
@@ -5051,10 +5067,10 @@ var MarkdownEditor = React28.forwardRef(function MarkdownEditor2({
|
|
|
5051
5067
|
});
|
|
5052
5068
|
|
|
5053
5069
|
// src/components/platform/AccountMenu.tsx
|
|
5054
|
-
import * as
|
|
5070
|
+
import * as React31 from "react";
|
|
5055
5071
|
|
|
5056
5072
|
// src/kits/session.ts
|
|
5057
|
-
import * as
|
|
5073
|
+
import * as React30 from "react";
|
|
5058
5074
|
var PERMISSION_CATALOG = [
|
|
5059
5075
|
{ group: "Plans", items: [
|
|
5060
5076
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -6621,8 +6637,8 @@ function roadmap(overrides) {
|
|
|
6621
6637
|
};
|
|
6622
6638
|
}
|
|
6623
6639
|
function useSession() {
|
|
6624
|
-
const [s, setS] =
|
|
6625
|
-
|
|
6640
|
+
const [s, setS] = React30.useState(getSession);
|
|
6641
|
+
React30.useEffect(() => subscribe(setS), []);
|
|
6626
6642
|
return s;
|
|
6627
6643
|
}
|
|
6628
6644
|
var SessionKit = {
|
|
@@ -6655,7 +6671,7 @@ var SessionKit = {
|
|
|
6655
6671
|
};
|
|
6656
6672
|
|
|
6657
6673
|
// src/components/platform/AccountMenu.tsx
|
|
6658
|
-
import { Fragment as Fragment14, jsx as jsx57, jsxs as
|
|
6674
|
+
import { Fragment as Fragment14, jsx as jsx57, jsxs as jsxs53 } from "react/jsx-runtime";
|
|
6659
6675
|
var DEFAULT_LINKS = [
|
|
6660
6676
|
{ id: "profile", label: "Your profile", icon: "user-circle", href: "../admin/index.html#profile" },
|
|
6661
6677
|
{ id: "preferences", label: "Preferences", icon: "sliders-horizontal", href: "../admin/index.html#preferences" }
|
|
@@ -6666,7 +6682,7 @@ var DEFAULT_ADMIN_LINKS = [
|
|
|
6666
6682
|
{ id: "flags", label: "Feature flags", icon: "toggle-right", href: "../admin/index.html#flags", perm: "flags.manage" }
|
|
6667
6683
|
];
|
|
6668
6684
|
function Item({ item, onPick }) {
|
|
6669
|
-
return /* @__PURE__ */
|
|
6685
|
+
return /* @__PURE__ */ jsxs53(
|
|
6670
6686
|
"button",
|
|
6671
6687
|
{
|
|
6672
6688
|
type: "button",
|
|
@@ -6692,9 +6708,9 @@ function AccountMenu({
|
|
|
6692
6708
|
...rest
|
|
6693
6709
|
}) {
|
|
6694
6710
|
const session = SessionKit.useSession();
|
|
6695
|
-
const [open, setOpen] =
|
|
6696
|
-
const [switching, setSwitching] =
|
|
6697
|
-
const ref =
|
|
6711
|
+
const [open, setOpen] = React31.useState(false);
|
|
6712
|
+
const [switching, setSwitching] = React31.useState(false);
|
|
6713
|
+
const ref = React31.useRef(null);
|
|
6698
6714
|
const user = session.user;
|
|
6699
6715
|
const visibleAdmin = adminLinks.filter((l) => !l.perm || SessionKit.can(l.perm));
|
|
6700
6716
|
const pick = (item) => {
|
|
@@ -6708,8 +6724,8 @@ function AccountMenu({
|
|
|
6708
6724
|
if (onSignOut) return onSignOut();
|
|
6709
6725
|
window.alert("Signed out. (Simulated \u2014 no auth provider is wired up.)");
|
|
6710
6726
|
};
|
|
6711
|
-
return /* @__PURE__ */
|
|
6712
|
-
/* @__PURE__ */
|
|
6727
|
+
return /* @__PURE__ */ jsxs53(Fragment14, { children: [
|
|
6728
|
+
/* @__PURE__ */ jsxs53(
|
|
6713
6729
|
"button",
|
|
6714
6730
|
{
|
|
6715
6731
|
type: "button",
|
|
@@ -6726,27 +6742,27 @@ function AccountMenu({
|
|
|
6726
6742
|
]
|
|
6727
6743
|
}
|
|
6728
6744
|
),
|
|
6729
|
-
/* @__PURE__ */ jsx57(Popover, { open, anchorRef: ref, onClose: () => setOpen(false), placement: "bottom-end", width: 272, children: /* @__PURE__ */
|
|
6730
|
-
/* @__PURE__ */
|
|
6745
|
+
/* @__PURE__ */ jsx57(Popover, { open, anchorRef: ref, onClose: () => setOpen(false), placement: "bottom-end", width: 272, children: /* @__PURE__ */ jsxs53("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
|
|
6746
|
+
/* @__PURE__ */ jsxs53("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
6731
6747
|
/* @__PURE__ */ jsx57(Avatar, { name: user.name }),
|
|
6732
|
-
/* @__PURE__ */
|
|
6748
|
+
/* @__PURE__ */ jsxs53("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
|
|
6733
6749
|
/* @__PURE__ */ jsx57("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
|
|
6734
6750
|
/* @__PURE__ */ jsx57("span", { className: "fd-body-sm fd-muted fd-table-trunc", children: user.email })
|
|
6735
6751
|
] })
|
|
6736
6752
|
] }),
|
|
6737
6753
|
showRoles && session.roles.length ? /* @__PURE__ */ jsx57("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: session.roles.map((r) => /* @__PURE__ */ jsx57(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
|
|
6738
6754
|
/* @__PURE__ */ jsx57("div", { className: "fd-acct-group", children: links.map((l) => /* @__PURE__ */ jsx57(Item, { item: l, onPick: pick }, l.id)) }),
|
|
6739
|
-
visibleAdmin.length ? /* @__PURE__ */
|
|
6755
|
+
visibleAdmin.length ? /* @__PURE__ */ jsxs53("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
6740
6756
|
/* @__PURE__ */ jsx57("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: "Administration" }),
|
|
6741
6757
|
visibleAdmin.map((l) => /* @__PURE__ */ jsx57(Item, { item: l, onPick: pick }, l.id))
|
|
6742
6758
|
] }) : null,
|
|
6743
|
-
allowUserSwitch ? /* @__PURE__ */
|
|
6744
|
-
/* @__PURE__ */
|
|
6759
|
+
allowUserSwitch ? /* @__PURE__ */ jsxs53("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
6760
|
+
/* @__PURE__ */ jsxs53("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
|
|
6745
6761
|
/* @__PURE__ */ jsx57("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
|
|
6746
6762
|
/* @__PURE__ */ jsx57("span", { style: { flex: 1 }, children: "View as another member" }),
|
|
6747
6763
|
/* @__PURE__ */ jsx57("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
|
|
6748
6764
|
] }),
|
|
6749
|
-
switching ? /* @__PURE__ */ jsx57("div", { className: "fd-stack", style: { gap: 0 }, children: session.allUsers.filter((u) => u.status === "active").map((u) => /* @__PURE__ */
|
|
6765
|
+
switching ? /* @__PURE__ */ jsx57("div", { className: "fd-stack", style: { gap: 0 }, children: session.allUsers.filter((u) => u.status === "active").map((u) => /* @__PURE__ */ jsxs53(
|
|
6750
6766
|
"button",
|
|
6751
6767
|
{
|
|
6752
6768
|
type: "button",
|
|
@@ -6759,7 +6775,7 @@ function AccountMenu({
|
|
|
6759
6775
|
},
|
|
6760
6776
|
children: [
|
|
6761
6777
|
/* @__PURE__ */ jsx57(Avatar, { name: u.name, size: "sm" }),
|
|
6762
|
-
/* @__PURE__ */
|
|
6778
|
+
/* @__PURE__ */ jsxs53("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
|
|
6763
6779
|
/* @__PURE__ */ jsx57("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
|
|
6764
6780
|
/* @__PURE__ */ jsx57("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") })
|
|
6765
6781
|
] }),
|
|
@@ -6769,7 +6785,7 @@ function AccountMenu({
|
|
|
6769
6785
|
u.id
|
|
6770
6786
|
)) }) : null
|
|
6771
6787
|
] }) : null,
|
|
6772
|
-
/* @__PURE__ */ jsx57("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: /* @__PURE__ */
|
|
6788
|
+
/* @__PURE__ */ jsx57("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: /* @__PURE__ */ jsxs53("button", { type: "button", role: "menuitem", className: "fd-acct-item", "data-danger": "true", onClick: signOut, children: [
|
|
6773
6789
|
/* @__PURE__ */ jsx57("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
|
|
6774
6790
|
/* @__PURE__ */ jsx57("span", { style: { flex: 1 }, children: "Sign out" })
|
|
6775
6791
|
] }) })
|
|
@@ -6778,14 +6794,14 @@ function AccountMenu({
|
|
|
6778
6794
|
}
|
|
6779
6795
|
|
|
6780
6796
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
6781
|
-
import * as
|
|
6782
|
-
import { jsx as jsx58, jsxs as
|
|
6797
|
+
import * as React32 from "react";
|
|
6798
|
+
import { jsx as jsx58, jsxs as jsxs54 } from "react/jsx-runtime";
|
|
6783
6799
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
6784
6800
|
function Json({ obj }) {
|
|
6785
6801
|
return /* @__PURE__ */ jsx58("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
6786
6802
|
}
|
|
6787
6803
|
function Endpoint({ s, onRequest }) {
|
|
6788
|
-
const [tried, setTried] =
|
|
6804
|
+
const [tried, setTried] = React32.useState(null);
|
|
6789
6805
|
const run = async () => {
|
|
6790
6806
|
setTried("busy");
|
|
6791
6807
|
const t0 = (window.performance || Date).now();
|
|
@@ -6796,13 +6812,13 @@ function Endpoint({ s, onRequest }) {
|
|
|
6796
6812
|
setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
|
|
6797
6813
|
}
|
|
6798
6814
|
};
|
|
6799
|
-
return /* @__PURE__ */ jsx58(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */
|
|
6800
|
-
/* @__PURE__ */
|
|
6815
|
+
return /* @__PURE__ */ jsx58(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
6816
|
+
/* @__PURE__ */ jsxs54("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
|
|
6801
6817
|
/* @__PURE__ */ jsx58(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
|
|
6802
6818
|
/* @__PURE__ */ jsx58("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
|
|
6803
6819
|
s.isList ? /* @__PURE__ */ jsx58(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
|
|
6804
6820
|
/* @__PURE__ */ jsx58("span", { style: { flex: 1 } }),
|
|
6805
|
-
/* @__PURE__ */
|
|
6821
|
+
/* @__PURE__ */ jsxs54("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
6806
6822
|
s.latency[0],
|
|
6807
6823
|
"\u2013",
|
|
6808
6824
|
s.latency[1],
|
|
@@ -6810,31 +6826,31 @@ function Endpoint({ s, onRequest }) {
|
|
|
6810
6826
|
] }),
|
|
6811
6827
|
/* @__PURE__ */ jsx58(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
|
|
6812
6828
|
] }),
|
|
6813
|
-
/* @__PURE__ */
|
|
6814
|
-
/* @__PURE__ */
|
|
6829
|
+
/* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
|
|
6830
|
+
/* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6815
6831
|
/* @__PURE__ */ jsx58("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
|
|
6816
6832
|
/* @__PURE__ */ jsx58("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
|
|
6817
6833
|
s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx58("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx58(Tag, { children: u }, u)) }) : null
|
|
6818
6834
|
] }),
|
|
6819
|
-
/* @__PURE__ */
|
|
6820
|
-
s.request ? /* @__PURE__ */
|
|
6835
|
+
/* @__PURE__ */ jsxs54("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
|
|
6836
|
+
s.request ? /* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6821
6837
|
/* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", children: "Request body" }),
|
|
6822
6838
|
/* @__PURE__ */ jsx58(Json, { obj: s.request })
|
|
6823
6839
|
] }) : null,
|
|
6824
|
-
s.query ? /* @__PURE__ */
|
|
6840
|
+
s.query ? /* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6825
6841
|
/* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", children: "Query" }),
|
|
6826
6842
|
/* @__PURE__ */ jsx58(Json, { obj: s.query })
|
|
6827
6843
|
] }) : null,
|
|
6828
|
-
/* @__PURE__ */
|
|
6844
|
+
/* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6829
6845
|
/* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", children: "Response 200" }),
|
|
6830
6846
|
/* @__PURE__ */ jsx58(Json, { obj: s.response })
|
|
6831
6847
|
] })
|
|
6832
6848
|
] }),
|
|
6833
6849
|
s.notes ? /* @__PURE__ */ jsx58(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
|
|
6834
|
-
tried && tried !== "busy" ? /* @__PURE__ */
|
|
6835
|
-
/* @__PURE__ */
|
|
6850
|
+
tried && tried !== "busy" ? /* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6851
|
+
/* @__PURE__ */ jsxs54("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
6836
6852
|
/* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
|
|
6837
|
-
/* @__PURE__ */
|
|
6853
|
+
/* @__PURE__ */ jsxs54(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
|
|
6838
6854
|
tried.ms,
|
|
6839
6855
|
"ms"
|
|
6840
6856
|
] })
|
|
@@ -6858,29 +6874,29 @@ function ApiSpecBrowser({
|
|
|
6858
6874
|
className = "",
|
|
6859
6875
|
...rest
|
|
6860
6876
|
}) {
|
|
6861
|
-
const [q, setQ] =
|
|
6862
|
-
const [method, setMethod] =
|
|
6863
|
-
const [mod, setMod] =
|
|
6864
|
-
const [listOnly, setListOnly] =
|
|
6877
|
+
const [q, setQ] = React32.useState("");
|
|
6878
|
+
const [method, setMethod] = React32.useState(null);
|
|
6879
|
+
const [mod, setMod] = React32.useState(null);
|
|
6880
|
+
const [listOnly, setListOnly] = React32.useState(false);
|
|
6865
6881
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
6866
6882
|
const hits = spec.filter((s) => (!method || s.method === method) && (!listOnly || s.isList) && (!activeModule || activeModule.endpoints.indexOf(s.id) >= 0) && (!q || (s.path + " " + s.title + " " + s.purpose + " " + (s.usedBy || []).join(" ")).toLowerCase().includes(q.toLowerCase())));
|
|
6867
6883
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
6868
6884
|
const methods = [...new Set(spec.map((s) => s.method))];
|
|
6869
6885
|
const listCount = spec.filter((s) => s.isList).length;
|
|
6870
|
-
return /* @__PURE__ */
|
|
6871
|
-
/* @__PURE__ */
|
|
6886
|
+
return /* @__PURE__ */ jsxs54("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
|
|
6887
|
+
/* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
6872
6888
|
kicker ? /* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", children: kicker }) : null,
|
|
6873
6889
|
/* @__PURE__ */ jsx58("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
6874
6890
|
lede ? /* @__PURE__ */ jsx58("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
|
|
6875
6891
|
] }),
|
|
6876
|
-
modules && modules.length ? /* @__PURE__ */
|
|
6892
|
+
modules && modules.length ? /* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
6877
6893
|
/* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
|
|
6878
|
-
/* @__PURE__ */
|
|
6879
|
-
/* @__PURE__ */
|
|
6894
|
+
/* @__PURE__ */ jsxs54("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
6895
|
+
/* @__PURE__ */ jsxs54(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
|
|
6880
6896
|
"All screens ",
|
|
6881
6897
|
/* @__PURE__ */ jsx58("span", { className: "fd-mono", children: spec.length })
|
|
6882
6898
|
] }),
|
|
6883
|
-
modules.map((m) => /* @__PURE__ */
|
|
6899
|
+
modules.map((m) => /* @__PURE__ */ jsxs54(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
|
|
6884
6900
|
m.label,
|
|
6885
6901
|
" ",
|
|
6886
6902
|
/* @__PURE__ */ jsx58("span", { className: "fd-mono", children: m.endpoints.length })
|
|
@@ -6897,19 +6913,19 @@ function ApiSpecBrowser({
|
|
|
6897
6913
|
) : null
|
|
6898
6914
|
] }) : null,
|
|
6899
6915
|
sourceNote ? /* @__PURE__ */ jsx58(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
|
|
6900
|
-
/* @__PURE__ */
|
|
6916
|
+
/* @__PURE__ */ jsxs54("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
6901
6917
|
/* @__PURE__ */ jsx58(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
|
|
6902
|
-
methods.map((m) => /* @__PURE__ */
|
|
6918
|
+
methods.map((m) => /* @__PURE__ */ jsxs54(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
|
|
6903
6919
|
m,
|
|
6904
6920
|
" ",
|
|
6905
6921
|
/* @__PURE__ */ jsx58("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
|
|
6906
6922
|
] }, m)),
|
|
6907
|
-
listCount ? /* @__PURE__ */
|
|
6923
|
+
listCount ? /* @__PURE__ */ jsxs54(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
|
|
6908
6924
|
"Paged lists ",
|
|
6909
6925
|
/* @__PURE__ */ jsx58("span", { className: "fd-mono", children: listCount })
|
|
6910
6926
|
] }) : null,
|
|
6911
6927
|
/* @__PURE__ */ jsx58("span", { style: { flex: 1 } }),
|
|
6912
|
-
/* @__PURE__ */
|
|
6928
|
+
/* @__PURE__ */ jsxs54("span", { className: "fd-body-sm fd-muted", children: [
|
|
6913
6929
|
hits.length,
|
|
6914
6930
|
" of ",
|
|
6915
6931
|
spec.length,
|
|
@@ -6920,18 +6936,18 @@ function ApiSpecBrowser({
|
|
|
6920
6936
|
hits.length === 0 ? /* @__PURE__ */ jsx58(Card, { elevation: "flat", children: /* @__PURE__ */ jsx58("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
|
|
6921
6937
|
const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
|
|
6922
6938
|
if (!items.length) return null;
|
|
6923
|
-
return /* @__PURE__ */
|
|
6939
|
+
return /* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 12 }, children: [
|
|
6924
6940
|
/* @__PURE__ */ jsx58("span", { className: "fd-label-lg", children: g }),
|
|
6925
6941
|
items.map((s) => /* @__PURE__ */ jsx58(Endpoint, { s, onRequest }, s.id))
|
|
6926
6942
|
] }, g);
|
|
6927
6943
|
}),
|
|
6928
|
-
conventions && conventions.length ? /* @__PURE__ */ jsx58(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx58("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */
|
|
6944
|
+
conventions && conventions.length ? /* @__PURE__ */ jsx58(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx58("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs54("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
|
|
6929
6945
|
/* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
|
|
6930
6946
|
/* @__PURE__ */ jsx58("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
|
|
6931
6947
|
] }, k)) }) }) : null,
|
|
6932
|
-
openQuestions && openQuestions.length ? /* @__PURE__ */ jsx58(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx58("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */
|
|
6948
|
+
openQuestions && openQuestions.length ? /* @__PURE__ */ jsx58(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx58("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs54("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
|
|
6933
6949
|
/* @__PURE__ */ jsx58(Badge, { tone: "danger", children: id }),
|
|
6934
|
-
/* @__PURE__ */
|
|
6950
|
+
/* @__PURE__ */ jsxs54("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
|
|
6935
6951
|
/* @__PURE__ */ jsx58("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
|
|
6936
6952
|
/* @__PURE__ */ jsx58("span", { className: "fd-body-sm fd-muted", children: why })
|
|
6937
6953
|
] })
|
|
@@ -6940,8 +6956,8 @@ function ApiSpecBrowser({
|
|
|
6940
6956
|
}
|
|
6941
6957
|
|
|
6942
6958
|
// src/components/platform/ProfilePage.tsx
|
|
6943
|
-
import * as
|
|
6944
|
-
import { jsx as jsx59, jsxs as
|
|
6959
|
+
import * as React33 from "react";
|
|
6960
|
+
import { jsx as jsx59, jsxs as jsxs55 } from "react/jsx-runtime";
|
|
6945
6961
|
var TIMEZONES = ["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles", "America/Anchorage", "Pacific/Honolulu", "Europe/London", "Europe/Berlin"];
|
|
6946
6962
|
var NOTIFY = [
|
|
6947
6963
|
{ key: "planShared", label: "A plan is shared with me", detail: "Someone sends you a plan or a client link." },
|
|
@@ -6953,7 +6969,7 @@ var NOTIFY = [
|
|
|
6953
6969
|
function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSessions = true, className = "", ...rest }) {
|
|
6954
6970
|
const session = SessionKit.useSession();
|
|
6955
6971
|
const user = userProp || session.user;
|
|
6956
|
-
const [draft, setDraft] =
|
|
6972
|
+
const [draft, setDraft] = React33.useState(() => ({
|
|
6957
6973
|
name: user.name || "",
|
|
6958
6974
|
title: user.title || "",
|
|
6959
6975
|
email: user.email || "",
|
|
@@ -6962,8 +6978,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6962
6978
|
bio: user.bio || "",
|
|
6963
6979
|
notify: user.notify || { planShared: true, planChanged: true, goalMissed: true, flagChanged: false, weekly: true }
|
|
6964
6980
|
}));
|
|
6965
|
-
const [saving, setSaving] =
|
|
6966
|
-
const [saved, setSaved] =
|
|
6981
|
+
const [saving, setSaving] = React33.useState(false);
|
|
6982
|
+
const [saved, setSaved] = React33.useState(false);
|
|
6967
6983
|
const set = (k, v) => {
|
|
6968
6984
|
setDraft((d) => Object.assign({}, d, { [k]: v }));
|
|
6969
6985
|
setSaved(false);
|
|
@@ -6985,22 +7001,22 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6985
7001
|
{ id: "s2", device: "iPhone 15 \xB7 Safari", where: "Denver, CO", when: "2 hours ago" },
|
|
6986
7002
|
{ id: "s3", device: "Windows \xB7 Edge", where: "Chicago, IL", when: "Aug 12" }
|
|
6987
7003
|
];
|
|
6988
|
-
return /* @__PURE__ */
|
|
6989
|
-
/* @__PURE__ */
|
|
7004
|
+
return /* @__PURE__ */ jsxs55("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, ...rest, children: [
|
|
7005
|
+
/* @__PURE__ */ jsxs55("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
6990
7006
|
/* @__PURE__ */ jsx59("span", { className: "fd-overline fd-muted", children: "Account" }),
|
|
6991
7007
|
/* @__PURE__ */ jsx59("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
|
|
6992
7008
|
/* @__PURE__ */ jsx59("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
|
|
6993
7009
|
] }),
|
|
6994
|
-
/* @__PURE__ */ jsx59(Card, { elevation: "flat", children: /* @__PURE__ */
|
|
7010
|
+
/* @__PURE__ */ jsx59(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs55("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
|
|
6995
7011
|
/* @__PURE__ */ jsx59(Avatar, { name: draft.name || user.name, size: "lg" }),
|
|
6996
|
-
/* @__PURE__ */
|
|
7012
|
+
/* @__PURE__ */ jsxs55("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
|
|
6997
7013
|
/* @__PURE__ */ jsx59("span", { className: "fd-h3", style: { margin: 0 }, children: draft.name || user.name }),
|
|
6998
|
-
/* @__PURE__ */
|
|
7014
|
+
/* @__PURE__ */ jsxs55("span", { className: "fd-body-sm fd-muted", children: [
|
|
6999
7015
|
draft.title || "No title set",
|
|
7000
7016
|
" \xB7 ",
|
|
7001
7017
|
user.team || "No team"
|
|
7002
7018
|
] }),
|
|
7003
|
-
/* @__PURE__ */
|
|
7019
|
+
/* @__PURE__ */ jsxs55("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
|
|
7004
7020
|
session.roles.map((r) => /* @__PURE__ */ jsx59(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
|
|
7005
7021
|
user.sso ? /* @__PURE__ */ jsx59(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
|
|
7006
7022
|
] })
|
|
@@ -7010,17 +7026,17 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7010
7026
|
/* @__PURE__ */ jsx59(
|
|
7011
7027
|
Card,
|
|
7012
7028
|
{
|
|
7013
|
-
title: /* @__PURE__ */
|
|
7029
|
+
title: /* @__PURE__ */ jsxs55("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
7014
7030
|
/* @__PURE__ */ jsx59("span", { children: "Identity" }),
|
|
7015
7031
|
/* @__PURE__ */ jsx59("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Name and title appear on plans you share" })
|
|
7016
7032
|
] }),
|
|
7017
7033
|
elevation: "flat",
|
|
7018
|
-
children: /* @__PURE__ */
|
|
7019
|
-
/* @__PURE__ */
|
|
7034
|
+
children: /* @__PURE__ */ jsxs55("div", { className: "fd-stack", style: { gap: 14 }, children: [
|
|
7035
|
+
/* @__PURE__ */ jsxs55("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
|
|
7020
7036
|
/* @__PURE__ */ jsx59(Input, { label: "Full name", value: draft.name, onChange: (e) => set("name", e.target.value) }),
|
|
7021
7037
|
/* @__PURE__ */ jsx59(Input, { label: "Job title", value: draft.title, onChange: (e) => set("title", e.target.value), placeholder: "e.g. Senior media planner" })
|
|
7022
7038
|
] }),
|
|
7023
|
-
/* @__PURE__ */
|
|
7039
|
+
/* @__PURE__ */ jsxs55("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
|
|
7024
7040
|
/* @__PURE__ */ jsx59(
|
|
7025
7041
|
Input,
|
|
7026
7042
|
{
|
|
@@ -7047,7 +7063,7 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7047
7063
|
] })
|
|
7048
7064
|
}
|
|
7049
7065
|
),
|
|
7050
|
-
/* @__PURE__ */ jsx59(Card, { title: "Working preferences", elevation: "flat", children: /* @__PURE__ */
|
|
7066
|
+
/* @__PURE__ */ jsx59(Card, { title: "Working preferences", elevation: "flat", children: /* @__PURE__ */ jsxs55("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
|
|
7051
7067
|
/* @__PURE__ */ jsx59(
|
|
7052
7068
|
Select,
|
|
7053
7069
|
{
|
|
@@ -7063,7 +7079,7 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7063
7079
|
/* @__PURE__ */ jsx59(
|
|
7064
7080
|
Card,
|
|
7065
7081
|
{
|
|
7066
|
-
title: /* @__PURE__ */
|
|
7082
|
+
title: /* @__PURE__ */ jsxs55("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
7067
7083
|
/* @__PURE__ */ jsx59("span", { children: "Notifications" }),
|
|
7068
7084
|
/* @__PURE__ */ jsx59("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Email only for now \u2014 in-app notifications are on the roadmap" })
|
|
7069
7085
|
] }),
|
|
@@ -7071,10 +7087,10 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7071
7087
|
children: /* @__PURE__ */ jsx59("div", { className: "fd-stack", style: { gap: 14 }, children: NOTIFY.map((n) => /* @__PURE__ */ jsx59(Switch, { checked: !!draft.notify[n.key], onChange: () => setNotify(n.key), label: n.label, description: n.detail }, n.key)) })
|
|
7072
7088
|
}
|
|
7073
7089
|
),
|
|
7074
|
-
/* @__PURE__ */
|
|
7090
|
+
/* @__PURE__ */ jsxs55(
|
|
7075
7091
|
Card,
|
|
7076
7092
|
{
|
|
7077
|
-
title: /* @__PURE__ */
|
|
7093
|
+
title: /* @__PURE__ */ jsxs55("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
7078
7094
|
/* @__PURE__ */ jsx59("span", { children: "Access" }),
|
|
7079
7095
|
/* @__PURE__ */ jsx59("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
|
|
7080
7096
|
] }),
|
|
@@ -7090,9 +7106,9 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7090
7106
|
}
|
|
7091
7107
|
),
|
|
7092
7108
|
children: [
|
|
7093
|
-
/* @__PURE__ */
|
|
7109
|
+
/* @__PURE__ */ jsxs55("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
7094
7110
|
/* @__PURE__ */ jsx59(CardRow, { label: "Roles", children: session.roles.map((r) => r.name).join(", ") || "None" }),
|
|
7095
|
-
/* @__PURE__ */
|
|
7111
|
+
/* @__PURE__ */ jsxs55(CardRow, { label: "Permissions", children: [
|
|
7096
7112
|
session.permissions.length,
|
|
7097
7113
|
" granted"
|
|
7098
7114
|
] }),
|
|
@@ -7108,11 +7124,11 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7108
7124
|
title: "Signed-in devices",
|
|
7109
7125
|
elevation: "flat",
|
|
7110
7126
|
action: /* @__PURE__ */ jsx59(Button, { size: "sm", variant: "ghost", icon: "sign-out", children: "Sign out everywhere" }),
|
|
7111
|
-
children: /* @__PURE__ */ jsx59("div", { className: "fd-stack", style: { gap: 0 }, children: liveSessions.map((s) => /* @__PURE__ */
|
|
7127
|
+
children: /* @__PURE__ */ jsx59("div", { className: "fd-stack", style: { gap: 0 }, children: liveSessions.map((s) => /* @__PURE__ */ jsxs55("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
|
|
7112
7128
|
/* @__PURE__ */ jsx59("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
7113
|
-
/* @__PURE__ */
|
|
7129
|
+
/* @__PURE__ */ jsxs55("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
|
|
7114
7130
|
/* @__PURE__ */ jsx59("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
|
|
7115
|
-
/* @__PURE__ */
|
|
7131
|
+
/* @__PURE__ */ jsxs55("span", { className: "fd-body-sm fd-muted", children: [
|
|
7116
7132
|
s.where,
|
|
7117
7133
|
" \xB7 ",
|
|
7118
7134
|
s.when
|
|
@@ -7122,7 +7138,7 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7122
7138
|
] }, s.id)) })
|
|
7123
7139
|
}
|
|
7124
7140
|
) : null,
|
|
7125
|
-
/* @__PURE__ */
|
|
7141
|
+
/* @__PURE__ */ jsxs55("div", { className: "fd-row", style: {
|
|
7126
7142
|
gap: 10,
|
|
7127
7143
|
flexWrap: "wrap",
|
|
7128
7144
|
position: "sticky",
|
|
@@ -7153,10 +7169,10 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7153
7169
|
}
|
|
7154
7170
|
|
|
7155
7171
|
// src/components/platform/RoadmapTimeline.tsx
|
|
7156
|
-
import * as
|
|
7172
|
+
import * as React35 from "react";
|
|
7157
7173
|
|
|
7158
7174
|
// src/kits/runtime.ts
|
|
7159
|
-
import * as
|
|
7175
|
+
import * as React34 from "react";
|
|
7160
7176
|
var WIRED_ENDPOINTS = [
|
|
7161
7177
|
// Nothing yet. Every id below would come from a real service:
|
|
7162
7178
|
// "plan.get", "placements.list", …
|
|
@@ -7327,8 +7343,8 @@ var RuntimeKit = {
|
|
|
7327
7343
|
};
|
|
7328
7344
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
7329
7345
|
function useRuntimeMode() {
|
|
7330
|
-
const [m, setM] =
|
|
7331
|
-
|
|
7346
|
+
const [m, setM] = React34.useState(RuntimeKit.getMode());
|
|
7347
|
+
React34.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
7332
7348
|
return m;
|
|
7333
7349
|
}
|
|
7334
7350
|
function useFeatureStatus(key) {
|
|
@@ -7347,7 +7363,7 @@ var UseRuntimeMode = useRuntimeMode;
|
|
|
7347
7363
|
var UseFeatureStatus = useFeatureStatus;
|
|
7348
7364
|
|
|
7349
7365
|
// src/components/platform/RoadmapTimeline.tsx
|
|
7350
|
-
import { jsx as jsx60, jsxs as
|
|
7366
|
+
import { jsx as jsx60, jsxs as jsxs56 } from "react/jsx-runtime";
|
|
7351
7367
|
var STATUS = {
|
|
7352
7368
|
shipped: { tone: "success", icon: "check-circle", label: "Wired" },
|
|
7353
7369
|
next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
|
|
@@ -7362,24 +7378,24 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
7362
7378
|
const s = STATUS[item.status] || STATUS.planned;
|
|
7363
7379
|
const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
|
|
7364
7380
|
const blocking = deps.filter((d) => !d.implemented);
|
|
7365
|
-
return /* @__PURE__ */ jsx60(Card, { elevation: "flat", children: /* @__PURE__ */
|
|
7366
|
-
/* @__PURE__ */
|
|
7381
|
+
return /* @__PURE__ */ jsx60(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs56("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
7382
|
+
/* @__PURE__ */ jsxs56("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
7367
7383
|
/* @__PURE__ */ jsx60("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
|
|
7368
7384
|
/* @__PURE__ */ jsx60(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
|
|
7369
7385
|
/* @__PURE__ */ jsx60(Badge, { tone: s.tone, icon: s.icon, children: s.label })
|
|
7370
7386
|
] }),
|
|
7371
7387
|
/* @__PURE__ */ jsx60("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
|
|
7372
|
-
item.backend ? /* @__PURE__ */
|
|
7388
|
+
item.backend ? /* @__PURE__ */ jsxs56("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
|
|
7373
7389
|
/* @__PURE__ */ jsx60("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
|
|
7374
7390
|
/* @__PURE__ */ jsx60("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
|
|
7375
7391
|
] }) : null,
|
|
7376
|
-
/* @__PURE__ */
|
|
7377
|
-
item.effort ? /* @__PURE__ */
|
|
7392
|
+
/* @__PURE__ */ jsxs56("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
7393
|
+
item.effort ? /* @__PURE__ */ jsxs56("span", { className: "fd-body-sm fd-muted", children: [
|
|
7378
7394
|
/* @__PURE__ */ jsx60("i", { className: "ph ph-hourglass-medium" }),
|
|
7379
7395
|
" ",
|
|
7380
7396
|
item.effort
|
|
7381
7397
|
] }) : null,
|
|
7382
|
-
/* @__PURE__ */
|
|
7398
|
+
/* @__PURE__ */ jsxs56("span", { className: "fd-body-sm fd-muted", children: [
|
|
7383
7399
|
/* @__PURE__ */ jsx60("i", { className: "ph ph-user" }),
|
|
7384
7400
|
" ",
|
|
7385
7401
|
item.owner
|
|
@@ -7396,11 +7412,11 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
7396
7412
|
}
|
|
7397
7413
|
)
|
|
7398
7414
|
] }),
|
|
7399
|
-
deps.length ? /* @__PURE__ */
|
|
7415
|
+
deps.length ? /* @__PURE__ */ jsxs56("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
|
|
7400
7416
|
/* @__PURE__ */ jsx60("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
|
|
7401
7417
|
deps.map((d) => /* @__PURE__ */ jsx60(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
|
|
7402
7418
|
] }) : null,
|
|
7403
|
-
blocking.length && !item.implemented ? /* @__PURE__ */
|
|
7419
|
+
blocking.length && !item.implemented ? /* @__PURE__ */ jsxs56("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
|
|
7404
7420
|
"Blocked until ",
|
|
7405
7421
|
blocking.map((d) => d.label).join(" and "),
|
|
7406
7422
|
" ",
|
|
@@ -7411,12 +7427,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
7411
7427
|
}
|
|
7412
7428
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
7413
7429
|
const session = SessionKit.useSession();
|
|
7414
|
-
const [project, setProject] =
|
|
7415
|
-
const [q, setQ] =
|
|
7416
|
-
const scrollRef =
|
|
7417
|
-
const nowRef =
|
|
7418
|
-
const rm =
|
|
7419
|
-
const byKey =
|
|
7430
|
+
const [project, setProject] = React35.useState("");
|
|
7431
|
+
const [q, setQ] = React35.useState("");
|
|
7432
|
+
const scrollRef = React35.useRef(null);
|
|
7433
|
+
const nowRef = React35.useRef(null);
|
|
7434
|
+
const rm = React35.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
7435
|
+
const byKey = React35.useMemo(() => {
|
|
7420
7436
|
const m = {};
|
|
7421
7437
|
rm.items.forEach((i) => {
|
|
7422
7438
|
m[i.key] = i;
|
|
@@ -7425,7 +7441,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7425
7441
|
}, [rm]);
|
|
7426
7442
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
7427
7443
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
7428
|
-
|
|
7444
|
+
React35.useEffect(() => {
|
|
7429
7445
|
let raf1 = 0, raf2 = 0;
|
|
7430
7446
|
const place = () => {
|
|
7431
7447
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -7453,19 +7469,19 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7453
7469
|
}, 0);
|
|
7454
7470
|
const nextPhase = items.find((i) => !i.implemented);
|
|
7455
7471
|
let lastPhase = null;
|
|
7456
|
-
return /* @__PURE__ */
|
|
7457
|
-
/* @__PURE__ */
|
|
7472
|
+
return /* @__PURE__ */ jsxs56("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
|
|
7473
|
+
/* @__PURE__ */ jsxs56("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
7458
7474
|
/* @__PURE__ */ jsx60("span", { className: "fd-overline fd-muted", children: "Architecture" }),
|
|
7459
7475
|
/* @__PURE__ */ jsx60("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
7460
7476
|
/* @__PURE__ */ jsx60("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." })
|
|
7461
7477
|
] }),
|
|
7462
|
-
/* @__PURE__ */
|
|
7478
|
+
/* @__PURE__ */ jsxs56("div", { className: "fd-grid-stats is-thin", children: [
|
|
7463
7479
|
/* @__PURE__ */ jsx60(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
|
|
7464
7480
|
/* @__PURE__ */ jsx60(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
|
|
7465
7481
|
/* @__PURE__ */ jsx60(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
|
|
7466
7482
|
/* @__PURE__ */ jsx60(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
|
|
7467
7483
|
] }),
|
|
7468
|
-
/* @__PURE__ */
|
|
7484
|
+
/* @__PURE__ */ jsxs56("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
7469
7485
|
/* @__PURE__ */ jsx60(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 } }),
|
|
7470
7486
|
/* @__PURE__ */ jsx60(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
|
|
7471
7487
|
/* @__PURE__ */ jsx60("span", { style: { flex: 1 } }),
|
|
@@ -7492,23 +7508,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7492
7508
|
actions: null
|
|
7493
7509
|
}
|
|
7494
7510
|
),
|
|
7495
|
-
/* @__PURE__ */ jsx60("div", { className: "fd-rm", children: /* @__PURE__ */ jsx60("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */
|
|
7511
|
+
/* @__PURE__ */ jsx60("div", { className: "fd-rm", children: /* @__PURE__ */ jsx60("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs56("div", { className: "fd-rm-track", children: [
|
|
7496
7512
|
/* @__PURE__ */ jsx60("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx60("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
|
|
7497
7513
|
items.map((item, n) => {
|
|
7498
7514
|
const showPhase = item.phase !== lastPhase;
|
|
7499
7515
|
lastPhase = item.phase;
|
|
7500
7516
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
7501
7517
|
const isBoundary = n === firstPending;
|
|
7502
|
-
return /* @__PURE__ */
|
|
7503
|
-
showPhase ? /* @__PURE__ */
|
|
7504
|
-
/* @__PURE__ */
|
|
7518
|
+
return /* @__PURE__ */ jsxs56(React35.Fragment, { children: [
|
|
7519
|
+
showPhase ? /* @__PURE__ */ jsxs56("div", { className: "fd-rm-era", children: [
|
|
7520
|
+
/* @__PURE__ */ jsxs56("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
7505
7521
|
/* @__PURE__ */ jsx60("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
7506
|
-
item.phase === 0 ? null : /* @__PURE__ */
|
|
7522
|
+
item.phase === 0 ? null : /* @__PURE__ */ jsxs56("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
7507
7523
|
fmtDate(item.phaseStart),
|
|
7508
7524
|
" \u2013 ",
|
|
7509
7525
|
fmtDate(item.date)
|
|
7510
7526
|
] }),
|
|
7511
|
-
/* @__PURE__ */
|
|
7527
|
+
/* @__PURE__ */ jsxs56("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
7512
7528
|
"\xB7 ",
|
|
7513
7529
|
inPhase,
|
|
7514
7530
|
" feature",
|
|
@@ -7517,13 +7533,13 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7517
7533
|
] }),
|
|
7518
7534
|
item.phaseWhy ? /* @__PURE__ */ jsx60("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
|
|
7519
7535
|
] }) : null,
|
|
7520
|
-
isBoundary ? /* @__PURE__ */ jsx60("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */
|
|
7536
|
+
isBoundary ? /* @__PURE__ */ jsx60("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs56("span", { className: "fd-rm-now-pill", children: [
|
|
7521
7537
|
/* @__PURE__ */ jsx60("i", { className: "ph ph-map-pin" }),
|
|
7522
7538
|
" You are here \u2014 everything above is wired"
|
|
7523
7539
|
] }) }) : null,
|
|
7524
|
-
/* @__PURE__ */
|
|
7540
|
+
/* @__PURE__ */ jsxs56("div", { className: "fd-rm-row", children: [
|
|
7525
7541
|
/* @__PURE__ */ jsx60("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
|
|
7526
|
-
/* @__PURE__ */
|
|
7542
|
+
/* @__PURE__ */ jsxs56("div", { className: "fd-rm-date", children: [
|
|
7527
7543
|
fmtDate(item.date),
|
|
7528
7544
|
/* @__PURE__ */ jsx60("br", {}),
|
|
7529
7545
|
/* @__PURE__ */ jsx60("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
|
|
@@ -7534,7 +7550,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7534
7550
|
}),
|
|
7535
7551
|
!items.length ? /* @__PURE__ */ jsx60("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
|
|
7536
7552
|
] }) }) }),
|
|
7537
|
-
/* @__PURE__ */
|
|
7553
|
+
/* @__PURE__ */ jsxs56("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
|
|
7538
7554
|
"Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
|
|
7539
7555
|
/* @__PURE__ */ jsx60("code", { className: "fd-mono", children: "implemented" }),
|
|
7540
7556
|
" field, so this page cannot drift from what the apps actually do."
|
|
@@ -7543,9 +7559,9 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7543
7559
|
}
|
|
7544
7560
|
|
|
7545
7561
|
// src/components/platform/ComingSoon.tsx
|
|
7546
|
-
import * as
|
|
7562
|
+
import * as React36 from "react";
|
|
7547
7563
|
import { createPortal as createPortal5 } from "react-dom";
|
|
7548
|
-
import { Fragment as Fragment16, jsx as jsx61, jsxs as
|
|
7564
|
+
import { Fragment as Fragment16, jsx as jsx61, jsxs as jsxs57 } from "react/jsx-runtime";
|
|
7549
7565
|
var SOON_HOVERCARD_BASE = 220;
|
|
7550
7566
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
7551
7567
|
function readBypassed() {
|
|
@@ -7562,8 +7578,8 @@ function writeBypassed(list) {
|
|
|
7562
7578
|
}
|
|
7563
7579
|
}
|
|
7564
7580
|
function useBypass(key) {
|
|
7565
|
-
const [on, setOn] =
|
|
7566
|
-
|
|
7581
|
+
const [on, setOn] = React36.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
7582
|
+
React36.useEffect(() => {
|
|
7567
7583
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
7568
7584
|
}, [key]);
|
|
7569
7585
|
const set = (next) => {
|
|
@@ -7576,43 +7592,43 @@ function useBypass(key) {
|
|
|
7576
7592
|
return [on, set];
|
|
7577
7593
|
}
|
|
7578
7594
|
function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
|
|
7579
|
-
return /* @__PURE__ */
|
|
7580
|
-
/* @__PURE__ */
|
|
7595
|
+
return /* @__PURE__ */ jsxs57(Fragment16, { children: [
|
|
7596
|
+
/* @__PURE__ */ jsxs57("span", { className: "fd-soon-badge", children: [
|
|
7581
7597
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
7582
7598
|
label
|
|
7583
7599
|
] }),
|
|
7584
7600
|
detail ? /* @__PURE__ */ jsx61("span", { className: "fd-soon-detail", children: detail }) : null,
|
|
7585
|
-
backend ? /* @__PURE__ */
|
|
7601
|
+
backend ? /* @__PURE__ */ jsxs57("span", { className: "fd-soon-backend", children: [
|
|
7586
7602
|
/* @__PURE__ */ jsx61("span", { className: "fd-overline", children: "Needs" }),
|
|
7587
7603
|
" ",
|
|
7588
7604
|
backend
|
|
7589
7605
|
] }) : null,
|
|
7590
|
-
eta || effort || onRoadmap ? /* @__PURE__ */
|
|
7591
|
-
eta ? /* @__PURE__ */
|
|
7606
|
+
eta || effort || onRoadmap ? /* @__PURE__ */ jsxs57("span", { className: "fd-soon-meta", children: [
|
|
7607
|
+
eta ? /* @__PURE__ */ jsxs57("span", { children: [
|
|
7592
7608
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
|
|
7593
7609
|
" ",
|
|
7594
7610
|
eta
|
|
7595
7611
|
] }) : null,
|
|
7596
|
-
effort ? /* @__PURE__ */
|
|
7612
|
+
effort ? /* @__PURE__ */ jsxs57("span", { children: [
|
|
7597
7613
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
|
|
7598
7614
|
" ",
|
|
7599
7615
|
effort
|
|
7600
7616
|
] }) : null,
|
|
7601
|
-
onRoadmap ? /* @__PURE__ */
|
|
7617
|
+
onRoadmap ? /* @__PURE__ */ jsxs57("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
7602
7618
|
"See the roadmap ",
|
|
7603
7619
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7604
7620
|
] }) : null
|
|
7605
7621
|
] }) : null,
|
|
7606
|
-
allowed ? /* @__PURE__ */
|
|
7622
|
+
allowed ? /* @__PURE__ */ jsxs57("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
|
|
7607
7623
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-eye", "aria-hidden": "true" }),
|
|
7608
7624
|
" View and use it anyway"
|
|
7609
7625
|
] }) : null
|
|
7610
7626
|
] });
|
|
7611
7627
|
}
|
|
7612
7628
|
function useHoverCard(open) {
|
|
7613
|
-
const anchor =
|
|
7614
|
-
const [pos, setPos] =
|
|
7615
|
-
|
|
7629
|
+
const anchor = React36.useRef(null);
|
|
7630
|
+
const [pos, setPos] = React36.useState(null);
|
|
7631
|
+
React36.useLayoutEffect(() => {
|
|
7616
7632
|
if (!open || !anchor.current) {
|
|
7617
7633
|
setPos(null);
|
|
7618
7634
|
return;
|
|
@@ -7664,7 +7680,7 @@ function ComingSoon({
|
|
|
7664
7680
|
const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
|
|
7665
7681
|
if (inline) {
|
|
7666
7682
|
if (allowed && bypassed) {
|
|
7667
|
-
return /* @__PURE__ */
|
|
7683
|
+
return /* @__PURE__ */ jsxs57("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
|
|
7668
7684
|
children,
|
|
7669
7685
|
/* @__PURE__ */ jsx61(
|
|
7670
7686
|
"button",
|
|
@@ -7699,19 +7715,19 @@ function ComingSoon({
|
|
|
7699
7715
|
);
|
|
7700
7716
|
}
|
|
7701
7717
|
if (allowed && bypassed) {
|
|
7702
|
-
return /* @__PURE__ */
|
|
7703
|
-
/* @__PURE__ */
|
|
7704
|
-
/* @__PURE__ */
|
|
7718
|
+
return /* @__PURE__ */ jsxs57("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
|
|
7719
|
+
/* @__PURE__ */ jsxs57("div", { className: "fd-soon-bar", role: "status", children: [
|
|
7720
|
+
/* @__PURE__ */ jsxs57("span", { className: "fd-soon-badge", children: [
|
|
7705
7721
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
7706
7722
|
"Unwired feature \u2014 you are using it anyway"
|
|
7707
7723
|
] }),
|
|
7708
7724
|
/* @__PURE__ */ jsx61("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
|
|
7709
|
-
/* @__PURE__ */
|
|
7710
|
-
onRoadmap ? /* @__PURE__ */
|
|
7725
|
+
/* @__PURE__ */ jsxs57("span", { className: "fd-soon-bar-actions", children: [
|
|
7726
|
+
onRoadmap ? /* @__PURE__ */ jsxs57("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
7711
7727
|
"Roadmap ",
|
|
7712
7728
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7713
7729
|
] }) : null,
|
|
7714
|
-
/* @__PURE__ */
|
|
7730
|
+
/* @__PURE__ */ jsxs57("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
|
|
7715
7731
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
|
|
7716
7732
|
" Re-blur"
|
|
7717
7733
|
] })
|
|
@@ -7720,7 +7736,7 @@ function ComingSoon({
|
|
|
7720
7736
|
children
|
|
7721
7737
|
] });
|
|
7722
7738
|
}
|
|
7723
|
-
return /* @__PURE__ */
|
|
7739
|
+
return /* @__PURE__ */ jsxs57("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
|
|
7724
7740
|
/* @__PURE__ */ jsx61("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
7725
7741
|
/* @__PURE__ */ jsx61("div", { className: "fd-soon-veil" }),
|
|
7726
7742
|
/* @__PURE__ */ jsx61("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx61(
|
|
@@ -7739,10 +7755,10 @@ function ComingSoon({
|
|
|
7739
7755
|
] });
|
|
7740
7756
|
}
|
|
7741
7757
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
7742
|
-
const [open, setOpen] =
|
|
7758
|
+
const [open, setOpen] = React36.useState(false);
|
|
7743
7759
|
const [anchor, pos] = useHoverCard(open);
|
|
7744
7760
|
const zIndex = useOverlayLayer(SOON_HOVERCARD_BASE);
|
|
7745
|
-
const close =
|
|
7761
|
+
const close = React36.useRef(null);
|
|
7746
7762
|
const show = () => {
|
|
7747
7763
|
if (close.current) {
|
|
7748
7764
|
clearTimeout(close.current);
|
|
@@ -7758,10 +7774,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7758
7774
|
setOpen(false);
|
|
7759
7775
|
}, 140);
|
|
7760
7776
|
};
|
|
7761
|
-
|
|
7777
|
+
React36.useEffect(() => () => {
|
|
7762
7778
|
if (close.current) clearTimeout(close.current);
|
|
7763
7779
|
}, []);
|
|
7764
|
-
return /* @__PURE__ */
|
|
7780
|
+
return /* @__PURE__ */ jsxs57(
|
|
7765
7781
|
"span",
|
|
7766
7782
|
{
|
|
7767
7783
|
ref: anchor,
|
|
@@ -7826,10 +7842,10 @@ function formatEta(iso2) {
|
|
|
7826
7842
|
var FormatEta = formatEta;
|
|
7827
7843
|
|
|
7828
7844
|
// src/components/platform/Gate.tsx
|
|
7829
|
-
import { jsx as jsx62, jsxs as
|
|
7845
|
+
import { jsx as jsx62, jsxs as jsxs58 } from "react/jsx-runtime";
|
|
7830
7846
|
function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
|
|
7831
7847
|
const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
|
|
7832
|
-
return /* @__PURE__ */
|
|
7848
|
+
return /* @__PURE__ */ jsxs58(
|
|
7833
7849
|
"div",
|
|
7834
7850
|
{
|
|
7835
7851
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -7845,12 +7861,12 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
7845
7861
|
},
|
|
7846
7862
|
...rest,
|
|
7847
7863
|
children: [
|
|
7848
|
-
/* @__PURE__ */
|
|
7864
|
+
/* @__PURE__ */ jsxs58("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
7849
7865
|
/* @__PURE__ */ jsx62("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
7850
7866
|
/* @__PURE__ */ jsx62("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
|
|
7851
7867
|
] }),
|
|
7852
7868
|
/* @__PURE__ */ jsx62("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." }),
|
|
7853
|
-
need.length ? /* @__PURE__ */
|
|
7869
|
+
need.length ? /* @__PURE__ */ jsxs58("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
|
|
7854
7870
|
/* @__PURE__ */ jsx62("span", { className: "fd-overline fd-muted", children: "Requires" }),
|
|
7855
7871
|
need.map((p) => /* @__PURE__ */ jsx62("code", { className: "fd-mono", style: {
|
|
7856
7872
|
fontSize: 11.5,
|
|
@@ -7927,15 +7943,15 @@ function PermissionHint({ perm, children }) {
|
|
|
7927
7943
|
}
|
|
7928
7944
|
|
|
7929
7945
|
// src/components/platform/ModeSwitch.tsx
|
|
7930
|
-
import * as
|
|
7931
|
-
import { Fragment as Fragment17, jsx as jsx63, jsxs as
|
|
7946
|
+
import * as React37 from "react";
|
|
7947
|
+
import { Fragment as Fragment17, jsx as jsx63, jsxs as jsxs59 } from "react/jsx-runtime";
|
|
7932
7948
|
var MODE_SWITCH_BASE = 140;
|
|
7933
7949
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
7934
7950
|
const mode2 = useRuntimeMode();
|
|
7935
|
-
const [open, setOpen] =
|
|
7951
|
+
const [open, setOpen] = React37.useState(false);
|
|
7936
7952
|
const zIndex = useOverlayLayer(MODE_SWITCH_BASE);
|
|
7937
|
-
const ref =
|
|
7938
|
-
|
|
7953
|
+
const ref = React37.useRef(null);
|
|
7954
|
+
React37.useEffect(() => {
|
|
7939
7955
|
if (!open) return;
|
|
7940
7956
|
const away = (e) => {
|
|
7941
7957
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -7957,8 +7973,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7957
7973
|
RuntimeKit.setMode(next);
|
|
7958
7974
|
setOpen(false);
|
|
7959
7975
|
};
|
|
7960
|
-
return /* @__PURE__ */
|
|
7961
|
-
/* @__PURE__ */
|
|
7976
|
+
return /* @__PURE__ */ jsxs59("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
|
|
7977
|
+
/* @__PURE__ */ jsxs59(
|
|
7962
7978
|
"button",
|
|
7963
7979
|
{
|
|
7964
7980
|
type: "button",
|
|
@@ -7973,13 +7989,13 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7973
7989
|
]
|
|
7974
7990
|
}
|
|
7975
7991
|
),
|
|
7976
|
-
open ? /* @__PURE__ */ jsx63(LayerProvider, { zIndex, children: /* @__PURE__ */
|
|
7977
|
-
/* @__PURE__ */
|
|
7978
|
-
/* @__PURE__ */
|
|
7992
|
+
open ? /* @__PURE__ */ jsx63(LayerProvider, { zIndex, children: /* @__PURE__ */ jsxs59("span", { className: "fd-view-enter fd-mode-pop", style: { zIndex }, children: [
|
|
7993
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
7994
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
|
|
7979
7995
|
/* @__PURE__ */ jsx63("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
|
|
7980
7996
|
test ? "Test mode" : "Live mode"
|
|
7981
7997
|
] }),
|
|
7982
|
-
test ? /* @__PURE__ */
|
|
7998
|
+
test ? /* @__PURE__ */ jsxs59("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
7983
7999
|
requestCount,
|
|
7984
8000
|
" simulated request",
|
|
7985
8001
|
requestCount === 1 ? "" : "s"
|
|
@@ -7987,10 +8003,10 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7987
8003
|
/* @__PURE__ */ jsx63("span", { style: { flex: 1 } }),
|
|
7988
8004
|
test && onClearLog ? /* @__PURE__ */ jsx63("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
|
|
7989
8005
|
] }),
|
|
7990
|
-
/* @__PURE__ */
|
|
8006
|
+
/* @__PURE__ */ jsxs59("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
7991
8007
|
/* @__PURE__ */ jsx63("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." }),
|
|
7992
|
-
/* @__PURE__ */
|
|
7993
|
-
/* @__PURE__ */
|
|
8008
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
|
|
8009
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
7994
8010
|
s.endpointsWired,
|
|
7995
8011
|
" endpoint",
|
|
7996
8012
|
s.endpointsWired === 1 ? "" : "s",
|
|
@@ -8000,9 +8016,9 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
8000
8016
|
s.total,
|
|
8001
8017
|
" features complete"
|
|
8002
8018
|
] }),
|
|
8003
|
-
onOpenSpec ? /* @__PURE__ */
|
|
8019
|
+
onOpenSpec ? /* @__PURE__ */ jsxs59(Fragment17, { children: [
|
|
8004
8020
|
/* @__PURE__ */ jsx63("span", { style: { flex: 1 } }),
|
|
8005
|
-
/* @__PURE__ */
|
|
8021
|
+
/* @__PURE__ */ jsxs59("button", { type: "button", className: "fd-soon-link", onClick: () => {
|
|
8006
8022
|
setOpen(false);
|
|
8007
8023
|
onOpenSpec();
|
|
8008
8024
|
}, children: [
|
|
@@ -8012,18 +8028,18 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
8012
8028
|
] }) : null
|
|
8013
8029
|
] })
|
|
8014
8030
|
] }),
|
|
8015
|
-
/* @__PURE__ */
|
|
8016
|
-
/* @__PURE__ */
|
|
8031
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-mode-choice", children: [
|
|
8032
|
+
/* @__PURE__ */ jsxs59("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
|
|
8017
8033
|
/* @__PURE__ */ jsx63("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
8018
|
-
/* @__PURE__ */
|
|
8034
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-mode-opt-text", children: [
|
|
8019
8035
|
/* @__PURE__ */ jsx63("span", { className: "fd-mode-opt-title", children: "Live mode" }),
|
|
8020
8036
|
/* @__PURE__ */ jsx63("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
|
|
8021
8037
|
] }),
|
|
8022
8038
|
!test ? /* @__PURE__ */ jsx63("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
8023
8039
|
] }),
|
|
8024
|
-
/* @__PURE__ */
|
|
8040
|
+
/* @__PURE__ */ jsxs59("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
|
|
8025
8041
|
/* @__PURE__ */ jsx63("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
8026
|
-
/* @__PURE__ */
|
|
8042
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-mode-opt-text", children: [
|
|
8027
8043
|
/* @__PURE__ */ jsx63("span", { className: "fd-mode-opt-title", children: "Test mode" }),
|
|
8028
8044
|
/* @__PURE__ */ jsx63("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
|
|
8029
8045
|
] }),
|
|
@@ -8037,13 +8053,13 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
8037
8053
|
function TestModeBar({ onExit }) {
|
|
8038
8054
|
const mode2 = useRuntimeMode();
|
|
8039
8055
|
if (mode2 !== "test") return null;
|
|
8040
|
-
return /* @__PURE__ */
|
|
8041
|
-
/* @__PURE__ */
|
|
8056
|
+
return /* @__PURE__ */ jsxs59("div", { className: "fd-testbar", role: "status", children: [
|
|
8057
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-badge fd-badge-warning", children: [
|
|
8042
8058
|
/* @__PURE__ */ jsx63("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
8043
8059
|
"Test mode"
|
|
8044
8060
|
] }),
|
|
8045
8061
|
/* @__PURE__ */ jsx63("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
|
|
8046
|
-
/* @__PURE__ */
|
|
8062
|
+
/* @__PURE__ */ jsxs59("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
|
|
8047
8063
|
/* @__PURE__ */ jsx63("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
8048
8064
|
" Back to live mode"
|
|
8049
8065
|
] })
|
|
@@ -8051,7 +8067,7 @@ function TestModeBar({ onExit }) {
|
|
|
8051
8067
|
}
|
|
8052
8068
|
|
|
8053
8069
|
// src/components/planner/ChannelMeta.tsx
|
|
8054
|
-
import { jsx as jsx64, jsxs as
|
|
8070
|
+
import { jsx as jsx64, jsxs as jsxs60 } from "react/jsx-runtime";
|
|
8055
8071
|
var CHANNEL_WEIGHTS = {
|
|
8056
8072
|
"OOH": 50,
|
|
8057
8073
|
"DOOH": 50,
|
|
@@ -8106,7 +8122,7 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
8106
8122
|
if (dot) {
|
|
8107
8123
|
return /* @__PURE__ */ jsx64("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
|
|
8108
8124
|
}
|
|
8109
|
-
return /* @__PURE__ */
|
|
8125
|
+
return /* @__PURE__ */ jsxs60(
|
|
8110
8126
|
"span",
|
|
8111
8127
|
{
|
|
8112
8128
|
className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
|
|
@@ -8123,7 +8139,7 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
8123
8139
|
}
|
|
8124
8140
|
|
|
8125
8141
|
// src/components/planner/SaturationDistribution.tsx
|
|
8126
|
-
import { jsx as jsx65, jsxs as
|
|
8142
|
+
import { jsx as jsx65, jsxs as jsxs61 } from "react/jsx-runtime";
|
|
8127
8143
|
var BANDS2 = [
|
|
8128
8144
|
{ key: "weak", label: "Weak", n: 1, range: "< 50" },
|
|
8129
8145
|
{ key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
|
|
@@ -8134,11 +8150,11 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8134
8150
|
const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
|
|
8135
8151
|
const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
|
|
8136
8152
|
const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
|
|
8137
|
-
return /* @__PURE__ */
|
|
8153
|
+
return /* @__PURE__ */ jsxs61("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
8138
8154
|
/* @__PURE__ */ jsx65("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
|
|
8139
8155
|
const mark = "var(--csi-" + g.n + "-mark)";
|
|
8140
8156
|
const active = selectedBand === g.key;
|
|
8141
|
-
return /* @__PURE__ */
|
|
8157
|
+
return /* @__PURE__ */ jsxs61(
|
|
8142
8158
|
"button",
|
|
8143
8159
|
{
|
|
8144
8160
|
type: "button",
|
|
@@ -8154,13 +8170,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8154
8170
|
},
|
|
8155
8171
|
c.name
|
|
8156
8172
|
)) }),
|
|
8157
|
-
/* @__PURE__ */
|
|
8173
|
+
/* @__PURE__ */ jsxs61("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
|
|
8158
8174
|
/* @__PURE__ */ jsx65("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
|
|
8159
8175
|
/* @__PURE__ */ jsx65("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx65("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
|
|
8160
8176
|
] }),
|
|
8161
|
-
/* @__PURE__ */
|
|
8177
|
+
/* @__PURE__ */ jsxs61("span", { className: "fd-stack", style: { gap: 1 }, children: [
|
|
8162
8178
|
/* @__PURE__ */ jsx65("span", { className: "fd-label-lg", children: g.label }),
|
|
8163
|
-
/* @__PURE__ */
|
|
8179
|
+
/* @__PURE__ */ jsxs61("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
|
|
8164
8180
|
"CRP ",
|
|
8165
8181
|
g.range
|
|
8166
8182
|
] })
|
|
@@ -8170,10 +8186,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8170
8186
|
g.key
|
|
8171
8187
|
);
|
|
8172
8188
|
}) }),
|
|
8173
|
-
floorBand ? /* @__PURE__ */
|
|
8189
|
+
floorBand ? /* @__PURE__ */ jsxs61("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: [
|
|
8174
8190
|
/* @__PURE__ */ jsx65("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx65("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
|
|
8175
|
-
/* @__PURE__ */
|
|
8176
|
-
/* @__PURE__ */
|
|
8191
|
+
/* @__PURE__ */ jsxs61("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
|
|
8192
|
+
/* @__PURE__ */ jsxs61("strong", { style: { color: "var(--text)" }, children: [
|
|
8177
8193
|
"Plan floor ",
|
|
8178
8194
|
floorScore
|
|
8179
8195
|
] }),
|
|
@@ -8184,8 +8200,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8184
8200
|
}
|
|
8185
8201
|
|
|
8186
8202
|
// src/components/planner/MixGap.tsx
|
|
8187
|
-
import * as
|
|
8188
|
-
import { Fragment as Fragment18, jsx as jsx66, jsxs as
|
|
8203
|
+
import * as React38 from "react";
|
|
8204
|
+
import { Fragment as Fragment18, jsx as jsx66, jsxs as jsxs62 } from "react/jsx-runtime";
|
|
8189
8205
|
var MIX_GAP_LAYOUT = {
|
|
8190
8206
|
trackHeight: 30,
|
|
8191
8207
|
barHeight: 20,
|
|
@@ -8199,18 +8215,18 @@ function mixGapOffset(value, max) {
|
|
|
8199
8215
|
}
|
|
8200
8216
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
8201
8217
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
8202
|
-
const [hover, setHover] =
|
|
8218
|
+
const [hover, setHover] = React38.useState(null);
|
|
8203
8219
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
8204
8220
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
8205
8221
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
8206
8222
|
const barTop = (trackHeight - barHeight) / 2;
|
|
8207
|
-
return /* @__PURE__ */
|
|
8208
|
-
/* @__PURE__ */
|
|
8209
|
-
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */
|
|
8223
|
+
return /* @__PURE__ */ jsxs62("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
|
|
8224
|
+
/* @__PURE__ */ jsxs62("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
|
|
8225
|
+
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs62("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
8210
8226
|
/* @__PURE__ */ jsx66("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
|
|
8211
8227
|
l
|
|
8212
8228
|
] }, l)),
|
|
8213
|
-
/* @__PURE__ */
|
|
8229
|
+
/* @__PURE__ */ jsxs62("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
8214
8230
|
/* @__PURE__ */ jsx66("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
|
|
8215
8231
|
"Target"
|
|
8216
8232
|
] })
|
|
@@ -8220,7 +8236,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
8220
8236
|
const tone = toneOf(gap);
|
|
8221
8237
|
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 : "");
|
|
8222
8238
|
const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
|
|
8223
|
-
return /* @__PURE__ */
|
|
8239
|
+
return /* @__PURE__ */ jsxs62(
|
|
8224
8240
|
"div",
|
|
8225
8241
|
{
|
|
8226
8242
|
className: "fd-row",
|
|
@@ -8229,10 +8245,10 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
8229
8245
|
onMouseLeave: () => setHover(null),
|
|
8230
8246
|
children: [
|
|
8231
8247
|
/* @__PURE__ */ jsx66("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx66(ChannelTag, { channel: r.channel, size: "sm" }) }),
|
|
8232
|
-
/* @__PURE__ */ jsx66("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx66("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */
|
|
8248
|
+
/* @__PURE__ */ jsx66("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx66("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs62(Fragment18, { children: [
|
|
8233
8249
|
/* @__PURE__ */ jsx66("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)" } }),
|
|
8234
8250
|
/* @__PURE__ */ jsx66("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 } }),
|
|
8235
|
-
/* @__PURE__ */
|
|
8251
|
+
/* @__PURE__ */ jsxs62("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: [
|
|
8236
8252
|
r.realized,
|
|
8237
8253
|
"%"
|
|
8238
8254
|
] }),
|
|
@@ -8247,7 +8263,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
8247
8263
|
}
|
|
8248
8264
|
|
|
8249
8265
|
// src/components/planner/ChannelContribution.tsx
|
|
8250
|
-
import { jsx as jsx67, jsxs as
|
|
8266
|
+
import { jsx as jsx67, jsxs as jsxs63 } from "react/jsx-runtime";
|
|
8251
8267
|
var money = (n) => "$" + Math.round(n).toLocaleString();
|
|
8252
8268
|
function ChannelContribution({
|
|
8253
8269
|
channels = [],
|
|
@@ -8263,8 +8279,8 @@ function ChannelContribution({
|
|
|
8263
8279
|
const grand = total !== void 0 ? total : base + bonus;
|
|
8264
8280
|
const pct = (v) => grand ? v / grand * 100 : 0;
|
|
8265
8281
|
const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
|
|
8266
|
-
return /* @__PURE__ */
|
|
8267
|
-
loading ? /* @__PURE__ */ jsx67("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */
|
|
8282
|
+
return /* @__PURE__ */ jsxs63("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
8283
|
+
loading ? /* @__PURE__ */ jsx67("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs63("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
|
|
8268
8284
|
channels.map((c) => /* @__PURE__ */ jsx67(
|
|
8269
8285
|
"span",
|
|
8270
8286
|
{
|
|
@@ -8283,16 +8299,16 @@ function ChannelContribution({
|
|
|
8283
8299
|
}
|
|
8284
8300
|
) : null
|
|
8285
8301
|
] }),
|
|
8286
|
-
showTable ? /* @__PURE__ */
|
|
8287
|
-
/* @__PURE__ */ jsx67("thead", { children: /* @__PURE__ */
|
|
8302
|
+
showTable ? /* @__PURE__ */ jsxs63("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
|
|
8303
|
+
/* @__PURE__ */ jsx67("thead", { children: /* @__PURE__ */ jsxs63("tr", { children: [
|
|
8288
8304
|
/* @__PURE__ */ jsx67("th", { style: { width: "34%" }, children: "Channel" }),
|
|
8289
8305
|
/* @__PURE__ */ jsx67("th", { style: { width: "16%" }, children: "Weight" }),
|
|
8290
8306
|
/* @__PURE__ */ jsx67("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
|
|
8291
8307
|
/* @__PURE__ */ jsx67("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
|
|
8292
8308
|
/* @__PURE__ */ jsx67("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
|
|
8293
8309
|
] }) }),
|
|
8294
|
-
/* @__PURE__ */
|
|
8295
|
-
channels.map((c) => /* @__PURE__ */
|
|
8310
|
+
/* @__PURE__ */ jsxs63("tbody", { children: [
|
|
8311
|
+
channels.map((c) => /* @__PURE__ */ jsxs63("tr", { children: [
|
|
8296
8312
|
/* @__PURE__ */ jsx67("td", { children: /* @__PURE__ */ jsx67(ChannelTag, { channel: c.name, size: "sm" }) }),
|
|
8297
8313
|
/* @__PURE__ */ jsx67("td", { children: /* @__PURE__ */ jsx67(
|
|
8298
8314
|
"span",
|
|
@@ -8305,17 +8321,17 @@ function ChannelContribution({
|
|
|
8305
8321
|
) }),
|
|
8306
8322
|
/* @__PURE__ */ jsx67("td", { className: "is-num", children: c.spend }),
|
|
8307
8323
|
/* @__PURE__ */ jsx67("td", { className: "is-num", children: c.crp.toFixed(1) }),
|
|
8308
|
-
/* @__PURE__ */
|
|
8324
|
+
/* @__PURE__ */ jsxs63("td", { className: "is-num", children: [
|
|
8309
8325
|
pct(c.crp).toFixed(0),
|
|
8310
8326
|
"%"
|
|
8311
8327
|
] })
|
|
8312
8328
|
] }, c.name)),
|
|
8313
|
-
bonus > 0 ? /* @__PURE__ */
|
|
8314
|
-
/* @__PURE__ */ jsx67("td", { children: /* @__PURE__ */
|
|
8329
|
+
bonus > 0 ? /* @__PURE__ */ jsxs63("tr", { children: [
|
|
8330
|
+
/* @__PURE__ */ jsx67("td", { children: /* @__PURE__ */ jsxs63("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
|
|
8315
8331
|
/* @__PURE__ */ jsx67("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" } }),
|
|
8316
8332
|
"Surround-sound bonus"
|
|
8317
8333
|
] }) }),
|
|
8318
|
-
/* @__PURE__ */ jsx67("td", { children: /* @__PURE__ */
|
|
8334
|
+
/* @__PURE__ */ jsx67("td", { children: /* @__PURE__ */ jsxs63("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
|
|
8319
8335
|
"+",
|
|
8320
8336
|
bonusPct,
|
|
8321
8337
|
"% of +",
|
|
@@ -8324,12 +8340,12 @@ function ChannelContribution({
|
|
|
8324
8340
|
] }) }),
|
|
8325
8341
|
/* @__PURE__ */ jsx67("td", { className: "is-num fd-muted", children: "\u2014" }),
|
|
8326
8342
|
/* @__PURE__ */ jsx67("td", { className: "is-num", children: bonus.toFixed(1) }),
|
|
8327
|
-
/* @__PURE__ */
|
|
8343
|
+
/* @__PURE__ */ jsxs63("td", { className: "is-num", children: [
|
|
8328
8344
|
pct(bonus).toFixed(0),
|
|
8329
8345
|
"%"
|
|
8330
8346
|
] })
|
|
8331
8347
|
] }) : null,
|
|
8332
|
-
/* @__PURE__ */
|
|
8348
|
+
/* @__PURE__ */ jsxs63("tr", { style: { background: "var(--surface-2)" }, children: [
|
|
8333
8349
|
/* @__PURE__ */ jsx67("td", { style: { fontWeight: 700 }, children: "Campus total" }),
|
|
8334
8350
|
/* @__PURE__ */ jsx67("td", {}),
|
|
8335
8351
|
/* @__PURE__ */ jsx67("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
|
|
@@ -8342,8 +8358,8 @@ function ChannelContribution({
|
|
|
8342
8358
|
}
|
|
8343
8359
|
|
|
8344
8360
|
// src/components/planner/BudgetReallocator.tsx
|
|
8345
|
-
import * as
|
|
8346
|
-
import { Fragment as Fragment19, jsx as jsx68, jsxs as
|
|
8361
|
+
import * as React39 from "react";
|
|
8362
|
+
import { Fragment as Fragment19, jsx as jsx68, jsxs as jsxs64 } from "react/jsx-runtime";
|
|
8347
8363
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
8348
8364
|
function BudgetReallocator({
|
|
8349
8365
|
campus,
|
|
@@ -8358,8 +8374,8 @@ function BudgetReallocator({
|
|
|
8358
8374
|
onCancel,
|
|
8359
8375
|
className = ""
|
|
8360
8376
|
}) {
|
|
8361
|
-
const [draft, setDraft] =
|
|
8362
|
-
|
|
8377
|
+
const [draft, setDraft] = React39.useState(spend);
|
|
8378
|
+
React39.useEffect(() => setDraft(spend), [spend]);
|
|
8363
8379
|
const dirty = draft !== spend;
|
|
8364
8380
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
8365
8381
|
const nextBand = bandFor(nextCrp);
|
|
@@ -8374,21 +8390,21 @@ function BudgetReallocator({
|
|
|
8374
8390
|
setDraft(spend);
|
|
8375
8391
|
if (onCancel) onCancel();
|
|
8376
8392
|
};
|
|
8377
|
-
return /* @__PURE__ */
|
|
8393
|
+
return /* @__PURE__ */ jsxs64(
|
|
8378
8394
|
"div",
|
|
8379
8395
|
{
|
|
8380
8396
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
8381
8397
|
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)" },
|
|
8382
8398
|
children: [
|
|
8383
|
-
/* @__PURE__ */
|
|
8399
|
+
/* @__PURE__ */ jsxs64("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
8384
8400
|
/* @__PURE__ */ jsx68("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
|
|
8385
8401
|
/* @__PURE__ */ jsx68(CsiBadge, { band: nowBand, crp, size: "medium" }),
|
|
8386
|
-
dirty ? /* @__PURE__ */
|
|
8402
|
+
dirty ? /* @__PURE__ */ jsxs64(Fragment19, { children: [
|
|
8387
8403
|
/* @__PURE__ */ jsx68("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
|
|
8388
8404
|
/* @__PURE__ */ jsx68(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
|
|
8389
8405
|
] }) : null
|
|
8390
8406
|
] }),
|
|
8391
|
-
/* @__PURE__ */
|
|
8407
|
+
/* @__PURE__ */ jsxs64("div", { className: "fd-slider", children: [
|
|
8392
8408
|
/* @__PURE__ */ jsx68("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
8393
8409
|
dirty ? /* @__PURE__ */ jsx68("span", { className: "fd-slider-chip", style: { left: pct + "%", background: delta < 0 ? "var(--danger-solid)" : "var(--ok-solid)" }, children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString() }) : null,
|
|
8394
8410
|
/* @__PURE__ */ jsx68(
|
|
@@ -8407,8 +8423,8 @@ function BudgetReallocator({
|
|
|
8407
8423
|
}
|
|
8408
8424
|
)
|
|
8409
8425
|
] }),
|
|
8410
|
-
/* @__PURE__ */
|
|
8411
|
-
/* @__PURE__ */
|
|
8426
|
+
/* @__PURE__ */ jsxs64("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
8427
|
+
/* @__PURE__ */ jsxs64("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
|
|
8412
8428
|
/* @__PURE__ */ jsx68("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
|
|
8413
8429
|
/* @__PURE__ */ jsx68("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
|
|
8414
8430
|
] }),
|
|
@@ -8432,7 +8448,7 @@ function BudgetReallocator({
|
|
|
8432
8448
|
}
|
|
8433
8449
|
|
|
8434
8450
|
// src/components/planner/SurroundSound.tsx
|
|
8435
|
-
import { jsx as jsx69, jsxs as
|
|
8451
|
+
import { jsx as jsx69, jsxs as jsxs65 } from "react/jsx-runtime";
|
|
8436
8452
|
var CATEGORIES = [
|
|
8437
8453
|
{ key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
|
|
8438
8454
|
{ key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
|
|
@@ -8444,10 +8460,10 @@ var CATEGORIES = [
|
|
|
8444
8460
|
function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
|
|
8445
8461
|
const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
|
|
8446
8462
|
const single = present.length <= 2;
|
|
8447
|
-
return /* @__PURE__ */
|
|
8463
|
+
return /* @__PURE__ */ jsxs65("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
|
|
8448
8464
|
/* @__PURE__ */ jsx69("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
|
|
8449
8465
|
const on = present.includes(c.key);
|
|
8450
|
-
return /* @__PURE__ */
|
|
8466
|
+
return /* @__PURE__ */ jsxs65(
|
|
8451
8467
|
"span",
|
|
8452
8468
|
{
|
|
8453
8469
|
title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
|
|
@@ -8460,10 +8476,10 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
8460
8476
|
c.key
|
|
8461
8477
|
);
|
|
8462
8478
|
}) }),
|
|
8463
|
-
/* @__PURE__ */
|
|
8464
|
-
/* @__PURE__ */
|
|
8479
|
+
/* @__PURE__ */ jsxs65("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
8480
|
+
/* @__PURE__ */ jsxs65("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
8465
8481
|
/* @__PURE__ */ jsx69("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
|
|
8466
|
-
/* @__PURE__ */
|
|
8482
|
+
/* @__PURE__ */ jsxs65("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
|
|
8467
8483
|
"+",
|
|
8468
8484
|
bonusPct,
|
|
8469
8485
|
"% of +",
|
|
@@ -8472,7 +8488,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
8472
8488
|
] })
|
|
8473
8489
|
] }),
|
|
8474
8490
|
/* @__PURE__ */ jsx69("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx69("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
|
|
8475
|
-
/* @__PURE__ */
|
|
8491
|
+
/* @__PURE__ */ jsxs65("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
|
|
8476
8492
|
present.length,
|
|
8477
8493
|
" of 6 channel categories present.",
|
|
8478
8494
|
" ",
|
|
@@ -8484,7 +8500,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
8484
8500
|
}
|
|
8485
8501
|
|
|
8486
8502
|
// src/components/planner/Importance.tsx
|
|
8487
|
-
import { jsx as jsx70, jsxs as
|
|
8503
|
+
import { jsx as jsx70, jsxs as jsxs66 } from "react/jsx-runtime";
|
|
8488
8504
|
var IMPORTANCE_LEVELS = [
|
|
8489
8505
|
{ id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
|
|
8490
8506
|
{ id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
|
|
@@ -8514,7 +8530,7 @@ function importanceTokens(id) {
|
|
|
8514
8530
|
function ImportanceTag({ level, showLabel = true, size = "sm", className = "" }) {
|
|
8515
8531
|
const lvl = importanceLevel(level);
|
|
8516
8532
|
const t = importanceTokens(level);
|
|
8517
|
-
return /* @__PURE__ */
|
|
8533
|
+
return /* @__PURE__ */ jsxs66(
|
|
8518
8534
|
"span",
|
|
8519
8535
|
{
|
|
8520
8536
|
className: ["fd-imp-tag", size === "md" ? "is-md" : "", className].filter(Boolean).join(" "),
|
|
@@ -8529,8 +8545,8 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "" })
|
|
|
8529
8545
|
}
|
|
8530
8546
|
|
|
8531
8547
|
// src/components/planner/PreferenceMeter.tsx
|
|
8532
|
-
import * as
|
|
8533
|
-
import { jsx as jsx71, jsxs as
|
|
8548
|
+
import * as React40 from "react";
|
|
8549
|
+
import { jsx as jsx71, jsxs as jsxs67 } from "react/jsx-runtime";
|
|
8534
8550
|
function preferenceScore(criteria) {
|
|
8535
8551
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
8536
8552
|
const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
|
|
@@ -8559,7 +8575,7 @@ function PreferenceMeter({
|
|
|
8559
8575
|
className = ""
|
|
8560
8576
|
}) {
|
|
8561
8577
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
8562
|
-
const segments =
|
|
8578
|
+
const segments = React40.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
8563
8579
|
return /* @__PURE__ */ jsx71(
|
|
8564
8580
|
ScoreMeter,
|
|
8565
8581
|
{
|
|
@@ -8572,20 +8588,20 @@ function PreferenceMeter({
|
|
|
8572
8588
|
placement,
|
|
8573
8589
|
className,
|
|
8574
8590
|
breakdownLabel: breakdownTitle,
|
|
8575
|
-
breakdown: /* @__PURE__ */
|
|
8576
|
-
/* @__PURE__ */
|
|
8591
|
+
breakdown: /* @__PURE__ */ jsxs67("div", { className: "fd-prefbreak", children: [
|
|
8592
|
+
/* @__PURE__ */ jsxs67("div", { className: "fd-prefbreak-head", children: [
|
|
8577
8593
|
/* @__PURE__ */ jsx71("span", { className: "fd-label-lg", children: breakdownTitle }),
|
|
8578
8594
|
/* @__PURE__ */ jsx71("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
|
|
8579
8595
|
] }),
|
|
8580
8596
|
/* @__PURE__ */ jsx71("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
|
|
8581
8597
|
const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
|
|
8582
|
-
return /* @__PURE__ */
|
|
8598
|
+
return /* @__PURE__ */ jsxs67("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
|
|
8583
8599
|
/* @__PURE__ */ jsx71(ImportanceTag, { level: c.importance }),
|
|
8584
|
-
/* @__PURE__ */
|
|
8600
|
+
/* @__PURE__ */ jsxs67("span", { className: "fd-prefbreak-text", children: [
|
|
8585
8601
|
/* @__PURE__ */ jsx71("span", { className: "fd-prefbreak-label", children: c.label }),
|
|
8586
8602
|
c.note ? /* @__PURE__ */ jsx71("span", { className: "fd-prefbreak-note", children: c.note }) : null
|
|
8587
8603
|
] }),
|
|
8588
|
-
/* @__PURE__ */
|
|
8604
|
+
/* @__PURE__ */ jsxs67("span", { className: "fd-prefbreak-val fd-tabular", children: [
|
|
8589
8605
|
Math.round(Number(c.earned) || 0),
|
|
8590
8606
|
/* @__PURE__ */ jsx71("span", { className: "fd-prefbreak-sep", children: "/" }),
|
|
8591
8607
|
Math.round(c.weight)
|
|
@@ -8598,10 +8614,10 @@ function PreferenceMeter({
|
|
|
8598
8614
|
}
|
|
8599
8615
|
|
|
8600
8616
|
// src/components/chat/AgentChatPanel.tsx
|
|
8601
|
-
import * as
|
|
8617
|
+
import * as React46 from "react";
|
|
8602
8618
|
|
|
8603
8619
|
// src/components/chat/chatEngine.ts
|
|
8604
|
-
import * as
|
|
8620
|
+
import * as React41 from "react";
|
|
8605
8621
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
8606
8622
|
var JOB_PENDING = ["queued", "running"];
|
|
8607
8623
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -8655,22 +8671,22 @@ function useChatEngine(opts) {
|
|
|
8655
8671
|
onClear,
|
|
8656
8672
|
onFeedback
|
|
8657
8673
|
} = opts || {};
|
|
8658
|
-
const [status, setStatus] =
|
|
8659
|
-
const [threadId, setThreadId] =
|
|
8660
|
-
const [messages, setMessages] =
|
|
8661
|
-
const [queue, setQueue] =
|
|
8662
|
-
const [fatal, setFatal] =
|
|
8663
|
-
const [busy, setBusy] =
|
|
8664
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
8665
|
-
const listRef =
|
|
8666
|
-
const queueRef =
|
|
8667
|
-
const busyRef =
|
|
8668
|
-
const stoppedRef =
|
|
8669
|
-
const abortRef =
|
|
8670
|
-
const serverCount =
|
|
8671
|
-
const threadRef =
|
|
8672
|
-
const mounted =
|
|
8673
|
-
|
|
8674
|
+
const [status, setStatus] = React41.useState("idle");
|
|
8675
|
+
const [threadId, setThreadId] = React41.useState(null);
|
|
8676
|
+
const [messages, setMessages] = React41.useState([]);
|
|
8677
|
+
const [queue, setQueue] = React41.useState([]);
|
|
8678
|
+
const [fatal, setFatal] = React41.useState(null);
|
|
8679
|
+
const [busy, setBusy] = React41.useState(false);
|
|
8680
|
+
const [turnStartedAt, setTurnStartedAt] = React41.useState(null);
|
|
8681
|
+
const listRef = React41.useRef([]);
|
|
8682
|
+
const queueRef = React41.useRef([]);
|
|
8683
|
+
const busyRef = React41.useRef(false);
|
|
8684
|
+
const stoppedRef = React41.useRef(false);
|
|
8685
|
+
const abortRef = React41.useRef(null);
|
|
8686
|
+
const serverCount = React41.useRef(0);
|
|
8687
|
+
const threadRef = React41.useRef(null);
|
|
8688
|
+
const mounted = React41.useRef(true);
|
|
8689
|
+
React41.useEffect(() => {
|
|
8674
8690
|
mounted.current = true;
|
|
8675
8691
|
return () => {
|
|
8676
8692
|
mounted.current = false;
|
|
@@ -8692,14 +8708,14 @@ function useChatEngine(opts) {
|
|
|
8692
8708
|
}
|
|
8693
8709
|
return false;
|
|
8694
8710
|
};
|
|
8695
|
-
const loadThread =
|
|
8711
|
+
const loadThread = React41.useCallback(async (id) => {
|
|
8696
8712
|
const data = await apiAdapter.getThread(id);
|
|
8697
8713
|
const list = [...data && data.messages || []];
|
|
8698
8714
|
serverCount.current = list.length;
|
|
8699
8715
|
commit(list);
|
|
8700
8716
|
return list;
|
|
8701
8717
|
}, [apiAdapter]);
|
|
8702
|
-
|
|
8718
|
+
React41.useEffect(() => {
|
|
8703
8719
|
if (!apiAdapter) {
|
|
8704
8720
|
setStatus("idle");
|
|
8705
8721
|
setFatal(null);
|
|
@@ -8912,7 +8928,7 @@ function useChatEngine(opts) {
|
|
|
8912
8928
|
await dispatchTurn(turn);
|
|
8913
8929
|
}
|
|
8914
8930
|
}
|
|
8915
|
-
const send =
|
|
8931
|
+
const send = React41.useCallback((text, attachments) => {
|
|
8916
8932
|
const body = (text || "").trim();
|
|
8917
8933
|
if (!body && !(attachments && attachments.length)) return;
|
|
8918
8934
|
if (status === "disconnected") return;
|
|
@@ -8922,7 +8938,7 @@ function useChatEngine(opts) {
|
|
|
8922
8938
|
stoppedRef.current = false;
|
|
8923
8939
|
drain();
|
|
8924
8940
|
}, [status]);
|
|
8925
|
-
const stop =
|
|
8941
|
+
const stop = React41.useCallback(() => {
|
|
8926
8942
|
stoppedRef.current = true;
|
|
8927
8943
|
const ac = abortRef.current;
|
|
8928
8944
|
if (ac) {
|
|
@@ -8941,11 +8957,11 @@ function useChatEngine(opts) {
|
|
|
8941
8957
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
8942
8958
|
}
|
|
8943
8959
|
}, [apiAdapter]);
|
|
8944
|
-
const removeQueued =
|
|
8960
|
+
const removeQueued = React41.useCallback((id) => {
|
|
8945
8961
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
8946
8962
|
setQueue(queueRef.current.slice());
|
|
8947
8963
|
}, []);
|
|
8948
|
-
const retry =
|
|
8964
|
+
const retry = React41.useCallback(() => {
|
|
8949
8965
|
const list = listRef.current;
|
|
8950
8966
|
let at = -1;
|
|
8951
8967
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -8961,19 +8977,19 @@ function useChatEngine(opts) {
|
|
|
8961
8977
|
setQueue(queueRef.current.slice());
|
|
8962
8978
|
drain();
|
|
8963
8979
|
}, []);
|
|
8964
|
-
const clear =
|
|
8980
|
+
const clear = React41.useCallback(() => {
|
|
8965
8981
|
commit([]);
|
|
8966
8982
|
serverCount.current = 0;
|
|
8967
8983
|
queueRef.current = [];
|
|
8968
8984
|
setQueue([]);
|
|
8969
8985
|
onClear && onClear();
|
|
8970
8986
|
}, [onClear]);
|
|
8971
|
-
const setFeedback =
|
|
8987
|
+
const setFeedback = React41.useCallback((id, value) => {
|
|
8972
8988
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
8973
8989
|
const msg = listRef.current.find((m) => m.id === id);
|
|
8974
8990
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
8975
8991
|
}, [onFeedback]);
|
|
8976
|
-
const reload =
|
|
8992
|
+
const reload = React41.useCallback(async () => {
|
|
8977
8993
|
if (!threadRef.current) return;
|
|
8978
8994
|
setStatus("loading");
|
|
8979
8995
|
try {
|
|
@@ -9011,11 +9027,11 @@ var ChatKit = {
|
|
|
9011
9027
|
};
|
|
9012
9028
|
|
|
9013
9029
|
// src/components/chat/ChatTranscript.tsx
|
|
9014
|
-
import * as
|
|
9030
|
+
import * as React43 from "react";
|
|
9015
9031
|
|
|
9016
9032
|
// src/components/chat/ChatTurn.tsx
|
|
9017
|
-
import * as
|
|
9018
|
-
import { jsx as jsx72, jsxs as
|
|
9033
|
+
import * as React42 from "react";
|
|
9034
|
+
import { jsx as jsx72, jsxs as jsxs68 } from "react/jsx-runtime";
|
|
9019
9035
|
function JsonView({ value }) {
|
|
9020
9036
|
let text;
|
|
9021
9037
|
try {
|
|
@@ -9030,20 +9046,20 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
|
9030
9046
|
const s = schema || {};
|
|
9031
9047
|
const invalid = packet.valid === false;
|
|
9032
9048
|
const title = s.heading || packet.type;
|
|
9033
|
-
return /* @__PURE__ */
|
|
9034
|
-
/* @__PURE__ */
|
|
9049
|
+
return /* @__PURE__ */ jsxs68("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
|
|
9050
|
+
/* @__PURE__ */ jsxs68("header", { className: "fdc-packet-head", children: [
|
|
9035
9051
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
|
|
9036
9052
|
/* @__PURE__ */ jsx72("span", { className: "fdc-packet-title", children: title }),
|
|
9037
9053
|
packet.repaired ? /* @__PURE__ */ jsx72("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
|
|
9038
9054
|
invalid ? /* @__PURE__ */ jsx72("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
|
|
9039
9055
|
] }),
|
|
9040
|
-
invalid ? /* @__PURE__ */
|
|
9056
|
+
invalid ? /* @__PURE__ */ jsxs68("div", { className: "fdc-packet-alert", role: "alert", children: [
|
|
9041
9057
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
9042
9058
|
/* @__PURE__ */ jsx72("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
|
|
9043
9059
|
] }) : /* @__PURE__ */ jsx72("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx72(JsonView, { value: packet.payload }) }),
|
|
9044
|
-
!invalid && onApply ? /* @__PURE__ */
|
|
9060
|
+
!invalid && onApply ? /* @__PURE__ */ jsxs68("footer", { className: "fdc-packet-foot", children: [
|
|
9045
9061
|
packet.repaired ? /* @__PURE__ */ jsx72("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx72("span", {}),
|
|
9046
|
-
/* @__PURE__ */
|
|
9062
|
+
/* @__PURE__ */ jsxs68("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
|
|
9047
9063
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
|
|
9048
9064
|
applied ? "Applied" : s.applyLabel || "Apply"
|
|
9049
9065
|
] })
|
|
@@ -9051,13 +9067,13 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
|
9051
9067
|
] });
|
|
9052
9068
|
}
|
|
9053
9069
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
9054
|
-
const [open, setOpen] =
|
|
9070
|
+
const [open, setOpen] = React42.useState(defaultOpen);
|
|
9055
9071
|
if (!text) return null;
|
|
9056
|
-
return /* @__PURE__ */
|
|
9057
|
-
/* @__PURE__ */
|
|
9072
|
+
return /* @__PURE__ */ jsxs68("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
|
|
9073
|
+
/* @__PURE__ */ jsxs68("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
9058
9074
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-brain", "aria-hidden": "true" }),
|
|
9059
9075
|
/* @__PURE__ */ jsx72("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
|
|
9060
|
-
streaming ? /* @__PURE__ */
|
|
9076
|
+
streaming ? /* @__PURE__ */ jsxs68("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
9061
9077
|
/* @__PURE__ */ jsx72("span", {}),
|
|
9062
9078
|
/* @__PURE__ */ jsx72("span", {}),
|
|
9063
9079
|
/* @__PURE__ */ jsx72("span", {})
|
|
@@ -9068,19 +9084,19 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
|
9068
9084
|
] });
|
|
9069
9085
|
}
|
|
9070
9086
|
function Citations({ items = [], onOpen }) {
|
|
9071
|
-
const [open, setOpen] =
|
|
9087
|
+
const [open, setOpen] = React42.useState(false);
|
|
9072
9088
|
if (!items.length) return null;
|
|
9073
|
-
return /* @__PURE__ */
|
|
9074
|
-
/* @__PURE__ */
|
|
9089
|
+
return /* @__PURE__ */ jsxs68("div", { className: "fdc-cites", children: [
|
|
9090
|
+
/* @__PURE__ */ jsxs68("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
9075
9091
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
|
|
9076
|
-
/* @__PURE__ */
|
|
9092
|
+
/* @__PURE__ */ jsxs68("span", { children: [
|
|
9077
9093
|
items.length,
|
|
9078
9094
|
" source",
|
|
9079
9095
|
items.length === 1 ? "" : "s"
|
|
9080
9096
|
] }),
|
|
9081
9097
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
|
|
9082
9098
|
] }),
|
|
9083
|
-
open ? /* @__PURE__ */ jsx72("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */
|
|
9099
|
+
open ? /* @__PURE__ */ jsx72("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs68("li", { children: [
|
|
9084
9100
|
/* @__PURE__ */ jsx72("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
|
|
9085
9101
|
c.url ? /* @__PURE__ */ jsx72("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx72("span", { children: c.title || "Source" }),
|
|
9086
9102
|
c.detail ? /* @__PURE__ */ jsx72("span", { className: "fdc-cite-detail", children: c.detail }) : null
|
|
@@ -9094,24 +9110,24 @@ function clampText(text, max) {
|
|
|
9094
9110
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
9095
9111
|
}
|
|
9096
9112
|
function MessageBody({ message: m, ctx }) {
|
|
9097
|
-
const [expanded, setExpanded] =
|
|
9113
|
+
const [expanded, setExpanded] = React42.useState(false);
|
|
9098
9114
|
const isUser = m.role === "user";
|
|
9099
9115
|
const raw = m.text || "";
|
|
9100
9116
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
9101
9117
|
const body = clamped != null ? clamped : raw;
|
|
9102
9118
|
const showMd = ctx.markdown && !isUser;
|
|
9103
|
-
return /* @__PURE__ */
|
|
9119
|
+
return /* @__PURE__ */ jsxs68("div", { className: "fdc-body", children: [
|
|
9104
9120
|
m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx72(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
|
|
9105
9121
|
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx72(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
|
|
9106
|
-
body ? /* @__PURE__ */
|
|
9122
|
+
body ? /* @__PURE__ */ jsxs68("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
|
|
9107
9123
|
showMd ? /* @__PURE__ */ jsx72(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx72("div", { className: "fdc-plain", children: body }),
|
|
9108
9124
|
m.streaming ? /* @__PURE__ */ jsx72("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
|
|
9109
9125
|
] }) : null,
|
|
9110
|
-
clamped != null ? /* @__PURE__ */
|
|
9126
|
+
clamped != null ? /* @__PURE__ */ jsxs68("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
|
|
9111
9127
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
|
|
9112
9128
|
"Show more",
|
|
9113
9129
|
/* @__PURE__ */ jsx72("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
|
|
9114
|
-
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */
|
|
9130
|
+
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs68("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
|
|
9115
9131
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
|
|
9116
9132
|
"Show less"
|
|
9117
9133
|
] }) : null,
|
|
@@ -9127,33 +9143,33 @@ function MessageBody({ message: m, ctx }) {
|
|
|
9127
9143
|
}
|
|
9128
9144
|
) : null,
|
|
9129
9145
|
m.citations && m.citations.length ? /* @__PURE__ */ jsx72(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
|
|
9130
|
-
m.working ? /* @__PURE__ */
|
|
9131
|
-
/* @__PURE__ */
|
|
9146
|
+
m.working ? /* @__PURE__ */ jsxs68("div", { className: "fdc-working", role: "status", children: [
|
|
9147
|
+
/* @__PURE__ */ jsxs68("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
9132
9148
|
/* @__PURE__ */ jsx72("span", {}),
|
|
9133
9149
|
/* @__PURE__ */ jsx72("span", {}),
|
|
9134
9150
|
/* @__PURE__ */ jsx72("span", {})
|
|
9135
9151
|
] }),
|
|
9136
|
-
/* @__PURE__ */
|
|
9152
|
+
/* @__PURE__ */ jsxs68("span", { className: "fdc-working-label", children: [
|
|
9137
9153
|
m.resumed ? "Resuming" : "Working",
|
|
9138
|
-
m.job && m.job.status ? /* @__PURE__ */
|
|
9154
|
+
m.job && m.job.status ? /* @__PURE__ */ jsxs68("span", { className: "fdc-working-job", children: [
|
|
9139
9155
|
" \xB7 ",
|
|
9140
9156
|
m.job.status
|
|
9141
9157
|
] }) : null,
|
|
9142
|
-
m.job && m.job.detail ? /* @__PURE__ */
|
|
9158
|
+
m.job && m.job.detail ? /* @__PURE__ */ jsxs68("span", { className: "fdc-working-job", children: [
|
|
9143
9159
|
" \xB7 ",
|
|
9144
9160
|
m.job.detail
|
|
9145
9161
|
] }) : null
|
|
9146
9162
|
] }),
|
|
9147
9163
|
m.jobId ? /* @__PURE__ */ jsx72("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
|
|
9148
9164
|
] }) : null,
|
|
9149
|
-
m.stopped ? /* @__PURE__ */
|
|
9165
|
+
m.stopped ? /* @__PURE__ */ jsxs68("div", { className: "fdc-stopped", children: [
|
|
9150
9166
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
9151
9167
|
"Stopped"
|
|
9152
9168
|
] }) : null,
|
|
9153
|
-
m.error ? /* @__PURE__ */
|
|
9169
|
+
m.error ? /* @__PURE__ */ jsxs68("div", { className: "fdc-error", role: "alert", children: [
|
|
9154
9170
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
9155
9171
|
/* @__PURE__ */ jsx72("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
|
|
9156
|
-
m.retryable && ctx.onRetry ? /* @__PURE__ */
|
|
9172
|
+
m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs68("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
|
|
9157
9173
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
9158
9174
|
"Retry"
|
|
9159
9175
|
] }) : null
|
|
@@ -9161,9 +9177,9 @@ function MessageBody({ message: m, ctx }) {
|
|
|
9161
9177
|
] });
|
|
9162
9178
|
}
|
|
9163
9179
|
function useCopyRun() {
|
|
9164
|
-
const [done, setDone] =
|
|
9165
|
-
const t =
|
|
9166
|
-
|
|
9180
|
+
const [done, setDone] = React42.useState(false);
|
|
9181
|
+
const t = React42.useRef(null);
|
|
9182
|
+
React42.useEffect(() => () => {
|
|
9167
9183
|
if (t.current) clearTimeout(t.current);
|
|
9168
9184
|
}, []);
|
|
9169
9185
|
return [done, (text) => {
|
|
@@ -9183,14 +9199,14 @@ function RunActions({ group, ctx }) {
|
|
|
9183
9199
|
const isAssistant = group.role === "assistant";
|
|
9184
9200
|
const fb = last.feedback;
|
|
9185
9201
|
if (!ctx.messageActions) return null;
|
|
9186
|
-
return /* @__PURE__ */
|
|
9187
|
-
/* @__PURE__ */
|
|
9202
|
+
return /* @__PURE__ */ jsxs68("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
|
|
9203
|
+
/* @__PURE__ */ jsxs68("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
|
|
9188
9204
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
|
|
9189
9205
|
/* @__PURE__ */ jsx72("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
|
|
9190
9206
|
] }),
|
|
9191
9207
|
isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx72("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx72("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
9192
9208
|
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx72("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx72("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
9193
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */
|
|
9209
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs68(React42.Fragment, { children: [
|
|
9194
9210
|
/* @__PURE__ */ jsx72("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__ */ jsx72("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
9195
9211
|
/* @__PURE__ */ jsx72("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__ */ jsx72("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
9196
9212
|
] }) : null,
|
|
@@ -9202,14 +9218,14 @@ function ChatTurn({ group, ctx }) {
|
|
|
9202
9218
|
const name = isUser ? ctx.userName : group.author || ctx.assistantName;
|
|
9203
9219
|
const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
|
|
9204
9220
|
const stamp = group.messages[0].timestamp;
|
|
9205
|
-
return /* @__PURE__ */
|
|
9206
|
-
/* @__PURE__ */
|
|
9221
|
+
return /* @__PURE__ */ jsxs68("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
|
|
9222
|
+
/* @__PURE__ */ jsxs68("div", { className: "fdc-turn-head", children: [
|
|
9207
9223
|
ctx.showAvatars ? /* @__PURE__ */ jsx72("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx72("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx72("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx72("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
|
|
9208
9224
|
/* @__PURE__ */ jsx72("span", { className: "fdc-who", children: name }),
|
|
9209
9225
|
stamp ? /* @__PURE__ */ jsx72(RelativeTime, { className: "fdc-when", value: stamp }) : null,
|
|
9210
9226
|
group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx72("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
|
|
9211
9227
|
] }),
|
|
9212
|
-
/* @__PURE__ */
|
|
9228
|
+
/* @__PURE__ */ jsxs68("div", { className: "fdc-turn-body", children: [
|
|
9213
9229
|
group.messages.map((m) => /* @__PURE__ */ jsx72("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx72(MessageBody, { message: m, ctx }) }, m.id)),
|
|
9214
9230
|
/* @__PURE__ */ jsx72(RunActions, { group, ctx })
|
|
9215
9231
|
] })
|
|
@@ -9217,7 +9233,7 @@ function ChatTurn({ group, ctx }) {
|
|
|
9217
9233
|
}
|
|
9218
9234
|
|
|
9219
9235
|
// src/components/chat/ChatTranscript.tsx
|
|
9220
|
-
import { jsx as jsx73, jsxs as
|
|
9236
|
+
import { jsx as jsx73, jsxs as jsxs69 } from "react/jsx-runtime";
|
|
9221
9237
|
var GROUP_WINDOW = 6e4;
|
|
9222
9238
|
var STICK_PX = 100;
|
|
9223
9239
|
function groupMessages(list) {
|
|
@@ -9252,9 +9268,9 @@ function Suggestions({ items = [], onPick }) {
|
|
|
9252
9268
|
if (!items.length) return null;
|
|
9253
9269
|
return /* @__PURE__ */ jsx73("div", { className: "fdc-suggest", children: items.map((s, i) => {
|
|
9254
9270
|
const it = typeof s === "string" ? { label: s, text: s } : s;
|
|
9255
|
-
return /* @__PURE__ */
|
|
9271
|
+
return /* @__PURE__ */ jsxs69("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
|
|
9256
9272
|
it.icon ? /* @__PURE__ */ jsx73("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
|
|
9257
|
-
/* @__PURE__ */
|
|
9273
|
+
/* @__PURE__ */ jsxs69("span", { className: "fdc-suggest-text", children: [
|
|
9258
9274
|
/* @__PURE__ */ jsx73("span", { className: "fdc-suggest-label", children: it.label }),
|
|
9259
9275
|
it.description ? /* @__PURE__ */ jsx73("span", { className: "fdc-suggest-desc", children: it.description }) : null
|
|
9260
9276
|
] }),
|
|
@@ -9263,9 +9279,9 @@ function Suggestions({ items = [], onPick }) {
|
|
|
9263
9279
|
}) });
|
|
9264
9280
|
}
|
|
9265
9281
|
function LoadingTurns() {
|
|
9266
|
-
return /* @__PURE__ */ jsx73("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */
|
|
9282
|
+
return /* @__PURE__ */ jsx73("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs69("div", { className: "fdc-skel-turn", children: [
|
|
9267
9283
|
/* @__PURE__ */ jsx73("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
|
|
9268
|
-
/* @__PURE__ */
|
|
9284
|
+
/* @__PURE__ */ jsxs69("div", { className: "fdc-skel-lines", children: [
|
|
9269
9285
|
/* @__PURE__ */ jsx73("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
|
|
9270
9286
|
/* @__PURE__ */ jsx73("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
|
|
9271
9287
|
/* @__PURE__ */ jsx73("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
|
|
@@ -9285,10 +9301,10 @@ function ChatTranscript({
|
|
|
9285
9301
|
renderEmpty,
|
|
9286
9302
|
className = ""
|
|
9287
9303
|
}) {
|
|
9288
|
-
const scroller =
|
|
9289
|
-
const stick =
|
|
9290
|
-
const [pill, setPill] =
|
|
9291
|
-
const seen =
|
|
9304
|
+
const scroller = React43.useRef(null);
|
|
9305
|
+
const stick = React43.useRef(true);
|
|
9306
|
+
const [pill, setPill] = React43.useState(0);
|
|
9307
|
+
const seen = React43.useRef(0);
|
|
9292
9308
|
const toBottom = (smooth) => {
|
|
9293
9309
|
const el = scroller.current;
|
|
9294
9310
|
if (!el) return;
|
|
@@ -9307,7 +9323,7 @@ function ChatTranscript({
|
|
|
9307
9323
|
seen.current = messages.length;
|
|
9308
9324
|
}
|
|
9309
9325
|
};
|
|
9310
|
-
|
|
9326
|
+
React43.useLayoutEffect(() => {
|
|
9311
9327
|
const el = scroller.current;
|
|
9312
9328
|
if (!el) return;
|
|
9313
9329
|
if (stick.current) {
|
|
@@ -9315,7 +9331,7 @@ function ChatTranscript({
|
|
|
9315
9331
|
seen.current = messages.length;
|
|
9316
9332
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
9317
9333
|
}, [messages]);
|
|
9318
|
-
|
|
9334
|
+
React43.useEffect(() => {
|
|
9319
9335
|
const el = scroller.current;
|
|
9320
9336
|
const inner = el && el.firstChild;
|
|
9321
9337
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -9325,21 +9341,21 @@ function ChatTranscript({
|
|
|
9325
9341
|
ro.observe(inner);
|
|
9326
9342
|
return () => ro.disconnect();
|
|
9327
9343
|
}, []);
|
|
9328
|
-
const groups =
|
|
9344
|
+
const groups = React43.useMemo(() => groupMessages(messages), [messages]);
|
|
9329
9345
|
const empty = !messages.length && status === "ready";
|
|
9330
|
-
return /* @__PURE__ */
|
|
9331
|
-
/* @__PURE__ */
|
|
9346
|
+
return /* @__PURE__ */ jsxs69("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
9347
|
+
/* @__PURE__ */ jsxs69("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
9332
9348
|
status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx73(LoadingTurns, {}) : null,
|
|
9333
|
-
status === "disconnected" ? /* @__PURE__ */
|
|
9349
|
+
status === "disconnected" ? /* @__PURE__ */ jsxs69("div", { className: "fdc-dead", children: [
|
|
9334
9350
|
/* @__PURE__ */ jsx73("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx73("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
|
|
9335
9351
|
/* @__PURE__ */ jsx73("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
|
|
9336
9352
|
/* @__PURE__ */ jsx73("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." }),
|
|
9337
|
-
ctx.onReconnect ? /* @__PURE__ */
|
|
9353
|
+
ctx.onReconnect ? /* @__PURE__ */ jsxs69("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
|
|
9338
9354
|
/* @__PURE__ */ jsx73("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
9339
9355
|
"Try again"
|
|
9340
9356
|
] }) : null
|
|
9341
9357
|
] }) : null,
|
|
9342
|
-
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */
|
|
9358
|
+
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs69("div", { className: "fdc-empty", children: [
|
|
9343
9359
|
/* @__PURE__ */ jsx73("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx73("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
|
|
9344
9360
|
/* @__PURE__ */ jsx73("h3", { className: "fdc-empty-title", children: emptyTitle }),
|
|
9345
9361
|
emptyDescription ? /* @__PURE__ */ jsx73("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
|
|
@@ -9349,13 +9365,13 @@ function ChatTranscript({
|
|
|
9349
9365
|
const prev = groups[i - 1];
|
|
9350
9366
|
const k = dayKey(g.messages[0].timestamp);
|
|
9351
9367
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
9352
|
-
return /* @__PURE__ */
|
|
9368
|
+
return /* @__PURE__ */ jsxs69(React43.Fragment, { children: [
|
|
9353
9369
|
showDay ? /* @__PURE__ */ jsx73("div", { className: "fdc-day", children: /* @__PURE__ */ jsx73("span", { children: dayLabel(k) }) }) : null,
|
|
9354
9370
|
/* @__PURE__ */ jsx73(ChatTurn, { group: g, ctx })
|
|
9355
9371
|
] }, g.key || i);
|
|
9356
9372
|
})
|
|
9357
9373
|
] }),
|
|
9358
|
-
pill ? /* @__PURE__ */
|
|
9374
|
+
pill ? /* @__PURE__ */ jsxs69("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
|
|
9359
9375
|
/* @__PURE__ */ jsx73("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
|
|
9360
9376
|
pill,
|
|
9361
9377
|
" new message",
|
|
@@ -9366,8 +9382,8 @@ function ChatTranscript({
|
|
|
9366
9382
|
var TranscriptKit = { groupMessages };
|
|
9367
9383
|
|
|
9368
9384
|
// src/components/chat/ChatComposer.tsx
|
|
9369
|
-
import * as
|
|
9370
|
-
import { jsx as jsx74, jsxs as
|
|
9385
|
+
import * as React44 from "react";
|
|
9386
|
+
import { jsx as jsx74, jsxs as jsxs70 } from "react/jsx-runtime";
|
|
9371
9387
|
function ChatComposer({
|
|
9372
9388
|
onSubmit,
|
|
9373
9389
|
onStop,
|
|
@@ -9394,17 +9410,17 @@ function ChatComposer({
|
|
|
9394
9410
|
onReject,
|
|
9395
9411
|
onOpenAttachment
|
|
9396
9412
|
}) {
|
|
9397
|
-
const [text, setText] =
|
|
9398
|
-
const [trigger, setTrigger] =
|
|
9399
|
-
const [mentionItems, setMentionItems] =
|
|
9400
|
-
const [listening, setListening] =
|
|
9401
|
-
const [notice, setNotice] =
|
|
9402
|
-
const editor =
|
|
9403
|
-
const wrap =
|
|
9404
|
-
const stopVoice =
|
|
9413
|
+
const [text, setText] = React44.useState(draft || "");
|
|
9414
|
+
const [trigger, setTrigger] = React44.useState(null);
|
|
9415
|
+
const [mentionItems, setMentionItems] = React44.useState([]);
|
|
9416
|
+
const [listening, setListening] = React44.useState(false);
|
|
9417
|
+
const [notice, setNotice] = React44.useState(null);
|
|
9418
|
+
const editor = React44.useRef(null);
|
|
9419
|
+
const wrap = React44.useRef(null);
|
|
9420
|
+
const stopVoice = React44.useRef(null);
|
|
9405
9421
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
9406
9422
|
} });
|
|
9407
|
-
|
|
9423
|
+
React44.useEffect(() => {
|
|
9408
9424
|
if (draft != null && draft !== text) setText(draft);
|
|
9409
9425
|
}, [draft]);
|
|
9410
9426
|
const change = (v) => {
|
|
@@ -9438,7 +9454,7 @@ function ChatComposer({
|
|
|
9438
9454
|
e.preventDefault();
|
|
9439
9455
|
staged.add(found.files);
|
|
9440
9456
|
};
|
|
9441
|
-
|
|
9457
|
+
React44.useEffect(() => {
|
|
9442
9458
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
9443
9459
|
setMentionItems([]);
|
|
9444
9460
|
return;
|
|
@@ -9456,7 +9472,7 @@ function ChatComposer({
|
|
|
9456
9472
|
const q = (trigger.query || "").toLowerCase();
|
|
9457
9473
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
9458
9474
|
}, [trigger, mentionSources]);
|
|
9459
|
-
const slashItems =
|
|
9475
|
+
const slashItems = React44.useMemo(() => {
|
|
9460
9476
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
9461
9477
|
const q = (trigger.query || "").toLowerCase();
|
|
9462
9478
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -9533,8 +9549,8 @@ function ChatComposer({
|
|
|
9533
9549
|
stopVoice.current = typeof res === "function" ? res : () => {
|
|
9534
9550
|
};
|
|
9535
9551
|
};
|
|
9536
|
-
return /* @__PURE__ */
|
|
9537
|
-
queue.length ? /* @__PURE__ */ jsx74("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */
|
|
9552
|
+
return /* @__PURE__ */ jsxs70("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
|
|
9553
|
+
queue.length ? /* @__PURE__ */ jsx74("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs70("div", { className: "fdc-queue-row", children: [
|
|
9538
9554
|
/* @__PURE__ */ jsx74("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
|
|
9539
9555
|
/* @__PURE__ */ jsx74("span", { className: "fdc-queue-text", children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
|
|
9540
9556
|
onRemoveQueued ? /* @__PURE__ */ jsx74("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx74("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
@@ -9554,7 +9570,7 @@ function ChatComposer({
|
|
|
9554
9570
|
disabled: !fileUploadHandler || disabled,
|
|
9555
9571
|
label: "Drop to attach",
|
|
9556
9572
|
hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
|
|
9557
|
-
children: /* @__PURE__ */
|
|
9573
|
+
children: /* @__PURE__ */ jsxs70("div", { ref: wrap, className: "fdc-field-inner", children: [
|
|
9558
9574
|
staged.items.length ? /* @__PURE__ */ jsx74("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx74(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
|
|
9559
9575
|
/* @__PURE__ */ jsx74(
|
|
9560
9576
|
MarkdownEditor,
|
|
@@ -9575,20 +9591,20 @@ function ChatComposer({
|
|
|
9575
9591
|
ariaLabel: "Message"
|
|
9576
9592
|
}
|
|
9577
9593
|
),
|
|
9578
|
-
/* @__PURE__ */
|
|
9594
|
+
/* @__PURE__ */ jsxs70("div", { className: "fdc-tools", children: [
|
|
9579
9595
|
fileUploadHandler ? /* @__PURE__ */ jsx74(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
|
|
9580
9596
|
voiceHandler ? /* @__PURE__ */ jsx74("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx74("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
|
|
9581
9597
|
toolbarExtras,
|
|
9582
9598
|
/* @__PURE__ */ jsx74("span", { className: "fdc-tools-gap" }),
|
|
9583
|
-
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */
|
|
9599
|
+
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs70("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
|
|
9584
9600
|
text.length,
|
|
9585
9601
|
"/",
|
|
9586
9602
|
maxLength
|
|
9587
9603
|
] }) : null,
|
|
9588
|
-
busy ? /* @__PURE__ */
|
|
9604
|
+
busy ? /* @__PURE__ */ jsxs70("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
|
|
9589
9605
|
/* @__PURE__ */ jsx74("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
9590
9606
|
/* @__PURE__ */ jsx74("span", { children: "Stop" })
|
|
9591
|
-
] }) : /* @__PURE__ */
|
|
9607
|
+
] }) : /* @__PURE__ */ jsxs70("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
|
|
9592
9608
|
/* @__PURE__ */ jsx74("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
|
|
9593
9609
|
/* @__PURE__ */ jsx74("span", { className: "fdc-send-label", children: "Send" })
|
|
9594
9610
|
] })
|
|
@@ -9596,7 +9612,7 @@ function ChatComposer({
|
|
|
9596
9612
|
] })
|
|
9597
9613
|
}
|
|
9598
9614
|
),
|
|
9599
|
-
notice ? /* @__PURE__ */
|
|
9615
|
+
notice ? /* @__PURE__ */ jsxs70("div", { className: "fdc-notice", role: "status", children: [
|
|
9600
9616
|
/* @__PURE__ */ jsx74("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
9601
9617
|
notice
|
|
9602
9618
|
] }) : null,
|
|
@@ -9630,12 +9646,12 @@ function ChatComposer({
|
|
|
9630
9646
|
}
|
|
9631
9647
|
|
|
9632
9648
|
// src/components/chat/ChatSessionBar.tsx
|
|
9633
|
-
import * as
|
|
9634
|
-
import { jsx as jsx75, jsxs as
|
|
9649
|
+
import * as React45 from "react";
|
|
9650
|
+
import { jsx as jsx75, jsxs as jsxs71 } from "react/jsx-runtime";
|
|
9635
9651
|
var compact2 = meterFormats.compact;
|
|
9636
9652
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
9637
|
-
const [open, setOpen] =
|
|
9638
|
-
const anchor =
|
|
9653
|
+
const [open, setOpen] = React45.useState(false);
|
|
9654
|
+
const anchor = React45.useRef(null);
|
|
9639
9655
|
const stats = sessionStats || null;
|
|
9640
9656
|
const cu = contextUsage || null;
|
|
9641
9657
|
const limits = usageLimits || null;
|
|
@@ -9650,9 +9666,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9650
9666
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
9651
9667
|
if (cu) bits.push(pct + "% context");
|
|
9652
9668
|
const expandable = !!(cu || limits);
|
|
9653
|
-
return /* @__PURE__ */
|
|
9654
|
-
/* @__PURE__ */
|
|
9655
|
-
/* @__PURE__ */
|
|
9669
|
+
return /* @__PURE__ */ jsxs71(React45.Fragment, { children: [
|
|
9670
|
+
/* @__PURE__ */ jsxs71("div", { className: "fdc-bar", children: [
|
|
9671
|
+
/* @__PURE__ */ jsxs71(
|
|
9656
9672
|
"button",
|
|
9657
9673
|
{
|
|
9658
9674
|
type: "button",
|
|
@@ -9682,14 +9698,14 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9682
9698
|
maxHeight: 460,
|
|
9683
9699
|
padded: true,
|
|
9684
9700
|
label: "Usage",
|
|
9685
|
-
footer: onClear ? /* @__PURE__ */
|
|
9701
|
+
footer: onClear ? /* @__PURE__ */ jsxs71("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
|
|
9686
9702
|
setOpen(false);
|
|
9687
9703
|
onClear();
|
|
9688
9704
|
}, children: [
|
|
9689
9705
|
/* @__PURE__ */ jsx75("i", { className: "ph ph-trash", "aria-hidden": "true" }),
|
|
9690
9706
|
"Clear conversation"
|
|
9691
9707
|
] }) : void 0,
|
|
9692
|
-
children: /* @__PURE__ */
|
|
9708
|
+
children: /* @__PURE__ */ jsxs71("div", { className: "fdc-usage", children: [
|
|
9693
9709
|
cu ? /* @__PURE__ */ jsx75("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx75(
|
|
9694
9710
|
SegmentedMeter,
|
|
9695
9711
|
{
|
|
@@ -9702,7 +9718,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9702
9718
|
remainderLabel: "Free"
|
|
9703
9719
|
}
|
|
9704
9720
|
) }) : null,
|
|
9705
|
-
limits && limits.length ? /* @__PURE__ */
|
|
9721
|
+
limits && limits.length ? /* @__PURE__ */ jsxs71("section", { className: "fdc-usage-sec", children: [
|
|
9706
9722
|
/* @__PURE__ */ jsx75("h4", { className: "fdc-usage-h", children: "Usage limits" }),
|
|
9707
9723
|
/* @__PURE__ */ jsx75("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx75(
|
|
9708
9724
|
QuotaRow,
|
|
@@ -9714,23 +9730,23 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9714
9730
|
l.id
|
|
9715
9731
|
)) })
|
|
9716
9732
|
] }) : null,
|
|
9717
|
-
stats ? /* @__PURE__ */
|
|
9718
|
-
stats.elapsedMs ? /* @__PURE__ */
|
|
9733
|
+
stats ? /* @__PURE__ */ jsxs71("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
|
|
9734
|
+
stats.elapsedMs ? /* @__PURE__ */ jsxs71("div", { children: [
|
|
9719
9735
|
/* @__PURE__ */ jsx75("span", { children: "Session" }),
|
|
9720
9736
|
/* @__PURE__ */ jsx75("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
|
|
9721
9737
|
] }) : null,
|
|
9722
|
-
stats.tokens ? /* @__PURE__ */
|
|
9738
|
+
stats.tokens ? /* @__PURE__ */ jsxs71("div", { children: [
|
|
9723
9739
|
/* @__PURE__ */ jsx75("span", { children: "Tokens" }),
|
|
9724
9740
|
/* @__PURE__ */ jsx75("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
|
|
9725
9741
|
] }) : null,
|
|
9726
|
-
stats.costUsd != null ? /* @__PURE__ */
|
|
9742
|
+
stats.costUsd != null ? /* @__PURE__ */ jsxs71("div", { children: [
|
|
9727
9743
|
/* @__PURE__ */ jsx75("span", { children: "Cost" }),
|
|
9728
|
-
/* @__PURE__ */
|
|
9744
|
+
/* @__PURE__ */ jsxs71("b", { className: "fd-tabular", children: [
|
|
9729
9745
|
"$",
|
|
9730
9746
|
Number(stats.costUsd).toFixed(3)
|
|
9731
9747
|
] })
|
|
9732
9748
|
] }) : null,
|
|
9733
|
-
stats.turns ? /* @__PURE__ */
|
|
9749
|
+
stats.turns ? /* @__PURE__ */ jsxs71("div", { children: [
|
|
9734
9750
|
/* @__PURE__ */ jsx75("span", { children: "Turns" }),
|
|
9735
9751
|
/* @__PURE__ */ jsx75("b", { className: "fd-tabular", children: stats.turns })
|
|
9736
9752
|
] }) : null
|
|
@@ -9784,14 +9800,14 @@ function ModelControls({
|
|
|
9784
9800
|
items.push({ kind: "section", label: "Fast mode" });
|
|
9785
9801
|
items.push({
|
|
9786
9802
|
kind: "custom",
|
|
9787
|
-
render: () => /* @__PURE__ */
|
|
9803
|
+
render: () => /* @__PURE__ */ jsxs71("label", { className: "fdc-switchrow", children: [
|
|
9788
9804
|
/* @__PURE__ */ jsx75("span", { children: fastModeLabel }),
|
|
9789
9805
|
/* @__PURE__ */ jsx75("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
|
|
9790
9806
|
/* @__PURE__ */ jsx75("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx75("span", { className: "fd-switch-thumb" }) })
|
|
9791
9807
|
] })
|
|
9792
9808
|
});
|
|
9793
9809
|
}
|
|
9794
|
-
return /* @__PURE__ */
|
|
9810
|
+
return /* @__PURE__ */ jsxs71(React45.Fragment, { children: [
|
|
9795
9811
|
/* @__PURE__ */ jsx75(
|
|
9796
9812
|
MenuButton,
|
|
9797
9813
|
{
|
|
@@ -9824,7 +9840,7 @@ function ModelControls({
|
|
|
9824
9840
|
}
|
|
9825
9841
|
|
|
9826
9842
|
// src/components/chat/AgentChatPanel.tsx
|
|
9827
|
-
import { jsx as jsx76, jsxs as
|
|
9843
|
+
import { jsx as jsx76, jsxs as jsxs72 } from "react/jsx-runtime";
|
|
9828
9844
|
var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
|
|
9829
9845
|
function AgentChatPanel({
|
|
9830
9846
|
/* required */
|
|
@@ -9908,11 +9924,11 @@ function AgentChatPanel({
|
|
|
9908
9924
|
onFeedback,
|
|
9909
9925
|
onEditMessage
|
|
9910
9926
|
}) {
|
|
9911
|
-
const [panelWidth, setPanelWidth] =
|
|
9912
|
-
const [applied, setApplied] =
|
|
9913
|
-
const [draft, setDraft] =
|
|
9914
|
-
const dragging =
|
|
9915
|
-
|
|
9927
|
+
const [panelWidth, setPanelWidth] = React46.useState(width);
|
|
9928
|
+
const [applied, setApplied] = React46.useState({});
|
|
9929
|
+
const [draft, setDraft] = React46.useState("");
|
|
9930
|
+
const dragging = React46.useRef(null);
|
|
9931
|
+
React46.useEffect(() => setPanelWidth(width), [width]);
|
|
9916
9932
|
const engine = useChatEngine({
|
|
9917
9933
|
contextType,
|
|
9918
9934
|
contextId,
|
|
@@ -10029,7 +10045,7 @@ function AgentChatPanel({
|
|
|
10029
10045
|
})))
|
|
10030
10046
|
}
|
|
10031
10047
|
) : null;
|
|
10032
|
-
return /* @__PURE__ */
|
|
10048
|
+
return /* @__PURE__ */ jsxs72(
|
|
10033
10049
|
"aside",
|
|
10034
10050
|
{
|
|
10035
10051
|
className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
|
|
@@ -10055,13 +10071,13 @@ function AgentChatPanel({
|
|
|
10055
10071
|
}
|
|
10056
10072
|
}
|
|
10057
10073
|
) : null,
|
|
10058
|
-
showHeader ? /* @__PURE__ */
|
|
10074
|
+
showHeader ? /* @__PURE__ */ jsxs72("header", { className: "fdc-head", children: [
|
|
10059
10075
|
/* @__PURE__ */ jsx76("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx76("i", { className: "ph ph-" + assistantIcon }) }),
|
|
10060
|
-
/* @__PURE__ */
|
|
10076
|
+
/* @__PURE__ */ jsxs72("span", { className: "fdc-head-titles", children: [
|
|
10061
10077
|
/* @__PURE__ */ jsx76("span", { className: "fdc-head-title", children: title }),
|
|
10062
10078
|
subtitle ? /* @__PURE__ */ jsx76("span", { className: "fdc-head-sub", children: subtitle }) : null
|
|
10063
10079
|
] }),
|
|
10064
|
-
/* @__PURE__ */
|
|
10080
|
+
/* @__PURE__ */ jsxs72("span", { className: "fdc-head-acts", children: [
|
|
10065
10081
|
headerActions,
|
|
10066
10082
|
threadMenu,
|
|
10067
10083
|
onNewThread ? /* @__PURE__ */ jsx76("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx76("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
|
|
@@ -10116,7 +10132,7 @@ function AgentChatPanel({
|
|
|
10116
10132
|
}
|
|
10117
10133
|
|
|
10118
10134
|
// src/kits/query.ts
|
|
10119
|
-
import * as
|
|
10135
|
+
import * as React47 from "react";
|
|
10120
10136
|
function eqFilter(get2) {
|
|
10121
10137
|
return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
|
|
10122
10138
|
}
|
|
@@ -10148,22 +10164,22 @@ function compare(a, b, dir) {
|
|
|
10148
10164
|
var API = null;
|
|
10149
10165
|
var PREFS = null;
|
|
10150
10166
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
10151
|
-
const [query, setQuery] =
|
|
10167
|
+
const [query, setQuery] = React47.useState(() => {
|
|
10152
10168
|
const store = PREFS || window.PlannerPrefs;
|
|
10153
10169
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
10154
10170
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
10155
10171
|
});
|
|
10156
|
-
const savePref =
|
|
10172
|
+
const savePref = React47.useCallback((patch2) => {
|
|
10157
10173
|
const store = PREFS || window.PlannerPrefs;
|
|
10158
10174
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
10159
10175
|
}, [prefsKey]);
|
|
10160
|
-
const [res, setRes] =
|
|
10161
|
-
const [loading, setLoading] =
|
|
10162
|
-
const seq2 =
|
|
10176
|
+
const [res, setRes] = React47.useState(null);
|
|
10177
|
+
const [loading, setLoading] = React47.useState(true);
|
|
10178
|
+
const seq2 = React47.useRef(0);
|
|
10163
10179
|
const depKey = (deps || []).join("|");
|
|
10164
10180
|
const paramKey = JSON.stringify(params || {});
|
|
10165
10181
|
const queryKey = JSON.stringify(query);
|
|
10166
|
-
|
|
10182
|
+
React47.useEffect(() => {
|
|
10167
10183
|
const id = ++seq2.current;
|
|
10168
10184
|
setLoading(true);
|
|
10169
10185
|
const t = setTimeout(() => {
|
|
@@ -10616,6 +10632,7 @@ export {
|
|
|
10616
10632
|
meterFormats,
|
|
10617
10633
|
modifierLabel,
|
|
10618
10634
|
pastedTextName,
|
|
10635
|
+
pluralizeUnit,
|
|
10619
10636
|
preferenceScore,
|
|
10620
10637
|
preferenceSegments,
|
|
10621
10638
|
rangeFilter,
|