@flytedan/flytebot-design-system 0.6.1 → 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 +1285 -1033
- 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 +1279 -1033
- package/dist/index.js.map +1 -1
- package/package.json +1 -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,
|
|
@@ -2613,56 +2619,140 @@ function StepList({
|
|
|
2613
2619
|
] });
|
|
2614
2620
|
}
|
|
2615
2621
|
|
|
2616
|
-
// src/components/
|
|
2622
|
+
// src/components/data/VirtualList.tsx
|
|
2617
2623
|
var React15 = __toESM(require("react"), 1);
|
|
2618
2624
|
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
2619
|
-
|
|
2620
|
-
|
|
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;
|
|
2621
2675
|
React15.useEffect(() => {
|
|
2622
|
-
if (
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
] })
|
|
2633
|
-
|
|
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
|
+
);
|
|
2634
2708
|
}
|
|
2635
2709
|
|
|
2636
|
-
// src/components/
|
|
2710
|
+
// src/components/data/EntityRow.tsx
|
|
2637
2711
|
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
2638
|
-
function
|
|
2639
|
-
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
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
|
+
);
|
|
2649
2749
|
}
|
|
2650
2750
|
|
|
2651
|
-
// src/components/
|
|
2652
|
-
var
|
|
2653
|
-
function Switch({ label, description, className = "", ...rest }) {
|
|
2654
|
-
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
|
|
2655
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("input", { type: "checkbox", role: "switch", ...rest }),
|
|
2656
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-switch-track", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-switch-thumb" }) }),
|
|
2657
|
-
label ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "fd-choice-text", children: [
|
|
2658
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-switch-label", children: label }),
|
|
2659
|
-
description ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-choice-desc", children: description }) : null
|
|
2660
|
-
] }) : null
|
|
2661
|
-
] });
|
|
2662
|
-
}
|
|
2751
|
+
// src/components/data/TransferList.tsx
|
|
2752
|
+
var React16 = __toESM(require("react"), 1);
|
|
2663
2753
|
|
|
2664
2754
|
// src/components/forms/Input.tsx
|
|
2665
|
-
var
|
|
2755
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
2666
2756
|
function Input({
|
|
2667
2757
|
label,
|
|
2668
2758
|
help,
|
|
@@ -2690,27 +2780,27 @@ function Input({
|
|
|
2690
2780
|
size === "lg" ? "fd-input-lg" : "",
|
|
2691
2781
|
className
|
|
2692
2782
|
].filter(Boolean).join(" ");
|
|
2693
|
-
return /* @__PURE__ */ (0,
|
|
2694
|
-
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: [
|
|
2695
2785
|
label,
|
|
2696
|
-
required ? /* @__PURE__ */ (0,
|
|
2786
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-field-req", "aria-hidden": "true", children: "*" }) : null
|
|
2697
2787
|
] }) : null,
|
|
2698
|
-
/* @__PURE__ */ (0,
|
|
2699
|
-
icon ? /* @__PURE__ */ (0,
|
|
2700
|
-
prefix ? /* @__PURE__ */ (0,
|
|
2701
|
-
/* @__PURE__ */ (0,
|
|
2702
|
-
loading ? /* @__PURE__ */ (0,
|
|
2703
|
-
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
|
|
2704
2794
|
] }),
|
|
2705
|
-
error ? /* @__PURE__ */ (0,
|
|
2706
|
-
/* @__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" }),
|
|
2707
2797
|
error
|
|
2708
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
2798
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
2709
2799
|
] });
|
|
2710
2800
|
}
|
|
2711
2801
|
|
|
2712
2802
|
// src/components/forms/SearchField.tsx
|
|
2713
|
-
var
|
|
2803
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
2714
2804
|
function SearchField({
|
|
2715
2805
|
value,
|
|
2716
2806
|
onChange,
|
|
@@ -2725,7 +2815,7 @@ function SearchField({
|
|
|
2725
2815
|
...rest
|
|
2726
2816
|
}) {
|
|
2727
2817
|
const clear = onClear || (() => onChange(""));
|
|
2728
|
-
return /* @__PURE__ */ (0,
|
|
2818
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2729
2819
|
Input,
|
|
2730
2820
|
{
|
|
2731
2821
|
id,
|
|
@@ -2738,14 +2828,14 @@ function SearchField({
|
|
|
2738
2828
|
style,
|
|
2739
2829
|
className,
|
|
2740
2830
|
onChange: (e) => onChange(e.target.value),
|
|
2741
|
-
suffix: value ? /* @__PURE__ */ (0,
|
|
2831
|
+
suffix: value ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2742
2832
|
"button",
|
|
2743
2833
|
{
|
|
2744
2834
|
type: "button",
|
|
2745
2835
|
"aria-label": "Clear search",
|
|
2746
2836
|
onClick: clear,
|
|
2747
2837
|
style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
|
|
2748
|
-
children: /* @__PURE__ */ (0,
|
|
2838
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 }, "aria-hidden": "true" })
|
|
2749
2839
|
}
|
|
2750
2840
|
) : void 0,
|
|
2751
2841
|
...rest
|
|
@@ -2753,27 +2843,183 @@ function SearchField({
|
|
|
2753
2843
|
);
|
|
2754
2844
|
}
|
|
2755
2845
|
|
|
2756
|
-
// 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);
|
|
2757
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");
|
|
2758
3004
|
function Textarea({ label, help, error, required = false, rows = 4, disabled = false, id, className = "", style, ...rest }) {
|
|
2759
3005
|
const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
|
|
2760
3006
|
const box = ["fd-input", "fd-input-textarea", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : "", className].filter(Boolean).join(" ");
|
|
2761
|
-
return /* @__PURE__ */ (0,
|
|
2762
|
-
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: [
|
|
2763
3009
|
label,
|
|
2764
|
-
required ? /* @__PURE__ */ (0,
|
|
3010
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-field-req", children: "*" }) : null
|
|
2765
3011
|
] }) : null,
|
|
2766
|
-
/* @__PURE__ */ (0,
|
|
2767
|
-
error ? /* @__PURE__ */ (0,
|
|
2768
|
-
/* @__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" }),
|
|
2769
3015
|
error
|
|
2770
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3016
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
2771
3017
|
] });
|
|
2772
3018
|
}
|
|
2773
3019
|
|
|
2774
3020
|
// src/components/forms/NumberInput.tsx
|
|
2775
|
-
var
|
|
2776
|
-
var
|
|
3021
|
+
var React18 = __toESM(require("react"), 1);
|
|
3022
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
2777
3023
|
function NumberInput({
|
|
2778
3024
|
label,
|
|
2779
3025
|
help,
|
|
@@ -2797,10 +3043,10 @@ function NumberInput({
|
|
|
2797
3043
|
const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
|
|
2798
3044
|
return isNaN(n) ? null : n;
|
|
2799
3045
|
};
|
|
2800
|
-
const [text, setText] =
|
|
2801
|
-
const [editing, setEditing] =
|
|
2802
|
-
const timer =
|
|
2803
|
-
|
|
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(() => {
|
|
2804
3050
|
if (!editing) setText(value == null || value === "" ? "" : String(value));
|
|
2805
3051
|
}, [value, editing]);
|
|
2806
3052
|
const clamp = (n) => Math.min(max, Math.max(min, n));
|
|
@@ -2824,7 +3070,7 @@ function NumberInput({
|
|
|
2824
3070
|
const release = () => {
|
|
2825
3071
|
if (timer.current) clearTimeout(timer.current);
|
|
2826
3072
|
};
|
|
2827
|
-
|
|
3073
|
+
React18.useEffect(() => () => {
|
|
2828
3074
|
if (timer.current) clearTimeout(timer.current);
|
|
2829
3075
|
}, []);
|
|
2830
3076
|
const shown = editing ? text : (() => {
|
|
@@ -2832,14 +3078,14 @@ function NumberInput({
|
|
|
2832
3078
|
return n == null ? "" : format ? n.toLocaleString() : String(n);
|
|
2833
3079
|
})();
|
|
2834
3080
|
const box = ["fd-input", "fd-input-num", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
2835
|
-
return /* @__PURE__ */ (0,
|
|
2836
|
-
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: [
|
|
2837
3083
|
label,
|
|
2838
|
-
required ? /* @__PURE__ */ (0,
|
|
3084
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-field-req", children: "*" }) : null
|
|
2839
3085
|
] }) : null,
|
|
2840
|
-
/* @__PURE__ */ (0,
|
|
2841
|
-
prefix ? /* @__PURE__ */ (0,
|
|
2842
|
-
/* @__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)(
|
|
2843
3089
|
"input",
|
|
2844
3090
|
{
|
|
2845
3091
|
inputMode: "numeric",
|
|
@@ -2872,9 +3118,9 @@ function NumberInput({
|
|
|
2872
3118
|
}
|
|
2873
3119
|
}
|
|
2874
3120
|
),
|
|
2875
|
-
suffix ? /* @__PURE__ */ (0,
|
|
2876
|
-
/* @__PURE__ */ (0,
|
|
2877
|
-
/* @__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)(
|
|
2878
3124
|
"button",
|
|
2879
3125
|
{
|
|
2880
3126
|
type: "button",
|
|
@@ -2884,10 +3130,10 @@ function NumberInput({
|
|
|
2884
3130
|
onPointerDown: () => hold(-1),
|
|
2885
3131
|
onPointerUp: release,
|
|
2886
3132
|
onPointerLeave: release,
|
|
2887
|
-
children: /* @__PURE__ */ (0,
|
|
3133
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-minus" })
|
|
2888
3134
|
}
|
|
2889
3135
|
),
|
|
2890
|
-
/* @__PURE__ */ (0,
|
|
3136
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2891
3137
|
"button",
|
|
2892
3138
|
{
|
|
2893
3139
|
type: "button",
|
|
@@ -2897,26 +3143,26 @@ function NumberInput({
|
|
|
2897
3143
|
onPointerDown: () => hold(1),
|
|
2898
3144
|
onPointerUp: release,
|
|
2899
3145
|
onPointerLeave: release,
|
|
2900
|
-
children: /* @__PURE__ */ (0,
|
|
3146
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-plus" })
|
|
2901
3147
|
}
|
|
2902
3148
|
)
|
|
2903
3149
|
] })
|
|
2904
3150
|
] }),
|
|
2905
|
-
error ? /* @__PURE__ */ (0,
|
|
2906
|
-
/* @__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" }),
|
|
2907
3153
|
error
|
|
2908
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3154
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
2909
3155
|
] });
|
|
2910
3156
|
}
|
|
2911
3157
|
|
|
2912
3158
|
// src/components/forms/Select.tsx
|
|
2913
|
-
var
|
|
3159
|
+
var React19 = __toESM(require("react"), 1);
|
|
2914
3160
|
var import_react_dom4 = require("react-dom");
|
|
2915
|
-
var
|
|
3161
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
2916
3162
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
2917
3163
|
function usePopPos(open, ref, estH, estW) {
|
|
2918
|
-
const [pos, setPos] =
|
|
2919
|
-
|
|
3164
|
+
const [pos, setPos] = React19.useState(null);
|
|
3165
|
+
React19.useLayoutEffect(() => {
|
|
2920
3166
|
if (!open || !ref.current) {
|
|
2921
3167
|
setPos(null);
|
|
2922
3168
|
return;
|
|
@@ -2980,14 +3226,14 @@ function Select({
|
|
|
2980
3226
|
const vals = multiple ? Array.isArray(value) ? value : value ? [value] : [] : [];
|
|
2981
3227
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
2982
3228
|
const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
|
|
2983
|
-
const [open, setOpen] =
|
|
2984
|
-
const [q, setQ] =
|
|
2985
|
-
const [active, setActive] =
|
|
2986
|
-
const rootRef =
|
|
2987
|
-
const boxRef =
|
|
2988
|
-
const popRef =
|
|
2989
|
-
const listRef =
|
|
2990
|
-
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 });
|
|
2991
3237
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
2992
3238
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
2993
3239
|
const pos = usePopPos(open, boxRef, hasSearch ? 390 : 340, 260);
|
|
@@ -3013,7 +3259,7 @@ function Select({
|
|
|
3013
3259
|
}
|
|
3014
3260
|
setOpen(!open);
|
|
3015
3261
|
};
|
|
3016
|
-
|
|
3262
|
+
React19.useEffect(() => {
|
|
3017
3263
|
if (!open) return;
|
|
3018
3264
|
const away = (e) => {
|
|
3019
3265
|
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
@@ -3023,7 +3269,7 @@ function Select({
|
|
|
3023
3269
|
document.addEventListener("pointerdown", away);
|
|
3024
3270
|
return () => document.removeEventListener("pointerdown", away);
|
|
3025
3271
|
}, [open]);
|
|
3026
|
-
|
|
3272
|
+
React19.useEffect(() => {
|
|
3027
3273
|
if (!open || active < 0 || !listRef.current) return;
|
|
3028
3274
|
const el = listRef.current.querySelector('[data-i="' + active + '"]');
|
|
3029
3275
|
if (el) {
|
|
@@ -3077,13 +3323,13 @@ function Select({
|
|
|
3077
3323
|
});
|
|
3078
3324
|
const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
|
|
3079
3325
|
const box = ["fd-input", "fd-select", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
3080
|
-
return /* @__PURE__ */ (0,
|
|
3081
|
-
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: [
|
|
3082
3328
|
label,
|
|
3083
|
-
required ? /* @__PURE__ */ (0,
|
|
3329
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-field-req", children: "*" }) : null
|
|
3084
3330
|
] }) : null,
|
|
3085
|
-
/* @__PURE__ */ (0,
|
|
3086
|
-
/* @__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)(
|
|
3087
3333
|
"button",
|
|
3088
3334
|
{
|
|
3089
3335
|
type: "button",
|
|
@@ -3096,13 +3342,13 @@ function Select({
|
|
|
3096
3342
|
"aria-haspopup": "listbox",
|
|
3097
3343
|
style: { all: "unset", flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: 8, cursor: "inherit", overflow: "hidden" },
|
|
3098
3344
|
children: [
|
|
3099
|
-
selected && selected.icon ? /* @__PURE__ */ (0,
|
|
3100
|
-
/* @__PURE__ */ (0,
|
|
3101
|
-
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
|
|
3102
3348
|
]
|
|
3103
3349
|
}
|
|
3104
3350
|
),
|
|
3105
|
-
clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ (0,
|
|
3351
|
+
clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3106
3352
|
"button",
|
|
3107
3353
|
{
|
|
3108
3354
|
type: "button",
|
|
@@ -3112,22 +3358,22 @@ function Select({
|
|
|
3112
3358
|
fire(multiple ? [] : "");
|
|
3113
3359
|
},
|
|
3114
3360
|
style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
|
|
3115
|
-
children: /* @__PURE__ */ (0,
|
|
3361
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 } })
|
|
3116
3362
|
}
|
|
3117
3363
|
) : null,
|
|
3118
|
-
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" }) })
|
|
3119
3365
|
] }),
|
|
3120
3366
|
open && pos ? (0, import_react_dom4.createPortal)(
|
|
3121
|
-
/* @__PURE__ */ (0,
|
|
3367
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
3122
3368
|
"div",
|
|
3123
3369
|
{
|
|
3124
3370
|
className: "fd-pop" + (pos.up ? " is-up" : ""),
|
|
3125
3371
|
ref: popRef,
|
|
3126
3372
|
style: popStyle(pos, { minWidth: Math.max(pos.width, 260), maxWidth: 380, zIndex: 130, overflowY: "hidden" }),
|
|
3127
3373
|
children: [
|
|
3128
|
-
hasSearch ? /* @__PURE__ */ (0,
|
|
3129
|
-
/* @__PURE__ */ (0,
|
|
3130
|
-
/* @__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)(
|
|
3131
3377
|
"input",
|
|
3132
3378
|
{
|
|
3133
3379
|
autoFocus: true,
|
|
@@ -3140,15 +3386,15 @@ function Select({
|
|
|
3140
3386
|
}
|
|
3141
3387
|
}
|
|
3142
3388
|
),
|
|
3143
|
-
q ? /* @__PURE__ */ (0,
|
|
3389
|
+
q ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
3144
3390
|
] }) : null,
|
|
3145
|
-
/* @__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: [
|
|
3146
3392
|
'Nothing matches "',
|
|
3147
3393
|
q,
|
|
3148
3394
|
'".'
|
|
3149
|
-
] }) : groups.map((grp) => /* @__PURE__ */ (0,
|
|
3150
|
-
grp.g ? /* @__PURE__ */ (0,
|
|
3151
|
-
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)(
|
|
3152
3398
|
"button",
|
|
3153
3399
|
{
|
|
3154
3400
|
type: "button",
|
|
@@ -3160,21 +3406,21 @@ function Select({
|
|
|
3160
3406
|
onMouseEnter: () => setActive(i),
|
|
3161
3407
|
onClick: () => pick(o),
|
|
3162
3408
|
children: [
|
|
3163
|
-
multiple ? /* @__PURE__ */ (0,
|
|
3164
|
-
o.icon ? /* @__PURE__ */ (0,
|
|
3165
|
-
/* @__PURE__ */ (0,
|
|
3166
|
-
/* @__PURE__ */ (0,
|
|
3167
|
-
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
|
|
3168
3414
|
] }),
|
|
3169
|
-
o.meta ? /* @__PURE__ */ (0,
|
|
3170
|
-
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 })
|
|
3171
3417
|
]
|
|
3172
3418
|
},
|
|
3173
3419
|
String(o.value)
|
|
3174
3420
|
))
|
|
3175
3421
|
] }, grp.g || "_")) }),
|
|
3176
|
-
multiple ? /* @__PURE__ */ (0,
|
|
3177
|
-
/* @__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)(
|
|
3178
3424
|
"button",
|
|
3179
3425
|
{
|
|
3180
3426
|
type: "button",
|
|
@@ -3183,13 +3429,13 @@ function Select({
|
|
|
3183
3429
|
children: "Select all"
|
|
3184
3430
|
}
|
|
3185
3431
|
),
|
|
3186
|
-
/* @__PURE__ */ (0,
|
|
3187
|
-
/* @__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: [
|
|
3188
3434
|
vals.length,
|
|
3189
3435
|
" of ",
|
|
3190
3436
|
opts.length
|
|
3191
3437
|
] }),
|
|
3192
|
-
/* @__PURE__ */ (0,
|
|
3438
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3193
3439
|
"button",
|
|
3194
3440
|
{
|
|
3195
3441
|
type: "button",
|
|
@@ -3205,17 +3451,17 @@ function Select({
|
|
|
3205
3451
|
),
|
|
3206
3452
|
document.body
|
|
3207
3453
|
) : null,
|
|
3208
|
-
error ? /* @__PURE__ */ (0,
|
|
3209
|
-
/* @__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" }),
|
|
3210
3456
|
error
|
|
3211
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3457
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3212
3458
|
] });
|
|
3213
3459
|
}
|
|
3214
3460
|
|
|
3215
3461
|
// src/components/forms/DatePicker.tsx
|
|
3216
|
-
var
|
|
3462
|
+
var React20 = __toESM(require("react"), 1);
|
|
3217
3463
|
var import_react_dom5 = require("react-dom");
|
|
3218
|
-
var
|
|
3464
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
3219
3465
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
3220
3466
|
var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
3221
3467
|
var iso = (d) => d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
|
|
@@ -3229,8 +3475,8 @@ var fmt = (s) => {
|
|
|
3229
3475
|
return d ? MONTHS[d.getMonth()].slice(0, 3) + " " + d.getDate() + ", " + d.getFullYear() : "";
|
|
3230
3476
|
};
|
|
3231
3477
|
function usePopPos2(open, ref, estH, estW) {
|
|
3232
|
-
const [pos, setPos] =
|
|
3233
|
-
|
|
3478
|
+
const [pos, setPos] = React20.useState(null);
|
|
3479
|
+
React20.useLayoutEffect(() => {
|
|
3234
3480
|
if (!open || !ref.current) {
|
|
3235
3481
|
setPos(null);
|
|
3236
3482
|
return;
|
|
@@ -3274,10 +3520,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3274
3520
|
const today = /* @__PURE__ */ new Date();
|
|
3275
3521
|
const sel = range ? value || {} : { start: value, end: value };
|
|
3276
3522
|
const anchor = parse(sel.start) || parse(initialMonth) || today;
|
|
3277
|
-
const [vy, setVy] =
|
|
3278
|
-
const [vm, setVm] =
|
|
3279
|
-
const [mode2, setMode] =
|
|
3280
|
-
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);
|
|
3281
3527
|
const s = parse(sel.start), e = parse(sel.end);
|
|
3282
3528
|
const hoverEnd = range && s && !e && hover ? parse(hover) : null;
|
|
3283
3529
|
const inRange = (d) => {
|
|
@@ -3314,9 +3560,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3314
3560
|
const startPad = new Date(y, m, 1).getDay();
|
|
3315
3561
|
const cells = [];
|
|
3316
3562
|
for (let i = 0; i < 42; i++) cells.push(new Date(y, m, i - startPad + 1));
|
|
3317
|
-
return /* @__PURE__ */ (0,
|
|
3318
|
-
DOW.map((d) => /* @__PURE__ */ (0,
|
|
3319
|
-
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)(
|
|
3320
3566
|
"button",
|
|
3321
3567
|
{
|
|
3322
3568
|
type: "button",
|
|
@@ -3330,20 +3576,20 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3330
3576
|
] });
|
|
3331
3577
|
};
|
|
3332
3578
|
const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
|
|
3333
|
-
return /* @__PURE__ */ (0,
|
|
3334
|
-
/* @__PURE__ */ (0,
|
|
3335
|
-
/* @__PURE__ */ (0,
|
|
3336
|
-
/* @__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: [
|
|
3337
3583
|
mode2 === "days" ? MONTHS[vm] + " " + vy : mode2 === "months" ? vy : vy - 5 + " \u2013 " + (vy + 6),
|
|
3338
|
-
/* @__PURE__ */ (0,
|
|
3584
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-caret-down", style: { fontSize: 10, marginLeft: 6, color: "var(--text-muted)" } })
|
|
3339
3585
|
] }),
|
|
3340
|
-
months > 1 && mode2 === "days" ? /* @__PURE__ */ (0,
|
|
3341
|
-
/* @__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" }) })
|
|
3342
3588
|
] }),
|
|
3343
|
-
mode2 === "days" ? /* @__PURE__ */ (0,
|
|
3589
|
+
mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { style: { display: "flex", gap: 18 }, children: [
|
|
3344
3590
|
monthGrid(vy, vm),
|
|
3345
3591
|
months > 1 ? monthGrid(nextY, nextM) : null
|
|
3346
|
-
] }) : 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)(
|
|
3347
3593
|
"button",
|
|
3348
3594
|
{
|
|
3349
3595
|
type: "button",
|
|
@@ -3355,7 +3601,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3355
3601
|
children: m.slice(0, 3)
|
|
3356
3602
|
},
|
|
3357
3603
|
m
|
|
3358
|
-
)) }) : /* @__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)(
|
|
3359
3605
|
"button",
|
|
3360
3606
|
{
|
|
3361
3607
|
type: "button",
|
|
@@ -3368,8 +3614,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3368
3614
|
},
|
|
3369
3615
|
y
|
|
3370
3616
|
)) }),
|
|
3371
|
-
/* @__PURE__ */ (0,
|
|
3372
|
-
/* @__PURE__ */ (0,
|
|
3617
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal-foot", children: [
|
|
3618
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3373
3619
|
"button",
|
|
3374
3620
|
{
|
|
3375
3621
|
type: "button",
|
|
@@ -3383,8 +3629,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3383
3629
|
children: "Today"
|
|
3384
3630
|
}
|
|
3385
3631
|
),
|
|
3386
|
-
/* @__PURE__ */ (0,
|
|
3387
|
-
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: [
|
|
3388
3634
|
fmt(sel.start),
|
|
3389
3635
|
sel.end ? " \u2192 " + fmt(sel.end) : " \u2192 pick an end"
|
|
3390
3636
|
] }) : null
|
|
@@ -3392,12 +3638,12 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3392
3638
|
] });
|
|
3393
3639
|
}
|
|
3394
3640
|
function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, className = "", style, ...rest }) {
|
|
3395
|
-
const [open, setOpen] =
|
|
3396
|
-
const rootRef =
|
|
3397
|
-
const boxRef =
|
|
3398
|
-
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);
|
|
3399
3645
|
const pos = usePopPos2(open, boxRef, 430, range ? 600 : 316);
|
|
3400
|
-
|
|
3646
|
+
React20.useEffect(() => {
|
|
3401
3647
|
if (!open) return;
|
|
3402
3648
|
const away = (e) => {
|
|
3403
3649
|
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
@@ -3418,14 +3664,14 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3418
3664
|
const toggle = () => {
|
|
3419
3665
|
if (!disabled) setOpen(!open);
|
|
3420
3666
|
};
|
|
3421
|
-
return /* @__PURE__ */ (0,
|
|
3422
|
-
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: [
|
|
3423
3669
|
label,
|
|
3424
|
-
required ? /* @__PURE__ */ (0,
|
|
3670
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-field-req", children: "*" }) : null
|
|
3425
3671
|
] }) : null,
|
|
3426
|
-
/* @__PURE__ */ (0,
|
|
3427
|
-
/* @__PURE__ */ (0,
|
|
3428
|
-
/* @__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)(
|
|
3429
3675
|
"button",
|
|
3430
3676
|
{
|
|
3431
3677
|
type: "button",
|
|
@@ -3441,10 +3687,10 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3441
3687
|
children: display || placeholder || (range ? "Pick a date range" : "Pick a date")
|
|
3442
3688
|
}
|
|
3443
3689
|
),
|
|
3444
|
-
/* @__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" }) })
|
|
3445
3691
|
] }),
|
|
3446
3692
|
open && pos ? (0, import_react_dom5.createPortal)(
|
|
3447
|
-
/* @__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)(
|
|
3448
3694
|
Calendar,
|
|
3449
3695
|
{
|
|
3450
3696
|
range,
|
|
@@ -3458,21 +3704,21 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3458
3704
|
) }),
|
|
3459
3705
|
document.body
|
|
3460
3706
|
) : null,
|
|
3461
|
-
error ? /* @__PURE__ */ (0,
|
|
3462
|
-
/* @__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" }),
|
|
3463
3709
|
error
|
|
3464
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3710
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3465
3711
|
] });
|
|
3466
3712
|
}
|
|
3467
3713
|
|
|
3468
3714
|
// src/components/forms/TimePicker.tsx
|
|
3469
|
-
var
|
|
3715
|
+
var React21 = __toESM(require("react"), 1);
|
|
3470
3716
|
var import_react_dom6 = require("react-dom");
|
|
3471
|
-
var
|
|
3717
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
3472
3718
|
var pad = (n) => String(n).padStart(2, "0");
|
|
3473
3719
|
function usePopPos3(open, ref, estH, estW) {
|
|
3474
|
-
const [pos, setPos] =
|
|
3475
|
-
|
|
3720
|
+
const [pos, setPos] = React21.useState(null);
|
|
3721
|
+
React21.useLayoutEffect(() => {
|
|
3476
3722
|
if (!open || !ref.current) {
|
|
3477
3723
|
setPos(null);
|
|
3478
3724
|
return;
|
|
@@ -3518,9 +3764,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3518
3764
|
if (isNaN(m)) m = 0;
|
|
3519
3765
|
const pm = h24 >= 12;
|
|
3520
3766
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
3521
|
-
const [mode2, setMode] =
|
|
3522
|
-
const faceRef =
|
|
3523
|
-
const dragging =
|
|
3767
|
+
const [mode2, setMode] = React21.useState("h");
|
|
3768
|
+
const faceRef = React21.useRef(null);
|
|
3769
|
+
const dragging = React21.useRef(false);
|
|
3524
3770
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
3525
3771
|
const R = 108, NR = 80;
|
|
3526
3772
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -3555,12 +3801,12 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3555
3801
|
};
|
|
3556
3802
|
const handAngle = mode2 === "h" ? h12 % 12 * 30 : m * 6;
|
|
3557
3803
|
const minuteOff = mode2 === "m" && m % 5 !== 0;
|
|
3558
|
-
return /* @__PURE__ */ (0,
|
|
3559
|
-
/* @__PURE__ */ (0,
|
|
3560
|
-
/* @__PURE__ */ (0,
|
|
3561
|
-
/* @__PURE__ */ (0,
|
|
3562
|
-
/* @__PURE__ */ (0,
|
|
3563
|
-
/* @__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)(
|
|
3564
3810
|
"button",
|
|
3565
3811
|
{
|
|
3566
3812
|
type: "button",
|
|
@@ -3571,13 +3817,13 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3571
3817
|
ap
|
|
3572
3818
|
)) })
|
|
3573
3819
|
] }),
|
|
3574
|
-
/* @__PURE__ */ (0,
|
|
3575
|
-
/* @__PURE__ */ (0,
|
|
3576
|
-
/* @__PURE__ */ (0,
|
|
3577
|
-
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,
|
|
3578
3824
|
nums.map((n) => {
|
|
3579
3825
|
const a = angleOf(n) * Math.PI / 180;
|
|
3580
|
-
return /* @__PURE__ */ (0,
|
|
3826
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3581
3827
|
"span",
|
|
3582
3828
|
{
|
|
3583
3829
|
className: "fd-clock-num" + (n === selNum || mode2 === "m" && n === Math.round(m / 5) * 5 % 60 && m % 5 === 0 ? " is-sel" : ""),
|
|
@@ -3588,16 +3834,16 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3588
3834
|
);
|
|
3589
3835
|
})
|
|
3590
3836
|
] }),
|
|
3591
|
-
/* @__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" }) })
|
|
3592
3838
|
] });
|
|
3593
3839
|
}
|
|
3594
3840
|
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", className = "", style }) {
|
|
3595
|
-
const [open, setOpen] =
|
|
3596
|
-
const rootRef =
|
|
3597
|
-
const boxRef =
|
|
3598
|
-
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);
|
|
3599
3845
|
const pos = usePopPos3(open, boxRef, 420, 262);
|
|
3600
|
-
|
|
3846
|
+
React21.useEffect(() => {
|
|
3601
3847
|
if (!open) return;
|
|
3602
3848
|
const away = (e) => {
|
|
3603
3849
|
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
@@ -3622,14 +3868,14 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
3622
3868
|
const toggle = () => {
|
|
3623
3869
|
if (!disabled) setOpen(!open);
|
|
3624
3870
|
};
|
|
3625
|
-
return /* @__PURE__ */ (0,
|
|
3626
|
-
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: [
|
|
3627
3873
|
label,
|
|
3628
|
-
required ? /* @__PURE__ */ (0,
|
|
3874
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-field-req", children: "*" }) : null
|
|
3629
3875
|
] }) : null,
|
|
3630
|
-
/* @__PURE__ */ (0,
|
|
3631
|
-
/* @__PURE__ */ (0,
|
|
3632
|
-
/* @__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)(
|
|
3633
3879
|
"button",
|
|
3634
3880
|
{
|
|
3635
3881
|
type: "button",
|
|
@@ -3644,13 +3890,13 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
3644
3890
|
children: disp() || placeholder
|
|
3645
3891
|
}
|
|
3646
3892
|
),
|
|
3647
|
-
/* @__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" }) })
|
|
3648
3894
|
] }),
|
|
3649
3895
|
open && pos ? (0, import_react_dom6.createPortal)(
|
|
3650
|
-
/* @__PURE__ */ (0,
|
|
3651
|
-
/* @__PURE__ */ (0,
|
|
3652
|
-
/* @__PURE__ */ (0,
|
|
3653
|
-
/* @__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)(
|
|
3654
3900
|
"button",
|
|
3655
3901
|
{
|
|
3656
3902
|
type: "button",
|
|
@@ -3663,22 +3909,22 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
3663
3909
|
children: "Now"
|
|
3664
3910
|
}
|
|
3665
3911
|
),
|
|
3666
|
-
/* @__PURE__ */ (0,
|
|
3667
|
-
/* @__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" })
|
|
3668
3914
|
] })
|
|
3669
3915
|
] }),
|
|
3670
3916
|
document.body
|
|
3671
3917
|
) : null,
|
|
3672
|
-
error ? /* @__PURE__ */ (0,
|
|
3673
|
-
/* @__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" }),
|
|
3674
3920
|
error
|
|
3675
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3921
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3676
3922
|
] });
|
|
3677
3923
|
}
|
|
3678
3924
|
|
|
3679
3925
|
// src/components/forms/Slider.tsx
|
|
3680
|
-
var
|
|
3681
|
-
var
|
|
3926
|
+
var React22 = __toESM(require("react"), 1);
|
|
3927
|
+
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
3682
3928
|
function Slider({
|
|
3683
3929
|
label,
|
|
3684
3930
|
min = 0,
|
|
@@ -3692,18 +3938,18 @@ function Slider({
|
|
|
3692
3938
|
className = "",
|
|
3693
3939
|
...rest
|
|
3694
3940
|
}) {
|
|
3695
|
-
const [dragging, setDragging] =
|
|
3941
|
+
const [dragging, setDragging] = React22.useState(false);
|
|
3696
3942
|
const v = value === void 0 ? min : Number(value);
|
|
3697
3943
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
3698
|
-
return /* @__PURE__ */ (0,
|
|
3699
|
-
label ? /* @__PURE__ */ (0,
|
|
3700
|
-
/* @__PURE__ */ (0,
|
|
3701
|
-
/* @__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) })
|
|
3702
3948
|
] }) : null,
|
|
3703
|
-
/* @__PURE__ */ (0,
|
|
3704
|
-
/* @__PURE__ */ (0,
|
|
3705
|
-
showChip && dragging ? /* @__PURE__ */ (0,
|
|
3706
|
-
/* @__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)(
|
|
3707
3953
|
"input",
|
|
3708
3954
|
{
|
|
3709
3955
|
type: "range",
|
|
@@ -3720,13 +3966,13 @@ function Slider({
|
|
|
3720
3966
|
}
|
|
3721
3967
|
)
|
|
3722
3968
|
] }),
|
|
3723
|
-
help ? /* @__PURE__ */ (0,
|
|
3969
|
+
help ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3724
3970
|
] });
|
|
3725
3971
|
}
|
|
3726
3972
|
|
|
3727
3973
|
// src/components/forms/RangeSlider.tsx
|
|
3728
|
-
var
|
|
3729
|
-
var
|
|
3974
|
+
var React23 = __toESM(require("react"), 1);
|
|
3975
|
+
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
3730
3976
|
function RangeSlider({
|
|
3731
3977
|
label,
|
|
3732
3978
|
min = 0,
|
|
@@ -3745,9 +3991,9 @@ function RangeSlider({
|
|
|
3745
3991
|
}) {
|
|
3746
3992
|
const fmt2 = format || ((v) => String(v));
|
|
3747
3993
|
const [a, b] = value || [min, max];
|
|
3748
|
-
const [drag, setDrag] =
|
|
3749
|
-
const [focus, setFocus] =
|
|
3750
|
-
const railRef =
|
|
3994
|
+
const [drag, setDrag] = React23.useState(null);
|
|
3995
|
+
const [focus, setFocus] = React23.useState(null);
|
|
3996
|
+
const railRef = React23.useRef(null);
|
|
3751
3997
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
3752
3998
|
const clampPair = (i, v) => {
|
|
3753
3999
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -3762,7 +4008,7 @@ function RangeSlider({
|
|
|
3762
4008
|
const r = railRef.current.getBoundingClientRect();
|
|
3763
4009
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
3764
4010
|
};
|
|
3765
|
-
|
|
4011
|
+
React23.useEffect(() => {
|
|
3766
4012
|
if (drag === null) return;
|
|
3767
4013
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
3768
4014
|
const upH = () => setDrag(null);
|
|
@@ -3783,7 +4029,7 @@ function RangeSlider({
|
|
|
3783
4029
|
};
|
|
3784
4030
|
const thin = S.length > 7 ? Math.ceil(S.length / 5) : 1;
|
|
3785
4031
|
const pair = value || [S[0].value, S[S.length - 1].value];
|
|
3786
|
-
return /* @__PURE__ */ (0,
|
|
4032
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3787
4033
|
RangeSlider,
|
|
3788
4034
|
{
|
|
3789
4035
|
...rest,
|
|
@@ -3831,23 +4077,23 @@ function RangeSlider({
|
|
|
3831
4077
|
};
|
|
3832
4078
|
const showChip = (i) => drag === i || focus === i;
|
|
3833
4079
|
const hasLabels = marks.some((m) => m.label);
|
|
3834
|
-
return /* @__PURE__ */ (0,
|
|
3835
|
-
label ? /* @__PURE__ */ (0,
|
|
3836
|
-
/* @__PURE__ */ (0,
|
|
3837
|
-
/* @__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: [
|
|
3838
4084
|
fmt2(a),
|
|
3839
4085
|
" \u2013 ",
|
|
3840
4086
|
fmt2(b)
|
|
3841
4087
|
] })
|
|
3842
4088
|
] }) : null,
|
|
3843
|
-
/* @__PURE__ */ (0,
|
|
3844
|
-
/* @__PURE__ */ (0,
|
|
3845
|
-
/* @__PURE__ */ (0,
|
|
3846
|
-
marks.map((m) => /* @__PURE__ */ (0,
|
|
3847
|
-
/* @__PURE__ */ (0,
|
|
3848
|
-
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
|
|
3849
4095
|
] }, m.value)),
|
|
3850
|
-
[a, b].map((v, i) => /* @__PURE__ */ (0,
|
|
4096
|
+
[a, b].map((v, i) => /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3851
4097
|
"span",
|
|
3852
4098
|
{
|
|
3853
4099
|
className: "fd-range-thumb" + (drag === i ? " is-drag" : ""),
|
|
@@ -3862,18 +4108,18 @@ function RangeSlider({
|
|
|
3862
4108
|
onKeyDown: key(i),
|
|
3863
4109
|
onFocus: () => setFocus(i),
|
|
3864
4110
|
onBlur: () => setFocus(null),
|
|
3865
|
-
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) })
|
|
3866
4112
|
},
|
|
3867
4113
|
i
|
|
3868
4114
|
))
|
|
3869
4115
|
] }),
|
|
3870
|
-
help ? /* @__PURE__ */ (0,
|
|
4116
|
+
help ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3871
4117
|
] });
|
|
3872
4118
|
}
|
|
3873
4119
|
|
|
3874
4120
|
// src/components/forms/Dropzone.tsx
|
|
3875
|
-
var
|
|
3876
|
-
var
|
|
4121
|
+
var React24 = __toESM(require("react"), 1);
|
|
4122
|
+
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
3877
4123
|
function Dropzone({
|
|
3878
4124
|
onFiles,
|
|
3879
4125
|
onReject,
|
|
@@ -3887,8 +4133,8 @@ function Dropzone({
|
|
|
3887
4133
|
className = "",
|
|
3888
4134
|
style
|
|
3889
4135
|
}) {
|
|
3890
|
-
const [over, setOver] =
|
|
3891
|
-
const depth =
|
|
4136
|
+
const [over, setOver] = React24.useState(false);
|
|
4137
|
+
const depth = React24.useRef(0);
|
|
3892
4138
|
const has = (e) => {
|
|
3893
4139
|
const dt = e.dataTransfer;
|
|
3894
4140
|
if (!dt) return false;
|
|
@@ -3918,7 +4164,7 @@ function Dropzone({
|
|
|
3918
4164
|
if (rejected.length && onReject) onReject(rejected);
|
|
3919
4165
|
if (accepted.length && onFiles) onFiles(accepted);
|
|
3920
4166
|
};
|
|
3921
|
-
return /* @__PURE__ */ (0,
|
|
4167
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
3922
4168
|
"div",
|
|
3923
4169
|
{
|
|
3924
4170
|
className: ["fd-dropzone", over ? "is-over" : "", className].filter(Boolean).join(" "),
|
|
@@ -3929,10 +4175,10 @@ function Dropzone({
|
|
|
3929
4175
|
onDrop: drop,
|
|
3930
4176
|
children: [
|
|
3931
4177
|
children,
|
|
3932
|
-
over ? /* @__PURE__ */ (0,
|
|
3933
|
-
/* @__PURE__ */ (0,
|
|
3934
|
-
/* @__PURE__ */ (0,
|
|
3935
|
-
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
|
|
3936
4182
|
] }) }) : null
|
|
3937
4183
|
]
|
|
3938
4184
|
}
|
|
@@ -3950,9 +4196,9 @@ function FilePickButton({
|
|
|
3950
4196
|
className = "",
|
|
3951
4197
|
children
|
|
3952
4198
|
}) {
|
|
3953
|
-
const ref =
|
|
3954
|
-
return /* @__PURE__ */ (0,
|
|
3955
|
-
/* @__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)(
|
|
3956
4202
|
"button",
|
|
3957
4203
|
{
|
|
3958
4204
|
type: "button",
|
|
@@ -3961,10 +4207,10 @@ function FilePickButton({
|
|
|
3961
4207
|
"aria-label": label,
|
|
3962
4208
|
title: label,
|
|
3963
4209
|
onClick: () => ref.current && ref.current.click(),
|
|
3964
|
-
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" })
|
|
3965
4211
|
}
|
|
3966
4212
|
),
|
|
3967
|
-
/* @__PURE__ */ (0,
|
|
4213
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3968
4214
|
"input",
|
|
3969
4215
|
{
|
|
3970
4216
|
ref,
|
|
@@ -3984,10 +4230,10 @@ function FilePickButton({
|
|
|
3984
4230
|
}
|
|
3985
4231
|
function useStagedFiles(upload, opts) {
|
|
3986
4232
|
const o = opts || {};
|
|
3987
|
-
const [items, setItems] =
|
|
3988
|
-
const controllers =
|
|
4233
|
+
const [items, setItems] = React24.useState([]);
|
|
4234
|
+
const controllers = React24.useRef({});
|
|
3989
4235
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
3990
|
-
const run =
|
|
4236
|
+
const run = React24.useCallback((att) => {
|
|
3991
4237
|
if (!upload) return;
|
|
3992
4238
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
3993
4239
|
controllers.current[att.id] = ac;
|
|
@@ -4004,14 +4250,14 @@ function useStagedFiles(upload, opts) {
|
|
|
4004
4250
|
delete controllers.current[att.id];
|
|
4005
4251
|
});
|
|
4006
4252
|
}, [upload]);
|
|
4007
|
-
const add =
|
|
4253
|
+
const add = React24.useCallback((files) => {
|
|
4008
4254
|
if (!upload) return [];
|
|
4009
4255
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
4010
4256
|
setItems((list) => list.concat(atts));
|
|
4011
4257
|
atts.forEach(run);
|
|
4012
4258
|
return atts;
|
|
4013
4259
|
}, [upload, run]);
|
|
4014
|
-
const remove =
|
|
4260
|
+
const remove = React24.useCallback((att) => {
|
|
4015
4261
|
const ac = controllers.current[att.id];
|
|
4016
4262
|
if (ac) {
|
|
4017
4263
|
try {
|
|
@@ -4022,10 +4268,10 @@ function useStagedFiles(upload, opts) {
|
|
|
4022
4268
|
}
|
|
4023
4269
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
4024
4270
|
}, []);
|
|
4025
|
-
const retry =
|
|
4271
|
+
const retry = React24.useCallback((att) => {
|
|
4026
4272
|
run(att);
|
|
4027
4273
|
}, [run]);
|
|
4028
|
-
const clear =
|
|
4274
|
+
const clear = React24.useCallback(() => {
|
|
4029
4275
|
Object.values(controllers.current).forEach((ac) => {
|
|
4030
4276
|
try {
|
|
4031
4277
|
ac && ac.abort();
|
|
@@ -4041,7 +4287,7 @@ function useStagedFiles(upload, opts) {
|
|
|
4041
4287
|
var DropzoneKit = { useStagedFiles };
|
|
4042
4288
|
|
|
4043
4289
|
// src/components/forms/FileGrid.tsx
|
|
4044
|
-
var
|
|
4290
|
+
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
4045
4291
|
var truncateMiddle = (name, max = 34) => {
|
|
4046
4292
|
if (!name || name.length <= max) return name;
|
|
4047
4293
|
const ext = /\.[A-Za-z0-9]+$/.exec(name);
|
|
@@ -4050,7 +4296,7 @@ var truncateMiddle = (name, max = 34) => {
|
|
|
4050
4296
|
return head + "\u2026" + tail;
|
|
4051
4297
|
};
|
|
4052
4298
|
function Progress({ value }) {
|
|
4053
|
-
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)) + "%" } }) });
|
|
4054
4300
|
}
|
|
4055
4301
|
function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false, className = "" }) {
|
|
4056
4302
|
if (!file) return null;
|
|
@@ -4059,8 +4305,8 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
4059
4305
|
const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
|
|
4060
4306
|
const meta = file.meta || (file.size ? formatBytes(file.size) : "");
|
|
4061
4307
|
const clickable = !!onOpen && !uploading;
|
|
4062
|
-
return /* @__PURE__ */ (0,
|
|
4063
|
-
/* @__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)(
|
|
4064
4310
|
"button",
|
|
4065
4311
|
{
|
|
4066
4312
|
type: "button",
|
|
@@ -4069,16 +4315,16 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
4069
4315
|
onClick: clickable ? () => onOpen(file) : void 0,
|
|
4070
4316
|
title: file.name + (meta ? " \xB7 " + meta : ""),
|
|
4071
4317
|
children: [
|
|
4072
|
-
/* @__PURE__ */ (0,
|
|
4073
|
-
thumb ? /* @__PURE__ */ (0,
|
|
4074
|
-
(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
|
|
4075
4321
|
] }),
|
|
4076
|
-
/* @__PURE__ */ (0,
|
|
4077
|
-
/* @__PURE__ */ (0,
|
|
4078
|
-
/* @__PURE__ */ (0,
|
|
4079
|
-
/* @__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" }),
|
|
4080
4326
|
file.error
|
|
4081
|
-
] }) : uploading ? /* @__PURE__ */ (0,
|
|
4327
|
+
] }) : uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-tabular", children: [
|
|
4082
4328
|
Math.round(file.progress),
|
|
4083
4329
|
"% uploaded"
|
|
4084
4330
|
] }) : meta })
|
|
@@ -4086,29 +4332,29 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
4086
4332
|
]
|
|
4087
4333
|
}
|
|
4088
4334
|
),
|
|
4089
|
-
uploading ? /* @__PURE__ */ (0,
|
|
4090
|
-
file.error && onRetry ? /* @__PURE__ */ (0,
|
|
4091
|
-
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
|
|
4092
4338
|
] });
|
|
4093
4339
|
}
|
|
4094
4340
|
function FileTile({ file, onOpen, onRemove, maxHeight = 200, className = "" }) {
|
|
4095
4341
|
if (!file) return null;
|
|
4096
4342
|
const src = file.thumb && file.thumb.url || file.blobUrl || file.url;
|
|
4097
4343
|
const uploading = file.progress != null && file.progress < 100 && !file.error;
|
|
4098
|
-
return /* @__PURE__ */ (0,
|
|
4099
|
-
/* @__PURE__ */ (0,
|
|
4100
|
-
uploading ? /* @__PURE__ */ (0,
|
|
4101
|
-
file.error ? /* @__PURE__ */ (0,
|
|
4102
|
-
/* @__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" }),
|
|
4103
4349
|
file.error
|
|
4104
4350
|
] }) : null,
|
|
4105
|
-
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
|
|
4106
4352
|
] });
|
|
4107
4353
|
}
|
|
4108
4354
|
function FileStrip({ files = [], size = 68, onOpen, onRemove, onRetry, className = "" }) {
|
|
4109
4355
|
const list = files.filter(Boolean);
|
|
4110
4356
|
if (!list.length) return null;
|
|
4111
|
-
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)) });
|
|
4112
4358
|
}
|
|
4113
4359
|
var shortName = (name, keep = 5) => {
|
|
4114
4360
|
const s = String(name || "file");
|
|
@@ -4122,19 +4368,19 @@ function FileCell({ file, onOpen, onRemove, onRetry }) {
|
|
|
4122
4368
|
const image = isImage(file.mime, file.name);
|
|
4123
4369
|
const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
|
|
4124
4370
|
const label = file.name + (file.size ? " \xB7 " + formatBytes(file.size) : "");
|
|
4125
|
-
return /* @__PURE__ */ (0,
|
|
4126
|
-
/* @__PURE__ */ (0,
|
|
4127
|
-
thumb ? /* @__PURE__ */ (0,
|
|
4128
|
-
/* @__PURE__ */ (0,
|
|
4129
|
-
/* @__PURE__ */ (0,
|
|
4130
|
-
/* @__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) })
|
|
4131
4377
|
] }),
|
|
4132
|
-
(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
|
|
4133
4379
|
] }),
|
|
4134
|
-
uploading ? /* @__PURE__ */ (0,
|
|
4135
|
-
file.error ? /* @__PURE__ */ (0,
|
|
4136
|
-
file.error && onRetry ? /* @__PURE__ */ (0,
|
|
4137
|
-
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
|
|
4138
4384
|
] });
|
|
4139
4385
|
}
|
|
4140
4386
|
function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeight = 200, compact: compact3 = false, className = "" }) {
|
|
@@ -4142,15 +4388,15 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
4142
4388
|
if (!list.length) return null;
|
|
4143
4389
|
const pics = tiles ? list.filter((f) => isImage(f.mime, f.name)) : [];
|
|
4144
4390
|
const rest = list.filter((f) => pics.indexOf(f) === -1);
|
|
4145
|
-
return /* @__PURE__ */ (0,
|
|
4146
|
-
pics.length ? /* @__PURE__ */ (0,
|
|
4147
|
-
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
|
|
4148
4394
|
] });
|
|
4149
4395
|
}
|
|
4150
4396
|
|
|
4151
4397
|
// src/components/forms/MarkdownEditor.tsx
|
|
4152
|
-
var
|
|
4153
|
-
var
|
|
4398
|
+
var React25 = __toESM(require("react"), 1);
|
|
4399
|
+
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
4154
4400
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
4155
4401
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
4156
4402
|
function inlineParts(text) {
|
|
@@ -4363,7 +4609,7 @@ function syncDom(root, value) {
|
|
|
4363
4609
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
4364
4610
|
}
|
|
4365
4611
|
var LIST_CONT = RE_LI;
|
|
4366
|
-
var MarkdownEditor =
|
|
4612
|
+
var MarkdownEditor = React25.forwardRef(function MarkdownEditor2({
|
|
4367
4613
|
value = "",
|
|
4368
4614
|
onChange,
|
|
4369
4615
|
onSubmit,
|
|
@@ -4382,10 +4628,10 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4382
4628
|
className = "",
|
|
4383
4629
|
id
|
|
4384
4630
|
}, ref) {
|
|
4385
|
-
const boxRef =
|
|
4386
|
-
const composing =
|
|
4387
|
-
const pendingCaret =
|
|
4388
|
-
|
|
4631
|
+
const boxRef = React25.useRef(null);
|
|
4632
|
+
const composing = React25.useRef(false);
|
|
4633
|
+
const pendingCaret = React25.useRef(null);
|
|
4634
|
+
React25.useLayoutEffect(() => {
|
|
4389
4635
|
const root = boxRef.current;
|
|
4390
4636
|
if (!root || composing.current) return;
|
|
4391
4637
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -4394,7 +4640,7 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4394
4640
|
pendingCaret.current = null;
|
|
4395
4641
|
if (active && caret != null) placeCaret(root, caret);
|
|
4396
4642
|
}, [value]);
|
|
4397
|
-
|
|
4643
|
+
React25.useEffect(() => {
|
|
4398
4644
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
4399
4645
|
}, [autoFocus]);
|
|
4400
4646
|
const caretNow = () => {
|
|
@@ -4461,7 +4707,7 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4461
4707
|
api.replaceRange(from, to, next, from + next.length);
|
|
4462
4708
|
}
|
|
4463
4709
|
};
|
|
4464
|
-
|
|
4710
|
+
React25.useImperativeHandle(ref, () => api);
|
|
4465
4711
|
function detect(text, caret) {
|
|
4466
4712
|
if (!onTrigger) return;
|
|
4467
4713
|
const upto = text.slice(0, caret);
|
|
@@ -4574,8 +4820,8 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4574
4820
|
api.replaceRange(s.start, s.end, text.replace(/\r\n?/g, "\n"));
|
|
4575
4821
|
};
|
|
4576
4822
|
const lh = 1.55;
|
|
4577
|
-
return /* @__PURE__ */ (0,
|
|
4578
|
-
/* @__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)(
|
|
4579
4825
|
"div",
|
|
4580
4826
|
{
|
|
4581
4827
|
ref: boxRef,
|
|
@@ -4608,15 +4854,15 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4608
4854
|
}
|
|
4609
4855
|
}
|
|
4610
4856
|
),
|
|
4611
|
-
!value ? /* @__PURE__ */ (0,
|
|
4857
|
+
!value ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-rme-ph", "aria-hidden": "true", children: placeholder }) : null
|
|
4612
4858
|
] });
|
|
4613
4859
|
});
|
|
4614
4860
|
|
|
4615
4861
|
// src/components/platform/AccountMenu.tsx
|
|
4616
|
-
var
|
|
4862
|
+
var React27 = __toESM(require("react"), 1);
|
|
4617
4863
|
|
|
4618
4864
|
// src/kits/session.ts
|
|
4619
|
-
var
|
|
4865
|
+
var React26 = __toESM(require("react"), 1);
|
|
4620
4866
|
var PERMISSION_CATALOG = [
|
|
4621
4867
|
{ group: "Plans", items: [
|
|
4622
4868
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -6183,8 +6429,8 @@ function roadmap(overrides) {
|
|
|
6183
6429
|
};
|
|
6184
6430
|
}
|
|
6185
6431
|
function useSession() {
|
|
6186
|
-
const [s, setS] =
|
|
6187
|
-
|
|
6432
|
+
const [s, setS] = React26.useState(getSession);
|
|
6433
|
+
React26.useEffect(() => subscribe(setS), []);
|
|
6188
6434
|
return s;
|
|
6189
6435
|
}
|
|
6190
6436
|
var SessionKit = {
|
|
@@ -6217,7 +6463,7 @@ var SessionKit = {
|
|
|
6217
6463
|
};
|
|
6218
6464
|
|
|
6219
6465
|
// src/components/platform/AccountMenu.tsx
|
|
6220
|
-
var
|
|
6466
|
+
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
6221
6467
|
var DEFAULT_LINKS = [
|
|
6222
6468
|
{ id: "profile", label: "Your profile", icon: "user-circle", href: "../admin/index.html#profile" },
|
|
6223
6469
|
{ id: "preferences", label: "Preferences", icon: "sliders-horizontal", href: "../admin/index.html#preferences" }
|
|
@@ -6228,7 +6474,7 @@ var DEFAULT_ADMIN_LINKS = [
|
|
|
6228
6474
|
{ id: "flags", label: "Feature flags", icon: "toggle-right", href: "../admin/index.html#flags", perm: "flags.manage" }
|
|
6229
6475
|
];
|
|
6230
6476
|
function Item({ item, onPick }) {
|
|
6231
|
-
return /* @__PURE__ */ (0,
|
|
6477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
|
|
6232
6478
|
"button",
|
|
6233
6479
|
{
|
|
6234
6480
|
type: "button",
|
|
@@ -6236,9 +6482,9 @@ function Item({ item, onPick }) {
|
|
|
6236
6482
|
className: "fd-acct-item",
|
|
6237
6483
|
onClick: () => onPick(item),
|
|
6238
6484
|
children: [
|
|
6239
|
-
/* @__PURE__ */ (0,
|
|
6240
|
-
/* @__PURE__ */ (0,
|
|
6241
|
-
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
|
|
6242
6488
|
]
|
|
6243
6489
|
}
|
|
6244
6490
|
);
|
|
@@ -6254,9 +6500,9 @@ function AccountMenu({
|
|
|
6254
6500
|
...rest
|
|
6255
6501
|
}) {
|
|
6256
6502
|
const session = SessionKit.useSession();
|
|
6257
|
-
const [open, setOpen] =
|
|
6258
|
-
const [switching, setSwitching] =
|
|
6259
|
-
const ref =
|
|
6503
|
+
const [open, setOpen] = React27.useState(false);
|
|
6504
|
+
const [switching, setSwitching] = React27.useState(false);
|
|
6505
|
+
const ref = React27.useRef(null);
|
|
6260
6506
|
const user = session.user;
|
|
6261
6507
|
const visibleAdmin = adminLinks.filter((l) => !l.perm || SessionKit.can(l.perm));
|
|
6262
6508
|
const pick = (item) => {
|
|
@@ -6270,8 +6516,8 @@ function AccountMenu({
|
|
|
6270
6516
|
if (onSignOut) return onSignOut();
|
|
6271
6517
|
window.alert("Signed out. (Simulated \u2014 no auth provider is wired up.)");
|
|
6272
6518
|
};
|
|
6273
|
-
return /* @__PURE__ */ (0,
|
|
6274
|
-
/* @__PURE__ */ (0,
|
|
6519
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
|
|
6520
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
|
|
6275
6521
|
"button",
|
|
6276
6522
|
{
|
|
6277
6523
|
type: "button",
|
|
@@ -6283,32 +6529,32 @@ function AccountMenu({
|
|
|
6283
6529
|
onClick: () => setOpen((o) => !o),
|
|
6284
6530
|
...rest,
|
|
6285
6531
|
children: [
|
|
6286
|
-
/* @__PURE__ */ (0,
|
|
6287
|
-
/* @__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)" } })
|
|
6288
6534
|
]
|
|
6289
6535
|
}
|
|
6290
6536
|
),
|
|
6291
|
-
/* @__PURE__ */ (0,
|
|
6292
|
-
/* @__PURE__ */ (0,
|
|
6293
|
-
/* @__PURE__ */ (0,
|
|
6294
|
-
/* @__PURE__ */ (0,
|
|
6295
|
-
/* @__PURE__ */ (0,
|
|
6296
|
-
/* @__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 })
|
|
6297
6543
|
] })
|
|
6298
6544
|
] }),
|
|
6299
|
-
showRoles && session.roles.length ? /* @__PURE__ */ (0,
|
|
6300
|
-
/* @__PURE__ */ (0,
|
|
6301
|
-
visibleAdmin.length ? /* @__PURE__ */ (0,
|
|
6302
|
-
/* @__PURE__ */ (0,
|
|
6303
|
-
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))
|
|
6304
6550
|
] }) : null,
|
|
6305
|
-
allowUserSwitch ? /* @__PURE__ */ (0,
|
|
6306
|
-
/* @__PURE__ */ (0,
|
|
6307
|
-
/* @__PURE__ */ (0,
|
|
6308
|
-
/* @__PURE__ */ (0,
|
|
6309
|
-
/* @__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 } })
|
|
6310
6556
|
] }),
|
|
6311
|
-
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)(
|
|
6312
6558
|
"button",
|
|
6313
6559
|
{
|
|
6314
6560
|
type: "button",
|
|
@@ -6320,34 +6566,34 @@ function AccountMenu({
|
|
|
6320
6566
|
setSwitching(false);
|
|
6321
6567
|
},
|
|
6322
6568
|
children: [
|
|
6323
|
-
/* @__PURE__ */ (0,
|
|
6324
|
-
/* @__PURE__ */ (0,
|
|
6325
|
-
/* @__PURE__ */ (0,
|
|
6326
|
-
/* @__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(", ") })
|
|
6327
6573
|
] }),
|
|
6328
|
-
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
|
|
6329
6575
|
]
|
|
6330
6576
|
},
|
|
6331
6577
|
u.id
|
|
6332
6578
|
)) }) : null
|
|
6333
6579
|
] }) : null,
|
|
6334
|
-
/* @__PURE__ */ (0,
|
|
6335
|
-
/* @__PURE__ */ (0,
|
|
6336
|
-
/* @__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" })
|
|
6337
6583
|
] }) })
|
|
6338
6584
|
] }) })
|
|
6339
6585
|
] });
|
|
6340
6586
|
}
|
|
6341
6587
|
|
|
6342
6588
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
6343
|
-
var
|
|
6344
|
-
var
|
|
6589
|
+
var React28 = __toESM(require("react"), 1);
|
|
6590
|
+
var import_jsx_runtime57 = require("react/jsx-runtime");
|
|
6345
6591
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
6346
6592
|
function Json({ obj }) {
|
|
6347
|
-
return /* @__PURE__ */ (0,
|
|
6593
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
6348
6594
|
}
|
|
6349
6595
|
function Endpoint({ s, onRequest }) {
|
|
6350
|
-
const [tried, setTried] =
|
|
6596
|
+
const [tried, setTried] = React28.useState(null);
|
|
6351
6597
|
const run = async () => {
|
|
6352
6598
|
setTried("busy");
|
|
6353
6599
|
const t0 = (window.performance || Date).now();
|
|
@@ -6358,50 +6604,50 @@ function Endpoint({ s, onRequest }) {
|
|
|
6358
6604
|
setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
|
|
6359
6605
|
}
|
|
6360
6606
|
};
|
|
6361
|
-
return /* @__PURE__ */ (0,
|
|
6362
|
-
/* @__PURE__ */ (0,
|
|
6363
|
-
/* @__PURE__ */ (0,
|
|
6364
|
-
/* @__PURE__ */ (0,
|
|
6365
|
-
s.isList ? /* @__PURE__ */ (0,
|
|
6366
|
-
/* @__PURE__ */ (0,
|
|
6367
|
-
/* @__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: [
|
|
6368
6614
|
s.latency[0],
|
|
6369
6615
|
"\u2013",
|
|
6370
6616
|
s.latency[1],
|
|
6371
6617
|
"ms"
|
|
6372
6618
|
] }),
|
|
6373
|
-
/* @__PURE__ */ (0,
|
|
6619
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
|
|
6374
6620
|
] }),
|
|
6375
|
-
/* @__PURE__ */ (0,
|
|
6376
|
-
/* @__PURE__ */ (0,
|
|
6377
|
-
/* @__PURE__ */ (0,
|
|
6378
|
-
/* @__PURE__ */ (0,
|
|
6379
|
-
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
|
|
6380
6626
|
] }),
|
|
6381
|
-
/* @__PURE__ */ (0,
|
|
6382
|
-
s.request ? /* @__PURE__ */ (0,
|
|
6383
|
-
/* @__PURE__ */ (0,
|
|
6384
|
-
/* @__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 })
|
|
6385
6631
|
] }) : null,
|
|
6386
|
-
s.query ? /* @__PURE__ */ (0,
|
|
6387
|
-
/* @__PURE__ */ (0,
|
|
6388
|
-
/* @__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 })
|
|
6389
6635
|
] }) : null,
|
|
6390
|
-
/* @__PURE__ */ (0,
|
|
6391
|
-
/* @__PURE__ */ (0,
|
|
6392
|
-
/* @__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 })
|
|
6393
6639
|
] })
|
|
6394
6640
|
] }),
|
|
6395
|
-
s.notes ? /* @__PURE__ */ (0,
|
|
6396
|
-
tried && tried !== "busy" ? /* @__PURE__ */ (0,
|
|
6397
|
-
/* @__PURE__ */ (0,
|
|
6398
|
-
/* @__PURE__ */ (0,
|
|
6399
|
-
/* @__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: [
|
|
6400
6646
|
tried.ms,
|
|
6401
6647
|
"ms"
|
|
6402
6648
|
] })
|
|
6403
6649
|
] }),
|
|
6404
|
-
/* @__PURE__ */ (0,
|
|
6650
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
|
|
6405
6651
|
] }) : null
|
|
6406
6652
|
] })
|
|
6407
6653
|
] }) });
|
|
@@ -6420,58 +6666,58 @@ function ApiSpecBrowser({
|
|
|
6420
6666
|
className = "",
|
|
6421
6667
|
...rest
|
|
6422
6668
|
}) {
|
|
6423
|
-
const [q, setQ] =
|
|
6424
|
-
const [method, setMethod] =
|
|
6425
|
-
const [mod, setMod] =
|
|
6426
|
-
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);
|
|
6427
6673
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
6428
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())));
|
|
6429
6675
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
6430
6676
|
const methods = [...new Set(spec.map((s) => s.method))];
|
|
6431
6677
|
const listCount = spec.filter((s) => s.isList).length;
|
|
6432
|
-
return /* @__PURE__ */ (0,
|
|
6433
|
-
/* @__PURE__ */ (0,
|
|
6434
|
-
kicker ? /* @__PURE__ */ (0,
|
|
6435
|
-
/* @__PURE__ */ (0,
|
|
6436
|
-
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
|
|
6437
6683
|
] }),
|
|
6438
|
-
modules && modules.length ? /* @__PURE__ */ (0,
|
|
6439
|
-
/* @__PURE__ */ (0,
|
|
6440
|
-
/* @__PURE__ */ (0,
|
|
6441
|
-
/* @__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: [
|
|
6442
6688
|
"All screens ",
|
|
6443
|
-
/* @__PURE__ */ (0,
|
|
6689
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: spec.length })
|
|
6444
6690
|
] }),
|
|
6445
|
-
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: [
|
|
6446
6692
|
m.label,
|
|
6447
6693
|
" ",
|
|
6448
|
-
/* @__PURE__ */ (0,
|
|
6694
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
|
|
6449
6695
|
] }, m.id))
|
|
6450
6696
|
] }),
|
|
6451
|
-
activeModule ? /* @__PURE__ */ (0,
|
|
6697
|
+
activeModule ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
6452
6698
|
Flag,
|
|
6453
6699
|
{
|
|
6454
6700
|
tone: "info",
|
|
6455
6701
|
statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
|
|
6456
6702
|
cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
|
|
6457
|
-
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" })
|
|
6458
6704
|
}
|
|
6459
6705
|
) : null
|
|
6460
6706
|
] }) : null,
|
|
6461
|
-
sourceNote ? /* @__PURE__ */ (0,
|
|
6462
|
-
/* @__PURE__ */ (0,
|
|
6463
|
-
/* @__PURE__ */ (0,
|
|
6464
|
-
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: [
|
|
6465
6711
|
m,
|
|
6466
6712
|
" ",
|
|
6467
|
-
/* @__PURE__ */ (0,
|
|
6713
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
|
|
6468
6714
|
] }, m)),
|
|
6469
|
-
listCount ? /* @__PURE__ */ (0,
|
|
6715
|
+
listCount ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
|
|
6470
6716
|
"Paged lists ",
|
|
6471
|
-
/* @__PURE__ */ (0,
|
|
6717
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: listCount })
|
|
6472
6718
|
] }) : null,
|
|
6473
|
-
/* @__PURE__ */ (0,
|
|
6474
|
-
/* @__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: [
|
|
6475
6721
|
hits.length,
|
|
6476
6722
|
" of ",
|
|
6477
6723
|
spec.length,
|
|
@@ -6479,31 +6725,31 @@ function ApiSpecBrowser({
|
|
|
6479
6725
|
listCount ? " \xB7 " + listCount + " paged" : ""
|
|
6480
6726
|
] })
|
|
6481
6727
|
] }),
|
|
6482
|
-
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]) => {
|
|
6483
6729
|
const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
|
|
6484
6730
|
if (!items.length) return null;
|
|
6485
|
-
return /* @__PURE__ */ (0,
|
|
6486
|
-
/* @__PURE__ */ (0,
|
|
6487
|
-
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))
|
|
6488
6734
|
] }, g);
|
|
6489
6735
|
}),
|
|
6490
|
-
conventions && conventions.length ? /* @__PURE__ */ (0,
|
|
6491
|
-
/* @__PURE__ */ (0,
|
|
6492
|
-
/* @__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 })
|
|
6493
6739
|
] }, k)) }) }) : null,
|
|
6494
|
-
openQuestions && openQuestions.length ? /* @__PURE__ */ (0,
|
|
6495
|
-
/* @__PURE__ */ (0,
|
|
6496
|
-
/* @__PURE__ */ (0,
|
|
6497
|
-
/* @__PURE__ */ (0,
|
|
6498
|
-
/* @__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 })
|
|
6499
6745
|
] })
|
|
6500
6746
|
] }, id)) }) }) : null
|
|
6501
6747
|
] });
|
|
6502
6748
|
}
|
|
6503
6749
|
|
|
6504
6750
|
// src/components/platform/ProfilePage.tsx
|
|
6505
|
-
var
|
|
6506
|
-
var
|
|
6751
|
+
var React29 = __toESM(require("react"), 1);
|
|
6752
|
+
var import_jsx_runtime58 = require("react/jsx-runtime");
|
|
6507
6753
|
var TIMEZONES = ["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles", "America/Anchorage", "Pacific/Honolulu", "Europe/London", "Europe/Berlin"];
|
|
6508
6754
|
var NOTIFY = [
|
|
6509
6755
|
{ key: "planShared", label: "A plan is shared with me", detail: "Someone sends you a plan or a client link." },
|
|
@@ -6515,7 +6761,7 @@ var NOTIFY = [
|
|
|
6515
6761
|
function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSessions = true, className = "", ...rest }) {
|
|
6516
6762
|
const session = SessionKit.useSession();
|
|
6517
6763
|
const user = userProp || session.user;
|
|
6518
|
-
const [draft, setDraft] =
|
|
6764
|
+
const [draft, setDraft] = React29.useState(() => ({
|
|
6519
6765
|
name: user.name || "",
|
|
6520
6766
|
title: user.title || "",
|
|
6521
6767
|
email: user.email || "",
|
|
@@ -6524,8 +6770,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6524
6770
|
bio: user.bio || "",
|
|
6525
6771
|
notify: user.notify || { planShared: true, planChanged: true, goalMissed: true, flagChanged: false, weekly: true }
|
|
6526
6772
|
}));
|
|
6527
|
-
const [saving, setSaving] =
|
|
6528
|
-
const [saved, setSaved] =
|
|
6773
|
+
const [saving, setSaving] = React29.useState(false);
|
|
6774
|
+
const [saved, setSaved] = React29.useState(false);
|
|
6529
6775
|
const set = (k, v) => {
|
|
6530
6776
|
setDraft((d) => Object.assign({}, d, { [k]: v }));
|
|
6531
6777
|
setSaved(false);
|
|
@@ -6547,43 +6793,43 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6547
6793
|
{ id: "s2", device: "iPhone 15 \xB7 Safari", where: "Denver, CO", when: "2 hours ago" },
|
|
6548
6794
|
{ id: "s3", device: "Windows \xB7 Edge", where: "Chicago, IL", when: "Aug 12" }
|
|
6549
6795
|
];
|
|
6550
|
-
return /* @__PURE__ */ (0,
|
|
6551
|
-
/* @__PURE__ */ (0,
|
|
6552
|
-
/* @__PURE__ */ (0,
|
|
6553
|
-
/* @__PURE__ */ (0,
|
|
6554
|
-
/* @__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." })
|
|
6555
6801
|
] }),
|
|
6556
|
-
/* @__PURE__ */ (0,
|
|
6557
|
-
/* @__PURE__ */ (0,
|
|
6558
|
-
/* @__PURE__ */ (0,
|
|
6559
|
-
/* @__PURE__ */ (0,
|
|
6560
|
-
/* @__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: [
|
|
6561
6807
|
draft.title || "No title set",
|
|
6562
6808
|
" \xB7 ",
|
|
6563
6809
|
user.team || "No team"
|
|
6564
6810
|
] }),
|
|
6565
|
-
/* @__PURE__ */ (0,
|
|
6566
|
-
session.roles.map((r) => /* @__PURE__ */ (0,
|
|
6567
|
-
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
|
|
6568
6814
|
] })
|
|
6569
6815
|
] }),
|
|
6570
|
-
/* @__PURE__ */ (0,
|
|
6816
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", children: "Change photo" })
|
|
6571
6817
|
] }) }),
|
|
6572
|
-
/* @__PURE__ */ (0,
|
|
6818
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6573
6819
|
Card,
|
|
6574
6820
|
{
|
|
6575
|
-
title: /* @__PURE__ */ (0,
|
|
6576
|
-
/* @__PURE__ */ (0,
|
|
6577
|
-
/* @__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" })
|
|
6578
6824
|
] }),
|
|
6579
6825
|
elevation: "flat",
|
|
6580
|
-
children: /* @__PURE__ */ (0,
|
|
6581
|
-
/* @__PURE__ */ (0,
|
|
6582
|
-
/* @__PURE__ */ (0,
|
|
6583
|
-
/* @__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" })
|
|
6584
6830
|
] }),
|
|
6585
|
-
/* @__PURE__ */ (0,
|
|
6586
|
-
/* @__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)(
|
|
6587
6833
|
Input,
|
|
6588
6834
|
{
|
|
6589
6835
|
label: "Work email",
|
|
@@ -6593,9 +6839,9 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6593
6839
|
help: user.sso ? "Managed by your identity provider \u2014 change it there." : "Contact an administrator to change this."
|
|
6594
6840
|
}
|
|
6595
6841
|
),
|
|
6596
|
-
/* @__PURE__ */ (0,
|
|
6842
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Input, { label: "Phone", value: draft.phone, onChange: (e) => set("phone", e.target.value), placeholder: "Optional" })
|
|
6597
6843
|
] }),
|
|
6598
|
-
/* @__PURE__ */ (0,
|
|
6844
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6599
6845
|
Textarea,
|
|
6600
6846
|
{
|
|
6601
6847
|
label: "Short bio",
|
|
@@ -6609,8 +6855,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6609
6855
|
] })
|
|
6610
6856
|
}
|
|
6611
6857
|
),
|
|
6612
|
-
/* @__PURE__ */ (0,
|
|
6613
|
-
/* @__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)(
|
|
6614
6860
|
Select,
|
|
6615
6861
|
{
|
|
6616
6862
|
label: "Time zone",
|
|
@@ -6620,28 +6866,28 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6620
6866
|
help: "Flight dates and schedules render in this zone."
|
|
6621
6867
|
}
|
|
6622
6868
|
),
|
|
6623
|
-
/* @__PURE__ */ (0,
|
|
6869
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Select, { label: "Start of week", options: ["Monday", "Sunday"], placeholder: "Monday" })
|
|
6624
6870
|
] }) }),
|
|
6625
|
-
/* @__PURE__ */ (0,
|
|
6871
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6626
6872
|
Card,
|
|
6627
6873
|
{
|
|
6628
|
-
title: /* @__PURE__ */ (0,
|
|
6629
|
-
/* @__PURE__ */ (0,
|
|
6630
|
-
/* @__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" })
|
|
6631
6877
|
] }),
|
|
6632
6878
|
elevation: "flat",
|
|
6633
|
-
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)) })
|
|
6634
6880
|
}
|
|
6635
6881
|
),
|
|
6636
|
-
/* @__PURE__ */ (0,
|
|
6882
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
|
|
6637
6883
|
Card,
|
|
6638
6884
|
{
|
|
6639
|
-
title: /* @__PURE__ */ (0,
|
|
6640
|
-
/* @__PURE__ */ (0,
|
|
6641
|
-
/* @__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" })
|
|
6642
6888
|
] }),
|
|
6643
6889
|
elevation: "flat",
|
|
6644
|
-
action: /* @__PURE__ */ (0,
|
|
6890
|
+
action: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6645
6891
|
Button,
|
|
6646
6892
|
{
|
|
6647
6893
|
size: "sm",
|
|
@@ -6652,39 +6898,39 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6652
6898
|
}
|
|
6653
6899
|
),
|
|
6654
6900
|
children: [
|
|
6655
|
-
/* @__PURE__ */ (0,
|
|
6656
|
-
/* @__PURE__ */ (0,
|
|
6657
|
-
/* @__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: [
|
|
6658
6904
|
session.permissions.length,
|
|
6659
6905
|
" granted"
|
|
6660
6906
|
] }),
|
|
6661
|
-
/* @__PURE__ */ (0,
|
|
6907
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
|
|
6662
6908
|
] }),
|
|
6663
|
-
/* @__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." })
|
|
6664
6910
|
]
|
|
6665
6911
|
}
|
|
6666
6912
|
),
|
|
6667
|
-
showSessions ? /* @__PURE__ */ (0,
|
|
6913
|
+
showSessions ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6668
6914
|
Card,
|
|
6669
6915
|
{
|
|
6670
6916
|
title: "Signed-in devices",
|
|
6671
6917
|
elevation: "flat",
|
|
6672
|
-
action: /* @__PURE__ */ (0,
|
|
6673
|
-
children: /* @__PURE__ */ (0,
|
|
6674
|
-
/* @__PURE__ */ (0,
|
|
6675
|
-
/* @__PURE__ */ (0,
|
|
6676
|
-
/* @__PURE__ */ (0,
|
|
6677
|
-
/* @__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: [
|
|
6678
6924
|
s.where,
|
|
6679
6925
|
" \xB7 ",
|
|
6680
6926
|
s.when
|
|
6681
6927
|
] })
|
|
6682
6928
|
] }),
|
|
6683
|
-
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" })
|
|
6684
6930
|
] }, s.id)) })
|
|
6685
6931
|
}
|
|
6686
6932
|
) : null,
|
|
6687
|
-
/* @__PURE__ */ (0,
|
|
6933
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-row", style: {
|
|
6688
6934
|
gap: 10,
|
|
6689
6935
|
flexWrap: "wrap",
|
|
6690
6936
|
position: "sticky",
|
|
@@ -6695,8 +6941,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6695
6941
|
border: "1px solid var(--border)",
|
|
6696
6942
|
boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
|
|
6697
6943
|
}, children: [
|
|
6698
|
-
/* @__PURE__ */ (0,
|
|
6699
|
-
/* @__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)(
|
|
6700
6946
|
Button,
|
|
6701
6947
|
{
|
|
6702
6948
|
size: "sm",
|
|
@@ -6709,16 +6955,16 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6709
6955
|
children: "Discard"
|
|
6710
6956
|
}
|
|
6711
6957
|
),
|
|
6712
|
-
/* @__PURE__ */ (0,
|
|
6958
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty, loading: saving, onClick: save, children: "Save changes" })
|
|
6713
6959
|
] })
|
|
6714
6960
|
] });
|
|
6715
6961
|
}
|
|
6716
6962
|
|
|
6717
6963
|
// src/components/platform/RoadmapTimeline.tsx
|
|
6718
|
-
var
|
|
6964
|
+
var React31 = __toESM(require("react"), 1);
|
|
6719
6965
|
|
|
6720
6966
|
// src/kits/runtime.ts
|
|
6721
|
-
var
|
|
6967
|
+
var React30 = __toESM(require("react"), 1);
|
|
6722
6968
|
var WIRED_ENDPOINTS = [
|
|
6723
6969
|
// Nothing yet. Every id below would come from a real service:
|
|
6724
6970
|
// "plan.get", "placements.list", …
|
|
@@ -6889,8 +7135,8 @@ var RuntimeKit = {
|
|
|
6889
7135
|
};
|
|
6890
7136
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
6891
7137
|
function useRuntimeMode() {
|
|
6892
|
-
const [m, setM] =
|
|
6893
|
-
|
|
7138
|
+
const [m, setM] = React30.useState(RuntimeKit.getMode());
|
|
7139
|
+
React30.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
6894
7140
|
return m;
|
|
6895
7141
|
}
|
|
6896
7142
|
function useFeatureStatus(key) {
|
|
@@ -6909,7 +7155,7 @@ var UseRuntimeMode = useRuntimeMode;
|
|
|
6909
7155
|
var UseFeatureStatus = useFeatureStatus;
|
|
6910
7156
|
|
|
6911
7157
|
// src/components/platform/RoadmapTimeline.tsx
|
|
6912
|
-
var
|
|
7158
|
+
var import_jsx_runtime59 = require("react/jsx-runtime");
|
|
6913
7159
|
var STATUS = {
|
|
6914
7160
|
shipped: { tone: "success", icon: "check-circle", label: "Wired" },
|
|
6915
7161
|
next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
|
|
@@ -6924,45 +7170,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
6924
7170
|
const s = STATUS[item.status] || STATUS.planned;
|
|
6925
7171
|
const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
|
|
6926
7172
|
const blocking = deps.filter((d) => !d.implemented);
|
|
6927
|
-
return /* @__PURE__ */ (0,
|
|
6928
|
-
/* @__PURE__ */ (0,
|
|
6929
|
-
/* @__PURE__ */ (0,
|
|
6930
|
-
/* @__PURE__ */ (0,
|
|
6931
|
-
/* @__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 })
|
|
6932
7178
|
] }),
|
|
6933
|
-
/* @__PURE__ */ (0,
|
|
6934
|
-
item.backend ? /* @__PURE__ */ (0,
|
|
6935
|
-
/* @__PURE__ */ (0,
|
|
6936
|
-
/* @__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 })
|
|
6937
7183
|
] }) : null,
|
|
6938
|
-
/* @__PURE__ */ (0,
|
|
6939
|
-
item.effort ? /* @__PURE__ */ (0,
|
|
6940
|
-
/* @__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" }),
|
|
6941
7187
|
" ",
|
|
6942
7188
|
item.effort
|
|
6943
7189
|
] }) : null,
|
|
6944
|
-
/* @__PURE__ */ (0,
|
|
6945
|
-
/* @__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" }),
|
|
6946
7192
|
" ",
|
|
6947
7193
|
item.owner
|
|
6948
7194
|
] }),
|
|
6949
|
-
item.screen ? /* @__PURE__ */ (0,
|
|
6950
|
-
/* @__PURE__ */ (0,
|
|
6951
|
-
/* @__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)(
|
|
6952
7198
|
"button",
|
|
6953
7199
|
{
|
|
6954
7200
|
type: "button",
|
|
6955
7201
|
onClick: () => onOpenFlag && onOpenFlag(item.key),
|
|
6956
7202
|
style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
|
|
6957
|
-
children: /* @__PURE__ */ (0,
|
|
7203
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
|
|
6958
7204
|
}
|
|
6959
7205
|
)
|
|
6960
7206
|
] }),
|
|
6961
|
-
deps.length ? /* @__PURE__ */ (0,
|
|
6962
|
-
/* @__PURE__ */ (0,
|
|
6963
|
-
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))
|
|
6964
7210
|
] }) : null,
|
|
6965
|
-
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: [
|
|
6966
7212
|
"Blocked until ",
|
|
6967
7213
|
blocking.map((d) => d.label).join(" and "),
|
|
6968
7214
|
" ",
|
|
@@ -6973,12 +7219,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
6973
7219
|
}
|
|
6974
7220
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
6975
7221
|
const session = SessionKit.useSession();
|
|
6976
|
-
const [project, setProject] =
|
|
6977
|
-
const [q, setQ] =
|
|
6978
|
-
const scrollRef =
|
|
6979
|
-
const nowRef =
|
|
6980
|
-
const rm =
|
|
6981
|
-
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(() => {
|
|
6982
7228
|
const m = {};
|
|
6983
7229
|
rm.items.forEach((i) => {
|
|
6984
7230
|
m[i.key] = i;
|
|
@@ -6987,7 +7233,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
6987
7233
|
}, [rm]);
|
|
6988
7234
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
6989
7235
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
6990
|
-
|
|
7236
|
+
React31.useEffect(() => {
|
|
6991
7237
|
let raf1 = 0, raf2 = 0;
|
|
6992
7238
|
const place = () => {
|
|
6993
7239
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -7015,23 +7261,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7015
7261
|
}, 0);
|
|
7016
7262
|
const nextPhase = items.find((i) => !i.implemented);
|
|
7017
7263
|
let lastPhase = null;
|
|
7018
|
-
return /* @__PURE__ */ (0,
|
|
7019
|
-
/* @__PURE__ */ (0,
|
|
7020
|
-
/* @__PURE__ */ (0,
|
|
7021
|
-
/* @__PURE__ */ (0,
|
|
7022
|
-
/* @__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." })
|
|
7023
7269
|
] }),
|
|
7024
|
-
/* @__PURE__ */ (0,
|
|
7025
|
-
/* @__PURE__ */ (0,
|
|
7026
|
-
/* @__PURE__ */ (0,
|
|
7027
|
-
/* @__PURE__ */ (0,
|
|
7028
|
-
/* @__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" })
|
|
7029
7275
|
] }),
|
|
7030
|
-
/* @__PURE__ */ (0,
|
|
7031
|
-
/* @__PURE__ */ (0,
|
|
7032
|
-
/* @__PURE__ */ (0,
|
|
7033
|
-
/* @__PURE__ */ (0,
|
|
7034
|
-
/* @__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)(
|
|
7035
7281
|
Button,
|
|
7036
7282
|
{
|
|
7037
7283
|
size: "sm",
|
|
@@ -7045,7 +7291,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7045
7291
|
}
|
|
7046
7292
|
)
|
|
7047
7293
|
] }),
|
|
7048
|
-
/* @__PURE__ */ (0,
|
|
7294
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
7049
7295
|
Flag,
|
|
7050
7296
|
{
|
|
7051
7297
|
tone: "info",
|
|
@@ -7054,60 +7300,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7054
7300
|
actions: null
|
|
7055
7301
|
}
|
|
7056
7302
|
),
|
|
7057
|
-
/* @__PURE__ */ (0,
|
|
7058
|
-
/* @__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%" } }) }),
|
|
7059
7305
|
items.map((item, n) => {
|
|
7060
7306
|
const showPhase = item.phase !== lastPhase;
|
|
7061
7307
|
lastPhase = item.phase;
|
|
7062
7308
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
7063
7309
|
const isBoundary = n === firstPending;
|
|
7064
|
-
return /* @__PURE__ */ (0,
|
|
7065
|
-
showPhase ? /* @__PURE__ */ (0,
|
|
7066
|
-
/* @__PURE__ */ (0,
|
|
7067
|
-
/* @__PURE__ */ (0,
|
|
7068
|
-
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: [
|
|
7069
7315
|
fmtDate(item.phaseStart),
|
|
7070
7316
|
" \u2013 ",
|
|
7071
7317
|
fmtDate(item.date)
|
|
7072
7318
|
] }),
|
|
7073
|
-
/* @__PURE__ */ (0,
|
|
7319
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
7074
7320
|
"\xB7 ",
|
|
7075
7321
|
inPhase,
|
|
7076
7322
|
" feature",
|
|
7077
7323
|
inPhase === 1 ? "" : "s"
|
|
7078
7324
|
] })
|
|
7079
7325
|
] }),
|
|
7080
|
-
item.phaseWhy ? /* @__PURE__ */ (0,
|
|
7326
|
+
item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
|
|
7081
7327
|
] }) : null,
|
|
7082
|
-
isBoundary ? /* @__PURE__ */ (0,
|
|
7083
|
-
/* @__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" }),
|
|
7084
7330
|
" You are here \u2014 everything above is wired"
|
|
7085
7331
|
] }) }) : null,
|
|
7086
|
-
/* @__PURE__ */ (0,
|
|
7087
|
-
/* @__PURE__ */ (0,
|
|
7088
|
-
/* @__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: [
|
|
7089
7335
|
fmtDate(item.date),
|
|
7090
|
-
/* @__PURE__ */ (0,
|
|
7091
|
-
/* @__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 })
|
|
7092
7338
|
] }),
|
|
7093
|
-
/* @__PURE__ */ (0,
|
|
7339
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
|
|
7094
7340
|
] })
|
|
7095
7341
|
] }, item.key);
|
|
7096
7342
|
}),
|
|
7097
|
-
!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
|
|
7098
7344
|
] }) }) }),
|
|
7099
|
-
/* @__PURE__ */ (0,
|
|
7345
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
|
|
7100
7346
|
"Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
|
|
7101
|
-
/* @__PURE__ */ (0,
|
|
7347
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("code", { className: "fd-mono", children: "implemented" }),
|
|
7102
7348
|
" field, so this page cannot drift from what the apps actually do."
|
|
7103
7349
|
] })
|
|
7104
7350
|
] });
|
|
7105
7351
|
}
|
|
7106
7352
|
|
|
7107
7353
|
// src/components/platform/ComingSoon.tsx
|
|
7108
|
-
var
|
|
7354
|
+
var React32 = __toESM(require("react"), 1);
|
|
7109
7355
|
var import_react_dom7 = require("react-dom");
|
|
7110
|
-
var
|
|
7356
|
+
var import_jsx_runtime60 = require("react/jsx-runtime");
|
|
7111
7357
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
7112
7358
|
function readBypassed() {
|
|
7113
7359
|
try {
|
|
@@ -7123,8 +7369,8 @@ function writeBypassed(list) {
|
|
|
7123
7369
|
}
|
|
7124
7370
|
}
|
|
7125
7371
|
function useBypass(key) {
|
|
7126
|
-
const [on, setOn] =
|
|
7127
|
-
|
|
7372
|
+
const [on, setOn] = React32.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
7373
|
+
React32.useEffect(() => {
|
|
7128
7374
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
7129
7375
|
}, [key]);
|
|
7130
7376
|
const set = (next) => {
|
|
@@ -7137,43 +7383,43 @@ function useBypass(key) {
|
|
|
7137
7383
|
return [on, set];
|
|
7138
7384
|
}
|
|
7139
7385
|
function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
|
|
7140
|
-
return /* @__PURE__ */ (0,
|
|
7141
|
-
/* @__PURE__ */ (0,
|
|
7142
|
-
/* @__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" }),
|
|
7143
7389
|
label
|
|
7144
7390
|
] }),
|
|
7145
|
-
detail ? /* @__PURE__ */ (0,
|
|
7146
|
-
backend ? /* @__PURE__ */ (0,
|
|
7147
|
-
/* @__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" }),
|
|
7148
7394
|
" ",
|
|
7149
7395
|
backend
|
|
7150
7396
|
] }) : null,
|
|
7151
|
-
eta || effort || onRoadmap ? /* @__PURE__ */ (0,
|
|
7152
|
-
eta ? /* @__PURE__ */ (0,
|
|
7153
|
-
/* @__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" }),
|
|
7154
7400
|
" ",
|
|
7155
7401
|
eta
|
|
7156
7402
|
] }) : null,
|
|
7157
|
-
effort ? /* @__PURE__ */ (0,
|
|
7158
|
-
/* @__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" }),
|
|
7159
7405
|
" ",
|
|
7160
7406
|
effort
|
|
7161
7407
|
] }) : null,
|
|
7162
|
-
onRoadmap ? /* @__PURE__ */ (0,
|
|
7408
|
+
onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
7163
7409
|
"See the roadmap ",
|
|
7164
|
-
/* @__PURE__ */ (0,
|
|
7410
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7165
7411
|
] }) : null
|
|
7166
7412
|
] }) : null,
|
|
7167
|
-
allowed ? /* @__PURE__ */ (0,
|
|
7168
|
-
/* @__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" }),
|
|
7169
7415
|
" View and use it anyway"
|
|
7170
7416
|
] }) : null
|
|
7171
7417
|
] });
|
|
7172
7418
|
}
|
|
7173
7419
|
function useHoverCard(open) {
|
|
7174
|
-
const anchor =
|
|
7175
|
-
const [pos, setPos] =
|
|
7176
|
-
|
|
7420
|
+
const anchor = React32.useRef(null);
|
|
7421
|
+
const [pos, setPos] = React32.useState(null);
|
|
7422
|
+
React32.useLayoutEffect(() => {
|
|
7177
7423
|
if (!open || !anchor.current) {
|
|
7178
7424
|
setPos(null);
|
|
7179
7425
|
return;
|
|
@@ -7225,9 +7471,9 @@ function ComingSoon({
|
|
|
7225
7471
|
const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
|
|
7226
7472
|
if (inline) {
|
|
7227
7473
|
if (allowed && bypassed) {
|
|
7228
|
-
return /* @__PURE__ */ (0,
|
|
7474
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
|
|
7229
7475
|
children,
|
|
7230
|
-
/* @__PURE__ */ (0,
|
|
7476
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7231
7477
|
"button",
|
|
7232
7478
|
{
|
|
7233
7479
|
type: "button",
|
|
@@ -7235,12 +7481,12 @@ function ComingSoon({
|
|
|
7235
7481
|
title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
|
|
7236
7482
|
onClick: () => setBypassed(false),
|
|
7237
7483
|
"aria-label": "Re-blur this unwired feature",
|
|
7238
|
-
children: /* @__PURE__ */ (0,
|
|
7484
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
7239
7485
|
}
|
|
7240
7486
|
)
|
|
7241
7487
|
] });
|
|
7242
7488
|
}
|
|
7243
|
-
return /* @__PURE__ */ (0,
|
|
7489
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7244
7490
|
InlineSoon,
|
|
7245
7491
|
{
|
|
7246
7492
|
label,
|
|
@@ -7260,20 +7506,20 @@ function ComingSoon({
|
|
|
7260
7506
|
);
|
|
7261
7507
|
}
|
|
7262
7508
|
if (allowed && bypassed) {
|
|
7263
|
-
return /* @__PURE__ */ (0,
|
|
7264
|
-
/* @__PURE__ */ (0,
|
|
7265
|
-
/* @__PURE__ */ (0,
|
|
7266
|
-
/* @__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" }),
|
|
7267
7513
|
"Unwired feature \u2014 you are using it anyway"
|
|
7268
7514
|
] }),
|
|
7269
|
-
/* @__PURE__ */ (0,
|
|
7270
|
-
/* @__PURE__ */ (0,
|
|
7271
|
-
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: [
|
|
7272
7518
|
"Roadmap ",
|
|
7273
|
-
/* @__PURE__ */ (0,
|
|
7519
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7274
7520
|
] }) : null,
|
|
7275
|
-
/* @__PURE__ */ (0,
|
|
7276
|
-
/* @__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" }),
|
|
7277
7523
|
" Re-blur"
|
|
7278
7524
|
] })
|
|
7279
7525
|
] })
|
|
@@ -7281,10 +7527,10 @@ function ComingSoon({
|
|
|
7281
7527
|
children
|
|
7282
7528
|
] });
|
|
7283
7529
|
}
|
|
7284
|
-
return /* @__PURE__ */ (0,
|
|
7285
|
-
/* @__PURE__ */ (0,
|
|
7286
|
-
/* @__PURE__ */ (0,
|
|
7287
|
-
/* @__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)(
|
|
7288
7534
|
SoonCard,
|
|
7289
7535
|
{
|
|
7290
7536
|
label,
|
|
@@ -7300,9 +7546,9 @@ function ComingSoon({
|
|
|
7300
7546
|
] });
|
|
7301
7547
|
}
|
|
7302
7548
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
7303
|
-
const [open, setOpen] =
|
|
7549
|
+
const [open, setOpen] = React32.useState(false);
|
|
7304
7550
|
const [anchor, pos] = useHoverCard(open);
|
|
7305
|
-
const close =
|
|
7551
|
+
const close = React32.useRef(null);
|
|
7306
7552
|
const show = () => {
|
|
7307
7553
|
if (close.current) {
|
|
7308
7554
|
clearTimeout(close.current);
|
|
@@ -7318,10 +7564,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7318
7564
|
setOpen(false);
|
|
7319
7565
|
}, 140);
|
|
7320
7566
|
};
|
|
7321
|
-
|
|
7567
|
+
React32.useEffect(() => () => {
|
|
7322
7568
|
if (close.current) clearTimeout(close.current);
|
|
7323
7569
|
}, []);
|
|
7324
|
-
return /* @__PURE__ */ (0,
|
|
7570
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
|
|
7325
7571
|
"span",
|
|
7326
7572
|
{
|
|
7327
7573
|
ref: anchor,
|
|
@@ -7332,8 +7578,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7332
7578
|
onBlur: hide,
|
|
7333
7579
|
...rest,
|
|
7334
7580
|
children: [
|
|
7335
|
-
/* @__PURE__ */ (0,
|
|
7336
|
-
/* @__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)(
|
|
7337
7583
|
"button",
|
|
7338
7584
|
{
|
|
7339
7585
|
type: "button",
|
|
@@ -7344,11 +7590,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7344
7590
|
onFocus: show,
|
|
7345
7591
|
onBlur: hide,
|
|
7346
7592
|
onClick: () => open ? setOpen(false) : show(),
|
|
7347
|
-
children: /* @__PURE__ */ (0,
|
|
7593
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
7348
7594
|
}
|
|
7349
7595
|
),
|
|
7350
7596
|
open && pos ? (0, import_react_dom7.createPortal)(
|
|
7351
|
-
/* @__PURE__ */ (0,
|
|
7597
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7352
7598
|
"div",
|
|
7353
7599
|
{
|
|
7354
7600
|
className: "fd-soon-note fd-soon-hovercard",
|
|
@@ -7356,7 +7602,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7356
7602
|
style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width },
|
|
7357
7603
|
onMouseEnter: show,
|
|
7358
7604
|
onMouseLeave: hide,
|
|
7359
|
-
children: /* @__PURE__ */ (0,
|
|
7605
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7360
7606
|
SoonCard,
|
|
7361
7607
|
{
|
|
7362
7608
|
label,
|
|
@@ -7386,10 +7632,10 @@ function formatEta(iso2) {
|
|
|
7386
7632
|
var FormatEta = formatEta;
|
|
7387
7633
|
|
|
7388
7634
|
// src/components/platform/Gate.tsx
|
|
7389
|
-
var
|
|
7635
|
+
var import_jsx_runtime61 = require("react/jsx-runtime");
|
|
7390
7636
|
function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
|
|
7391
7637
|
const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
|
|
7392
|
-
return /* @__PURE__ */ (0,
|
|
7638
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
|
|
7393
7639
|
"div",
|
|
7394
7640
|
{
|
|
7395
7641
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -7405,14 +7651,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
7405
7651
|
},
|
|
7406
7652
|
...rest,
|
|
7407
7653
|
children: [
|
|
7408
|
-
/* @__PURE__ */ (0,
|
|
7409
|
-
/* @__PURE__ */ (0,
|
|
7410
|
-
/* @__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" })
|
|
7411
7657
|
] }),
|
|
7412
|
-
/* @__PURE__ */ (0,
|
|
7413
|
-
need.length ? /* @__PURE__ */ (0,
|
|
7414
|
-
/* @__PURE__ */ (0,
|
|
7415
|
-
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: {
|
|
7416
7662
|
fontSize: 11.5,
|
|
7417
7663
|
padding: "2px 7px",
|
|
7418
7664
|
borderRadius: 5,
|
|
@@ -7433,7 +7679,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, compact: compact3 =
|
|
|
7433
7679
|
if (ok) return children;
|
|
7434
7680
|
if (fallback !== void 0) return fallback;
|
|
7435
7681
|
if (silent) return null;
|
|
7436
|
-
return /* @__PURE__ */ (0,
|
|
7682
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
|
|
7437
7683
|
}
|
|
7438
7684
|
function FeatureGate({
|
|
7439
7685
|
flag,
|
|
@@ -7454,7 +7700,7 @@ function FeatureGate({
|
|
|
7454
7700
|
if (!preview) return fallback;
|
|
7455
7701
|
const f = SessionKit.findFlag(flag) || {};
|
|
7456
7702
|
const missing = rt.missing || [];
|
|
7457
|
-
return /* @__PURE__ */ (0,
|
|
7703
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
7458
7704
|
ComingSoon,
|
|
7459
7705
|
{
|
|
7460
7706
|
label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
|
|
@@ -7475,25 +7721,25 @@ function FeatureGate({
|
|
|
7475
7721
|
function PermissionHint({ perm, children }) {
|
|
7476
7722
|
SessionKit.useSession();
|
|
7477
7723
|
if (SessionKit.can(perm)) return children;
|
|
7478
|
-
return /* @__PURE__ */ (0,
|
|
7724
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
7479
7725
|
"span",
|
|
7480
7726
|
{
|
|
7481
7727
|
title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
|
|
7482
7728
|
style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
|
|
7483
7729
|
"aria-disabled": "true",
|
|
7484
|
-
children: /* @__PURE__ */ (0,
|
|
7730
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { style: { pointerEvents: "none" }, children })
|
|
7485
7731
|
}
|
|
7486
7732
|
);
|
|
7487
7733
|
}
|
|
7488
7734
|
|
|
7489
7735
|
// src/components/platform/ModeSwitch.tsx
|
|
7490
|
-
var
|
|
7491
|
-
var
|
|
7736
|
+
var React33 = __toESM(require("react"), 1);
|
|
7737
|
+
var import_jsx_runtime62 = require("react/jsx-runtime");
|
|
7492
7738
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
7493
7739
|
const mode2 = useRuntimeMode();
|
|
7494
|
-
const [open, setOpen] =
|
|
7495
|
-
const ref =
|
|
7496
|
-
|
|
7740
|
+
const [open, setOpen] = React33.useState(false);
|
|
7741
|
+
const ref = React33.useRef(null);
|
|
7742
|
+
React33.useEffect(() => {
|
|
7497
7743
|
if (!open) return;
|
|
7498
7744
|
const away = (e) => {
|
|
7499
7745
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -7515,8 +7761,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7515
7761
|
RuntimeKit.setMode(next);
|
|
7516
7762
|
setOpen(false);
|
|
7517
7763
|
};
|
|
7518
|
-
return /* @__PURE__ */ (0,
|
|
7519
|
-
/* @__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)(
|
|
7520
7766
|
"button",
|
|
7521
7767
|
{
|
|
7522
7768
|
type: "button",
|
|
@@ -7526,29 +7772,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7526
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.",
|
|
7527
7773
|
className: "fd-mode-btn" + (test ? " is-test" : "") + (open ? " is-open" : ""),
|
|
7528
7774
|
children: [
|
|
7529
|
-
/* @__PURE__ */ (0,
|
|
7530
|
-
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
|
|
7531
7777
|
]
|
|
7532
7778
|
}
|
|
7533
7779
|
),
|
|
7534
|
-
open ? /* @__PURE__ */ (0,
|
|
7535
|
-
/* @__PURE__ */ (0,
|
|
7536
|
-
/* @__PURE__ */ (0,
|
|
7537
|
-
/* @__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" }),
|
|
7538
7784
|
test ? "Test mode" : "Live mode"
|
|
7539
7785
|
] }),
|
|
7540
|
-
test ? /* @__PURE__ */ (0,
|
|
7786
|
+
test ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
7541
7787
|
requestCount,
|
|
7542
7788
|
" simulated request",
|
|
7543
7789
|
requestCount === 1 ? "" : "s"
|
|
7544
7790
|
] }) : null,
|
|
7545
|
-
/* @__PURE__ */ (0,
|
|
7546
|
-
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
|
|
7547
7793
|
] }),
|
|
7548
|
-
/* @__PURE__ */ (0,
|
|
7549
|
-
/* @__PURE__ */ (0,
|
|
7550
|
-
/* @__PURE__ */ (0,
|
|
7551
|
-
/* @__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: [
|
|
7552
7798
|
s.endpointsWired,
|
|
7553
7799
|
" endpoint",
|
|
7554
7800
|
s.endpointsWired === 1 ? "" : "s",
|
|
@@ -7558,58 +7804,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7558
7804
|
s.total,
|
|
7559
7805
|
" features complete"
|
|
7560
7806
|
] }),
|
|
7561
|
-
onOpenSpec ? /* @__PURE__ */ (0,
|
|
7562
|
-
/* @__PURE__ */ (0,
|
|
7563
|
-
/* @__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: () => {
|
|
7564
7810
|
setOpen(false);
|
|
7565
7811
|
onOpenSpec();
|
|
7566
7812
|
}, children: [
|
|
7567
7813
|
"API spec ",
|
|
7568
|
-
/* @__PURE__ */ (0,
|
|
7814
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7569
7815
|
] })
|
|
7570
7816
|
] }) : null
|
|
7571
7817
|
] })
|
|
7572
7818
|
] }),
|
|
7573
|
-
/* @__PURE__ */ (0,
|
|
7574
|
-
/* @__PURE__ */ (0,
|
|
7575
|
-
/* @__PURE__ */ (0,
|
|
7576
|
-
/* @__PURE__ */ (0,
|
|
7577
|
-
/* @__PURE__ */ (0,
|
|
7578
|
-
/* @__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" })
|
|
7579
7825
|
] }),
|
|
7580
|
-
!test ? /* @__PURE__ */ (0,
|
|
7826
|
+
!test ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
7581
7827
|
] }),
|
|
7582
|
-
/* @__PURE__ */ (0,
|
|
7583
|
-
/* @__PURE__ */ (0,
|
|
7584
|
-
/* @__PURE__ */ (0,
|
|
7585
|
-
/* @__PURE__ */ (0,
|
|
7586
|
-
/* @__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" })
|
|
7587
7833
|
] }),
|
|
7588
|
-
test ? /* @__PURE__ */ (0,
|
|
7834
|
+
test ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
7589
7835
|
] })
|
|
7590
7836
|
] }),
|
|
7591
|
-
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
|
|
7592
7838
|
] }) : null
|
|
7593
7839
|
] });
|
|
7594
7840
|
}
|
|
7595
7841
|
function TestModeBar({ onExit }) {
|
|
7596
7842
|
const mode2 = useRuntimeMode();
|
|
7597
7843
|
if (mode2 !== "test") return null;
|
|
7598
|
-
return /* @__PURE__ */ (0,
|
|
7599
|
-
/* @__PURE__ */ (0,
|
|
7600
|
-
/* @__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" }),
|
|
7601
7847
|
"Test mode"
|
|
7602
7848
|
] }),
|
|
7603
|
-
/* @__PURE__ */ (0,
|
|
7604
|
-
/* @__PURE__ */ (0,
|
|
7605
|
-
/* @__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" }),
|
|
7606
7852
|
" Back to live mode"
|
|
7607
7853
|
] })
|
|
7608
7854
|
] });
|
|
7609
7855
|
}
|
|
7610
7856
|
|
|
7611
7857
|
// src/components/planner/ChannelMeta.tsx
|
|
7612
|
-
var
|
|
7858
|
+
var import_jsx_runtime63 = require("react/jsx-runtime");
|
|
7613
7859
|
var CHANNEL_WEIGHTS = {
|
|
7614
7860
|
"OOH": 50,
|
|
7615
7861
|
"DOOH": 50,
|
|
@@ -7662,9 +7908,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
7662
7908
|
const m = ChannelMeta(channel);
|
|
7663
7909
|
const wt = channelWeightOf(channel || "");
|
|
7664
7910
|
if (dot) {
|
|
7665
|
-
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 });
|
|
7666
7912
|
}
|
|
7667
|
-
return /* @__PURE__ */ (0,
|
|
7913
|
+
return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
|
|
7668
7914
|
"span",
|
|
7669
7915
|
{
|
|
7670
7916
|
className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
|
|
@@ -7672,16 +7918,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
7672
7918
|
style: { "--chan": m.color },
|
|
7673
7919
|
...rest,
|
|
7674
7920
|
children: [
|
|
7675
|
-
/* @__PURE__ */ (0,
|
|
7676
|
-
showLabel ? /* @__PURE__ */ (0,
|
|
7677
|
-
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
|
|
7678
7924
|
]
|
|
7679
7925
|
}
|
|
7680
7926
|
);
|
|
7681
7927
|
}
|
|
7682
7928
|
|
|
7683
7929
|
// src/components/planner/SaturationDistribution.tsx
|
|
7684
|
-
var
|
|
7930
|
+
var import_jsx_runtime64 = require("react/jsx-runtime");
|
|
7685
7931
|
var BANDS2 = [
|
|
7686
7932
|
{ key: "weak", label: "Weak", n: 1, range: "< 50" },
|
|
7687
7933
|
{ key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
|
|
@@ -7692,18 +7938,18 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
7692
7938
|
const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
|
|
7693
7939
|
const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
|
|
7694
7940
|
const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
|
|
7695
|
-
return /* @__PURE__ */ (0,
|
|
7696
|
-
/* @__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) => {
|
|
7697
7943
|
const mark = "var(--csi-" + g.n + "-mark)";
|
|
7698
7944
|
const active = selectedBand === g.key;
|
|
7699
|
-
return /* @__PURE__ */ (0,
|
|
7945
|
+
return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
|
|
7700
7946
|
"button",
|
|
7701
7947
|
{
|
|
7702
7948
|
type: "button",
|
|
7703
7949
|
onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
|
|
7704
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)" },
|
|
7705
7951
|
children: [
|
|
7706
|
-
/* @__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)(
|
|
7707
7953
|
"span",
|
|
7708
7954
|
{
|
|
7709
7955
|
title: c.name + " \xB7 " + c.crp,
|
|
@@ -7712,13 +7958,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
7712
7958
|
},
|
|
7713
7959
|
c.name
|
|
7714
7960
|
)) }),
|
|
7715
|
-
/* @__PURE__ */ (0,
|
|
7716
|
-
/* @__PURE__ */ (0,
|
|
7717
|
-
/* @__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)) })
|
|
7718
7964
|
] }),
|
|
7719
|
-
/* @__PURE__ */ (0,
|
|
7720
|
-
/* @__PURE__ */ (0,
|
|
7721
|
-
/* @__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: [
|
|
7722
7968
|
"CRP ",
|
|
7723
7969
|
g.range
|
|
7724
7970
|
] })
|
|
@@ -7728,10 +7974,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
7728
7974
|
g.key
|
|
7729
7975
|
);
|
|
7730
7976
|
}) }),
|
|
7731
|
-
floorBand ? /* @__PURE__ */ (0,
|
|
7732
|
-
/* @__PURE__ */ (0,
|
|
7733
|
-
/* @__PURE__ */ (0,
|
|
7734
|
-
/* @__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: [
|
|
7735
7981
|
"Plan floor ",
|
|
7736
7982
|
floorScore
|
|
7737
7983
|
] }),
|
|
@@ -7742,21 +7988,21 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
7742
7988
|
}
|
|
7743
7989
|
|
|
7744
7990
|
// src/components/planner/MixGap.tsx
|
|
7745
|
-
var
|
|
7746
|
-
var
|
|
7991
|
+
var React34 = __toESM(require("react"), 1);
|
|
7992
|
+
var import_jsx_runtime65 = require("react/jsx-runtime");
|
|
7747
7993
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
7748
7994
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
7749
|
-
const [hover, setHover] =
|
|
7995
|
+
const [hover, setHover] = React34.useState(null);
|
|
7750
7996
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
7751
7997
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
7752
|
-
return /* @__PURE__ */ (0,
|
|
7753
|
-
/* @__PURE__ */ (0,
|
|
7754
|
-
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0,
|
|
7755
|
-
/* @__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 } }),
|
|
7756
8002
|
l
|
|
7757
8003
|
] }, l)),
|
|
7758
|
-
/* @__PURE__ */ (0,
|
|
7759
|
-
/* @__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)" } }),
|
|
7760
8006
|
"Target"
|
|
7761
8007
|
] })
|
|
7762
8008
|
] }),
|
|
@@ -7764,7 +8010,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
7764
8010
|
const gap = r.realized - r.target;
|
|
7765
8011
|
const tone = toneOf(gap);
|
|
7766
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 : "");
|
|
7767
|
-
return /* @__PURE__ */ (0,
|
|
8013
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
|
|
7768
8014
|
"div",
|
|
7769
8015
|
{
|
|
7770
8016
|
className: "fd-row",
|
|
@@ -7772,15 +8018,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
7772
8018
|
onMouseEnter: () => setHover(r.channel),
|
|
7773
8019
|
onMouseLeave: () => setHover(null),
|
|
7774
8020
|
children: [
|
|
7775
|
-
/* @__PURE__ */ (0,
|
|
7776
|
-
/* @__PURE__ */ (0,
|
|
7777
|
-
/* @__PURE__ */ (0,
|
|
7778
|
-
/* @__PURE__ */ (0,
|
|
7779
|
-
/* @__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: [
|
|
7780
8026
|
r.realized,
|
|
7781
8027
|
"%"
|
|
7782
8028
|
] }),
|
|
7783
|
-
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
|
|
7784
8030
|
] }) })
|
|
7785
8031
|
]
|
|
7786
8032
|
},
|
|
@@ -7791,7 +8037,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
7791
8037
|
}
|
|
7792
8038
|
|
|
7793
8039
|
// src/components/planner/ChannelContribution.tsx
|
|
7794
|
-
var
|
|
8040
|
+
var import_jsx_runtime66 = require("react/jsx-runtime");
|
|
7795
8041
|
var money = (n) => "$" + Math.round(n).toLocaleString();
|
|
7796
8042
|
function ChannelContribution({
|
|
7797
8043
|
channels = [],
|
|
@@ -7807,9 +8053,9 @@ function ChannelContribution({
|
|
|
7807
8053
|
const grand = total !== void 0 ? total : base + bonus;
|
|
7808
8054
|
const pct = (v) => grand ? v / grand * 100 : 0;
|
|
7809
8055
|
const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
|
|
7810
|
-
return /* @__PURE__ */ (0,
|
|
7811
|
-
loading ? /* @__PURE__ */ (0,
|
|
7812
|
-
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)(
|
|
7813
8059
|
"span",
|
|
7814
8060
|
{
|
|
7815
8061
|
title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
|
|
@@ -7818,7 +8064,7 @@ function ChannelContribution({
|
|
|
7818
8064
|
},
|
|
7819
8065
|
c.name
|
|
7820
8066
|
)),
|
|
7821
|
-
bonus > 0 ? /* @__PURE__ */ (0,
|
|
8067
|
+
bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
|
|
7822
8068
|
"span",
|
|
7823
8069
|
{
|
|
7824
8070
|
title: "Surround-sound bonus +" + bonusPct + "%",
|
|
@@ -7827,18 +8073,18 @@ function ChannelContribution({
|
|
|
7827
8073
|
}
|
|
7828
8074
|
) : null
|
|
7829
8075
|
] }),
|
|
7830
|
-
showTable ? /* @__PURE__ */ (0,
|
|
7831
|
-
/* @__PURE__ */ (0,
|
|
7832
|
-
/* @__PURE__ */ (0,
|
|
7833
|
-
/* @__PURE__ */ (0,
|
|
7834
|
-
/* @__PURE__ */ (0,
|
|
7835
|
-
/* @__PURE__ */ (0,
|
|
7836
|
-
/* @__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" })
|
|
7837
8083
|
] }) }),
|
|
7838
|
-
/* @__PURE__ */ (0,
|
|
7839
|
-
channels.map((c) => /* @__PURE__ */ (0,
|
|
7840
|
-
/* @__PURE__ */ (0,
|
|
7841
|
-
/* @__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)(
|
|
7842
8088
|
"span",
|
|
7843
8089
|
{
|
|
7844
8090
|
className: "fd-badge fd-badge-neutral",
|
|
@@ -7847,38 +8093,38 @@ function ChannelContribution({
|
|
|
7847
8093
|
children: "weight " + (channelWeightOf(c.name) || 0)
|
|
7848
8094
|
}
|
|
7849
8095
|
) }),
|
|
7850
|
-
/* @__PURE__ */ (0,
|
|
7851
|
-
/* @__PURE__ */ (0,
|
|
7852
|
-
/* @__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: [
|
|
7853
8099
|
pct(c.crp).toFixed(0),
|
|
7854
8100
|
"%"
|
|
7855
8101
|
] })
|
|
7856
8102
|
] }, c.name)),
|
|
7857
|
-
bonus > 0 ? /* @__PURE__ */ (0,
|
|
7858
|
-
/* @__PURE__ */ (0,
|
|
7859
|
-
/* @__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" } }),
|
|
7860
8106
|
"Surround-sound bonus"
|
|
7861
8107
|
] }) }),
|
|
7862
|
-
/* @__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: [
|
|
7863
8109
|
"+",
|
|
7864
8110
|
bonusPct,
|
|
7865
8111
|
"% of +",
|
|
7866
8112
|
bonusMax,
|
|
7867
8113
|
"%"
|
|
7868
8114
|
] }) }),
|
|
7869
|
-
/* @__PURE__ */ (0,
|
|
7870
|
-
/* @__PURE__ */ (0,
|
|
7871
|
-
/* @__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: [
|
|
7872
8118
|
pct(bonus).toFixed(0),
|
|
7873
8119
|
"%"
|
|
7874
8120
|
] })
|
|
7875
8121
|
] }) : null,
|
|
7876
|
-
/* @__PURE__ */ (0,
|
|
7877
|
-
/* @__PURE__ */ (0,
|
|
7878
|
-
/* @__PURE__ */ (0,
|
|
7879
|
-
/* @__PURE__ */ (0,
|
|
7880
|
-
/* @__PURE__ */ (0,
|
|
7881
|
-
/* @__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%" })
|
|
7882
8128
|
] })
|
|
7883
8129
|
] })
|
|
7884
8130
|
] }) : null
|
|
@@ -7886,8 +8132,8 @@ function ChannelContribution({
|
|
|
7886
8132
|
}
|
|
7887
8133
|
|
|
7888
8134
|
// src/components/planner/BudgetReallocator.tsx
|
|
7889
|
-
var
|
|
7890
|
-
var
|
|
8135
|
+
var React35 = __toESM(require("react"), 1);
|
|
8136
|
+
var import_jsx_runtime67 = require("react/jsx-runtime");
|
|
7891
8137
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
7892
8138
|
function BudgetReallocator({
|
|
7893
8139
|
campus,
|
|
@@ -7902,8 +8148,8 @@ function BudgetReallocator({
|
|
|
7902
8148
|
onCancel,
|
|
7903
8149
|
className = ""
|
|
7904
8150
|
}) {
|
|
7905
|
-
const [draft, setDraft] =
|
|
7906
|
-
|
|
8151
|
+
const [draft, setDraft] = React35.useState(spend);
|
|
8152
|
+
React35.useEffect(() => setDraft(spend), [spend]);
|
|
7907
8153
|
const dirty = draft !== spend;
|
|
7908
8154
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
7909
8155
|
const nextBand = bandFor(nextCrp);
|
|
@@ -7918,24 +8164,24 @@ function BudgetReallocator({
|
|
|
7918
8164
|
setDraft(spend);
|
|
7919
8165
|
if (onCancel) onCancel();
|
|
7920
8166
|
};
|
|
7921
|
-
return /* @__PURE__ */ (0,
|
|
8167
|
+
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
|
|
7922
8168
|
"div",
|
|
7923
8169
|
{
|
|
7924
8170
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
7925
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)" },
|
|
7926
8172
|
children: [
|
|
7927
|
-
/* @__PURE__ */ (0,
|
|
7928
|
-
/* @__PURE__ */ (0,
|
|
7929
|
-
/* @__PURE__ */ (0,
|
|
7930
|
-
dirty ? /* @__PURE__ */ (0,
|
|
7931
|
-
/* @__PURE__ */ (0,
|
|
7932
|
-
/* @__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 })
|
|
7933
8179
|
] }) : null
|
|
7934
8180
|
] }),
|
|
7935
|
-
/* @__PURE__ */ (0,
|
|
7936
|
-
/* @__PURE__ */ (0,
|
|
7937
|
-
dirty ? /* @__PURE__ */ (0,
|
|
7938
|
-
/* @__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)(
|
|
7939
8185
|
"input",
|
|
7940
8186
|
{
|
|
7941
8187
|
type: "range",
|
|
@@ -7951,13 +8197,13 @@ function BudgetReallocator({
|
|
|
7951
8197
|
}
|
|
7952
8198
|
)
|
|
7953
8199
|
] }),
|
|
7954
|
-
/* @__PURE__ */ (0,
|
|
7955
|
-
/* @__PURE__ */ (0,
|
|
7956
|
-
/* @__PURE__ */ (0,
|
|
7957
|
-
/* @__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." })
|
|
7958
8204
|
] }),
|
|
7959
|
-
/* @__PURE__ */ (0,
|
|
7960
|
-
/* @__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)(
|
|
7961
8207
|
"button",
|
|
7962
8208
|
{
|
|
7963
8209
|
type: "button",
|
|
@@ -7976,7 +8222,7 @@ function BudgetReallocator({
|
|
|
7976
8222
|
}
|
|
7977
8223
|
|
|
7978
8224
|
// src/components/planner/SurroundSound.tsx
|
|
7979
|
-
var
|
|
8225
|
+
var import_jsx_runtime68 = require("react/jsx-runtime");
|
|
7980
8226
|
var CATEGORIES = [
|
|
7981
8227
|
{ key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
|
|
7982
8228
|
{ key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
|
|
@@ -7988,26 +8234,26 @@ var CATEGORIES = [
|
|
|
7988
8234
|
function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
|
|
7989
8235
|
const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
|
|
7990
8236
|
const single = present.length <= 2;
|
|
7991
|
-
return /* @__PURE__ */ (0,
|
|
7992
|
-
/* @__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) => {
|
|
7993
8239
|
const on = present.includes(c.key);
|
|
7994
|
-
return /* @__PURE__ */ (0,
|
|
8240
|
+
return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
|
|
7995
8241
|
"span",
|
|
7996
8242
|
{
|
|
7997
8243
|
title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
|
|
7998
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)" },
|
|
7999
8245
|
children: [
|
|
8000
|
-
/* @__PURE__ */ (0,
|
|
8001
|
-
/* @__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 })
|
|
8002
8248
|
]
|
|
8003
8249
|
},
|
|
8004
8250
|
c.key
|
|
8005
8251
|
);
|
|
8006
8252
|
}) }),
|
|
8007
|
-
/* @__PURE__ */ (0,
|
|
8008
|
-
/* @__PURE__ */ (0,
|
|
8009
|
-
/* @__PURE__ */ (0,
|
|
8010
|
-
/* @__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: [
|
|
8011
8257
|
"+",
|
|
8012
8258
|
bonusPct,
|
|
8013
8259
|
"% of +",
|
|
@@ -8015,8 +8261,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
8015
8261
|
"%"
|
|
8016
8262
|
] })
|
|
8017
8263
|
] }),
|
|
8018
|
-
/* @__PURE__ */ (0,
|
|
8019
|
-
/* @__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: [
|
|
8020
8266
|
present.length,
|
|
8021
8267
|
" of 6 channel categories present.",
|
|
8022
8268
|
" ",
|
|
@@ -8028,10 +8274,10 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
8028
8274
|
}
|
|
8029
8275
|
|
|
8030
8276
|
// src/components/chat/AgentChatPanel.tsx
|
|
8031
|
-
var
|
|
8277
|
+
var React41 = __toESM(require("react"), 1);
|
|
8032
8278
|
|
|
8033
8279
|
// src/components/chat/chatEngine.ts
|
|
8034
|
-
var
|
|
8280
|
+
var React36 = __toESM(require("react"), 1);
|
|
8035
8281
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
8036
8282
|
var JOB_PENDING = ["queued", "running"];
|
|
8037
8283
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -8085,22 +8331,22 @@ function useChatEngine(opts) {
|
|
|
8085
8331
|
onClear,
|
|
8086
8332
|
onFeedback
|
|
8087
8333
|
} = opts || {};
|
|
8088
|
-
const [status, setStatus] =
|
|
8089
|
-
const [threadId, setThreadId] =
|
|
8090
|
-
const [messages, setMessages] =
|
|
8091
|
-
const [queue, setQueue] =
|
|
8092
|
-
const [fatal, setFatal] =
|
|
8093
|
-
const [busy, setBusy] =
|
|
8094
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
8095
|
-
const listRef =
|
|
8096
|
-
const queueRef =
|
|
8097
|
-
const busyRef =
|
|
8098
|
-
const stoppedRef =
|
|
8099
|
-
const abortRef =
|
|
8100
|
-
const serverCount =
|
|
8101
|
-
const threadRef =
|
|
8102
|
-
const mounted =
|
|
8103
|
-
|
|
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(() => {
|
|
8104
8350
|
mounted.current = true;
|
|
8105
8351
|
return () => {
|
|
8106
8352
|
mounted.current = false;
|
|
@@ -8122,14 +8368,14 @@ function useChatEngine(opts) {
|
|
|
8122
8368
|
}
|
|
8123
8369
|
return false;
|
|
8124
8370
|
};
|
|
8125
|
-
const loadThread =
|
|
8371
|
+
const loadThread = React36.useCallback(async (id) => {
|
|
8126
8372
|
const data = await apiAdapter.getThread(id);
|
|
8127
8373
|
const list = [...data && data.messages || []];
|
|
8128
8374
|
serverCount.current = list.length;
|
|
8129
8375
|
commit(list);
|
|
8130
8376
|
return list;
|
|
8131
8377
|
}, [apiAdapter]);
|
|
8132
|
-
|
|
8378
|
+
React36.useEffect(() => {
|
|
8133
8379
|
if (!apiAdapter) {
|
|
8134
8380
|
setStatus("idle");
|
|
8135
8381
|
setFatal(null);
|
|
@@ -8342,7 +8588,7 @@ function useChatEngine(opts) {
|
|
|
8342
8588
|
await dispatchTurn(turn);
|
|
8343
8589
|
}
|
|
8344
8590
|
}
|
|
8345
|
-
const send =
|
|
8591
|
+
const send = React36.useCallback((text, attachments) => {
|
|
8346
8592
|
const body = (text || "").trim();
|
|
8347
8593
|
if (!body && !(attachments && attachments.length)) return;
|
|
8348
8594
|
if (status === "disconnected") return;
|
|
@@ -8352,7 +8598,7 @@ function useChatEngine(opts) {
|
|
|
8352
8598
|
stoppedRef.current = false;
|
|
8353
8599
|
drain();
|
|
8354
8600
|
}, [status]);
|
|
8355
|
-
const stop =
|
|
8601
|
+
const stop = React36.useCallback(() => {
|
|
8356
8602
|
stoppedRef.current = true;
|
|
8357
8603
|
const ac = abortRef.current;
|
|
8358
8604
|
if (ac) {
|
|
@@ -8371,11 +8617,11 @@ function useChatEngine(opts) {
|
|
|
8371
8617
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
8372
8618
|
}
|
|
8373
8619
|
}, [apiAdapter]);
|
|
8374
|
-
const removeQueued =
|
|
8620
|
+
const removeQueued = React36.useCallback((id) => {
|
|
8375
8621
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
8376
8622
|
setQueue(queueRef.current.slice());
|
|
8377
8623
|
}, []);
|
|
8378
|
-
const retry =
|
|
8624
|
+
const retry = React36.useCallback(() => {
|
|
8379
8625
|
const list = listRef.current;
|
|
8380
8626
|
let at = -1;
|
|
8381
8627
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -8391,19 +8637,19 @@ function useChatEngine(opts) {
|
|
|
8391
8637
|
setQueue(queueRef.current.slice());
|
|
8392
8638
|
drain();
|
|
8393
8639
|
}, []);
|
|
8394
|
-
const clear =
|
|
8640
|
+
const clear = React36.useCallback(() => {
|
|
8395
8641
|
commit([]);
|
|
8396
8642
|
serverCount.current = 0;
|
|
8397
8643
|
queueRef.current = [];
|
|
8398
8644
|
setQueue([]);
|
|
8399
8645
|
onClear && onClear();
|
|
8400
8646
|
}, [onClear]);
|
|
8401
|
-
const setFeedback =
|
|
8647
|
+
const setFeedback = React36.useCallback((id, value) => {
|
|
8402
8648
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
8403
8649
|
const msg = listRef.current.find((m) => m.id === id);
|
|
8404
8650
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
8405
8651
|
}, [onFeedback]);
|
|
8406
|
-
const reload =
|
|
8652
|
+
const reload = React36.useCallback(async () => {
|
|
8407
8653
|
if (!threadRef.current) return;
|
|
8408
8654
|
setStatus("loading");
|
|
8409
8655
|
try {
|
|
@@ -8441,11 +8687,11 @@ var ChatKit = {
|
|
|
8441
8687
|
};
|
|
8442
8688
|
|
|
8443
8689
|
// src/components/chat/ChatTranscript.tsx
|
|
8444
|
-
var
|
|
8690
|
+
var React38 = __toESM(require("react"), 1);
|
|
8445
8691
|
|
|
8446
8692
|
// src/components/chat/ChatTurn.tsx
|
|
8447
|
-
var
|
|
8448
|
-
var
|
|
8693
|
+
var React37 = __toESM(require("react"), 1);
|
|
8694
|
+
var import_jsx_runtime69 = require("react/jsx-runtime");
|
|
8449
8695
|
function JsonView({ value }) {
|
|
8450
8696
|
let text;
|
|
8451
8697
|
try {
|
|
@@ -8453,67 +8699,67 @@ function JsonView({ value }) {
|
|
|
8453
8699
|
} catch (e) {
|
|
8454
8700
|
text = String(value);
|
|
8455
8701
|
}
|
|
8456
|
-
return /* @__PURE__ */ (0,
|
|
8702
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
|
|
8457
8703
|
}
|
|
8458
8704
|
function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
8459
8705
|
if (!packet) return null;
|
|
8460
8706
|
const s = schema || {};
|
|
8461
8707
|
const invalid = packet.valid === false;
|
|
8462
8708
|
const title = s.heading || packet.type;
|
|
8463
|
-
return /* @__PURE__ */ (0,
|
|
8464
|
-
/* @__PURE__ */ (0,
|
|
8465
|
-
/* @__PURE__ */ (0,
|
|
8466
|
-
/* @__PURE__ */ (0,
|
|
8467
|
-
packet.repaired ? /* @__PURE__ */ (0,
|
|
8468
|
-
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
|
|
8469
8715
|
] }),
|
|
8470
|
-
invalid ? /* @__PURE__ */ (0,
|
|
8471
|
-
/* @__PURE__ */ (0,
|
|
8472
|
-
/* @__PURE__ */ (0,
|
|
8473
|
-
] }) : /* @__PURE__ */ (0,
|
|
8474
|
-
!invalid && onApply ? /* @__PURE__ */ (0,
|
|
8475
|
-
packet.repaired ? /* @__PURE__ */ (0,
|
|
8476
|
-
/* @__PURE__ */ (0,
|
|
8477
|
-
/* @__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" }),
|
|
8478
8724
|
applied ? "Applied" : s.applyLabel || "Apply"
|
|
8479
8725
|
] })
|
|
8480
8726
|
] }) : null
|
|
8481
8727
|
] });
|
|
8482
8728
|
}
|
|
8483
8729
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
8484
|
-
const [open, setOpen] =
|
|
8730
|
+
const [open, setOpen] = React37.useState(defaultOpen);
|
|
8485
8731
|
if (!text) return null;
|
|
8486
|
-
return /* @__PURE__ */ (0,
|
|
8487
|
-
/* @__PURE__ */ (0,
|
|
8488
|
-
/* @__PURE__ */ (0,
|
|
8489
|
-
/* @__PURE__ */ (0,
|
|
8490
|
-
streaming ? /* @__PURE__ */ (0,
|
|
8491
|
-
/* @__PURE__ */ (0,
|
|
8492
|
-
/* @__PURE__ */ (0,
|
|
8493
|
-
/* @__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", {})
|
|
8494
8740
|
] }) : null,
|
|
8495
|
-
/* @__PURE__ */ (0,
|
|
8741
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
|
|
8496
8742
|
] }),
|
|
8497
|
-
open ? /* @__PURE__ */ (0,
|
|
8743
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "fdc-think-body", children: text }) : null
|
|
8498
8744
|
] });
|
|
8499
8745
|
}
|
|
8500
8746
|
function Citations({ items = [], onOpen }) {
|
|
8501
|
-
const [open, setOpen] =
|
|
8747
|
+
const [open, setOpen] = React37.useState(false);
|
|
8502
8748
|
if (!items.length) return null;
|
|
8503
|
-
return /* @__PURE__ */ (0,
|
|
8504
|
-
/* @__PURE__ */ (0,
|
|
8505
|
-
/* @__PURE__ */ (0,
|
|
8506
|
-
/* @__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: [
|
|
8507
8753
|
items.length,
|
|
8508
8754
|
" source",
|
|
8509
8755
|
items.length === 1 ? "" : "s"
|
|
8510
8756
|
] }),
|
|
8511
|
-
/* @__PURE__ */ (0,
|
|
8757
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
|
|
8512
8758
|
] }),
|
|
8513
|
-
open ? /* @__PURE__ */ (0,
|
|
8514
|
-
/* @__PURE__ */ (0,
|
|
8515
|
-
c.url ? /* @__PURE__ */ (0,
|
|
8516
|
-
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
|
|
8517
8763
|
] }, c.id || i)) }) : null
|
|
8518
8764
|
] });
|
|
8519
8765
|
}
|
|
@@ -8524,29 +8770,29 @@ function clampText(text, max) {
|
|
|
8524
8770
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
8525
8771
|
}
|
|
8526
8772
|
function MessageBody({ message: m, ctx }) {
|
|
8527
|
-
const [expanded, setExpanded] =
|
|
8773
|
+
const [expanded, setExpanded] = React37.useState(false);
|
|
8528
8774
|
const isUser = m.role === "user";
|
|
8529
8775
|
const raw = m.text || "";
|
|
8530
8776
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
8531
8777
|
const body = clamped != null ? clamped : raw;
|
|
8532
8778
|
const showMd = ctx.markdown && !isUser;
|
|
8533
|
-
return /* @__PURE__ */ (0,
|
|
8534
|
-
m.thinking && ctx.showThinking ? /* @__PURE__ */ (0,
|
|
8535
|
-
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0,
|
|
8536
|
-
body ? /* @__PURE__ */ (0,
|
|
8537
|
-
showMd ? /* @__PURE__ */ (0,
|
|
8538
|
-
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
|
|
8539
8785
|
] }) : null,
|
|
8540
|
-
clamped != null ? /* @__PURE__ */ (0,
|
|
8541
|
-
/* @__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" }),
|
|
8542
8788
|
"Show more",
|
|
8543
|
-
/* @__PURE__ */ (0,
|
|
8544
|
-
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0,
|
|
8545
|
-
/* @__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" }),
|
|
8546
8792
|
"Show less"
|
|
8547
8793
|
] }) : null,
|
|
8548
|
-
m.attachments && m.attachments.length ? /* @__PURE__ */ (0,
|
|
8549
|
-
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)(
|
|
8550
8796
|
PacketCard,
|
|
8551
8797
|
{
|
|
8552
8798
|
packet: m.packet,
|
|
@@ -8556,44 +8802,44 @@ function MessageBody({ message: m, ctx }) {
|
|
|
8556
8802
|
applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
|
|
8557
8803
|
}
|
|
8558
8804
|
) : null,
|
|
8559
|
-
m.citations && m.citations.length ? /* @__PURE__ */ (0,
|
|
8560
|
-
m.working ? /* @__PURE__ */ (0,
|
|
8561
|
-
/* @__PURE__ */ (0,
|
|
8562
|
-
/* @__PURE__ */ (0,
|
|
8563
|
-
/* @__PURE__ */ (0,
|
|
8564
|
-
/* @__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", {})
|
|
8565
8811
|
] }),
|
|
8566
|
-
/* @__PURE__ */ (0,
|
|
8812
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-working-label", children: [
|
|
8567
8813
|
m.resumed ? "Resuming" : "Working",
|
|
8568
|
-
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: [
|
|
8569
8815
|
" \xB7 ",
|
|
8570
8816
|
m.job.status
|
|
8571
8817
|
] }) : null,
|
|
8572
|
-
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: [
|
|
8573
8819
|
" \xB7 ",
|
|
8574
8820
|
m.job.detail
|
|
8575
8821
|
] }) : null
|
|
8576
8822
|
] }),
|
|
8577
|
-
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
|
|
8578
8824
|
] }) : null,
|
|
8579
|
-
m.stopped ? /* @__PURE__ */ (0,
|
|
8580
|
-
/* @__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" }),
|
|
8581
8827
|
"Stopped"
|
|
8582
8828
|
] }) : null,
|
|
8583
|
-
m.error ? /* @__PURE__ */ (0,
|
|
8584
|
-
/* @__PURE__ */ (0,
|
|
8585
|
-
/* @__PURE__ */ (0,
|
|
8586
|
-
m.retryable && ctx.onRetry ? /* @__PURE__ */ (0,
|
|
8587
|
-
/* @__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" }),
|
|
8588
8834
|
"Retry"
|
|
8589
8835
|
] }) : null
|
|
8590
8836
|
] }) : null
|
|
8591
8837
|
] });
|
|
8592
8838
|
}
|
|
8593
8839
|
function useCopyRun() {
|
|
8594
|
-
const [done, setDone] =
|
|
8595
|
-
const t =
|
|
8596
|
-
|
|
8840
|
+
const [done, setDone] = React37.useState(false);
|
|
8841
|
+
const t = React37.useRef(null);
|
|
8842
|
+
React37.useEffect(() => () => {
|
|
8597
8843
|
if (t.current) clearTimeout(t.current);
|
|
8598
8844
|
}, []);
|
|
8599
8845
|
return [done, (text) => {
|
|
@@ -8613,16 +8859,16 @@ function RunActions({ group, ctx }) {
|
|
|
8613
8859
|
const isAssistant = group.role === "assistant";
|
|
8614
8860
|
const fb = last.feedback;
|
|
8615
8861
|
if (!ctx.messageActions) return null;
|
|
8616
|
-
return /* @__PURE__ */ (0,
|
|
8617
|
-
/* @__PURE__ */ (0,
|
|
8618
|
-
/* @__PURE__ */ (0,
|
|
8619
|
-
/* @__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" })
|
|
8620
8866
|
] }),
|
|
8621
|
-
isAssistant && ctx.onRetry ? /* @__PURE__ */ (0,
|
|
8622
|
-
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0,
|
|
8623
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0,
|
|
8624
|
-
/* @__PURE__ */ (0,
|
|
8625
|
-
/* @__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" }) })
|
|
8626
8872
|
] }) : null,
|
|
8627
8873
|
ctx.extraActions ? ctx.extraActions(group) : null
|
|
8628
8874
|
] });
|
|
@@ -8632,22 +8878,22 @@ function ChatTurn({ group, ctx }) {
|
|
|
8632
8878
|
const name = isUser ? ctx.userName : group.author || ctx.assistantName;
|
|
8633
8879
|
const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
|
|
8634
8880
|
const stamp = group.messages[0].timestamp;
|
|
8635
|
-
return /* @__PURE__ */ (0,
|
|
8636
|
-
/* @__PURE__ */ (0,
|
|
8637
|
-
ctx.showAvatars ? /* @__PURE__ */ (0,
|
|
8638
|
-
/* @__PURE__ */ (0,
|
|
8639
|
-
stamp ? /* @__PURE__ */ (0,
|
|
8640
|
-
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
|
|
8641
8887
|
] }),
|
|
8642
|
-
/* @__PURE__ */ (0,
|
|
8643
|
-
group.messages.map((m) => /* @__PURE__ */ (0,
|
|
8644
|
-
/* @__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 })
|
|
8645
8891
|
] })
|
|
8646
8892
|
] });
|
|
8647
8893
|
}
|
|
8648
8894
|
|
|
8649
8895
|
// src/components/chat/ChatTranscript.tsx
|
|
8650
|
-
var
|
|
8896
|
+
var import_jsx_runtime70 = require("react/jsx-runtime");
|
|
8651
8897
|
var GROUP_WINDOW = 6e4;
|
|
8652
8898
|
var STICK_PX = 100;
|
|
8653
8899
|
function groupMessages(list) {
|
|
@@ -8680,25 +8926,25 @@ function dayLabel(key) {
|
|
|
8680
8926
|
}
|
|
8681
8927
|
function Suggestions({ items = [], onPick }) {
|
|
8682
8928
|
if (!items.length) return null;
|
|
8683
|
-
return /* @__PURE__ */ (0,
|
|
8929
|
+
return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
|
|
8684
8930
|
const it = typeof s === "string" ? { label: s, text: s } : s;
|
|
8685
|
-
return /* @__PURE__ */ (0,
|
|
8686
|
-
it.icon ? /* @__PURE__ */ (0,
|
|
8687
|
-
/* @__PURE__ */ (0,
|
|
8688
|
-
/* @__PURE__ */ (0,
|
|
8689
|
-
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
|
|
8690
8936
|
] }),
|
|
8691
|
-
/* @__PURE__ */ (0,
|
|
8937
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
|
|
8692
8938
|
] }, it.id || i);
|
|
8693
8939
|
}) });
|
|
8694
8940
|
}
|
|
8695
8941
|
function LoadingTurns() {
|
|
8696
|
-
return /* @__PURE__ */ (0,
|
|
8697
|
-
/* @__PURE__ */ (0,
|
|
8698
|
-
/* @__PURE__ */ (0,
|
|
8699
|
-
/* @__PURE__ */ (0,
|
|
8700
|
-
/* @__PURE__ */ (0,
|
|
8701
|
-
/* @__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 } })
|
|
8702
8948
|
] })
|
|
8703
8949
|
] }, i)) });
|
|
8704
8950
|
}
|
|
@@ -8715,10 +8961,10 @@ function ChatTranscript({
|
|
|
8715
8961
|
renderEmpty,
|
|
8716
8962
|
className = ""
|
|
8717
8963
|
}) {
|
|
8718
|
-
const scroller =
|
|
8719
|
-
const stick =
|
|
8720
|
-
const [pill, setPill] =
|
|
8721
|
-
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);
|
|
8722
8968
|
const toBottom = (smooth) => {
|
|
8723
8969
|
const el = scroller.current;
|
|
8724
8970
|
if (!el) return;
|
|
@@ -8737,7 +8983,7 @@ function ChatTranscript({
|
|
|
8737
8983
|
seen.current = messages.length;
|
|
8738
8984
|
}
|
|
8739
8985
|
};
|
|
8740
|
-
|
|
8986
|
+
React38.useLayoutEffect(() => {
|
|
8741
8987
|
const el = scroller.current;
|
|
8742
8988
|
if (!el) return;
|
|
8743
8989
|
if (stick.current) {
|
|
@@ -8745,7 +8991,7 @@ function ChatTranscript({
|
|
|
8745
8991
|
seen.current = messages.length;
|
|
8746
8992
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
8747
8993
|
}, [messages]);
|
|
8748
|
-
|
|
8994
|
+
React38.useEffect(() => {
|
|
8749
8995
|
const el = scroller.current;
|
|
8750
8996
|
const inner = el && el.firstChild;
|
|
8751
8997
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -8755,38 +9001,38 @@ function ChatTranscript({
|
|
|
8755
9001
|
ro.observe(inner);
|
|
8756
9002
|
return () => ro.disconnect();
|
|
8757
9003
|
}, []);
|
|
8758
|
-
const groups =
|
|
9004
|
+
const groups = React38.useMemo(() => groupMessages(messages), [messages]);
|
|
8759
9005
|
const empty = !messages.length && status === "ready";
|
|
8760
|
-
return /* @__PURE__ */ (0,
|
|
8761
|
-
/* @__PURE__ */ (0,
|
|
8762
|
-
status === "loading" || status === "resolving" ? /* @__PURE__ */ (0,
|
|
8763
|
-
status === "disconnected" ? /* @__PURE__ */ (0,
|
|
8764
|
-
/* @__PURE__ */ (0,
|
|
8765
|
-
/* @__PURE__ */ (0,
|
|
8766
|
-
/* @__PURE__ */ (0,
|
|
8767
|
-
ctx.onReconnect ? /* @__PURE__ */ (0,
|
|
8768
|
-
/* @__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" }),
|
|
8769
9015
|
"Try again"
|
|
8770
9016
|
] }) : null
|
|
8771
9017
|
] }) : null,
|
|
8772
|
-
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0,
|
|
8773
|
-
/* @__PURE__ */ (0,
|
|
8774
|
-
/* @__PURE__ */ (0,
|
|
8775
|
-
emptyDescription ? /* @__PURE__ */ (0,
|
|
8776
|
-
/* @__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 })
|
|
8777
9023
|
] }) : null,
|
|
8778
9024
|
groups.map((g, i) => {
|
|
8779
9025
|
const prev = groups[i - 1];
|
|
8780
9026
|
const k = dayKey(g.messages[0].timestamp);
|
|
8781
9027
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
8782
|
-
return /* @__PURE__ */ (0,
|
|
8783
|
-
showDay ? /* @__PURE__ */ (0,
|
|
8784
|
-
/* @__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 })
|
|
8785
9031
|
] }, g.key || i);
|
|
8786
9032
|
})
|
|
8787
9033
|
] }),
|
|
8788
|
-
pill ? /* @__PURE__ */ (0,
|
|
8789
|
-
/* @__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" }),
|
|
8790
9036
|
pill,
|
|
8791
9037
|
" new message",
|
|
8792
9038
|
pill === 1 ? "" : "s"
|
|
@@ -8796,8 +9042,8 @@ function ChatTranscript({
|
|
|
8796
9042
|
var TranscriptKit = { groupMessages };
|
|
8797
9043
|
|
|
8798
9044
|
// src/components/chat/ChatComposer.tsx
|
|
8799
|
-
var
|
|
8800
|
-
var
|
|
9045
|
+
var React39 = __toESM(require("react"), 1);
|
|
9046
|
+
var import_jsx_runtime71 = require("react/jsx-runtime");
|
|
8801
9047
|
function ChatComposer({
|
|
8802
9048
|
onSubmit,
|
|
8803
9049
|
onStop,
|
|
@@ -8824,17 +9070,17 @@ function ChatComposer({
|
|
|
8824
9070
|
onReject,
|
|
8825
9071
|
onOpenAttachment
|
|
8826
9072
|
}) {
|
|
8827
|
-
const [text, setText] =
|
|
8828
|
-
const [trigger, setTrigger] =
|
|
8829
|
-
const [mentionItems, setMentionItems] =
|
|
8830
|
-
const [listening, setListening] =
|
|
8831
|
-
const [notice, setNotice] =
|
|
8832
|
-
const editor =
|
|
8833
|
-
const wrap =
|
|
8834
|
-
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);
|
|
8835
9081
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
8836
9082
|
} });
|
|
8837
|
-
|
|
9083
|
+
React39.useEffect(() => {
|
|
8838
9084
|
if (draft != null && draft !== text) setText(draft);
|
|
8839
9085
|
}, [draft]);
|
|
8840
9086
|
const change = (v) => {
|
|
@@ -8868,7 +9114,7 @@ function ChatComposer({
|
|
|
8868
9114
|
e.preventDefault();
|
|
8869
9115
|
staged.add(found.files);
|
|
8870
9116
|
};
|
|
8871
|
-
|
|
9117
|
+
React39.useEffect(() => {
|
|
8872
9118
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
8873
9119
|
setMentionItems([]);
|
|
8874
9120
|
return;
|
|
@@ -8886,7 +9132,7 @@ function ChatComposer({
|
|
|
8886
9132
|
const q = (trigger.query || "").toLowerCase();
|
|
8887
9133
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
8888
9134
|
}, [trigger, mentionSources]);
|
|
8889
|
-
const slashItems =
|
|
9135
|
+
const slashItems = React39.useMemo(() => {
|
|
8890
9136
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
8891
9137
|
const q = (trigger.query || "").toLowerCase();
|
|
8892
9138
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -8900,7 +9146,7 @@ function ChatComposer({
|
|
|
8900
9146
|
description: it.description,
|
|
8901
9147
|
icon: it.icon,
|
|
8902
9148
|
meta: mention.meta,
|
|
8903
|
-
shortcut: slash.shortcut ? /* @__PURE__ */ (0,
|
|
9149
|
+
shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
|
|
8904
9150
|
onSelect: () => {
|
|
8905
9151
|
const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
|
|
8906
9152
|
editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
|
|
@@ -8963,14 +9209,14 @@ function ChatComposer({
|
|
|
8963
9209
|
stopVoice.current = typeof res === "function" ? res : () => {
|
|
8964
9210
|
};
|
|
8965
9211
|
};
|
|
8966
|
-
return /* @__PURE__ */ (0,
|
|
8967
|
-
queue.length ? /* @__PURE__ */ (0,
|
|
8968
|
-
/* @__PURE__ */ (0,
|
|
8969
|
-
/* @__PURE__ */ (0,
|
|
8970
|
-
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
|
|
8971
9217
|
] }, q.id)) }) : null,
|
|
8972
9218
|
sessionBar,
|
|
8973
|
-
/* @__PURE__ */ (0,
|
|
9219
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
|
|
8974
9220
|
Dropzone,
|
|
8975
9221
|
{
|
|
8976
9222
|
className: "fdc-field",
|
|
@@ -8984,9 +9230,9 @@ function ChatComposer({
|
|
|
8984
9230
|
disabled: !fileUploadHandler || disabled,
|
|
8985
9231
|
label: "Drop to attach",
|
|
8986
9232
|
hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
|
|
8987
|
-
children: /* @__PURE__ */ (0,
|
|
8988
|
-
staged.items.length ? /* @__PURE__ */ (0,
|
|
8989
|
-
/* @__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)(
|
|
8990
9236
|
MarkdownEditor,
|
|
8991
9237
|
{
|
|
8992
9238
|
ref: editor,
|
|
@@ -9005,33 +9251,33 @@ function ChatComposer({
|
|
|
9005
9251
|
ariaLabel: "Message"
|
|
9006
9252
|
}
|
|
9007
9253
|
),
|
|
9008
|
-
/* @__PURE__ */ (0,
|
|
9009
|
-
fileUploadHandler ? /* @__PURE__ */ (0,
|
|
9010
|
-
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,
|
|
9011
9257
|
toolbarExtras,
|
|
9012
|
-
/* @__PURE__ */ (0,
|
|
9013
|
-
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: [
|
|
9014
9260
|
text.length,
|
|
9015
9261
|
"/",
|
|
9016
9262
|
maxLength
|
|
9017
9263
|
] }) : null,
|
|
9018
|
-
busy ? /* @__PURE__ */ (0,
|
|
9019
|
-
/* @__PURE__ */ (0,
|
|
9020
|
-
/* @__PURE__ */ (0,
|
|
9021
|
-
] }) : /* @__PURE__ */ (0,
|
|
9022
|
-
/* @__PURE__ */ (0,
|
|
9023
|
-
/* @__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" })
|
|
9024
9270
|
] })
|
|
9025
9271
|
] })
|
|
9026
9272
|
] })
|
|
9027
9273
|
}
|
|
9028
9274
|
),
|
|
9029
|
-
notice ? /* @__PURE__ */ (0,
|
|
9030
|
-
/* @__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" }),
|
|
9031
9277
|
notice
|
|
9032
9278
|
] }) : null,
|
|
9033
|
-
hint && !notice ? /* @__PURE__ */ (0,
|
|
9034
|
-
/* @__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)(
|
|
9035
9281
|
Popover,
|
|
9036
9282
|
{
|
|
9037
9283
|
open: menuOpen,
|
|
@@ -9045,12 +9291,12 @@ function ChatComposer({
|
|
|
9045
9291
|
returnFocus: false,
|
|
9046
9292
|
closeOnOutside: true,
|
|
9047
9293
|
label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
|
|
9048
|
-
children: /* @__PURE__ */ (0,
|
|
9294
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
|
|
9049
9295
|
Menu,
|
|
9050
9296
|
{
|
|
9051
9297
|
items: menuItems,
|
|
9052
9298
|
autoFocus: false,
|
|
9053
|
-
header: /* @__PURE__ */ (0,
|
|
9299
|
+
header: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
|
|
9054
9300
|
onClose: () => setTrigger(null)
|
|
9055
9301
|
}
|
|
9056
9302
|
)
|
|
@@ -9060,12 +9306,12 @@ function ChatComposer({
|
|
|
9060
9306
|
}
|
|
9061
9307
|
|
|
9062
9308
|
// src/components/chat/ChatSessionBar.tsx
|
|
9063
|
-
var
|
|
9064
|
-
var
|
|
9309
|
+
var React40 = __toESM(require("react"), 1);
|
|
9310
|
+
var import_jsx_runtime72 = require("react/jsx-runtime");
|
|
9065
9311
|
var compact2 = meterFormats.compact;
|
|
9066
9312
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
9067
|
-
const [open, setOpen] =
|
|
9068
|
-
const anchor =
|
|
9313
|
+
const [open, setOpen] = React40.useState(false);
|
|
9314
|
+
const anchor = React40.useRef(null);
|
|
9069
9315
|
const stats = sessionStats || null;
|
|
9070
9316
|
const cu = contextUsage || null;
|
|
9071
9317
|
const limits = usageLimits || null;
|
|
@@ -9080,9 +9326,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9080
9326
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
9081
9327
|
if (cu) bits.push(pct + "% context");
|
|
9082
9328
|
const expandable = !!(cu || limits);
|
|
9083
|
-
return /* @__PURE__ */ (0,
|
|
9084
|
-
/* @__PURE__ */ (0,
|
|
9085
|
-
/* @__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)(
|
|
9086
9332
|
"button",
|
|
9087
9333
|
{
|
|
9088
9334
|
type: "button",
|
|
@@ -9093,16 +9339,16 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9093
9339
|
"aria-expanded": expandable ? open : void 0,
|
|
9094
9340
|
"aria-label": expandable ? "Usage details" : void 0,
|
|
9095
9341
|
children: [
|
|
9096
|
-
cu ? /* @__PURE__ */ (0,
|
|
9097
|
-
/* @__PURE__ */ (0,
|
|
9098
|
-
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
|
|
9099
9345
|
]
|
|
9100
9346
|
}
|
|
9101
9347
|
),
|
|
9102
9348
|
extras
|
|
9103
9349
|
] }),
|
|
9104
|
-
/* @__PURE__ */ (0,
|
|
9105
|
-
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)(
|
|
9106
9352
|
SegmentedMeter,
|
|
9107
9353
|
{
|
|
9108
9354
|
total,
|
|
@@ -9114,9 +9360,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9114
9360
|
remainderLabel: "Free"
|
|
9115
9361
|
}
|
|
9116
9362
|
) }) : null,
|
|
9117
|
-
limits && limits.length ? /* @__PURE__ */ (0,
|
|
9118
|
-
/* @__PURE__ */ (0,
|
|
9119
|
-
/* @__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)(
|
|
9120
9366
|
QuotaRow,
|
|
9121
9367
|
{
|
|
9122
9368
|
label: l.label,
|
|
@@ -9126,32 +9372,32 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9126
9372
|
l.id
|
|
9127
9373
|
)) })
|
|
9128
9374
|
] }) : null,
|
|
9129
|
-
stats ? /* @__PURE__ */ (0,
|
|
9130
|
-
stats.elapsedMs ? /* @__PURE__ */ (0,
|
|
9131
|
-
/* @__PURE__ */ (0,
|
|
9132
|
-
/* @__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) })
|
|
9133
9379
|
] }) : null,
|
|
9134
|
-
stats.tokens ? /* @__PURE__ */ (0,
|
|
9135
|
-
/* @__PURE__ */ (0,
|
|
9136
|
-
/* @__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() })
|
|
9137
9383
|
] }) : null,
|
|
9138
|
-
stats.costUsd != null ? /* @__PURE__ */ (0,
|
|
9139
|
-
/* @__PURE__ */ (0,
|
|
9140
|
-
/* @__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: [
|
|
9141
9387
|
"$",
|
|
9142
9388
|
Number(stats.costUsd).toFixed(3)
|
|
9143
9389
|
] })
|
|
9144
9390
|
] }) : null,
|
|
9145
|
-
stats.turns ? /* @__PURE__ */ (0,
|
|
9146
|
-
/* @__PURE__ */ (0,
|
|
9147
|
-
/* @__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 })
|
|
9148
9394
|
] }) : null
|
|
9149
9395
|
] }) : null,
|
|
9150
|
-
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: () => {
|
|
9151
9397
|
setOpen(false);
|
|
9152
9398
|
onClear();
|
|
9153
9399
|
}, children: [
|
|
9154
|
-
/* @__PURE__ */ (0,
|
|
9400
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
|
|
9155
9401
|
"Clear conversation"
|
|
9156
9402
|
] }) }) : null
|
|
9157
9403
|
] }) })
|
|
@@ -9188,7 +9434,7 @@ function ModelControls({
|
|
|
9188
9434
|
disabled: m.disabled,
|
|
9189
9435
|
checked: m.id === (current2 && current2.id),
|
|
9190
9436
|
meta: m.meta,
|
|
9191
|
-
shortcut: m.shortcut ? /* @__PURE__ */ (0,
|
|
9437
|
+
shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
|
|
9192
9438
|
onSelect: () => onModelChange && onModelChange(m.id)
|
|
9193
9439
|
});
|
|
9194
9440
|
const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
|
|
@@ -9201,15 +9447,15 @@ function ModelControls({
|
|
|
9201
9447
|
items.push({ kind: "section", label: "Fast mode" });
|
|
9202
9448
|
items.push({
|
|
9203
9449
|
kind: "custom",
|
|
9204
|
-
render: () => /* @__PURE__ */ (0,
|
|
9205
|
-
/* @__PURE__ */ (0,
|
|
9206
|
-
/* @__PURE__ */ (0,
|
|
9207
|
-
/* @__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" }) })
|
|
9208
9454
|
] })
|
|
9209
9455
|
});
|
|
9210
9456
|
}
|
|
9211
|
-
return /* @__PURE__ */ (0,
|
|
9212
|
-
/* @__PURE__ */ (0,
|
|
9457
|
+
return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(React40.Fragment, { children: [
|
|
9458
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
|
|
9213
9459
|
MenuButton,
|
|
9214
9460
|
{
|
|
9215
9461
|
items,
|
|
@@ -9220,7 +9466,7 @@ function ModelControls({
|
|
|
9220
9466
|
title: "Choose a model"
|
|
9221
9467
|
}
|
|
9222
9468
|
),
|
|
9223
|
-
effortLevels && effortLevels.length ? /* @__PURE__ */ (0,
|
|
9469
|
+
effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
|
|
9224
9470
|
MenuButton,
|
|
9225
9471
|
{
|
|
9226
9472
|
placement: "top-end",
|
|
@@ -9241,7 +9487,7 @@ function ModelControls({
|
|
|
9241
9487
|
}
|
|
9242
9488
|
|
|
9243
9489
|
// src/components/chat/AgentChatPanel.tsx
|
|
9244
|
-
var
|
|
9490
|
+
var import_jsx_runtime73 = require("react/jsx-runtime");
|
|
9245
9491
|
var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
|
|
9246
9492
|
function AgentChatPanel({
|
|
9247
9493
|
/* required */
|
|
@@ -9325,11 +9571,11 @@ function AgentChatPanel({
|
|
|
9325
9571
|
onFeedback,
|
|
9326
9572
|
onEditMessage
|
|
9327
9573
|
}) {
|
|
9328
|
-
const [panelWidth, setPanelWidth] =
|
|
9329
|
-
const [applied, setApplied] =
|
|
9330
|
-
const [draft, setDraft] =
|
|
9331
|
-
const dragging =
|
|
9332
|
-
|
|
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]);
|
|
9333
9579
|
const engine = useChatEngine({
|
|
9334
9580
|
contextType,
|
|
9335
9581
|
contextId,
|
|
@@ -9395,7 +9641,7 @@ function AgentChatPanel({
|
|
|
9395
9641
|
onReconnect: engine.reload,
|
|
9396
9642
|
deadTitle: "The assistant isn\u2019t reachable"
|
|
9397
9643
|
};
|
|
9398
|
-
const sessionBar = /* @__PURE__ */ (0,
|
|
9644
|
+
const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9399
9645
|
ChatSessionBar,
|
|
9400
9646
|
{
|
|
9401
9647
|
sessionStats,
|
|
@@ -9404,7 +9650,7 @@ function AgentChatPanel({
|
|
|
9404
9650
|
onClear: engine.visible.length ? engine.clear : void 0
|
|
9405
9651
|
}
|
|
9406
9652
|
);
|
|
9407
|
-
const modelControls = /* @__PURE__ */ (0,
|
|
9653
|
+
const modelControls = /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9408
9654
|
ModelControls,
|
|
9409
9655
|
{
|
|
9410
9656
|
models,
|
|
@@ -9419,7 +9665,7 @@ function AgentChatPanel({
|
|
|
9419
9665
|
narrow
|
|
9420
9666
|
}
|
|
9421
9667
|
);
|
|
9422
|
-
const threadMenu = threads && threads.length ? /* @__PURE__ */ (0,
|
|
9668
|
+
const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9423
9669
|
MenuButton,
|
|
9424
9670
|
{
|
|
9425
9671
|
variant: "ghost",
|
|
@@ -9446,7 +9692,7 @@ function AgentChatPanel({
|
|
|
9446
9692
|
})))
|
|
9447
9693
|
}
|
|
9448
9694
|
) : null;
|
|
9449
|
-
return /* @__PURE__ */ (0,
|
|
9695
|
+
return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
|
|
9450
9696
|
"aside",
|
|
9451
9697
|
{
|
|
9452
9698
|
className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
|
|
@@ -9457,7 +9703,7 @@ function AgentChatPanel({
|
|
|
9457
9703
|
},
|
|
9458
9704
|
"aria-label": title,
|
|
9459
9705
|
children: [
|
|
9460
|
-
surface === "sidebar" && resizable ? /* @__PURE__ */ (0,
|
|
9706
|
+
surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9461
9707
|
"div",
|
|
9462
9708
|
{
|
|
9463
9709
|
className: "fdc-grip",
|
|
@@ -9472,20 +9718,20 @@ function AgentChatPanel({
|
|
|
9472
9718
|
}
|
|
9473
9719
|
}
|
|
9474
9720
|
) : null,
|
|
9475
|
-
showHeader ? /* @__PURE__ */ (0,
|
|
9476
|
-
/* @__PURE__ */ (0,
|
|
9477
|
-
/* @__PURE__ */ (0,
|
|
9478
|
-
/* @__PURE__ */ (0,
|
|
9479
|
-
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
|
|
9480
9726
|
] }),
|
|
9481
|
-
/* @__PURE__ */ (0,
|
|
9727
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fdc-head-acts", children: [
|
|
9482
9728
|
headerActions,
|
|
9483
9729
|
threadMenu,
|
|
9484
|
-
onNewThread ? /* @__PURE__ */ (0,
|
|
9485
|
-
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
|
|
9486
9732
|
] })
|
|
9487
9733
|
] }) : null,
|
|
9488
|
-
/* @__PURE__ */ (0,
|
|
9734
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9489
9735
|
ChatTranscript,
|
|
9490
9736
|
{
|
|
9491
9737
|
messages: engine.visible,
|
|
@@ -9500,7 +9746,7 @@ function AgentChatPanel({
|
|
|
9500
9746
|
renderEmpty
|
|
9501
9747
|
}
|
|
9502
9748
|
),
|
|
9503
|
-
/* @__PURE__ */ (0,
|
|
9749
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9504
9750
|
ChatComposer,
|
|
9505
9751
|
{
|
|
9506
9752
|
onSubmit: (text, atts) => engine.send(text, atts),
|
|
@@ -9533,7 +9779,7 @@ function AgentChatPanel({
|
|
|
9533
9779
|
}
|
|
9534
9780
|
|
|
9535
9781
|
// src/kits/query.ts
|
|
9536
|
-
var
|
|
9782
|
+
var React42 = __toESM(require("react"), 1);
|
|
9537
9783
|
function eqFilter(get2) {
|
|
9538
9784
|
return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
|
|
9539
9785
|
}
|
|
@@ -9565,22 +9811,22 @@ function compare(a, b, dir) {
|
|
|
9565
9811
|
var API = null;
|
|
9566
9812
|
var PREFS = null;
|
|
9567
9813
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
9568
|
-
const [query, setQuery] =
|
|
9814
|
+
const [query, setQuery] = React42.useState(() => {
|
|
9569
9815
|
const store = PREFS || window.PlannerPrefs;
|
|
9570
9816
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
9571
9817
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
9572
9818
|
});
|
|
9573
|
-
const savePref =
|
|
9819
|
+
const savePref = React42.useCallback((patch2) => {
|
|
9574
9820
|
const store = PREFS || window.PlannerPrefs;
|
|
9575
9821
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
9576
9822
|
}, [prefsKey]);
|
|
9577
|
-
const [res, setRes] =
|
|
9578
|
-
const [loading, setLoading] =
|
|
9579
|
-
const seq2 =
|
|
9823
|
+
const [res, setRes] = React42.useState(null);
|
|
9824
|
+
const [loading, setLoading] = React42.useState(true);
|
|
9825
|
+
const seq2 = React42.useRef(0);
|
|
9580
9826
|
const depKey = (deps || []).join("|");
|
|
9581
9827
|
const paramKey = JSON.stringify(params || {});
|
|
9582
9828
|
const queryKey = JSON.stringify(query);
|
|
9583
|
-
|
|
9829
|
+
React42.useEffect(() => {
|
|
9584
9830
|
const id = ++seq2.current;
|
|
9585
9831
|
setLoading(true);
|
|
9586
9832
|
const t = setTimeout(() => {
|
|
@@ -9919,6 +10165,7 @@ function createVersionStore(initialState, options) {
|
|
|
9919
10165
|
Dropzone,
|
|
9920
10166
|
DropzoneKit,
|
|
9921
10167
|
EmptyState,
|
|
10168
|
+
EntityRow,
|
|
9922
10169
|
FeatureGate,
|
|
9923
10170
|
FileChip,
|
|
9924
10171
|
FileGrid,
|
|
@@ -9991,11 +10238,16 @@ function createVersionStore(initialState, options) {
|
|
|
9991
10238
|
Tooltip,
|
|
9992
10239
|
Topbar,
|
|
9993
10240
|
TranscriptKit,
|
|
10241
|
+
TransferList,
|
|
9994
10242
|
UseFeatureStatus,
|
|
9995
10243
|
UseRuntimeMode,
|
|
10244
|
+
VIRTUAL_LIST_BUFFER_ROWS,
|
|
10245
|
+
VirtualList,
|
|
9996
10246
|
acceptMatches,
|
|
9997
10247
|
anyOfFilter,
|
|
9998
10248
|
channelWeightOf,
|
|
10249
|
+
computeNeedMore,
|
|
10250
|
+
computeVirtualWindow,
|
|
9999
10251
|
createVersionStore,
|
|
10000
10252
|
eqFilter,
|
|
10001
10253
|
extensionOf,
|