@flytedan/flytebot-design-system 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1293 -1034
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +225 -1
- package/dist/index.d.ts +225 -1
- package/dist/index.js +1287 -1034
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/styles/components.css +6 -1
package/dist/index.cjs
CHANGED
|
@@ -70,6 +70,7 @@ __export(index_exports, {
|
|
|
70
70
|
Dropzone: () => Dropzone,
|
|
71
71
|
DropzoneKit: () => DropzoneKit,
|
|
72
72
|
EmptyState: () => EmptyState,
|
|
73
|
+
EntityRow: () => EntityRow,
|
|
73
74
|
FeatureGate: () => FeatureGate,
|
|
74
75
|
FileChip: () => FileChip,
|
|
75
76
|
FileGrid: () => FileGrid,
|
|
@@ -142,11 +143,16 @@ __export(index_exports, {
|
|
|
142
143
|
Tooltip: () => Tooltip,
|
|
143
144
|
Topbar: () => Topbar,
|
|
144
145
|
TranscriptKit: () => TranscriptKit,
|
|
146
|
+
TransferList: () => TransferList,
|
|
145
147
|
UseFeatureStatus: () => UseFeatureStatus,
|
|
146
148
|
UseRuntimeMode: () => UseRuntimeMode,
|
|
149
|
+
VIRTUAL_LIST_BUFFER_ROWS: () => VIRTUAL_LIST_BUFFER_ROWS,
|
|
150
|
+
VirtualList: () => VirtualList,
|
|
147
151
|
acceptMatches: () => acceptMatches,
|
|
148
152
|
anyOfFilter: () => anyOfFilter,
|
|
149
153
|
channelWeightOf: () => channelWeightOf,
|
|
154
|
+
computeNeedMore: () => computeNeedMore,
|
|
155
|
+
computeVirtualWindow: () => computeVirtualWindow,
|
|
150
156
|
createVersionStore: () => createVersionStore,
|
|
151
157
|
eqFilter: () => eqFilter,
|
|
152
158
|
extensionOf: () => extensionOf,
|
|
@@ -390,7 +396,14 @@ function Popover({
|
|
|
390
396
|
bottom: pos.bottom == null ? "auto" : pos.bottom,
|
|
391
397
|
width: matchWidth ? pos.width : width,
|
|
392
398
|
minWidth: minWidth || (matchWidth ? void 0 : 200),
|
|
393
|
-
|
|
399
|
+
// Size to content by default — cap only at real available room between the
|
|
400
|
+
// anchor and the viewport edge (pos.maxH, computed by usePopoverPosition).
|
|
401
|
+
// A caller-supplied `maxHeight` narrows that further (e.g. a long menu that
|
|
402
|
+
// should scroll well before it reaches the viewport edge); it must never
|
|
403
|
+
// widen past pos.maxH, which is why it's still Math.min'd against it. There
|
|
404
|
+
// is intentionally no arbitrary default here — an unrequested cap would clip
|
|
405
|
+
// ordinary content that simply happens to be taller than some fixed number.
|
|
406
|
+
maxHeight: maxHeight != null ? Math.min(maxHeight, pos.maxH) : pos.maxH,
|
|
394
407
|
transformOrigin: pos.side === "top" ? "bottom center" : "top center",
|
|
395
408
|
zIndex: 140,
|
|
396
409
|
...style
|
|
@@ -2606,56 +2619,140 @@ function StepList({
|
|
|
2606
2619
|
] });
|
|
2607
2620
|
}
|
|
2608
2621
|
|
|
2609
|
-
// src/components/
|
|
2622
|
+
// src/components/data/VirtualList.tsx
|
|
2610
2623
|
var React15 = __toESM(require("react"), 1);
|
|
2611
2624
|
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
2612
|
-
|
|
2613
|
-
|
|
2625
|
+
var VIRTUAL_LIST_BUFFER_ROWS = 20;
|
|
2626
|
+
function computeVirtualWindow(opts) {
|
|
2627
|
+
const { scrollTop, viewportHeight, itemHeight, itemCount, bufferRows = VIRTUAL_LIST_BUFFER_ROWS } = opts;
|
|
2628
|
+
if (itemCount <= 0 || itemHeight <= 0) {
|
|
2629
|
+
return { visibleStart: 0, visibleEnd: -1, startIndex: 0, endIndex: -1, totalHeight: 0, offsetY: 0 };
|
|
2630
|
+
}
|
|
2631
|
+
const lastPossible = itemCount - 1;
|
|
2632
|
+
const visibleStart = Math.min(lastPossible, Math.max(0, Math.floor(scrollTop / itemHeight)));
|
|
2633
|
+
const visibleRows = Math.max(1, Math.ceil(viewportHeight / itemHeight));
|
|
2634
|
+
const visibleEnd = Math.min(lastPossible, visibleStart + visibleRows - 1);
|
|
2635
|
+
const startIndex = Math.max(0, visibleStart - bufferRows);
|
|
2636
|
+
const endIndex = Math.min(lastPossible, visibleEnd + bufferRows);
|
|
2637
|
+
return {
|
|
2638
|
+
visibleStart,
|
|
2639
|
+
visibleEnd,
|
|
2640
|
+
startIndex,
|
|
2641
|
+
endIndex,
|
|
2642
|
+
totalHeight: itemCount * itemHeight,
|
|
2643
|
+
offsetY: startIndex * itemHeight
|
|
2644
|
+
};
|
|
2645
|
+
}
|
|
2646
|
+
function computeNeedMore(win, itemCount, bufferRows = VIRTUAL_LIST_BUFFER_ROWS) {
|
|
2647
|
+
if (itemCount <= 0) return { start: true, end: true };
|
|
2648
|
+
return {
|
|
2649
|
+
start: win.visibleStart <= bufferRows,
|
|
2650
|
+
end: itemCount - 1 - win.visibleEnd <= bufferRows
|
|
2651
|
+
};
|
|
2652
|
+
}
|
|
2653
|
+
function VirtualList({
|
|
2654
|
+
items,
|
|
2655
|
+
itemHeight,
|
|
2656
|
+
renderItem,
|
|
2657
|
+
onNeedMore,
|
|
2658
|
+
hasMore,
|
|
2659
|
+
loading = false,
|
|
2660
|
+
keyOf,
|
|
2661
|
+
height = 400,
|
|
2662
|
+
emptyState,
|
|
2663
|
+
className = "",
|
|
2664
|
+
style
|
|
2665
|
+
}) {
|
|
2666
|
+
const [scrollTop, setScrollTop] = React15.useState(0);
|
|
2667
|
+
const requested = React15.useRef({ start: null, end: null });
|
|
2668
|
+
const win = React15.useMemo(
|
|
2669
|
+
() => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: items.length }),
|
|
2670
|
+
[scrollTop, height, itemHeight, items.length]
|
|
2671
|
+
);
|
|
2672
|
+
const need = React15.useMemo(() => computeNeedMore(win, items.length), [win, items.length]);
|
|
2673
|
+
const wantStart = need.start && hasMore?.start !== false;
|
|
2674
|
+
const wantEnd = need.end && hasMore?.end !== false;
|
|
2614
2675
|
React15.useEffect(() => {
|
|
2615
|
-
if (
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
] })
|
|
2626
|
-
|
|
2676
|
+
if (loading || !wantStart || requested.current.start === items.length) return;
|
|
2677
|
+
requested.current.start = items.length;
|
|
2678
|
+
onNeedMore("start");
|
|
2679
|
+
}, [wantStart, loading, items.length, onNeedMore]);
|
|
2680
|
+
React15.useEffect(() => {
|
|
2681
|
+
if (loading || !wantEnd || requested.current.end === items.length) return;
|
|
2682
|
+
requested.current.end = items.length;
|
|
2683
|
+
onNeedMore("end");
|
|
2684
|
+
}, [wantEnd, loading, items.length, onNeedMore]);
|
|
2685
|
+
if (!items.length && !loading && emptyState) {
|
|
2686
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: ["fd-vlist", className].filter(Boolean).join(" "), style: { height, overflow: "auto", ...style }, children: emptyState });
|
|
2687
|
+
}
|
|
2688
|
+
const rows = [];
|
|
2689
|
+
for (let i = win.startIndex; i <= win.endIndex; i++) {
|
|
2690
|
+
const item = items[i];
|
|
2691
|
+
if (item === void 0) continue;
|
|
2692
|
+
rows.push(
|
|
2693
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { style: { height: itemHeight, boxSizing: "border-box" }, children: renderItem(item, i) }, keyOf(item))
|
|
2694
|
+
);
|
|
2695
|
+
}
|
|
2696
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
2697
|
+
"div",
|
|
2698
|
+
{
|
|
2699
|
+
className: ["fd-vlist", className].filter(Boolean).join(" "),
|
|
2700
|
+
style: { height, overflowY: "auto", overflowX: "hidden", position: "relative", ...style },
|
|
2701
|
+
onScroll: (e) => setScrollTop(e.currentTarget.scrollTop),
|
|
2702
|
+
children: [
|
|
2703
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { style: { height: win.totalHeight, position: "relative" }, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { style: { position: "absolute", top: win.offsetY, left: 0, right: 0 }, children: rows }) }),
|
|
2704
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { style: { position: "sticky", bottom: 0, left: 0, right: 0, display: "grid", placeItems: "center", padding: "8px 0", background: "var(--surface)" }, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "fd-spinner", "aria-hidden": "true" }) }) : null
|
|
2705
|
+
]
|
|
2706
|
+
}
|
|
2707
|
+
);
|
|
2627
2708
|
}
|
|
2628
2709
|
|
|
2629
|
-
// src/components/
|
|
2710
|
+
// src/components/data/EntityRow.tsx
|
|
2630
2711
|
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
2631
|
-
function
|
|
2632
|
-
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2712
|
+
function EntityRow({ title, meta, action, draggable = false, onDragStart, onDragEnd, style, className = "" }) {
|
|
2713
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
|
|
2714
|
+
"div",
|
|
2715
|
+
{
|
|
2716
|
+
draggable,
|
|
2717
|
+
onDragStart,
|
|
2718
|
+
onDragEnd,
|
|
2719
|
+
className: ["fd-erow", className].filter(Boolean).join(" "),
|
|
2720
|
+
style: {
|
|
2721
|
+
display: "flex",
|
|
2722
|
+
alignItems: "center",
|
|
2723
|
+
gap: 8,
|
|
2724
|
+
height: "100%",
|
|
2725
|
+
padding: "0 8px",
|
|
2726
|
+
borderRadius: 6,
|
|
2727
|
+
cursor: draggable ? "grab" : void 0,
|
|
2728
|
+
...style
|
|
2729
|
+
},
|
|
2730
|
+
children: [
|
|
2731
|
+
draggable ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("i", { className: "ph ph-dots-six-vertical", "aria-hidden": "true", style: { fontSize: 13, flex: "none", color: "var(--text-muted)" } }) : null,
|
|
2732
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: 1 }, children: [
|
|
2733
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600, color: "var(--text)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: title }),
|
|
2734
|
+
meta ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { style: { fontSize: "var(--overline-size)", color: "var(--text-muted)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: meta }) : null
|
|
2735
|
+
] }),
|
|
2736
|
+
action ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
2737
|
+
IconButton,
|
|
2738
|
+
{
|
|
2739
|
+
icon: action.icon,
|
|
2740
|
+
label: action.label,
|
|
2741
|
+
size: "sm",
|
|
2742
|
+
onClick: action.onClick,
|
|
2743
|
+
style: { color: action.tone === "add" ? "var(--ok-text)" : action.tone === "remove" ? "var(--danger-text)" : void 0 }
|
|
2744
|
+
}
|
|
2745
|
+
) : null
|
|
2746
|
+
]
|
|
2747
|
+
}
|
|
2748
|
+
);
|
|
2642
2749
|
}
|
|
2643
2750
|
|
|
2644
|
-
// src/components/
|
|
2645
|
-
var
|
|
2646
|
-
function Switch({ label, description, className = "", ...rest }) {
|
|
2647
|
-
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
|
|
2648
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("input", { type: "checkbox", role: "switch", ...rest }),
|
|
2649
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-switch-track", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-switch-thumb" }) }),
|
|
2650
|
-
label ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "fd-choice-text", children: [
|
|
2651
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-switch-label", children: label }),
|
|
2652
|
-
description ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-choice-desc", children: description }) : null
|
|
2653
|
-
] }) : null
|
|
2654
|
-
] });
|
|
2655
|
-
}
|
|
2751
|
+
// src/components/data/TransferList.tsx
|
|
2752
|
+
var React16 = __toESM(require("react"), 1);
|
|
2656
2753
|
|
|
2657
2754
|
// src/components/forms/Input.tsx
|
|
2658
|
-
var
|
|
2755
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
2659
2756
|
function Input({
|
|
2660
2757
|
label,
|
|
2661
2758
|
help,
|
|
@@ -2683,27 +2780,27 @@ function Input({
|
|
|
2683
2780
|
size === "lg" ? "fd-input-lg" : "",
|
|
2684
2781
|
className
|
|
2685
2782
|
].filter(Boolean).join(" ");
|
|
2686
|
-
return /* @__PURE__ */ (0,
|
|
2687
|
-
label ? /* @__PURE__ */ (0,
|
|
2783
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "fd-field", style, children: [
|
|
2784
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("label", { className: "fd-field-label", htmlFor: fieldId, children: [
|
|
2688
2785
|
label,
|
|
2689
|
-
required ? /* @__PURE__ */ (0,
|
|
2786
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-field-req", "aria-hidden": "true", children: "*" }) : null
|
|
2690
2787
|
] }) : null,
|
|
2691
|
-
/* @__PURE__ */ (0,
|
|
2692
|
-
icon ? /* @__PURE__ */ (0,
|
|
2693
|
-
prefix ? /* @__PURE__ */ (0,
|
|
2694
|
-
/* @__PURE__ */ (0,
|
|
2695
|
-
loading ? /* @__PURE__ */ (0,
|
|
2696
|
-
suffix && !loading ? /* @__PURE__ */ (0,
|
|
2788
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: box, children: [
|
|
2789
|
+
icon ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("i", { className: "ph ph-" + icon, "aria-hidden": "true" }) }) : null,
|
|
2790
|
+
prefix ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
|
|
2791
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("input", { id: fieldId, disabled, style: inputStyle, "aria-invalid": error ? "true" : void 0, ...rest }),
|
|
2792
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading" }) : null,
|
|
2793
|
+
suffix && !loading ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-input-affix", children: suffix }) : null
|
|
2697
2794
|
] }),
|
|
2698
|
-
error ? /* @__PURE__ */ (0,
|
|
2699
|
-
/* @__PURE__ */ (0,
|
|
2795
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "fd-field-error", children: [
|
|
2796
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
2700
2797
|
error
|
|
2701
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
2798
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
2702
2799
|
] });
|
|
2703
2800
|
}
|
|
2704
2801
|
|
|
2705
2802
|
// src/components/forms/SearchField.tsx
|
|
2706
|
-
var
|
|
2803
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
2707
2804
|
function SearchField({
|
|
2708
2805
|
value,
|
|
2709
2806
|
onChange,
|
|
@@ -2718,7 +2815,7 @@ function SearchField({
|
|
|
2718
2815
|
...rest
|
|
2719
2816
|
}) {
|
|
2720
2817
|
const clear = onClear || (() => onChange(""));
|
|
2721
|
-
return /* @__PURE__ */ (0,
|
|
2818
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2722
2819
|
Input,
|
|
2723
2820
|
{
|
|
2724
2821
|
id,
|
|
@@ -2731,14 +2828,14 @@ function SearchField({
|
|
|
2731
2828
|
style,
|
|
2732
2829
|
className,
|
|
2733
2830
|
onChange: (e) => onChange(e.target.value),
|
|
2734
|
-
suffix: value ? /* @__PURE__ */ (0,
|
|
2831
|
+
suffix: value ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2735
2832
|
"button",
|
|
2736
2833
|
{
|
|
2737
2834
|
type: "button",
|
|
2738
2835
|
"aria-label": "Clear search",
|
|
2739
2836
|
onClick: clear,
|
|
2740
2837
|
style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
|
|
2741
|
-
children: /* @__PURE__ */ (0,
|
|
2838
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 }, "aria-hidden": "true" })
|
|
2742
2839
|
}
|
|
2743
2840
|
) : void 0,
|
|
2744
2841
|
...rest
|
|
@@ -2746,27 +2843,183 @@ function SearchField({
|
|
|
2746
2843
|
);
|
|
2747
2844
|
}
|
|
2748
2845
|
|
|
2749
|
-
// src/components/
|
|
2846
|
+
// src/components/data/TransferList.tsx
|
|
2847
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
2848
|
+
var emptyHasMore = {};
|
|
2849
|
+
function TransferList({
|
|
2850
|
+
left,
|
|
2851
|
+
right,
|
|
2852
|
+
keyOf,
|
|
2853
|
+
renderLabel,
|
|
2854
|
+
renderMeta,
|
|
2855
|
+
onMove,
|
|
2856
|
+
itemHeight = 44,
|
|
2857
|
+
listHeight = 440,
|
|
2858
|
+
className = ""
|
|
2859
|
+
}) {
|
|
2860
|
+
const [dragging, setDragging] = React16.useState(null);
|
|
2861
|
+
const [dragOverSide, setDragOverSide] = React16.useState(null);
|
|
2862
|
+
const startDrag = (e, item, from) => {
|
|
2863
|
+
const key = keyOf(item);
|
|
2864
|
+
setDragging({ key, from });
|
|
2865
|
+
e.dataTransfer.effectAllowed = "move";
|
|
2866
|
+
e.dataTransfer.setData("text/plain", String(key));
|
|
2867
|
+
};
|
|
2868
|
+
const endDrag = () => {
|
|
2869
|
+
setDragging(null);
|
|
2870
|
+
setDragOverSide(null);
|
|
2871
|
+
};
|
|
2872
|
+
const findItem = (side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key);
|
|
2873
|
+
const dropOnSide = (e, side) => {
|
|
2874
|
+
e.preventDefault();
|
|
2875
|
+
setDragOverSide(null);
|
|
2876
|
+
if (!dragging || dragging.from === side) return;
|
|
2877
|
+
const item = findItem(dragging.from, dragging.key);
|
|
2878
|
+
if (item !== void 0) onMove(item, dragging.from, side);
|
|
2879
|
+
setDragging(null);
|
|
2880
|
+
};
|
|
2881
|
+
const renderSide = (side, cfg, opposite) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
2882
|
+
"div",
|
|
2883
|
+
{
|
|
2884
|
+
style: {
|
|
2885
|
+
flex: 1,
|
|
2886
|
+
minWidth: 0,
|
|
2887
|
+
display: "flex",
|
|
2888
|
+
flexDirection: "column",
|
|
2889
|
+
gap: 8,
|
|
2890
|
+
padding: 10,
|
|
2891
|
+
borderRadius: 10,
|
|
2892
|
+
border: "1px solid " + (dragOverSide === side ? "var(--brand)" : "var(--border)"),
|
|
2893
|
+
background: "var(--surface)"
|
|
2894
|
+
},
|
|
2895
|
+
onDragOver: (e) => {
|
|
2896
|
+
if (!dragging || dragging.from === side) return;
|
|
2897
|
+
e.preventDefault();
|
|
2898
|
+
e.dataTransfer.dropEffect = "move";
|
|
2899
|
+
if (dragOverSide !== side) setDragOverSide(side);
|
|
2900
|
+
},
|
|
2901
|
+
onDragLeave: (e) => {
|
|
2902
|
+
if (e.currentTarget.contains(e.relatedTarget)) return;
|
|
2903
|
+
setDragOverSide((s) => s === side ? null : s);
|
|
2904
|
+
},
|
|
2905
|
+
onDrop: (e) => dropOnSide(e, side),
|
|
2906
|
+
children: [
|
|
2907
|
+
cfg.label ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "fd-overline fd-muted", children: [
|
|
2908
|
+
cfg.label,
|
|
2909
|
+
cfg.total != null ? " (" + cfg.total.toLocaleString() + ")" : ""
|
|
2910
|
+
] }) : null,
|
|
2911
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
2912
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(SearchField, { value: cfg.search, onChange: cfg.onSearchChange, placeholder: "Search", "aria-label": (cfg.label || side) + " search", style: { flex: 1 } }),
|
|
2913
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(SortMenu, { fields: cfg.sortFields, sort: cfg.sort, onSort: cfg.onSort })
|
|
2914
|
+
] }),
|
|
2915
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2916
|
+
VirtualList,
|
|
2917
|
+
{
|
|
2918
|
+
items: cfg.items,
|
|
2919
|
+
itemHeight,
|
|
2920
|
+
height: listHeight,
|
|
2921
|
+
keyOf,
|
|
2922
|
+
loading: cfg.loading,
|
|
2923
|
+
hasMore: cfg.hasMore || emptyHasMore,
|
|
2924
|
+
onNeedMore: cfg.onNeedMore,
|
|
2925
|
+
emptyState: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(EmptyState, { icon: "tray", title: "Nothing here" }),
|
|
2926
|
+
renderItem: (item) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2927
|
+
EntityRow,
|
|
2928
|
+
{
|
|
2929
|
+
title: renderLabel(item),
|
|
2930
|
+
meta: renderMeta ? renderMeta(item) : void 0,
|
|
2931
|
+
draggable: true,
|
|
2932
|
+
onDragStart: (e) => startDrag(e, item, side),
|
|
2933
|
+
onDragEnd: endDrag,
|
|
2934
|
+
style: { opacity: dragging && dragging.from === side && dragging.key === keyOf(item) ? 0.4 : 1 },
|
|
2935
|
+
action: {
|
|
2936
|
+
icon: side === "left" ? "plus" : "minus",
|
|
2937
|
+
label: (side === "left" ? "Move to " : "Move from ") + (side === "left" ? right.label || "the other list" : left.label || "the other list"),
|
|
2938
|
+
tone: side === "left" ? "add" : "remove",
|
|
2939
|
+
onClick: () => onMove(item, side, opposite)
|
|
2940
|
+
}
|
|
2941
|
+
}
|
|
2942
|
+
)
|
|
2943
|
+
}
|
|
2944
|
+
)
|
|
2945
|
+
]
|
|
2946
|
+
}
|
|
2947
|
+
);
|
|
2948
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: ["fd-tlist", className].filter(Boolean).join(" "), style: { display: "flex", gap: 16, alignItems: "flex-start" }, children: [
|
|
2949
|
+
renderSide("left", left, "right"),
|
|
2950
|
+
renderSide("right", right, "left")
|
|
2951
|
+
] });
|
|
2952
|
+
}
|
|
2953
|
+
|
|
2954
|
+
// src/components/forms/Checkbox.tsx
|
|
2955
|
+
var React17 = __toESM(require("react"), 1);
|
|
2750
2956
|
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
2957
|
+
function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
|
|
2958
|
+
const ref = React17.useRef(null);
|
|
2959
|
+
React17.useEffect(() => {
|
|
2960
|
+
if (ref.current) ref.current.indeterminate = indeterminate;
|
|
2961
|
+
}, [indeterminate]);
|
|
2962
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
2963
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "fd-choice-input", children: [
|
|
2964
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("input", { ref, type: "checkbox", ...rest }),
|
|
2965
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-choice-box", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("i", { className: indeterminate ? "ph ph-minus" : "ph ph-check" }) })
|
|
2966
|
+
] }),
|
|
2967
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "fd-choice-text", children: [
|
|
2968
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-choice-title", children: label }),
|
|
2969
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-choice-desc", children: description }) : null
|
|
2970
|
+
] })
|
|
2971
|
+
] });
|
|
2972
|
+
}
|
|
2973
|
+
|
|
2974
|
+
// src/components/forms/Radio.tsx
|
|
2975
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
2976
|
+
function Radio({ label, description, card = false, className = "", ...rest }) {
|
|
2977
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
2978
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "fd-choice-input", children: [
|
|
2979
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("input", { type: "radio", ...rest }),
|
|
2980
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-choice-dot" }) })
|
|
2981
|
+
] }),
|
|
2982
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "fd-choice-text", children: [
|
|
2983
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-choice-title", children: label }),
|
|
2984
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-choice-desc", children: description }) : null
|
|
2985
|
+
] })
|
|
2986
|
+
] });
|
|
2987
|
+
}
|
|
2988
|
+
|
|
2989
|
+
// src/components/forms/Switch.tsx
|
|
2990
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
2991
|
+
function Switch({ label, description, className = "", ...rest }) {
|
|
2992
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
|
|
2993
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("input", { type: "checkbox", role: "switch", ...rest }),
|
|
2994
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-switch-track", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-switch-thumb" }) }),
|
|
2995
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-choice-text", children: [
|
|
2996
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-switch-label", children: label }),
|
|
2997
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-choice-desc", children: description }) : null
|
|
2998
|
+
] }) : null
|
|
2999
|
+
] });
|
|
3000
|
+
}
|
|
3001
|
+
|
|
3002
|
+
// src/components/forms/Textarea.tsx
|
|
3003
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
2751
3004
|
function Textarea({ label, help, error, required = false, rows = 4, disabled = false, id, className = "", style, ...rest }) {
|
|
2752
3005
|
const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
|
|
2753
3006
|
const box = ["fd-input", "fd-input-textarea", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : "", className].filter(Boolean).join(" ");
|
|
2754
|
-
return /* @__PURE__ */ (0,
|
|
2755
|
-
label ? /* @__PURE__ */ (0,
|
|
3007
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "fd-field", style, children: [
|
|
3008
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("label", { className: "fd-field-label", htmlFor: fieldId, children: [
|
|
2756
3009
|
label,
|
|
2757
|
-
required ? /* @__PURE__ */ (0,
|
|
3010
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-field-req", children: "*" }) : null
|
|
2758
3011
|
] }) : null,
|
|
2759
|
-
/* @__PURE__ */ (0,
|
|
2760
|
-
error ? /* @__PURE__ */ (0,
|
|
2761
|
-
/* @__PURE__ */ (0,
|
|
3012
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: box, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("textarea", { id: fieldId, rows, disabled, "aria-invalid": error ? "true" : void 0, ...rest }) }),
|
|
3013
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "fd-field-error", children: [
|
|
3014
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
2762
3015
|
error
|
|
2763
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3016
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
2764
3017
|
] });
|
|
2765
3018
|
}
|
|
2766
3019
|
|
|
2767
3020
|
// src/components/forms/NumberInput.tsx
|
|
2768
|
-
var
|
|
2769
|
-
var
|
|
3021
|
+
var React18 = __toESM(require("react"), 1);
|
|
3022
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
2770
3023
|
function NumberInput({
|
|
2771
3024
|
label,
|
|
2772
3025
|
help,
|
|
@@ -2790,10 +3043,10 @@ function NumberInput({
|
|
|
2790
3043
|
const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
|
|
2791
3044
|
return isNaN(n) ? null : n;
|
|
2792
3045
|
};
|
|
2793
|
-
const [text, setText] =
|
|
2794
|
-
const [editing, setEditing] =
|
|
2795
|
-
const timer =
|
|
2796
|
-
|
|
3046
|
+
const [text, setText] = React18.useState(value == null || value === "" ? "" : String(value));
|
|
3047
|
+
const [editing, setEditing] = React18.useState(false);
|
|
3048
|
+
const timer = React18.useRef(null);
|
|
3049
|
+
React18.useEffect(() => {
|
|
2797
3050
|
if (!editing) setText(value == null || value === "" ? "" : String(value));
|
|
2798
3051
|
}, [value, editing]);
|
|
2799
3052
|
const clamp = (n) => Math.min(max, Math.max(min, n));
|
|
@@ -2817,7 +3070,7 @@ function NumberInput({
|
|
|
2817
3070
|
const release = () => {
|
|
2818
3071
|
if (timer.current) clearTimeout(timer.current);
|
|
2819
3072
|
};
|
|
2820
|
-
|
|
3073
|
+
React18.useEffect(() => () => {
|
|
2821
3074
|
if (timer.current) clearTimeout(timer.current);
|
|
2822
3075
|
}, []);
|
|
2823
3076
|
const shown = editing ? text : (() => {
|
|
@@ -2825,14 +3078,14 @@ function NumberInput({
|
|
|
2825
3078
|
return n == null ? "" : format ? n.toLocaleString() : String(n);
|
|
2826
3079
|
})();
|
|
2827
3080
|
const box = ["fd-input", "fd-input-num", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
2828
|
-
return /* @__PURE__ */ (0,
|
|
2829
|
-
label ? /* @__PURE__ */ (0,
|
|
3081
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
|
|
3082
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "fd-field-label", children: [
|
|
2830
3083
|
label,
|
|
2831
|
-
required ? /* @__PURE__ */ (0,
|
|
3084
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-field-req", children: "*" }) : null
|
|
2832
3085
|
] }) : null,
|
|
2833
|
-
/* @__PURE__ */ (0,
|
|
2834
|
-
prefix ? /* @__PURE__ */ (0,
|
|
2835
|
-
/* @__PURE__ */ (0,
|
|
3086
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: box, style: { gap: 8 }, children: [
|
|
3087
|
+
prefix ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
|
|
3088
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2836
3089
|
"input",
|
|
2837
3090
|
{
|
|
2838
3091
|
inputMode: "numeric",
|
|
@@ -2865,9 +3118,9 @@ function NumberInput({
|
|
|
2865
3118
|
}
|
|
2866
3119
|
}
|
|
2867
3120
|
),
|
|
2868
|
-
suffix ? /* @__PURE__ */ (0,
|
|
2869
|
-
/* @__PURE__ */ (0,
|
|
2870
|
-
/* @__PURE__ */ (0,
|
|
3121
|
+
suffix ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-input-affix", children: suffix }) : null,
|
|
3122
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "fd-row", style: { gap: 4, flex: "none" }, children: [
|
|
3123
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2871
3124
|
"button",
|
|
2872
3125
|
{
|
|
2873
3126
|
type: "button",
|
|
@@ -2877,10 +3130,10 @@ function NumberInput({
|
|
|
2877
3130
|
onPointerDown: () => hold(-1),
|
|
2878
3131
|
onPointerUp: release,
|
|
2879
3132
|
onPointerLeave: release,
|
|
2880
|
-
children: /* @__PURE__ */ (0,
|
|
3133
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-minus" })
|
|
2881
3134
|
}
|
|
2882
3135
|
),
|
|
2883
|
-
/* @__PURE__ */ (0,
|
|
3136
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2884
3137
|
"button",
|
|
2885
3138
|
{
|
|
2886
3139
|
type: "button",
|
|
@@ -2890,26 +3143,26 @@ function NumberInput({
|
|
|
2890
3143
|
onPointerDown: () => hold(1),
|
|
2891
3144
|
onPointerUp: release,
|
|
2892
3145
|
onPointerLeave: release,
|
|
2893
|
-
children: /* @__PURE__ */ (0,
|
|
3146
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-plus" })
|
|
2894
3147
|
}
|
|
2895
3148
|
)
|
|
2896
3149
|
] })
|
|
2897
3150
|
] }),
|
|
2898
|
-
error ? /* @__PURE__ */ (0,
|
|
2899
|
-
/* @__PURE__ */ (0,
|
|
3151
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "fd-field-error", children: [
|
|
3152
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
2900
3153
|
error
|
|
2901
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3154
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
2902
3155
|
] });
|
|
2903
3156
|
}
|
|
2904
3157
|
|
|
2905
3158
|
// src/components/forms/Select.tsx
|
|
2906
|
-
var
|
|
3159
|
+
var React19 = __toESM(require("react"), 1);
|
|
2907
3160
|
var import_react_dom4 = require("react-dom");
|
|
2908
|
-
var
|
|
3161
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
2909
3162
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
2910
3163
|
function usePopPos(open, ref, estH, estW) {
|
|
2911
|
-
const [pos, setPos] =
|
|
2912
|
-
|
|
3164
|
+
const [pos, setPos] = React19.useState(null);
|
|
3165
|
+
React19.useLayoutEffect(() => {
|
|
2913
3166
|
if (!open || !ref.current) {
|
|
2914
3167
|
setPos(null);
|
|
2915
3168
|
return;
|
|
@@ -2973,14 +3226,14 @@ function Select({
|
|
|
2973
3226
|
const vals = multiple ? Array.isArray(value) ? value : value ? [value] : [] : [];
|
|
2974
3227
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
2975
3228
|
const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
|
|
2976
|
-
const [open, setOpen] =
|
|
2977
|
-
const [q, setQ] =
|
|
2978
|
-
const [active, setActive] =
|
|
2979
|
-
const rootRef =
|
|
2980
|
-
const boxRef =
|
|
2981
|
-
const popRef =
|
|
2982
|
-
const listRef =
|
|
2983
|
-
const typeBuf =
|
|
3229
|
+
const [open, setOpen] = React19.useState(false);
|
|
3230
|
+
const [q, setQ] = React19.useState("");
|
|
3231
|
+
const [active, setActive] = React19.useState(-1);
|
|
3232
|
+
const rootRef = React19.useRef(null);
|
|
3233
|
+
const boxRef = React19.useRef(null);
|
|
3234
|
+
const popRef = React19.useRef(null);
|
|
3235
|
+
const listRef = React19.useRef(null);
|
|
3236
|
+
const typeBuf = React19.useRef({ s: "", t: 0 });
|
|
2984
3237
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
2985
3238
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
2986
3239
|
const pos = usePopPos(open, boxRef, hasSearch ? 390 : 340, 260);
|
|
@@ -3006,7 +3259,7 @@ function Select({
|
|
|
3006
3259
|
}
|
|
3007
3260
|
setOpen(!open);
|
|
3008
3261
|
};
|
|
3009
|
-
|
|
3262
|
+
React19.useEffect(() => {
|
|
3010
3263
|
if (!open) return;
|
|
3011
3264
|
const away = (e) => {
|
|
3012
3265
|
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
@@ -3016,7 +3269,7 @@ function Select({
|
|
|
3016
3269
|
document.addEventListener("pointerdown", away);
|
|
3017
3270
|
return () => document.removeEventListener("pointerdown", away);
|
|
3018
3271
|
}, [open]);
|
|
3019
|
-
|
|
3272
|
+
React19.useEffect(() => {
|
|
3020
3273
|
if (!open || active < 0 || !listRef.current) return;
|
|
3021
3274
|
const el = listRef.current.querySelector('[data-i="' + active + '"]');
|
|
3022
3275
|
if (el) {
|
|
@@ -3070,13 +3323,13 @@ function Select({
|
|
|
3070
3323
|
});
|
|
3071
3324
|
const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
|
|
3072
3325
|
const box = ["fd-input", "fd-select", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
3073
|
-
return /* @__PURE__ */ (0,
|
|
3074
|
-
label ? /* @__PURE__ */ (0,
|
|
3326
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
3327
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "fd-field-label", htmlFor: fieldId, onClick: toggle, children: [
|
|
3075
3328
|
label,
|
|
3076
|
-
required ? /* @__PURE__ */ (0,
|
|
3329
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-field-req", children: "*" }) : null
|
|
3077
3330
|
] }) : null,
|
|
3078
|
-
/* @__PURE__ */ (0,
|
|
3079
|
-
/* @__PURE__ */ (0,
|
|
3331
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: box, style: { cursor: disabled ? "not-allowed" : "pointer" }, ref: boxRef, children: [
|
|
3332
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
3080
3333
|
"button",
|
|
3081
3334
|
{
|
|
3082
3335
|
type: "button",
|
|
@@ -3089,13 +3342,13 @@ function Select({
|
|
|
3089
3342
|
"aria-haspopup": "listbox",
|
|
3090
3343
|
style: { all: "unset", flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: 8, cursor: "inherit", overflow: "hidden" },
|
|
3091
3344
|
children: [
|
|
3092
|
-
selected && selected.icon ? /* @__PURE__ */ (0,
|
|
3093
|
-
/* @__PURE__ */ (0,
|
|
3094
|
-
multiple && chosen.length > 1 ? /* @__PURE__ */ (0,
|
|
3345
|
+
selected && selected.icon ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-" + selected.icon, style: { flex: "none", color: "var(--text-2)" } }) : null,
|
|
3346
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: (multiple ? chosen.length : selected) ? "var(--text)" : "var(--text-muted)" }, children: boxText }),
|
|
3347
|
+
multiple && chosen.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-mono", style: { flex: "none", fontSize: 11, fontWeight: 700, padding: "1px 6px", borderRadius: 99, background: "var(--brand)", color: "#fff" }, children: chosen.length }) : null
|
|
3095
3348
|
]
|
|
3096
3349
|
}
|
|
3097
3350
|
),
|
|
3098
|
-
clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ (0,
|
|
3351
|
+
clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3099
3352
|
"button",
|
|
3100
3353
|
{
|
|
3101
3354
|
type: "button",
|
|
@@ -3105,22 +3358,22 @@ function Select({
|
|
|
3105
3358
|
fire(multiple ? [] : "");
|
|
3106
3359
|
},
|
|
3107
3360
|
style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
|
|
3108
|
-
children: /* @__PURE__ */ (0,
|
|
3361
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 } })
|
|
3109
3362
|
}
|
|
3110
3363
|
) : null,
|
|
3111
|
-
loading ? /* @__PURE__ */ (0,
|
|
3364
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading options" }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-select-caret", onClick: toggle, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
|
|
3112
3365
|
] }),
|
|
3113
3366
|
open && pos ? (0, import_react_dom4.createPortal)(
|
|
3114
|
-
/* @__PURE__ */ (0,
|
|
3367
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
3115
3368
|
"div",
|
|
3116
3369
|
{
|
|
3117
3370
|
className: "fd-pop" + (pos.up ? " is-up" : ""),
|
|
3118
3371
|
ref: popRef,
|
|
3119
3372
|
style: popStyle(pos, { minWidth: Math.max(pos.width, 260), maxWidth: 380, zIndex: 130, overflowY: "hidden" }),
|
|
3120
3373
|
children: [
|
|
3121
|
-
hasSearch ? /* @__PURE__ */ (0,
|
|
3122
|
-
/* @__PURE__ */ (0,
|
|
3123
|
-
/* @__PURE__ */ (0,
|
|
3374
|
+
hasSearch ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fd-pop-search", children: [
|
|
3375
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-magnifying-glass", style: { color: "var(--text-muted)", fontSize: 14 } }),
|
|
3376
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3124
3377
|
"input",
|
|
3125
3378
|
{
|
|
3126
3379
|
autoFocus: true,
|
|
@@ -3133,15 +3386,15 @@ function Select({
|
|
|
3133
3386
|
}
|
|
3134
3387
|
}
|
|
3135
3388
|
),
|
|
3136
|
-
q ? /* @__PURE__ */ (0,
|
|
3389
|
+
q ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
3137
3390
|
] }) : null,
|
|
3138
|
-
/* @__PURE__ */ (0,
|
|
3391
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "fd-pop-list", role: "listbox", "aria-multiselectable": multiple || void 0, ref: listRef, style: { maxHeight: Math.max(120, pos.maxH - (hasSearch ? 64 : 12) - (multiple ? 42 : 0)) }, children: visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fd-pop-empty", children: [
|
|
3139
3392
|
'Nothing matches "',
|
|
3140
3393
|
q,
|
|
3141
3394
|
'".'
|
|
3142
|
-
] }) : groups.map((grp) => /* @__PURE__ */ (0,
|
|
3143
|
-
grp.g ? /* @__PURE__ */ (0,
|
|
3144
|
-
grp.items.map(({ o, i }) => /* @__PURE__ */ (0,
|
|
3395
|
+
] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(React19.Fragment, { children: [
|
|
3396
|
+
grp.g ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
|
|
3397
|
+
grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
3145
3398
|
"button",
|
|
3146
3399
|
{
|
|
3147
3400
|
type: "button",
|
|
@@ -3153,21 +3406,21 @@ function Select({
|
|
|
3153
3406
|
onMouseEnter: () => setActive(i),
|
|
3154
3407
|
onClick: () => pick(o),
|
|
3155
3408
|
children: [
|
|
3156
|
-
multiple ? /* @__PURE__ */ (0,
|
|
3157
|
-
o.icon ? /* @__PURE__ */ (0,
|
|
3158
|
-
/* @__PURE__ */ (0,
|
|
3159
|
-
/* @__PURE__ */ (0,
|
|
3160
|
-
o.description ? /* @__PURE__ */ (0,
|
|
3409
|
+
multiple ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("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__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-check", style: { fontSize: 11 } }) : null }) : null,
|
|
3410
|
+
o.icon ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-opt-icon", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-" + o.icon }) }) : null,
|
|
3411
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { style: { flex: 1, minWidth: 0 }, children: [
|
|
3412
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-opt-label", children: o.label }),
|
|
3413
|
+
o.description ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-opt-desc", children: o.description }) : null
|
|
3161
3414
|
] }),
|
|
3162
|
-
o.meta ? /* @__PURE__ */ (0,
|
|
3163
|
-
multiple ? null : /* @__PURE__ */ (0,
|
|
3415
|
+
o.meta ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-opt-meta", children: o.meta }) : null,
|
|
3416
|
+
multiple ? null : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-opt-check", children: o.value === value ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-check" }) : null })
|
|
3164
3417
|
]
|
|
3165
3418
|
},
|
|
3166
3419
|
String(o.value)
|
|
3167
3420
|
))
|
|
3168
3421
|
] }, grp.g || "_")) }),
|
|
3169
|
-
multiple ? /* @__PURE__ */ (0,
|
|
3170
|
-
/* @__PURE__ */ (0,
|
|
3422
|
+
multiple ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "8px 12px", borderTop: "1px solid var(--border)" }, children: [
|
|
3423
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3171
3424
|
"button",
|
|
3172
3425
|
{
|
|
3173
3426
|
type: "button",
|
|
@@ -3176,13 +3429,13 @@ function Select({
|
|
|
3176
3429
|
children: "Select all"
|
|
3177
3430
|
}
|
|
3178
3431
|
),
|
|
3179
|
-
/* @__PURE__ */ (0,
|
|
3180
|
-
/* @__PURE__ */ (0,
|
|
3432
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { style: { flex: 1 } }),
|
|
3433
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
3181
3434
|
vals.length,
|
|
3182
3435
|
" of ",
|
|
3183
3436
|
opts.length
|
|
3184
3437
|
] }),
|
|
3185
|
-
/* @__PURE__ */ (0,
|
|
3438
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3186
3439
|
"button",
|
|
3187
3440
|
{
|
|
3188
3441
|
type: "button",
|
|
@@ -3198,17 +3451,17 @@ function Select({
|
|
|
3198
3451
|
),
|
|
3199
3452
|
document.body
|
|
3200
3453
|
) : null,
|
|
3201
|
-
error ? /* @__PURE__ */ (0,
|
|
3202
|
-
/* @__PURE__ */ (0,
|
|
3454
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "fd-field-error", children: [
|
|
3455
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3203
3456
|
error
|
|
3204
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3457
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3205
3458
|
] });
|
|
3206
3459
|
}
|
|
3207
3460
|
|
|
3208
3461
|
// src/components/forms/DatePicker.tsx
|
|
3209
|
-
var
|
|
3462
|
+
var React20 = __toESM(require("react"), 1);
|
|
3210
3463
|
var import_react_dom5 = require("react-dom");
|
|
3211
|
-
var
|
|
3464
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
3212
3465
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
3213
3466
|
var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
3214
3467
|
var iso = (d) => d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
|
|
@@ -3222,8 +3475,8 @@ var fmt = (s) => {
|
|
|
3222
3475
|
return d ? MONTHS[d.getMonth()].slice(0, 3) + " " + d.getDate() + ", " + d.getFullYear() : "";
|
|
3223
3476
|
};
|
|
3224
3477
|
function usePopPos2(open, ref, estH, estW) {
|
|
3225
|
-
const [pos, setPos] =
|
|
3226
|
-
|
|
3478
|
+
const [pos, setPos] = React20.useState(null);
|
|
3479
|
+
React20.useLayoutEffect(() => {
|
|
3227
3480
|
if (!open || !ref.current) {
|
|
3228
3481
|
setPos(null);
|
|
3229
3482
|
return;
|
|
@@ -3267,10 +3520,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3267
3520
|
const today = /* @__PURE__ */ new Date();
|
|
3268
3521
|
const sel = range ? value || {} : { start: value, end: value };
|
|
3269
3522
|
const anchor = parse(sel.start) || parse(initialMonth) || today;
|
|
3270
|
-
const [vy, setVy] =
|
|
3271
|
-
const [vm, setVm] =
|
|
3272
|
-
const [mode2, setMode] =
|
|
3273
|
-
const [hover, setHover] =
|
|
3523
|
+
const [vy, setVy] = React20.useState(anchor.getFullYear());
|
|
3524
|
+
const [vm, setVm] = React20.useState(anchor.getMonth());
|
|
3525
|
+
const [mode2, setMode] = React20.useState("days");
|
|
3526
|
+
const [hover, setHover] = React20.useState(null);
|
|
3274
3527
|
const s = parse(sel.start), e = parse(sel.end);
|
|
3275
3528
|
const hoverEnd = range && s && !e && hover ? parse(hover) : null;
|
|
3276
3529
|
const inRange = (d) => {
|
|
@@ -3307,9 +3560,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3307
3560
|
const startPad = new Date(y, m, 1).getDay();
|
|
3308
3561
|
const cells = [];
|
|
3309
3562
|
for (let i = 0; i < 42; i++) cells.push(new Date(y, m, i - startPad + 1));
|
|
3310
|
-
return /* @__PURE__ */ (0,
|
|
3311
|
-
DOW.map((d) => /* @__PURE__ */ (0,
|
|
3312
|
-
cells.map((d, i) => /* @__PURE__ */ (0,
|
|
3563
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal-grid", style: { width: months > 1 ? 252 : "auto", flex: "none" }, onMouseLeave: () => setHover(null), children: [
|
|
3564
|
+
DOW.map((d) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-cal-dow", children: d }, d)),
|
|
3565
|
+
cells.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3313
3566
|
"button",
|
|
3314
3567
|
{
|
|
3315
3568
|
type: "button",
|
|
@@ -3323,20 +3576,20 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3323
3576
|
] });
|
|
3324
3577
|
};
|
|
3325
3578
|
const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
|
|
3326
|
-
return /* @__PURE__ */ (0,
|
|
3327
|
-
/* @__PURE__ */ (0,
|
|
3328
|
-
/* @__PURE__ */ (0,
|
|
3329
|
-
/* @__PURE__ */ (0,
|
|
3579
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, children: [
|
|
3580
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal-head", children: [
|
|
3581
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("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__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-caret-left" }) }),
|
|
3582
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("button", { type: "button", className: "fd-cal-title", onClick: () => setMode(mode2 === "days" ? "months" : mode2 === "months" ? "years" : "days"), children: [
|
|
3330
3583
|
mode2 === "days" ? MONTHS[vm] + " " + vy : mode2 === "months" ? vy : vy - 5 + " \u2013 " + (vy + 6),
|
|
3331
|
-
/* @__PURE__ */ (0,
|
|
3584
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-caret-down", style: { fontSize: 10, marginLeft: 6, color: "var(--text-muted)" } })
|
|
3332
3585
|
] }),
|
|
3333
|
-
months > 1 && mode2 === "days" ? /* @__PURE__ */ (0,
|
|
3334
|
-
/* @__PURE__ */ (0,
|
|
3586
|
+
months > 1 && mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-cal-title", style: { cursor: "default", background: "none" }, children: MONTHS[nextM] + " " + nextY }) : null,
|
|
3587
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("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__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-caret-right" }) })
|
|
3335
3588
|
] }),
|
|
3336
|
-
mode2 === "days" ? /* @__PURE__ */ (0,
|
|
3589
|
+
mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { style: { display: "flex", gap: 18 }, children: [
|
|
3337
3590
|
monthGrid(vy, vm),
|
|
3338
3591
|
months > 1 ? monthGrid(nextY, nextM) : null
|
|
3339
|
-
] }) : mode2 === "months" ? /* @__PURE__ */ (0,
|
|
3592
|
+
] }) : mode2 === "months" ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "fd-cal-grid-months", children: MONTHS.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3340
3593
|
"button",
|
|
3341
3594
|
{
|
|
3342
3595
|
type: "button",
|
|
@@ -3348,7 +3601,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3348
3601
|
children: m.slice(0, 3)
|
|
3349
3602
|
},
|
|
3350
3603
|
m
|
|
3351
|
-
)) }) : /* @__PURE__ */ (0,
|
|
3604
|
+
)) }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "fd-cal-grid-months", children: Array.from({ length: 12 }, (_, i) => vy - 5 + i).map((y) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3352
3605
|
"button",
|
|
3353
3606
|
{
|
|
3354
3607
|
type: "button",
|
|
@@ -3361,8 +3614,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3361
3614
|
},
|
|
3362
3615
|
y
|
|
3363
3616
|
)) }),
|
|
3364
|
-
/* @__PURE__ */ (0,
|
|
3365
|
-
/* @__PURE__ */ (0,
|
|
3617
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal-foot", children: [
|
|
3618
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3366
3619
|
"button",
|
|
3367
3620
|
{
|
|
3368
3621
|
type: "button",
|
|
@@ -3376,8 +3629,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3376
3629
|
children: "Today"
|
|
3377
3630
|
}
|
|
3378
3631
|
),
|
|
3379
|
-
/* @__PURE__ */ (0,
|
|
3380
|
-
range && sel.start ? /* @__PURE__ */ (0,
|
|
3632
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { style: { flex: 1 } }),
|
|
3633
|
+
range && sel.start ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
3381
3634
|
fmt(sel.start),
|
|
3382
3635
|
sel.end ? " \u2192 " + fmt(sel.end) : " \u2192 pick an end"
|
|
3383
3636
|
] }) : null
|
|
@@ -3385,12 +3638,12 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3385
3638
|
] });
|
|
3386
3639
|
}
|
|
3387
3640
|
function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, className = "", style, ...rest }) {
|
|
3388
|
-
const [open, setOpen] =
|
|
3389
|
-
const rootRef =
|
|
3390
|
-
const boxRef =
|
|
3391
|
-
const popRef =
|
|
3641
|
+
const [open, setOpen] = React20.useState(false);
|
|
3642
|
+
const rootRef = React20.useRef(null);
|
|
3643
|
+
const boxRef = React20.useRef(null);
|
|
3644
|
+
const popRef = React20.useRef(null);
|
|
3392
3645
|
const pos = usePopPos2(open, boxRef, 430, range ? 600 : 316);
|
|
3393
|
-
|
|
3646
|
+
React20.useEffect(() => {
|
|
3394
3647
|
if (!open) return;
|
|
3395
3648
|
const away = (e) => {
|
|
3396
3649
|
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
@@ -3411,14 +3664,14 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3411
3664
|
const toggle = () => {
|
|
3412
3665
|
if (!disabled) setOpen(!open);
|
|
3413
3666
|
};
|
|
3414
|
-
return /* @__PURE__ */ (0,
|
|
3415
|
-
label ? /* @__PURE__ */ (0,
|
|
3667
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
3668
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("label", { className: "fd-field-label", onClick: toggle, children: [
|
|
3416
3669
|
label,
|
|
3417
|
-
required ? /* @__PURE__ */ (0,
|
|
3670
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-field-req", children: "*" }) : null
|
|
3418
3671
|
] }) : null,
|
|
3419
|
-
/* @__PURE__ */ (0,
|
|
3420
|
-
/* @__PURE__ */ (0,
|
|
3421
|
-
/* @__PURE__ */ (0,
|
|
3672
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("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: [
|
|
3673
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }) }),
|
|
3674
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3422
3675
|
"button",
|
|
3423
3676
|
{
|
|
3424
3677
|
type: "button",
|
|
@@ -3434,10 +3687,10 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3434
3687
|
children: display || placeholder || (range ? "Pick a date range" : "Pick a date")
|
|
3435
3688
|
}
|
|
3436
3689
|
),
|
|
3437
|
-
/* @__PURE__ */ (0,
|
|
3690
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-select-caret", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
|
|
3438
3691
|
] }),
|
|
3439
3692
|
open && pos ? (0, import_react_dom5.createPortal)(
|
|
3440
|
-
/* @__PURE__ */ (0,
|
|
3693
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "fd-pop" + (pos.up ? " is-up" : ""), ref: popRef, style: popStyle2(pos, { width: "max-content", minWidth: 0, zIndex: 130 }), children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3441
3694
|
Calendar,
|
|
3442
3695
|
{
|
|
3443
3696
|
range,
|
|
@@ -3451,21 +3704,21 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3451
3704
|
) }),
|
|
3452
3705
|
document.body
|
|
3453
3706
|
) : null,
|
|
3454
|
-
error ? /* @__PURE__ */ (0,
|
|
3455
|
-
/* @__PURE__ */ (0,
|
|
3707
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "fd-field-error", children: [
|
|
3708
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3456
3709
|
error
|
|
3457
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3710
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3458
3711
|
] });
|
|
3459
3712
|
}
|
|
3460
3713
|
|
|
3461
3714
|
// src/components/forms/TimePicker.tsx
|
|
3462
|
-
var
|
|
3715
|
+
var React21 = __toESM(require("react"), 1);
|
|
3463
3716
|
var import_react_dom6 = require("react-dom");
|
|
3464
|
-
var
|
|
3717
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
3465
3718
|
var pad = (n) => String(n).padStart(2, "0");
|
|
3466
3719
|
function usePopPos3(open, ref, estH, estW) {
|
|
3467
|
-
const [pos, setPos] =
|
|
3468
|
-
|
|
3720
|
+
const [pos, setPos] = React21.useState(null);
|
|
3721
|
+
React21.useLayoutEffect(() => {
|
|
3469
3722
|
if (!open || !ref.current) {
|
|
3470
3723
|
setPos(null);
|
|
3471
3724
|
return;
|
|
@@ -3511,9 +3764,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3511
3764
|
if (isNaN(m)) m = 0;
|
|
3512
3765
|
const pm = h24 >= 12;
|
|
3513
3766
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
3514
|
-
const [mode2, setMode] =
|
|
3515
|
-
const faceRef =
|
|
3516
|
-
const dragging =
|
|
3767
|
+
const [mode2, setMode] = React21.useState("h");
|
|
3768
|
+
const faceRef = React21.useRef(null);
|
|
3769
|
+
const dragging = React21.useRef(false);
|
|
3517
3770
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
3518
3771
|
const R = 108, NR = 80;
|
|
3519
3772
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -3548,12 +3801,12 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3548
3801
|
};
|
|
3549
3802
|
const handAngle = mode2 === "h" ? h12 % 12 * 30 : m * 6;
|
|
3550
3803
|
const minuteOff = mode2 === "m" && m % 5 !== 0;
|
|
3551
|
-
return /* @__PURE__ */ (0,
|
|
3552
|
-
/* @__PURE__ */ (0,
|
|
3553
|
-
/* @__PURE__ */ (0,
|
|
3554
|
-
/* @__PURE__ */ (0,
|
|
3555
|
-
/* @__PURE__ */ (0,
|
|
3556
|
-
/* @__PURE__ */ (0,
|
|
3804
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { style: { padding: "4px 14px 14px" }, children: [
|
|
3805
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-clock-digits", children: [
|
|
3806
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", className: "fd-clock-digit" + (mode2 === "h" ? " is-active" : ""), onClick: () => setMode("h"), children: pad(h12) }),
|
|
3807
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { style: { fontSize: 24, fontWeight: 700, color: "var(--text-muted)" }, children: ":" }),
|
|
3808
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", className: "fd-clock-digit" + (mode2 === "m" ? " is-active" : ""), onClick: () => setMode("m"), children: pad(m) }),
|
|
3809
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-stack", style: { gap: 3, marginLeft: 8 }, children: ["AM", "PM"].map((ap) => /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3557
3810
|
"button",
|
|
3558
3811
|
{
|
|
3559
3812
|
type: "button",
|
|
@@ -3564,13 +3817,13 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3564
3817
|
ap
|
|
3565
3818
|
)) })
|
|
3566
3819
|
] }),
|
|
3567
|
-
/* @__PURE__ */ (0,
|
|
3568
|
-
/* @__PURE__ */ (0,
|
|
3569
|
-
/* @__PURE__ */ (0,
|
|
3570
|
-
minuteOff ? /* @__PURE__ */ (0,
|
|
3820
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-clock", ref: faceRef, onPointerDown: down, onPointerMove: move, onPointerUp: upH, children: [
|
|
3821
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-clock-hand", style: { height: NR - (minuteOff ? 14 : 16), transform: "translateX(-50%) rotate(" + handAngle + "deg)", bottom: "50%" } }),
|
|
3822
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-clock-pivot" }),
|
|
3823
|
+
minuteOff ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("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,
|
|
3571
3824
|
nums.map((n) => {
|
|
3572
3825
|
const a = angleOf(n) * Math.PI / 180;
|
|
3573
|
-
return /* @__PURE__ */ (0,
|
|
3826
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3574
3827
|
"span",
|
|
3575
3828
|
{
|
|
3576
3829
|
className: "fd-clock-num" + (n === selNum || mode2 === "m" && n === Math.round(m / 5) * 5 % 60 && m % 5 === 0 ? " is-sel" : ""),
|
|
@@ -3581,16 +3834,16 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3581
3834
|
);
|
|
3582
3835
|
})
|
|
3583
3836
|
] }),
|
|
3584
|
-
/* @__PURE__ */ (0,
|
|
3837
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "fd-row", style: { justifyContent: "center", gap: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-body-sm fd-muted", children: mode2 === "h" ? "Pick the hour \u2014 drag or tap" : "Now the minutes" }) })
|
|
3585
3838
|
] });
|
|
3586
3839
|
}
|
|
3587
3840
|
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", className = "", style }) {
|
|
3588
|
-
const [open, setOpen] =
|
|
3589
|
-
const rootRef =
|
|
3590
|
-
const boxRef =
|
|
3591
|
-
const popRef =
|
|
3841
|
+
const [open, setOpen] = React21.useState(false);
|
|
3842
|
+
const rootRef = React21.useRef(null);
|
|
3843
|
+
const boxRef = React21.useRef(null);
|
|
3844
|
+
const popRef = React21.useRef(null);
|
|
3592
3845
|
const pos = usePopPos3(open, boxRef, 420, 262);
|
|
3593
|
-
|
|
3846
|
+
React21.useEffect(() => {
|
|
3594
3847
|
if (!open) return;
|
|
3595
3848
|
const away = (e) => {
|
|
3596
3849
|
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
@@ -3615,14 +3868,14 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
3615
3868
|
const toggle = () => {
|
|
3616
3869
|
if (!disabled) setOpen(!open);
|
|
3617
3870
|
};
|
|
3618
|
-
return /* @__PURE__ */ (0,
|
|
3619
|
-
label ? /* @__PURE__ */ (0,
|
|
3871
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
3872
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("label", { className: "fd-field-label", onClick: toggle, children: [
|
|
3620
3873
|
label,
|
|
3621
|
-
required ? /* @__PURE__ */ (0,
|
|
3874
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-field-req", children: "*" }) : null
|
|
3622
3875
|
] }) : null,
|
|
3623
|
-
/* @__PURE__ */ (0,
|
|
3624
|
-
/* @__PURE__ */ (0,
|
|
3625
|
-
/* @__PURE__ */ (0,
|
|
3876
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("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: [
|
|
3877
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-clock", "aria-hidden": "true" }) }),
|
|
3878
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3626
3879
|
"button",
|
|
3627
3880
|
{
|
|
3628
3881
|
type: "button",
|
|
@@ -3637,13 +3890,13 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
3637
3890
|
children: disp() || placeholder
|
|
3638
3891
|
}
|
|
3639
3892
|
),
|
|
3640
|
-
/* @__PURE__ */ (0,
|
|
3893
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-select-caret", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
|
|
3641
3894
|
] }),
|
|
3642
3895
|
open && pos ? (0, import_react_dom6.createPortal)(
|
|
3643
|
-
/* @__PURE__ */ (0,
|
|
3644
|
-
/* @__PURE__ */ (0,
|
|
3645
|
-
/* @__PURE__ */ (0,
|
|
3646
|
-
/* @__PURE__ */ (0,
|
|
3896
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-pop" + (pos.up ? " is-up" : ""), ref: popRef, style: popStyle3(pos, { width: 262, minWidth: 0, zIndex: 130 }), children: [
|
|
3897
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ClockFace, { value: value || "09:00", onChange: (v) => onChange && onChange({ target: { value: v } }) }),
|
|
3898
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-cal-foot", style: { margin: "0 14px 12px", paddingTop: 10 }, children: [
|
|
3899
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3647
3900
|
"button",
|
|
3648
3901
|
{
|
|
3649
3902
|
type: "button",
|
|
@@ -3656,22 +3909,22 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
3656
3909
|
children: "Now"
|
|
3657
3910
|
}
|
|
3658
3911
|
),
|
|
3659
|
-
/* @__PURE__ */ (0,
|
|
3660
|
-
/* @__PURE__ */ (0,
|
|
3912
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { style: { flex: 1 } }),
|
|
3913
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", onClick: () => setOpen(false), children: "Done" })
|
|
3661
3914
|
] })
|
|
3662
3915
|
] }),
|
|
3663
3916
|
document.body
|
|
3664
3917
|
) : null,
|
|
3665
|
-
error ? /* @__PURE__ */ (0,
|
|
3666
|
-
/* @__PURE__ */ (0,
|
|
3918
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "fd-field-error", children: [
|
|
3919
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3667
3920
|
error
|
|
3668
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3921
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3669
3922
|
] });
|
|
3670
3923
|
}
|
|
3671
3924
|
|
|
3672
3925
|
// src/components/forms/Slider.tsx
|
|
3673
|
-
var
|
|
3674
|
-
var
|
|
3926
|
+
var React22 = __toESM(require("react"), 1);
|
|
3927
|
+
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
3675
3928
|
function Slider({
|
|
3676
3929
|
label,
|
|
3677
3930
|
min = 0,
|
|
@@ -3685,18 +3938,18 @@ function Slider({
|
|
|
3685
3938
|
className = "",
|
|
3686
3939
|
...rest
|
|
3687
3940
|
}) {
|
|
3688
|
-
const [dragging, setDragging] =
|
|
3941
|
+
const [dragging, setDragging] = React22.useState(false);
|
|
3689
3942
|
const v = value === void 0 ? min : Number(value);
|
|
3690
3943
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
3691
|
-
return /* @__PURE__ */ (0,
|
|
3692
|
-
label ? /* @__PURE__ */ (0,
|
|
3693
|
-
/* @__PURE__ */ (0,
|
|
3694
|
-
/* @__PURE__ */ (0,
|
|
3944
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
|
|
3945
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
3946
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-field-label", children: label }),
|
|
3947
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: format(v) })
|
|
3695
3948
|
] }) : null,
|
|
3696
|
-
/* @__PURE__ */ (0,
|
|
3697
|
-
/* @__PURE__ */ (0,
|
|
3698
|
-
showChip && dragging ? /* @__PURE__ */ (0,
|
|
3699
|
-
/* @__PURE__ */ (0,
|
|
3949
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "fd-slider", children: [
|
|
3950
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
3951
|
+
showChip && dragging ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-slider-chip", style: { left: pct + "%" }, children: format(v) }) : null,
|
|
3952
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3700
3953
|
"input",
|
|
3701
3954
|
{
|
|
3702
3955
|
type: "range",
|
|
@@ -3713,13 +3966,13 @@ function Slider({
|
|
|
3713
3966
|
}
|
|
3714
3967
|
)
|
|
3715
3968
|
] }),
|
|
3716
|
-
help ? /* @__PURE__ */ (0,
|
|
3969
|
+
help ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3717
3970
|
] });
|
|
3718
3971
|
}
|
|
3719
3972
|
|
|
3720
3973
|
// src/components/forms/RangeSlider.tsx
|
|
3721
|
-
var
|
|
3722
|
-
var
|
|
3974
|
+
var React23 = __toESM(require("react"), 1);
|
|
3975
|
+
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
3723
3976
|
function RangeSlider({
|
|
3724
3977
|
label,
|
|
3725
3978
|
min = 0,
|
|
@@ -3738,9 +3991,9 @@ function RangeSlider({
|
|
|
3738
3991
|
}) {
|
|
3739
3992
|
const fmt2 = format || ((v) => String(v));
|
|
3740
3993
|
const [a, b] = value || [min, max];
|
|
3741
|
-
const [drag, setDrag] =
|
|
3742
|
-
const [focus, setFocus] =
|
|
3743
|
-
const railRef =
|
|
3994
|
+
const [drag, setDrag] = React23.useState(null);
|
|
3995
|
+
const [focus, setFocus] = React23.useState(null);
|
|
3996
|
+
const railRef = React23.useRef(null);
|
|
3744
3997
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
3745
3998
|
const clampPair = (i, v) => {
|
|
3746
3999
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -3755,7 +4008,7 @@ function RangeSlider({
|
|
|
3755
4008
|
const r = railRef.current.getBoundingClientRect();
|
|
3756
4009
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
3757
4010
|
};
|
|
3758
|
-
|
|
4011
|
+
React23.useEffect(() => {
|
|
3759
4012
|
if (drag === null) return;
|
|
3760
4013
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
3761
4014
|
const upH = () => setDrag(null);
|
|
@@ -3776,7 +4029,7 @@ function RangeSlider({
|
|
|
3776
4029
|
};
|
|
3777
4030
|
const thin = S.length > 7 ? Math.ceil(S.length / 5) : 1;
|
|
3778
4031
|
const pair = value || [S[0].value, S[S.length - 1].value];
|
|
3779
|
-
return /* @__PURE__ */ (0,
|
|
4032
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3780
4033
|
RangeSlider,
|
|
3781
4034
|
{
|
|
3782
4035
|
...rest,
|
|
@@ -3824,23 +4077,23 @@ function RangeSlider({
|
|
|
3824
4077
|
};
|
|
3825
4078
|
const showChip = (i) => drag === i || focus === i;
|
|
3826
4079
|
const hasLabels = marks.some((m) => m.label);
|
|
3827
|
-
return /* @__PURE__ */ (0,
|
|
3828
|
-
label ? /* @__PURE__ */ (0,
|
|
3829
|
-
/* @__PURE__ */ (0,
|
|
3830
|
-
/* @__PURE__ */ (0,
|
|
4080
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), ...rest, children: [
|
|
4081
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
4082
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-field-label", children: label }),
|
|
4083
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: [
|
|
3831
4084
|
fmt2(a),
|
|
3832
4085
|
" \u2013 ",
|
|
3833
4086
|
fmt2(b)
|
|
3834
4087
|
] })
|
|
3835
4088
|
] }) : null,
|
|
3836
|
-
/* @__PURE__ */ (0,
|
|
3837
|
-
/* @__PURE__ */ (0,
|
|
3838
|
-
/* @__PURE__ */ (0,
|
|
3839
|
-
marks.map((m) => /* @__PURE__ */ (0,
|
|
3840
|
-
/* @__PURE__ */ (0,
|
|
3841
|
-
m.label ? /* @__PURE__ */ (0,
|
|
4089
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
|
|
4090
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-rail", ref: railRef }),
|
|
4091
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
|
|
4092
|
+
marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React23.Fragment, { children: [
|
|
4093
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
|
|
4094
|
+
m.label ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
|
|
3842
4095
|
] }, m.value)),
|
|
3843
|
-
[a, b].map((v, i) => /* @__PURE__ */ (0,
|
|
4096
|
+
[a, b].map((v, i) => /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3844
4097
|
"span",
|
|
3845
4098
|
{
|
|
3846
4099
|
className: "fd-range-thumb" + (drag === i ? " is-drag" : ""),
|
|
@@ -3855,18 +4108,18 @@ function RangeSlider({
|
|
|
3855
4108
|
onKeyDown: key(i),
|
|
3856
4109
|
onFocus: () => setFocus(i),
|
|
3857
4110
|
onBlur: () => setFocus(null),
|
|
3858
|
-
children: /* @__PURE__ */ (0,
|
|
4111
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-chip", style: { opacity: showChip(i) ? 1 : void 0 }, children: fmt2(v) })
|
|
3859
4112
|
},
|
|
3860
4113
|
i
|
|
3861
4114
|
))
|
|
3862
4115
|
] }),
|
|
3863
|
-
help ? /* @__PURE__ */ (0,
|
|
4116
|
+
help ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3864
4117
|
] });
|
|
3865
4118
|
}
|
|
3866
4119
|
|
|
3867
4120
|
// src/components/forms/Dropzone.tsx
|
|
3868
|
-
var
|
|
3869
|
-
var
|
|
4121
|
+
var React24 = __toESM(require("react"), 1);
|
|
4122
|
+
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
3870
4123
|
function Dropzone({
|
|
3871
4124
|
onFiles,
|
|
3872
4125
|
onReject,
|
|
@@ -3880,8 +4133,8 @@ function Dropzone({
|
|
|
3880
4133
|
className = "",
|
|
3881
4134
|
style
|
|
3882
4135
|
}) {
|
|
3883
|
-
const [over, setOver] =
|
|
3884
|
-
const depth =
|
|
4136
|
+
const [over, setOver] = React24.useState(false);
|
|
4137
|
+
const depth = React24.useRef(0);
|
|
3885
4138
|
const has = (e) => {
|
|
3886
4139
|
const dt = e.dataTransfer;
|
|
3887
4140
|
if (!dt) return false;
|
|
@@ -3911,7 +4164,7 @@ function Dropzone({
|
|
|
3911
4164
|
if (rejected.length && onReject) onReject(rejected);
|
|
3912
4165
|
if (accepted.length && onFiles) onFiles(accepted);
|
|
3913
4166
|
};
|
|
3914
|
-
return /* @__PURE__ */ (0,
|
|
4167
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
3915
4168
|
"div",
|
|
3916
4169
|
{
|
|
3917
4170
|
className: ["fd-dropzone", over ? "is-over" : "", className].filter(Boolean).join(" "),
|
|
@@ -3922,10 +4175,10 @@ function Dropzone({
|
|
|
3922
4175
|
onDrop: drop,
|
|
3923
4176
|
children: [
|
|
3924
4177
|
children,
|
|
3925
|
-
over ? /* @__PURE__ */ (0,
|
|
3926
|
-
/* @__PURE__ */ (0,
|
|
3927
|
-
/* @__PURE__ */ (0,
|
|
3928
|
-
hint ? /* @__PURE__ */ (0,
|
|
4178
|
+
over ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "fd-dropzone-veil", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "fd-dropzone-card", children: [
|
|
4179
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-tray-arrow-down" }),
|
|
4180
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-dropzone-label", children: label }),
|
|
4181
|
+
hint ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-dropzone-hint", children: hint }) : null
|
|
3929
4182
|
] }) }) : null
|
|
3930
4183
|
]
|
|
3931
4184
|
}
|
|
@@ -3943,9 +4196,9 @@ function FilePickButton({
|
|
|
3943
4196
|
className = "",
|
|
3944
4197
|
children
|
|
3945
4198
|
}) {
|
|
3946
|
-
const ref =
|
|
3947
|
-
return /* @__PURE__ */ (0,
|
|
3948
|
-
/* @__PURE__ */ (0,
|
|
4199
|
+
const ref = React24.useRef(null);
|
|
4200
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(React24.Fragment, { children: [
|
|
4201
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3949
4202
|
"button",
|
|
3950
4203
|
{
|
|
3951
4204
|
type: "button",
|
|
@@ -3954,10 +4207,10 @@ function FilePickButton({
|
|
|
3954
4207
|
"aria-label": label,
|
|
3955
4208
|
title: label,
|
|
3956
4209
|
onClick: () => ref.current && ref.current.click(),
|
|
3957
|
-
children: children != null ? children : /* @__PURE__ */ (0,
|
|
4210
|
+
children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-" + icon, "aria-hidden": "true" })
|
|
3958
4211
|
}
|
|
3959
4212
|
),
|
|
3960
|
-
/* @__PURE__ */ (0,
|
|
4213
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3961
4214
|
"input",
|
|
3962
4215
|
{
|
|
3963
4216
|
ref,
|
|
@@ -3977,10 +4230,10 @@ function FilePickButton({
|
|
|
3977
4230
|
}
|
|
3978
4231
|
function useStagedFiles(upload, opts) {
|
|
3979
4232
|
const o = opts || {};
|
|
3980
|
-
const [items, setItems] =
|
|
3981
|
-
const controllers =
|
|
4233
|
+
const [items, setItems] = React24.useState([]);
|
|
4234
|
+
const controllers = React24.useRef({});
|
|
3982
4235
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
3983
|
-
const run =
|
|
4236
|
+
const run = React24.useCallback((att) => {
|
|
3984
4237
|
if (!upload) return;
|
|
3985
4238
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
3986
4239
|
controllers.current[att.id] = ac;
|
|
@@ -3997,14 +4250,14 @@ function useStagedFiles(upload, opts) {
|
|
|
3997
4250
|
delete controllers.current[att.id];
|
|
3998
4251
|
});
|
|
3999
4252
|
}, [upload]);
|
|
4000
|
-
const add =
|
|
4253
|
+
const add = React24.useCallback((files) => {
|
|
4001
4254
|
if (!upload) return [];
|
|
4002
4255
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
4003
4256
|
setItems((list) => list.concat(atts));
|
|
4004
4257
|
atts.forEach(run);
|
|
4005
4258
|
return atts;
|
|
4006
4259
|
}, [upload, run]);
|
|
4007
|
-
const remove =
|
|
4260
|
+
const remove = React24.useCallback((att) => {
|
|
4008
4261
|
const ac = controllers.current[att.id];
|
|
4009
4262
|
if (ac) {
|
|
4010
4263
|
try {
|
|
@@ -4015,10 +4268,10 @@ function useStagedFiles(upload, opts) {
|
|
|
4015
4268
|
}
|
|
4016
4269
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
4017
4270
|
}, []);
|
|
4018
|
-
const retry =
|
|
4271
|
+
const retry = React24.useCallback((att) => {
|
|
4019
4272
|
run(att);
|
|
4020
4273
|
}, [run]);
|
|
4021
|
-
const clear =
|
|
4274
|
+
const clear = React24.useCallback(() => {
|
|
4022
4275
|
Object.values(controllers.current).forEach((ac) => {
|
|
4023
4276
|
try {
|
|
4024
4277
|
ac && ac.abort();
|
|
@@ -4034,7 +4287,7 @@ function useStagedFiles(upload, opts) {
|
|
|
4034
4287
|
var DropzoneKit = { useStagedFiles };
|
|
4035
4288
|
|
|
4036
4289
|
// src/components/forms/FileGrid.tsx
|
|
4037
|
-
var
|
|
4290
|
+
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
4038
4291
|
var truncateMiddle = (name, max = 34) => {
|
|
4039
4292
|
if (!name || name.length <= max) return name;
|
|
4040
4293
|
const ext = /\.[A-Za-z0-9]+$/.exec(name);
|
|
@@ -4043,7 +4296,7 @@ var truncateMiddle = (name, max = 34) => {
|
|
|
4043
4296
|
return head + "\u2026" + tail;
|
|
4044
4297
|
};
|
|
4045
4298
|
function Progress({ value }) {
|
|
4046
|
-
return /* @__PURE__ */ (0,
|
|
4299
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-file-prog", role: "progressbar", "aria-valuenow": Math.round(value), "aria-valuemin": 0, "aria-valuemax": 100, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-file-prog-fill", style: { width: Math.max(4, Math.min(100, value)) + "%" } }) });
|
|
4047
4300
|
}
|
|
4048
4301
|
function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false, className = "" }) {
|
|
4049
4302
|
if (!file) return null;
|
|
@@ -4052,8 +4305,8 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
4052
4305
|
const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
|
|
4053
4306
|
const meta = file.meta || (file.size ? formatBytes(file.size) : "");
|
|
4054
4307
|
const clickable = !!onOpen && !uploading;
|
|
4055
|
-
return /* @__PURE__ */ (0,
|
|
4056
|
-
/* @__PURE__ */ (0,
|
|
4308
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: ["fd-file", compact3 ? "is-compact" : "", file.error ? "is-error" : "", uploading ? "is-uploading" : "", className].filter(Boolean).join(" "), children: [
|
|
4309
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
4057
4310
|
"button",
|
|
4058
4311
|
{
|
|
4059
4312
|
type: "button",
|
|
@@ -4062,16 +4315,16 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
4062
4315
|
onClick: clickable ? () => onOpen(file) : void 0,
|
|
4063
4316
|
title: file.name + (meta ? " \xB7 " + meta : ""),
|
|
4064
4317
|
children: [
|
|
4065
|
-
/* @__PURE__ */ (0,
|
|
4066
|
-
thumb ? /* @__PURE__ */ (0,
|
|
4067
|
-
(file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0,
|
|
4318
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-file-icon", children: [
|
|
4319
|
+
thumb ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("img", { src: thumb, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
|
|
4320
|
+
(file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-play fd-file-play", "aria-hidden": "true" }) : null
|
|
4068
4321
|
] }),
|
|
4069
|
-
/* @__PURE__ */ (0,
|
|
4070
|
-
/* @__PURE__ */ (0,
|
|
4071
|
-
/* @__PURE__ */ (0,
|
|
4072
|
-
/* @__PURE__ */ (0,
|
|
4322
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-file-text", children: [
|
|
4323
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-file-name", children: truncateMiddle(file.name, compact3 ? 26 : 40) }),
|
|
4324
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-file-meta", children: file.error ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-file-err", children: [
|
|
4325
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
4073
4326
|
file.error
|
|
4074
|
-
] }) : uploading ? /* @__PURE__ */ (0,
|
|
4327
|
+
] }) : uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-tabular", children: [
|
|
4075
4328
|
Math.round(file.progress),
|
|
4076
4329
|
"% uploaded"
|
|
4077
4330
|
] }) : meta })
|
|
@@ -4079,29 +4332,29 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
4079
4332
|
]
|
|
4080
4333
|
}
|
|
4081
4334
|
),
|
|
4082
|
-
uploading ? /* @__PURE__ */ (0,
|
|
4083
|
-
file.error && onRetry ? /* @__PURE__ */ (0,
|
|
4084
|
-
onRemove ? /* @__PURE__ */ (0,
|
|
4335
|
+
uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Progress, { value: file.progress }) : null,
|
|
4336
|
+
file.error && onRetry ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("button", { type: "button", className: "fd-file-act", onClick: () => onRetry(file), "aria-label": "Retry upload of " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
4337
|
+
onRemove ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("button", { type: "button", className: "fd-file-act", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
4085
4338
|
] });
|
|
4086
4339
|
}
|
|
4087
4340
|
function FileTile({ file, onOpen, onRemove, maxHeight = 200, className = "" }) {
|
|
4088
4341
|
if (!file) return null;
|
|
4089
4342
|
const src = file.thumb && file.thumb.url || file.blobUrl || file.url;
|
|
4090
4343
|
const uploading = file.progress != null && file.progress < 100 && !file.error;
|
|
4091
|
-
return /* @__PURE__ */ (0,
|
|
4092
|
-
/* @__PURE__ */ (0,
|
|
4093
|
-
uploading ? /* @__PURE__ */ (0,
|
|
4094
|
-
file.error ? /* @__PURE__ */ (0,
|
|
4095
|
-
/* @__PURE__ */ (0,
|
|
4344
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("figure", { className: ["fd-tile", uploading ? "is-uploading" : "", file.error ? "is-error" : "", className].filter(Boolean).join(" "), children: [
|
|
4345
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("button", { type: "button", className: "fd-tile-btn", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen, children: src ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("img", { src, alt: file.name || "", style: { maxHeight }, loading: "lazy" }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-tile-fallback", children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }) }) }),
|
|
4346
|
+
uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Progress, { value: file.progress }) : null,
|
|
4347
|
+
file.error ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("figcaption", { className: "fd-tile-err", children: [
|
|
4348
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
4096
4349
|
file.error
|
|
4097
4350
|
] }) : null,
|
|
4098
|
-
onRemove ? /* @__PURE__ */ (0,
|
|
4351
|
+
onRemove ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("button", { type: "button", className: "fd-tile-x", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
4099
4352
|
] });
|
|
4100
4353
|
}
|
|
4101
4354
|
function FileStrip({ files = [], size = 68, onOpen, onRemove, onRetry, className = "" }) {
|
|
4102
4355
|
const list = files.filter(Boolean);
|
|
4103
4356
|
if (!list.length) return null;
|
|
4104
|
-
return /* @__PURE__ */ (0,
|
|
4357
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: ["fd-filestrip", className].filter(Boolean).join(" "), style: { "--fd-cell": size + "px" }, children: list.map((f) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(FileCell, { file: f, onOpen, onRemove, onRetry }, f.id || f.name)) });
|
|
4105
4358
|
}
|
|
4106
4359
|
var shortName = (name, keep = 5) => {
|
|
4107
4360
|
const s = String(name || "file");
|
|
@@ -4115,19 +4368,19 @@ function FileCell({ file, onOpen, onRemove, onRetry }) {
|
|
|
4115
4368
|
const image = isImage(file.mime, file.name);
|
|
4116
4369
|
const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
|
|
4117
4370
|
const label = file.name + (file.size ? " \xB7 " + formatBytes(file.size) : "");
|
|
4118
|
-
return /* @__PURE__ */ (0,
|
|
4119
|
-
/* @__PURE__ */ (0,
|
|
4120
|
-
thumb ? /* @__PURE__ */ (0,
|
|
4121
|
-
/* @__PURE__ */ (0,
|
|
4122
|
-
/* @__PURE__ */ (0,
|
|
4123
|
-
/* @__PURE__ */ (0,
|
|
4371
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: ["fd-cell", file.error ? "is-error" : "", uploading ? "is-uploading" : ""].filter(Boolean).join(" "), title: file.error ? file.name + " \u2014 " + file.error : label, children: [
|
|
4372
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("button", { type: "button", className: "fd-cell-main", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen || uploading, "aria-label": "Open " + file.name, children: [
|
|
4373
|
+
thumb ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("img", { src: thumb, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-cell-doc", children: [
|
|
4374
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
|
|
4375
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-cell-name", children: shortName(file.name) }),
|
|
4376
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-cell-size", children: file.meta || formatBytes(file.size) })
|
|
4124
4377
|
] }),
|
|
4125
|
-
(file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0,
|
|
4378
|
+
(file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-play fd-cell-play", "aria-hidden": "true" }) : null
|
|
4126
4379
|
] }),
|
|
4127
|
-
uploading ? /* @__PURE__ */ (0,
|
|
4128
|
-
file.error ? /* @__PURE__ */ (0,
|
|
4129
|
-
file.error && onRetry ? /* @__PURE__ */ (0,
|
|
4130
|
-
onRemove ? /* @__PURE__ */ (0,
|
|
4380
|
+
uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Progress, { value: file.progress }) : null,
|
|
4381
|
+
file.error ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-cell-err", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-warning-circle" }) }) : null,
|
|
4382
|
+
file.error && onRetry ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("button", { type: "button", className: "fd-cell-x is-retry", onClick: () => onRetry(file), "aria-label": "Retry upload of " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
4383
|
+
onRemove ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("button", { type: "button", className: "fd-cell-x", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
4131
4384
|
] });
|
|
4132
4385
|
}
|
|
4133
4386
|
function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeight = 200, compact: compact3 = false, className = "" }) {
|
|
@@ -4135,15 +4388,15 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
4135
4388
|
if (!list.length) return null;
|
|
4136
4389
|
const pics = tiles ? list.filter((f) => isImage(f.mime, f.name)) : [];
|
|
4137
4390
|
const rest = list.filter((f) => pics.indexOf(f) === -1);
|
|
4138
|
-
return /* @__PURE__ */ (0,
|
|
4139
|
-
pics.length ? /* @__PURE__ */ (0,
|
|
4140
|
-
rest.length ? /* @__PURE__ */ (0,
|
|
4391
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: ["fd-filegrid", className].filter(Boolean).join(" "), children: [
|
|
4392
|
+
pics.length ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "fd-filegrid-tiles", children: pics.map((f) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(FileTile, { file: f, onOpen, onRemove, maxHeight }, f.id || f.name)) }) : null,
|
|
4393
|
+
rest.length ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "fd-filegrid-chips", children: rest.map((f) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(FileChip, { file: f, onOpen, onRemove, onRetry, compact: compact3 }, f.id || f.name)) }) : null
|
|
4141
4394
|
] });
|
|
4142
4395
|
}
|
|
4143
4396
|
|
|
4144
4397
|
// src/components/forms/MarkdownEditor.tsx
|
|
4145
|
-
var
|
|
4146
|
-
var
|
|
4398
|
+
var React25 = __toESM(require("react"), 1);
|
|
4399
|
+
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
4147
4400
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
4148
4401
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
4149
4402
|
function inlineParts(text) {
|
|
@@ -4356,7 +4609,7 @@ function syncDom(root, value) {
|
|
|
4356
4609
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
4357
4610
|
}
|
|
4358
4611
|
var LIST_CONT = RE_LI;
|
|
4359
|
-
var MarkdownEditor =
|
|
4612
|
+
var MarkdownEditor = React25.forwardRef(function MarkdownEditor2({
|
|
4360
4613
|
value = "",
|
|
4361
4614
|
onChange,
|
|
4362
4615
|
onSubmit,
|
|
@@ -4375,10 +4628,10 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4375
4628
|
className = "",
|
|
4376
4629
|
id
|
|
4377
4630
|
}, ref) {
|
|
4378
|
-
const boxRef =
|
|
4379
|
-
const composing =
|
|
4380
|
-
const pendingCaret =
|
|
4381
|
-
|
|
4631
|
+
const boxRef = React25.useRef(null);
|
|
4632
|
+
const composing = React25.useRef(false);
|
|
4633
|
+
const pendingCaret = React25.useRef(null);
|
|
4634
|
+
React25.useLayoutEffect(() => {
|
|
4382
4635
|
const root = boxRef.current;
|
|
4383
4636
|
if (!root || composing.current) return;
|
|
4384
4637
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -4387,7 +4640,7 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4387
4640
|
pendingCaret.current = null;
|
|
4388
4641
|
if (active && caret != null) placeCaret(root, caret);
|
|
4389
4642
|
}, [value]);
|
|
4390
|
-
|
|
4643
|
+
React25.useEffect(() => {
|
|
4391
4644
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
4392
4645
|
}, [autoFocus]);
|
|
4393
4646
|
const caretNow = () => {
|
|
@@ -4454,7 +4707,7 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4454
4707
|
api.replaceRange(from, to, next, from + next.length);
|
|
4455
4708
|
}
|
|
4456
4709
|
};
|
|
4457
|
-
|
|
4710
|
+
React25.useImperativeHandle(ref, () => api);
|
|
4458
4711
|
function detect(text, caret) {
|
|
4459
4712
|
if (!onTrigger) return;
|
|
4460
4713
|
const upto = text.slice(0, caret);
|
|
@@ -4567,8 +4820,8 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4567
4820
|
api.replaceRange(s.start, s.end, text.replace(/\r\n?/g, "\n"));
|
|
4568
4821
|
};
|
|
4569
4822
|
const lh = 1.55;
|
|
4570
|
-
return /* @__PURE__ */ (0,
|
|
4571
|
-
/* @__PURE__ */ (0,
|
|
4823
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: ["fd-rme-wrap", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "), children: [
|
|
4824
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4572
4825
|
"div",
|
|
4573
4826
|
{
|
|
4574
4827
|
ref: boxRef,
|
|
@@ -4601,15 +4854,15 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4601
4854
|
}
|
|
4602
4855
|
}
|
|
4603
4856
|
),
|
|
4604
|
-
!value ? /* @__PURE__ */ (0,
|
|
4857
|
+
!value ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-rme-ph", "aria-hidden": "true", children: placeholder }) : null
|
|
4605
4858
|
] });
|
|
4606
4859
|
});
|
|
4607
4860
|
|
|
4608
4861
|
// src/components/platform/AccountMenu.tsx
|
|
4609
|
-
var
|
|
4862
|
+
var React27 = __toESM(require("react"), 1);
|
|
4610
4863
|
|
|
4611
4864
|
// src/kits/session.ts
|
|
4612
|
-
var
|
|
4865
|
+
var React26 = __toESM(require("react"), 1);
|
|
4613
4866
|
var PERMISSION_CATALOG = [
|
|
4614
4867
|
{ group: "Plans", items: [
|
|
4615
4868
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -6176,8 +6429,8 @@ function roadmap(overrides) {
|
|
|
6176
6429
|
};
|
|
6177
6430
|
}
|
|
6178
6431
|
function useSession() {
|
|
6179
|
-
const [s, setS] =
|
|
6180
|
-
|
|
6432
|
+
const [s, setS] = React26.useState(getSession);
|
|
6433
|
+
React26.useEffect(() => subscribe(setS), []);
|
|
6181
6434
|
return s;
|
|
6182
6435
|
}
|
|
6183
6436
|
var SessionKit = {
|
|
@@ -6210,7 +6463,7 @@ var SessionKit = {
|
|
|
6210
6463
|
};
|
|
6211
6464
|
|
|
6212
6465
|
// src/components/platform/AccountMenu.tsx
|
|
6213
|
-
var
|
|
6466
|
+
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
6214
6467
|
var DEFAULT_LINKS = [
|
|
6215
6468
|
{ id: "profile", label: "Your profile", icon: "user-circle", href: "../admin/index.html#profile" },
|
|
6216
6469
|
{ id: "preferences", label: "Preferences", icon: "sliders-horizontal", href: "../admin/index.html#preferences" }
|
|
@@ -6221,7 +6474,7 @@ var DEFAULT_ADMIN_LINKS = [
|
|
|
6221
6474
|
{ id: "flags", label: "Feature flags", icon: "toggle-right", href: "../admin/index.html#flags", perm: "flags.manage" }
|
|
6222
6475
|
];
|
|
6223
6476
|
function Item({ item, onPick }) {
|
|
6224
|
-
return /* @__PURE__ */ (0,
|
|
6477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
|
|
6225
6478
|
"button",
|
|
6226
6479
|
{
|
|
6227
6480
|
type: "button",
|
|
@@ -6229,9 +6482,9 @@ function Item({ item, onPick }) {
|
|
|
6229
6482
|
className: "fd-acct-item",
|
|
6230
6483
|
onClick: () => onPick(item),
|
|
6231
6484
|
children: [
|
|
6232
|
-
/* @__PURE__ */ (0,
|
|
6233
|
-
/* @__PURE__ */ (0,
|
|
6234
|
-
item.badge ? /* @__PURE__ */ (0,
|
|
6485
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }),
|
|
6486
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { flex: 1 }, children: item.label }),
|
|
6487
|
+
item.badge ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Badge, { tone: "neutral", children: item.badge }) : null
|
|
6235
6488
|
]
|
|
6236
6489
|
}
|
|
6237
6490
|
);
|
|
@@ -6247,9 +6500,9 @@ function AccountMenu({
|
|
|
6247
6500
|
...rest
|
|
6248
6501
|
}) {
|
|
6249
6502
|
const session = SessionKit.useSession();
|
|
6250
|
-
const [open, setOpen] =
|
|
6251
|
-
const [switching, setSwitching] =
|
|
6252
|
-
const ref =
|
|
6503
|
+
const [open, setOpen] = React27.useState(false);
|
|
6504
|
+
const [switching, setSwitching] = React27.useState(false);
|
|
6505
|
+
const ref = React27.useRef(null);
|
|
6253
6506
|
const user = session.user;
|
|
6254
6507
|
const visibleAdmin = adminLinks.filter((l) => !l.perm || SessionKit.can(l.perm));
|
|
6255
6508
|
const pick = (item) => {
|
|
@@ -6263,8 +6516,8 @@ function AccountMenu({
|
|
|
6263
6516
|
if (onSignOut) return onSignOut();
|
|
6264
6517
|
window.alert("Signed out. (Simulated \u2014 no auth provider is wired up.)");
|
|
6265
6518
|
};
|
|
6266
|
-
return /* @__PURE__ */ (0,
|
|
6267
|
-
/* @__PURE__ */ (0,
|
|
6519
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
|
|
6520
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
|
|
6268
6521
|
"button",
|
|
6269
6522
|
{
|
|
6270
6523
|
type: "button",
|
|
@@ -6276,32 +6529,32 @@ function AccountMenu({
|
|
|
6276
6529
|
onClick: () => setOpen((o) => !o),
|
|
6277
6530
|
...rest,
|
|
6278
6531
|
children: [
|
|
6279
|
-
/* @__PURE__ */ (0,
|
|
6280
|
-
/* @__PURE__ */ (0,
|
|
6532
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Avatar, { name: user.name, size: "sm" }),
|
|
6533
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
|
|
6281
6534
|
]
|
|
6282
6535
|
}
|
|
6283
6536
|
),
|
|
6284
|
-
/* @__PURE__ */ (0,
|
|
6285
|
-
/* @__PURE__ */ (0,
|
|
6286
|
-
/* @__PURE__ */ (0,
|
|
6287
|
-
/* @__PURE__ */ (0,
|
|
6288
|
-
/* @__PURE__ */ (0,
|
|
6289
|
-
/* @__PURE__ */ (0,
|
|
6537
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Popover, { open, anchorRef: ref, onClose: () => setOpen(false), placement: "bottom-end", width: 272, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
|
|
6538
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
6539
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Avatar, { name: user.name }),
|
|
6540
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
|
|
6541
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
|
|
6542
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-body-sm fd-muted fd-table-trunc", children: user.email })
|
|
6290
6543
|
] })
|
|
6291
6544
|
] }),
|
|
6292
|
-
showRoles && session.roles.length ? /* @__PURE__ */ (0,
|
|
6293
|
-
/* @__PURE__ */ (0,
|
|
6294
|
-
visibleAdmin.length ? /* @__PURE__ */ (0,
|
|
6295
|
-
/* @__PURE__ */ (0,
|
|
6296
|
-
visibleAdmin.map((l) => /* @__PURE__ */ (0,
|
|
6545
|
+
showRoles && session.roles.length ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: session.roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
|
|
6546
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-acct-group", children: links.map((l) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Item, { item: l, onPick: pick }, l.id)) }),
|
|
6547
|
+
visibleAdmin.length ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
6548
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: "Administration" }),
|
|
6549
|
+
visibleAdmin.map((l) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Item, { item: l, onPick: pick }, l.id))
|
|
6297
6550
|
] }) : null,
|
|
6298
|
-
allowUserSwitch ? /* @__PURE__ */ (0,
|
|
6299
|
-
/* @__PURE__ */ (0,
|
|
6300
|
-
/* @__PURE__ */ (0,
|
|
6301
|
-
/* @__PURE__ */ (0,
|
|
6302
|
-
/* @__PURE__ */ (0,
|
|
6551
|
+
allowUserSwitch ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
6552
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
|
|
6553
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
|
|
6554
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
|
|
6555
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
|
|
6303
6556
|
] }),
|
|
6304
|
-
switching ? /* @__PURE__ */ (0,
|
|
6557
|
+
switching ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-stack", style: { gap: 0, maxHeight: 208, overflowY: "auto" }, children: session.allUsers.filter((u) => u.status === "active").map((u) => /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
|
|
6305
6558
|
"button",
|
|
6306
6559
|
{
|
|
6307
6560
|
type: "button",
|
|
@@ -6313,34 +6566,34 @@ function AccountMenu({
|
|
|
6313
6566
|
setSwitching(false);
|
|
6314
6567
|
},
|
|
6315
6568
|
children: [
|
|
6316
|
-
/* @__PURE__ */ (0,
|
|
6317
|
-
/* @__PURE__ */ (0,
|
|
6318
|
-
/* @__PURE__ */ (0,
|
|
6319
|
-
/* @__PURE__ */ (0,
|
|
6569
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Avatar, { name: u.name, size: "sm" }),
|
|
6570
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
|
|
6571
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
|
|
6572
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") })
|
|
6320
6573
|
] }),
|
|
6321
|
-
u.id === user.id ? /* @__PURE__ */ (0,
|
|
6574
|
+
u.id === user.id ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
|
|
6322
6575
|
]
|
|
6323
6576
|
},
|
|
6324
6577
|
u.id
|
|
6325
6578
|
)) }) : null
|
|
6326
6579
|
] }) : null,
|
|
6327
|
-
/* @__PURE__ */ (0,
|
|
6328
|
-
/* @__PURE__ */ (0,
|
|
6329
|
-
/* @__PURE__ */ (0,
|
|
6580
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", "data-danger": "true", onClick: signOut, children: [
|
|
6581
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
|
|
6582
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { flex: 1 }, children: "Sign out" })
|
|
6330
6583
|
] }) })
|
|
6331
6584
|
] }) })
|
|
6332
6585
|
] });
|
|
6333
6586
|
}
|
|
6334
6587
|
|
|
6335
6588
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
6336
|
-
var
|
|
6337
|
-
var
|
|
6589
|
+
var React28 = __toESM(require("react"), 1);
|
|
6590
|
+
var import_jsx_runtime57 = require("react/jsx-runtime");
|
|
6338
6591
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
6339
6592
|
function Json({ obj }) {
|
|
6340
|
-
return /* @__PURE__ */ (0,
|
|
6593
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
6341
6594
|
}
|
|
6342
6595
|
function Endpoint({ s, onRequest }) {
|
|
6343
|
-
const [tried, setTried] =
|
|
6596
|
+
const [tried, setTried] = React28.useState(null);
|
|
6344
6597
|
const run = async () => {
|
|
6345
6598
|
setTried("busy");
|
|
6346
6599
|
const t0 = (window.performance || Date).now();
|
|
@@ -6351,50 +6604,50 @@ function Endpoint({ s, onRequest }) {
|
|
|
6351
6604
|
setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
|
|
6352
6605
|
}
|
|
6353
6606
|
};
|
|
6354
|
-
return /* @__PURE__ */ (0,
|
|
6355
|
-
/* @__PURE__ */ (0,
|
|
6356
|
-
/* @__PURE__ */ (0,
|
|
6357
|
-
/* @__PURE__ */ (0,
|
|
6358
|
-
s.isList ? /* @__PURE__ */ (0,
|
|
6359
|
-
/* @__PURE__ */ (0,
|
|
6360
|
-
/* @__PURE__ */ (0,
|
|
6607
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
6608
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
|
|
6609
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
|
|
6610
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
|
|
6611
|
+
s.isList ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
|
|
6612
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { style: { flex: 1 } }),
|
|
6613
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
6361
6614
|
s.latency[0],
|
|
6362
6615
|
"\u2013",
|
|
6363
6616
|
s.latency[1],
|
|
6364
6617
|
"ms"
|
|
6365
6618
|
] }),
|
|
6366
|
-
/* @__PURE__ */ (0,
|
|
6619
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
|
|
6367
6620
|
] }),
|
|
6368
|
-
/* @__PURE__ */ (0,
|
|
6369
|
-
/* @__PURE__ */ (0,
|
|
6370
|
-
/* @__PURE__ */ (0,
|
|
6371
|
-
/* @__PURE__ */ (0,
|
|
6372
|
-
s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0,
|
|
6621
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
|
|
6622
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6623
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
|
|
6624
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
|
|
6625
|
+
s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Tag, { children: u }, u)) }) : null
|
|
6373
6626
|
] }),
|
|
6374
|
-
/* @__PURE__ */ (0,
|
|
6375
|
-
s.request ? /* @__PURE__ */ (0,
|
|
6376
|
-
/* @__PURE__ */ (0,
|
|
6377
|
-
/* @__PURE__ */ (0,
|
|
6627
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
|
|
6628
|
+
s.request ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6629
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Request body" }),
|
|
6630
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: s.request })
|
|
6378
6631
|
] }) : null,
|
|
6379
|
-
s.query ? /* @__PURE__ */ (0,
|
|
6380
|
-
/* @__PURE__ */ (0,
|
|
6381
|
-
/* @__PURE__ */ (0,
|
|
6632
|
+
s.query ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6633
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Query" }),
|
|
6634
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: s.query })
|
|
6382
6635
|
] }) : null,
|
|
6383
|
-
/* @__PURE__ */ (0,
|
|
6384
|
-
/* @__PURE__ */ (0,
|
|
6385
|
-
/* @__PURE__ */ (0,
|
|
6636
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6637
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Response 200" }),
|
|
6638
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: s.response })
|
|
6386
6639
|
] })
|
|
6387
6640
|
] }),
|
|
6388
|
-
s.notes ? /* @__PURE__ */ (0,
|
|
6389
|
-
tried && tried !== "busy" ? /* @__PURE__ */ (0,
|
|
6390
|
-
/* @__PURE__ */ (0,
|
|
6391
|
-
/* @__PURE__ */ (0,
|
|
6392
|
-
/* @__PURE__ */ (0,
|
|
6641
|
+
s.notes ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
|
|
6642
|
+
tried && tried !== "busy" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6643
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
6644
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
|
|
6645
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
|
|
6393
6646
|
tried.ms,
|
|
6394
6647
|
"ms"
|
|
6395
6648
|
] })
|
|
6396
6649
|
] }),
|
|
6397
|
-
/* @__PURE__ */ (0,
|
|
6650
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
|
|
6398
6651
|
] }) : null
|
|
6399
6652
|
] })
|
|
6400
6653
|
] }) });
|
|
@@ -6413,58 +6666,58 @@ function ApiSpecBrowser({
|
|
|
6413
6666
|
className = "",
|
|
6414
6667
|
...rest
|
|
6415
6668
|
}) {
|
|
6416
|
-
const [q, setQ] =
|
|
6417
|
-
const [method, setMethod] =
|
|
6418
|
-
const [mod, setMod] =
|
|
6419
|
-
const [listOnly, setListOnly] =
|
|
6669
|
+
const [q, setQ] = React28.useState("");
|
|
6670
|
+
const [method, setMethod] = React28.useState(null);
|
|
6671
|
+
const [mod, setMod] = React28.useState(null);
|
|
6672
|
+
const [listOnly, setListOnly] = React28.useState(false);
|
|
6420
6673
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
6421
6674
|
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())));
|
|
6422
6675
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
6423
6676
|
const methods = [...new Set(spec.map((s) => s.method))];
|
|
6424
6677
|
const listCount = spec.filter((s) => s.isList).length;
|
|
6425
|
-
return /* @__PURE__ */ (0,
|
|
6426
|
-
/* @__PURE__ */ (0,
|
|
6427
|
-
kicker ? /* @__PURE__ */ (0,
|
|
6428
|
-
/* @__PURE__ */ (0,
|
|
6429
|
-
lede ? /* @__PURE__ */ (0,
|
|
6678
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
|
|
6679
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
6680
|
+
kicker ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: kicker }) : null,
|
|
6681
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
6682
|
+
lede ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
|
|
6430
6683
|
] }),
|
|
6431
|
-
modules && modules.length ? /* @__PURE__ */ (0,
|
|
6432
|
-
/* @__PURE__ */ (0,
|
|
6433
|
-
/* @__PURE__ */ (0,
|
|
6434
|
-
/* @__PURE__ */ (0,
|
|
6684
|
+
modules && modules.length ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
6685
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
|
|
6686
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
6687
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
|
|
6435
6688
|
"All screens ",
|
|
6436
|
-
/* @__PURE__ */ (0,
|
|
6689
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: spec.length })
|
|
6437
6690
|
] }),
|
|
6438
|
-
modules.map((m) => /* @__PURE__ */ (0,
|
|
6691
|
+
modules.map((m) => /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
|
|
6439
6692
|
m.label,
|
|
6440
6693
|
" ",
|
|
6441
|
-
/* @__PURE__ */ (0,
|
|
6694
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
|
|
6442
6695
|
] }, m.id))
|
|
6443
6696
|
] }),
|
|
6444
|
-
activeModule ? /* @__PURE__ */ (0,
|
|
6697
|
+
activeModule ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
6445
6698
|
Flag,
|
|
6446
6699
|
{
|
|
6447
6700
|
tone: "info",
|
|
6448
6701
|
statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
|
|
6449
6702
|
cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
|
|
6450
|
-
actions: /* @__PURE__ */ (0,
|
|
6703
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
|
|
6451
6704
|
}
|
|
6452
6705
|
) : null
|
|
6453
6706
|
] }) : null,
|
|
6454
|
-
sourceNote ? /* @__PURE__ */ (0,
|
|
6455
|
-
/* @__PURE__ */ (0,
|
|
6456
|
-
/* @__PURE__ */ (0,
|
|
6457
|
-
methods.map((m) => /* @__PURE__ */ (0,
|
|
6707
|
+
sourceNote ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
|
|
6708
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
6709
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
|
|
6710
|
+
methods.map((m) => /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
|
|
6458
6711
|
m,
|
|
6459
6712
|
" ",
|
|
6460
|
-
/* @__PURE__ */ (0,
|
|
6713
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
|
|
6461
6714
|
] }, m)),
|
|
6462
|
-
listCount ? /* @__PURE__ */ (0,
|
|
6715
|
+
listCount ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
|
|
6463
6716
|
"Paged lists ",
|
|
6464
|
-
/* @__PURE__ */ (0,
|
|
6717
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: listCount })
|
|
6465
6718
|
] }) : null,
|
|
6466
|
-
/* @__PURE__ */ (0,
|
|
6467
|
-
/* @__PURE__ */ (0,
|
|
6719
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { style: { flex: 1 } }),
|
|
6720
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
6468
6721
|
hits.length,
|
|
6469
6722
|
" of ",
|
|
6470
6723
|
spec.length,
|
|
@@ -6472,31 +6725,31 @@ function ApiSpecBrowser({
|
|
|
6472
6725
|
listCount ? " \xB7 " + listCount + " paged" : ""
|
|
6473
6726
|
] })
|
|
6474
6727
|
] }),
|
|
6475
|
-
hits.length === 0 ? /* @__PURE__ */ (0,
|
|
6728
|
+
hits.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
|
|
6476
6729
|
const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
|
|
6477
6730
|
if (!items.length) return null;
|
|
6478
|
-
return /* @__PURE__ */ (0,
|
|
6479
|
-
/* @__PURE__ */ (0,
|
|
6480
|
-
items.map((s) => /* @__PURE__ */ (0,
|
|
6731
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 12 }, children: [
|
|
6732
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-label-lg", children: g }),
|
|
6733
|
+
items.map((s) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Endpoint, { s, onRequest }, s.id))
|
|
6481
6734
|
] }, g);
|
|
6482
6735
|
}),
|
|
6483
|
-
conventions && conventions.length ? /* @__PURE__ */ (0,
|
|
6484
|
-
/* @__PURE__ */ (0,
|
|
6485
|
-
/* @__PURE__ */ (0,
|
|
6736
|
+
conventions && conventions.length ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
|
|
6737
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
|
|
6738
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
|
|
6486
6739
|
] }, k)) }) }) : null,
|
|
6487
|
-
openQuestions && openQuestions.length ? /* @__PURE__ */ (0,
|
|
6488
|
-
/* @__PURE__ */ (0,
|
|
6489
|
-
/* @__PURE__ */ (0,
|
|
6490
|
-
/* @__PURE__ */ (0,
|
|
6491
|
-
/* @__PURE__ */ (0,
|
|
6740
|
+
openQuestions && openQuestions.length ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
|
|
6741
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Badge, { tone: "danger", children: id }),
|
|
6742
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
|
|
6743
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
|
|
6744
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-body-sm fd-muted", children: why })
|
|
6492
6745
|
] })
|
|
6493
6746
|
] }, id)) }) }) : null
|
|
6494
6747
|
] });
|
|
6495
6748
|
}
|
|
6496
6749
|
|
|
6497
6750
|
// src/components/platform/ProfilePage.tsx
|
|
6498
|
-
var
|
|
6499
|
-
var
|
|
6751
|
+
var React29 = __toESM(require("react"), 1);
|
|
6752
|
+
var import_jsx_runtime58 = require("react/jsx-runtime");
|
|
6500
6753
|
var TIMEZONES = ["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles", "America/Anchorage", "Pacific/Honolulu", "Europe/London", "Europe/Berlin"];
|
|
6501
6754
|
var NOTIFY = [
|
|
6502
6755
|
{ key: "planShared", label: "A plan is shared with me", detail: "Someone sends you a plan or a client link." },
|
|
@@ -6508,7 +6761,7 @@ var NOTIFY = [
|
|
|
6508
6761
|
function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSessions = true, className = "", ...rest }) {
|
|
6509
6762
|
const session = SessionKit.useSession();
|
|
6510
6763
|
const user = userProp || session.user;
|
|
6511
|
-
const [draft, setDraft] =
|
|
6764
|
+
const [draft, setDraft] = React29.useState(() => ({
|
|
6512
6765
|
name: user.name || "",
|
|
6513
6766
|
title: user.title || "",
|
|
6514
6767
|
email: user.email || "",
|
|
@@ -6517,8 +6770,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6517
6770
|
bio: user.bio || "",
|
|
6518
6771
|
notify: user.notify || { planShared: true, planChanged: true, goalMissed: true, flagChanged: false, weekly: true }
|
|
6519
6772
|
}));
|
|
6520
|
-
const [saving, setSaving] =
|
|
6521
|
-
const [saved, setSaved] =
|
|
6773
|
+
const [saving, setSaving] = React29.useState(false);
|
|
6774
|
+
const [saved, setSaved] = React29.useState(false);
|
|
6522
6775
|
const set = (k, v) => {
|
|
6523
6776
|
setDraft((d) => Object.assign({}, d, { [k]: v }));
|
|
6524
6777
|
setSaved(false);
|
|
@@ -6540,43 +6793,43 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6540
6793
|
{ id: "s2", device: "iPhone 15 \xB7 Safari", where: "Denver, CO", when: "2 hours ago" },
|
|
6541
6794
|
{ id: "s3", device: "Windows \xB7 Edge", where: "Chicago, IL", when: "Aug 12" }
|
|
6542
6795
|
];
|
|
6543
|
-
return /* @__PURE__ */ (0,
|
|
6544
|
-
/* @__PURE__ */ (0,
|
|
6545
|
-
/* @__PURE__ */ (0,
|
|
6546
|
-
/* @__PURE__ */ (0,
|
|
6547
|
-
/* @__PURE__ */ (0,
|
|
6796
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, ...rest, children: [
|
|
6797
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
6798
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
|
|
6799
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
|
|
6800
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("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." })
|
|
6548
6801
|
] }),
|
|
6549
|
-
/* @__PURE__ */ (0,
|
|
6550
|
-
/* @__PURE__ */ (0,
|
|
6551
|
-
/* @__PURE__ */ (0,
|
|
6552
|
-
/* @__PURE__ */ (0,
|
|
6553
|
-
/* @__PURE__ */ (0,
|
|
6802
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
|
|
6803
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Avatar, { name: draft.name || user.name, size: "lg" }),
|
|
6804
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
|
|
6805
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: draft.name || user.name }),
|
|
6806
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
6554
6807
|
draft.title || "No title set",
|
|
6555
6808
|
" \xB7 ",
|
|
6556
6809
|
user.team || "No team"
|
|
6557
6810
|
] }),
|
|
6558
|
-
/* @__PURE__ */ (0,
|
|
6559
|
-
session.roles.map((r) => /* @__PURE__ */ (0,
|
|
6560
|
-
user.sso ? /* @__PURE__ */ (0,
|
|
6811
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
|
|
6812
|
+
session.roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
|
|
6813
|
+
user.sso ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
|
|
6561
6814
|
] })
|
|
6562
6815
|
] }),
|
|
6563
|
-
/* @__PURE__ */ (0,
|
|
6816
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", children: "Change photo" })
|
|
6564
6817
|
] }) }),
|
|
6565
|
-
/* @__PURE__ */ (0,
|
|
6818
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6566
6819
|
Card,
|
|
6567
6820
|
{
|
|
6568
|
-
title: /* @__PURE__ */ (0,
|
|
6569
|
-
/* @__PURE__ */ (0,
|
|
6570
|
-
/* @__PURE__ */ (0,
|
|
6821
|
+
title: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
6822
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: "Identity" }),
|
|
6823
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Name and title appear on plans you share" })
|
|
6571
6824
|
] }),
|
|
6572
6825
|
elevation: "flat",
|
|
6573
|
-
children: /* @__PURE__ */ (0,
|
|
6574
|
-
/* @__PURE__ */ (0,
|
|
6575
|
-
/* @__PURE__ */ (0,
|
|
6576
|
-
/* @__PURE__ */ (0,
|
|
6826
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
|
|
6827
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
|
|
6828
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Input, { label: "Full name", value: draft.name, onChange: (e) => set("name", e.target.value) }),
|
|
6829
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Input, { label: "Job title", value: draft.title, onChange: (e) => set("title", e.target.value), placeholder: "e.g. Senior media planner" })
|
|
6577
6830
|
] }),
|
|
6578
|
-
/* @__PURE__ */ (0,
|
|
6579
|
-
/* @__PURE__ */ (0,
|
|
6831
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
|
|
6832
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6580
6833
|
Input,
|
|
6581
6834
|
{
|
|
6582
6835
|
label: "Work email",
|
|
@@ -6586,9 +6839,9 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6586
6839
|
help: user.sso ? "Managed by your identity provider \u2014 change it there." : "Contact an administrator to change this."
|
|
6587
6840
|
}
|
|
6588
6841
|
),
|
|
6589
|
-
/* @__PURE__ */ (0,
|
|
6842
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Input, { label: "Phone", value: draft.phone, onChange: (e) => set("phone", e.target.value), placeholder: "Optional" })
|
|
6590
6843
|
] }),
|
|
6591
|
-
/* @__PURE__ */ (0,
|
|
6844
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6592
6845
|
Textarea,
|
|
6593
6846
|
{
|
|
6594
6847
|
label: "Short bio",
|
|
@@ -6602,8 +6855,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6602
6855
|
] })
|
|
6603
6856
|
}
|
|
6604
6857
|
),
|
|
6605
|
-
/* @__PURE__ */ (0,
|
|
6606
|
-
/* @__PURE__ */ (0,
|
|
6858
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Card, { title: "Working preferences", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
|
|
6859
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6607
6860
|
Select,
|
|
6608
6861
|
{
|
|
6609
6862
|
label: "Time zone",
|
|
@@ -6613,28 +6866,28 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6613
6866
|
help: "Flight dates and schedules render in this zone."
|
|
6614
6867
|
}
|
|
6615
6868
|
),
|
|
6616
|
-
/* @__PURE__ */ (0,
|
|
6869
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Select, { label: "Start of week", options: ["Monday", "Sunday"], placeholder: "Monday" })
|
|
6617
6870
|
] }) }),
|
|
6618
|
-
/* @__PURE__ */ (0,
|
|
6871
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6619
6872
|
Card,
|
|
6620
6873
|
{
|
|
6621
|
-
title: /* @__PURE__ */ (0,
|
|
6622
|
-
/* @__PURE__ */ (0,
|
|
6623
|
-
/* @__PURE__ */ (0,
|
|
6874
|
+
title: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
6875
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: "Notifications" }),
|
|
6876
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Email only for now \u2014 in-app notifications are on the roadmap" })
|
|
6624
6877
|
] }),
|
|
6625
6878
|
elevation: "flat",
|
|
6626
|
-
children: /* @__PURE__ */ (0,
|
|
6879
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "fd-stack", style: { gap: 14 }, children: NOTIFY.map((n) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Switch, { checked: !!draft.notify[n.key], onChange: () => setNotify(n.key), label: n.label, description: n.detail }, n.key)) })
|
|
6627
6880
|
}
|
|
6628
6881
|
),
|
|
6629
|
-
/* @__PURE__ */ (0,
|
|
6882
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
|
|
6630
6883
|
Card,
|
|
6631
6884
|
{
|
|
6632
|
-
title: /* @__PURE__ */ (0,
|
|
6633
|
-
/* @__PURE__ */ (0,
|
|
6634
|
-
/* @__PURE__ */ (0,
|
|
6885
|
+
title: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
6886
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: "Access" }),
|
|
6887
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
|
|
6635
6888
|
] }),
|
|
6636
6889
|
elevation: "flat",
|
|
6637
|
-
action: /* @__PURE__ */ (0,
|
|
6890
|
+
action: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6638
6891
|
Button,
|
|
6639
6892
|
{
|
|
6640
6893
|
size: "sm",
|
|
@@ -6645,39 +6898,39 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6645
6898
|
}
|
|
6646
6899
|
),
|
|
6647
6900
|
children: [
|
|
6648
|
-
/* @__PURE__ */ (0,
|
|
6649
|
-
/* @__PURE__ */ (0,
|
|
6650
|
-
/* @__PURE__ */ (0,
|
|
6901
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
6902
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(CardRow, { label: "Roles", children: session.roles.map((r) => r.name).join(", ") || "None" }),
|
|
6903
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(CardRow, { label: "Permissions", children: [
|
|
6651
6904
|
session.permissions.length,
|
|
6652
6905
|
" granted"
|
|
6653
6906
|
] }),
|
|
6654
|
-
/* @__PURE__ */ (0,
|
|
6907
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
|
|
6655
6908
|
] }),
|
|
6656
|
-
/* @__PURE__ */ (0,
|
|
6909
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
|
|
6657
6910
|
]
|
|
6658
6911
|
}
|
|
6659
6912
|
),
|
|
6660
|
-
showSessions ? /* @__PURE__ */ (0,
|
|
6913
|
+
showSessions ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6661
6914
|
Card,
|
|
6662
6915
|
{
|
|
6663
6916
|
title: "Signed-in devices",
|
|
6664
6917
|
elevation: "flat",
|
|
6665
|
-
action: /* @__PURE__ */ (0,
|
|
6666
|
-
children: /* @__PURE__ */ (0,
|
|
6667
|
-
/* @__PURE__ */ (0,
|
|
6668
|
-
/* @__PURE__ */ (0,
|
|
6669
|
-
/* @__PURE__ */ (0,
|
|
6670
|
-
/* @__PURE__ */ (0,
|
|
6918
|
+
action: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", children: "Sign out everywhere" }),
|
|
6919
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: liveSessions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
|
|
6920
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
6921
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
|
|
6922
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
|
|
6923
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
6671
6924
|
s.where,
|
|
6672
6925
|
" \xB7 ",
|
|
6673
6926
|
s.when
|
|
6674
6927
|
] })
|
|
6675
6928
|
] }),
|
|
6676
|
-
s.current ? /* @__PURE__ */ (0,
|
|
6929
|
+
s.current ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { size: "sm", variant: "ghost", children: "Revoke" })
|
|
6677
6930
|
] }, s.id)) })
|
|
6678
6931
|
}
|
|
6679
6932
|
) : null,
|
|
6680
|
-
/* @__PURE__ */ (0,
|
|
6933
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-row", style: {
|
|
6681
6934
|
gap: 10,
|
|
6682
6935
|
flexWrap: "wrap",
|
|
6683
6936
|
position: "sticky",
|
|
@@ -6688,8 +6941,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6688
6941
|
border: "1px solid var(--border)",
|
|
6689
6942
|
boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
|
|
6690
6943
|
}, children: [
|
|
6691
|
-
/* @__PURE__ */ (0,
|
|
6692
|
-
/* @__PURE__ */ (0,
|
|
6944
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
|
|
6945
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6693
6946
|
Button,
|
|
6694
6947
|
{
|
|
6695
6948
|
size: "sm",
|
|
@@ -6702,16 +6955,16 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6702
6955
|
children: "Discard"
|
|
6703
6956
|
}
|
|
6704
6957
|
),
|
|
6705
|
-
/* @__PURE__ */ (0,
|
|
6958
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty, loading: saving, onClick: save, children: "Save changes" })
|
|
6706
6959
|
] })
|
|
6707
6960
|
] });
|
|
6708
6961
|
}
|
|
6709
6962
|
|
|
6710
6963
|
// src/components/platform/RoadmapTimeline.tsx
|
|
6711
|
-
var
|
|
6964
|
+
var React31 = __toESM(require("react"), 1);
|
|
6712
6965
|
|
|
6713
6966
|
// src/kits/runtime.ts
|
|
6714
|
-
var
|
|
6967
|
+
var React30 = __toESM(require("react"), 1);
|
|
6715
6968
|
var WIRED_ENDPOINTS = [
|
|
6716
6969
|
// Nothing yet. Every id below would come from a real service:
|
|
6717
6970
|
// "plan.get", "placements.list", …
|
|
@@ -6882,8 +7135,8 @@ var RuntimeKit = {
|
|
|
6882
7135
|
};
|
|
6883
7136
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
6884
7137
|
function useRuntimeMode() {
|
|
6885
|
-
const [m, setM] =
|
|
6886
|
-
|
|
7138
|
+
const [m, setM] = React30.useState(RuntimeKit.getMode());
|
|
7139
|
+
React30.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
6887
7140
|
return m;
|
|
6888
7141
|
}
|
|
6889
7142
|
function useFeatureStatus(key) {
|
|
@@ -6902,7 +7155,7 @@ var UseRuntimeMode = useRuntimeMode;
|
|
|
6902
7155
|
var UseFeatureStatus = useFeatureStatus;
|
|
6903
7156
|
|
|
6904
7157
|
// src/components/platform/RoadmapTimeline.tsx
|
|
6905
|
-
var
|
|
7158
|
+
var import_jsx_runtime59 = require("react/jsx-runtime");
|
|
6906
7159
|
var STATUS = {
|
|
6907
7160
|
shipped: { tone: "success", icon: "check-circle", label: "Wired" },
|
|
6908
7161
|
next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
|
|
@@ -6917,45 +7170,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
6917
7170
|
const s = STATUS[item.status] || STATUS.planned;
|
|
6918
7171
|
const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
|
|
6919
7172
|
const blocking = deps.filter((d) => !d.implemented);
|
|
6920
|
-
return /* @__PURE__ */ (0,
|
|
6921
|
-
/* @__PURE__ */ (0,
|
|
6922
|
-
/* @__PURE__ */ (0,
|
|
6923
|
-
/* @__PURE__ */ (0,
|
|
6924
|
-
/* @__PURE__ */ (0,
|
|
7173
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
7174
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
7175
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
|
|
7176
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
|
|
7177
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Badge, { tone: s.tone, icon: s.icon, children: s.label })
|
|
6925
7178
|
] }),
|
|
6926
|
-
/* @__PURE__ */ (0,
|
|
6927
|
-
item.backend ? /* @__PURE__ */ (0,
|
|
6928
|
-
/* @__PURE__ */ (0,
|
|
6929
|
-
/* @__PURE__ */ (0,
|
|
7179
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
|
|
7180
|
+
item.backend ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
|
|
7181
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
|
|
7182
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
|
|
6930
7183
|
] }) : null,
|
|
6931
|
-
/* @__PURE__ */ (0,
|
|
6932
|
-
item.effort ? /* @__PURE__ */ (0,
|
|
6933
|
-
/* @__PURE__ */ (0,
|
|
7184
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
7185
|
+
item.effort ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
7186
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-hourglass-medium" }),
|
|
6934
7187
|
" ",
|
|
6935
7188
|
item.effort
|
|
6936
7189
|
] }) : null,
|
|
6937
|
-
/* @__PURE__ */ (0,
|
|
6938
|
-
/* @__PURE__ */ (0,
|
|
7190
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
7191
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-user" }),
|
|
6939
7192
|
" ",
|
|
6940
7193
|
item.owner
|
|
6941
7194
|
] }),
|
|
6942
|
-
item.screen ? /* @__PURE__ */ (0,
|
|
6943
|
-
/* @__PURE__ */ (0,
|
|
6944
|
-
/* @__PURE__ */ (0,
|
|
7195
|
+
item.screen ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
|
|
7196
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { flex: 1 } }),
|
|
7197
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
6945
7198
|
"button",
|
|
6946
7199
|
{
|
|
6947
7200
|
type: "button",
|
|
6948
7201
|
onClick: () => onOpenFlag && onOpenFlag(item.key),
|
|
6949
7202
|
style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
|
|
6950
|
-
children: /* @__PURE__ */ (0,
|
|
7203
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
|
|
6951
7204
|
}
|
|
6952
7205
|
)
|
|
6953
7206
|
] }),
|
|
6954
|
-
deps.length ? /* @__PURE__ */ (0,
|
|
6955
|
-
/* @__PURE__ */ (0,
|
|
6956
|
-
deps.map((d) => /* @__PURE__ */ (0,
|
|
7207
|
+
deps.length ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
|
|
7208
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
|
|
7209
|
+
deps.map((d) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
|
|
6957
7210
|
] }) : null,
|
|
6958
|
-
blocking.length && !item.implemented ? /* @__PURE__ */ (0,
|
|
7211
|
+
blocking.length && !item.implemented ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
|
|
6959
7212
|
"Blocked until ",
|
|
6960
7213
|
blocking.map((d) => d.label).join(" and "),
|
|
6961
7214
|
" ",
|
|
@@ -6966,12 +7219,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
6966
7219
|
}
|
|
6967
7220
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
6968
7221
|
const session = SessionKit.useSession();
|
|
6969
|
-
const [project, setProject] =
|
|
6970
|
-
const [q, setQ] =
|
|
6971
|
-
const scrollRef =
|
|
6972
|
-
const nowRef =
|
|
6973
|
-
const rm =
|
|
6974
|
-
const byKey =
|
|
7222
|
+
const [project, setProject] = React31.useState("");
|
|
7223
|
+
const [q, setQ] = React31.useState("");
|
|
7224
|
+
const scrollRef = React31.useRef(null);
|
|
7225
|
+
const nowRef = React31.useRef(null);
|
|
7226
|
+
const rm = React31.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
7227
|
+
const byKey = React31.useMemo(() => {
|
|
6975
7228
|
const m = {};
|
|
6976
7229
|
rm.items.forEach((i) => {
|
|
6977
7230
|
m[i.key] = i;
|
|
@@ -6980,7 +7233,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
6980
7233
|
}, [rm]);
|
|
6981
7234
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
6982
7235
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
6983
|
-
|
|
7236
|
+
React31.useEffect(() => {
|
|
6984
7237
|
let raf1 = 0, raf2 = 0;
|
|
6985
7238
|
const place = () => {
|
|
6986
7239
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -7008,23 +7261,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7008
7261
|
}, 0);
|
|
7009
7262
|
const nextPhase = items.find((i) => !i.implemented);
|
|
7010
7263
|
let lastPhase = null;
|
|
7011
|
-
return /* @__PURE__ */ (0,
|
|
7012
|
-
/* @__PURE__ */ (0,
|
|
7013
|
-
/* @__PURE__ */ (0,
|
|
7014
|
-
/* @__PURE__ */ (0,
|
|
7015
|
-
/* @__PURE__ */ (0,
|
|
7264
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
|
|
7265
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
7266
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", children: "Architecture" }),
|
|
7267
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
7268
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("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." })
|
|
7016
7269
|
] }),
|
|
7017
|
-
/* @__PURE__ */ (0,
|
|
7018
|
-
/* @__PURE__ */ (0,
|
|
7019
|
-
/* @__PURE__ */ (0,
|
|
7020
|
-
/* @__PURE__ */ (0,
|
|
7021
|
-
/* @__PURE__ */ (0,
|
|
7270
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-grid-stats is-thin", children: [
|
|
7271
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
|
|
7272
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
|
|
7273
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
|
|
7274
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
|
|
7022
7275
|
] }),
|
|
7023
|
-
/* @__PURE__ */ (0,
|
|
7024
|
-
/* @__PURE__ */ (0,
|
|
7025
|
-
/* @__PURE__ */ (0,
|
|
7026
|
-
/* @__PURE__ */ (0,
|
|
7027
|
-
/* @__PURE__ */ (0,
|
|
7276
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
7277
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(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 } }),
|
|
7278
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
|
|
7279
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { flex: 1 } }),
|
|
7280
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
7028
7281
|
Button,
|
|
7029
7282
|
{
|
|
7030
7283
|
size: "sm",
|
|
@@ -7038,7 +7291,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7038
7291
|
}
|
|
7039
7292
|
)
|
|
7040
7293
|
] }),
|
|
7041
|
-
/* @__PURE__ */ (0,
|
|
7294
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
7042
7295
|
Flag,
|
|
7043
7296
|
{
|
|
7044
7297
|
tone: "info",
|
|
@@ -7047,60 +7300,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7047
7300
|
actions: null
|
|
7048
7301
|
}
|
|
7049
7302
|
),
|
|
7050
|
-
/* @__PURE__ */ (0,
|
|
7051
|
-
/* @__PURE__ */ (0,
|
|
7303
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "fd-rm", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-rm-track", children: [
|
|
7304
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-rm-spine", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
|
|
7052
7305
|
items.map((item, n) => {
|
|
7053
7306
|
const showPhase = item.phase !== lastPhase;
|
|
7054
7307
|
lastPhase = item.phase;
|
|
7055
7308
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
7056
7309
|
const isBoundary = n === firstPending;
|
|
7057
|
-
return /* @__PURE__ */ (0,
|
|
7058
|
-
showPhase ? /* @__PURE__ */ (0,
|
|
7059
|
-
/* @__PURE__ */ (0,
|
|
7060
|
-
/* @__PURE__ */ (0,
|
|
7061
|
-
item.phase === 0 ? null : /* @__PURE__ */ (0,
|
|
7310
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React31.Fragment, { children: [
|
|
7311
|
+
showPhase ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-rm-era", children: [
|
|
7312
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
7313
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
7314
|
+
item.phase === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
7062
7315
|
fmtDate(item.phaseStart),
|
|
7063
7316
|
" \u2013 ",
|
|
7064
7317
|
fmtDate(item.date)
|
|
7065
7318
|
] }),
|
|
7066
|
-
/* @__PURE__ */ (0,
|
|
7319
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
7067
7320
|
"\xB7 ",
|
|
7068
7321
|
inPhase,
|
|
7069
7322
|
" feature",
|
|
7070
7323
|
inPhase === 1 ? "" : "s"
|
|
7071
7324
|
] })
|
|
7072
7325
|
] }),
|
|
7073
|
-
item.phaseWhy ? /* @__PURE__ */ (0,
|
|
7326
|
+
item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
|
|
7074
7327
|
] }) : null,
|
|
7075
|
-
isBoundary ? /* @__PURE__ */ (0,
|
|
7076
|
-
/* @__PURE__ */ (0,
|
|
7328
|
+
isBoundary ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-rm-now-pill", children: [
|
|
7329
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-map-pin" }),
|
|
7077
7330
|
" You are here \u2014 everything above is wired"
|
|
7078
7331
|
] }) }) : null,
|
|
7079
|
-
/* @__PURE__ */ (0,
|
|
7080
|
-
/* @__PURE__ */ (0,
|
|
7081
|
-
/* @__PURE__ */ (0,
|
|
7332
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-rm-row", children: [
|
|
7333
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
|
|
7334
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-rm-date", children: [
|
|
7082
7335
|
fmtDate(item.date),
|
|
7083
|
-
/* @__PURE__ */ (0,
|
|
7084
|
-
/* @__PURE__ */ (0,
|
|
7336
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("br", {}),
|
|
7337
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
|
|
7085
7338
|
] }),
|
|
7086
|
-
/* @__PURE__ */ (0,
|
|
7339
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
|
|
7087
7340
|
] })
|
|
7088
7341
|
] }, item.key);
|
|
7089
7342
|
}),
|
|
7090
|
-
!items.length ? /* @__PURE__ */ (0,
|
|
7343
|
+
!items.length ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
|
|
7091
7344
|
] }) }) }),
|
|
7092
|
-
/* @__PURE__ */ (0,
|
|
7345
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
|
|
7093
7346
|
"Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
|
|
7094
|
-
/* @__PURE__ */ (0,
|
|
7347
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("code", { className: "fd-mono", children: "implemented" }),
|
|
7095
7348
|
" field, so this page cannot drift from what the apps actually do."
|
|
7096
7349
|
] })
|
|
7097
7350
|
] });
|
|
7098
7351
|
}
|
|
7099
7352
|
|
|
7100
7353
|
// src/components/platform/ComingSoon.tsx
|
|
7101
|
-
var
|
|
7354
|
+
var React32 = __toESM(require("react"), 1);
|
|
7102
7355
|
var import_react_dom7 = require("react-dom");
|
|
7103
|
-
var
|
|
7356
|
+
var import_jsx_runtime60 = require("react/jsx-runtime");
|
|
7104
7357
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
7105
7358
|
function readBypassed() {
|
|
7106
7359
|
try {
|
|
@@ -7116,8 +7369,8 @@ function writeBypassed(list) {
|
|
|
7116
7369
|
}
|
|
7117
7370
|
}
|
|
7118
7371
|
function useBypass(key) {
|
|
7119
|
-
const [on, setOn] =
|
|
7120
|
-
|
|
7372
|
+
const [on, setOn] = React32.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
7373
|
+
React32.useEffect(() => {
|
|
7121
7374
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
7122
7375
|
}, [key]);
|
|
7123
7376
|
const set = (next) => {
|
|
@@ -7130,43 +7383,43 @@ function useBypass(key) {
|
|
|
7130
7383
|
return [on, set];
|
|
7131
7384
|
}
|
|
7132
7385
|
function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
|
|
7133
|
-
return /* @__PURE__ */ (0,
|
|
7134
|
-
/* @__PURE__ */ (0,
|
|
7135
|
-
/* @__PURE__ */ (0,
|
|
7386
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
|
|
7387
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-badge", children: [
|
|
7388
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
7136
7389
|
label
|
|
7137
7390
|
] }),
|
|
7138
|
-
detail ? /* @__PURE__ */ (0,
|
|
7139
|
-
backend ? /* @__PURE__ */ (0,
|
|
7140
|
-
/* @__PURE__ */ (0,
|
|
7391
|
+
detail ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-soon-detail", children: detail }) : null,
|
|
7392
|
+
backend ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-backend", children: [
|
|
7393
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-overline", children: "Needs" }),
|
|
7141
7394
|
" ",
|
|
7142
7395
|
backend
|
|
7143
7396
|
] }) : null,
|
|
7144
|
-
eta || effort || onRoadmap ? /* @__PURE__ */ (0,
|
|
7145
|
-
eta ? /* @__PURE__ */ (0,
|
|
7146
|
-
/* @__PURE__ */ (0,
|
|
7397
|
+
eta || effort || onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-meta", children: [
|
|
7398
|
+
eta ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { children: [
|
|
7399
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
|
|
7147
7400
|
" ",
|
|
7148
7401
|
eta
|
|
7149
7402
|
] }) : null,
|
|
7150
|
-
effort ? /* @__PURE__ */ (0,
|
|
7151
|
-
/* @__PURE__ */ (0,
|
|
7403
|
+
effort ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { children: [
|
|
7404
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
|
|
7152
7405
|
" ",
|
|
7153
7406
|
effort
|
|
7154
7407
|
] }) : null,
|
|
7155
|
-
onRoadmap ? /* @__PURE__ */ (0,
|
|
7408
|
+
onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
7156
7409
|
"See the roadmap ",
|
|
7157
|
-
/* @__PURE__ */ (0,
|
|
7410
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7158
7411
|
] }) : null
|
|
7159
7412
|
] }) : null,
|
|
7160
|
-
allowed ? /* @__PURE__ */ (0,
|
|
7161
|
-
/* @__PURE__ */ (0,
|
|
7413
|
+
allowed ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
|
|
7414
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-eye", "aria-hidden": "true" }),
|
|
7162
7415
|
" View and use it anyway"
|
|
7163
7416
|
] }) : null
|
|
7164
7417
|
] });
|
|
7165
7418
|
}
|
|
7166
7419
|
function useHoverCard(open) {
|
|
7167
|
-
const anchor =
|
|
7168
|
-
const [pos, setPos] =
|
|
7169
|
-
|
|
7420
|
+
const anchor = React32.useRef(null);
|
|
7421
|
+
const [pos, setPos] = React32.useState(null);
|
|
7422
|
+
React32.useLayoutEffect(() => {
|
|
7170
7423
|
if (!open || !anchor.current) {
|
|
7171
7424
|
setPos(null);
|
|
7172
7425
|
return;
|
|
@@ -7218,9 +7471,9 @@ function ComingSoon({
|
|
|
7218
7471
|
const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
|
|
7219
7472
|
if (inline) {
|
|
7220
7473
|
if (allowed && bypassed) {
|
|
7221
|
-
return /* @__PURE__ */ (0,
|
|
7474
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
|
|
7222
7475
|
children,
|
|
7223
|
-
/* @__PURE__ */ (0,
|
|
7476
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7224
7477
|
"button",
|
|
7225
7478
|
{
|
|
7226
7479
|
type: "button",
|
|
@@ -7228,12 +7481,12 @@ function ComingSoon({
|
|
|
7228
7481
|
title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
|
|
7229
7482
|
onClick: () => setBypassed(false),
|
|
7230
7483
|
"aria-label": "Re-blur this unwired feature",
|
|
7231
|
-
children: /* @__PURE__ */ (0,
|
|
7484
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
7232
7485
|
}
|
|
7233
7486
|
)
|
|
7234
7487
|
] });
|
|
7235
7488
|
}
|
|
7236
|
-
return /* @__PURE__ */ (0,
|
|
7489
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7237
7490
|
InlineSoon,
|
|
7238
7491
|
{
|
|
7239
7492
|
label,
|
|
@@ -7253,20 +7506,20 @@ function ComingSoon({
|
|
|
7253
7506
|
);
|
|
7254
7507
|
}
|
|
7255
7508
|
if (allowed && bypassed) {
|
|
7256
|
-
return /* @__PURE__ */ (0,
|
|
7257
|
-
/* @__PURE__ */ (0,
|
|
7258
|
-
/* @__PURE__ */ (0,
|
|
7259
|
-
/* @__PURE__ */ (0,
|
|
7509
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
|
|
7510
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "fd-soon-bar", role: "status", children: [
|
|
7511
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-badge", children: [
|
|
7512
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
7260
7513
|
"Unwired feature \u2014 you are using it anyway"
|
|
7261
7514
|
] }),
|
|
7262
|
-
/* @__PURE__ */ (0,
|
|
7263
|
-
/* @__PURE__ */ (0,
|
|
7264
|
-
onRoadmap ? /* @__PURE__ */ (0,
|
|
7515
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
|
|
7516
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-bar-actions", children: [
|
|
7517
|
+
onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
7265
7518
|
"Roadmap ",
|
|
7266
|
-
/* @__PURE__ */ (0,
|
|
7519
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7267
7520
|
] }) : null,
|
|
7268
|
-
/* @__PURE__ */ (0,
|
|
7269
|
-
/* @__PURE__ */ (0,
|
|
7521
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
|
|
7522
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
|
|
7270
7523
|
" Re-blur"
|
|
7271
7524
|
] })
|
|
7272
7525
|
] })
|
|
@@ -7274,10 +7527,10 @@ function ComingSoon({
|
|
|
7274
7527
|
children
|
|
7275
7528
|
] });
|
|
7276
7529
|
}
|
|
7277
|
-
return /* @__PURE__ */ (0,
|
|
7278
|
-
/* @__PURE__ */ (0,
|
|
7279
|
-
/* @__PURE__ */ (0,
|
|
7280
|
-
/* @__PURE__ */ (0,
|
|
7530
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
|
|
7531
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
7532
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "fd-soon-veil" }),
|
|
7533
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7281
7534
|
SoonCard,
|
|
7282
7535
|
{
|
|
7283
7536
|
label,
|
|
@@ -7293,9 +7546,9 @@ function ComingSoon({
|
|
|
7293
7546
|
] });
|
|
7294
7547
|
}
|
|
7295
7548
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
7296
|
-
const [open, setOpen] =
|
|
7549
|
+
const [open, setOpen] = React32.useState(false);
|
|
7297
7550
|
const [anchor, pos] = useHoverCard(open);
|
|
7298
|
-
const close =
|
|
7551
|
+
const close = React32.useRef(null);
|
|
7299
7552
|
const show = () => {
|
|
7300
7553
|
if (close.current) {
|
|
7301
7554
|
clearTimeout(close.current);
|
|
@@ -7311,10 +7564,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7311
7564
|
setOpen(false);
|
|
7312
7565
|
}, 140);
|
|
7313
7566
|
};
|
|
7314
|
-
|
|
7567
|
+
React32.useEffect(() => () => {
|
|
7315
7568
|
if (close.current) clearTimeout(close.current);
|
|
7316
7569
|
}, []);
|
|
7317
|
-
return /* @__PURE__ */ (0,
|
|
7570
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
|
|
7318
7571
|
"span",
|
|
7319
7572
|
{
|
|
7320
7573
|
ref: anchor,
|
|
@@ -7325,8 +7578,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7325
7578
|
onBlur: hide,
|
|
7326
7579
|
...rest,
|
|
7327
7580
|
children: [
|
|
7328
|
-
/* @__PURE__ */ (0,
|
|
7329
|
-
/* @__PURE__ */ (0,
|
|
7581
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
7582
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7330
7583
|
"button",
|
|
7331
7584
|
{
|
|
7332
7585
|
type: "button",
|
|
@@ -7337,11 +7590,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7337
7590
|
onFocus: show,
|
|
7338
7591
|
onBlur: hide,
|
|
7339
7592
|
onClick: () => open ? setOpen(false) : show(),
|
|
7340
|
-
children: /* @__PURE__ */ (0,
|
|
7593
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
7341
7594
|
}
|
|
7342
7595
|
),
|
|
7343
7596
|
open && pos ? (0, import_react_dom7.createPortal)(
|
|
7344
|
-
/* @__PURE__ */ (0,
|
|
7597
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7345
7598
|
"div",
|
|
7346
7599
|
{
|
|
7347
7600
|
className: "fd-soon-note fd-soon-hovercard",
|
|
@@ -7349,7 +7602,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7349
7602
|
style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width },
|
|
7350
7603
|
onMouseEnter: show,
|
|
7351
7604
|
onMouseLeave: hide,
|
|
7352
|
-
children: /* @__PURE__ */ (0,
|
|
7605
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7353
7606
|
SoonCard,
|
|
7354
7607
|
{
|
|
7355
7608
|
label,
|
|
@@ -7379,10 +7632,10 @@ function formatEta(iso2) {
|
|
|
7379
7632
|
var FormatEta = formatEta;
|
|
7380
7633
|
|
|
7381
7634
|
// src/components/platform/Gate.tsx
|
|
7382
|
-
var
|
|
7635
|
+
var import_jsx_runtime61 = require("react/jsx-runtime");
|
|
7383
7636
|
function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
|
|
7384
7637
|
const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
|
|
7385
|
-
return /* @__PURE__ */ (0,
|
|
7638
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
|
|
7386
7639
|
"div",
|
|
7387
7640
|
{
|
|
7388
7641
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -7398,14 +7651,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
7398
7651
|
},
|
|
7399
7652
|
...rest,
|
|
7400
7653
|
children: [
|
|
7401
|
-
/* @__PURE__ */ (0,
|
|
7402
|
-
/* @__PURE__ */ (0,
|
|
7403
|
-
/* @__PURE__ */ (0,
|
|
7654
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
7655
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
7656
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
|
|
7404
7657
|
] }),
|
|
7405
|
-
/* @__PURE__ */ (0,
|
|
7406
|
-
need.length ? /* @__PURE__ */ (0,
|
|
7407
|
-
/* @__PURE__ */ (0,
|
|
7408
|
-
need.map((p) => /* @__PURE__ */ (0,
|
|
7658
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("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." }),
|
|
7659
|
+
need.length ? /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
|
|
7660
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-overline fd-muted", children: "Requires" }),
|
|
7661
|
+
need.map((p) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("code", { className: "fd-mono", style: {
|
|
7409
7662
|
fontSize: 11.5,
|
|
7410
7663
|
padding: "2px 7px",
|
|
7411
7664
|
borderRadius: 5,
|
|
@@ -7426,7 +7679,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, compact: compact3 =
|
|
|
7426
7679
|
if (ok) return children;
|
|
7427
7680
|
if (fallback !== void 0) return fallback;
|
|
7428
7681
|
if (silent) return null;
|
|
7429
|
-
return /* @__PURE__ */ (0,
|
|
7682
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
|
|
7430
7683
|
}
|
|
7431
7684
|
function FeatureGate({
|
|
7432
7685
|
flag,
|
|
@@ -7447,7 +7700,7 @@ function FeatureGate({
|
|
|
7447
7700
|
if (!preview) return fallback;
|
|
7448
7701
|
const f = SessionKit.findFlag(flag) || {};
|
|
7449
7702
|
const missing = rt.missing || [];
|
|
7450
|
-
return /* @__PURE__ */ (0,
|
|
7703
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
7451
7704
|
ComingSoon,
|
|
7452
7705
|
{
|
|
7453
7706
|
label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
|
|
@@ -7468,25 +7721,25 @@ function FeatureGate({
|
|
|
7468
7721
|
function PermissionHint({ perm, children }) {
|
|
7469
7722
|
SessionKit.useSession();
|
|
7470
7723
|
if (SessionKit.can(perm)) return children;
|
|
7471
|
-
return /* @__PURE__ */ (0,
|
|
7724
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
7472
7725
|
"span",
|
|
7473
7726
|
{
|
|
7474
7727
|
title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
|
|
7475
7728
|
style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
|
|
7476
7729
|
"aria-disabled": "true",
|
|
7477
|
-
children: /* @__PURE__ */ (0,
|
|
7730
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { style: { pointerEvents: "none" }, children })
|
|
7478
7731
|
}
|
|
7479
7732
|
);
|
|
7480
7733
|
}
|
|
7481
7734
|
|
|
7482
7735
|
// src/components/platform/ModeSwitch.tsx
|
|
7483
|
-
var
|
|
7484
|
-
var
|
|
7736
|
+
var React33 = __toESM(require("react"), 1);
|
|
7737
|
+
var import_jsx_runtime62 = require("react/jsx-runtime");
|
|
7485
7738
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
7486
7739
|
const mode2 = useRuntimeMode();
|
|
7487
|
-
const [open, setOpen] =
|
|
7488
|
-
const ref =
|
|
7489
|
-
|
|
7740
|
+
const [open, setOpen] = React33.useState(false);
|
|
7741
|
+
const ref = React33.useRef(null);
|
|
7742
|
+
React33.useEffect(() => {
|
|
7490
7743
|
if (!open) return;
|
|
7491
7744
|
const away = (e) => {
|
|
7492
7745
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -7508,8 +7761,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7508
7761
|
RuntimeKit.setMode(next);
|
|
7509
7762
|
setOpen(false);
|
|
7510
7763
|
};
|
|
7511
|
-
return /* @__PURE__ */ (0,
|
|
7512
|
-
/* @__PURE__ */ (0,
|
|
7764
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
|
|
7765
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
|
|
7513
7766
|
"button",
|
|
7514
7767
|
{
|
|
7515
7768
|
type: "button",
|
|
@@ -7519,29 +7772,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7519
7772
|
title: test ? "Test mode \u2014 every response is simulated. Click to inspect requests or return to live mode." : "Live mode \u2014 incomplete features are shown under construction. Click for test mode.",
|
|
7520
7773
|
className: "fd-mode-btn" + (test ? " is-test" : "") + (open ? " is-open" : ""),
|
|
7521
7774
|
children: [
|
|
7522
|
-
/* @__PURE__ */ (0,
|
|
7523
|
-
test && requestCount ? /* @__PURE__ */ (0,
|
|
7775
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
|
|
7776
|
+
test && requestCount ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
|
|
7524
7777
|
]
|
|
7525
7778
|
}
|
|
7526
7779
|
),
|
|
7527
|
-
open ? /* @__PURE__ */ (0,
|
|
7528
|
-
/* @__PURE__ */ (0,
|
|
7529
|
-
/* @__PURE__ */ (0,
|
|
7530
|
-
/* @__PURE__ */ (0,
|
|
7780
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-view-enter fd-mode-pop", children: [
|
|
7781
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
7782
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
|
|
7783
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
|
|
7531
7784
|
test ? "Test mode" : "Live mode"
|
|
7532
7785
|
] }),
|
|
7533
|
-
test ? /* @__PURE__ */ (0,
|
|
7786
|
+
test ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
7534
7787
|
requestCount,
|
|
7535
7788
|
" simulated request",
|
|
7536
7789
|
requestCount === 1 ? "" : "s"
|
|
7537
7790
|
] }) : null,
|
|
7538
|
-
/* @__PURE__ */ (0,
|
|
7539
|
-
test && onClearLog ? /* @__PURE__ */ (0,
|
|
7791
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { flex: 1 } }),
|
|
7792
|
+
test && onClearLog ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
|
|
7540
7793
|
] }),
|
|
7541
|
-
/* @__PURE__ */ (0,
|
|
7542
|
-
/* @__PURE__ */ (0,
|
|
7543
|
-
/* @__PURE__ */ (0,
|
|
7544
|
-
/* @__PURE__ */ (0,
|
|
7794
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
7795
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("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." }),
|
|
7796
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
|
|
7797
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
7545
7798
|
s.endpointsWired,
|
|
7546
7799
|
" endpoint",
|
|
7547
7800
|
s.endpointsWired === 1 ? "" : "s",
|
|
@@ -7551,58 +7804,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7551
7804
|
s.total,
|
|
7552
7805
|
" features complete"
|
|
7553
7806
|
] }),
|
|
7554
|
-
onOpenSpec ? /* @__PURE__ */ (0,
|
|
7555
|
-
/* @__PURE__ */ (0,
|
|
7556
|
-
/* @__PURE__ */ (0,
|
|
7807
|
+
onOpenSpec ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(import_jsx_runtime62.Fragment, { children: [
|
|
7808
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { flex: 1 } }),
|
|
7809
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => {
|
|
7557
7810
|
setOpen(false);
|
|
7558
7811
|
onOpenSpec();
|
|
7559
7812
|
}, children: [
|
|
7560
7813
|
"API spec ",
|
|
7561
|
-
/* @__PURE__ */ (0,
|
|
7814
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7562
7815
|
] })
|
|
7563
7816
|
] }) : null
|
|
7564
7817
|
] })
|
|
7565
7818
|
] }),
|
|
7566
|
-
/* @__PURE__ */ (0,
|
|
7567
|
-
/* @__PURE__ */ (0,
|
|
7568
|
-
/* @__PURE__ */ (0,
|
|
7569
|
-
/* @__PURE__ */ (0,
|
|
7570
|
-
/* @__PURE__ */ (0,
|
|
7571
|
-
/* @__PURE__ */ (0,
|
|
7819
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-mode-choice", children: [
|
|
7820
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
|
|
7821
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
7822
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-mode-opt-text", children: [
|
|
7823
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mode-opt-title", children: "Live mode" }),
|
|
7824
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
|
|
7572
7825
|
] }),
|
|
7573
|
-
!test ? /* @__PURE__ */ (0,
|
|
7826
|
+
!test ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
7574
7827
|
] }),
|
|
7575
|
-
/* @__PURE__ */ (0,
|
|
7576
|
-
/* @__PURE__ */ (0,
|
|
7577
|
-
/* @__PURE__ */ (0,
|
|
7578
|
-
/* @__PURE__ */ (0,
|
|
7579
|
-
/* @__PURE__ */ (0,
|
|
7828
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
|
|
7829
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
7830
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-mode-opt-text", children: [
|
|
7831
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mode-opt-title", children: "Test mode" }),
|
|
7832
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
|
|
7580
7833
|
] }),
|
|
7581
|
-
test ? /* @__PURE__ */ (0,
|
|
7834
|
+
test ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
7582
7835
|
] })
|
|
7583
7836
|
] }),
|
|
7584
|
-
test && renderLog ? /* @__PURE__ */ (0,
|
|
7837
|
+
test && renderLog ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
|
|
7585
7838
|
] }) : null
|
|
7586
7839
|
] });
|
|
7587
7840
|
}
|
|
7588
7841
|
function TestModeBar({ onExit }) {
|
|
7589
7842
|
const mode2 = useRuntimeMode();
|
|
7590
7843
|
if (mode2 !== "test") return null;
|
|
7591
|
-
return /* @__PURE__ */ (0,
|
|
7592
|
-
/* @__PURE__ */ (0,
|
|
7593
|
-
/* @__PURE__ */ (0,
|
|
7844
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "fd-testbar", role: "status", children: [
|
|
7845
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-badge fd-badge-warning", children: [
|
|
7846
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
7594
7847
|
"Test mode"
|
|
7595
7848
|
] }),
|
|
7596
|
-
/* @__PURE__ */ (0,
|
|
7597
|
-
/* @__PURE__ */ (0,
|
|
7598
|
-
/* @__PURE__ */ (0,
|
|
7849
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
|
|
7850
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
|
|
7851
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
7599
7852
|
" Back to live mode"
|
|
7600
7853
|
] })
|
|
7601
7854
|
] });
|
|
7602
7855
|
}
|
|
7603
7856
|
|
|
7604
7857
|
// src/components/planner/ChannelMeta.tsx
|
|
7605
|
-
var
|
|
7858
|
+
var import_jsx_runtime63 = require("react/jsx-runtime");
|
|
7606
7859
|
var CHANNEL_WEIGHTS = {
|
|
7607
7860
|
"OOH": 50,
|
|
7608
7861
|
"DOOH": 50,
|
|
@@ -7655,9 +7908,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
7655
7908
|
const m = ChannelMeta(channel);
|
|
7656
7909
|
const wt = channelWeightOf(channel || "");
|
|
7657
7910
|
if (dot) {
|
|
7658
|
-
return /* @__PURE__ */ (0,
|
|
7911
|
+
return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
|
|
7659
7912
|
}
|
|
7660
|
-
return /* @__PURE__ */ (0,
|
|
7913
|
+
return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
|
|
7661
7914
|
"span",
|
|
7662
7915
|
{
|
|
7663
7916
|
className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
|
|
@@ -7665,16 +7918,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
7665
7918
|
style: { "--chan": m.color },
|
|
7666
7919
|
...rest,
|
|
7667
7920
|
children: [
|
|
7668
|
-
/* @__PURE__ */ (0,
|
|
7669
|
-
showLabel ? /* @__PURE__ */ (0,
|
|
7670
|
-
weight ? /* @__PURE__ */ (0,
|
|
7921
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
|
|
7922
|
+
showLabel ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-chan-label", children: m.label }) : null,
|
|
7923
|
+
weight ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-chan-weight", children: wt || 0 }) : null
|
|
7671
7924
|
]
|
|
7672
7925
|
}
|
|
7673
7926
|
);
|
|
7674
7927
|
}
|
|
7675
7928
|
|
|
7676
7929
|
// src/components/planner/SaturationDistribution.tsx
|
|
7677
|
-
var
|
|
7930
|
+
var import_jsx_runtime64 = require("react/jsx-runtime");
|
|
7678
7931
|
var BANDS2 = [
|
|
7679
7932
|
{ key: "weak", label: "Weak", n: 1, range: "< 50" },
|
|
7680
7933
|
{ key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
|
|
@@ -7685,18 +7938,18 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
7685
7938
|
const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
|
|
7686
7939
|
const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
|
|
7687
7940
|
const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
|
|
7688
|
-
return /* @__PURE__ */ (0,
|
|
7689
|
-
/* @__PURE__ */ (0,
|
|
7941
|
+
return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
7942
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
|
|
7690
7943
|
const mark = "var(--csi-" + g.n + "-mark)";
|
|
7691
7944
|
const active = selectedBand === g.key;
|
|
7692
|
-
return /* @__PURE__ */ (0,
|
|
7945
|
+
return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
|
|
7693
7946
|
"button",
|
|
7694
7947
|
{
|
|
7695
7948
|
type: "button",
|
|
7696
7949
|
onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
|
|
7697
7950
|
style: { display: "flex", flexDirection: "column", justifyContent: "flex-end", gap: 10, padding: 12, border: "1px solid " + (active ? "var(--border-strong)" : "var(--border)"), borderRadius: "var(--r-lg)", background: active ? "var(--surface-2)" : "var(--surface)", cursor: onSelectBand ? "pointer" : "default", textAlign: "left", minHeight: 190, transition: "background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease)" },
|
|
7698
7951
|
children: [
|
|
7699
|
-
/* @__PURE__ */ (0,
|
|
7952
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
|
|
7700
7953
|
"span",
|
|
7701
7954
|
{
|
|
7702
7955
|
title: c.name + " \xB7 " + c.crp,
|
|
@@ -7705,13 +7958,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
7705
7958
|
},
|
|
7706
7959
|
c.name
|
|
7707
7960
|
)) }),
|
|
7708
|
-
/* @__PURE__ */ (0,
|
|
7709
|
-
/* @__PURE__ */ (0,
|
|
7710
|
-
/* @__PURE__ */ (0,
|
|
7961
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
|
|
7962
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
|
|
7963
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
|
|
7711
7964
|
] }),
|
|
7712
|
-
/* @__PURE__ */ (0,
|
|
7713
|
-
/* @__PURE__ */ (0,
|
|
7714
|
-
/* @__PURE__ */ (0,
|
|
7965
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-stack", style: { gap: 1 }, children: [
|
|
7966
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-label-lg", children: g.label }),
|
|
7967
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
|
|
7715
7968
|
"CRP ",
|
|
7716
7969
|
g.range
|
|
7717
7970
|
] })
|
|
@@ -7721,10 +7974,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
7721
7974
|
g.key
|
|
7722
7975
|
);
|
|
7723
7976
|
}) }),
|
|
7724
|
-
floorBand ? /* @__PURE__ */ (0,
|
|
7725
|
-
/* @__PURE__ */ (0,
|
|
7726
|
-
/* @__PURE__ */ (0,
|
|
7727
|
-
/* @__PURE__ */ (0,
|
|
7977
|
+
floorBand ? /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("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: [
|
|
7978
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
|
|
7979
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
|
|
7980
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("strong", { style: { color: "var(--text)" }, children: [
|
|
7728
7981
|
"Plan floor ",
|
|
7729
7982
|
floorScore
|
|
7730
7983
|
] }),
|
|
@@ -7735,21 +7988,21 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
7735
7988
|
}
|
|
7736
7989
|
|
|
7737
7990
|
// src/components/planner/MixGap.tsx
|
|
7738
|
-
var
|
|
7739
|
-
var
|
|
7991
|
+
var React34 = __toESM(require("react"), 1);
|
|
7992
|
+
var import_jsx_runtime65 = require("react/jsx-runtime");
|
|
7740
7993
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
7741
7994
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
7742
|
-
const [hover, setHover] =
|
|
7995
|
+
const [hover, setHover] = React34.useState(null);
|
|
7743
7996
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
7744
7997
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
7745
|
-
return /* @__PURE__ */ (0,
|
|
7746
|
-
/* @__PURE__ */ (0,
|
|
7747
|
-
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0,
|
|
7748
|
-
/* @__PURE__ */ (0,
|
|
7998
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
|
|
7999
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
|
|
8000
|
+
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
8001
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
|
|
7749
8002
|
l
|
|
7750
8003
|
] }, l)),
|
|
7751
|
-
/* @__PURE__ */ (0,
|
|
7752
|
-
/* @__PURE__ */ (0,
|
|
8004
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
8005
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { width: 3, height: 14, background: "var(--n-500)" } }),
|
|
7753
8006
|
"Target"
|
|
7754
8007
|
] })
|
|
7755
8008
|
] }),
|
|
@@ -7757,7 +8010,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
7757
8010
|
const gap = r.realized - r.target;
|
|
7758
8011
|
const tone = toneOf(gap);
|
|
7759
8012
|
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 : "");
|
|
7760
|
-
return /* @__PURE__ */ (0,
|
|
8013
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
|
|
7761
8014
|
"div",
|
|
7762
8015
|
{
|
|
7763
8016
|
className: "fd-row",
|
|
@@ -7765,15 +8018,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
7765
8018
|
onMouseEnter: () => setHover(r.channel),
|
|
7766
8019
|
onMouseLeave: () => setHover(null),
|
|
7767
8020
|
children: [
|
|
7768
|
-
/* @__PURE__ */ (0,
|
|
7769
|
-
/* @__PURE__ */ (0,
|
|
7770
|
-
/* @__PURE__ */ (0,
|
|
7771
|
-
/* @__PURE__ */ (0,
|
|
7772
|
-
/* @__PURE__ */ (0,
|
|
8021
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(ChannelTag, { channel: r.channel, size: "sm" }) }),
|
|
8022
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { position: "relative", flex: 1, height: 22, minWidth: 120 }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "fd-skel", style: { position: "absolute", inset: "5px 0", borderRadius: 3 } }) : /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(import_jsx_runtime65.Fragment, { children: [
|
|
8023
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { position: "absolute", left: 0, top: 5, height: 12, width: r.realized / max * 100 + "%", background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
|
|
8024
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { position: "absolute", left: r.target / max * 100 + "%", top: 0, width: 3, height: 22, background: "var(--n-500)", borderRadius: 1 } }),
|
|
8025
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("span", { className: "fd-num", style: { position: "absolute", right: Math.max(r.realized, r.target) / max > 0.82 ? 0 : "auto", left: Math.max(r.realized, r.target) / max > 0.82 ? "auto" : "calc(" + Math.max(r.realized, r.target) / max * 100 + "% + 10px)", top: 2, fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap", background: Math.max(r.realized, r.target) / max > 0.82 ? "var(--surface)" : "none", paddingLeft: 3 }, children: [
|
|
7773
8026
|
r.realized,
|
|
7774
8027
|
"%"
|
|
7775
8028
|
] }),
|
|
7776
|
-
hover === r.channel ? /* @__PURE__ */ (0,
|
|
8029
|
+
hover === r.channel ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: 26, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
|
|
7777
8030
|
] }) })
|
|
7778
8031
|
]
|
|
7779
8032
|
},
|
|
@@ -7784,7 +8037,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
7784
8037
|
}
|
|
7785
8038
|
|
|
7786
8039
|
// src/components/planner/ChannelContribution.tsx
|
|
7787
|
-
var
|
|
8040
|
+
var import_jsx_runtime66 = require("react/jsx-runtime");
|
|
7788
8041
|
var money = (n) => "$" + Math.round(n).toLocaleString();
|
|
7789
8042
|
function ChannelContribution({
|
|
7790
8043
|
channels = [],
|
|
@@ -7800,9 +8053,9 @@ function ChannelContribution({
|
|
|
7800
8053
|
const grand = total !== void 0 ? total : base + bonus;
|
|
7801
8054
|
const pct = (v) => grand ? v / grand * 100 : 0;
|
|
7802
8055
|
const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
|
|
7803
|
-
return /* @__PURE__ */ (0,
|
|
7804
|
-
loading ? /* @__PURE__ */ (0,
|
|
7805
|
-
channels.map((c) => /* @__PURE__ */ (0,
|
|
8056
|
+
return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
8057
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
|
|
8058
|
+
channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
|
|
7806
8059
|
"span",
|
|
7807
8060
|
{
|
|
7808
8061
|
title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
|
|
@@ -7811,7 +8064,7 @@ function ChannelContribution({
|
|
|
7811
8064
|
},
|
|
7812
8065
|
c.name
|
|
7813
8066
|
)),
|
|
7814
|
-
bonus > 0 ? /* @__PURE__ */ (0,
|
|
8067
|
+
bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
|
|
7815
8068
|
"span",
|
|
7816
8069
|
{
|
|
7817
8070
|
title: "Surround-sound bonus +" + bonusPct + "%",
|
|
@@ -7820,18 +8073,18 @@ function ChannelContribution({
|
|
|
7820
8073
|
}
|
|
7821
8074
|
) : null
|
|
7822
8075
|
] }),
|
|
7823
|
-
showTable ? /* @__PURE__ */ (0,
|
|
7824
|
-
/* @__PURE__ */ (0,
|
|
7825
|
-
/* @__PURE__ */ (0,
|
|
7826
|
-
/* @__PURE__ */ (0,
|
|
7827
|
-
/* @__PURE__ */ (0,
|
|
7828
|
-
/* @__PURE__ */ (0,
|
|
7829
|
-
/* @__PURE__ */ (0,
|
|
8076
|
+
showTable ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
|
|
8077
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { children: [
|
|
8078
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { style: { width: "34%" }, children: "Channel" }),
|
|
8079
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { style: { width: "16%" }, children: "Weight" }),
|
|
8080
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
|
|
8081
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
|
|
8082
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
|
|
7830
8083
|
] }) }),
|
|
7831
|
-
/* @__PURE__ */ (0,
|
|
7832
|
-
channels.map((c) => /* @__PURE__ */ (0,
|
|
7833
|
-
/* @__PURE__ */ (0,
|
|
7834
|
-
/* @__PURE__ */ (0,
|
|
8084
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tbody", { children: [
|
|
8085
|
+
channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { children: [
|
|
8086
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(ChannelTag, { channel: c.name, size: "sm" }) }),
|
|
8087
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
|
|
7835
8088
|
"span",
|
|
7836
8089
|
{
|
|
7837
8090
|
className: "fd-badge fd-badge-neutral",
|
|
@@ -7840,38 +8093,38 @@ function ChannelContribution({
|
|
|
7840
8093
|
children: "weight " + (channelWeightOf(c.name) || 0)
|
|
7841
8094
|
}
|
|
7842
8095
|
) }),
|
|
7843
|
-
/* @__PURE__ */ (0,
|
|
7844
|
-
/* @__PURE__ */ (0,
|
|
7845
|
-
/* @__PURE__ */ (0,
|
|
8096
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", children: c.spend }),
|
|
8097
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", children: c.crp.toFixed(1) }),
|
|
8098
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("td", { className: "is-num", children: [
|
|
7846
8099
|
pct(c.crp).toFixed(0),
|
|
7847
8100
|
"%"
|
|
7848
8101
|
] })
|
|
7849
8102
|
] }, c.name)),
|
|
7850
|
-
bonus > 0 ? /* @__PURE__ */ (0,
|
|
7851
|
-
/* @__PURE__ */ (0,
|
|
7852
|
-
/* @__PURE__ */ (0,
|
|
8103
|
+
bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { children: [
|
|
8104
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
|
|
8105
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("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" } }),
|
|
7853
8106
|
"Surround-sound bonus"
|
|
7854
8107
|
] }) }),
|
|
7855
|
-
/* @__PURE__ */ (0,
|
|
8108
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
|
|
7856
8109
|
"+",
|
|
7857
8110
|
bonusPct,
|
|
7858
8111
|
"% of +",
|
|
7859
8112
|
bonusMax,
|
|
7860
8113
|
"%"
|
|
7861
8114
|
] }) }),
|
|
7862
|
-
/* @__PURE__ */ (0,
|
|
7863
|
-
/* @__PURE__ */ (0,
|
|
7864
|
-
/* @__PURE__ */ (0,
|
|
8115
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num fd-muted", children: "\u2014" }),
|
|
8116
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", children: bonus.toFixed(1) }),
|
|
8117
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("td", { className: "is-num", children: [
|
|
7865
8118
|
pct(bonus).toFixed(0),
|
|
7866
8119
|
"%"
|
|
7867
8120
|
] })
|
|
7868
8121
|
] }) : null,
|
|
7869
|
-
/* @__PURE__ */ (0,
|
|
7870
|
-
/* @__PURE__ */ (0,
|
|
7871
|
-
/* @__PURE__ */ (0,
|
|
7872
|
-
/* @__PURE__ */ (0,
|
|
7873
|
-
/* @__PURE__ */ (0,
|
|
7874
|
-
/* @__PURE__ */ (0,
|
|
8122
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { style: { background: "var(--surface-2)" }, children: [
|
|
8123
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { style: { fontWeight: 700 }, children: "Campus total" }),
|
|
8124
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", {}),
|
|
8125
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
|
|
8126
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
|
|
8127
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
|
|
7875
8128
|
] })
|
|
7876
8129
|
] })
|
|
7877
8130
|
] }) : null
|
|
@@ -7879,8 +8132,8 @@ function ChannelContribution({
|
|
|
7879
8132
|
}
|
|
7880
8133
|
|
|
7881
8134
|
// src/components/planner/BudgetReallocator.tsx
|
|
7882
|
-
var
|
|
7883
|
-
var
|
|
8135
|
+
var React35 = __toESM(require("react"), 1);
|
|
8136
|
+
var import_jsx_runtime67 = require("react/jsx-runtime");
|
|
7884
8137
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
7885
8138
|
function BudgetReallocator({
|
|
7886
8139
|
campus,
|
|
@@ -7895,8 +8148,8 @@ function BudgetReallocator({
|
|
|
7895
8148
|
onCancel,
|
|
7896
8149
|
className = ""
|
|
7897
8150
|
}) {
|
|
7898
|
-
const [draft, setDraft] =
|
|
7899
|
-
|
|
8151
|
+
const [draft, setDraft] = React35.useState(spend);
|
|
8152
|
+
React35.useEffect(() => setDraft(spend), [spend]);
|
|
7900
8153
|
const dirty = draft !== spend;
|
|
7901
8154
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
7902
8155
|
const nextBand = bandFor(nextCrp);
|
|
@@ -7911,24 +8164,24 @@ function BudgetReallocator({
|
|
|
7911
8164
|
setDraft(spend);
|
|
7912
8165
|
if (onCancel) onCancel();
|
|
7913
8166
|
};
|
|
7914
|
-
return /* @__PURE__ */ (0,
|
|
8167
|
+
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
|
|
7915
8168
|
"div",
|
|
7916
8169
|
{
|
|
7917
8170
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
7918
8171
|
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)" },
|
|
7919
8172
|
children: [
|
|
7920
|
-
/* @__PURE__ */ (0,
|
|
7921
|
-
/* @__PURE__ */ (0,
|
|
7922
|
-
/* @__PURE__ */ (0,
|
|
7923
|
-
dirty ? /* @__PURE__ */ (0,
|
|
7924
|
-
/* @__PURE__ */ (0,
|
|
7925
|
-
/* @__PURE__ */ (0,
|
|
8173
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
8174
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
|
|
8175
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)(CsiBadge, { band: nowBand, crp: Number(crp.toFixed(1)), size: "medium" }),
|
|
8176
|
+
dirty ? /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(import_jsx_runtime67.Fragment, { children: [
|
|
8177
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
|
|
8178
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)(CsiBadge, { band: nextBand, crp: Number(nextCrp.toFixed(1)), size: "medium", preview: true })
|
|
7926
8179
|
] }) : null
|
|
7927
8180
|
] }),
|
|
7928
|
-
/* @__PURE__ */ (0,
|
|
7929
|
-
/* @__PURE__ */ (0,
|
|
7930
|
-
dirty ? /* @__PURE__ */ (0,
|
|
7931
|
-
/* @__PURE__ */ (0,
|
|
8181
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fd-slider", children: [
|
|
8182
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
8183
|
+
dirty ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("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,
|
|
8184
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
|
|
7932
8185
|
"input",
|
|
7933
8186
|
{
|
|
7934
8187
|
type: "range",
|
|
@@ -7944,13 +8197,13 @@ function BudgetReallocator({
|
|
|
7944
8197
|
}
|
|
7945
8198
|
)
|
|
7946
8199
|
] }),
|
|
7947
|
-
/* @__PURE__ */ (0,
|
|
7948
|
-
/* @__PURE__ */ (0,
|
|
7949
|
-
/* @__PURE__ */ (0,
|
|
7950
|
-
/* @__PURE__ */ (0,
|
|
8200
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
8201
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
|
|
8202
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
|
|
8203
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
|
|
7951
8204
|
] }),
|
|
7952
|
-
/* @__PURE__ */ (0,
|
|
7953
|
-
/* @__PURE__ */ (0,
|
|
8205
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
|
|
8206
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
|
|
7954
8207
|
"button",
|
|
7955
8208
|
{
|
|
7956
8209
|
type: "button",
|
|
@@ -7969,7 +8222,7 @@ function BudgetReallocator({
|
|
|
7969
8222
|
}
|
|
7970
8223
|
|
|
7971
8224
|
// src/components/planner/SurroundSound.tsx
|
|
7972
|
-
var
|
|
8225
|
+
var import_jsx_runtime68 = require("react/jsx-runtime");
|
|
7973
8226
|
var CATEGORIES = [
|
|
7974
8227
|
{ key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
|
|
7975
8228
|
{ key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
|
|
@@ -7981,26 +8234,26 @@ var CATEGORIES = [
|
|
|
7981
8234
|
function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
|
|
7982
8235
|
const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
|
|
7983
8236
|
const single = present.length <= 2;
|
|
7984
|
-
return /* @__PURE__ */ (0,
|
|
7985
|
-
/* @__PURE__ */ (0,
|
|
8237
|
+
return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
|
|
8238
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
|
|
7986
8239
|
const on = present.includes(c.key);
|
|
7987
|
-
return /* @__PURE__ */ (0,
|
|
8240
|
+
return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
|
|
7988
8241
|
"span",
|
|
7989
8242
|
{
|
|
7990
8243
|
title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
|
|
7991
8244
|
style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 5, width: 62, padding: "10px 0", borderRadius: "var(--r-md)", border: "1px solid " + (on ? "var(--csi-2-edge)" : "var(--border)"), background: on ? "var(--csi-2-fill)" : "var(--surface-2)", color: on ? "var(--csi-2-text)" : "var(--text-disabled)" },
|
|
7992
8245
|
children: [
|
|
7993
|
-
/* @__PURE__ */ (0,
|
|
7994
|
-
/* @__PURE__ */ (0,
|
|
8246
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
8247
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
|
|
7995
8248
|
]
|
|
7996
8249
|
},
|
|
7997
8250
|
c.key
|
|
7998
8251
|
);
|
|
7999
8252
|
}) }),
|
|
8000
|
-
/* @__PURE__ */ (0,
|
|
8001
|
-
/* @__PURE__ */ (0,
|
|
8002
|
-
/* @__PURE__ */ (0,
|
|
8003
|
-
/* @__PURE__ */ (0,
|
|
8253
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
8254
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
8255
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
|
|
8256
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
|
|
8004
8257
|
"+",
|
|
8005
8258
|
bonusPct,
|
|
8006
8259
|
"% of +",
|
|
@@ -8008,8 +8261,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
8008
8261
|
"%"
|
|
8009
8262
|
] })
|
|
8010
8263
|
] }),
|
|
8011
|
-
/* @__PURE__ */ (0,
|
|
8012
|
-
/* @__PURE__ */ (0,
|
|
8264
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
|
|
8265
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
|
|
8013
8266
|
present.length,
|
|
8014
8267
|
" of 6 channel categories present.",
|
|
8015
8268
|
" ",
|
|
@@ -8021,10 +8274,10 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
8021
8274
|
}
|
|
8022
8275
|
|
|
8023
8276
|
// src/components/chat/AgentChatPanel.tsx
|
|
8024
|
-
var
|
|
8277
|
+
var React41 = __toESM(require("react"), 1);
|
|
8025
8278
|
|
|
8026
8279
|
// src/components/chat/chatEngine.ts
|
|
8027
|
-
var
|
|
8280
|
+
var React36 = __toESM(require("react"), 1);
|
|
8028
8281
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
8029
8282
|
var JOB_PENDING = ["queued", "running"];
|
|
8030
8283
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -8078,22 +8331,22 @@ function useChatEngine(opts) {
|
|
|
8078
8331
|
onClear,
|
|
8079
8332
|
onFeedback
|
|
8080
8333
|
} = opts || {};
|
|
8081
|
-
const [status, setStatus] =
|
|
8082
|
-
const [threadId, setThreadId] =
|
|
8083
|
-
const [messages, setMessages] =
|
|
8084
|
-
const [queue, setQueue] =
|
|
8085
|
-
const [fatal, setFatal] =
|
|
8086
|
-
const [busy, setBusy] =
|
|
8087
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
8088
|
-
const listRef =
|
|
8089
|
-
const queueRef =
|
|
8090
|
-
const busyRef =
|
|
8091
|
-
const stoppedRef =
|
|
8092
|
-
const abortRef =
|
|
8093
|
-
const serverCount =
|
|
8094
|
-
const threadRef =
|
|
8095
|
-
const mounted =
|
|
8096
|
-
|
|
8334
|
+
const [status, setStatus] = React36.useState("idle");
|
|
8335
|
+
const [threadId, setThreadId] = React36.useState(null);
|
|
8336
|
+
const [messages, setMessages] = React36.useState([]);
|
|
8337
|
+
const [queue, setQueue] = React36.useState([]);
|
|
8338
|
+
const [fatal, setFatal] = React36.useState(null);
|
|
8339
|
+
const [busy, setBusy] = React36.useState(false);
|
|
8340
|
+
const [turnStartedAt, setTurnStartedAt] = React36.useState(null);
|
|
8341
|
+
const listRef = React36.useRef([]);
|
|
8342
|
+
const queueRef = React36.useRef([]);
|
|
8343
|
+
const busyRef = React36.useRef(false);
|
|
8344
|
+
const stoppedRef = React36.useRef(false);
|
|
8345
|
+
const abortRef = React36.useRef(null);
|
|
8346
|
+
const serverCount = React36.useRef(0);
|
|
8347
|
+
const threadRef = React36.useRef(null);
|
|
8348
|
+
const mounted = React36.useRef(true);
|
|
8349
|
+
React36.useEffect(() => {
|
|
8097
8350
|
mounted.current = true;
|
|
8098
8351
|
return () => {
|
|
8099
8352
|
mounted.current = false;
|
|
@@ -8115,14 +8368,14 @@ function useChatEngine(opts) {
|
|
|
8115
8368
|
}
|
|
8116
8369
|
return false;
|
|
8117
8370
|
};
|
|
8118
|
-
const loadThread =
|
|
8371
|
+
const loadThread = React36.useCallback(async (id) => {
|
|
8119
8372
|
const data = await apiAdapter.getThread(id);
|
|
8120
8373
|
const list = [...data && data.messages || []];
|
|
8121
8374
|
serverCount.current = list.length;
|
|
8122
8375
|
commit(list);
|
|
8123
8376
|
return list;
|
|
8124
8377
|
}, [apiAdapter]);
|
|
8125
|
-
|
|
8378
|
+
React36.useEffect(() => {
|
|
8126
8379
|
if (!apiAdapter) {
|
|
8127
8380
|
setStatus("idle");
|
|
8128
8381
|
setFatal(null);
|
|
@@ -8335,7 +8588,7 @@ function useChatEngine(opts) {
|
|
|
8335
8588
|
await dispatchTurn(turn);
|
|
8336
8589
|
}
|
|
8337
8590
|
}
|
|
8338
|
-
const send =
|
|
8591
|
+
const send = React36.useCallback((text, attachments) => {
|
|
8339
8592
|
const body = (text || "").trim();
|
|
8340
8593
|
if (!body && !(attachments && attachments.length)) return;
|
|
8341
8594
|
if (status === "disconnected") return;
|
|
@@ -8345,7 +8598,7 @@ function useChatEngine(opts) {
|
|
|
8345
8598
|
stoppedRef.current = false;
|
|
8346
8599
|
drain();
|
|
8347
8600
|
}, [status]);
|
|
8348
|
-
const stop =
|
|
8601
|
+
const stop = React36.useCallback(() => {
|
|
8349
8602
|
stoppedRef.current = true;
|
|
8350
8603
|
const ac = abortRef.current;
|
|
8351
8604
|
if (ac) {
|
|
@@ -8364,11 +8617,11 @@ function useChatEngine(opts) {
|
|
|
8364
8617
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
8365
8618
|
}
|
|
8366
8619
|
}, [apiAdapter]);
|
|
8367
|
-
const removeQueued =
|
|
8620
|
+
const removeQueued = React36.useCallback((id) => {
|
|
8368
8621
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
8369
8622
|
setQueue(queueRef.current.slice());
|
|
8370
8623
|
}, []);
|
|
8371
|
-
const retry =
|
|
8624
|
+
const retry = React36.useCallback(() => {
|
|
8372
8625
|
const list = listRef.current;
|
|
8373
8626
|
let at = -1;
|
|
8374
8627
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -8384,19 +8637,19 @@ function useChatEngine(opts) {
|
|
|
8384
8637
|
setQueue(queueRef.current.slice());
|
|
8385
8638
|
drain();
|
|
8386
8639
|
}, []);
|
|
8387
|
-
const clear =
|
|
8640
|
+
const clear = React36.useCallback(() => {
|
|
8388
8641
|
commit([]);
|
|
8389
8642
|
serverCount.current = 0;
|
|
8390
8643
|
queueRef.current = [];
|
|
8391
8644
|
setQueue([]);
|
|
8392
8645
|
onClear && onClear();
|
|
8393
8646
|
}, [onClear]);
|
|
8394
|
-
const setFeedback =
|
|
8647
|
+
const setFeedback = React36.useCallback((id, value) => {
|
|
8395
8648
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
8396
8649
|
const msg = listRef.current.find((m) => m.id === id);
|
|
8397
8650
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
8398
8651
|
}, [onFeedback]);
|
|
8399
|
-
const reload =
|
|
8652
|
+
const reload = React36.useCallback(async () => {
|
|
8400
8653
|
if (!threadRef.current) return;
|
|
8401
8654
|
setStatus("loading");
|
|
8402
8655
|
try {
|
|
@@ -8434,11 +8687,11 @@ var ChatKit = {
|
|
|
8434
8687
|
};
|
|
8435
8688
|
|
|
8436
8689
|
// src/components/chat/ChatTranscript.tsx
|
|
8437
|
-
var
|
|
8690
|
+
var React38 = __toESM(require("react"), 1);
|
|
8438
8691
|
|
|
8439
8692
|
// src/components/chat/ChatTurn.tsx
|
|
8440
|
-
var
|
|
8441
|
-
var
|
|
8693
|
+
var React37 = __toESM(require("react"), 1);
|
|
8694
|
+
var import_jsx_runtime69 = require("react/jsx-runtime");
|
|
8442
8695
|
function JsonView({ value }) {
|
|
8443
8696
|
let text;
|
|
8444
8697
|
try {
|
|
@@ -8446,67 +8699,67 @@ function JsonView({ value }) {
|
|
|
8446
8699
|
} catch (e) {
|
|
8447
8700
|
text = String(value);
|
|
8448
8701
|
}
|
|
8449
|
-
return /* @__PURE__ */ (0,
|
|
8702
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
|
|
8450
8703
|
}
|
|
8451
8704
|
function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
8452
8705
|
if (!packet) return null;
|
|
8453
8706
|
const s = schema || {};
|
|
8454
8707
|
const invalid = packet.valid === false;
|
|
8455
8708
|
const title = s.heading || packet.type;
|
|
8456
|
-
return /* @__PURE__ */ (0,
|
|
8457
|
-
/* @__PURE__ */ (0,
|
|
8458
|
-
/* @__PURE__ */ (0,
|
|
8459
|
-
/* @__PURE__ */ (0,
|
|
8460
|
-
packet.repaired ? /* @__PURE__ */ (0,
|
|
8461
|
-
invalid ? /* @__PURE__ */ (0,
|
|
8709
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
|
|
8710
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("header", { className: "fdc-packet-head", children: [
|
|
8711
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
|
|
8712
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-packet-title", children: title }),
|
|
8713
|
+
packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
|
|
8714
|
+
invalid ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
|
|
8462
8715
|
] }),
|
|
8463
|
-
invalid ? /* @__PURE__ */ (0,
|
|
8464
|
-
/* @__PURE__ */ (0,
|
|
8465
|
-
/* @__PURE__ */ (0,
|
|
8466
|
-
] }) : /* @__PURE__ */ (0,
|
|
8467
|
-
!invalid && onApply ? /* @__PURE__ */ (0,
|
|
8468
|
-
packet.repaired ? /* @__PURE__ */ (0,
|
|
8469
|
-
/* @__PURE__ */ (0,
|
|
8470
|
-
/* @__PURE__ */ (0,
|
|
8716
|
+
invalid ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-packet-alert", role: "alert", children: [
|
|
8717
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
8718
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
|
|
8719
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(JsonView, { value: packet.payload }) }),
|
|
8720
|
+
!invalid && onApply ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("footer", { className: "fdc-packet-foot", children: [
|
|
8721
|
+
packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
|
|
8722
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
|
|
8723
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
|
|
8471
8724
|
applied ? "Applied" : s.applyLabel || "Apply"
|
|
8472
8725
|
] })
|
|
8473
8726
|
] }) : null
|
|
8474
8727
|
] });
|
|
8475
8728
|
}
|
|
8476
8729
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
8477
|
-
const [open, setOpen] =
|
|
8730
|
+
const [open, setOpen] = React37.useState(defaultOpen);
|
|
8478
8731
|
if (!text) return null;
|
|
8479
|
-
return /* @__PURE__ */ (0,
|
|
8480
|
-
/* @__PURE__ */ (0,
|
|
8481
|
-
/* @__PURE__ */ (0,
|
|
8482
|
-
/* @__PURE__ */ (0,
|
|
8483
|
-
streaming ? /* @__PURE__ */ (0,
|
|
8484
|
-
/* @__PURE__ */ (0,
|
|
8485
|
-
/* @__PURE__ */ (0,
|
|
8486
|
-
/* @__PURE__ */ (0,
|
|
8732
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
|
|
8733
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
8734
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-brain", "aria-hidden": "true" }),
|
|
8735
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
|
|
8736
|
+
streaming ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
8737
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
|
|
8738
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
|
|
8739
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {})
|
|
8487
8740
|
] }) : null,
|
|
8488
|
-
/* @__PURE__ */ (0,
|
|
8741
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
|
|
8489
8742
|
] }),
|
|
8490
|
-
open ? /* @__PURE__ */ (0,
|
|
8743
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "fdc-think-body", children: text }) : null
|
|
8491
8744
|
] });
|
|
8492
8745
|
}
|
|
8493
8746
|
function Citations({ items = [], onOpen }) {
|
|
8494
|
-
const [open, setOpen] =
|
|
8747
|
+
const [open, setOpen] = React37.useState(false);
|
|
8495
8748
|
if (!items.length) return null;
|
|
8496
|
-
return /* @__PURE__ */ (0,
|
|
8497
|
-
/* @__PURE__ */ (0,
|
|
8498
|
-
/* @__PURE__ */ (0,
|
|
8499
|
-
/* @__PURE__ */ (0,
|
|
8749
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-cites", children: [
|
|
8750
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
8751
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
|
|
8752
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { children: [
|
|
8500
8753
|
items.length,
|
|
8501
8754
|
" source",
|
|
8502
8755
|
items.length === 1 ? "" : "s"
|
|
8503
8756
|
] }),
|
|
8504
|
-
/* @__PURE__ */ (0,
|
|
8757
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
|
|
8505
8758
|
] }),
|
|
8506
|
-
open ? /* @__PURE__ */ (0,
|
|
8507
|
-
/* @__PURE__ */ (0,
|
|
8508
|
-
c.url ? /* @__PURE__ */ (0,
|
|
8509
|
-
c.detail ? /* @__PURE__ */ (0,
|
|
8759
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("li", { children: [
|
|
8760
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
|
|
8761
|
+
c.url ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: c.title || "Source" }),
|
|
8762
|
+
c.detail ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-cite-detail", children: c.detail }) : null
|
|
8510
8763
|
] }, c.id || i)) }) : null
|
|
8511
8764
|
] });
|
|
8512
8765
|
}
|
|
@@ -8517,29 +8770,29 @@ function clampText(text, max) {
|
|
|
8517
8770
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
8518
8771
|
}
|
|
8519
8772
|
function MessageBody({ message: m, ctx }) {
|
|
8520
|
-
const [expanded, setExpanded] =
|
|
8773
|
+
const [expanded, setExpanded] = React37.useState(false);
|
|
8521
8774
|
const isUser = m.role === "user";
|
|
8522
8775
|
const raw = m.text || "";
|
|
8523
8776
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
8524
8777
|
const body = clamped != null ? clamped : raw;
|
|
8525
8778
|
const showMd = ctx.markdown && !isUser;
|
|
8526
|
-
return /* @__PURE__ */ (0,
|
|
8527
|
-
m.thinking && ctx.showThinking ? /* @__PURE__ */ (0,
|
|
8528
|
-
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0,
|
|
8529
|
-
body ? /* @__PURE__ */ (0,
|
|
8530
|
-
showMd ? /* @__PURE__ */ (0,
|
|
8531
|
-
m.streaming ? /* @__PURE__ */ (0,
|
|
8779
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-body", children: [
|
|
8780
|
+
m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
|
|
8781
|
+
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
|
|
8782
|
+
body ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
|
|
8783
|
+
showMd ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "fdc-plain", children: body }),
|
|
8784
|
+
m.streaming ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
|
|
8532
8785
|
] }) : null,
|
|
8533
|
-
clamped != null ? /* @__PURE__ */ (0,
|
|
8534
|
-
/* @__PURE__ */ (0,
|
|
8786
|
+
clamped != null ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
|
|
8787
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
|
|
8535
8788
|
"Show more",
|
|
8536
|
-
/* @__PURE__ */ (0,
|
|
8537
|
-
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0,
|
|
8538
|
-
/* @__PURE__ */ (0,
|
|
8789
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
|
|
8790
|
+
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
|
|
8791
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
|
|
8539
8792
|
"Show less"
|
|
8540
8793
|
] }) : null,
|
|
8541
|
-
m.attachments && m.attachments.length ? /* @__PURE__ */ (0,
|
|
8542
|
-
m.packet ? /* @__PURE__ */ (0,
|
|
8794
|
+
m.attachments && m.attachments.length ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
|
|
8795
|
+
m.packet ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
|
|
8543
8796
|
PacketCard,
|
|
8544
8797
|
{
|
|
8545
8798
|
packet: m.packet,
|
|
@@ -8549,44 +8802,44 @@ function MessageBody({ message: m, ctx }) {
|
|
|
8549
8802
|
applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
|
|
8550
8803
|
}
|
|
8551
8804
|
) : null,
|
|
8552
|
-
m.citations && m.citations.length ? /* @__PURE__ */ (0,
|
|
8553
|
-
m.working ? /* @__PURE__ */ (0,
|
|
8554
|
-
/* @__PURE__ */ (0,
|
|
8555
|
-
/* @__PURE__ */ (0,
|
|
8556
|
-
/* @__PURE__ */ (0,
|
|
8557
|
-
/* @__PURE__ */ (0,
|
|
8805
|
+
m.citations && m.citations.length ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
|
|
8806
|
+
m.working ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-working", role: "status", children: [
|
|
8807
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
8808
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
|
|
8809
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
|
|
8810
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {})
|
|
8558
8811
|
] }),
|
|
8559
|
-
/* @__PURE__ */ (0,
|
|
8812
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-working-label", children: [
|
|
8560
8813
|
m.resumed ? "Resuming" : "Working",
|
|
8561
|
-
m.job && m.job.status ? /* @__PURE__ */ (0,
|
|
8814
|
+
m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-working-job", children: [
|
|
8562
8815
|
" \xB7 ",
|
|
8563
8816
|
m.job.status
|
|
8564
8817
|
] }) : null,
|
|
8565
|
-
m.job && m.job.detail ? /* @__PURE__ */ (0,
|
|
8818
|
+
m.job && m.job.detail ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-working-job", children: [
|
|
8566
8819
|
" \xB7 ",
|
|
8567
8820
|
m.job.detail
|
|
8568
8821
|
] }) : null
|
|
8569
8822
|
] }),
|
|
8570
|
-
m.jobId ? /* @__PURE__ */ (0,
|
|
8823
|
+
m.jobId ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
|
|
8571
8824
|
] }) : null,
|
|
8572
|
-
m.stopped ? /* @__PURE__ */ (0,
|
|
8573
|
-
/* @__PURE__ */ (0,
|
|
8825
|
+
m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-stopped", children: [
|
|
8826
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
8574
8827
|
"Stopped"
|
|
8575
8828
|
] }) : null,
|
|
8576
|
-
m.error ? /* @__PURE__ */ (0,
|
|
8577
|
-
/* @__PURE__ */ (0,
|
|
8578
|
-
/* @__PURE__ */ (0,
|
|
8579
|
-
m.retryable && ctx.onRetry ? /* @__PURE__ */ (0,
|
|
8580
|
-
/* @__PURE__ */ (0,
|
|
8829
|
+
m.error ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-error", role: "alert", children: [
|
|
8830
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
8831
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
|
|
8832
|
+
m.retryable && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
|
|
8833
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
8581
8834
|
"Retry"
|
|
8582
8835
|
] }) : null
|
|
8583
8836
|
] }) : null
|
|
8584
8837
|
] });
|
|
8585
8838
|
}
|
|
8586
8839
|
function useCopyRun() {
|
|
8587
|
-
const [done, setDone] =
|
|
8588
|
-
const t =
|
|
8589
|
-
|
|
8840
|
+
const [done, setDone] = React37.useState(false);
|
|
8841
|
+
const t = React37.useRef(null);
|
|
8842
|
+
React37.useEffect(() => () => {
|
|
8590
8843
|
if (t.current) clearTimeout(t.current);
|
|
8591
8844
|
}, []);
|
|
8592
8845
|
return [done, (text) => {
|
|
@@ -8606,16 +8859,16 @@ function RunActions({ group, ctx }) {
|
|
|
8606
8859
|
const isAssistant = group.role === "assistant";
|
|
8607
8860
|
const fb = last.feedback;
|
|
8608
8861
|
if (!ctx.messageActions) return null;
|
|
8609
|
-
return /* @__PURE__ */ (0,
|
|
8610
|
-
/* @__PURE__ */ (0,
|
|
8611
|
-
/* @__PURE__ */ (0,
|
|
8612
|
-
/* @__PURE__ */ (0,
|
|
8862
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
|
|
8863
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
|
|
8864
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
|
|
8865
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
|
|
8613
8866
|
] }),
|
|
8614
|
-
isAssistant && ctx.onRetry ? /* @__PURE__ */ (0,
|
|
8615
|
-
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0,
|
|
8616
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0,
|
|
8617
|
-
/* @__PURE__ */ (0,
|
|
8618
|
-
/* @__PURE__ */ (0,
|
|
8867
|
+
isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
8868
|
+
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
8869
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(React37.Fragment, { children: [
|
|
8870
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("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__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
8871
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("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__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
8619
8872
|
] }) : null,
|
|
8620
8873
|
ctx.extraActions ? ctx.extraActions(group) : null
|
|
8621
8874
|
] });
|
|
@@ -8625,22 +8878,22 @@ function ChatTurn({ group, ctx }) {
|
|
|
8625
8878
|
const name = isUser ? ctx.userName : group.author || ctx.assistantName;
|
|
8626
8879
|
const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
|
|
8627
8880
|
const stamp = group.messages[0].timestamp;
|
|
8628
|
-
return /* @__PURE__ */ (0,
|
|
8629
|
-
/* @__PURE__ */ (0,
|
|
8630
|
-
ctx.showAvatars ? /* @__PURE__ */ (0,
|
|
8631
|
-
/* @__PURE__ */ (0,
|
|
8632
|
-
stamp ? /* @__PURE__ */ (0,
|
|
8633
|
-
group.messages.some((m) => m.model) ? /* @__PURE__ */ (0,
|
|
8881
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
|
|
8882
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-turn-head", children: [
|
|
8883
|
+
ctx.showAvatars ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
|
|
8884
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-who", children: name }),
|
|
8885
|
+
stamp ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(RelativeTime, { className: "fdc-when", value: stamp }) : null,
|
|
8886
|
+
group.messages.some((m) => m.model) ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
|
|
8634
8887
|
] }),
|
|
8635
|
-
/* @__PURE__ */ (0,
|
|
8636
|
-
group.messages.map((m) => /* @__PURE__ */ (0,
|
|
8637
|
-
/* @__PURE__ */ (0,
|
|
8888
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-turn-body", children: [
|
|
8889
|
+
group.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(MessageBody, { message: m, ctx }) }, m.id)),
|
|
8890
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)(RunActions, { group, ctx })
|
|
8638
8891
|
] })
|
|
8639
8892
|
] });
|
|
8640
8893
|
}
|
|
8641
8894
|
|
|
8642
8895
|
// src/components/chat/ChatTranscript.tsx
|
|
8643
|
-
var
|
|
8896
|
+
var import_jsx_runtime70 = require("react/jsx-runtime");
|
|
8644
8897
|
var GROUP_WINDOW = 6e4;
|
|
8645
8898
|
var STICK_PX = 100;
|
|
8646
8899
|
function groupMessages(list) {
|
|
@@ -8673,25 +8926,25 @@ function dayLabel(key) {
|
|
|
8673
8926
|
}
|
|
8674
8927
|
function Suggestions({ items = [], onPick }) {
|
|
8675
8928
|
if (!items.length) return null;
|
|
8676
|
-
return /* @__PURE__ */ (0,
|
|
8929
|
+
return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
|
|
8677
8930
|
const it = typeof s === "string" ? { label: s, text: s } : s;
|
|
8678
|
-
return /* @__PURE__ */ (0,
|
|
8679
|
-
it.icon ? /* @__PURE__ */ (0,
|
|
8680
|
-
/* @__PURE__ */ (0,
|
|
8681
|
-
/* @__PURE__ */ (0,
|
|
8682
|
-
it.description ? /* @__PURE__ */ (0,
|
|
8931
|
+
return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
|
|
8932
|
+
it.icon ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
|
|
8933
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "fdc-suggest-text", children: [
|
|
8934
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fdc-suggest-label", children: it.label }),
|
|
8935
|
+
it.description ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fdc-suggest-desc", children: it.description }) : null
|
|
8683
8936
|
] }),
|
|
8684
|
-
/* @__PURE__ */ (0,
|
|
8937
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
|
|
8685
8938
|
] }, it.id || i);
|
|
8686
8939
|
}) });
|
|
8687
8940
|
}
|
|
8688
8941
|
function LoadingTurns() {
|
|
8689
|
-
return /* @__PURE__ */ (0,
|
|
8690
|
-
/* @__PURE__ */ (0,
|
|
8691
|
-
/* @__PURE__ */ (0,
|
|
8692
|
-
/* @__PURE__ */ (0,
|
|
8693
|
-
/* @__PURE__ */ (0,
|
|
8694
|
-
/* @__PURE__ */ (0,
|
|
8942
|
+
return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-skel-turn", children: [
|
|
8943
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
|
|
8944
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-skel-lines", children: [
|
|
8945
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
|
|
8946
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
|
|
8947
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
|
|
8695
8948
|
] })
|
|
8696
8949
|
] }, i)) });
|
|
8697
8950
|
}
|
|
@@ -8708,10 +8961,10 @@ function ChatTranscript({
|
|
|
8708
8961
|
renderEmpty,
|
|
8709
8962
|
className = ""
|
|
8710
8963
|
}) {
|
|
8711
|
-
const scroller =
|
|
8712
|
-
const stick =
|
|
8713
|
-
const [pill, setPill] =
|
|
8714
|
-
const seen =
|
|
8964
|
+
const scroller = React38.useRef(null);
|
|
8965
|
+
const stick = React38.useRef(true);
|
|
8966
|
+
const [pill, setPill] = React38.useState(0);
|
|
8967
|
+
const seen = React38.useRef(0);
|
|
8715
8968
|
const toBottom = (smooth) => {
|
|
8716
8969
|
const el = scroller.current;
|
|
8717
8970
|
if (!el) return;
|
|
@@ -8730,7 +8983,7 @@ function ChatTranscript({
|
|
|
8730
8983
|
seen.current = messages.length;
|
|
8731
8984
|
}
|
|
8732
8985
|
};
|
|
8733
|
-
|
|
8986
|
+
React38.useLayoutEffect(() => {
|
|
8734
8987
|
const el = scroller.current;
|
|
8735
8988
|
if (!el) return;
|
|
8736
8989
|
if (stick.current) {
|
|
@@ -8738,7 +8991,7 @@ function ChatTranscript({
|
|
|
8738
8991
|
seen.current = messages.length;
|
|
8739
8992
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
8740
8993
|
}, [messages]);
|
|
8741
|
-
|
|
8994
|
+
React38.useEffect(() => {
|
|
8742
8995
|
const el = scroller.current;
|
|
8743
8996
|
const inner = el && el.firstChild;
|
|
8744
8997
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -8748,38 +9001,38 @@ function ChatTranscript({
|
|
|
8748
9001
|
ro.observe(inner);
|
|
8749
9002
|
return () => ro.disconnect();
|
|
8750
9003
|
}, []);
|
|
8751
|
-
const groups =
|
|
9004
|
+
const groups = React38.useMemo(() => groupMessages(messages), [messages]);
|
|
8752
9005
|
const empty = !messages.length && status === "ready";
|
|
8753
|
-
return /* @__PURE__ */ (0,
|
|
8754
|
-
/* @__PURE__ */ (0,
|
|
8755
|
-
status === "loading" || status === "resolving" ? /* @__PURE__ */ (0,
|
|
8756
|
-
status === "disconnected" ? /* @__PURE__ */ (0,
|
|
8757
|
-
/* @__PURE__ */ (0,
|
|
8758
|
-
/* @__PURE__ */ (0,
|
|
8759
|
-
/* @__PURE__ */ (0,
|
|
8760
|
-
ctx.onReconnect ? /* @__PURE__ */ (0,
|
|
8761
|
-
/* @__PURE__ */ (0,
|
|
9006
|
+
return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
9007
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
9008
|
+
status === "loading" || status === "resolving" ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(LoadingTurns, {}) : null,
|
|
9009
|
+
status === "disconnected" ? /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-dead", children: [
|
|
9010
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
|
|
9011
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
|
|
9012
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("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." }),
|
|
9013
|
+
ctx.onReconnect ? /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
|
|
9014
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
8762
9015
|
"Try again"
|
|
8763
9016
|
] }) : null
|
|
8764
9017
|
] }) : null,
|
|
8765
|
-
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0,
|
|
8766
|
-
/* @__PURE__ */ (0,
|
|
8767
|
-
/* @__PURE__ */ (0,
|
|
8768
|
-
emptyDescription ? /* @__PURE__ */ (0,
|
|
8769
|
-
/* @__PURE__ */ (0,
|
|
9018
|
+
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-empty", children: [
|
|
9019
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
|
|
9020
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("h3", { className: "fdc-empty-title", children: emptyTitle }),
|
|
9021
|
+
emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
|
|
9022
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)(Suggestions, { items: suggestions, onPick })
|
|
8770
9023
|
] }) : null,
|
|
8771
9024
|
groups.map((g, i) => {
|
|
8772
9025
|
const prev = groups[i - 1];
|
|
8773
9026
|
const k = dayKey(g.messages[0].timestamp);
|
|
8774
9027
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
8775
|
-
return /* @__PURE__ */ (0,
|
|
8776
|
-
showDay ? /* @__PURE__ */ (0,
|
|
8777
|
-
/* @__PURE__ */ (0,
|
|
9028
|
+
return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(React38.Fragment, { children: [
|
|
9029
|
+
showDay ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { children: dayLabel(k) }) }) : null,
|
|
9030
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)(ChatTurn, { group: g, ctx })
|
|
8778
9031
|
] }, g.key || i);
|
|
8779
9032
|
})
|
|
8780
9033
|
] }),
|
|
8781
|
-
pill ? /* @__PURE__ */ (0,
|
|
8782
|
-
/* @__PURE__ */ (0,
|
|
9034
|
+
pill ? /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
|
|
9035
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
|
|
8783
9036
|
pill,
|
|
8784
9037
|
" new message",
|
|
8785
9038
|
pill === 1 ? "" : "s"
|
|
@@ -8789,8 +9042,8 @@ function ChatTranscript({
|
|
|
8789
9042
|
var TranscriptKit = { groupMessages };
|
|
8790
9043
|
|
|
8791
9044
|
// src/components/chat/ChatComposer.tsx
|
|
8792
|
-
var
|
|
8793
|
-
var
|
|
9045
|
+
var React39 = __toESM(require("react"), 1);
|
|
9046
|
+
var import_jsx_runtime71 = require("react/jsx-runtime");
|
|
8794
9047
|
function ChatComposer({
|
|
8795
9048
|
onSubmit,
|
|
8796
9049
|
onStop,
|
|
@@ -8817,17 +9070,17 @@ function ChatComposer({
|
|
|
8817
9070
|
onReject,
|
|
8818
9071
|
onOpenAttachment
|
|
8819
9072
|
}) {
|
|
8820
|
-
const [text, setText] =
|
|
8821
|
-
const [trigger, setTrigger] =
|
|
8822
|
-
const [mentionItems, setMentionItems] =
|
|
8823
|
-
const [listening, setListening] =
|
|
8824
|
-
const [notice, setNotice] =
|
|
8825
|
-
const editor =
|
|
8826
|
-
const wrap =
|
|
8827
|
-
const stopVoice =
|
|
9073
|
+
const [text, setText] = React39.useState(draft || "");
|
|
9074
|
+
const [trigger, setTrigger] = React39.useState(null);
|
|
9075
|
+
const [mentionItems, setMentionItems] = React39.useState([]);
|
|
9076
|
+
const [listening, setListening] = React39.useState(false);
|
|
9077
|
+
const [notice, setNotice] = React39.useState(null);
|
|
9078
|
+
const editor = React39.useRef(null);
|
|
9079
|
+
const wrap = React39.useRef(null);
|
|
9080
|
+
const stopVoice = React39.useRef(null);
|
|
8828
9081
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
8829
9082
|
} });
|
|
8830
|
-
|
|
9083
|
+
React39.useEffect(() => {
|
|
8831
9084
|
if (draft != null && draft !== text) setText(draft);
|
|
8832
9085
|
}, [draft]);
|
|
8833
9086
|
const change = (v) => {
|
|
@@ -8861,7 +9114,7 @@ function ChatComposer({
|
|
|
8861
9114
|
e.preventDefault();
|
|
8862
9115
|
staged.add(found.files);
|
|
8863
9116
|
};
|
|
8864
|
-
|
|
9117
|
+
React39.useEffect(() => {
|
|
8865
9118
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
8866
9119
|
setMentionItems([]);
|
|
8867
9120
|
return;
|
|
@@ -8879,7 +9132,7 @@ function ChatComposer({
|
|
|
8879
9132
|
const q = (trigger.query || "").toLowerCase();
|
|
8880
9133
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
8881
9134
|
}, [trigger, mentionSources]);
|
|
8882
|
-
const slashItems =
|
|
9135
|
+
const slashItems = React39.useMemo(() => {
|
|
8883
9136
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
8884
9137
|
const q = (trigger.query || "").toLowerCase();
|
|
8885
9138
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -8893,7 +9146,7 @@ function ChatComposer({
|
|
|
8893
9146
|
description: it.description,
|
|
8894
9147
|
icon: it.icon,
|
|
8895
9148
|
meta: mention.meta,
|
|
8896
|
-
shortcut: slash.shortcut ? /* @__PURE__ */ (0,
|
|
9149
|
+
shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
|
|
8897
9150
|
onSelect: () => {
|
|
8898
9151
|
const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
|
|
8899
9152
|
editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
|
|
@@ -8956,14 +9209,14 @@ function ChatComposer({
|
|
|
8956
9209
|
stopVoice.current = typeof res === "function" ? res : () => {
|
|
8957
9210
|
};
|
|
8958
9211
|
};
|
|
8959
|
-
return /* @__PURE__ */ (0,
|
|
8960
|
-
queue.length ? /* @__PURE__ */ (0,
|
|
8961
|
-
/* @__PURE__ */ (0,
|
|
8962
|
-
/* @__PURE__ */ (0,
|
|
8963
|
-
onRemoveQueued ? /* @__PURE__ */ (0,
|
|
9212
|
+
return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
|
|
9213
|
+
queue.length ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "fdc-queue-row", children: [
|
|
9214
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
|
|
9215
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "fdc-queue-text", children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
|
|
9216
|
+
onRemoveQueued ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
8964
9217
|
] }, q.id)) }) : null,
|
|
8965
9218
|
sessionBar,
|
|
8966
|
-
/* @__PURE__ */ (0,
|
|
9219
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
|
|
8967
9220
|
Dropzone,
|
|
8968
9221
|
{
|
|
8969
9222
|
className: "fdc-field",
|
|
@@ -8977,9 +9230,9 @@ function ChatComposer({
|
|
|
8977
9230
|
disabled: !fileUploadHandler || disabled,
|
|
8978
9231
|
label: "Drop to attach",
|
|
8979
9232
|
hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
|
|
8980
|
-
children: /* @__PURE__ */ (0,
|
|
8981
|
-
staged.items.length ? /* @__PURE__ */ (0,
|
|
8982
|
-
/* @__PURE__ */ (0,
|
|
9233
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { ref: wrap, className: "fdc-field-inner", children: [
|
|
9234
|
+
staged.items.length ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "fdc-staged", children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
|
|
9235
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
|
|
8983
9236
|
MarkdownEditor,
|
|
8984
9237
|
{
|
|
8985
9238
|
ref: editor,
|
|
@@ -8998,33 +9251,33 @@ function ChatComposer({
|
|
|
8998
9251
|
ariaLabel: "Message"
|
|
8999
9252
|
}
|
|
9000
9253
|
),
|
|
9001
|
-
/* @__PURE__ */ (0,
|
|
9002
|
-
fileUploadHandler ? /* @__PURE__ */ (0,
|
|
9003
|
-
voiceHandler ? /* @__PURE__ */ (0,
|
|
9254
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "fdc-tools", children: [
|
|
9255
|
+
fileUploadHandler ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
|
|
9256
|
+
voiceHandler ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
|
|
9004
9257
|
toolbarExtras,
|
|
9005
|
-
/* @__PURE__ */ (0,
|
|
9006
|
-
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0,
|
|
9258
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "fdc-tools-gap" }),
|
|
9259
|
+
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
|
|
9007
9260
|
text.length,
|
|
9008
9261
|
"/",
|
|
9009
9262
|
maxLength
|
|
9010
9263
|
] }) : null,
|
|
9011
|
-
busy ? /* @__PURE__ */ (0,
|
|
9012
|
-
/* @__PURE__ */ (0,
|
|
9013
|
-
/* @__PURE__ */ (0,
|
|
9014
|
-
] }) : /* @__PURE__ */ (0,
|
|
9015
|
-
/* @__PURE__ */ (0,
|
|
9016
|
-
/* @__PURE__ */ (0,
|
|
9264
|
+
busy ? /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
|
|
9265
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
9266
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { children: "Stop" })
|
|
9267
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
|
|
9268
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
|
|
9269
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "fdc-send-label", children: "Send" })
|
|
9017
9270
|
] })
|
|
9018
9271
|
] })
|
|
9019
9272
|
] })
|
|
9020
9273
|
}
|
|
9021
9274
|
),
|
|
9022
|
-
notice ? /* @__PURE__ */ (0,
|
|
9023
|
-
/* @__PURE__ */ (0,
|
|
9275
|
+
notice ? /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "fdc-notice", role: "status", children: [
|
|
9276
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
9024
9277
|
notice
|
|
9025
9278
|
] }) : null,
|
|
9026
|
-
hint && !notice ? /* @__PURE__ */ (0,
|
|
9027
|
-
/* @__PURE__ */ (0,
|
|
9279
|
+
hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "fdc-hint", children: hint }) : null,
|
|
9280
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
|
|
9028
9281
|
Popover,
|
|
9029
9282
|
{
|
|
9030
9283
|
open: menuOpen,
|
|
@@ -9038,12 +9291,12 @@ function ChatComposer({
|
|
|
9038
9291
|
returnFocus: false,
|
|
9039
9292
|
closeOnOutside: true,
|
|
9040
9293
|
label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
|
|
9041
|
-
children: /* @__PURE__ */ (0,
|
|
9294
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
|
|
9042
9295
|
Menu,
|
|
9043
9296
|
{
|
|
9044
9297
|
items: menuItems,
|
|
9045
9298
|
autoFocus: false,
|
|
9046
|
-
header: /* @__PURE__ */ (0,
|
|
9299
|
+
header: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
|
|
9047
9300
|
onClose: () => setTrigger(null)
|
|
9048
9301
|
}
|
|
9049
9302
|
)
|
|
@@ -9053,12 +9306,12 @@ function ChatComposer({
|
|
|
9053
9306
|
}
|
|
9054
9307
|
|
|
9055
9308
|
// src/components/chat/ChatSessionBar.tsx
|
|
9056
|
-
var
|
|
9057
|
-
var
|
|
9309
|
+
var React40 = __toESM(require("react"), 1);
|
|
9310
|
+
var import_jsx_runtime72 = require("react/jsx-runtime");
|
|
9058
9311
|
var compact2 = meterFormats.compact;
|
|
9059
9312
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
9060
|
-
const [open, setOpen] =
|
|
9061
|
-
const anchor =
|
|
9313
|
+
const [open, setOpen] = React40.useState(false);
|
|
9314
|
+
const anchor = React40.useRef(null);
|
|
9062
9315
|
const stats = sessionStats || null;
|
|
9063
9316
|
const cu = contextUsage || null;
|
|
9064
9317
|
const limits = usageLimits || null;
|
|
@@ -9073,9 +9326,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9073
9326
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
9074
9327
|
if (cu) bits.push(pct + "% context");
|
|
9075
9328
|
const expandable = !!(cu || limits);
|
|
9076
|
-
return /* @__PURE__ */ (0,
|
|
9077
|
-
/* @__PURE__ */ (0,
|
|
9078
|
-
/* @__PURE__ */ (0,
|
|
9329
|
+
return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(React40.Fragment, { children: [
|
|
9330
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "fdc-bar", children: [
|
|
9331
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
|
|
9079
9332
|
"button",
|
|
9080
9333
|
{
|
|
9081
9334
|
type: "button",
|
|
@@ -9086,16 +9339,16 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9086
9339
|
"aria-expanded": expandable ? open : void 0,
|
|
9087
9340
|
"aria-label": expandable ? "Usage details" : void 0,
|
|
9088
9341
|
children: [
|
|
9089
|
-
cu ? /* @__PURE__ */ (0,
|
|
9090
|
-
/* @__PURE__ */ (0,
|
|
9091
|
-
expandable ? /* @__PURE__ */ (0,
|
|
9342
|
+
cu ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
|
|
9343
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "fdc-bar-text", children: bits.join(" \xB7 ") }),
|
|
9344
|
+
expandable ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
|
|
9092
9345
|
]
|
|
9093
9346
|
}
|
|
9094
9347
|
),
|
|
9095
9348
|
extras
|
|
9096
9349
|
] }),
|
|
9097
|
-
/* @__PURE__ */ (0,
|
|
9098
|
-
cu ? /* @__PURE__ */ (0,
|
|
9350
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)(Popover, { open, anchorRef: anchor, placement: "top-start", onClose: () => setOpen(false), minWidth: 330, maxHeight: 460, padded: true, label: "Usage", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "fdc-usage", children: [
|
|
9351
|
+
cu ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
|
|
9099
9352
|
SegmentedMeter,
|
|
9100
9353
|
{
|
|
9101
9354
|
total,
|
|
@@ -9107,9 +9360,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9107
9360
|
remainderLabel: "Free"
|
|
9108
9361
|
}
|
|
9109
9362
|
) }) : null,
|
|
9110
|
-
limits && limits.length ? /* @__PURE__ */ (0,
|
|
9111
|
-
/* @__PURE__ */ (0,
|
|
9112
|
-
/* @__PURE__ */ (0,
|
|
9363
|
+
limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("section", { className: "fdc-usage-sec", children: [
|
|
9364
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
|
|
9365
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
|
|
9113
9366
|
QuotaRow,
|
|
9114
9367
|
{
|
|
9115
9368
|
label: l.label,
|
|
@@ -9119,32 +9372,32 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9119
9372
|
l.id
|
|
9120
9373
|
)) })
|
|
9121
9374
|
] }) : null,
|
|
9122
|
-
stats ? /* @__PURE__ */ (0,
|
|
9123
|
-
stats.elapsedMs ? /* @__PURE__ */ (0,
|
|
9124
|
-
/* @__PURE__ */ (0,
|
|
9125
|
-
/* @__PURE__ */ (0,
|
|
9375
|
+
stats ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
|
|
9376
|
+
stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { children: [
|
|
9377
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: "Session" }),
|
|
9378
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
|
|
9126
9379
|
] }) : null,
|
|
9127
|
-
stats.tokens ? /* @__PURE__ */ (0,
|
|
9128
|
-
/* @__PURE__ */ (0,
|
|
9129
|
-
/* @__PURE__ */ (0,
|
|
9380
|
+
stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { children: [
|
|
9381
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: "Tokens" }),
|
|
9382
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
|
|
9130
9383
|
] }) : null,
|
|
9131
|
-
stats.costUsd != null ? /* @__PURE__ */ (0,
|
|
9132
|
-
/* @__PURE__ */ (0,
|
|
9133
|
-
/* @__PURE__ */ (0,
|
|
9384
|
+
stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { children: [
|
|
9385
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: "Cost" }),
|
|
9386
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("b", { className: "fd-tabular", children: [
|
|
9134
9387
|
"$",
|
|
9135
9388
|
Number(stats.costUsd).toFixed(3)
|
|
9136
9389
|
] })
|
|
9137
9390
|
] }) : null,
|
|
9138
|
-
stats.turns ? /* @__PURE__ */ (0,
|
|
9139
|
-
/* @__PURE__ */ (0,
|
|
9140
|
-
/* @__PURE__ */ (0,
|
|
9391
|
+
stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { children: [
|
|
9392
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: "Turns" }),
|
|
9393
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("b", { className: "fd-tabular", children: stats.turns })
|
|
9141
9394
|
] }) : null
|
|
9142
9395
|
] }) : null,
|
|
9143
|
-
onClear ? /* @__PURE__ */ (0,
|
|
9396
|
+
onClear ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("footer", { className: "fdc-usage-foot", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
|
|
9144
9397
|
setOpen(false);
|
|
9145
9398
|
onClear();
|
|
9146
9399
|
}, children: [
|
|
9147
|
-
/* @__PURE__ */ (0,
|
|
9400
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
|
|
9148
9401
|
"Clear conversation"
|
|
9149
9402
|
] }) }) : null
|
|
9150
9403
|
] }) })
|
|
@@ -9181,7 +9434,7 @@ function ModelControls({
|
|
|
9181
9434
|
disabled: m.disabled,
|
|
9182
9435
|
checked: m.id === (current2 && current2.id),
|
|
9183
9436
|
meta: m.meta,
|
|
9184
|
-
shortcut: m.shortcut ? /* @__PURE__ */ (0,
|
|
9437
|
+
shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
|
|
9185
9438
|
onSelect: () => onModelChange && onModelChange(m.id)
|
|
9186
9439
|
});
|
|
9187
9440
|
const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
|
|
@@ -9194,15 +9447,15 @@ function ModelControls({
|
|
|
9194
9447
|
items.push({ kind: "section", label: "Fast mode" });
|
|
9195
9448
|
items.push({
|
|
9196
9449
|
kind: "custom",
|
|
9197
|
-
render: () => /* @__PURE__ */ (0,
|
|
9198
|
-
/* @__PURE__ */ (0,
|
|
9199
|
-
/* @__PURE__ */ (0,
|
|
9200
|
-
/* @__PURE__ */ (0,
|
|
9450
|
+
render: () => /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("label", { className: "fdc-switchrow", children: [
|
|
9451
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: fastModeLabel }),
|
|
9452
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
|
|
9453
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "fd-switch-thumb" }) })
|
|
9201
9454
|
] })
|
|
9202
9455
|
});
|
|
9203
9456
|
}
|
|
9204
|
-
return /* @__PURE__ */ (0,
|
|
9205
|
-
/* @__PURE__ */ (0,
|
|
9457
|
+
return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(React40.Fragment, { children: [
|
|
9458
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
|
|
9206
9459
|
MenuButton,
|
|
9207
9460
|
{
|
|
9208
9461
|
items,
|
|
@@ -9213,7 +9466,7 @@ function ModelControls({
|
|
|
9213
9466
|
title: "Choose a model"
|
|
9214
9467
|
}
|
|
9215
9468
|
),
|
|
9216
|
-
effortLevels && effortLevels.length ? /* @__PURE__ */ (0,
|
|
9469
|
+
effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
|
|
9217
9470
|
MenuButton,
|
|
9218
9471
|
{
|
|
9219
9472
|
placement: "top-end",
|
|
@@ -9234,7 +9487,7 @@ function ModelControls({
|
|
|
9234
9487
|
}
|
|
9235
9488
|
|
|
9236
9489
|
// src/components/chat/AgentChatPanel.tsx
|
|
9237
|
-
var
|
|
9490
|
+
var import_jsx_runtime73 = require("react/jsx-runtime");
|
|
9238
9491
|
var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
|
|
9239
9492
|
function AgentChatPanel({
|
|
9240
9493
|
/* required */
|
|
@@ -9318,11 +9571,11 @@ function AgentChatPanel({
|
|
|
9318
9571
|
onFeedback,
|
|
9319
9572
|
onEditMessage
|
|
9320
9573
|
}) {
|
|
9321
|
-
const [panelWidth, setPanelWidth] =
|
|
9322
|
-
const [applied, setApplied] =
|
|
9323
|
-
const [draft, setDraft] =
|
|
9324
|
-
const dragging =
|
|
9325
|
-
|
|
9574
|
+
const [panelWidth, setPanelWidth] = React41.useState(width);
|
|
9575
|
+
const [applied, setApplied] = React41.useState({});
|
|
9576
|
+
const [draft, setDraft] = React41.useState("");
|
|
9577
|
+
const dragging = React41.useRef(null);
|
|
9578
|
+
React41.useEffect(() => setPanelWidth(width), [width]);
|
|
9326
9579
|
const engine = useChatEngine({
|
|
9327
9580
|
contextType,
|
|
9328
9581
|
contextId,
|
|
@@ -9388,7 +9641,7 @@ function AgentChatPanel({
|
|
|
9388
9641
|
onReconnect: engine.reload,
|
|
9389
9642
|
deadTitle: "The assistant isn\u2019t reachable"
|
|
9390
9643
|
};
|
|
9391
|
-
const sessionBar = /* @__PURE__ */ (0,
|
|
9644
|
+
const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9392
9645
|
ChatSessionBar,
|
|
9393
9646
|
{
|
|
9394
9647
|
sessionStats,
|
|
@@ -9397,7 +9650,7 @@ function AgentChatPanel({
|
|
|
9397
9650
|
onClear: engine.visible.length ? engine.clear : void 0
|
|
9398
9651
|
}
|
|
9399
9652
|
);
|
|
9400
|
-
const modelControls = /* @__PURE__ */ (0,
|
|
9653
|
+
const modelControls = /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9401
9654
|
ModelControls,
|
|
9402
9655
|
{
|
|
9403
9656
|
models,
|
|
@@ -9412,7 +9665,7 @@ function AgentChatPanel({
|
|
|
9412
9665
|
narrow
|
|
9413
9666
|
}
|
|
9414
9667
|
);
|
|
9415
|
-
const threadMenu = threads && threads.length ? /* @__PURE__ */ (0,
|
|
9668
|
+
const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9416
9669
|
MenuButton,
|
|
9417
9670
|
{
|
|
9418
9671
|
variant: "ghost",
|
|
@@ -9439,7 +9692,7 @@ function AgentChatPanel({
|
|
|
9439
9692
|
})))
|
|
9440
9693
|
}
|
|
9441
9694
|
) : null;
|
|
9442
|
-
return /* @__PURE__ */ (0,
|
|
9695
|
+
return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
|
|
9443
9696
|
"aside",
|
|
9444
9697
|
{
|
|
9445
9698
|
className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
|
|
@@ -9450,7 +9703,7 @@ function AgentChatPanel({
|
|
|
9450
9703
|
},
|
|
9451
9704
|
"aria-label": title,
|
|
9452
9705
|
children: [
|
|
9453
|
-
surface === "sidebar" && resizable ? /* @__PURE__ */ (0,
|
|
9706
|
+
surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9454
9707
|
"div",
|
|
9455
9708
|
{
|
|
9456
9709
|
className: "fdc-grip",
|
|
@@ -9465,20 +9718,20 @@ function AgentChatPanel({
|
|
|
9465
9718
|
}
|
|
9466
9719
|
}
|
|
9467
9720
|
) : null,
|
|
9468
|
-
showHeader ? /* @__PURE__ */ (0,
|
|
9469
|
-
/* @__PURE__ */ (0,
|
|
9470
|
-
/* @__PURE__ */ (0,
|
|
9471
|
-
/* @__PURE__ */ (0,
|
|
9472
|
-
subtitle ? /* @__PURE__ */ (0,
|
|
9721
|
+
showHeader ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("header", { className: "fdc-head", children: [
|
|
9722
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-" + assistantIcon }) }),
|
|
9723
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fdc-head-titles", children: [
|
|
9724
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-head-title", children: title }),
|
|
9725
|
+
subtitle ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-head-sub", children: subtitle }) : null
|
|
9473
9726
|
] }),
|
|
9474
|
-
/* @__PURE__ */ (0,
|
|
9727
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fdc-head-acts", children: [
|
|
9475
9728
|
headerActions,
|
|
9476
9729
|
threadMenu,
|
|
9477
|
-
onNewThread ? /* @__PURE__ */ (0,
|
|
9478
|
-
onClose ? /* @__PURE__ */ (0,
|
|
9730
|
+
onNewThread ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
|
|
9731
|
+
onClose ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
9479
9732
|
] })
|
|
9480
9733
|
] }) : null,
|
|
9481
|
-
/* @__PURE__ */ (0,
|
|
9734
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9482
9735
|
ChatTranscript,
|
|
9483
9736
|
{
|
|
9484
9737
|
messages: engine.visible,
|
|
@@ -9493,7 +9746,7 @@ function AgentChatPanel({
|
|
|
9493
9746
|
renderEmpty
|
|
9494
9747
|
}
|
|
9495
9748
|
),
|
|
9496
|
-
/* @__PURE__ */ (0,
|
|
9749
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9497
9750
|
ChatComposer,
|
|
9498
9751
|
{
|
|
9499
9752
|
onSubmit: (text, atts) => engine.send(text, atts),
|
|
@@ -9526,7 +9779,7 @@ function AgentChatPanel({
|
|
|
9526
9779
|
}
|
|
9527
9780
|
|
|
9528
9781
|
// src/kits/query.ts
|
|
9529
|
-
var
|
|
9782
|
+
var React42 = __toESM(require("react"), 1);
|
|
9530
9783
|
function eqFilter(get2) {
|
|
9531
9784
|
return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
|
|
9532
9785
|
}
|
|
@@ -9558,22 +9811,22 @@ function compare(a, b, dir) {
|
|
|
9558
9811
|
var API = null;
|
|
9559
9812
|
var PREFS = null;
|
|
9560
9813
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
9561
|
-
const [query, setQuery] =
|
|
9814
|
+
const [query, setQuery] = React42.useState(() => {
|
|
9562
9815
|
const store = PREFS || window.PlannerPrefs;
|
|
9563
9816
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
9564
9817
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
9565
9818
|
});
|
|
9566
|
-
const savePref =
|
|
9819
|
+
const savePref = React42.useCallback((patch2) => {
|
|
9567
9820
|
const store = PREFS || window.PlannerPrefs;
|
|
9568
9821
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
9569
9822
|
}, [prefsKey]);
|
|
9570
|
-
const [res, setRes] =
|
|
9571
|
-
const [loading, setLoading] =
|
|
9572
|
-
const seq2 =
|
|
9823
|
+
const [res, setRes] = React42.useState(null);
|
|
9824
|
+
const [loading, setLoading] = React42.useState(true);
|
|
9825
|
+
const seq2 = React42.useRef(0);
|
|
9573
9826
|
const depKey = (deps || []).join("|");
|
|
9574
9827
|
const paramKey = JSON.stringify(params || {});
|
|
9575
9828
|
const queryKey = JSON.stringify(query);
|
|
9576
|
-
|
|
9829
|
+
React42.useEffect(() => {
|
|
9577
9830
|
const id = ++seq2.current;
|
|
9578
9831
|
setLoading(true);
|
|
9579
9832
|
const t = setTimeout(() => {
|
|
@@ -9912,6 +10165,7 @@ function createVersionStore(initialState, options) {
|
|
|
9912
10165
|
Dropzone,
|
|
9913
10166
|
DropzoneKit,
|
|
9914
10167
|
EmptyState,
|
|
10168
|
+
EntityRow,
|
|
9915
10169
|
FeatureGate,
|
|
9916
10170
|
FileChip,
|
|
9917
10171
|
FileGrid,
|
|
@@ -9984,11 +10238,16 @@ function createVersionStore(initialState, options) {
|
|
|
9984
10238
|
Tooltip,
|
|
9985
10239
|
Topbar,
|
|
9986
10240
|
TranscriptKit,
|
|
10241
|
+
TransferList,
|
|
9987
10242
|
UseFeatureStatus,
|
|
9988
10243
|
UseRuntimeMode,
|
|
10244
|
+
VIRTUAL_LIST_BUFFER_ROWS,
|
|
10245
|
+
VirtualList,
|
|
9989
10246
|
acceptMatches,
|
|
9990
10247
|
anyOfFilter,
|
|
9991
10248
|
channelWeightOf,
|
|
10249
|
+
computeNeedMore,
|
|
10250
|
+
computeVirtualWindow,
|
|
9992
10251
|
createVersionStore,
|
|
9993
10252
|
eqFilter,
|
|
9994
10253
|
extensionOf,
|