@flytedan/flytebot-design-system 0.12.5 → 0.12.6
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 +313 -303
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +795 -785
- 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,7 @@ 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";
|
|
2145
2155
|
function Pagination({
|
|
2146
2156
|
page = 1,
|
|
2147
2157
|
pageSize = 25,
|
|
@@ -2166,12 +2176,12 @@ function Pagination({
|
|
|
2166
2176
|
if (i === 1 || i === totalPages || Math.abs(i - page) <= span) nums.push(i);
|
|
2167
2177
|
else if (nums[nums.length - 1] !== "\u2026") nums.push("\u2026");
|
|
2168
2178
|
}
|
|
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__ */
|
|
2179
|
+
return /* @__PURE__ */ jsxs29("div", { className: ["fd-pag", className].filter(Boolean).join(" "), ...rest, children: [
|
|
2180
|
+
/* @__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
2181
|
"No ",
|
|
2172
2182
|
unit
|
|
2173
|
-
] }) : /* @__PURE__ */
|
|
2174
|
-
/* @__PURE__ */
|
|
2183
|
+
] }) : /* @__PURE__ */ jsxs29(Fragment7, { children: [
|
|
2184
|
+
/* @__PURE__ */ jsxs29("strong", { children: [
|
|
2175
2185
|
from.toLocaleString(),
|
|
2176
2186
|
"\u2013",
|
|
2177
2187
|
to.toLocaleString()
|
|
@@ -2181,11 +2191,11 @@ function Pagination({
|
|
|
2181
2191
|
" ",
|
|
2182
2192
|
unit
|
|
2183
2193
|
] }) }),
|
|
2184
|
-
onPageSizeChange ? /* @__PURE__ */
|
|
2194
|
+
onPageSizeChange ? /* @__PURE__ */ jsxs29("label", { className: "fd-pag-size", children: [
|
|
2185
2195
|
/* @__PURE__ */ jsx33("span", { children: "Rows" }),
|
|
2186
2196
|
/* @__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
2197
|
] }) : null,
|
|
2188
|
-
/* @__PURE__ */
|
|
2198
|
+
/* @__PURE__ */ jsxs29("span", { className: "fd-pag-nav", children: [
|
|
2189
2199
|
/* @__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
2200
|
/* @__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
2201
|
nums.map((n, i) => n === "\u2026" ? /* @__PURE__ */ jsx33("span", { className: "fd-pag-gap", "aria-hidden": "true", children: "\u2026" }, "e" + i) : /* @__PURE__ */ jsx33(
|
|
@@ -2206,8 +2216,8 @@ function Pagination({
|
|
|
2206
2216
|
}
|
|
2207
2217
|
|
|
2208
2218
|
// src/components/data/RelativeTime.tsx
|
|
2209
|
-
import * as
|
|
2210
|
-
import { jsxs as
|
|
2219
|
+
import * as React12 from "react";
|
|
2220
|
+
import { jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2211
2221
|
var MIN = 6e4;
|
|
2212
2222
|
var HOUR = 36e5;
|
|
2213
2223
|
var DAY = 864e5;
|
|
@@ -2258,9 +2268,9 @@ function formatDuration(ms) {
|
|
|
2258
2268
|
return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
|
|
2259
2269
|
}
|
|
2260
2270
|
function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
|
|
2261
|
-
const [, force] =
|
|
2271
|
+
const [, force] = React12.useState(0);
|
|
2262
2272
|
const t = value instanceof Date ? value.getTime() : Date.parse(value);
|
|
2263
|
-
|
|
2273
|
+
React12.useEffect(() => {
|
|
2264
2274
|
if (!refresh2 || !t || isNaN(t)) return;
|
|
2265
2275
|
const abs = Math.abs(t - Date.now());
|
|
2266
2276
|
if (abs > DAY) return;
|
|
@@ -2269,17 +2279,17 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
|
|
|
2269
2279
|
return () => clearInterval(id);
|
|
2270
2280
|
}, [t, refresh2]);
|
|
2271
2281
|
if (!t || isNaN(t)) return null;
|
|
2272
|
-
return /* @__PURE__ */
|
|
2282
|
+
return /* @__PURE__ */ jsxs30("time", { className, dateTime: new Date(t).toISOString(), title: formatAbsolute(new Date(t)), ...rest, children: [
|
|
2273
2283
|
prefix ? prefix + " " : "",
|
|
2274
2284
|
formatRelative(new Date(t))
|
|
2275
2285
|
] });
|
|
2276
2286
|
}
|
|
2277
2287
|
|
|
2278
2288
|
// src/components/data/ScoreMeter.tsx
|
|
2279
|
-
import * as
|
|
2289
|
+
import * as React14 from "react";
|
|
2280
2290
|
|
|
2281
2291
|
// src/components/data/SegmentedMeter.tsx
|
|
2282
|
-
import * as
|
|
2292
|
+
import * as React13 from "react";
|
|
2283
2293
|
|
|
2284
2294
|
// src/kits/files.ts
|
|
2285
2295
|
function formatBytes(n) {
|
|
@@ -2439,7 +2449,7 @@ var FileKit = {
|
|
|
2439
2449
|
};
|
|
2440
2450
|
|
|
2441
2451
|
// src/components/data/SegmentedMeter.tsx
|
|
2442
|
-
import { jsx as jsx34, jsxs as
|
|
2452
|
+
import { jsx as jsx34, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2443
2453
|
var VARIANT_FILL = {
|
|
2444
2454
|
brand: "var(--brand)",
|
|
2445
2455
|
neutral: "var(--n-400)",
|
|
@@ -2484,16 +2494,16 @@ function SegmentedMeter({
|
|
|
2484
2494
|
const pct = safeTotal ? Math.min(100, Math.round(used / safeTotal * 100)) : 0;
|
|
2485
2495
|
const w = (v) => safeTotal ? Math.max(0, Math.min(100, Number(v) / safeTotal * 100)) : 0;
|
|
2486
2496
|
const fill = (s, i) => s.color || (s.variant ? VARIANT_FILL[s.variant] : void 0) || CHART[i % CHART.length];
|
|
2487
|
-
const generatedId =
|
|
2497
|
+
const generatedId = React13.useId();
|
|
2488
2498
|
const uid2 = id || generatedId;
|
|
2489
|
-
return /* @__PURE__ */
|
|
2490
|
-
label || showTotal ? /* @__PURE__ */
|
|
2499
|
+
return /* @__PURE__ */ jsxs31("div", { className: ["fd-segmeter", className].filter(Boolean).join(" "), onClick, children: [
|
|
2500
|
+
label || showTotal ? /* @__PURE__ */ jsxs31("div", { className: "fd-segmeter-head", children: [
|
|
2491
2501
|
label ? /* @__PURE__ */ jsx34("span", { className: "fd-segmeter-label", id: uid2 + "-l", children: label }) : /* @__PURE__ */ jsx34("span", {}),
|
|
2492
|
-
showTotal ? /* @__PURE__ */
|
|
2502
|
+
showTotal ? /* @__PURE__ */ jsxs31("span", { className: "fd-segmeter-total fd-tabular", children: [
|
|
2493
2503
|
format(used),
|
|
2494
2504
|
/* @__PURE__ */ jsx34("span", { className: "fd-segmeter-sep", children: " / " }),
|
|
2495
2505
|
safeTotal ? format(safeTotal) : "\u2014",
|
|
2496
|
-
showPercent ? /* @__PURE__ */
|
|
2506
|
+
showPercent ? /* @__PURE__ */ jsxs31("span", { className: "fd-segmeter-pct", children: [
|
|
2497
2507
|
" (",
|
|
2498
2508
|
pct,
|
|
2499
2509
|
"%)"
|
|
@@ -2523,13 +2533,13 @@ function SegmentedMeter({
|
|
|
2523
2533
|
))
|
|
2524
2534
|
}
|
|
2525
2535
|
),
|
|
2526
|
-
legend ? /* @__PURE__ */
|
|
2527
|
-
items.map((s, i) => /* @__PURE__ */
|
|
2536
|
+
legend ? /* @__PURE__ */ jsxs31("ul", { className: "fd-segmeter-legend", children: [
|
|
2537
|
+
items.map((s, i) => /* @__PURE__ */ jsxs31("li", { children: [
|
|
2528
2538
|
/* @__PURE__ */ jsx34("span", { className: "fd-segmeter-dot", style: { background: fill(s, i) }, "aria-hidden": "true" }),
|
|
2529
2539
|
/* @__PURE__ */ jsx34("span", { className: "fd-segmeter-key", children: s.label }),
|
|
2530
2540
|
/* @__PURE__ */ jsx34("span", { className: "fd-segmeter-val fd-tabular", children: format(s.value) })
|
|
2531
2541
|
] }, s.id || s.label || i)),
|
|
2532
|
-
safeTotal && used < safeTotal ? /* @__PURE__ */
|
|
2542
|
+
safeTotal && used < safeTotal ? /* @__PURE__ */ jsxs31("li", { className: "is-remainder", children: [
|
|
2533
2543
|
/* @__PURE__ */ jsx34("span", { className: "fd-segmeter-dot is-empty", "aria-hidden": "true" }),
|
|
2534
2544
|
/* @__PURE__ */ jsx34("span", { className: "fd-segmeter-key", children: remainderLabel }),
|
|
2535
2545
|
/* @__PURE__ */ jsx34("span", { className: "fd-segmeter-val fd-tabular", children: format(safeTotal - used) })
|
|
@@ -2540,11 +2550,11 @@ function SegmentedMeter({
|
|
|
2540
2550
|
function QuotaRow({ label, percent = 0, note, tone, className = "" }) {
|
|
2541
2551
|
const p = Math.max(0, Math.min(100, Math.round(Number(percent) || 0)));
|
|
2542
2552
|
const auto = p >= 90 ? "danger" : p >= 70 ? "warn" : "brand";
|
|
2543
|
-
return /* @__PURE__ */
|
|
2544
|
-
/* @__PURE__ */
|
|
2553
|
+
return /* @__PURE__ */ jsxs31("div", { className: ["fd-quota", className].filter(Boolean).join(" "), children: [
|
|
2554
|
+
/* @__PURE__ */ jsxs31("div", { className: "fd-quota-head", children: [
|
|
2545
2555
|
/* @__PURE__ */ jsx34("span", { className: "fd-quota-label", children: label }),
|
|
2546
2556
|
note ? /* @__PURE__ */ jsx34("span", { className: "fd-quota-note", children: note }) : null,
|
|
2547
|
-
/* @__PURE__ */
|
|
2557
|
+
/* @__PURE__ */ jsxs31("span", { className: "fd-quota-pct fd-tabular", children: [
|
|
2548
2558
|
p,
|
|
2549
2559
|
"%"
|
|
2550
2560
|
] })
|
|
@@ -2554,7 +2564,7 @@ function QuotaRow({ label, percent = 0, note, tone, className = "" }) {
|
|
|
2554
2564
|
}
|
|
2555
2565
|
|
|
2556
2566
|
// src/components/data/ScoreMeter.tsx
|
|
2557
|
-
import { jsx as jsx35, jsxs as
|
|
2567
|
+
import { jsx as jsx35, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
2558
2568
|
function ScoreMeter({
|
|
2559
2569
|
score,
|
|
2560
2570
|
segments,
|
|
@@ -2568,10 +2578,10 @@ function ScoreMeter({
|
|
|
2568
2578
|
breakdownWidth = 280,
|
|
2569
2579
|
className = ""
|
|
2570
2580
|
}) {
|
|
2571
|
-
const [open, setOpen] =
|
|
2572
|
-
const ref =
|
|
2581
|
+
const [open, setOpen] = React14.useState(false);
|
|
2582
|
+
const ref = React14.useRef(null);
|
|
2573
2583
|
const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
|
|
2574
|
-
const body = /* @__PURE__ */
|
|
2584
|
+
const body = /* @__PURE__ */ jsxs32(React14.Fragment, { children: [
|
|
2575
2585
|
/* @__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
2586
|
showScore ? /* @__PURE__ */ jsx35("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
|
|
2577
2587
|
] });
|
|
@@ -2590,7 +2600,7 @@ function ScoreMeter({
|
|
|
2590
2600
|
}
|
|
2591
2601
|
);
|
|
2592
2602
|
}
|
|
2593
|
-
return /* @__PURE__ */
|
|
2603
|
+
return /* @__PURE__ */ jsxs32(React14.Fragment, { children: [
|
|
2594
2604
|
/* @__PURE__ */ jsx35(
|
|
2595
2605
|
"button",
|
|
2596
2606
|
{
|
|
@@ -2621,14 +2631,14 @@ function ScoreMeter({
|
|
|
2621
2631
|
}
|
|
2622
2632
|
|
|
2623
2633
|
// src/components/data/SortMenu.tsx
|
|
2624
|
-
import * as
|
|
2625
|
-
import { jsx as jsx36, jsxs as
|
|
2634
|
+
import * as React15 from "react";
|
|
2635
|
+
import { jsx as jsx36, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2626
2636
|
var SORT_MENU_BASE = 120;
|
|
2627
2637
|
function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", className = "", ...rest }) {
|
|
2628
|
-
const [open, setOpen] =
|
|
2638
|
+
const [open, setOpen] = React15.useState(false);
|
|
2629
2639
|
const zIndex = useOverlayLayer(SORT_MENU_BASE);
|
|
2630
|
-
const ref =
|
|
2631
|
-
|
|
2640
|
+
const ref = React15.useRef(null);
|
|
2641
|
+
React15.useEffect(() => {
|
|
2632
2642
|
if (!open) return;
|
|
2633
2643
|
const away = (e) => {
|
|
2634
2644
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -2670,16 +2680,16 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
|
|
|
2670
2680
|
}
|
|
2671
2681
|
);
|
|
2672
2682
|
};
|
|
2673
|
-
return /* @__PURE__ */
|
|
2674
|
-
/* @__PURE__ */
|
|
2683
|
+
return /* @__PURE__ */ jsxs33("span", { className, style: { position: "relative", display: "inline-flex" }, ref, ...rest, children: [
|
|
2684
|
+
/* @__PURE__ */ jsxs33(Button, { size, variant: "secondary", icon: dir === "asc" ? "sort-ascending" : "sort-descending", onClick: () => setOpen(!open), children: [
|
|
2675
2685
|
cur ? cur.label : "Unsorted",
|
|
2676
2686
|
/* @__PURE__ */ jsx36("i", { className: "ph ph-" + (dir === "asc" ? "arrow-up" : "arrow-down"), style: { fontSize: 12, marginLeft: 6, opacity: 0.75 } })
|
|
2677
2687
|
] }),
|
|
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__ */
|
|
2688
|
+
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
2689
|
/* @__PURE__ */ jsx36("span", { className: "fd-overline fd-muted", style: { padding: "4px 8px 6px" }, children: "Sort by" }),
|
|
2680
2690
|
fields.map((f) => {
|
|
2681
2691
|
const active = cur && cur.key === f.key;
|
|
2682
|
-
return /* @__PURE__ */
|
|
2692
|
+
return /* @__PURE__ */ jsxs33("span", { className: "fd-row", style: { gap: 8, padding: "4px 8px", borderRadius: 7, background: active ? "var(--surface-brand)" : "transparent" }, children: [
|
|
2683
2693
|
/* @__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
2694
|
arrow(f, "asc"),
|
|
2685
2695
|
arrow(f, "desc")
|
|
@@ -2690,8 +2700,8 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
|
|
|
2690
2700
|
}
|
|
2691
2701
|
|
|
2692
2702
|
// src/components/data/StepList.tsx
|
|
2693
|
-
import * as
|
|
2694
|
-
import { jsx as jsx37, jsxs as
|
|
2703
|
+
import * as React16 from "react";
|
|
2704
|
+
import { jsx as jsx37, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2695
2705
|
var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
|
|
2696
2706
|
function StepList({
|
|
2697
2707
|
steps = [],
|
|
@@ -2703,9 +2713,9 @@ function StepList({
|
|
|
2703
2713
|
dense = false,
|
|
2704
2714
|
className = ""
|
|
2705
2715
|
}) {
|
|
2706
|
-
const [openState, setOpenState] =
|
|
2716
|
+
const [openState, setOpenState] = React16.useState(defaultOpen);
|
|
2707
2717
|
const open = openProp == null ? openState : openProp;
|
|
2708
|
-
const [expanded, setExpanded] =
|
|
2718
|
+
const [expanded, setExpanded] = React16.useState({});
|
|
2709
2719
|
if (!steps.length) return null;
|
|
2710
2720
|
const running = steps.some((s) => s.status === "running");
|
|
2711
2721
|
const failed = steps.filter((s) => s.status === "error").length;
|
|
@@ -2717,15 +2727,15 @@ function StepList({
|
|
|
2717
2727
|
if (openProp == null) setOpenState(next);
|
|
2718
2728
|
onToggle && onToggle(next);
|
|
2719
2729
|
};
|
|
2720
|
-
return /* @__PURE__ */
|
|
2721
|
-
/* @__PURE__ */
|
|
2730
|
+
return /* @__PURE__ */ jsxs34("div", { className: ["fd-steps", dense ? "is-dense" : "", open ? "is-open" : "", className].filter(Boolean).join(" "), children: [
|
|
2731
|
+
/* @__PURE__ */ jsxs34("button", { type: "button", className: "fd-steps-head", onClick: toggle, "aria-expanded": open, children: [
|
|
2722
2732
|
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
2733
|
/* @__PURE__ */ jsx37("span", { className: "fd-steps-title", children: summary }),
|
|
2724
|
-
/* @__PURE__ */
|
|
2734
|
+
/* @__PURE__ */ jsxs34("span", { className: "fd-steps-count fd-tabular", children: [
|
|
2725
2735
|
steps.length,
|
|
2726
2736
|
" step",
|
|
2727
2737
|
steps.length === 1 ? "" : "s",
|
|
2728
|
-
failed ? /* @__PURE__ */
|
|
2738
|
+
failed ? /* @__PURE__ */ jsxs34("span", { className: "fd-steps-failed", children: [
|
|
2729
2739
|
" \xB7 ",
|
|
2730
2740
|
failed,
|
|
2731
2741
|
" failed"
|
|
@@ -2737,10 +2747,10 @@ function StepList({
|
|
|
2737
2747
|
const id = s.id || i;
|
|
2738
2748
|
const isOpen = !!expanded[id];
|
|
2739
2749
|
const icon = KIND_ICON[s.kind || ""] || "dot-outline";
|
|
2740
|
-
return /* @__PURE__ */
|
|
2741
|
-
/* @__PURE__ */
|
|
2750
|
+
return /* @__PURE__ */ jsxs34("li", { className: "fd-step is-" + (s.status || "ok"), children: [
|
|
2751
|
+
/* @__PURE__ */ jsxs34("div", { className: "fd-step-row", children: [
|
|
2742
2752
|
/* @__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__ */
|
|
2753
|
+
s.detail ? /* @__PURE__ */ jsxs34(
|
|
2744
2754
|
"button",
|
|
2745
2755
|
{
|
|
2746
2756
|
type: "button",
|
|
@@ -2763,8 +2773,8 @@ function StepList({
|
|
|
2763
2773
|
}
|
|
2764
2774
|
|
|
2765
2775
|
// src/components/data/VirtualList.tsx
|
|
2766
|
-
import * as
|
|
2767
|
-
import { jsx as jsx38, jsxs as
|
|
2776
|
+
import * as React17 from "react";
|
|
2777
|
+
import { jsx as jsx38, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2768
2778
|
var VIRTUAL_LIST_BUFFER_ROWS = 20;
|
|
2769
2779
|
var VIRTUAL_LIST_ROW_GAP = 6;
|
|
2770
2780
|
function computeVirtualWindow(opts) {
|
|
@@ -2815,35 +2825,35 @@ function VirtualList({
|
|
|
2815
2825
|
className = "",
|
|
2816
2826
|
style
|
|
2817
2827
|
}) {
|
|
2818
|
-
const [scrollTop, setScrollTop] =
|
|
2819
|
-
const loaded =
|
|
2828
|
+
const [scrollTop, setScrollTop] = React17.useState(0);
|
|
2829
|
+
const loaded = React17.useMemo(
|
|
2820
2830
|
() => ({ firstItemIndex, count: items.length }),
|
|
2821
2831
|
[firstItemIndex, items.length]
|
|
2822
2832
|
);
|
|
2823
2833
|
const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
|
|
2824
2834
|
const bandKey = firstItemIndex + ":" + items.length;
|
|
2825
|
-
const win =
|
|
2835
|
+
const win = React17.useMemo(
|
|
2826
2836
|
() => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
|
|
2827
2837
|
[scrollTop, height, itemHeight, total, loaded]
|
|
2828
2838
|
);
|
|
2829
|
-
const need =
|
|
2839
|
+
const need = React17.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
|
|
2830
2840
|
const wantStart = need.start && hasMore?.start !== false;
|
|
2831
2841
|
const wantEnd = need.end && hasMore?.end !== false;
|
|
2832
2842
|
const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
|
|
2833
2843
|
const askKey = bandKey + "@" + bucket2;
|
|
2834
|
-
const asked =
|
|
2835
|
-
|
|
2844
|
+
const asked = React17.useRef({ start: null, end: null });
|
|
2845
|
+
React17.useEffect(() => {
|
|
2836
2846
|
if (loading || !wantStart || asked.current.start === askKey) return;
|
|
2837
2847
|
asked.current.start = askKey;
|
|
2838
2848
|
onNeedMore("start", win);
|
|
2839
2849
|
}, [wantStart, loading, askKey, onNeedMore, win]);
|
|
2840
|
-
|
|
2850
|
+
React17.useEffect(() => {
|
|
2841
2851
|
if (loading || !wantEnd || asked.current.end === askKey) return;
|
|
2842
2852
|
asked.current.end = askKey;
|
|
2843
2853
|
onNeedMore("end", win);
|
|
2844
2854
|
}, [wantEnd, loading, askKey, onNeedMore, win]);
|
|
2845
|
-
const lastKeysRef =
|
|
2846
|
-
const newKeys =
|
|
2855
|
+
const lastKeysRef = React17.useRef(null);
|
|
2856
|
+
const newKeys = React17.useMemo(() => {
|
|
2847
2857
|
const prev = lastKeysRef.current;
|
|
2848
2858
|
if (!prev) return /* @__PURE__ */ new Set();
|
|
2849
2859
|
const fresh = /* @__PURE__ */ new Set();
|
|
@@ -2853,7 +2863,7 @@ function VirtualList({
|
|
|
2853
2863
|
}
|
|
2854
2864
|
return fresh;
|
|
2855
2865
|
}, [items]);
|
|
2856
|
-
|
|
2866
|
+
React17.useEffect(() => {
|
|
2857
2867
|
lastKeysRef.current = new Set(items.map(keyOf));
|
|
2858
2868
|
}, [items]);
|
|
2859
2869
|
const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
|
|
@@ -2877,8 +2887,8 @@ function VirtualList({
|
|
|
2877
2887
|
)
|
|
2878
2888
|
);
|
|
2879
2889
|
}
|
|
2880
|
-
return /* @__PURE__ */
|
|
2881
|
-
/* @__PURE__ */
|
|
2890
|
+
return /* @__PURE__ */ jsxs35("div", { className: ["fd-vlist-wrap", className].filter(Boolean).join(" "), style: { height, position: "relative", ...gapStyle, ...style }, children: [
|
|
2891
|
+
/* @__PURE__ */ jsxs35(
|
|
2882
2892
|
"div",
|
|
2883
2893
|
{
|
|
2884
2894
|
className: "fd-vlist fd-scrollbar",
|
|
@@ -2890,7 +2900,7 @@ function VirtualList({
|
|
|
2890
2900
|
]
|
|
2891
2901
|
}
|
|
2892
2902
|
),
|
|
2893
|
-
refreshing ? /* @__PURE__ */ jsx38("div", { className: "fd-vlist-refresh-scrim", children: /* @__PURE__ */
|
|
2903
|
+
refreshing ? /* @__PURE__ */ jsx38("div", { className: "fd-vlist-refresh-scrim", children: /* @__PURE__ */ jsxs35("div", { className: "fd-vlist-refresh-card", children: [
|
|
2894
2904
|
/* @__PURE__ */ jsx38("span", { className: "fd-spinner", "aria-hidden": "true" }),
|
|
2895
2905
|
/* @__PURE__ */ jsx38("span", { className: "fd-body-sm", children: refreshingLabel })
|
|
2896
2906
|
] }) }) : null
|
|
@@ -2898,8 +2908,8 @@ function VirtualList({
|
|
|
2898
2908
|
}
|
|
2899
2909
|
|
|
2900
2910
|
// src/components/data/EntityRow.tsx
|
|
2901
|
-
import * as
|
|
2902
|
-
import { jsx as jsx39, jsxs as
|
|
2911
|
+
import * as React18 from "react";
|
|
2912
|
+
import { jsx as jsx39, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
2903
2913
|
var ENTITY_ROW_METRIC_WIDTH = 74;
|
|
2904
2914
|
var METRIC_TONE_COLOR = {
|
|
2905
2915
|
default: "var(--text-2)",
|
|
@@ -2911,7 +2921,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
|
|
|
2911
2921
|
const key = m.id || m.label || i;
|
|
2912
2922
|
const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
|
|
2913
2923
|
const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
|
|
2914
|
-
const content = /* @__PURE__ */
|
|
2924
|
+
const content = /* @__PURE__ */ jsxs36(React18.Fragment, { children: [
|
|
2915
2925
|
m.icon ? /* @__PURE__ */ jsx39("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
|
|
2916
2926
|
/* @__PURE__ */ jsx39("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
|
|
2917
2927
|
/* @__PURE__ */ jsx39("span", { className: "fd-sr", children: " " + m.label })
|
|
@@ -2932,7 +2942,7 @@ function EntityRow({
|
|
|
2932
2942
|
className = ""
|
|
2933
2943
|
}) {
|
|
2934
2944
|
const hasStrip = metrics && metrics.length > 0 || accessory != null;
|
|
2935
|
-
return /* @__PURE__ */
|
|
2945
|
+
return /* @__PURE__ */ jsxs36(
|
|
2936
2946
|
"div",
|
|
2937
2947
|
{
|
|
2938
2948
|
onPointerDown,
|
|
@@ -2951,12 +2961,12 @@ function EntityRow({
|
|
|
2951
2961
|
},
|
|
2952
2962
|
children: [
|
|
2953
2963
|
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__ */
|
|
2964
|
+
/* @__PURE__ */ jsxs36("span", { className: "fd-erow-body", children: [
|
|
2965
|
+
/* @__PURE__ */ jsxs36("span", { className: "fd-erow-titleline", children: [
|
|
2956
2966
|
/* @__PURE__ */ jsx39("span", { className: "fd-erow-title fd-body-sm", children: title }),
|
|
2957
2967
|
meta ? /* @__PURE__ */ jsx39("span", { className: "fd-erow-meta", children: meta }) : null
|
|
2958
2968
|
] }),
|
|
2959
|
-
hasStrip ? /* @__PURE__ */
|
|
2969
|
+
hasStrip ? /* @__PURE__ */ jsxs36("span", { className: "fd-erow-strip", children: [
|
|
2960
2970
|
metrics && metrics.length ? /* @__PURE__ */ jsx39(EntityRowMetrics, { metrics }) : null,
|
|
2961
2971
|
accessory ? /* @__PURE__ */ jsx39("span", { className: "fd-erow-accessory", children: accessory }) : null
|
|
2962
2972
|
] }) : null
|
|
@@ -2979,18 +2989,18 @@ function EntityRow({
|
|
|
2979
2989
|
}
|
|
2980
2990
|
|
|
2981
2991
|
// src/components/data/TransferList.tsx
|
|
2982
|
-
import * as
|
|
2992
|
+
import * as React20 from "react";
|
|
2983
2993
|
import { createPortal as createPortal4 } from "react-dom";
|
|
2984
2994
|
|
|
2985
2995
|
// src/components/forms/field.tsx
|
|
2986
|
-
import * as
|
|
2987
|
-
import { jsx as jsx40, jsxs as
|
|
2996
|
+
import * as React19 from "react";
|
|
2997
|
+
import { jsx as jsx40, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
2988
2998
|
function useFieldId(id) {
|
|
2989
|
-
const generated =
|
|
2999
|
+
const generated = React19.useId();
|
|
2990
3000
|
return id || generated;
|
|
2991
3001
|
}
|
|
2992
3002
|
function FieldLabel({ htmlFor, id, required = false, onClick, children }) {
|
|
2993
|
-
return /* @__PURE__ */
|
|
3003
|
+
return /* @__PURE__ */ jsxs37("label", { className: "fd-field-label", htmlFor, id, onClick, children: [
|
|
2994
3004
|
children,
|
|
2995
3005
|
required ? /* @__PURE__ */ jsx40("span", { className: "fd-field-req", "aria-hidden": "true", children: "*" }) : null
|
|
2996
3006
|
] });
|
|
@@ -3002,7 +3012,7 @@ function useTriggerLabelling(label, id) {
|
|
|
3002
3012
|
}
|
|
3003
3013
|
|
|
3004
3014
|
// src/components/forms/Input.tsx
|
|
3005
|
-
import { jsx as jsx41, jsxs as
|
|
3015
|
+
import { jsx as jsx41, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
3006
3016
|
function Input({
|
|
3007
3017
|
label,
|
|
3008
3018
|
help,
|
|
@@ -3029,16 +3039,16 @@ function Input({
|
|
|
3029
3039
|
disabled ? "fd-input-disabled" : "",
|
|
3030
3040
|
size === "lg" ? "fd-input-lg" : ""
|
|
3031
3041
|
].filter(Boolean).join(" ");
|
|
3032
|
-
return /* @__PURE__ */
|
|
3042
|
+
return /* @__PURE__ */ jsxs38("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
|
|
3033
3043
|
label ? /* @__PURE__ */ jsx41(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
|
|
3034
|
-
/* @__PURE__ */
|
|
3044
|
+
/* @__PURE__ */ jsxs38("div", { className: box, children: [
|
|
3035
3045
|
icon ? /* @__PURE__ */ jsx41("span", { className: "fd-input-icon", children: /* @__PURE__ */ jsx41("i", { className: "ph ph-" + icon, "aria-hidden": "true" }) }) : null,
|
|
3036
3046
|
prefix ? /* @__PURE__ */ jsx41("span", { className: "fd-input-affix", children: prefix }) : null,
|
|
3037
3047
|
/* @__PURE__ */ jsx41("input", { id: fieldId, disabled, style: inputStyle, "aria-invalid": error ? "true" : void 0, ...rest }),
|
|
3038
3048
|
loading ? /* @__PURE__ */ jsx41("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading" }) : null,
|
|
3039
3049
|
suffix && !loading ? /* @__PURE__ */ jsx41("span", { className: "fd-input-affix", children: suffix }) : null
|
|
3040
3050
|
] }),
|
|
3041
|
-
error ? /* @__PURE__ */
|
|
3051
|
+
error ? /* @__PURE__ */ jsxs38("span", { className: "fd-field-error", children: [
|
|
3042
3052
|
/* @__PURE__ */ jsx41("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3043
3053
|
error
|
|
3044
3054
|
] }) : help ? /* @__PURE__ */ jsx41("span", { className: "fd-field-help", children: help }) : null
|
|
@@ -3090,7 +3100,7 @@ function SearchField({
|
|
|
3090
3100
|
}
|
|
3091
3101
|
|
|
3092
3102
|
// src/components/data/TransferList.tsx
|
|
3093
|
-
import { jsx as jsx43, jsxs as
|
|
3103
|
+
import { jsx as jsx43, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
3094
3104
|
var emptyHasMore = {};
|
|
3095
3105
|
var DRAG_THRESHOLD_PX = 5;
|
|
3096
3106
|
function TransferList({
|
|
@@ -3104,12 +3114,12 @@ function TransferList({
|
|
|
3104
3114
|
listHeight = 440,
|
|
3105
3115
|
className = ""
|
|
3106
3116
|
}) {
|
|
3107
|
-
const [drag, setDrag] =
|
|
3108
|
-
const [dragOverSide, setDragOverSide] =
|
|
3109
|
-
const dragRef =
|
|
3110
|
-
const armedRef =
|
|
3111
|
-
const sideRefs =
|
|
3112
|
-
const hitTestSide =
|
|
3117
|
+
const [drag, setDrag] = React20.useState(null);
|
|
3118
|
+
const [dragOverSide, setDragOverSide] = React20.useState(null);
|
|
3119
|
+
const dragRef = React20.useRef(null);
|
|
3120
|
+
const armedRef = React20.useRef(null);
|
|
3121
|
+
const sideRefs = React20.useRef({ left: null, right: null });
|
|
3122
|
+
const hitTestSide = React20.useCallback((x, y) => {
|
|
3113
3123
|
for (const side of ["left", "right"]) {
|
|
3114
3124
|
const el = sideRefs.current[side];
|
|
3115
3125
|
if (!el) continue;
|
|
@@ -3118,7 +3128,7 @@ function TransferList({
|
|
|
3118
3128
|
}
|
|
3119
3129
|
return null;
|
|
3120
3130
|
}, []);
|
|
3121
|
-
const findItem =
|
|
3131
|
+
const findItem = React20.useCallback(
|
|
3122
3132
|
(side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
|
|
3123
3133
|
[left.items, right.items, keyOf]
|
|
3124
3134
|
);
|
|
@@ -3140,7 +3150,7 @@ function TransferList({
|
|
|
3140
3150
|
height: rect.height
|
|
3141
3151
|
};
|
|
3142
3152
|
};
|
|
3143
|
-
|
|
3153
|
+
React20.useEffect(() => {
|
|
3144
3154
|
const onMovePointer = (e) => {
|
|
3145
3155
|
const armed = armedRef.current;
|
|
3146
3156
|
if (!armed || e.pointerId !== armed.pointerId) return;
|
|
@@ -3193,7 +3203,7 @@ function TransferList({
|
|
|
3193
3203
|
window.removeEventListener("pointercancel", endDrag);
|
|
3194
3204
|
};
|
|
3195
3205
|
}, [hitTestSide, findItem, onMove]);
|
|
3196
|
-
|
|
3206
|
+
React20.useEffect(() => {
|
|
3197
3207
|
if (!drag || typeof document === "undefined") return;
|
|
3198
3208
|
const prev = document.body.style.userSelect;
|
|
3199
3209
|
document.body.style.userSelect = "none";
|
|
@@ -3203,7 +3213,7 @@ function TransferList({
|
|
|
3203
3213
|
}, [drag]);
|
|
3204
3214
|
const renderSide = (side, cfg, opposite) => {
|
|
3205
3215
|
const showOverlay = drag != null && dragOverSide === side;
|
|
3206
|
-
return /* @__PURE__ */
|
|
3216
|
+
return /* @__PURE__ */ jsxs39(
|
|
3207
3217
|
"div",
|
|
3208
3218
|
{
|
|
3209
3219
|
ref: (el) => {
|
|
@@ -3211,12 +3221,12 @@ function TransferList({
|
|
|
3211
3221
|
},
|
|
3212
3222
|
className: ["fd-tlist-side", dragOverSide === side ? "is-drop-target" : ""].filter(Boolean).join(" "),
|
|
3213
3223
|
children: [
|
|
3214
|
-
cfg.label ? /* @__PURE__ */
|
|
3224
|
+
cfg.label ? /* @__PURE__ */ jsxs39("span", { className: "fd-overline fd-muted", children: [
|
|
3215
3225
|
cfg.label,
|
|
3216
3226
|
cfg.total != null ? " (" + cfg.total.toLocaleString() + ")" : ""
|
|
3217
3227
|
] }) : null,
|
|
3218
3228
|
cfg.header ? /* @__PURE__ */ jsx43("div", { className: "fd-tlist-header", children: cfg.header }) : null,
|
|
3219
|
-
/* @__PURE__ */
|
|
3229
|
+
/* @__PURE__ */ jsxs39("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
3220
3230
|
/* @__PURE__ */ jsx43(SearchField, { value: cfg.search, onChange: cfg.onSearchChange, placeholder: "Search", "aria-label": (cfg.label || side) + " search", style: { flex: 1 } }),
|
|
3221
3231
|
/* @__PURE__ */ jsx43(SortMenu, { fields: cfg.sortFields, sort: cfg.sort, onSort: cfg.onSort, align: side === "left" ? "left" : "right" })
|
|
3222
3232
|
] }),
|
|
@@ -3263,7 +3273,7 @@ function TransferList({
|
|
|
3263
3273
|
}
|
|
3264
3274
|
),
|
|
3265
3275
|
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__ */
|
|
3276
|
+
showOverlay ? /* @__PURE__ */ jsx43("div", { className: "fd-tlist-drop-overlay", "aria-hidden": "true", children: /* @__PURE__ */ jsxs39("span", { className: "fd-tlist-drop-card", children: [
|
|
3267
3277
|
/* @__PURE__ */ jsx43("i", { className: "ph ph-tray-arrow-down", style: { fontSize: 18 }, "aria-hidden": "true" }),
|
|
3268
3278
|
/* @__PURE__ */ jsx43("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: cfg.dropLabel || "Drop here" + (cfg.label ? " \u2014 " + cfg.label : "") })
|
|
3269
3279
|
] }) }) : null
|
|
@@ -3271,8 +3281,8 @@ function TransferList({
|
|
|
3271
3281
|
}
|
|
3272
3282
|
);
|
|
3273
3283
|
};
|
|
3274
|
-
return /* @__PURE__ */
|
|
3275
|
-
/* @__PURE__ */
|
|
3284
|
+
return /* @__PURE__ */ jsxs39("div", { className: ["fd-tlist", className].filter(Boolean).join(" "), children: [
|
|
3285
|
+
/* @__PURE__ */ jsxs39("div", { className: "fd-tlist-panes", children: [
|
|
3276
3286
|
renderSide("left", left, "right"),
|
|
3277
3287
|
renderSide("right", right, "left")
|
|
3278
3288
|
] }),
|
|
@@ -3301,19 +3311,19 @@ function TransferList({
|
|
|
3301
3311
|
}
|
|
3302
3312
|
|
|
3303
3313
|
// src/components/forms/Checkbox.tsx
|
|
3304
|
-
import * as
|
|
3305
|
-
import { jsx as jsx44, jsxs as
|
|
3314
|
+
import * as React21 from "react";
|
|
3315
|
+
import { jsx as jsx44, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
3306
3316
|
function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
|
|
3307
|
-
const ref =
|
|
3308
|
-
|
|
3317
|
+
const ref = React21.useRef(null);
|
|
3318
|
+
React21.useEffect(() => {
|
|
3309
3319
|
if (ref.current) ref.current.indeterminate = indeterminate;
|
|
3310
3320
|
}, [indeterminate]);
|
|
3311
|
-
return /* @__PURE__ */
|
|
3312
|
-
/* @__PURE__ */
|
|
3321
|
+
return /* @__PURE__ */ jsxs40("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
3322
|
+
/* @__PURE__ */ jsxs40("span", { className: "fd-choice-input", children: [
|
|
3313
3323
|
/* @__PURE__ */ jsx44("input", { ref, type: "checkbox", ...rest }),
|
|
3314
3324
|
/* @__PURE__ */ jsx44("span", { className: "fd-choice-box", "aria-hidden": "true", children: /* @__PURE__ */ jsx44("i", { className: indeterminate ? "ph ph-minus" : "ph ph-check" }) })
|
|
3315
3325
|
] }),
|
|
3316
|
-
/* @__PURE__ */
|
|
3326
|
+
/* @__PURE__ */ jsxs40("span", { className: "fd-choice-text", children: [
|
|
3317
3327
|
/* @__PURE__ */ jsx44("span", { className: "fd-choice-title", children: label }),
|
|
3318
3328
|
description ? /* @__PURE__ */ jsx44("span", { className: "fd-choice-desc", children: description }) : null
|
|
3319
3329
|
] })
|
|
@@ -3321,14 +3331,14 @@ function Checkbox({ label, description, card = false, indeterminate = false, cla
|
|
|
3321
3331
|
}
|
|
3322
3332
|
|
|
3323
3333
|
// src/components/forms/Radio.tsx
|
|
3324
|
-
import { jsx as jsx45, jsxs as
|
|
3334
|
+
import { jsx as jsx45, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
3325
3335
|
function Radio({ label, description, card = false, className = "", ...rest }) {
|
|
3326
|
-
return /* @__PURE__ */
|
|
3327
|
-
/* @__PURE__ */
|
|
3336
|
+
return /* @__PURE__ */ jsxs41("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
3337
|
+
/* @__PURE__ */ jsxs41("span", { className: "fd-choice-input", children: [
|
|
3328
3338
|
/* @__PURE__ */ jsx45("input", { type: "radio", ...rest }),
|
|
3329
3339
|
/* @__PURE__ */ jsx45("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ jsx45("span", { className: "fd-choice-dot" }) })
|
|
3330
3340
|
] }),
|
|
3331
|
-
/* @__PURE__ */
|
|
3341
|
+
/* @__PURE__ */ jsxs41("span", { className: "fd-choice-text", children: [
|
|
3332
3342
|
/* @__PURE__ */ jsx45("span", { className: "fd-choice-title", children: label }),
|
|
3333
3343
|
description ? /* @__PURE__ */ jsx45("span", { className: "fd-choice-desc", children: description }) : null
|
|
3334
3344
|
] })
|
|
@@ -3336,12 +3346,12 @@ function Radio({ label, description, card = false, className = "", ...rest }) {
|
|
|
3336
3346
|
}
|
|
3337
3347
|
|
|
3338
3348
|
// src/components/forms/Switch.tsx
|
|
3339
|
-
import { jsx as jsx46, jsxs as
|
|
3349
|
+
import { jsx as jsx46, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
3340
3350
|
function Switch({ label, description, className = "", ...rest }) {
|
|
3341
|
-
return /* @__PURE__ */
|
|
3351
|
+
return /* @__PURE__ */ jsxs42("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
|
|
3342
3352
|
/* @__PURE__ */ jsx46("input", { type: "checkbox", role: "switch", ...rest }),
|
|
3343
3353
|
/* @__PURE__ */ jsx46("span", { className: "fd-switch-track", children: /* @__PURE__ */ jsx46("span", { className: "fd-switch-thumb" }) }),
|
|
3344
|
-
label ? /* @__PURE__ */
|
|
3354
|
+
label ? /* @__PURE__ */ jsxs42("span", { className: "fd-choice-text", children: [
|
|
3345
3355
|
/* @__PURE__ */ jsx46("span", { className: "fd-switch-label", children: label }),
|
|
3346
3356
|
description ? /* @__PURE__ */ jsx46("span", { className: "fd-choice-desc", children: description }) : null
|
|
3347
3357
|
] }) : null
|
|
@@ -3349,14 +3359,14 @@ function Switch({ label, description, className = "", ...rest }) {
|
|
|
3349
3359
|
}
|
|
3350
3360
|
|
|
3351
3361
|
// src/components/forms/Textarea.tsx
|
|
3352
|
-
import { jsx as jsx47, jsxs as
|
|
3362
|
+
import { jsx as jsx47, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
3353
3363
|
function Textarea({ label, help, error, required = false, rows = 4, disabled = false, id, className = "", style, ...rest }) {
|
|
3354
3364
|
const fieldId = useFieldId(id);
|
|
3355
3365
|
const box = ["fd-input", "fd-input-textarea", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
3356
|
-
return /* @__PURE__ */
|
|
3366
|
+
return /* @__PURE__ */ jsxs43("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
|
|
3357
3367
|
label ? /* @__PURE__ */ jsx47(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
|
|
3358
3368
|
/* @__PURE__ */ jsx47("div", { className: box, children: /* @__PURE__ */ jsx47("textarea", { id: fieldId, rows, disabled, "aria-invalid": error ? "true" : void 0, ...rest }) }),
|
|
3359
|
-
error ? /* @__PURE__ */
|
|
3369
|
+
error ? /* @__PURE__ */ jsxs43("span", { className: "fd-field-error", children: [
|
|
3360
3370
|
/* @__PURE__ */ jsx47("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3361
3371
|
error
|
|
3362
3372
|
] }) : help ? /* @__PURE__ */ jsx47("span", { className: "fd-field-help", children: help }) : null
|
|
@@ -3364,8 +3374,8 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
|
|
|
3364
3374
|
}
|
|
3365
3375
|
|
|
3366
3376
|
// src/components/forms/NumberInput.tsx
|
|
3367
|
-
import * as
|
|
3368
|
-
import { jsx as jsx48, jsxs as
|
|
3377
|
+
import * as React22 from "react";
|
|
3378
|
+
import { jsx as jsx48, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
3369
3379
|
function NumberInput({
|
|
3370
3380
|
label,
|
|
3371
3381
|
help,
|
|
@@ -3392,10 +3402,10 @@ function NumberInput({
|
|
|
3392
3402
|
const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
|
|
3393
3403
|
return isNaN(n) ? null : n;
|
|
3394
3404
|
};
|
|
3395
|
-
const [text, setText] =
|
|
3396
|
-
const [editing, setEditing] =
|
|
3397
|
-
const timer =
|
|
3398
|
-
|
|
3405
|
+
const [text, setText] = React22.useState(value == null || value === "" ? "" : String(value));
|
|
3406
|
+
const [editing, setEditing] = React22.useState(false);
|
|
3407
|
+
const timer = React22.useRef(null);
|
|
3408
|
+
React22.useEffect(() => {
|
|
3399
3409
|
if (!editing) setText(value == null || value === "" ? "" : String(value));
|
|
3400
3410
|
}, [value, editing]);
|
|
3401
3411
|
const clamp = (n) => Math.min(max, Math.max(min, n));
|
|
@@ -3419,7 +3429,7 @@ function NumberInput({
|
|
|
3419
3429
|
const release = () => {
|
|
3420
3430
|
if (timer.current) clearTimeout(timer.current);
|
|
3421
3431
|
};
|
|
3422
|
-
|
|
3432
|
+
React22.useEffect(() => () => {
|
|
3423
3433
|
if (timer.current) clearTimeout(timer.current);
|
|
3424
3434
|
}, []);
|
|
3425
3435
|
const shown = editing ? text : (() => {
|
|
@@ -3429,9 +3439,9 @@ function NumberInput({
|
|
|
3429
3439
|
const box = ["fd-input", "fd-input-num", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
3430
3440
|
const fieldName = label || ariaLabel;
|
|
3431
3441
|
const stepperName = (verb) => fieldName ? verb + " " + fieldName : verb;
|
|
3432
|
-
return /* @__PURE__ */
|
|
3442
|
+
return /* @__PURE__ */ jsxs44("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
|
|
3433
3443
|
label ? /* @__PURE__ */ jsx48(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
|
|
3434
|
-
/* @__PURE__ */
|
|
3444
|
+
/* @__PURE__ */ jsxs44("div", { className: box, style: { gap: 8 }, children: [
|
|
3435
3445
|
prefix ? /* @__PURE__ */ jsx48("span", { className: "fd-input-affix", children: prefix }) : null,
|
|
3436
3446
|
/* @__PURE__ */ jsx48(
|
|
3437
3447
|
"input",
|
|
@@ -3469,7 +3479,7 @@ function NumberInput({
|
|
|
3469
3479
|
}
|
|
3470
3480
|
),
|
|
3471
3481
|
suffix ? /* @__PURE__ */ jsx48("span", { className: "fd-input-affix", children: suffix }) : null,
|
|
3472
|
-
/* @__PURE__ */
|
|
3482
|
+
/* @__PURE__ */ jsxs44("span", { className: "fd-row", style: { gap: 4, flex: "none" }, children: [
|
|
3473
3483
|
/* @__PURE__ */ jsx48(
|
|
3474
3484
|
"button",
|
|
3475
3485
|
{
|
|
@@ -3498,7 +3508,7 @@ function NumberInput({
|
|
|
3498
3508
|
)
|
|
3499
3509
|
] })
|
|
3500
3510
|
] }),
|
|
3501
|
-
error ? /* @__PURE__ */
|
|
3511
|
+
error ? /* @__PURE__ */ jsxs44("span", { className: "fd-field-error", children: [
|
|
3502
3512
|
/* @__PURE__ */ jsx48("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3503
3513
|
error
|
|
3504
3514
|
] }) : help ? /* @__PURE__ */ jsx48("span", { className: "fd-field-help", children: help }) : null
|
|
@@ -3506,8 +3516,8 @@ function NumberInput({
|
|
|
3506
3516
|
}
|
|
3507
3517
|
|
|
3508
3518
|
// src/components/forms/Select.tsx
|
|
3509
|
-
import * as
|
|
3510
|
-
import { jsx as jsx49, jsxs as
|
|
3519
|
+
import * as React23 from "react";
|
|
3520
|
+
import { jsx as jsx49, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
3511
3521
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
3512
3522
|
function Select({
|
|
3513
3523
|
label,
|
|
@@ -3533,13 +3543,13 @@ function Select({
|
|
|
3533
3543
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
3534
3544
|
const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
|
|
3535
3545
|
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 =
|
|
3546
|
+
const [open, setOpen] = React23.useState(false);
|
|
3547
|
+
const [q, setQ] = React23.useState("");
|
|
3548
|
+
const [active, setActive] = React23.useState(-1);
|
|
3549
|
+
const rootRef = React23.useRef(null);
|
|
3550
|
+
const boxRef = React23.useRef(null);
|
|
3551
|
+
const listRef = React23.useRef(null);
|
|
3552
|
+
const typeBuf = React23.useRef({ s: "", t: 0 });
|
|
3543
3553
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
3544
3554
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
3545
3555
|
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 +3574,7 @@ function Select({
|
|
|
3564
3574
|
}
|
|
3565
3575
|
setOpen(!open);
|
|
3566
3576
|
};
|
|
3567
|
-
|
|
3577
|
+
React23.useEffect(() => {
|
|
3568
3578
|
if (!open || active < 0 || !listRef.current) return;
|
|
3569
3579
|
const el = listRef.current.querySelector('[data-i="' + active + '"]');
|
|
3570
3580
|
if (el) {
|
|
@@ -3617,10 +3627,10 @@ function Select({
|
|
|
3617
3627
|
else last.items.push({ o, i });
|
|
3618
3628
|
});
|
|
3619
3629
|
const box = ["fd-input", "fd-select", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
3620
|
-
return /* @__PURE__ */
|
|
3630
|
+
return /* @__PURE__ */ jsxs45("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
3621
3631
|
label ? /* @__PURE__ */ jsx49(FieldLabel, { id: labelId, required, onClick: toggle, children: label }) : null,
|
|
3622
|
-
/* @__PURE__ */
|
|
3623
|
-
/* @__PURE__ */
|
|
3632
|
+
/* @__PURE__ */ jsxs45("div", { className: box, style: { cursor: disabled ? "not-allowed" : "pointer" }, ref: boxRef, children: [
|
|
3633
|
+
/* @__PURE__ */ jsxs45(
|
|
3624
3634
|
"button",
|
|
3625
3635
|
{
|
|
3626
3636
|
type: "button",
|
|
@@ -3668,7 +3678,7 @@ function Select({
|
|
|
3668
3678
|
minWidth: 260,
|
|
3669
3679
|
role: "presentation",
|
|
3670
3680
|
style: { maxWidth: 380 },
|
|
3671
|
-
header: hasSearch ? /* @__PURE__ */
|
|
3681
|
+
header: hasSearch ? /* @__PURE__ */ jsxs45("div", { className: "fd-pop-search", children: [
|
|
3672
3682
|
/* @__PURE__ */ jsx49("i", { className: "ph ph-magnifying-glass", style: { color: "var(--text-muted)", fontSize: 14 } }),
|
|
3673
3683
|
/* @__PURE__ */ jsx49(
|
|
3674
3684
|
"input",
|
|
@@ -3685,7 +3695,7 @@ function Select({
|
|
|
3685
3695
|
),
|
|
3686
3696
|
q ? /* @__PURE__ */ jsx49("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
3687
3697
|
] }) : void 0,
|
|
3688
|
-
footer: multiple ? /* @__PURE__ */
|
|
3698
|
+
footer: multiple ? /* @__PURE__ */ jsxs45(React23.Fragment, { children: [
|
|
3689
3699
|
/* @__PURE__ */ jsx49(
|
|
3690
3700
|
"button",
|
|
3691
3701
|
{
|
|
@@ -3696,7 +3706,7 @@ function Select({
|
|
|
3696
3706
|
}
|
|
3697
3707
|
),
|
|
3698
3708
|
/* @__PURE__ */ jsx49("span", { style: { flex: 1 } }),
|
|
3699
|
-
/* @__PURE__ */
|
|
3709
|
+
/* @__PURE__ */ jsxs45("span", { className: "fd-body-sm fd-muted", children: [
|
|
3700
3710
|
vals.length,
|
|
3701
3711
|
" of ",
|
|
3702
3712
|
opts.length
|
|
@@ -3712,13 +3722,13 @@ function Select({
|
|
|
3712
3722
|
}
|
|
3713
3723
|
)
|
|
3714
3724
|
] }) : 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__ */
|
|
3725
|
+
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
3726
|
'Nothing matches "',
|
|
3717
3727
|
q,
|
|
3718
3728
|
'".'
|
|
3719
|
-
] }) : groups.map((grp) => /* @__PURE__ */
|
|
3729
|
+
] }) : groups.map((grp) => /* @__PURE__ */ jsxs45(React23.Fragment, { children: [
|
|
3720
3730
|
grp.g ? /* @__PURE__ */ jsx49("div", { className: "fd-pop-group", children: grp.g }) : null,
|
|
3721
|
-
grp.items.map(({ o, i }) => /* @__PURE__ */
|
|
3731
|
+
grp.items.map(({ o, i }) => /* @__PURE__ */ jsxs45(
|
|
3722
3732
|
"button",
|
|
3723
3733
|
{
|
|
3724
3734
|
type: "button",
|
|
@@ -3732,7 +3742,7 @@ function Select({
|
|
|
3732
3742
|
children: [
|
|
3733
3743
|
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
3744
|
o.icon ? /* @__PURE__ */ jsx49("span", { className: "fd-opt-icon", children: /* @__PURE__ */ jsx49("i", { className: "ph ph-" + o.icon }) }) : null,
|
|
3735
|
-
/* @__PURE__ */
|
|
3745
|
+
/* @__PURE__ */ jsxs45("span", { style: { flex: 1, minWidth: 0 }, children: [
|
|
3736
3746
|
/* @__PURE__ */ jsx49("span", { className: "fd-opt-label", children: o.label }),
|
|
3737
3747
|
o.description ? /* @__PURE__ */ jsx49("span", { className: "fd-opt-desc", children: o.description }) : null
|
|
3738
3748
|
] }),
|
|
@@ -3745,7 +3755,7 @@ function Select({
|
|
|
3745
3755
|
] }, grp.g || "_")) })
|
|
3746
3756
|
}
|
|
3747
3757
|
),
|
|
3748
|
-
error ? /* @__PURE__ */
|
|
3758
|
+
error ? /* @__PURE__ */ jsxs45("span", { className: "fd-field-error", children: [
|
|
3749
3759
|
/* @__PURE__ */ jsx49("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3750
3760
|
error
|
|
3751
3761
|
] }) : help ? /* @__PURE__ */ jsx49("span", { className: "fd-field-help", children: help }) : null
|
|
@@ -3753,8 +3763,8 @@ function Select({
|
|
|
3753
3763
|
}
|
|
3754
3764
|
|
|
3755
3765
|
// src/components/forms/DatePicker.tsx
|
|
3756
|
-
import * as
|
|
3757
|
-
import { jsx as jsx50, jsxs as
|
|
3766
|
+
import * as React24 from "react";
|
|
3767
|
+
import { jsx as jsx50, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
3758
3768
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
3759
3769
|
var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
3760
3770
|
var iso = (d) => d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
|
|
@@ -3771,10 +3781,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3771
3781
|
const today = /* @__PURE__ */ new Date();
|
|
3772
3782
|
const sel = range ? value || {} : { start: value, end: value };
|
|
3773
3783
|
const anchor = parse(sel.start) || parse(initialMonth) || today;
|
|
3774
|
-
const [vy, setVy] =
|
|
3775
|
-
const [vm, setVm] =
|
|
3776
|
-
const [mode2, setMode] =
|
|
3777
|
-
const [hover, setHover] =
|
|
3784
|
+
const [vy, setVy] = React24.useState(anchor.getFullYear());
|
|
3785
|
+
const [vm, setVm] = React24.useState(anchor.getMonth());
|
|
3786
|
+
const [mode2, setMode] = React24.useState("days");
|
|
3787
|
+
const [hover, setHover] = React24.useState(null);
|
|
3778
3788
|
const s = parse(sel.start), e = parse(sel.end);
|
|
3779
3789
|
const hoverEnd = range && s && !e && hover ? parse(hover) : null;
|
|
3780
3790
|
const inRange = (d) => {
|
|
@@ -3811,7 +3821,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3811
3821
|
const startPad = new Date(y, m, 1).getDay();
|
|
3812
3822
|
const cells = [];
|
|
3813
3823
|
for (let i = 0; i < 42; i++) cells.push(new Date(y, m, i - startPad + 1));
|
|
3814
|
-
return /* @__PURE__ */
|
|
3824
|
+
return /* @__PURE__ */ jsxs46("div", { className: "fd-cal-grid", style: { width: months > 1 ? 252 : "auto", flex: "none" }, onMouseLeave: () => setHover(null), children: [
|
|
3815
3825
|
DOW.map((d) => /* @__PURE__ */ jsx50("span", { className: "fd-cal-dow", children: d }, d)),
|
|
3816
3826
|
cells.map((d, i) => /* @__PURE__ */ jsx50(
|
|
3817
3827
|
"button",
|
|
@@ -3827,17 +3837,17 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3827
3837
|
] });
|
|
3828
3838
|
};
|
|
3829
3839
|
const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
|
|
3830
|
-
return /* @__PURE__ */
|
|
3831
|
-
/* @__PURE__ */
|
|
3840
|
+
return /* @__PURE__ */ jsxs46("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, children: [
|
|
3841
|
+
/* @__PURE__ */ jsxs46("div", { className: "fd-cal-head", children: [
|
|
3832
3842
|
/* @__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__ */
|
|
3843
|
+
/* @__PURE__ */ jsxs46("button", { type: "button", className: "fd-cal-title", onClick: () => setMode(mode2 === "days" ? "months" : mode2 === "months" ? "years" : "days"), children: [
|
|
3834
3844
|
mode2 === "days" ? MONTHS[vm] + " " + vy : mode2 === "months" ? vy : vy - 5 + " \u2013 " + (vy + 6),
|
|
3835
3845
|
/* @__PURE__ */ jsx50("i", { className: "ph ph-caret-down", style: { fontSize: 10, marginLeft: 6, color: "var(--text-muted)" } })
|
|
3836
3846
|
] }),
|
|
3837
3847
|
months > 1 && mode2 === "days" ? /* @__PURE__ */ jsx50("span", { className: "fd-cal-title", style: { cursor: "default", background: "none" }, children: MONTHS[nextM] + " " + nextY }) : null,
|
|
3838
3848
|
/* @__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
3849
|
] }),
|
|
3840
|
-
mode2 === "days" ? /* @__PURE__ */
|
|
3850
|
+
mode2 === "days" ? /* @__PURE__ */ jsxs46("div", { style: { display: "flex", gap: 18 }, children: [
|
|
3841
3851
|
monthGrid(vy, vm),
|
|
3842
3852
|
months > 1 ? monthGrid(nextY, nextM) : null
|
|
3843
3853
|
] }) : mode2 === "months" ? /* @__PURE__ */ jsx50("div", { className: "fd-cal-grid-months", children: MONTHS.map((m, i) => /* @__PURE__ */ jsx50(
|
|
@@ -3865,7 +3875,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3865
3875
|
},
|
|
3866
3876
|
y
|
|
3867
3877
|
)) }),
|
|
3868
|
-
/* @__PURE__ */
|
|
3878
|
+
/* @__PURE__ */ jsxs46("div", { className: "fd-cal-foot", children: [
|
|
3869
3879
|
/* @__PURE__ */ jsx50(
|
|
3870
3880
|
"button",
|
|
3871
3881
|
{
|
|
@@ -3881,7 +3891,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3881
3891
|
}
|
|
3882
3892
|
),
|
|
3883
3893
|
/* @__PURE__ */ jsx50("span", { style: { flex: 1 } }),
|
|
3884
|
-
range && sel.start ? /* @__PURE__ */
|
|
3894
|
+
range && sel.start ? /* @__PURE__ */ jsxs46("span", { className: "fd-body-sm fd-muted", children: [
|
|
3885
3895
|
fmt(sel.start),
|
|
3886
3896
|
sel.end ? " \u2192 " + fmt(sel.end) : " \u2192 pick an end"
|
|
3887
3897
|
] }) : null
|
|
@@ -3890,16 +3900,16 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3890
3900
|
}
|
|
3891
3901
|
function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, ...rest }) {
|
|
3892
3902
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
3893
|
-
const [open, setOpen] =
|
|
3894
|
-
const rootRef =
|
|
3895
|
-
const boxRef =
|
|
3903
|
+
const [open, setOpen] = React24.useState(false);
|
|
3904
|
+
const rootRef = React24.useRef(null);
|
|
3905
|
+
const boxRef = React24.useRef(null);
|
|
3896
3906
|
const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
|
|
3897
3907
|
const toggle = () => {
|
|
3898
3908
|
if (!disabled) setOpen(!open);
|
|
3899
3909
|
};
|
|
3900
|
-
return /* @__PURE__ */
|
|
3910
|
+
return /* @__PURE__ */ jsxs46("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
3901
3911
|
label ? /* @__PURE__ */ jsx50(FieldLabel, { id: labelId, required, onClick: toggle, children: label }) : null,
|
|
3902
|
-
/* @__PURE__ */
|
|
3912
|
+
/* @__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
3913
|
/* @__PURE__ */ jsx50("span", { className: "fd-input-icon", children: /* @__PURE__ */ jsx50("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }) }),
|
|
3904
3914
|
/* @__PURE__ */ jsx50(
|
|
3905
3915
|
"button",
|
|
@@ -3946,7 +3956,7 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3946
3956
|
)
|
|
3947
3957
|
}
|
|
3948
3958
|
),
|
|
3949
|
-
error ? /* @__PURE__ */
|
|
3959
|
+
error ? /* @__PURE__ */ jsxs46("span", { className: "fd-field-error", children: [
|
|
3950
3960
|
/* @__PURE__ */ jsx50("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3951
3961
|
error
|
|
3952
3962
|
] }) : help ? /* @__PURE__ */ jsx50("span", { className: "fd-field-help", children: help }) : null
|
|
@@ -3954,8 +3964,8 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3954
3964
|
}
|
|
3955
3965
|
|
|
3956
3966
|
// src/components/forms/TimePicker.tsx
|
|
3957
|
-
import * as
|
|
3958
|
-
import { jsx as jsx51, jsxs as
|
|
3967
|
+
import * as React25 from "react";
|
|
3968
|
+
import { jsx as jsx51, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
3959
3969
|
var pad = (n) => String(n).padStart(2, "0");
|
|
3960
3970
|
function ClockFace({ value = "09:00", onChange }) {
|
|
3961
3971
|
let [h24, m] = value.split(":").map(Number);
|
|
@@ -3963,9 +3973,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3963
3973
|
if (isNaN(m)) m = 0;
|
|
3964
3974
|
const pm = h24 >= 12;
|
|
3965
3975
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
3966
|
-
const [mode2, setMode] =
|
|
3967
|
-
const faceRef =
|
|
3968
|
-
const dragging =
|
|
3976
|
+
const [mode2, setMode] = React25.useState("h");
|
|
3977
|
+
const faceRef = React25.useRef(null);
|
|
3978
|
+
const dragging = React25.useRef(false);
|
|
3969
3979
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
3970
3980
|
const R = 108, NR = 80;
|
|
3971
3981
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -4000,8 +4010,8 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
4000
4010
|
};
|
|
4001
4011
|
const handAngle = mode2 === "h" ? h12 % 12 * 30 : m * 6;
|
|
4002
4012
|
const minuteOff = mode2 === "m" && m % 5 !== 0;
|
|
4003
|
-
return /* @__PURE__ */
|
|
4004
|
-
/* @__PURE__ */
|
|
4013
|
+
return /* @__PURE__ */ jsxs47("div", { style: { padding: "4px 14px 14px" }, children: [
|
|
4014
|
+
/* @__PURE__ */ jsxs47("div", { className: "fd-clock-digits", children: [
|
|
4005
4015
|
/* @__PURE__ */ jsx51("button", { type: "button", className: "fd-clock-digit" + (mode2 === "h" ? " is-active" : ""), onClick: () => setMode("h"), children: pad(h12) }),
|
|
4006
4016
|
/* @__PURE__ */ jsx51("span", { style: { fontSize: 24, fontWeight: 700, color: "var(--text-muted)" }, children: ":" }),
|
|
4007
4017
|
/* @__PURE__ */ jsx51("button", { type: "button", className: "fd-clock-digit" + (mode2 === "m" ? " is-active" : ""), onClick: () => setMode("m"), children: pad(m) }),
|
|
@@ -4016,7 +4026,7 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
4016
4026
|
ap
|
|
4017
4027
|
)) })
|
|
4018
4028
|
] }),
|
|
4019
|
-
/* @__PURE__ */
|
|
4029
|
+
/* @__PURE__ */ jsxs47("div", { className: "fd-clock", ref: faceRef, onPointerDown: down, onPointerMove: move, onPointerUp: upH, children: [
|
|
4020
4030
|
/* @__PURE__ */ jsx51("span", { className: "fd-clock-hand", style: { height: NR - (minuteOff ? 14 : 16), transform: "translateX(-50%) rotate(" + handAngle + "deg)", bottom: "50%" } }),
|
|
4021
4031
|
/* @__PURE__ */ jsx51("span", { className: "fd-clock-pivot" }),
|
|
4022
4032
|
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 +4048,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
4038
4048
|
}
|
|
4039
4049
|
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
|
|
4040
4050
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
4041
|
-
const [open, setOpen] =
|
|
4042
|
-
const rootRef =
|
|
4043
|
-
const boxRef =
|
|
4051
|
+
const [open, setOpen] = React25.useState(false);
|
|
4052
|
+
const rootRef = React25.useRef(null);
|
|
4053
|
+
const boxRef = React25.useRef(null);
|
|
4044
4054
|
const disp = () => {
|
|
4045
4055
|
if (!value) return "";
|
|
4046
4056
|
const [h, m] = value.split(":").map(Number);
|
|
@@ -4049,9 +4059,9 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4049
4059
|
const toggle = () => {
|
|
4050
4060
|
if (!disabled) setOpen(!open);
|
|
4051
4061
|
};
|
|
4052
|
-
return /* @__PURE__ */
|
|
4062
|
+
return /* @__PURE__ */ jsxs47("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
4053
4063
|
label ? /* @__PURE__ */ jsx51(FieldLabel, { id: labelId, required, onClick: toggle, children: label }) : null,
|
|
4054
|
-
/* @__PURE__ */
|
|
4064
|
+
/* @__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
4065
|
/* @__PURE__ */ jsx51("span", { className: "fd-input-icon", children: /* @__PURE__ */ jsx51("i", { className: "ph ph-clock", "aria-hidden": "true" }) }),
|
|
4056
4066
|
/* @__PURE__ */ jsx51(
|
|
4057
4067
|
"button",
|
|
@@ -4083,7 +4093,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4083
4093
|
offset: 6,
|
|
4084
4094
|
width: 262,
|
|
4085
4095
|
role: "presentation",
|
|
4086
|
-
footer: /* @__PURE__ */
|
|
4096
|
+
footer: /* @__PURE__ */ jsxs47(React25.Fragment, { children: [
|
|
4087
4097
|
/* @__PURE__ */ jsx51(
|
|
4088
4098
|
"button",
|
|
4089
4099
|
{
|
|
@@ -4103,7 +4113,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4103
4113
|
children: /* @__PURE__ */ jsx51(ClockFace, { value: value || "09:00", onChange: (v) => onChange && onChange({ target: { value: v } }) })
|
|
4104
4114
|
}
|
|
4105
4115
|
),
|
|
4106
|
-
error ? /* @__PURE__ */
|
|
4116
|
+
error ? /* @__PURE__ */ jsxs47("span", { className: "fd-field-error", children: [
|
|
4107
4117
|
/* @__PURE__ */ jsx51("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
4108
4118
|
error
|
|
4109
4119
|
] }) : help ? /* @__PURE__ */ jsx51("span", { className: "fd-field-help", children: help }) : null
|
|
@@ -4111,8 +4121,8 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4111
4121
|
}
|
|
4112
4122
|
|
|
4113
4123
|
// src/components/forms/Slider.tsx
|
|
4114
|
-
import * as
|
|
4115
|
-
import { jsx as jsx52, jsxs as
|
|
4124
|
+
import * as React26 from "react";
|
|
4125
|
+
import { jsx as jsx52, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
4116
4126
|
function Slider({
|
|
4117
4127
|
label,
|
|
4118
4128
|
min = 0,
|
|
@@ -4129,15 +4139,15 @@ function Slider({
|
|
|
4129
4139
|
...rest
|
|
4130
4140
|
}) {
|
|
4131
4141
|
const fieldId = useFieldId(id);
|
|
4132
|
-
const [dragging, setDragging] =
|
|
4142
|
+
const [dragging, setDragging] = React26.useState(false);
|
|
4133
4143
|
const v = value === void 0 ? min : Number(value);
|
|
4134
4144
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
4135
|
-
return /* @__PURE__ */
|
|
4136
|
-
label ? /* @__PURE__ */
|
|
4145
|
+
return /* @__PURE__ */ jsxs48("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
|
|
4146
|
+
label ? /* @__PURE__ */ jsxs48("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
4137
4147
|
/* @__PURE__ */ jsx52(FieldLabel, { htmlFor: fieldId, children: label }),
|
|
4138
4148
|
/* @__PURE__ */ jsx52("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: format(v) })
|
|
4139
4149
|
] }) : null,
|
|
4140
|
-
/* @__PURE__ */
|
|
4150
|
+
/* @__PURE__ */ jsxs48("div", { className: "fd-slider", children: [
|
|
4141
4151
|
/* @__PURE__ */ jsx52("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
4142
4152
|
showChip && dragging ? /* @__PURE__ */ jsx52("span", { className: "fd-slider-chip", style: { left: pct + "%" }, children: format(v) }) : null,
|
|
4143
4153
|
/* @__PURE__ */ jsx52(
|
|
@@ -4163,8 +4173,8 @@ function Slider({
|
|
|
4163
4173
|
}
|
|
4164
4174
|
|
|
4165
4175
|
// src/components/forms/RangeSlider.tsx
|
|
4166
|
-
import * as
|
|
4167
|
-
import { jsx as jsx53, jsxs as
|
|
4176
|
+
import * as React27 from "react";
|
|
4177
|
+
import { jsx as jsx53, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
4168
4178
|
function RangeSlider({
|
|
4169
4179
|
label,
|
|
4170
4180
|
min = 0,
|
|
@@ -4183,9 +4193,9 @@ function RangeSlider({
|
|
|
4183
4193
|
}) {
|
|
4184
4194
|
const fmt2 = format || ((v) => String(v));
|
|
4185
4195
|
const [a, b] = value || [min, max];
|
|
4186
|
-
const [drag, setDrag] =
|
|
4187
|
-
const [focus, setFocus] =
|
|
4188
|
-
const railRef =
|
|
4196
|
+
const [drag, setDrag] = React27.useState(null);
|
|
4197
|
+
const [focus, setFocus] = React27.useState(null);
|
|
4198
|
+
const railRef = React27.useRef(null);
|
|
4189
4199
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
4190
4200
|
const clampPair = (i, v) => {
|
|
4191
4201
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -4200,7 +4210,7 @@ function RangeSlider({
|
|
|
4200
4210
|
const r = railRef.current.getBoundingClientRect();
|
|
4201
4211
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
4202
4212
|
};
|
|
4203
|
-
|
|
4213
|
+
React27.useEffect(() => {
|
|
4204
4214
|
if (drag === null) return;
|
|
4205
4215
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
4206
4216
|
const upH = () => setDrag(null);
|
|
@@ -4269,19 +4279,19 @@ function RangeSlider({
|
|
|
4269
4279
|
};
|
|
4270
4280
|
const showChip = (i) => drag === i || focus === i;
|
|
4271
4281
|
const hasLabels = marks.some((m) => m.label);
|
|
4272
|
-
return /* @__PURE__ */
|
|
4273
|
-
label ? /* @__PURE__ */
|
|
4282
|
+
return /* @__PURE__ */ jsxs49("div", { className: ["fd-field", className].filter(Boolean).join(" "), ...rest, children: [
|
|
4283
|
+
label ? /* @__PURE__ */ jsxs49("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
4274
4284
|
/* @__PURE__ */ jsx53("span", { className: "fd-field-label", children: label }),
|
|
4275
|
-
/* @__PURE__ */
|
|
4285
|
+
/* @__PURE__ */ jsxs49("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: [
|
|
4276
4286
|
fmt2(a),
|
|
4277
4287
|
" \u2013 ",
|
|
4278
4288
|
fmt2(b)
|
|
4279
4289
|
] })
|
|
4280
4290
|
] }) : null,
|
|
4281
|
-
/* @__PURE__ */
|
|
4291
|
+
/* @__PURE__ */ jsxs49("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
|
|
4282
4292
|
/* @__PURE__ */ jsx53("span", { className: "fd-range-rail", ref: railRef }),
|
|
4283
4293
|
/* @__PURE__ */ jsx53("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
|
|
4284
|
-
marks.map((m) => /* @__PURE__ */
|
|
4294
|
+
marks.map((m) => /* @__PURE__ */ jsxs49(React27.Fragment, { children: [
|
|
4285
4295
|
/* @__PURE__ */ jsx53("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
|
|
4286
4296
|
m.label ? /* @__PURE__ */ jsx53("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
|
|
4287
4297
|
] }, m.value)),
|
|
@@ -4310,8 +4320,8 @@ function RangeSlider({
|
|
|
4310
4320
|
}
|
|
4311
4321
|
|
|
4312
4322
|
// src/components/forms/Dropzone.tsx
|
|
4313
|
-
import * as
|
|
4314
|
-
import { jsx as jsx54, jsxs as
|
|
4323
|
+
import * as React28 from "react";
|
|
4324
|
+
import { jsx as jsx54, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
4315
4325
|
function Dropzone({
|
|
4316
4326
|
onFiles,
|
|
4317
4327
|
onReject,
|
|
@@ -4325,8 +4335,8 @@ function Dropzone({
|
|
|
4325
4335
|
className = "",
|
|
4326
4336
|
style
|
|
4327
4337
|
}) {
|
|
4328
|
-
const [over, setOver] =
|
|
4329
|
-
const depth =
|
|
4338
|
+
const [over, setOver] = React28.useState(false);
|
|
4339
|
+
const depth = React28.useRef(0);
|
|
4330
4340
|
const has = (e) => {
|
|
4331
4341
|
const dt = e.dataTransfer;
|
|
4332
4342
|
if (!dt) return false;
|
|
@@ -4356,7 +4366,7 @@ function Dropzone({
|
|
|
4356
4366
|
if (rejected.length && onReject) onReject(rejected);
|
|
4357
4367
|
if (accepted.length && onFiles) onFiles(accepted);
|
|
4358
4368
|
};
|
|
4359
|
-
return /* @__PURE__ */
|
|
4369
|
+
return /* @__PURE__ */ jsxs50(
|
|
4360
4370
|
"div",
|
|
4361
4371
|
{
|
|
4362
4372
|
className: ["fd-dropzone", over ? "is-over" : "", className].filter(Boolean).join(" "),
|
|
@@ -4367,7 +4377,7 @@ function Dropzone({
|
|
|
4367
4377
|
onDrop: drop,
|
|
4368
4378
|
children: [
|
|
4369
4379
|
children,
|
|
4370
|
-
over ? /* @__PURE__ */ jsx54("div", { className: "fd-dropzone-veil", "aria-hidden": "true", children: /* @__PURE__ */
|
|
4380
|
+
over ? /* @__PURE__ */ jsx54("div", { className: "fd-dropzone-veil", "aria-hidden": "true", children: /* @__PURE__ */ jsxs50("div", { className: "fd-dropzone-card", children: [
|
|
4371
4381
|
/* @__PURE__ */ jsx54("i", { className: "ph ph-tray-arrow-down" }),
|
|
4372
4382
|
/* @__PURE__ */ jsx54("span", { className: "fd-dropzone-label", children: label }),
|
|
4373
4383
|
hint ? /* @__PURE__ */ jsx54("span", { className: "fd-dropzone-hint", children: hint }) : null
|
|
@@ -4388,8 +4398,8 @@ function FilePickButton({
|
|
|
4388
4398
|
className = "",
|
|
4389
4399
|
children
|
|
4390
4400
|
}) {
|
|
4391
|
-
const ref =
|
|
4392
|
-
return /* @__PURE__ */
|
|
4401
|
+
const ref = React28.useRef(null);
|
|
4402
|
+
return /* @__PURE__ */ jsxs50(React28.Fragment, { children: [
|
|
4393
4403
|
/* @__PURE__ */ jsx54(
|
|
4394
4404
|
"button",
|
|
4395
4405
|
{
|
|
@@ -4422,10 +4432,10 @@ function FilePickButton({
|
|
|
4422
4432
|
}
|
|
4423
4433
|
function useStagedFiles(upload, opts) {
|
|
4424
4434
|
const o = opts || {};
|
|
4425
|
-
const [items, setItems] =
|
|
4426
|
-
const controllers =
|
|
4435
|
+
const [items, setItems] = React28.useState([]);
|
|
4436
|
+
const controllers = React28.useRef({});
|
|
4427
4437
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
4428
|
-
const run =
|
|
4438
|
+
const run = React28.useCallback((att) => {
|
|
4429
4439
|
if (!upload) return;
|
|
4430
4440
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
4431
4441
|
controllers.current[att.id] = ac;
|
|
@@ -4442,14 +4452,14 @@ function useStagedFiles(upload, opts) {
|
|
|
4442
4452
|
delete controllers.current[att.id];
|
|
4443
4453
|
});
|
|
4444
4454
|
}, [upload]);
|
|
4445
|
-
const add =
|
|
4455
|
+
const add = React28.useCallback((files) => {
|
|
4446
4456
|
if (!upload) return [];
|
|
4447
4457
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
4448
4458
|
setItems((list) => list.concat(atts));
|
|
4449
4459
|
atts.forEach(run);
|
|
4450
4460
|
return atts;
|
|
4451
4461
|
}, [upload, run]);
|
|
4452
|
-
const remove =
|
|
4462
|
+
const remove = React28.useCallback((att) => {
|
|
4453
4463
|
const ac = controllers.current[att.id];
|
|
4454
4464
|
if (ac) {
|
|
4455
4465
|
try {
|
|
@@ -4460,10 +4470,10 @@ function useStagedFiles(upload, opts) {
|
|
|
4460
4470
|
}
|
|
4461
4471
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
4462
4472
|
}, []);
|
|
4463
|
-
const retry =
|
|
4473
|
+
const retry = React28.useCallback((att) => {
|
|
4464
4474
|
run(att);
|
|
4465
4475
|
}, [run]);
|
|
4466
|
-
const clear =
|
|
4476
|
+
const clear = React28.useCallback(() => {
|
|
4467
4477
|
Object.values(controllers.current).forEach((ac) => {
|
|
4468
4478
|
try {
|
|
4469
4479
|
ac && ac.abort();
|
|
@@ -4479,7 +4489,7 @@ function useStagedFiles(upload, opts) {
|
|
|
4479
4489
|
var DropzoneKit = { useStagedFiles };
|
|
4480
4490
|
|
|
4481
4491
|
// src/components/forms/FileGrid.tsx
|
|
4482
|
-
import { jsx as jsx55, jsxs as
|
|
4492
|
+
import { jsx as jsx55, jsxs as jsxs51 } from "react/jsx-runtime";
|
|
4483
4493
|
var truncateMiddle = (name, max = 34) => {
|
|
4484
4494
|
if (!name || name.length <= max) return name;
|
|
4485
4495
|
const ext = /\.[A-Za-z0-9]+$/.exec(name);
|
|
@@ -4497,8 +4507,8 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
4497
4507
|
const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
|
|
4498
4508
|
const meta = file.meta || (file.size ? formatBytes(file.size) : "");
|
|
4499
4509
|
const clickable = !!onOpen && !uploading;
|
|
4500
|
-
return /* @__PURE__ */
|
|
4501
|
-
/* @__PURE__ */
|
|
4510
|
+
return /* @__PURE__ */ jsxs51("div", { className: ["fd-file", compact3 ? "is-compact" : "", file.error ? "is-error" : "", uploading ? "is-uploading" : "", className].filter(Boolean).join(" "), children: [
|
|
4511
|
+
/* @__PURE__ */ jsxs51(
|
|
4502
4512
|
"button",
|
|
4503
4513
|
{
|
|
4504
4514
|
type: "button",
|
|
@@ -4507,16 +4517,16 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
4507
4517
|
onClick: clickable ? () => onOpen(file) : void 0,
|
|
4508
4518
|
title: file.name + (meta ? " \xB7 " + meta : ""),
|
|
4509
4519
|
children: [
|
|
4510
|
-
/* @__PURE__ */
|
|
4520
|
+
/* @__PURE__ */ jsxs51("span", { className: "fd-file-icon", children: [
|
|
4511
4521
|
thumb ? /* @__PURE__ */ jsx55("img", { src: thumb, alt: "" }) : /* @__PURE__ */ jsx55("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
|
|
4512
4522
|
(file.mime || "").startsWith("video/") ? /* @__PURE__ */ jsx55("i", { className: "ph ph-play fd-file-play", "aria-hidden": "true" }) : null
|
|
4513
4523
|
] }),
|
|
4514
|
-
/* @__PURE__ */
|
|
4524
|
+
/* @__PURE__ */ jsxs51("span", { className: "fd-file-text", children: [
|
|
4515
4525
|
/* @__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__ */
|
|
4526
|
+
/* @__PURE__ */ jsx55("span", { className: "fd-file-meta", children: file.error ? /* @__PURE__ */ jsxs51("span", { className: "fd-file-err", children: [
|
|
4517
4527
|
/* @__PURE__ */ jsx55("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
4518
4528
|
file.error
|
|
4519
|
-
] }) : uploading ? /* @__PURE__ */
|
|
4529
|
+
] }) : uploading ? /* @__PURE__ */ jsxs51("span", { className: "fd-tabular", children: [
|
|
4520
4530
|
Math.round(file.progress),
|
|
4521
4531
|
"% uploaded"
|
|
4522
4532
|
] }) : meta })
|
|
@@ -4533,10 +4543,10 @@ function FileTile({ file, onOpen, onRemove, maxHeight = 200, className = "" }) {
|
|
|
4533
4543
|
if (!file) return null;
|
|
4534
4544
|
const src = file.thumb && file.thumb.url || file.blobUrl || file.url;
|
|
4535
4545
|
const uploading = file.progress != null && file.progress < 100 && !file.error;
|
|
4536
|
-
return /* @__PURE__ */
|
|
4546
|
+
return /* @__PURE__ */ jsxs51("figure", { className: ["fd-tile", uploading ? "is-uploading" : "", file.error ? "is-error" : "", className].filter(Boolean).join(" "), children: [
|
|
4537
4547
|
/* @__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
4548
|
uploading ? /* @__PURE__ */ jsx55(Progress, { value: file.progress }) : null,
|
|
4539
|
-
file.error ? /* @__PURE__ */
|
|
4549
|
+
file.error ? /* @__PURE__ */ jsxs51("figcaption", { className: "fd-tile-err", children: [
|
|
4540
4550
|
/* @__PURE__ */ jsx55("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
4541
4551
|
file.error
|
|
4542
4552
|
] }) : null,
|
|
@@ -4560,9 +4570,9 @@ function FileCell({ file, onOpen, onRemove, onRetry }) {
|
|
|
4560
4570
|
const image = isImage(file.mime, file.name);
|
|
4561
4571
|
const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
|
|
4562
4572
|
const label = file.name + (file.size ? " \xB7 " + formatBytes(file.size) : "");
|
|
4563
|
-
return /* @__PURE__ */
|
|
4564
|
-
/* @__PURE__ */
|
|
4565
|
-
thumb ? /* @__PURE__ */ jsx55("img", { src: thumb, alt: "" }) : /* @__PURE__ */
|
|
4573
|
+
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: [
|
|
4574
|
+
/* @__PURE__ */ jsxs51("button", { type: "button", className: "fd-cell-main", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen || uploading, "aria-label": "Open " + file.name, children: [
|
|
4575
|
+
thumb ? /* @__PURE__ */ jsx55("img", { src: thumb, alt: "" }) : /* @__PURE__ */ jsxs51("span", { className: "fd-cell-doc", children: [
|
|
4566
4576
|
/* @__PURE__ */ jsx55("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
|
|
4567
4577
|
/* @__PURE__ */ jsx55("span", { className: "fd-cell-name", children: shortName(file.name) }),
|
|
4568
4578
|
/* @__PURE__ */ jsx55("span", { className: "fd-cell-size", children: file.meta || formatBytes(file.size) })
|
|
@@ -4580,15 +4590,15 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
4580
4590
|
if (!list.length) return null;
|
|
4581
4591
|
const pics = tiles ? list.filter((f) => isImage(f.mime, f.name)) : [];
|
|
4582
4592
|
const rest = list.filter((f) => pics.indexOf(f) === -1);
|
|
4583
|
-
return /* @__PURE__ */
|
|
4593
|
+
return /* @__PURE__ */ jsxs51("div", { className: ["fd-filegrid", className].filter(Boolean).join(" "), children: [
|
|
4584
4594
|
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
4595
|
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
4596
|
] });
|
|
4587
4597
|
}
|
|
4588
4598
|
|
|
4589
4599
|
// src/components/forms/MarkdownEditor.tsx
|
|
4590
|
-
import * as
|
|
4591
|
-
import { jsx as jsx56, jsxs as
|
|
4600
|
+
import * as React29 from "react";
|
|
4601
|
+
import { jsx as jsx56, jsxs as jsxs52 } from "react/jsx-runtime";
|
|
4592
4602
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
4593
4603
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
4594
4604
|
function inlineParts(text) {
|
|
@@ -4801,7 +4811,7 @@ function syncDom(root, value) {
|
|
|
4801
4811
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
4802
4812
|
}
|
|
4803
4813
|
var LIST_CONT = RE_LI;
|
|
4804
|
-
var MarkdownEditor =
|
|
4814
|
+
var MarkdownEditor = React29.forwardRef(function MarkdownEditor2({
|
|
4805
4815
|
value = "",
|
|
4806
4816
|
onChange,
|
|
4807
4817
|
onSubmit,
|
|
@@ -4820,10 +4830,10 @@ var MarkdownEditor = React28.forwardRef(function MarkdownEditor2({
|
|
|
4820
4830
|
className = "",
|
|
4821
4831
|
id
|
|
4822
4832
|
}, ref) {
|
|
4823
|
-
const boxRef =
|
|
4824
|
-
const composing =
|
|
4825
|
-
const pendingCaret =
|
|
4826
|
-
|
|
4833
|
+
const boxRef = React29.useRef(null);
|
|
4834
|
+
const composing = React29.useRef(false);
|
|
4835
|
+
const pendingCaret = React29.useRef(null);
|
|
4836
|
+
React29.useLayoutEffect(() => {
|
|
4827
4837
|
const root = boxRef.current;
|
|
4828
4838
|
if (!root || composing.current) return;
|
|
4829
4839
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -4832,7 +4842,7 @@ var MarkdownEditor = React28.forwardRef(function MarkdownEditor2({
|
|
|
4832
4842
|
pendingCaret.current = null;
|
|
4833
4843
|
if (active && caret != null) placeCaret(root, caret);
|
|
4834
4844
|
}, [value]);
|
|
4835
|
-
|
|
4845
|
+
React29.useEffect(() => {
|
|
4836
4846
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
4837
4847
|
}, [autoFocus]);
|
|
4838
4848
|
const caretNow = () => {
|
|
@@ -4899,7 +4909,7 @@ var MarkdownEditor = React28.forwardRef(function MarkdownEditor2({
|
|
|
4899
4909
|
api.replaceRange(from, to, next, from + next.length);
|
|
4900
4910
|
}
|
|
4901
4911
|
};
|
|
4902
|
-
|
|
4912
|
+
React29.useImperativeHandle(ref, () => api);
|
|
4903
4913
|
function detect(text, caret) {
|
|
4904
4914
|
if (!onTrigger) return;
|
|
4905
4915
|
const upto = text.slice(0, caret);
|
|
@@ -5012,7 +5022,7 @@ var MarkdownEditor = React28.forwardRef(function MarkdownEditor2({
|
|
|
5012
5022
|
api.replaceRange(s.start, s.end, text.replace(/\r\n?/g, "\n"));
|
|
5013
5023
|
};
|
|
5014
5024
|
const lh = 1.55;
|
|
5015
|
-
return /* @__PURE__ */
|
|
5025
|
+
return /* @__PURE__ */ jsxs52("div", { className: ["fd-rme-wrap", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "), children: [
|
|
5016
5026
|
/* @__PURE__ */ jsx56(
|
|
5017
5027
|
"div",
|
|
5018
5028
|
{
|
|
@@ -5051,10 +5061,10 @@ var MarkdownEditor = React28.forwardRef(function MarkdownEditor2({
|
|
|
5051
5061
|
});
|
|
5052
5062
|
|
|
5053
5063
|
// src/components/platform/AccountMenu.tsx
|
|
5054
|
-
import * as
|
|
5064
|
+
import * as React31 from "react";
|
|
5055
5065
|
|
|
5056
5066
|
// src/kits/session.ts
|
|
5057
|
-
import * as
|
|
5067
|
+
import * as React30 from "react";
|
|
5058
5068
|
var PERMISSION_CATALOG = [
|
|
5059
5069
|
{ group: "Plans", items: [
|
|
5060
5070
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -6621,8 +6631,8 @@ function roadmap(overrides) {
|
|
|
6621
6631
|
};
|
|
6622
6632
|
}
|
|
6623
6633
|
function useSession() {
|
|
6624
|
-
const [s, setS] =
|
|
6625
|
-
|
|
6634
|
+
const [s, setS] = React30.useState(getSession);
|
|
6635
|
+
React30.useEffect(() => subscribe(setS), []);
|
|
6626
6636
|
return s;
|
|
6627
6637
|
}
|
|
6628
6638
|
var SessionKit = {
|
|
@@ -6655,7 +6665,7 @@ var SessionKit = {
|
|
|
6655
6665
|
};
|
|
6656
6666
|
|
|
6657
6667
|
// src/components/platform/AccountMenu.tsx
|
|
6658
|
-
import { Fragment as Fragment14, jsx as jsx57, jsxs as
|
|
6668
|
+
import { Fragment as Fragment14, jsx as jsx57, jsxs as jsxs53 } from "react/jsx-runtime";
|
|
6659
6669
|
var DEFAULT_LINKS = [
|
|
6660
6670
|
{ id: "profile", label: "Your profile", icon: "user-circle", href: "../admin/index.html#profile" },
|
|
6661
6671
|
{ id: "preferences", label: "Preferences", icon: "sliders-horizontal", href: "../admin/index.html#preferences" }
|
|
@@ -6666,7 +6676,7 @@ var DEFAULT_ADMIN_LINKS = [
|
|
|
6666
6676
|
{ id: "flags", label: "Feature flags", icon: "toggle-right", href: "../admin/index.html#flags", perm: "flags.manage" }
|
|
6667
6677
|
];
|
|
6668
6678
|
function Item({ item, onPick }) {
|
|
6669
|
-
return /* @__PURE__ */
|
|
6679
|
+
return /* @__PURE__ */ jsxs53(
|
|
6670
6680
|
"button",
|
|
6671
6681
|
{
|
|
6672
6682
|
type: "button",
|
|
@@ -6692,9 +6702,9 @@ function AccountMenu({
|
|
|
6692
6702
|
...rest
|
|
6693
6703
|
}) {
|
|
6694
6704
|
const session = SessionKit.useSession();
|
|
6695
|
-
const [open, setOpen] =
|
|
6696
|
-
const [switching, setSwitching] =
|
|
6697
|
-
const ref =
|
|
6705
|
+
const [open, setOpen] = React31.useState(false);
|
|
6706
|
+
const [switching, setSwitching] = React31.useState(false);
|
|
6707
|
+
const ref = React31.useRef(null);
|
|
6698
6708
|
const user = session.user;
|
|
6699
6709
|
const visibleAdmin = adminLinks.filter((l) => !l.perm || SessionKit.can(l.perm));
|
|
6700
6710
|
const pick = (item) => {
|
|
@@ -6708,8 +6718,8 @@ function AccountMenu({
|
|
|
6708
6718
|
if (onSignOut) return onSignOut();
|
|
6709
6719
|
window.alert("Signed out. (Simulated \u2014 no auth provider is wired up.)");
|
|
6710
6720
|
};
|
|
6711
|
-
return /* @__PURE__ */
|
|
6712
|
-
/* @__PURE__ */
|
|
6721
|
+
return /* @__PURE__ */ jsxs53(Fragment14, { children: [
|
|
6722
|
+
/* @__PURE__ */ jsxs53(
|
|
6713
6723
|
"button",
|
|
6714
6724
|
{
|
|
6715
6725
|
type: "button",
|
|
@@ -6726,27 +6736,27 @@ function AccountMenu({
|
|
|
6726
6736
|
]
|
|
6727
6737
|
}
|
|
6728
6738
|
),
|
|
6729
|
-
/* @__PURE__ */ jsx57(Popover, { open, anchorRef: ref, onClose: () => setOpen(false), placement: "bottom-end", width: 272, children: /* @__PURE__ */
|
|
6730
|
-
/* @__PURE__ */
|
|
6739
|
+
/* @__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: [
|
|
6740
|
+
/* @__PURE__ */ jsxs53("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
6731
6741
|
/* @__PURE__ */ jsx57(Avatar, { name: user.name }),
|
|
6732
|
-
/* @__PURE__ */
|
|
6742
|
+
/* @__PURE__ */ jsxs53("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
|
|
6733
6743
|
/* @__PURE__ */ jsx57("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
|
|
6734
6744
|
/* @__PURE__ */ jsx57("span", { className: "fd-body-sm fd-muted fd-table-trunc", children: user.email })
|
|
6735
6745
|
] })
|
|
6736
6746
|
] }),
|
|
6737
6747
|
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
6748
|
/* @__PURE__ */ jsx57("div", { className: "fd-acct-group", children: links.map((l) => /* @__PURE__ */ jsx57(Item, { item: l, onPick: pick }, l.id)) }),
|
|
6739
|
-
visibleAdmin.length ? /* @__PURE__ */
|
|
6749
|
+
visibleAdmin.length ? /* @__PURE__ */ jsxs53("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
6740
6750
|
/* @__PURE__ */ jsx57("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: "Administration" }),
|
|
6741
6751
|
visibleAdmin.map((l) => /* @__PURE__ */ jsx57(Item, { item: l, onPick: pick }, l.id))
|
|
6742
6752
|
] }) : null,
|
|
6743
|
-
allowUserSwitch ? /* @__PURE__ */
|
|
6744
|
-
/* @__PURE__ */
|
|
6753
|
+
allowUserSwitch ? /* @__PURE__ */ jsxs53("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
6754
|
+
/* @__PURE__ */ jsxs53("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
|
|
6745
6755
|
/* @__PURE__ */ jsx57("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
|
|
6746
6756
|
/* @__PURE__ */ jsx57("span", { style: { flex: 1 }, children: "View as another member" }),
|
|
6747
6757
|
/* @__PURE__ */ jsx57("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
|
|
6748
6758
|
] }),
|
|
6749
|
-
switching ? /* @__PURE__ */ jsx57("div", { className: "fd-stack", style: { gap: 0 }, children: session.allUsers.filter((u) => u.status === "active").map((u) => /* @__PURE__ */
|
|
6759
|
+
switching ? /* @__PURE__ */ jsx57("div", { className: "fd-stack", style: { gap: 0 }, children: session.allUsers.filter((u) => u.status === "active").map((u) => /* @__PURE__ */ jsxs53(
|
|
6750
6760
|
"button",
|
|
6751
6761
|
{
|
|
6752
6762
|
type: "button",
|
|
@@ -6759,7 +6769,7 @@ function AccountMenu({
|
|
|
6759
6769
|
},
|
|
6760
6770
|
children: [
|
|
6761
6771
|
/* @__PURE__ */ jsx57(Avatar, { name: u.name, size: "sm" }),
|
|
6762
|
-
/* @__PURE__ */
|
|
6772
|
+
/* @__PURE__ */ jsxs53("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
|
|
6763
6773
|
/* @__PURE__ */ jsx57("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
|
|
6764
6774
|
/* @__PURE__ */ jsx57("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") })
|
|
6765
6775
|
] }),
|
|
@@ -6769,7 +6779,7 @@ function AccountMenu({
|
|
|
6769
6779
|
u.id
|
|
6770
6780
|
)) }) : null
|
|
6771
6781
|
] }) : null,
|
|
6772
|
-
/* @__PURE__ */ jsx57("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: /* @__PURE__ */
|
|
6782
|
+
/* @__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
6783
|
/* @__PURE__ */ jsx57("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
|
|
6774
6784
|
/* @__PURE__ */ jsx57("span", { style: { flex: 1 }, children: "Sign out" })
|
|
6775
6785
|
] }) })
|
|
@@ -6778,14 +6788,14 @@ function AccountMenu({
|
|
|
6778
6788
|
}
|
|
6779
6789
|
|
|
6780
6790
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
6781
|
-
import * as
|
|
6782
|
-
import { jsx as jsx58, jsxs as
|
|
6791
|
+
import * as React32 from "react";
|
|
6792
|
+
import { jsx as jsx58, jsxs as jsxs54 } from "react/jsx-runtime";
|
|
6783
6793
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
6784
6794
|
function Json({ obj }) {
|
|
6785
6795
|
return /* @__PURE__ */ jsx58("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
6786
6796
|
}
|
|
6787
6797
|
function Endpoint({ s, onRequest }) {
|
|
6788
|
-
const [tried, setTried] =
|
|
6798
|
+
const [tried, setTried] = React32.useState(null);
|
|
6789
6799
|
const run = async () => {
|
|
6790
6800
|
setTried("busy");
|
|
6791
6801
|
const t0 = (window.performance || Date).now();
|
|
@@ -6796,13 +6806,13 @@ function Endpoint({ s, onRequest }) {
|
|
|
6796
6806
|
setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
|
|
6797
6807
|
}
|
|
6798
6808
|
};
|
|
6799
|
-
return /* @__PURE__ */ jsx58(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */
|
|
6800
|
-
/* @__PURE__ */
|
|
6809
|
+
return /* @__PURE__ */ jsx58(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
6810
|
+
/* @__PURE__ */ jsxs54("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
|
|
6801
6811
|
/* @__PURE__ */ jsx58(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
|
|
6802
6812
|
/* @__PURE__ */ jsx58("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
|
|
6803
6813
|
s.isList ? /* @__PURE__ */ jsx58(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
|
|
6804
6814
|
/* @__PURE__ */ jsx58("span", { style: { flex: 1 } }),
|
|
6805
|
-
/* @__PURE__ */
|
|
6815
|
+
/* @__PURE__ */ jsxs54("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
6806
6816
|
s.latency[0],
|
|
6807
6817
|
"\u2013",
|
|
6808
6818
|
s.latency[1],
|
|
@@ -6810,31 +6820,31 @@ function Endpoint({ s, onRequest }) {
|
|
|
6810
6820
|
] }),
|
|
6811
6821
|
/* @__PURE__ */ jsx58(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
|
|
6812
6822
|
] }),
|
|
6813
|
-
/* @__PURE__ */
|
|
6814
|
-
/* @__PURE__ */
|
|
6823
|
+
/* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
|
|
6824
|
+
/* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6815
6825
|
/* @__PURE__ */ jsx58("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
|
|
6816
6826
|
/* @__PURE__ */ jsx58("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
|
|
6817
6827
|
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
6828
|
] }),
|
|
6819
|
-
/* @__PURE__ */
|
|
6820
|
-
s.request ? /* @__PURE__ */
|
|
6829
|
+
/* @__PURE__ */ jsxs54("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
|
|
6830
|
+
s.request ? /* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6821
6831
|
/* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", children: "Request body" }),
|
|
6822
6832
|
/* @__PURE__ */ jsx58(Json, { obj: s.request })
|
|
6823
6833
|
] }) : null,
|
|
6824
|
-
s.query ? /* @__PURE__ */
|
|
6834
|
+
s.query ? /* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6825
6835
|
/* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", children: "Query" }),
|
|
6826
6836
|
/* @__PURE__ */ jsx58(Json, { obj: s.query })
|
|
6827
6837
|
] }) : null,
|
|
6828
|
-
/* @__PURE__ */
|
|
6838
|
+
/* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6829
6839
|
/* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", children: "Response 200" }),
|
|
6830
6840
|
/* @__PURE__ */ jsx58(Json, { obj: s.response })
|
|
6831
6841
|
] })
|
|
6832
6842
|
] }),
|
|
6833
6843
|
s.notes ? /* @__PURE__ */ jsx58(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
|
|
6834
|
-
tried && tried !== "busy" ? /* @__PURE__ */
|
|
6835
|
-
/* @__PURE__ */
|
|
6844
|
+
tried && tried !== "busy" ? /* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6845
|
+
/* @__PURE__ */ jsxs54("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
6836
6846
|
/* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
|
|
6837
|
-
/* @__PURE__ */
|
|
6847
|
+
/* @__PURE__ */ jsxs54(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
|
|
6838
6848
|
tried.ms,
|
|
6839
6849
|
"ms"
|
|
6840
6850
|
] })
|
|
@@ -6858,29 +6868,29 @@ function ApiSpecBrowser({
|
|
|
6858
6868
|
className = "",
|
|
6859
6869
|
...rest
|
|
6860
6870
|
}) {
|
|
6861
|
-
const [q, setQ] =
|
|
6862
|
-
const [method, setMethod] =
|
|
6863
|
-
const [mod, setMod] =
|
|
6864
|
-
const [listOnly, setListOnly] =
|
|
6871
|
+
const [q, setQ] = React32.useState("");
|
|
6872
|
+
const [method, setMethod] = React32.useState(null);
|
|
6873
|
+
const [mod, setMod] = React32.useState(null);
|
|
6874
|
+
const [listOnly, setListOnly] = React32.useState(false);
|
|
6865
6875
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
6866
6876
|
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
6877
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
6868
6878
|
const methods = [...new Set(spec.map((s) => s.method))];
|
|
6869
6879
|
const listCount = spec.filter((s) => s.isList).length;
|
|
6870
|
-
return /* @__PURE__ */
|
|
6871
|
-
/* @__PURE__ */
|
|
6880
|
+
return /* @__PURE__ */ jsxs54("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
|
|
6881
|
+
/* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
6872
6882
|
kicker ? /* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", children: kicker }) : null,
|
|
6873
6883
|
/* @__PURE__ */ jsx58("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
6874
6884
|
lede ? /* @__PURE__ */ jsx58("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
|
|
6875
6885
|
] }),
|
|
6876
|
-
modules && modules.length ? /* @__PURE__ */
|
|
6886
|
+
modules && modules.length ? /* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
6877
6887
|
/* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
|
|
6878
|
-
/* @__PURE__ */
|
|
6879
|
-
/* @__PURE__ */
|
|
6888
|
+
/* @__PURE__ */ jsxs54("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
6889
|
+
/* @__PURE__ */ jsxs54(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
|
|
6880
6890
|
"All screens ",
|
|
6881
6891
|
/* @__PURE__ */ jsx58("span", { className: "fd-mono", children: spec.length })
|
|
6882
6892
|
] }),
|
|
6883
|
-
modules.map((m) => /* @__PURE__ */
|
|
6893
|
+
modules.map((m) => /* @__PURE__ */ jsxs54(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
|
|
6884
6894
|
m.label,
|
|
6885
6895
|
" ",
|
|
6886
6896
|
/* @__PURE__ */ jsx58("span", { className: "fd-mono", children: m.endpoints.length })
|
|
@@ -6897,19 +6907,19 @@ function ApiSpecBrowser({
|
|
|
6897
6907
|
) : null
|
|
6898
6908
|
] }) : null,
|
|
6899
6909
|
sourceNote ? /* @__PURE__ */ jsx58(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
|
|
6900
|
-
/* @__PURE__ */
|
|
6910
|
+
/* @__PURE__ */ jsxs54("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
6901
6911
|
/* @__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__ */
|
|
6912
|
+
methods.map((m) => /* @__PURE__ */ jsxs54(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
|
|
6903
6913
|
m,
|
|
6904
6914
|
" ",
|
|
6905
6915
|
/* @__PURE__ */ jsx58("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
|
|
6906
6916
|
] }, m)),
|
|
6907
|
-
listCount ? /* @__PURE__ */
|
|
6917
|
+
listCount ? /* @__PURE__ */ jsxs54(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
|
|
6908
6918
|
"Paged lists ",
|
|
6909
6919
|
/* @__PURE__ */ jsx58("span", { className: "fd-mono", children: listCount })
|
|
6910
6920
|
] }) : null,
|
|
6911
6921
|
/* @__PURE__ */ jsx58("span", { style: { flex: 1 } }),
|
|
6912
|
-
/* @__PURE__ */
|
|
6922
|
+
/* @__PURE__ */ jsxs54("span", { className: "fd-body-sm fd-muted", children: [
|
|
6913
6923
|
hits.length,
|
|
6914
6924
|
" of ",
|
|
6915
6925
|
spec.length,
|
|
@@ -6920,18 +6930,18 @@ function ApiSpecBrowser({
|
|
|
6920
6930
|
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
6931
|
const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
|
|
6922
6932
|
if (!items.length) return null;
|
|
6923
|
-
return /* @__PURE__ */
|
|
6933
|
+
return /* @__PURE__ */ jsxs54("div", { className: "fd-stack", style: { gap: 12 }, children: [
|
|
6924
6934
|
/* @__PURE__ */ jsx58("span", { className: "fd-label-lg", children: g }),
|
|
6925
6935
|
items.map((s) => /* @__PURE__ */ jsx58(Endpoint, { s, onRequest }, s.id))
|
|
6926
6936
|
] }, g);
|
|
6927
6937
|
}),
|
|
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__ */
|
|
6938
|
+
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
6939
|
/* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
|
|
6930
6940
|
/* @__PURE__ */ jsx58("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
|
|
6931
6941
|
] }, 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__ */
|
|
6942
|
+
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
6943
|
/* @__PURE__ */ jsx58(Badge, { tone: "danger", children: id }),
|
|
6934
|
-
/* @__PURE__ */
|
|
6944
|
+
/* @__PURE__ */ jsxs54("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
|
|
6935
6945
|
/* @__PURE__ */ jsx58("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
|
|
6936
6946
|
/* @__PURE__ */ jsx58("span", { className: "fd-body-sm fd-muted", children: why })
|
|
6937
6947
|
] })
|
|
@@ -6940,8 +6950,8 @@ function ApiSpecBrowser({
|
|
|
6940
6950
|
}
|
|
6941
6951
|
|
|
6942
6952
|
// src/components/platform/ProfilePage.tsx
|
|
6943
|
-
import * as
|
|
6944
|
-
import { jsx as jsx59, jsxs as
|
|
6953
|
+
import * as React33 from "react";
|
|
6954
|
+
import { jsx as jsx59, jsxs as jsxs55 } from "react/jsx-runtime";
|
|
6945
6955
|
var TIMEZONES = ["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles", "America/Anchorage", "Pacific/Honolulu", "Europe/London", "Europe/Berlin"];
|
|
6946
6956
|
var NOTIFY = [
|
|
6947
6957
|
{ key: "planShared", label: "A plan is shared with me", detail: "Someone sends you a plan or a client link." },
|
|
@@ -6953,7 +6963,7 @@ var NOTIFY = [
|
|
|
6953
6963
|
function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSessions = true, className = "", ...rest }) {
|
|
6954
6964
|
const session = SessionKit.useSession();
|
|
6955
6965
|
const user = userProp || session.user;
|
|
6956
|
-
const [draft, setDraft] =
|
|
6966
|
+
const [draft, setDraft] = React33.useState(() => ({
|
|
6957
6967
|
name: user.name || "",
|
|
6958
6968
|
title: user.title || "",
|
|
6959
6969
|
email: user.email || "",
|
|
@@ -6962,8 +6972,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6962
6972
|
bio: user.bio || "",
|
|
6963
6973
|
notify: user.notify || { planShared: true, planChanged: true, goalMissed: true, flagChanged: false, weekly: true }
|
|
6964
6974
|
}));
|
|
6965
|
-
const [saving, setSaving] =
|
|
6966
|
-
const [saved, setSaved] =
|
|
6975
|
+
const [saving, setSaving] = React33.useState(false);
|
|
6976
|
+
const [saved, setSaved] = React33.useState(false);
|
|
6967
6977
|
const set = (k, v) => {
|
|
6968
6978
|
setDraft((d) => Object.assign({}, d, { [k]: v }));
|
|
6969
6979
|
setSaved(false);
|
|
@@ -6985,22 +6995,22 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6985
6995
|
{ id: "s2", device: "iPhone 15 \xB7 Safari", where: "Denver, CO", when: "2 hours ago" },
|
|
6986
6996
|
{ id: "s3", device: "Windows \xB7 Edge", where: "Chicago, IL", when: "Aug 12" }
|
|
6987
6997
|
];
|
|
6988
|
-
return /* @__PURE__ */
|
|
6989
|
-
/* @__PURE__ */
|
|
6998
|
+
return /* @__PURE__ */ jsxs55("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, ...rest, children: [
|
|
6999
|
+
/* @__PURE__ */ jsxs55("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
6990
7000
|
/* @__PURE__ */ jsx59("span", { className: "fd-overline fd-muted", children: "Account" }),
|
|
6991
7001
|
/* @__PURE__ */ jsx59("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
|
|
6992
7002
|
/* @__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
7003
|
] }),
|
|
6994
|
-
/* @__PURE__ */ jsx59(Card, { elevation: "flat", children: /* @__PURE__ */
|
|
7004
|
+
/* @__PURE__ */ jsx59(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs55("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
|
|
6995
7005
|
/* @__PURE__ */ jsx59(Avatar, { name: draft.name || user.name, size: "lg" }),
|
|
6996
|
-
/* @__PURE__ */
|
|
7006
|
+
/* @__PURE__ */ jsxs55("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
|
|
6997
7007
|
/* @__PURE__ */ jsx59("span", { className: "fd-h3", style: { margin: 0 }, children: draft.name || user.name }),
|
|
6998
|
-
/* @__PURE__ */
|
|
7008
|
+
/* @__PURE__ */ jsxs55("span", { className: "fd-body-sm fd-muted", children: [
|
|
6999
7009
|
draft.title || "No title set",
|
|
7000
7010
|
" \xB7 ",
|
|
7001
7011
|
user.team || "No team"
|
|
7002
7012
|
] }),
|
|
7003
|
-
/* @__PURE__ */
|
|
7013
|
+
/* @__PURE__ */ jsxs55("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
|
|
7004
7014
|
session.roles.map((r) => /* @__PURE__ */ jsx59(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
|
|
7005
7015
|
user.sso ? /* @__PURE__ */ jsx59(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
|
|
7006
7016
|
] })
|
|
@@ -7010,17 +7020,17 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7010
7020
|
/* @__PURE__ */ jsx59(
|
|
7011
7021
|
Card,
|
|
7012
7022
|
{
|
|
7013
|
-
title: /* @__PURE__ */
|
|
7023
|
+
title: /* @__PURE__ */ jsxs55("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
7014
7024
|
/* @__PURE__ */ jsx59("span", { children: "Identity" }),
|
|
7015
7025
|
/* @__PURE__ */ jsx59("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Name and title appear on plans you share" })
|
|
7016
7026
|
] }),
|
|
7017
7027
|
elevation: "flat",
|
|
7018
|
-
children: /* @__PURE__ */
|
|
7019
|
-
/* @__PURE__ */
|
|
7028
|
+
children: /* @__PURE__ */ jsxs55("div", { className: "fd-stack", style: { gap: 14 }, children: [
|
|
7029
|
+
/* @__PURE__ */ jsxs55("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
|
|
7020
7030
|
/* @__PURE__ */ jsx59(Input, { label: "Full name", value: draft.name, onChange: (e) => set("name", e.target.value) }),
|
|
7021
7031
|
/* @__PURE__ */ jsx59(Input, { label: "Job title", value: draft.title, onChange: (e) => set("title", e.target.value), placeholder: "e.g. Senior media planner" })
|
|
7022
7032
|
] }),
|
|
7023
|
-
/* @__PURE__ */
|
|
7033
|
+
/* @__PURE__ */ jsxs55("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
|
|
7024
7034
|
/* @__PURE__ */ jsx59(
|
|
7025
7035
|
Input,
|
|
7026
7036
|
{
|
|
@@ -7047,7 +7057,7 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7047
7057
|
] })
|
|
7048
7058
|
}
|
|
7049
7059
|
),
|
|
7050
|
-
/* @__PURE__ */ jsx59(Card, { title: "Working preferences", elevation: "flat", children: /* @__PURE__ */
|
|
7060
|
+
/* @__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
7061
|
/* @__PURE__ */ jsx59(
|
|
7052
7062
|
Select,
|
|
7053
7063
|
{
|
|
@@ -7063,7 +7073,7 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7063
7073
|
/* @__PURE__ */ jsx59(
|
|
7064
7074
|
Card,
|
|
7065
7075
|
{
|
|
7066
|
-
title: /* @__PURE__ */
|
|
7076
|
+
title: /* @__PURE__ */ jsxs55("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
7067
7077
|
/* @__PURE__ */ jsx59("span", { children: "Notifications" }),
|
|
7068
7078
|
/* @__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
7079
|
] }),
|
|
@@ -7071,10 +7081,10 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7071
7081
|
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
7082
|
}
|
|
7073
7083
|
),
|
|
7074
|
-
/* @__PURE__ */
|
|
7084
|
+
/* @__PURE__ */ jsxs55(
|
|
7075
7085
|
Card,
|
|
7076
7086
|
{
|
|
7077
|
-
title: /* @__PURE__ */
|
|
7087
|
+
title: /* @__PURE__ */ jsxs55("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
7078
7088
|
/* @__PURE__ */ jsx59("span", { children: "Access" }),
|
|
7079
7089
|
/* @__PURE__ */ jsx59("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
|
|
7080
7090
|
] }),
|
|
@@ -7090,9 +7100,9 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7090
7100
|
}
|
|
7091
7101
|
),
|
|
7092
7102
|
children: [
|
|
7093
|
-
/* @__PURE__ */
|
|
7103
|
+
/* @__PURE__ */ jsxs55("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
7094
7104
|
/* @__PURE__ */ jsx59(CardRow, { label: "Roles", children: session.roles.map((r) => r.name).join(", ") || "None" }),
|
|
7095
|
-
/* @__PURE__ */
|
|
7105
|
+
/* @__PURE__ */ jsxs55(CardRow, { label: "Permissions", children: [
|
|
7096
7106
|
session.permissions.length,
|
|
7097
7107
|
" granted"
|
|
7098
7108
|
] }),
|
|
@@ -7108,11 +7118,11 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7108
7118
|
title: "Signed-in devices",
|
|
7109
7119
|
elevation: "flat",
|
|
7110
7120
|
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__ */
|
|
7121
|
+
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
7122
|
/* @__PURE__ */ jsx59("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
7113
|
-
/* @__PURE__ */
|
|
7123
|
+
/* @__PURE__ */ jsxs55("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
|
|
7114
7124
|
/* @__PURE__ */ jsx59("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
|
|
7115
|
-
/* @__PURE__ */
|
|
7125
|
+
/* @__PURE__ */ jsxs55("span", { className: "fd-body-sm fd-muted", children: [
|
|
7116
7126
|
s.where,
|
|
7117
7127
|
" \xB7 ",
|
|
7118
7128
|
s.when
|
|
@@ -7122,7 +7132,7 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7122
7132
|
] }, s.id)) })
|
|
7123
7133
|
}
|
|
7124
7134
|
) : null,
|
|
7125
|
-
/* @__PURE__ */
|
|
7135
|
+
/* @__PURE__ */ jsxs55("div", { className: "fd-row", style: {
|
|
7126
7136
|
gap: 10,
|
|
7127
7137
|
flexWrap: "wrap",
|
|
7128
7138
|
position: "sticky",
|
|
@@ -7153,10 +7163,10 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7153
7163
|
}
|
|
7154
7164
|
|
|
7155
7165
|
// src/components/platform/RoadmapTimeline.tsx
|
|
7156
|
-
import * as
|
|
7166
|
+
import * as React35 from "react";
|
|
7157
7167
|
|
|
7158
7168
|
// src/kits/runtime.ts
|
|
7159
|
-
import * as
|
|
7169
|
+
import * as React34 from "react";
|
|
7160
7170
|
var WIRED_ENDPOINTS = [
|
|
7161
7171
|
// Nothing yet. Every id below would come from a real service:
|
|
7162
7172
|
// "plan.get", "placements.list", …
|
|
@@ -7327,8 +7337,8 @@ var RuntimeKit = {
|
|
|
7327
7337
|
};
|
|
7328
7338
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
7329
7339
|
function useRuntimeMode() {
|
|
7330
|
-
const [m, setM] =
|
|
7331
|
-
|
|
7340
|
+
const [m, setM] = React34.useState(RuntimeKit.getMode());
|
|
7341
|
+
React34.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
7332
7342
|
return m;
|
|
7333
7343
|
}
|
|
7334
7344
|
function useFeatureStatus(key) {
|
|
@@ -7347,7 +7357,7 @@ var UseRuntimeMode = useRuntimeMode;
|
|
|
7347
7357
|
var UseFeatureStatus = useFeatureStatus;
|
|
7348
7358
|
|
|
7349
7359
|
// src/components/platform/RoadmapTimeline.tsx
|
|
7350
|
-
import { jsx as jsx60, jsxs as
|
|
7360
|
+
import { jsx as jsx60, jsxs as jsxs56 } from "react/jsx-runtime";
|
|
7351
7361
|
var STATUS = {
|
|
7352
7362
|
shipped: { tone: "success", icon: "check-circle", label: "Wired" },
|
|
7353
7363
|
next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
|
|
@@ -7362,24 +7372,24 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
7362
7372
|
const s = STATUS[item.status] || STATUS.planned;
|
|
7363
7373
|
const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
|
|
7364
7374
|
const blocking = deps.filter((d) => !d.implemented);
|
|
7365
|
-
return /* @__PURE__ */ jsx60(Card, { elevation: "flat", children: /* @__PURE__ */
|
|
7366
|
-
/* @__PURE__ */
|
|
7375
|
+
return /* @__PURE__ */ jsx60(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs56("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
7376
|
+
/* @__PURE__ */ jsxs56("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
7367
7377
|
/* @__PURE__ */ jsx60("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
|
|
7368
7378
|
/* @__PURE__ */ jsx60(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
|
|
7369
7379
|
/* @__PURE__ */ jsx60(Badge, { tone: s.tone, icon: s.icon, children: s.label })
|
|
7370
7380
|
] }),
|
|
7371
7381
|
/* @__PURE__ */ jsx60("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
|
|
7372
|
-
item.backend ? /* @__PURE__ */
|
|
7382
|
+
item.backend ? /* @__PURE__ */ jsxs56("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
|
|
7373
7383
|
/* @__PURE__ */ jsx60("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
|
|
7374
7384
|
/* @__PURE__ */ jsx60("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
|
|
7375
7385
|
] }) : null,
|
|
7376
|
-
/* @__PURE__ */
|
|
7377
|
-
item.effort ? /* @__PURE__ */
|
|
7386
|
+
/* @__PURE__ */ jsxs56("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
7387
|
+
item.effort ? /* @__PURE__ */ jsxs56("span", { className: "fd-body-sm fd-muted", children: [
|
|
7378
7388
|
/* @__PURE__ */ jsx60("i", { className: "ph ph-hourglass-medium" }),
|
|
7379
7389
|
" ",
|
|
7380
7390
|
item.effort
|
|
7381
7391
|
] }) : null,
|
|
7382
|
-
/* @__PURE__ */
|
|
7392
|
+
/* @__PURE__ */ jsxs56("span", { className: "fd-body-sm fd-muted", children: [
|
|
7383
7393
|
/* @__PURE__ */ jsx60("i", { className: "ph ph-user" }),
|
|
7384
7394
|
" ",
|
|
7385
7395
|
item.owner
|
|
@@ -7396,11 +7406,11 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
7396
7406
|
}
|
|
7397
7407
|
)
|
|
7398
7408
|
] }),
|
|
7399
|
-
deps.length ? /* @__PURE__ */
|
|
7409
|
+
deps.length ? /* @__PURE__ */ jsxs56("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
|
|
7400
7410
|
/* @__PURE__ */ jsx60("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
|
|
7401
7411
|
deps.map((d) => /* @__PURE__ */ jsx60(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
|
|
7402
7412
|
] }) : null,
|
|
7403
|
-
blocking.length && !item.implemented ? /* @__PURE__ */
|
|
7413
|
+
blocking.length && !item.implemented ? /* @__PURE__ */ jsxs56("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
|
|
7404
7414
|
"Blocked until ",
|
|
7405
7415
|
blocking.map((d) => d.label).join(" and "),
|
|
7406
7416
|
" ",
|
|
@@ -7411,12 +7421,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
7411
7421
|
}
|
|
7412
7422
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
7413
7423
|
const session = SessionKit.useSession();
|
|
7414
|
-
const [project, setProject] =
|
|
7415
|
-
const [q, setQ] =
|
|
7416
|
-
const scrollRef =
|
|
7417
|
-
const nowRef =
|
|
7418
|
-
const rm =
|
|
7419
|
-
const byKey =
|
|
7424
|
+
const [project, setProject] = React35.useState("");
|
|
7425
|
+
const [q, setQ] = React35.useState("");
|
|
7426
|
+
const scrollRef = React35.useRef(null);
|
|
7427
|
+
const nowRef = React35.useRef(null);
|
|
7428
|
+
const rm = React35.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
7429
|
+
const byKey = React35.useMemo(() => {
|
|
7420
7430
|
const m = {};
|
|
7421
7431
|
rm.items.forEach((i) => {
|
|
7422
7432
|
m[i.key] = i;
|
|
@@ -7425,7 +7435,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7425
7435
|
}, [rm]);
|
|
7426
7436
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
7427
7437
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
7428
|
-
|
|
7438
|
+
React35.useEffect(() => {
|
|
7429
7439
|
let raf1 = 0, raf2 = 0;
|
|
7430
7440
|
const place = () => {
|
|
7431
7441
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -7453,19 +7463,19 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7453
7463
|
}, 0);
|
|
7454
7464
|
const nextPhase = items.find((i) => !i.implemented);
|
|
7455
7465
|
let lastPhase = null;
|
|
7456
|
-
return /* @__PURE__ */
|
|
7457
|
-
/* @__PURE__ */
|
|
7466
|
+
return /* @__PURE__ */ jsxs56("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
|
|
7467
|
+
/* @__PURE__ */ jsxs56("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
7458
7468
|
/* @__PURE__ */ jsx60("span", { className: "fd-overline fd-muted", children: "Architecture" }),
|
|
7459
7469
|
/* @__PURE__ */ jsx60("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
7460
7470
|
/* @__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
7471
|
] }),
|
|
7462
|
-
/* @__PURE__ */
|
|
7472
|
+
/* @__PURE__ */ jsxs56("div", { className: "fd-grid-stats is-thin", children: [
|
|
7463
7473
|
/* @__PURE__ */ jsx60(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
|
|
7464
7474
|
/* @__PURE__ */ jsx60(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
|
|
7465
7475
|
/* @__PURE__ */ jsx60(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
|
|
7466
7476
|
/* @__PURE__ */ jsx60(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
|
|
7467
7477
|
] }),
|
|
7468
|
-
/* @__PURE__ */
|
|
7478
|
+
/* @__PURE__ */ jsxs56("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
7469
7479
|
/* @__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
7480
|
/* @__PURE__ */ jsx60(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
|
|
7471
7481
|
/* @__PURE__ */ jsx60("span", { style: { flex: 1 } }),
|
|
@@ -7492,23 +7502,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7492
7502
|
actions: null
|
|
7493
7503
|
}
|
|
7494
7504
|
),
|
|
7495
|
-
/* @__PURE__ */ jsx60("div", { className: "fd-rm", children: /* @__PURE__ */ jsx60("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */
|
|
7505
|
+
/* @__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
7506
|
/* @__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
7507
|
items.map((item, n) => {
|
|
7498
7508
|
const showPhase = item.phase !== lastPhase;
|
|
7499
7509
|
lastPhase = item.phase;
|
|
7500
7510
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
7501
7511
|
const isBoundary = n === firstPending;
|
|
7502
|
-
return /* @__PURE__ */
|
|
7503
|
-
showPhase ? /* @__PURE__ */
|
|
7504
|
-
/* @__PURE__ */
|
|
7512
|
+
return /* @__PURE__ */ jsxs56(React35.Fragment, { children: [
|
|
7513
|
+
showPhase ? /* @__PURE__ */ jsxs56("div", { className: "fd-rm-era", children: [
|
|
7514
|
+
/* @__PURE__ */ jsxs56("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
7505
7515
|
/* @__PURE__ */ jsx60("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
7506
|
-
item.phase === 0 ? null : /* @__PURE__ */
|
|
7516
|
+
item.phase === 0 ? null : /* @__PURE__ */ jsxs56("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
7507
7517
|
fmtDate(item.phaseStart),
|
|
7508
7518
|
" \u2013 ",
|
|
7509
7519
|
fmtDate(item.date)
|
|
7510
7520
|
] }),
|
|
7511
|
-
/* @__PURE__ */
|
|
7521
|
+
/* @__PURE__ */ jsxs56("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
7512
7522
|
"\xB7 ",
|
|
7513
7523
|
inPhase,
|
|
7514
7524
|
" feature",
|
|
@@ -7517,13 +7527,13 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7517
7527
|
] }),
|
|
7518
7528
|
item.phaseWhy ? /* @__PURE__ */ jsx60("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
|
|
7519
7529
|
] }) : null,
|
|
7520
|
-
isBoundary ? /* @__PURE__ */ jsx60("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */
|
|
7530
|
+
isBoundary ? /* @__PURE__ */ jsx60("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs56("span", { className: "fd-rm-now-pill", children: [
|
|
7521
7531
|
/* @__PURE__ */ jsx60("i", { className: "ph ph-map-pin" }),
|
|
7522
7532
|
" You are here \u2014 everything above is wired"
|
|
7523
7533
|
] }) }) : null,
|
|
7524
|
-
/* @__PURE__ */
|
|
7534
|
+
/* @__PURE__ */ jsxs56("div", { className: "fd-rm-row", children: [
|
|
7525
7535
|
/* @__PURE__ */ jsx60("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
|
|
7526
|
-
/* @__PURE__ */
|
|
7536
|
+
/* @__PURE__ */ jsxs56("div", { className: "fd-rm-date", children: [
|
|
7527
7537
|
fmtDate(item.date),
|
|
7528
7538
|
/* @__PURE__ */ jsx60("br", {}),
|
|
7529
7539
|
/* @__PURE__ */ jsx60("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
|
|
@@ -7534,7 +7544,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7534
7544
|
}),
|
|
7535
7545
|
!items.length ? /* @__PURE__ */ jsx60("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
|
|
7536
7546
|
] }) }) }),
|
|
7537
|
-
/* @__PURE__ */
|
|
7547
|
+
/* @__PURE__ */ jsxs56("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
|
|
7538
7548
|
"Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
|
|
7539
7549
|
/* @__PURE__ */ jsx60("code", { className: "fd-mono", children: "implemented" }),
|
|
7540
7550
|
" field, so this page cannot drift from what the apps actually do."
|
|
@@ -7543,9 +7553,9 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7543
7553
|
}
|
|
7544
7554
|
|
|
7545
7555
|
// src/components/platform/ComingSoon.tsx
|
|
7546
|
-
import * as
|
|
7556
|
+
import * as React36 from "react";
|
|
7547
7557
|
import { createPortal as createPortal5 } from "react-dom";
|
|
7548
|
-
import { Fragment as Fragment16, jsx as jsx61, jsxs as
|
|
7558
|
+
import { Fragment as Fragment16, jsx as jsx61, jsxs as jsxs57 } from "react/jsx-runtime";
|
|
7549
7559
|
var SOON_HOVERCARD_BASE = 220;
|
|
7550
7560
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
7551
7561
|
function readBypassed() {
|
|
@@ -7562,8 +7572,8 @@ function writeBypassed(list) {
|
|
|
7562
7572
|
}
|
|
7563
7573
|
}
|
|
7564
7574
|
function useBypass(key) {
|
|
7565
|
-
const [on, setOn] =
|
|
7566
|
-
|
|
7575
|
+
const [on, setOn] = React36.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
7576
|
+
React36.useEffect(() => {
|
|
7567
7577
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
7568
7578
|
}, [key]);
|
|
7569
7579
|
const set = (next) => {
|
|
@@ -7576,43 +7586,43 @@ function useBypass(key) {
|
|
|
7576
7586
|
return [on, set];
|
|
7577
7587
|
}
|
|
7578
7588
|
function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
|
|
7579
|
-
return /* @__PURE__ */
|
|
7580
|
-
/* @__PURE__ */
|
|
7589
|
+
return /* @__PURE__ */ jsxs57(Fragment16, { children: [
|
|
7590
|
+
/* @__PURE__ */ jsxs57("span", { className: "fd-soon-badge", children: [
|
|
7581
7591
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
7582
7592
|
label
|
|
7583
7593
|
] }),
|
|
7584
7594
|
detail ? /* @__PURE__ */ jsx61("span", { className: "fd-soon-detail", children: detail }) : null,
|
|
7585
|
-
backend ? /* @__PURE__ */
|
|
7595
|
+
backend ? /* @__PURE__ */ jsxs57("span", { className: "fd-soon-backend", children: [
|
|
7586
7596
|
/* @__PURE__ */ jsx61("span", { className: "fd-overline", children: "Needs" }),
|
|
7587
7597
|
" ",
|
|
7588
7598
|
backend
|
|
7589
7599
|
] }) : null,
|
|
7590
|
-
eta || effort || onRoadmap ? /* @__PURE__ */
|
|
7591
|
-
eta ? /* @__PURE__ */
|
|
7600
|
+
eta || effort || onRoadmap ? /* @__PURE__ */ jsxs57("span", { className: "fd-soon-meta", children: [
|
|
7601
|
+
eta ? /* @__PURE__ */ jsxs57("span", { children: [
|
|
7592
7602
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
|
|
7593
7603
|
" ",
|
|
7594
7604
|
eta
|
|
7595
7605
|
] }) : null,
|
|
7596
|
-
effort ? /* @__PURE__ */
|
|
7606
|
+
effort ? /* @__PURE__ */ jsxs57("span", { children: [
|
|
7597
7607
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
|
|
7598
7608
|
" ",
|
|
7599
7609
|
effort
|
|
7600
7610
|
] }) : null,
|
|
7601
|
-
onRoadmap ? /* @__PURE__ */
|
|
7611
|
+
onRoadmap ? /* @__PURE__ */ jsxs57("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
7602
7612
|
"See the roadmap ",
|
|
7603
7613
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7604
7614
|
] }) : null
|
|
7605
7615
|
] }) : null,
|
|
7606
|
-
allowed ? /* @__PURE__ */
|
|
7616
|
+
allowed ? /* @__PURE__ */ jsxs57("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
|
|
7607
7617
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-eye", "aria-hidden": "true" }),
|
|
7608
7618
|
" View and use it anyway"
|
|
7609
7619
|
] }) : null
|
|
7610
7620
|
] });
|
|
7611
7621
|
}
|
|
7612
7622
|
function useHoverCard(open) {
|
|
7613
|
-
const anchor =
|
|
7614
|
-
const [pos, setPos] =
|
|
7615
|
-
|
|
7623
|
+
const anchor = React36.useRef(null);
|
|
7624
|
+
const [pos, setPos] = React36.useState(null);
|
|
7625
|
+
React36.useLayoutEffect(() => {
|
|
7616
7626
|
if (!open || !anchor.current) {
|
|
7617
7627
|
setPos(null);
|
|
7618
7628
|
return;
|
|
@@ -7664,7 +7674,7 @@ function ComingSoon({
|
|
|
7664
7674
|
const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
|
|
7665
7675
|
if (inline) {
|
|
7666
7676
|
if (allowed && bypassed) {
|
|
7667
|
-
return /* @__PURE__ */
|
|
7677
|
+
return /* @__PURE__ */ jsxs57("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
|
|
7668
7678
|
children,
|
|
7669
7679
|
/* @__PURE__ */ jsx61(
|
|
7670
7680
|
"button",
|
|
@@ -7699,19 +7709,19 @@ function ComingSoon({
|
|
|
7699
7709
|
);
|
|
7700
7710
|
}
|
|
7701
7711
|
if (allowed && bypassed) {
|
|
7702
|
-
return /* @__PURE__ */
|
|
7703
|
-
/* @__PURE__ */
|
|
7704
|
-
/* @__PURE__ */
|
|
7712
|
+
return /* @__PURE__ */ jsxs57("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
|
|
7713
|
+
/* @__PURE__ */ jsxs57("div", { className: "fd-soon-bar", role: "status", children: [
|
|
7714
|
+
/* @__PURE__ */ jsxs57("span", { className: "fd-soon-badge", children: [
|
|
7705
7715
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
7706
7716
|
"Unwired feature \u2014 you are using it anyway"
|
|
7707
7717
|
] }),
|
|
7708
7718
|
/* @__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__ */
|
|
7719
|
+
/* @__PURE__ */ jsxs57("span", { className: "fd-soon-bar-actions", children: [
|
|
7720
|
+
onRoadmap ? /* @__PURE__ */ jsxs57("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
7711
7721
|
"Roadmap ",
|
|
7712
7722
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7713
7723
|
] }) : null,
|
|
7714
|
-
/* @__PURE__ */
|
|
7724
|
+
/* @__PURE__ */ jsxs57("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
|
|
7715
7725
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
|
|
7716
7726
|
" Re-blur"
|
|
7717
7727
|
] })
|
|
@@ -7720,7 +7730,7 @@ function ComingSoon({
|
|
|
7720
7730
|
children
|
|
7721
7731
|
] });
|
|
7722
7732
|
}
|
|
7723
|
-
return /* @__PURE__ */
|
|
7733
|
+
return /* @__PURE__ */ jsxs57("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
|
|
7724
7734
|
/* @__PURE__ */ jsx61("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
7725
7735
|
/* @__PURE__ */ jsx61("div", { className: "fd-soon-veil" }),
|
|
7726
7736
|
/* @__PURE__ */ jsx61("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx61(
|
|
@@ -7739,10 +7749,10 @@ function ComingSoon({
|
|
|
7739
7749
|
] });
|
|
7740
7750
|
}
|
|
7741
7751
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
7742
|
-
const [open, setOpen] =
|
|
7752
|
+
const [open, setOpen] = React36.useState(false);
|
|
7743
7753
|
const [anchor, pos] = useHoverCard(open);
|
|
7744
7754
|
const zIndex = useOverlayLayer(SOON_HOVERCARD_BASE);
|
|
7745
|
-
const close =
|
|
7755
|
+
const close = React36.useRef(null);
|
|
7746
7756
|
const show = () => {
|
|
7747
7757
|
if (close.current) {
|
|
7748
7758
|
clearTimeout(close.current);
|
|
@@ -7758,10 +7768,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7758
7768
|
setOpen(false);
|
|
7759
7769
|
}, 140);
|
|
7760
7770
|
};
|
|
7761
|
-
|
|
7771
|
+
React36.useEffect(() => () => {
|
|
7762
7772
|
if (close.current) clearTimeout(close.current);
|
|
7763
7773
|
}, []);
|
|
7764
|
-
return /* @__PURE__ */
|
|
7774
|
+
return /* @__PURE__ */ jsxs57(
|
|
7765
7775
|
"span",
|
|
7766
7776
|
{
|
|
7767
7777
|
ref: anchor,
|
|
@@ -7826,10 +7836,10 @@ function formatEta(iso2) {
|
|
|
7826
7836
|
var FormatEta = formatEta;
|
|
7827
7837
|
|
|
7828
7838
|
// src/components/platform/Gate.tsx
|
|
7829
|
-
import { jsx as jsx62, jsxs as
|
|
7839
|
+
import { jsx as jsx62, jsxs as jsxs58 } from "react/jsx-runtime";
|
|
7830
7840
|
function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
|
|
7831
7841
|
const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
|
|
7832
|
-
return /* @__PURE__ */
|
|
7842
|
+
return /* @__PURE__ */ jsxs58(
|
|
7833
7843
|
"div",
|
|
7834
7844
|
{
|
|
7835
7845
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -7845,12 +7855,12 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
7845
7855
|
},
|
|
7846
7856
|
...rest,
|
|
7847
7857
|
children: [
|
|
7848
|
-
/* @__PURE__ */
|
|
7858
|
+
/* @__PURE__ */ jsxs58("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
7849
7859
|
/* @__PURE__ */ jsx62("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
7850
7860
|
/* @__PURE__ */ jsx62("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
|
|
7851
7861
|
] }),
|
|
7852
7862
|
/* @__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__ */
|
|
7863
|
+
need.length ? /* @__PURE__ */ jsxs58("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
|
|
7854
7864
|
/* @__PURE__ */ jsx62("span", { className: "fd-overline fd-muted", children: "Requires" }),
|
|
7855
7865
|
need.map((p) => /* @__PURE__ */ jsx62("code", { className: "fd-mono", style: {
|
|
7856
7866
|
fontSize: 11.5,
|
|
@@ -7927,15 +7937,15 @@ function PermissionHint({ perm, children }) {
|
|
|
7927
7937
|
}
|
|
7928
7938
|
|
|
7929
7939
|
// src/components/platform/ModeSwitch.tsx
|
|
7930
|
-
import * as
|
|
7931
|
-
import { Fragment as Fragment17, jsx as jsx63, jsxs as
|
|
7940
|
+
import * as React37 from "react";
|
|
7941
|
+
import { Fragment as Fragment17, jsx as jsx63, jsxs as jsxs59 } from "react/jsx-runtime";
|
|
7932
7942
|
var MODE_SWITCH_BASE = 140;
|
|
7933
7943
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
7934
7944
|
const mode2 = useRuntimeMode();
|
|
7935
|
-
const [open, setOpen] =
|
|
7945
|
+
const [open, setOpen] = React37.useState(false);
|
|
7936
7946
|
const zIndex = useOverlayLayer(MODE_SWITCH_BASE);
|
|
7937
|
-
const ref =
|
|
7938
|
-
|
|
7947
|
+
const ref = React37.useRef(null);
|
|
7948
|
+
React37.useEffect(() => {
|
|
7939
7949
|
if (!open) return;
|
|
7940
7950
|
const away = (e) => {
|
|
7941
7951
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -7957,8 +7967,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7957
7967
|
RuntimeKit.setMode(next);
|
|
7958
7968
|
setOpen(false);
|
|
7959
7969
|
};
|
|
7960
|
-
return /* @__PURE__ */
|
|
7961
|
-
/* @__PURE__ */
|
|
7970
|
+
return /* @__PURE__ */ jsxs59("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
|
|
7971
|
+
/* @__PURE__ */ jsxs59(
|
|
7962
7972
|
"button",
|
|
7963
7973
|
{
|
|
7964
7974
|
type: "button",
|
|
@@ -7973,13 +7983,13 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7973
7983
|
]
|
|
7974
7984
|
}
|
|
7975
7985
|
),
|
|
7976
|
-
open ? /* @__PURE__ */ jsx63(LayerProvider, { zIndex, children: /* @__PURE__ */
|
|
7977
|
-
/* @__PURE__ */
|
|
7978
|
-
/* @__PURE__ */
|
|
7986
|
+
open ? /* @__PURE__ */ jsx63(LayerProvider, { zIndex, children: /* @__PURE__ */ jsxs59("span", { className: "fd-view-enter fd-mode-pop", style: { zIndex }, children: [
|
|
7987
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
7988
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
|
|
7979
7989
|
/* @__PURE__ */ jsx63("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
|
|
7980
7990
|
test ? "Test mode" : "Live mode"
|
|
7981
7991
|
] }),
|
|
7982
|
-
test ? /* @__PURE__ */
|
|
7992
|
+
test ? /* @__PURE__ */ jsxs59("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
7983
7993
|
requestCount,
|
|
7984
7994
|
" simulated request",
|
|
7985
7995
|
requestCount === 1 ? "" : "s"
|
|
@@ -7987,10 +7997,10 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7987
7997
|
/* @__PURE__ */ jsx63("span", { style: { flex: 1 } }),
|
|
7988
7998
|
test && onClearLog ? /* @__PURE__ */ jsx63("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
|
|
7989
7999
|
] }),
|
|
7990
|
-
/* @__PURE__ */
|
|
8000
|
+
/* @__PURE__ */ jsxs59("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
7991
8001
|
/* @__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__ */
|
|
8002
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
|
|
8003
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
7994
8004
|
s.endpointsWired,
|
|
7995
8005
|
" endpoint",
|
|
7996
8006
|
s.endpointsWired === 1 ? "" : "s",
|
|
@@ -8000,9 +8010,9 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
8000
8010
|
s.total,
|
|
8001
8011
|
" features complete"
|
|
8002
8012
|
] }),
|
|
8003
|
-
onOpenSpec ? /* @__PURE__ */
|
|
8013
|
+
onOpenSpec ? /* @__PURE__ */ jsxs59(Fragment17, { children: [
|
|
8004
8014
|
/* @__PURE__ */ jsx63("span", { style: { flex: 1 } }),
|
|
8005
|
-
/* @__PURE__ */
|
|
8015
|
+
/* @__PURE__ */ jsxs59("button", { type: "button", className: "fd-soon-link", onClick: () => {
|
|
8006
8016
|
setOpen(false);
|
|
8007
8017
|
onOpenSpec();
|
|
8008
8018
|
}, children: [
|
|
@@ -8012,18 +8022,18 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
8012
8022
|
] }) : null
|
|
8013
8023
|
] })
|
|
8014
8024
|
] }),
|
|
8015
|
-
/* @__PURE__ */
|
|
8016
|
-
/* @__PURE__ */
|
|
8025
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-mode-choice", children: [
|
|
8026
|
+
/* @__PURE__ */ jsxs59("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
|
|
8017
8027
|
/* @__PURE__ */ jsx63("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
8018
|
-
/* @__PURE__ */
|
|
8028
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-mode-opt-text", children: [
|
|
8019
8029
|
/* @__PURE__ */ jsx63("span", { className: "fd-mode-opt-title", children: "Live mode" }),
|
|
8020
8030
|
/* @__PURE__ */ jsx63("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
|
|
8021
8031
|
] }),
|
|
8022
8032
|
!test ? /* @__PURE__ */ jsx63("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
8023
8033
|
] }),
|
|
8024
|
-
/* @__PURE__ */
|
|
8034
|
+
/* @__PURE__ */ jsxs59("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
|
|
8025
8035
|
/* @__PURE__ */ jsx63("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
8026
|
-
/* @__PURE__ */
|
|
8036
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-mode-opt-text", children: [
|
|
8027
8037
|
/* @__PURE__ */ jsx63("span", { className: "fd-mode-opt-title", children: "Test mode" }),
|
|
8028
8038
|
/* @__PURE__ */ jsx63("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
|
|
8029
8039
|
] }),
|
|
@@ -8037,13 +8047,13 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
8037
8047
|
function TestModeBar({ onExit }) {
|
|
8038
8048
|
const mode2 = useRuntimeMode();
|
|
8039
8049
|
if (mode2 !== "test") return null;
|
|
8040
|
-
return /* @__PURE__ */
|
|
8041
|
-
/* @__PURE__ */
|
|
8050
|
+
return /* @__PURE__ */ jsxs59("div", { className: "fd-testbar", role: "status", children: [
|
|
8051
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-badge fd-badge-warning", children: [
|
|
8042
8052
|
/* @__PURE__ */ jsx63("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
8043
8053
|
"Test mode"
|
|
8044
8054
|
] }),
|
|
8045
8055
|
/* @__PURE__ */ jsx63("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
|
|
8046
|
-
/* @__PURE__ */
|
|
8056
|
+
/* @__PURE__ */ jsxs59("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
|
|
8047
8057
|
/* @__PURE__ */ jsx63("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
8048
8058
|
" Back to live mode"
|
|
8049
8059
|
] })
|
|
@@ -8051,7 +8061,7 @@ function TestModeBar({ onExit }) {
|
|
|
8051
8061
|
}
|
|
8052
8062
|
|
|
8053
8063
|
// src/components/planner/ChannelMeta.tsx
|
|
8054
|
-
import { jsx as jsx64, jsxs as
|
|
8064
|
+
import { jsx as jsx64, jsxs as jsxs60 } from "react/jsx-runtime";
|
|
8055
8065
|
var CHANNEL_WEIGHTS = {
|
|
8056
8066
|
"OOH": 50,
|
|
8057
8067
|
"DOOH": 50,
|
|
@@ -8106,7 +8116,7 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
8106
8116
|
if (dot) {
|
|
8107
8117
|
return /* @__PURE__ */ jsx64("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
|
|
8108
8118
|
}
|
|
8109
|
-
return /* @__PURE__ */
|
|
8119
|
+
return /* @__PURE__ */ jsxs60(
|
|
8110
8120
|
"span",
|
|
8111
8121
|
{
|
|
8112
8122
|
className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
|
|
@@ -8123,7 +8133,7 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
8123
8133
|
}
|
|
8124
8134
|
|
|
8125
8135
|
// src/components/planner/SaturationDistribution.tsx
|
|
8126
|
-
import { jsx as jsx65, jsxs as
|
|
8136
|
+
import { jsx as jsx65, jsxs as jsxs61 } from "react/jsx-runtime";
|
|
8127
8137
|
var BANDS2 = [
|
|
8128
8138
|
{ key: "weak", label: "Weak", n: 1, range: "< 50" },
|
|
8129
8139
|
{ key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
|
|
@@ -8134,11 +8144,11 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8134
8144
|
const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
|
|
8135
8145
|
const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
|
|
8136
8146
|
const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
|
|
8137
|
-
return /* @__PURE__ */
|
|
8147
|
+
return /* @__PURE__ */ jsxs61("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
8138
8148
|
/* @__PURE__ */ jsx65("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
|
|
8139
8149
|
const mark = "var(--csi-" + g.n + "-mark)";
|
|
8140
8150
|
const active = selectedBand === g.key;
|
|
8141
|
-
return /* @__PURE__ */
|
|
8151
|
+
return /* @__PURE__ */ jsxs61(
|
|
8142
8152
|
"button",
|
|
8143
8153
|
{
|
|
8144
8154
|
type: "button",
|
|
@@ -8154,13 +8164,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8154
8164
|
},
|
|
8155
8165
|
c.name
|
|
8156
8166
|
)) }),
|
|
8157
|
-
/* @__PURE__ */
|
|
8167
|
+
/* @__PURE__ */ jsxs61("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
|
|
8158
8168
|
/* @__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
8169
|
/* @__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
8170
|
] }),
|
|
8161
|
-
/* @__PURE__ */
|
|
8171
|
+
/* @__PURE__ */ jsxs61("span", { className: "fd-stack", style: { gap: 1 }, children: [
|
|
8162
8172
|
/* @__PURE__ */ jsx65("span", { className: "fd-label-lg", children: g.label }),
|
|
8163
|
-
/* @__PURE__ */
|
|
8173
|
+
/* @__PURE__ */ jsxs61("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
|
|
8164
8174
|
"CRP ",
|
|
8165
8175
|
g.range
|
|
8166
8176
|
] })
|
|
@@ -8170,10 +8180,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8170
8180
|
g.key
|
|
8171
8181
|
);
|
|
8172
8182
|
}) }),
|
|
8173
|
-
floorBand ? /* @__PURE__ */
|
|
8183
|
+
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
8184
|
/* @__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__ */
|
|
8185
|
+
/* @__PURE__ */ jsxs61("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
|
|
8186
|
+
/* @__PURE__ */ jsxs61("strong", { style: { color: "var(--text)" }, children: [
|
|
8177
8187
|
"Plan floor ",
|
|
8178
8188
|
floorScore
|
|
8179
8189
|
] }),
|
|
@@ -8184,8 +8194,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8184
8194
|
}
|
|
8185
8195
|
|
|
8186
8196
|
// src/components/planner/MixGap.tsx
|
|
8187
|
-
import * as
|
|
8188
|
-
import { Fragment as Fragment18, jsx as jsx66, jsxs as
|
|
8197
|
+
import * as React38 from "react";
|
|
8198
|
+
import { Fragment as Fragment18, jsx as jsx66, jsxs as jsxs62 } from "react/jsx-runtime";
|
|
8189
8199
|
var MIX_GAP_LAYOUT = {
|
|
8190
8200
|
trackHeight: 30,
|
|
8191
8201
|
barHeight: 20,
|
|
@@ -8199,18 +8209,18 @@ function mixGapOffset(value, max) {
|
|
|
8199
8209
|
}
|
|
8200
8210
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
8201
8211
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
8202
|
-
const [hover, setHover] =
|
|
8212
|
+
const [hover, setHover] = React38.useState(null);
|
|
8203
8213
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
8204
8214
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
8205
8215
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
8206
8216
|
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__ */
|
|
8217
|
+
return /* @__PURE__ */ jsxs62("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
|
|
8218
|
+
/* @__PURE__ */ jsxs62("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
|
|
8219
|
+
[["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
8220
|
/* @__PURE__ */ jsx66("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
|
|
8211
8221
|
l
|
|
8212
8222
|
] }, l)),
|
|
8213
|
-
/* @__PURE__ */
|
|
8223
|
+
/* @__PURE__ */ jsxs62("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
8214
8224
|
/* @__PURE__ */ jsx66("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
|
|
8215
8225
|
"Target"
|
|
8216
8226
|
] })
|
|
@@ -8220,7 +8230,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
8220
8230
|
const tone = toneOf(gap);
|
|
8221
8231
|
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
8232
|
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__ */
|
|
8233
|
+
return /* @__PURE__ */ jsxs62(
|
|
8224
8234
|
"div",
|
|
8225
8235
|
{
|
|
8226
8236
|
className: "fd-row",
|
|
@@ -8229,10 +8239,10 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
8229
8239
|
onMouseLeave: () => setHover(null),
|
|
8230
8240
|
children: [
|
|
8231
8241
|
/* @__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__ */
|
|
8242
|
+
/* @__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
8243
|
/* @__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
8244
|
/* @__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__ */
|
|
8245
|
+
/* @__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
8246
|
r.realized,
|
|
8237
8247
|
"%"
|
|
8238
8248
|
] }),
|
|
@@ -8247,7 +8257,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
8247
8257
|
}
|
|
8248
8258
|
|
|
8249
8259
|
// src/components/planner/ChannelContribution.tsx
|
|
8250
|
-
import { jsx as jsx67, jsxs as
|
|
8260
|
+
import { jsx as jsx67, jsxs as jsxs63 } from "react/jsx-runtime";
|
|
8251
8261
|
var money = (n) => "$" + Math.round(n).toLocaleString();
|
|
8252
8262
|
function ChannelContribution({
|
|
8253
8263
|
channels = [],
|
|
@@ -8263,8 +8273,8 @@ function ChannelContribution({
|
|
|
8263
8273
|
const grand = total !== void 0 ? total : base + bonus;
|
|
8264
8274
|
const pct = (v) => grand ? v / grand * 100 : 0;
|
|
8265
8275
|
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__ */
|
|
8276
|
+
return /* @__PURE__ */ jsxs63("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
8277
|
+
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
8278
|
channels.map((c) => /* @__PURE__ */ jsx67(
|
|
8269
8279
|
"span",
|
|
8270
8280
|
{
|
|
@@ -8283,16 +8293,16 @@ function ChannelContribution({
|
|
|
8283
8293
|
}
|
|
8284
8294
|
) : null
|
|
8285
8295
|
] }),
|
|
8286
|
-
showTable ? /* @__PURE__ */
|
|
8287
|
-
/* @__PURE__ */ jsx67("thead", { children: /* @__PURE__ */
|
|
8296
|
+
showTable ? /* @__PURE__ */ jsxs63("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
|
|
8297
|
+
/* @__PURE__ */ jsx67("thead", { children: /* @__PURE__ */ jsxs63("tr", { children: [
|
|
8288
8298
|
/* @__PURE__ */ jsx67("th", { style: { width: "34%" }, children: "Channel" }),
|
|
8289
8299
|
/* @__PURE__ */ jsx67("th", { style: { width: "16%" }, children: "Weight" }),
|
|
8290
8300
|
/* @__PURE__ */ jsx67("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
|
|
8291
8301
|
/* @__PURE__ */ jsx67("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
|
|
8292
8302
|
/* @__PURE__ */ jsx67("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
|
|
8293
8303
|
] }) }),
|
|
8294
|
-
/* @__PURE__ */
|
|
8295
|
-
channels.map((c) => /* @__PURE__ */
|
|
8304
|
+
/* @__PURE__ */ jsxs63("tbody", { children: [
|
|
8305
|
+
channels.map((c) => /* @__PURE__ */ jsxs63("tr", { children: [
|
|
8296
8306
|
/* @__PURE__ */ jsx67("td", { children: /* @__PURE__ */ jsx67(ChannelTag, { channel: c.name, size: "sm" }) }),
|
|
8297
8307
|
/* @__PURE__ */ jsx67("td", { children: /* @__PURE__ */ jsx67(
|
|
8298
8308
|
"span",
|
|
@@ -8305,17 +8315,17 @@ function ChannelContribution({
|
|
|
8305
8315
|
) }),
|
|
8306
8316
|
/* @__PURE__ */ jsx67("td", { className: "is-num", children: c.spend }),
|
|
8307
8317
|
/* @__PURE__ */ jsx67("td", { className: "is-num", children: c.crp.toFixed(1) }),
|
|
8308
|
-
/* @__PURE__ */
|
|
8318
|
+
/* @__PURE__ */ jsxs63("td", { className: "is-num", children: [
|
|
8309
8319
|
pct(c.crp).toFixed(0),
|
|
8310
8320
|
"%"
|
|
8311
8321
|
] })
|
|
8312
8322
|
] }, c.name)),
|
|
8313
|
-
bonus > 0 ? /* @__PURE__ */
|
|
8314
|
-
/* @__PURE__ */ jsx67("td", { children: /* @__PURE__ */
|
|
8323
|
+
bonus > 0 ? /* @__PURE__ */ jsxs63("tr", { children: [
|
|
8324
|
+
/* @__PURE__ */ jsx67("td", { children: /* @__PURE__ */ jsxs63("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
|
|
8315
8325
|
/* @__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
8326
|
"Surround-sound bonus"
|
|
8317
8327
|
] }) }),
|
|
8318
|
-
/* @__PURE__ */ jsx67("td", { children: /* @__PURE__ */
|
|
8328
|
+
/* @__PURE__ */ jsx67("td", { children: /* @__PURE__ */ jsxs63("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
|
|
8319
8329
|
"+",
|
|
8320
8330
|
bonusPct,
|
|
8321
8331
|
"% of +",
|
|
@@ -8324,12 +8334,12 @@ function ChannelContribution({
|
|
|
8324
8334
|
] }) }),
|
|
8325
8335
|
/* @__PURE__ */ jsx67("td", { className: "is-num fd-muted", children: "\u2014" }),
|
|
8326
8336
|
/* @__PURE__ */ jsx67("td", { className: "is-num", children: bonus.toFixed(1) }),
|
|
8327
|
-
/* @__PURE__ */
|
|
8337
|
+
/* @__PURE__ */ jsxs63("td", { className: "is-num", children: [
|
|
8328
8338
|
pct(bonus).toFixed(0),
|
|
8329
8339
|
"%"
|
|
8330
8340
|
] })
|
|
8331
8341
|
] }) : null,
|
|
8332
|
-
/* @__PURE__ */
|
|
8342
|
+
/* @__PURE__ */ jsxs63("tr", { style: { background: "var(--surface-2)" }, children: [
|
|
8333
8343
|
/* @__PURE__ */ jsx67("td", { style: { fontWeight: 700 }, children: "Campus total" }),
|
|
8334
8344
|
/* @__PURE__ */ jsx67("td", {}),
|
|
8335
8345
|
/* @__PURE__ */ jsx67("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
|
|
@@ -8342,8 +8352,8 @@ function ChannelContribution({
|
|
|
8342
8352
|
}
|
|
8343
8353
|
|
|
8344
8354
|
// src/components/planner/BudgetReallocator.tsx
|
|
8345
|
-
import * as
|
|
8346
|
-
import { Fragment as Fragment19, jsx as jsx68, jsxs as
|
|
8355
|
+
import * as React39 from "react";
|
|
8356
|
+
import { Fragment as Fragment19, jsx as jsx68, jsxs as jsxs64 } from "react/jsx-runtime";
|
|
8347
8357
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
8348
8358
|
function BudgetReallocator({
|
|
8349
8359
|
campus,
|
|
@@ -8358,8 +8368,8 @@ function BudgetReallocator({
|
|
|
8358
8368
|
onCancel,
|
|
8359
8369
|
className = ""
|
|
8360
8370
|
}) {
|
|
8361
|
-
const [draft, setDraft] =
|
|
8362
|
-
|
|
8371
|
+
const [draft, setDraft] = React39.useState(spend);
|
|
8372
|
+
React39.useEffect(() => setDraft(spend), [spend]);
|
|
8363
8373
|
const dirty = draft !== spend;
|
|
8364
8374
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
8365
8375
|
const nextBand = bandFor(nextCrp);
|
|
@@ -8374,21 +8384,21 @@ function BudgetReallocator({
|
|
|
8374
8384
|
setDraft(spend);
|
|
8375
8385
|
if (onCancel) onCancel();
|
|
8376
8386
|
};
|
|
8377
|
-
return /* @__PURE__ */
|
|
8387
|
+
return /* @__PURE__ */ jsxs64(
|
|
8378
8388
|
"div",
|
|
8379
8389
|
{
|
|
8380
8390
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
8381
8391
|
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
8392
|
children: [
|
|
8383
|
-
/* @__PURE__ */
|
|
8393
|
+
/* @__PURE__ */ jsxs64("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
8384
8394
|
/* @__PURE__ */ jsx68("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
|
|
8385
8395
|
/* @__PURE__ */ jsx68(CsiBadge, { band: nowBand, crp, size: "medium" }),
|
|
8386
|
-
dirty ? /* @__PURE__ */
|
|
8396
|
+
dirty ? /* @__PURE__ */ jsxs64(Fragment19, { children: [
|
|
8387
8397
|
/* @__PURE__ */ jsx68("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
|
|
8388
8398
|
/* @__PURE__ */ jsx68(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
|
|
8389
8399
|
] }) : null
|
|
8390
8400
|
] }),
|
|
8391
|
-
/* @__PURE__ */
|
|
8401
|
+
/* @__PURE__ */ jsxs64("div", { className: "fd-slider", children: [
|
|
8392
8402
|
/* @__PURE__ */ jsx68("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
8393
8403
|
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
8404
|
/* @__PURE__ */ jsx68(
|
|
@@ -8407,8 +8417,8 @@ function BudgetReallocator({
|
|
|
8407
8417
|
}
|
|
8408
8418
|
)
|
|
8409
8419
|
] }),
|
|
8410
|
-
/* @__PURE__ */
|
|
8411
|
-
/* @__PURE__ */
|
|
8420
|
+
/* @__PURE__ */ jsxs64("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
8421
|
+
/* @__PURE__ */ jsxs64("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
|
|
8412
8422
|
/* @__PURE__ */ jsx68("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
|
|
8413
8423
|
/* @__PURE__ */ jsx68("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
|
|
8414
8424
|
] }),
|
|
@@ -8432,7 +8442,7 @@ function BudgetReallocator({
|
|
|
8432
8442
|
}
|
|
8433
8443
|
|
|
8434
8444
|
// src/components/planner/SurroundSound.tsx
|
|
8435
|
-
import { jsx as jsx69, jsxs as
|
|
8445
|
+
import { jsx as jsx69, jsxs as jsxs65 } from "react/jsx-runtime";
|
|
8436
8446
|
var CATEGORIES = [
|
|
8437
8447
|
{ key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
|
|
8438
8448
|
{ key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
|
|
@@ -8444,10 +8454,10 @@ var CATEGORIES = [
|
|
|
8444
8454
|
function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
|
|
8445
8455
|
const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
|
|
8446
8456
|
const single = present.length <= 2;
|
|
8447
|
-
return /* @__PURE__ */
|
|
8457
|
+
return /* @__PURE__ */ jsxs65("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
|
|
8448
8458
|
/* @__PURE__ */ jsx69("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
|
|
8449
8459
|
const on = present.includes(c.key);
|
|
8450
|
-
return /* @__PURE__ */
|
|
8460
|
+
return /* @__PURE__ */ jsxs65(
|
|
8451
8461
|
"span",
|
|
8452
8462
|
{
|
|
8453
8463
|
title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
|
|
@@ -8460,10 +8470,10 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
8460
8470
|
c.key
|
|
8461
8471
|
);
|
|
8462
8472
|
}) }),
|
|
8463
|
-
/* @__PURE__ */
|
|
8464
|
-
/* @__PURE__ */
|
|
8473
|
+
/* @__PURE__ */ jsxs65("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
8474
|
+
/* @__PURE__ */ jsxs65("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
8465
8475
|
/* @__PURE__ */ jsx69("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
|
|
8466
|
-
/* @__PURE__ */
|
|
8476
|
+
/* @__PURE__ */ jsxs65("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
|
|
8467
8477
|
"+",
|
|
8468
8478
|
bonusPct,
|
|
8469
8479
|
"% of +",
|
|
@@ -8472,7 +8482,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
8472
8482
|
] })
|
|
8473
8483
|
] }),
|
|
8474
8484
|
/* @__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__ */
|
|
8485
|
+
/* @__PURE__ */ jsxs65("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
|
|
8476
8486
|
present.length,
|
|
8477
8487
|
" of 6 channel categories present.",
|
|
8478
8488
|
" ",
|
|
@@ -8484,7 +8494,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
8484
8494
|
}
|
|
8485
8495
|
|
|
8486
8496
|
// src/components/planner/Importance.tsx
|
|
8487
|
-
import { jsx as jsx70, jsxs as
|
|
8497
|
+
import { jsx as jsx70, jsxs as jsxs66 } from "react/jsx-runtime";
|
|
8488
8498
|
var IMPORTANCE_LEVELS = [
|
|
8489
8499
|
{ id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
|
|
8490
8500
|
{ id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
|
|
@@ -8514,7 +8524,7 @@ function importanceTokens(id) {
|
|
|
8514
8524
|
function ImportanceTag({ level, showLabel = true, size = "sm", className = "" }) {
|
|
8515
8525
|
const lvl = importanceLevel(level);
|
|
8516
8526
|
const t = importanceTokens(level);
|
|
8517
|
-
return /* @__PURE__ */
|
|
8527
|
+
return /* @__PURE__ */ jsxs66(
|
|
8518
8528
|
"span",
|
|
8519
8529
|
{
|
|
8520
8530
|
className: ["fd-imp-tag", size === "md" ? "is-md" : "", className].filter(Boolean).join(" "),
|
|
@@ -8529,8 +8539,8 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "" })
|
|
|
8529
8539
|
}
|
|
8530
8540
|
|
|
8531
8541
|
// src/components/planner/PreferenceMeter.tsx
|
|
8532
|
-
import * as
|
|
8533
|
-
import { jsx as jsx71, jsxs as
|
|
8542
|
+
import * as React40 from "react";
|
|
8543
|
+
import { jsx as jsx71, jsxs as jsxs67 } from "react/jsx-runtime";
|
|
8534
8544
|
function preferenceScore(criteria) {
|
|
8535
8545
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
8536
8546
|
const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
|
|
@@ -8559,7 +8569,7 @@ function PreferenceMeter({
|
|
|
8559
8569
|
className = ""
|
|
8560
8570
|
}) {
|
|
8561
8571
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
8562
|
-
const segments =
|
|
8572
|
+
const segments = React40.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
8563
8573
|
return /* @__PURE__ */ jsx71(
|
|
8564
8574
|
ScoreMeter,
|
|
8565
8575
|
{
|
|
@@ -8572,20 +8582,20 @@ function PreferenceMeter({
|
|
|
8572
8582
|
placement,
|
|
8573
8583
|
className,
|
|
8574
8584
|
breakdownLabel: breakdownTitle,
|
|
8575
|
-
breakdown: /* @__PURE__ */
|
|
8576
|
-
/* @__PURE__ */
|
|
8585
|
+
breakdown: /* @__PURE__ */ jsxs67("div", { className: "fd-prefbreak", children: [
|
|
8586
|
+
/* @__PURE__ */ jsxs67("div", { className: "fd-prefbreak-head", children: [
|
|
8577
8587
|
/* @__PURE__ */ jsx71("span", { className: "fd-label-lg", children: breakdownTitle }),
|
|
8578
8588
|
/* @__PURE__ */ jsx71("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
|
|
8579
8589
|
] }),
|
|
8580
8590
|
/* @__PURE__ */ jsx71("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
|
|
8581
8591
|
const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
|
|
8582
|
-
return /* @__PURE__ */
|
|
8592
|
+
return /* @__PURE__ */ jsxs67("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
|
|
8583
8593
|
/* @__PURE__ */ jsx71(ImportanceTag, { level: c.importance }),
|
|
8584
|
-
/* @__PURE__ */
|
|
8594
|
+
/* @__PURE__ */ jsxs67("span", { className: "fd-prefbreak-text", children: [
|
|
8585
8595
|
/* @__PURE__ */ jsx71("span", { className: "fd-prefbreak-label", children: c.label }),
|
|
8586
8596
|
c.note ? /* @__PURE__ */ jsx71("span", { className: "fd-prefbreak-note", children: c.note }) : null
|
|
8587
8597
|
] }),
|
|
8588
|
-
/* @__PURE__ */
|
|
8598
|
+
/* @__PURE__ */ jsxs67("span", { className: "fd-prefbreak-val fd-tabular", children: [
|
|
8589
8599
|
Math.round(Number(c.earned) || 0),
|
|
8590
8600
|
/* @__PURE__ */ jsx71("span", { className: "fd-prefbreak-sep", children: "/" }),
|
|
8591
8601
|
Math.round(c.weight)
|
|
@@ -8598,10 +8608,10 @@ function PreferenceMeter({
|
|
|
8598
8608
|
}
|
|
8599
8609
|
|
|
8600
8610
|
// src/components/chat/AgentChatPanel.tsx
|
|
8601
|
-
import * as
|
|
8611
|
+
import * as React46 from "react";
|
|
8602
8612
|
|
|
8603
8613
|
// src/components/chat/chatEngine.ts
|
|
8604
|
-
import * as
|
|
8614
|
+
import * as React41 from "react";
|
|
8605
8615
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
8606
8616
|
var JOB_PENDING = ["queued", "running"];
|
|
8607
8617
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -8655,22 +8665,22 @@ function useChatEngine(opts) {
|
|
|
8655
8665
|
onClear,
|
|
8656
8666
|
onFeedback
|
|
8657
8667
|
} = 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
|
-
|
|
8668
|
+
const [status, setStatus] = React41.useState("idle");
|
|
8669
|
+
const [threadId, setThreadId] = React41.useState(null);
|
|
8670
|
+
const [messages, setMessages] = React41.useState([]);
|
|
8671
|
+
const [queue, setQueue] = React41.useState([]);
|
|
8672
|
+
const [fatal, setFatal] = React41.useState(null);
|
|
8673
|
+
const [busy, setBusy] = React41.useState(false);
|
|
8674
|
+
const [turnStartedAt, setTurnStartedAt] = React41.useState(null);
|
|
8675
|
+
const listRef = React41.useRef([]);
|
|
8676
|
+
const queueRef = React41.useRef([]);
|
|
8677
|
+
const busyRef = React41.useRef(false);
|
|
8678
|
+
const stoppedRef = React41.useRef(false);
|
|
8679
|
+
const abortRef = React41.useRef(null);
|
|
8680
|
+
const serverCount = React41.useRef(0);
|
|
8681
|
+
const threadRef = React41.useRef(null);
|
|
8682
|
+
const mounted = React41.useRef(true);
|
|
8683
|
+
React41.useEffect(() => {
|
|
8674
8684
|
mounted.current = true;
|
|
8675
8685
|
return () => {
|
|
8676
8686
|
mounted.current = false;
|
|
@@ -8692,14 +8702,14 @@ function useChatEngine(opts) {
|
|
|
8692
8702
|
}
|
|
8693
8703
|
return false;
|
|
8694
8704
|
};
|
|
8695
|
-
const loadThread =
|
|
8705
|
+
const loadThread = React41.useCallback(async (id) => {
|
|
8696
8706
|
const data = await apiAdapter.getThread(id);
|
|
8697
8707
|
const list = [...data && data.messages || []];
|
|
8698
8708
|
serverCount.current = list.length;
|
|
8699
8709
|
commit(list);
|
|
8700
8710
|
return list;
|
|
8701
8711
|
}, [apiAdapter]);
|
|
8702
|
-
|
|
8712
|
+
React41.useEffect(() => {
|
|
8703
8713
|
if (!apiAdapter) {
|
|
8704
8714
|
setStatus("idle");
|
|
8705
8715
|
setFatal(null);
|
|
@@ -8912,7 +8922,7 @@ function useChatEngine(opts) {
|
|
|
8912
8922
|
await dispatchTurn(turn);
|
|
8913
8923
|
}
|
|
8914
8924
|
}
|
|
8915
|
-
const send =
|
|
8925
|
+
const send = React41.useCallback((text, attachments) => {
|
|
8916
8926
|
const body = (text || "").trim();
|
|
8917
8927
|
if (!body && !(attachments && attachments.length)) return;
|
|
8918
8928
|
if (status === "disconnected") return;
|
|
@@ -8922,7 +8932,7 @@ function useChatEngine(opts) {
|
|
|
8922
8932
|
stoppedRef.current = false;
|
|
8923
8933
|
drain();
|
|
8924
8934
|
}, [status]);
|
|
8925
|
-
const stop =
|
|
8935
|
+
const stop = React41.useCallback(() => {
|
|
8926
8936
|
stoppedRef.current = true;
|
|
8927
8937
|
const ac = abortRef.current;
|
|
8928
8938
|
if (ac) {
|
|
@@ -8941,11 +8951,11 @@ function useChatEngine(opts) {
|
|
|
8941
8951
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
8942
8952
|
}
|
|
8943
8953
|
}, [apiAdapter]);
|
|
8944
|
-
const removeQueued =
|
|
8954
|
+
const removeQueued = React41.useCallback((id) => {
|
|
8945
8955
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
8946
8956
|
setQueue(queueRef.current.slice());
|
|
8947
8957
|
}, []);
|
|
8948
|
-
const retry =
|
|
8958
|
+
const retry = React41.useCallback(() => {
|
|
8949
8959
|
const list = listRef.current;
|
|
8950
8960
|
let at = -1;
|
|
8951
8961
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -8961,19 +8971,19 @@ function useChatEngine(opts) {
|
|
|
8961
8971
|
setQueue(queueRef.current.slice());
|
|
8962
8972
|
drain();
|
|
8963
8973
|
}, []);
|
|
8964
|
-
const clear =
|
|
8974
|
+
const clear = React41.useCallback(() => {
|
|
8965
8975
|
commit([]);
|
|
8966
8976
|
serverCount.current = 0;
|
|
8967
8977
|
queueRef.current = [];
|
|
8968
8978
|
setQueue([]);
|
|
8969
8979
|
onClear && onClear();
|
|
8970
8980
|
}, [onClear]);
|
|
8971
|
-
const setFeedback =
|
|
8981
|
+
const setFeedback = React41.useCallback((id, value) => {
|
|
8972
8982
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
8973
8983
|
const msg = listRef.current.find((m) => m.id === id);
|
|
8974
8984
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
8975
8985
|
}, [onFeedback]);
|
|
8976
|
-
const reload =
|
|
8986
|
+
const reload = React41.useCallback(async () => {
|
|
8977
8987
|
if (!threadRef.current) return;
|
|
8978
8988
|
setStatus("loading");
|
|
8979
8989
|
try {
|
|
@@ -9011,11 +9021,11 @@ var ChatKit = {
|
|
|
9011
9021
|
};
|
|
9012
9022
|
|
|
9013
9023
|
// src/components/chat/ChatTranscript.tsx
|
|
9014
|
-
import * as
|
|
9024
|
+
import * as React43 from "react";
|
|
9015
9025
|
|
|
9016
9026
|
// src/components/chat/ChatTurn.tsx
|
|
9017
|
-
import * as
|
|
9018
|
-
import { jsx as jsx72, jsxs as
|
|
9027
|
+
import * as React42 from "react";
|
|
9028
|
+
import { jsx as jsx72, jsxs as jsxs68 } from "react/jsx-runtime";
|
|
9019
9029
|
function JsonView({ value }) {
|
|
9020
9030
|
let text;
|
|
9021
9031
|
try {
|
|
@@ -9030,20 +9040,20 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
|
9030
9040
|
const s = schema || {};
|
|
9031
9041
|
const invalid = packet.valid === false;
|
|
9032
9042
|
const title = s.heading || packet.type;
|
|
9033
|
-
return /* @__PURE__ */
|
|
9034
|
-
/* @__PURE__ */
|
|
9043
|
+
return /* @__PURE__ */ jsxs68("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
|
|
9044
|
+
/* @__PURE__ */ jsxs68("header", { className: "fdc-packet-head", children: [
|
|
9035
9045
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
|
|
9036
9046
|
/* @__PURE__ */ jsx72("span", { className: "fdc-packet-title", children: title }),
|
|
9037
9047
|
packet.repaired ? /* @__PURE__ */ jsx72("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
|
|
9038
9048
|
invalid ? /* @__PURE__ */ jsx72("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
|
|
9039
9049
|
] }),
|
|
9040
|
-
invalid ? /* @__PURE__ */
|
|
9050
|
+
invalid ? /* @__PURE__ */ jsxs68("div", { className: "fdc-packet-alert", role: "alert", children: [
|
|
9041
9051
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
9042
9052
|
/* @__PURE__ */ jsx72("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
|
|
9043
9053
|
] }) : /* @__PURE__ */ jsx72("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx72(JsonView, { value: packet.payload }) }),
|
|
9044
|
-
!invalid && onApply ? /* @__PURE__ */
|
|
9054
|
+
!invalid && onApply ? /* @__PURE__ */ jsxs68("footer", { className: "fdc-packet-foot", children: [
|
|
9045
9055
|
packet.repaired ? /* @__PURE__ */ jsx72("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx72("span", {}),
|
|
9046
|
-
/* @__PURE__ */
|
|
9056
|
+
/* @__PURE__ */ jsxs68("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
|
|
9047
9057
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
|
|
9048
9058
|
applied ? "Applied" : s.applyLabel || "Apply"
|
|
9049
9059
|
] })
|
|
@@ -9051,13 +9061,13 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
|
9051
9061
|
] });
|
|
9052
9062
|
}
|
|
9053
9063
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
9054
|
-
const [open, setOpen] =
|
|
9064
|
+
const [open, setOpen] = React42.useState(defaultOpen);
|
|
9055
9065
|
if (!text) return null;
|
|
9056
|
-
return /* @__PURE__ */
|
|
9057
|
-
/* @__PURE__ */
|
|
9066
|
+
return /* @__PURE__ */ jsxs68("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
|
|
9067
|
+
/* @__PURE__ */ jsxs68("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
9058
9068
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-brain", "aria-hidden": "true" }),
|
|
9059
9069
|
/* @__PURE__ */ jsx72("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
|
|
9060
|
-
streaming ? /* @__PURE__ */
|
|
9070
|
+
streaming ? /* @__PURE__ */ jsxs68("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
9061
9071
|
/* @__PURE__ */ jsx72("span", {}),
|
|
9062
9072
|
/* @__PURE__ */ jsx72("span", {}),
|
|
9063
9073
|
/* @__PURE__ */ jsx72("span", {})
|
|
@@ -9068,19 +9078,19 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
|
9068
9078
|
] });
|
|
9069
9079
|
}
|
|
9070
9080
|
function Citations({ items = [], onOpen }) {
|
|
9071
|
-
const [open, setOpen] =
|
|
9081
|
+
const [open, setOpen] = React42.useState(false);
|
|
9072
9082
|
if (!items.length) return null;
|
|
9073
|
-
return /* @__PURE__ */
|
|
9074
|
-
/* @__PURE__ */
|
|
9083
|
+
return /* @__PURE__ */ jsxs68("div", { className: "fdc-cites", children: [
|
|
9084
|
+
/* @__PURE__ */ jsxs68("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
9075
9085
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
|
|
9076
|
-
/* @__PURE__ */
|
|
9086
|
+
/* @__PURE__ */ jsxs68("span", { children: [
|
|
9077
9087
|
items.length,
|
|
9078
9088
|
" source",
|
|
9079
9089
|
items.length === 1 ? "" : "s"
|
|
9080
9090
|
] }),
|
|
9081
9091
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
|
|
9082
9092
|
] }),
|
|
9083
|
-
open ? /* @__PURE__ */ jsx72("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */
|
|
9093
|
+
open ? /* @__PURE__ */ jsx72("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs68("li", { children: [
|
|
9084
9094
|
/* @__PURE__ */ jsx72("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
|
|
9085
9095
|
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
9096
|
c.detail ? /* @__PURE__ */ jsx72("span", { className: "fdc-cite-detail", children: c.detail }) : null
|
|
@@ -9094,24 +9104,24 @@ function clampText(text, max) {
|
|
|
9094
9104
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
9095
9105
|
}
|
|
9096
9106
|
function MessageBody({ message: m, ctx }) {
|
|
9097
|
-
const [expanded, setExpanded] =
|
|
9107
|
+
const [expanded, setExpanded] = React42.useState(false);
|
|
9098
9108
|
const isUser = m.role === "user";
|
|
9099
9109
|
const raw = m.text || "";
|
|
9100
9110
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
9101
9111
|
const body = clamped != null ? clamped : raw;
|
|
9102
9112
|
const showMd = ctx.markdown && !isUser;
|
|
9103
|
-
return /* @__PURE__ */
|
|
9113
|
+
return /* @__PURE__ */ jsxs68("div", { className: "fdc-body", children: [
|
|
9104
9114
|
m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx72(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
|
|
9105
9115
|
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__ */
|
|
9116
|
+
body ? /* @__PURE__ */ jsxs68("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
|
|
9107
9117
|
showMd ? /* @__PURE__ */ jsx72(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx72("div", { className: "fdc-plain", children: body }),
|
|
9108
9118
|
m.streaming ? /* @__PURE__ */ jsx72("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
|
|
9109
9119
|
] }) : null,
|
|
9110
|
-
clamped != null ? /* @__PURE__ */
|
|
9120
|
+
clamped != null ? /* @__PURE__ */ jsxs68("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
|
|
9111
9121
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
|
|
9112
9122
|
"Show more",
|
|
9113
9123
|
/* @__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__ */
|
|
9124
|
+
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs68("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
|
|
9115
9125
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
|
|
9116
9126
|
"Show less"
|
|
9117
9127
|
] }) : null,
|
|
@@ -9127,33 +9137,33 @@ function MessageBody({ message: m, ctx }) {
|
|
|
9127
9137
|
}
|
|
9128
9138
|
) : null,
|
|
9129
9139
|
m.citations && m.citations.length ? /* @__PURE__ */ jsx72(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
|
|
9130
|
-
m.working ? /* @__PURE__ */
|
|
9131
|
-
/* @__PURE__ */
|
|
9140
|
+
m.working ? /* @__PURE__ */ jsxs68("div", { className: "fdc-working", role: "status", children: [
|
|
9141
|
+
/* @__PURE__ */ jsxs68("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
9132
9142
|
/* @__PURE__ */ jsx72("span", {}),
|
|
9133
9143
|
/* @__PURE__ */ jsx72("span", {}),
|
|
9134
9144
|
/* @__PURE__ */ jsx72("span", {})
|
|
9135
9145
|
] }),
|
|
9136
|
-
/* @__PURE__ */
|
|
9146
|
+
/* @__PURE__ */ jsxs68("span", { className: "fdc-working-label", children: [
|
|
9137
9147
|
m.resumed ? "Resuming" : "Working",
|
|
9138
|
-
m.job && m.job.status ? /* @__PURE__ */
|
|
9148
|
+
m.job && m.job.status ? /* @__PURE__ */ jsxs68("span", { className: "fdc-working-job", children: [
|
|
9139
9149
|
" \xB7 ",
|
|
9140
9150
|
m.job.status
|
|
9141
9151
|
] }) : null,
|
|
9142
|
-
m.job && m.job.detail ? /* @__PURE__ */
|
|
9152
|
+
m.job && m.job.detail ? /* @__PURE__ */ jsxs68("span", { className: "fdc-working-job", children: [
|
|
9143
9153
|
" \xB7 ",
|
|
9144
9154
|
m.job.detail
|
|
9145
9155
|
] }) : null
|
|
9146
9156
|
] }),
|
|
9147
9157
|
m.jobId ? /* @__PURE__ */ jsx72("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
|
|
9148
9158
|
] }) : null,
|
|
9149
|
-
m.stopped ? /* @__PURE__ */
|
|
9159
|
+
m.stopped ? /* @__PURE__ */ jsxs68("div", { className: "fdc-stopped", children: [
|
|
9150
9160
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
9151
9161
|
"Stopped"
|
|
9152
9162
|
] }) : null,
|
|
9153
|
-
m.error ? /* @__PURE__ */
|
|
9163
|
+
m.error ? /* @__PURE__ */ jsxs68("div", { className: "fdc-error", role: "alert", children: [
|
|
9154
9164
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
9155
9165
|
/* @__PURE__ */ jsx72("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
|
|
9156
|
-
m.retryable && ctx.onRetry ? /* @__PURE__ */
|
|
9166
|
+
m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs68("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
|
|
9157
9167
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
9158
9168
|
"Retry"
|
|
9159
9169
|
] }) : null
|
|
@@ -9161,9 +9171,9 @@ function MessageBody({ message: m, ctx }) {
|
|
|
9161
9171
|
] });
|
|
9162
9172
|
}
|
|
9163
9173
|
function useCopyRun() {
|
|
9164
|
-
const [done, setDone] =
|
|
9165
|
-
const t =
|
|
9166
|
-
|
|
9174
|
+
const [done, setDone] = React42.useState(false);
|
|
9175
|
+
const t = React42.useRef(null);
|
|
9176
|
+
React42.useEffect(() => () => {
|
|
9167
9177
|
if (t.current) clearTimeout(t.current);
|
|
9168
9178
|
}, []);
|
|
9169
9179
|
return [done, (text) => {
|
|
@@ -9183,14 +9193,14 @@ function RunActions({ group, ctx }) {
|
|
|
9183
9193
|
const isAssistant = group.role === "assistant";
|
|
9184
9194
|
const fb = last.feedback;
|
|
9185
9195
|
if (!ctx.messageActions) return null;
|
|
9186
|
-
return /* @__PURE__ */
|
|
9187
|
-
/* @__PURE__ */
|
|
9196
|
+
return /* @__PURE__ */ jsxs68("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
|
|
9197
|
+
/* @__PURE__ */ jsxs68("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
|
|
9188
9198
|
/* @__PURE__ */ jsx72("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
|
|
9189
9199
|
/* @__PURE__ */ jsx72("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
|
|
9190
9200
|
] }),
|
|
9191
9201
|
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
9202
|
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__ */
|
|
9203
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs68(React42.Fragment, { children: [
|
|
9194
9204
|
/* @__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
9205
|
/* @__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
9206
|
] }) : null,
|
|
@@ -9202,14 +9212,14 @@ function ChatTurn({ group, ctx }) {
|
|
|
9202
9212
|
const name = isUser ? ctx.userName : group.author || ctx.assistantName;
|
|
9203
9213
|
const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
|
|
9204
9214
|
const stamp = group.messages[0].timestamp;
|
|
9205
|
-
return /* @__PURE__ */
|
|
9206
|
-
/* @__PURE__ */
|
|
9215
|
+
return /* @__PURE__ */ jsxs68("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
|
|
9216
|
+
/* @__PURE__ */ jsxs68("div", { className: "fdc-turn-head", children: [
|
|
9207
9217
|
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
9218
|
/* @__PURE__ */ jsx72("span", { className: "fdc-who", children: name }),
|
|
9209
9219
|
stamp ? /* @__PURE__ */ jsx72(RelativeTime, { className: "fdc-when", value: stamp }) : null,
|
|
9210
9220
|
group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx72("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
|
|
9211
9221
|
] }),
|
|
9212
|
-
/* @__PURE__ */
|
|
9222
|
+
/* @__PURE__ */ jsxs68("div", { className: "fdc-turn-body", children: [
|
|
9213
9223
|
group.messages.map((m) => /* @__PURE__ */ jsx72("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx72(MessageBody, { message: m, ctx }) }, m.id)),
|
|
9214
9224
|
/* @__PURE__ */ jsx72(RunActions, { group, ctx })
|
|
9215
9225
|
] })
|
|
@@ -9217,7 +9227,7 @@ function ChatTurn({ group, ctx }) {
|
|
|
9217
9227
|
}
|
|
9218
9228
|
|
|
9219
9229
|
// src/components/chat/ChatTranscript.tsx
|
|
9220
|
-
import { jsx as jsx73, jsxs as
|
|
9230
|
+
import { jsx as jsx73, jsxs as jsxs69 } from "react/jsx-runtime";
|
|
9221
9231
|
var GROUP_WINDOW = 6e4;
|
|
9222
9232
|
var STICK_PX = 100;
|
|
9223
9233
|
function groupMessages(list) {
|
|
@@ -9252,9 +9262,9 @@ function Suggestions({ items = [], onPick }) {
|
|
|
9252
9262
|
if (!items.length) return null;
|
|
9253
9263
|
return /* @__PURE__ */ jsx73("div", { className: "fdc-suggest", children: items.map((s, i) => {
|
|
9254
9264
|
const it = typeof s === "string" ? { label: s, text: s } : s;
|
|
9255
|
-
return /* @__PURE__ */
|
|
9265
|
+
return /* @__PURE__ */ jsxs69("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
|
|
9256
9266
|
it.icon ? /* @__PURE__ */ jsx73("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
|
|
9257
|
-
/* @__PURE__ */
|
|
9267
|
+
/* @__PURE__ */ jsxs69("span", { className: "fdc-suggest-text", children: [
|
|
9258
9268
|
/* @__PURE__ */ jsx73("span", { className: "fdc-suggest-label", children: it.label }),
|
|
9259
9269
|
it.description ? /* @__PURE__ */ jsx73("span", { className: "fdc-suggest-desc", children: it.description }) : null
|
|
9260
9270
|
] }),
|
|
@@ -9263,9 +9273,9 @@ function Suggestions({ items = [], onPick }) {
|
|
|
9263
9273
|
}) });
|
|
9264
9274
|
}
|
|
9265
9275
|
function LoadingTurns() {
|
|
9266
|
-
return /* @__PURE__ */ jsx73("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */
|
|
9276
|
+
return /* @__PURE__ */ jsx73("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs69("div", { className: "fdc-skel-turn", children: [
|
|
9267
9277
|
/* @__PURE__ */ jsx73("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
|
|
9268
|
-
/* @__PURE__ */
|
|
9278
|
+
/* @__PURE__ */ jsxs69("div", { className: "fdc-skel-lines", children: [
|
|
9269
9279
|
/* @__PURE__ */ jsx73("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
|
|
9270
9280
|
/* @__PURE__ */ jsx73("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
|
|
9271
9281
|
/* @__PURE__ */ jsx73("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
|
|
@@ -9285,10 +9295,10 @@ function ChatTranscript({
|
|
|
9285
9295
|
renderEmpty,
|
|
9286
9296
|
className = ""
|
|
9287
9297
|
}) {
|
|
9288
|
-
const scroller =
|
|
9289
|
-
const stick =
|
|
9290
|
-
const [pill, setPill] =
|
|
9291
|
-
const seen =
|
|
9298
|
+
const scroller = React43.useRef(null);
|
|
9299
|
+
const stick = React43.useRef(true);
|
|
9300
|
+
const [pill, setPill] = React43.useState(0);
|
|
9301
|
+
const seen = React43.useRef(0);
|
|
9292
9302
|
const toBottom = (smooth) => {
|
|
9293
9303
|
const el = scroller.current;
|
|
9294
9304
|
if (!el) return;
|
|
@@ -9307,7 +9317,7 @@ function ChatTranscript({
|
|
|
9307
9317
|
seen.current = messages.length;
|
|
9308
9318
|
}
|
|
9309
9319
|
};
|
|
9310
|
-
|
|
9320
|
+
React43.useLayoutEffect(() => {
|
|
9311
9321
|
const el = scroller.current;
|
|
9312
9322
|
if (!el) return;
|
|
9313
9323
|
if (stick.current) {
|
|
@@ -9315,7 +9325,7 @@ function ChatTranscript({
|
|
|
9315
9325
|
seen.current = messages.length;
|
|
9316
9326
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
9317
9327
|
}, [messages]);
|
|
9318
|
-
|
|
9328
|
+
React43.useEffect(() => {
|
|
9319
9329
|
const el = scroller.current;
|
|
9320
9330
|
const inner = el && el.firstChild;
|
|
9321
9331
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -9325,21 +9335,21 @@ function ChatTranscript({
|
|
|
9325
9335
|
ro.observe(inner);
|
|
9326
9336
|
return () => ro.disconnect();
|
|
9327
9337
|
}, []);
|
|
9328
|
-
const groups =
|
|
9338
|
+
const groups = React43.useMemo(() => groupMessages(messages), [messages]);
|
|
9329
9339
|
const empty = !messages.length && status === "ready";
|
|
9330
|
-
return /* @__PURE__ */
|
|
9331
|
-
/* @__PURE__ */
|
|
9340
|
+
return /* @__PURE__ */ jsxs69("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
9341
|
+
/* @__PURE__ */ jsxs69("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
9332
9342
|
status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx73(LoadingTurns, {}) : null,
|
|
9333
|
-
status === "disconnected" ? /* @__PURE__ */
|
|
9343
|
+
status === "disconnected" ? /* @__PURE__ */ jsxs69("div", { className: "fdc-dead", children: [
|
|
9334
9344
|
/* @__PURE__ */ jsx73("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx73("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
|
|
9335
9345
|
/* @__PURE__ */ jsx73("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
|
|
9336
9346
|
/* @__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__ */
|
|
9347
|
+
ctx.onReconnect ? /* @__PURE__ */ jsxs69("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
|
|
9338
9348
|
/* @__PURE__ */ jsx73("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
9339
9349
|
"Try again"
|
|
9340
9350
|
] }) : null
|
|
9341
9351
|
] }) : null,
|
|
9342
|
-
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */
|
|
9352
|
+
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs69("div", { className: "fdc-empty", children: [
|
|
9343
9353
|
/* @__PURE__ */ jsx73("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx73("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
|
|
9344
9354
|
/* @__PURE__ */ jsx73("h3", { className: "fdc-empty-title", children: emptyTitle }),
|
|
9345
9355
|
emptyDescription ? /* @__PURE__ */ jsx73("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
|
|
@@ -9349,13 +9359,13 @@ function ChatTranscript({
|
|
|
9349
9359
|
const prev = groups[i - 1];
|
|
9350
9360
|
const k = dayKey(g.messages[0].timestamp);
|
|
9351
9361
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
9352
|
-
return /* @__PURE__ */
|
|
9362
|
+
return /* @__PURE__ */ jsxs69(React43.Fragment, { children: [
|
|
9353
9363
|
showDay ? /* @__PURE__ */ jsx73("div", { className: "fdc-day", children: /* @__PURE__ */ jsx73("span", { children: dayLabel(k) }) }) : null,
|
|
9354
9364
|
/* @__PURE__ */ jsx73(ChatTurn, { group: g, ctx })
|
|
9355
9365
|
] }, g.key || i);
|
|
9356
9366
|
})
|
|
9357
9367
|
] }),
|
|
9358
|
-
pill ? /* @__PURE__ */
|
|
9368
|
+
pill ? /* @__PURE__ */ jsxs69("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
|
|
9359
9369
|
/* @__PURE__ */ jsx73("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
|
|
9360
9370
|
pill,
|
|
9361
9371
|
" new message",
|
|
@@ -9366,8 +9376,8 @@ function ChatTranscript({
|
|
|
9366
9376
|
var TranscriptKit = { groupMessages };
|
|
9367
9377
|
|
|
9368
9378
|
// src/components/chat/ChatComposer.tsx
|
|
9369
|
-
import * as
|
|
9370
|
-
import { jsx as jsx74, jsxs as
|
|
9379
|
+
import * as React44 from "react";
|
|
9380
|
+
import { jsx as jsx74, jsxs as jsxs70 } from "react/jsx-runtime";
|
|
9371
9381
|
function ChatComposer({
|
|
9372
9382
|
onSubmit,
|
|
9373
9383
|
onStop,
|
|
@@ -9394,17 +9404,17 @@ function ChatComposer({
|
|
|
9394
9404
|
onReject,
|
|
9395
9405
|
onOpenAttachment
|
|
9396
9406
|
}) {
|
|
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 =
|
|
9407
|
+
const [text, setText] = React44.useState(draft || "");
|
|
9408
|
+
const [trigger, setTrigger] = React44.useState(null);
|
|
9409
|
+
const [mentionItems, setMentionItems] = React44.useState([]);
|
|
9410
|
+
const [listening, setListening] = React44.useState(false);
|
|
9411
|
+
const [notice, setNotice] = React44.useState(null);
|
|
9412
|
+
const editor = React44.useRef(null);
|
|
9413
|
+
const wrap = React44.useRef(null);
|
|
9414
|
+
const stopVoice = React44.useRef(null);
|
|
9405
9415
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
9406
9416
|
} });
|
|
9407
|
-
|
|
9417
|
+
React44.useEffect(() => {
|
|
9408
9418
|
if (draft != null && draft !== text) setText(draft);
|
|
9409
9419
|
}, [draft]);
|
|
9410
9420
|
const change = (v) => {
|
|
@@ -9438,7 +9448,7 @@ function ChatComposer({
|
|
|
9438
9448
|
e.preventDefault();
|
|
9439
9449
|
staged.add(found.files);
|
|
9440
9450
|
};
|
|
9441
|
-
|
|
9451
|
+
React44.useEffect(() => {
|
|
9442
9452
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
9443
9453
|
setMentionItems([]);
|
|
9444
9454
|
return;
|
|
@@ -9456,7 +9466,7 @@ function ChatComposer({
|
|
|
9456
9466
|
const q = (trigger.query || "").toLowerCase();
|
|
9457
9467
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
9458
9468
|
}, [trigger, mentionSources]);
|
|
9459
|
-
const slashItems =
|
|
9469
|
+
const slashItems = React44.useMemo(() => {
|
|
9460
9470
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
9461
9471
|
const q = (trigger.query || "").toLowerCase();
|
|
9462
9472
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -9533,8 +9543,8 @@ function ChatComposer({
|
|
|
9533
9543
|
stopVoice.current = typeof res === "function" ? res : () => {
|
|
9534
9544
|
};
|
|
9535
9545
|
};
|
|
9536
|
-
return /* @__PURE__ */
|
|
9537
|
-
queue.length ? /* @__PURE__ */ jsx74("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */
|
|
9546
|
+
return /* @__PURE__ */ jsxs70("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
|
|
9547
|
+
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
9548
|
/* @__PURE__ */ jsx74("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
|
|
9539
9549
|
/* @__PURE__ */ jsx74("span", { className: "fdc-queue-text", children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
|
|
9540
9550
|
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 +9564,7 @@ function ChatComposer({
|
|
|
9554
9564
|
disabled: !fileUploadHandler || disabled,
|
|
9555
9565
|
label: "Drop to attach",
|
|
9556
9566
|
hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
|
|
9557
|
-
children: /* @__PURE__ */
|
|
9567
|
+
children: /* @__PURE__ */ jsxs70("div", { ref: wrap, className: "fdc-field-inner", children: [
|
|
9558
9568
|
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
9569
|
/* @__PURE__ */ jsx74(
|
|
9560
9570
|
MarkdownEditor,
|
|
@@ -9575,20 +9585,20 @@ function ChatComposer({
|
|
|
9575
9585
|
ariaLabel: "Message"
|
|
9576
9586
|
}
|
|
9577
9587
|
),
|
|
9578
|
-
/* @__PURE__ */
|
|
9588
|
+
/* @__PURE__ */ jsxs70("div", { className: "fdc-tools", children: [
|
|
9579
9589
|
fileUploadHandler ? /* @__PURE__ */ jsx74(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
|
|
9580
9590
|
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
9591
|
toolbarExtras,
|
|
9582
9592
|
/* @__PURE__ */ jsx74("span", { className: "fdc-tools-gap" }),
|
|
9583
|
-
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */
|
|
9593
|
+
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs70("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
|
|
9584
9594
|
text.length,
|
|
9585
9595
|
"/",
|
|
9586
9596
|
maxLength
|
|
9587
9597
|
] }) : null,
|
|
9588
|
-
busy ? /* @__PURE__ */
|
|
9598
|
+
busy ? /* @__PURE__ */ jsxs70("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
|
|
9589
9599
|
/* @__PURE__ */ jsx74("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
9590
9600
|
/* @__PURE__ */ jsx74("span", { children: "Stop" })
|
|
9591
|
-
] }) : /* @__PURE__ */
|
|
9601
|
+
] }) : /* @__PURE__ */ jsxs70("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
|
|
9592
9602
|
/* @__PURE__ */ jsx74("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
|
|
9593
9603
|
/* @__PURE__ */ jsx74("span", { className: "fdc-send-label", children: "Send" })
|
|
9594
9604
|
] })
|
|
@@ -9596,7 +9606,7 @@ function ChatComposer({
|
|
|
9596
9606
|
] })
|
|
9597
9607
|
}
|
|
9598
9608
|
),
|
|
9599
|
-
notice ? /* @__PURE__ */
|
|
9609
|
+
notice ? /* @__PURE__ */ jsxs70("div", { className: "fdc-notice", role: "status", children: [
|
|
9600
9610
|
/* @__PURE__ */ jsx74("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
9601
9611
|
notice
|
|
9602
9612
|
] }) : null,
|
|
@@ -9630,12 +9640,12 @@ function ChatComposer({
|
|
|
9630
9640
|
}
|
|
9631
9641
|
|
|
9632
9642
|
// src/components/chat/ChatSessionBar.tsx
|
|
9633
|
-
import * as
|
|
9634
|
-
import { jsx as jsx75, jsxs as
|
|
9643
|
+
import * as React45 from "react";
|
|
9644
|
+
import { jsx as jsx75, jsxs as jsxs71 } from "react/jsx-runtime";
|
|
9635
9645
|
var compact2 = meterFormats.compact;
|
|
9636
9646
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
9637
|
-
const [open, setOpen] =
|
|
9638
|
-
const anchor =
|
|
9647
|
+
const [open, setOpen] = React45.useState(false);
|
|
9648
|
+
const anchor = React45.useRef(null);
|
|
9639
9649
|
const stats = sessionStats || null;
|
|
9640
9650
|
const cu = contextUsage || null;
|
|
9641
9651
|
const limits = usageLimits || null;
|
|
@@ -9650,9 +9660,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9650
9660
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
9651
9661
|
if (cu) bits.push(pct + "% context");
|
|
9652
9662
|
const expandable = !!(cu || limits);
|
|
9653
|
-
return /* @__PURE__ */
|
|
9654
|
-
/* @__PURE__ */
|
|
9655
|
-
/* @__PURE__ */
|
|
9663
|
+
return /* @__PURE__ */ jsxs71(React45.Fragment, { children: [
|
|
9664
|
+
/* @__PURE__ */ jsxs71("div", { className: "fdc-bar", children: [
|
|
9665
|
+
/* @__PURE__ */ jsxs71(
|
|
9656
9666
|
"button",
|
|
9657
9667
|
{
|
|
9658
9668
|
type: "button",
|
|
@@ -9682,14 +9692,14 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9682
9692
|
maxHeight: 460,
|
|
9683
9693
|
padded: true,
|
|
9684
9694
|
label: "Usage",
|
|
9685
|
-
footer: onClear ? /* @__PURE__ */
|
|
9695
|
+
footer: onClear ? /* @__PURE__ */ jsxs71("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
|
|
9686
9696
|
setOpen(false);
|
|
9687
9697
|
onClear();
|
|
9688
9698
|
}, children: [
|
|
9689
9699
|
/* @__PURE__ */ jsx75("i", { className: "ph ph-trash", "aria-hidden": "true" }),
|
|
9690
9700
|
"Clear conversation"
|
|
9691
9701
|
] }) : void 0,
|
|
9692
|
-
children: /* @__PURE__ */
|
|
9702
|
+
children: /* @__PURE__ */ jsxs71("div", { className: "fdc-usage", children: [
|
|
9693
9703
|
cu ? /* @__PURE__ */ jsx75("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx75(
|
|
9694
9704
|
SegmentedMeter,
|
|
9695
9705
|
{
|
|
@@ -9702,7 +9712,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9702
9712
|
remainderLabel: "Free"
|
|
9703
9713
|
}
|
|
9704
9714
|
) }) : null,
|
|
9705
|
-
limits && limits.length ? /* @__PURE__ */
|
|
9715
|
+
limits && limits.length ? /* @__PURE__ */ jsxs71("section", { className: "fdc-usage-sec", children: [
|
|
9706
9716
|
/* @__PURE__ */ jsx75("h4", { className: "fdc-usage-h", children: "Usage limits" }),
|
|
9707
9717
|
/* @__PURE__ */ jsx75("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx75(
|
|
9708
9718
|
QuotaRow,
|
|
@@ -9714,23 +9724,23 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9714
9724
|
l.id
|
|
9715
9725
|
)) })
|
|
9716
9726
|
] }) : null,
|
|
9717
|
-
stats ? /* @__PURE__ */
|
|
9718
|
-
stats.elapsedMs ? /* @__PURE__ */
|
|
9727
|
+
stats ? /* @__PURE__ */ jsxs71("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
|
|
9728
|
+
stats.elapsedMs ? /* @__PURE__ */ jsxs71("div", { children: [
|
|
9719
9729
|
/* @__PURE__ */ jsx75("span", { children: "Session" }),
|
|
9720
9730
|
/* @__PURE__ */ jsx75("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
|
|
9721
9731
|
] }) : null,
|
|
9722
|
-
stats.tokens ? /* @__PURE__ */
|
|
9732
|
+
stats.tokens ? /* @__PURE__ */ jsxs71("div", { children: [
|
|
9723
9733
|
/* @__PURE__ */ jsx75("span", { children: "Tokens" }),
|
|
9724
9734
|
/* @__PURE__ */ jsx75("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
|
|
9725
9735
|
] }) : null,
|
|
9726
|
-
stats.costUsd != null ? /* @__PURE__ */
|
|
9736
|
+
stats.costUsd != null ? /* @__PURE__ */ jsxs71("div", { children: [
|
|
9727
9737
|
/* @__PURE__ */ jsx75("span", { children: "Cost" }),
|
|
9728
|
-
/* @__PURE__ */
|
|
9738
|
+
/* @__PURE__ */ jsxs71("b", { className: "fd-tabular", children: [
|
|
9729
9739
|
"$",
|
|
9730
9740
|
Number(stats.costUsd).toFixed(3)
|
|
9731
9741
|
] })
|
|
9732
9742
|
] }) : null,
|
|
9733
|
-
stats.turns ? /* @__PURE__ */
|
|
9743
|
+
stats.turns ? /* @__PURE__ */ jsxs71("div", { children: [
|
|
9734
9744
|
/* @__PURE__ */ jsx75("span", { children: "Turns" }),
|
|
9735
9745
|
/* @__PURE__ */ jsx75("b", { className: "fd-tabular", children: stats.turns })
|
|
9736
9746
|
] }) : null
|
|
@@ -9784,14 +9794,14 @@ function ModelControls({
|
|
|
9784
9794
|
items.push({ kind: "section", label: "Fast mode" });
|
|
9785
9795
|
items.push({
|
|
9786
9796
|
kind: "custom",
|
|
9787
|
-
render: () => /* @__PURE__ */
|
|
9797
|
+
render: () => /* @__PURE__ */ jsxs71("label", { className: "fdc-switchrow", children: [
|
|
9788
9798
|
/* @__PURE__ */ jsx75("span", { children: fastModeLabel }),
|
|
9789
9799
|
/* @__PURE__ */ jsx75("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
|
|
9790
9800
|
/* @__PURE__ */ jsx75("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx75("span", { className: "fd-switch-thumb" }) })
|
|
9791
9801
|
] })
|
|
9792
9802
|
});
|
|
9793
9803
|
}
|
|
9794
|
-
return /* @__PURE__ */
|
|
9804
|
+
return /* @__PURE__ */ jsxs71(React45.Fragment, { children: [
|
|
9795
9805
|
/* @__PURE__ */ jsx75(
|
|
9796
9806
|
MenuButton,
|
|
9797
9807
|
{
|
|
@@ -9824,7 +9834,7 @@ function ModelControls({
|
|
|
9824
9834
|
}
|
|
9825
9835
|
|
|
9826
9836
|
// src/components/chat/AgentChatPanel.tsx
|
|
9827
|
-
import { jsx as jsx76, jsxs as
|
|
9837
|
+
import { jsx as jsx76, jsxs as jsxs72 } from "react/jsx-runtime";
|
|
9828
9838
|
var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
|
|
9829
9839
|
function AgentChatPanel({
|
|
9830
9840
|
/* required */
|
|
@@ -9908,11 +9918,11 @@ function AgentChatPanel({
|
|
|
9908
9918
|
onFeedback,
|
|
9909
9919
|
onEditMessage
|
|
9910
9920
|
}) {
|
|
9911
|
-
const [panelWidth, setPanelWidth] =
|
|
9912
|
-
const [applied, setApplied] =
|
|
9913
|
-
const [draft, setDraft] =
|
|
9914
|
-
const dragging =
|
|
9915
|
-
|
|
9921
|
+
const [panelWidth, setPanelWidth] = React46.useState(width);
|
|
9922
|
+
const [applied, setApplied] = React46.useState({});
|
|
9923
|
+
const [draft, setDraft] = React46.useState("");
|
|
9924
|
+
const dragging = React46.useRef(null);
|
|
9925
|
+
React46.useEffect(() => setPanelWidth(width), [width]);
|
|
9916
9926
|
const engine = useChatEngine({
|
|
9917
9927
|
contextType,
|
|
9918
9928
|
contextId,
|
|
@@ -10029,7 +10039,7 @@ function AgentChatPanel({
|
|
|
10029
10039
|
})))
|
|
10030
10040
|
}
|
|
10031
10041
|
) : null;
|
|
10032
|
-
return /* @__PURE__ */
|
|
10042
|
+
return /* @__PURE__ */ jsxs72(
|
|
10033
10043
|
"aside",
|
|
10034
10044
|
{
|
|
10035
10045
|
className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
|
|
@@ -10055,13 +10065,13 @@ function AgentChatPanel({
|
|
|
10055
10065
|
}
|
|
10056
10066
|
}
|
|
10057
10067
|
) : null,
|
|
10058
|
-
showHeader ? /* @__PURE__ */
|
|
10068
|
+
showHeader ? /* @__PURE__ */ jsxs72("header", { className: "fdc-head", children: [
|
|
10059
10069
|
/* @__PURE__ */ jsx76("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx76("i", { className: "ph ph-" + assistantIcon }) }),
|
|
10060
|
-
/* @__PURE__ */
|
|
10070
|
+
/* @__PURE__ */ jsxs72("span", { className: "fdc-head-titles", children: [
|
|
10061
10071
|
/* @__PURE__ */ jsx76("span", { className: "fdc-head-title", children: title }),
|
|
10062
10072
|
subtitle ? /* @__PURE__ */ jsx76("span", { className: "fdc-head-sub", children: subtitle }) : null
|
|
10063
10073
|
] }),
|
|
10064
|
-
/* @__PURE__ */
|
|
10074
|
+
/* @__PURE__ */ jsxs72("span", { className: "fdc-head-acts", children: [
|
|
10065
10075
|
headerActions,
|
|
10066
10076
|
threadMenu,
|
|
10067
10077
|
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 +10126,7 @@ function AgentChatPanel({
|
|
|
10116
10126
|
}
|
|
10117
10127
|
|
|
10118
10128
|
// src/kits/query.ts
|
|
10119
|
-
import * as
|
|
10129
|
+
import * as React47 from "react";
|
|
10120
10130
|
function eqFilter(get2) {
|
|
10121
10131
|
return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
|
|
10122
10132
|
}
|
|
@@ -10148,22 +10158,22 @@ function compare(a, b, dir) {
|
|
|
10148
10158
|
var API = null;
|
|
10149
10159
|
var PREFS = null;
|
|
10150
10160
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
10151
|
-
const [query, setQuery] =
|
|
10161
|
+
const [query, setQuery] = React47.useState(() => {
|
|
10152
10162
|
const store = PREFS || window.PlannerPrefs;
|
|
10153
10163
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
10154
10164
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
10155
10165
|
});
|
|
10156
|
-
const savePref =
|
|
10166
|
+
const savePref = React47.useCallback((patch2) => {
|
|
10157
10167
|
const store = PREFS || window.PlannerPrefs;
|
|
10158
10168
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
10159
10169
|
}, [prefsKey]);
|
|
10160
|
-
const [res, setRes] =
|
|
10161
|
-
const [loading, setLoading] =
|
|
10162
|
-
const seq2 =
|
|
10170
|
+
const [res, setRes] = React47.useState(null);
|
|
10171
|
+
const [loading, setLoading] = React47.useState(true);
|
|
10172
|
+
const seq2 = React47.useRef(0);
|
|
10163
10173
|
const depKey = (deps || []).join("|");
|
|
10164
10174
|
const paramKey = JSON.stringify(params || {});
|
|
10165
10175
|
const queryKey = JSON.stringify(query);
|
|
10166
|
-
|
|
10176
|
+
React47.useEffect(() => {
|
|
10167
10177
|
const id = ++seq2.current;
|
|
10168
10178
|
setLoading(true);
|
|
10169
10179
|
const t = setTimeout(() => {
|