@flytedan/flytebot-design-system 0.6.1 → 0.7.1
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 +1290 -1035
- 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 +1284 -1035
- 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,
|
|
@@ -1254,6 +1260,9 @@ var BANDS = {
|
|
|
1254
1260
|
strong: { n: 3, label: "Strong" },
|
|
1255
1261
|
dominant: { n: 4, label: "Dominant" }
|
|
1256
1262
|
};
|
|
1263
|
+
function formatCrp(crp) {
|
|
1264
|
+
return crp.toFixed(1);
|
|
1265
|
+
}
|
|
1257
1266
|
function CsiMeter({ band = "weak", size = 4, width = 5, gap = 2 }) {
|
|
1258
1267
|
const n = (BANDS[band] || BANDS.weak).n;
|
|
1259
1268
|
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-meter", style: { gap: gap + "px" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
@@ -1276,7 +1285,7 @@ function CsiBadge({ band = "weak", crp, size = "compact", preview = false, alert
|
|
|
1276
1285
|
alert ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-badge-dot", style: { background: "var(--csi-alert)" }, "aria-label": "Fixable" }) : null,
|
|
1277
1286
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CsiMeter, { band, size: size === "medium" ? 11 : 9, width: size === "medium" ? 4 : 3 }),
|
|
1278
1287
|
b.label,
|
|
1279
|
-
crp !== void 0 && crp !== null ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-csi-crp", children: crp }) : null
|
|
1288
|
+
crp !== void 0 && crp !== null ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-csi-crp", children: formatCrp(crp) }) : null
|
|
1280
1289
|
]
|
|
1281
1290
|
}
|
|
1282
1291
|
);
|
|
@@ -1285,7 +1294,7 @@ function CsiHero({ band = "weak", crp, label, className = "" }) {
|
|
|
1285
1294
|
const b = BANDS[band] || BANDS.weak;
|
|
1286
1295
|
const mark = "var(--csi-" + b.n + "-mark)";
|
|
1287
1296
|
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 10 }, children: [
|
|
1288
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-csi-hero-num", style: { color: mark }, children: crp }),
|
|
1297
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-csi-hero-num", style: { color: mark }, children: crp !== void 0 && crp !== null ? formatCrp(crp) : "" }),
|
|
1289
1298
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-label-lg", style: { color: "var(--text-2)" }, children: label || b.label }),
|
|
1290
1299
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-meter", style: { gap: 3, color: mark, width: 120 }, children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-meter-seg" + (i <= b.n ? " is-on" : ""), style: { height: 6, flex: 1 } }, i)) })
|
|
1291
1300
|
] });
|
|
@@ -2613,56 +2622,140 @@ function StepList({
|
|
|
2613
2622
|
] });
|
|
2614
2623
|
}
|
|
2615
2624
|
|
|
2616
|
-
// src/components/
|
|
2625
|
+
// src/components/data/VirtualList.tsx
|
|
2617
2626
|
var React15 = __toESM(require("react"), 1);
|
|
2618
2627
|
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
2619
|
-
|
|
2620
|
-
|
|
2628
|
+
var VIRTUAL_LIST_BUFFER_ROWS = 20;
|
|
2629
|
+
function computeVirtualWindow(opts) {
|
|
2630
|
+
const { scrollTop, viewportHeight, itemHeight, itemCount, bufferRows = VIRTUAL_LIST_BUFFER_ROWS } = opts;
|
|
2631
|
+
if (itemCount <= 0 || itemHeight <= 0) {
|
|
2632
|
+
return { visibleStart: 0, visibleEnd: -1, startIndex: 0, endIndex: -1, totalHeight: 0, offsetY: 0 };
|
|
2633
|
+
}
|
|
2634
|
+
const lastPossible = itemCount - 1;
|
|
2635
|
+
const visibleStart = Math.min(lastPossible, Math.max(0, Math.floor(scrollTop / itemHeight)));
|
|
2636
|
+
const visibleRows = Math.max(1, Math.ceil(viewportHeight / itemHeight));
|
|
2637
|
+
const visibleEnd = Math.min(lastPossible, visibleStart + visibleRows - 1);
|
|
2638
|
+
const startIndex = Math.max(0, visibleStart - bufferRows);
|
|
2639
|
+
const endIndex = Math.min(lastPossible, visibleEnd + bufferRows);
|
|
2640
|
+
return {
|
|
2641
|
+
visibleStart,
|
|
2642
|
+
visibleEnd,
|
|
2643
|
+
startIndex,
|
|
2644
|
+
endIndex,
|
|
2645
|
+
totalHeight: itemCount * itemHeight,
|
|
2646
|
+
offsetY: startIndex * itemHeight
|
|
2647
|
+
};
|
|
2648
|
+
}
|
|
2649
|
+
function computeNeedMore(win, itemCount, bufferRows = VIRTUAL_LIST_BUFFER_ROWS) {
|
|
2650
|
+
if (itemCount <= 0) return { start: true, end: true };
|
|
2651
|
+
return {
|
|
2652
|
+
start: win.visibleStart <= bufferRows,
|
|
2653
|
+
end: itemCount - 1 - win.visibleEnd <= bufferRows
|
|
2654
|
+
};
|
|
2655
|
+
}
|
|
2656
|
+
function VirtualList({
|
|
2657
|
+
items,
|
|
2658
|
+
itemHeight,
|
|
2659
|
+
renderItem,
|
|
2660
|
+
onNeedMore,
|
|
2661
|
+
hasMore,
|
|
2662
|
+
loading = false,
|
|
2663
|
+
keyOf,
|
|
2664
|
+
height = 400,
|
|
2665
|
+
emptyState,
|
|
2666
|
+
className = "",
|
|
2667
|
+
style
|
|
2668
|
+
}) {
|
|
2669
|
+
const [scrollTop, setScrollTop] = React15.useState(0);
|
|
2670
|
+
const requested = React15.useRef({ start: null, end: null });
|
|
2671
|
+
const win = React15.useMemo(
|
|
2672
|
+
() => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: items.length }),
|
|
2673
|
+
[scrollTop, height, itemHeight, items.length]
|
|
2674
|
+
);
|
|
2675
|
+
const need = React15.useMemo(() => computeNeedMore(win, items.length), [win, items.length]);
|
|
2676
|
+
const wantStart = need.start && hasMore?.start !== false;
|
|
2677
|
+
const wantEnd = need.end && hasMore?.end !== false;
|
|
2621
2678
|
React15.useEffect(() => {
|
|
2622
|
-
if (
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
] })
|
|
2633
|
-
|
|
2679
|
+
if (loading || !wantStart || requested.current.start === items.length) return;
|
|
2680
|
+
requested.current.start = items.length;
|
|
2681
|
+
onNeedMore("start");
|
|
2682
|
+
}, [wantStart, loading, items.length, onNeedMore]);
|
|
2683
|
+
React15.useEffect(() => {
|
|
2684
|
+
if (loading || !wantEnd || requested.current.end === items.length) return;
|
|
2685
|
+
requested.current.end = items.length;
|
|
2686
|
+
onNeedMore("end");
|
|
2687
|
+
}, [wantEnd, loading, items.length, onNeedMore]);
|
|
2688
|
+
if (!items.length && !loading && emptyState) {
|
|
2689
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: ["fd-vlist", className].filter(Boolean).join(" "), style: { height, overflow: "auto", ...style }, children: emptyState });
|
|
2690
|
+
}
|
|
2691
|
+
const rows = [];
|
|
2692
|
+
for (let i = win.startIndex; i <= win.endIndex; i++) {
|
|
2693
|
+
const item = items[i];
|
|
2694
|
+
if (item === void 0) continue;
|
|
2695
|
+
rows.push(
|
|
2696
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { style: { height: itemHeight, boxSizing: "border-box" }, children: renderItem(item, i) }, keyOf(item))
|
|
2697
|
+
);
|
|
2698
|
+
}
|
|
2699
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
2700
|
+
"div",
|
|
2701
|
+
{
|
|
2702
|
+
className: ["fd-vlist", className].filter(Boolean).join(" "),
|
|
2703
|
+
style: { height, overflowY: "auto", overflowX: "hidden", position: "relative", ...style },
|
|
2704
|
+
onScroll: (e) => setScrollTop(e.currentTarget.scrollTop),
|
|
2705
|
+
children: [
|
|
2706
|
+
/* @__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 }) }),
|
|
2707
|
+
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
|
|
2708
|
+
]
|
|
2709
|
+
}
|
|
2710
|
+
);
|
|
2634
2711
|
}
|
|
2635
2712
|
|
|
2636
|
-
// src/components/
|
|
2713
|
+
// src/components/data/EntityRow.tsx
|
|
2637
2714
|
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
|
-
|
|
2715
|
+
function EntityRow({ title, meta, action, draggable = false, onDragStart, onDragEnd, style, className = "" }) {
|
|
2716
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
|
|
2717
|
+
"div",
|
|
2718
|
+
{
|
|
2719
|
+
draggable,
|
|
2720
|
+
onDragStart,
|
|
2721
|
+
onDragEnd,
|
|
2722
|
+
className: ["fd-erow", className].filter(Boolean).join(" "),
|
|
2723
|
+
style: {
|
|
2724
|
+
display: "flex",
|
|
2725
|
+
alignItems: "center",
|
|
2726
|
+
gap: 8,
|
|
2727
|
+
height: "100%",
|
|
2728
|
+
padding: "0 8px",
|
|
2729
|
+
borderRadius: 6,
|
|
2730
|
+
cursor: draggable ? "grab" : void 0,
|
|
2731
|
+
...style
|
|
2732
|
+
},
|
|
2733
|
+
children: [
|
|
2734
|
+
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,
|
|
2735
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: 1 }, children: [
|
|
2736
|
+
/* @__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 }),
|
|
2737
|
+
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
|
|
2738
|
+
] }),
|
|
2739
|
+
action ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
2740
|
+
IconButton,
|
|
2741
|
+
{
|
|
2742
|
+
icon: action.icon,
|
|
2743
|
+
label: action.label,
|
|
2744
|
+
size: "sm",
|
|
2745
|
+
onClick: action.onClick,
|
|
2746
|
+
style: { color: action.tone === "add" ? "var(--ok-text)" : action.tone === "remove" ? "var(--danger-text)" : void 0 }
|
|
2747
|
+
}
|
|
2748
|
+
) : null
|
|
2749
|
+
]
|
|
2750
|
+
}
|
|
2751
|
+
);
|
|
2649
2752
|
}
|
|
2650
2753
|
|
|
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
|
-
}
|
|
2754
|
+
// src/components/data/TransferList.tsx
|
|
2755
|
+
var React16 = __toESM(require("react"), 1);
|
|
2663
2756
|
|
|
2664
2757
|
// src/components/forms/Input.tsx
|
|
2665
|
-
var
|
|
2758
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
2666
2759
|
function Input({
|
|
2667
2760
|
label,
|
|
2668
2761
|
help,
|
|
@@ -2690,27 +2783,27 @@ function Input({
|
|
|
2690
2783
|
size === "lg" ? "fd-input-lg" : "",
|
|
2691
2784
|
className
|
|
2692
2785
|
].filter(Boolean).join(" ");
|
|
2693
|
-
return /* @__PURE__ */ (0,
|
|
2694
|
-
label ? /* @__PURE__ */ (0,
|
|
2786
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "fd-field", style, children: [
|
|
2787
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("label", { className: "fd-field-label", htmlFor: fieldId, children: [
|
|
2695
2788
|
label,
|
|
2696
|
-
required ? /* @__PURE__ */ (0,
|
|
2789
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-field-req", "aria-hidden": "true", children: "*" }) : null
|
|
2697
2790
|
] }) : null,
|
|
2698
|
-
/* @__PURE__ */ (0,
|
|
2699
|
-
icon ? /* @__PURE__ */ (0,
|
|
2700
|
-
prefix ? /* @__PURE__ */ (0,
|
|
2701
|
-
/* @__PURE__ */ (0,
|
|
2702
|
-
loading ? /* @__PURE__ */ (0,
|
|
2703
|
-
suffix && !loading ? /* @__PURE__ */ (0,
|
|
2791
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: box, children: [
|
|
2792
|
+
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,
|
|
2793
|
+
prefix ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
|
|
2794
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("input", { id: fieldId, disabled, style: inputStyle, "aria-invalid": error ? "true" : void 0, ...rest }),
|
|
2795
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading" }) : null,
|
|
2796
|
+
suffix && !loading ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-input-affix", children: suffix }) : null
|
|
2704
2797
|
] }),
|
|
2705
|
-
error ? /* @__PURE__ */ (0,
|
|
2706
|
-
/* @__PURE__ */ (0,
|
|
2798
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "fd-field-error", children: [
|
|
2799
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
2707
2800
|
error
|
|
2708
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
2801
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
2709
2802
|
] });
|
|
2710
2803
|
}
|
|
2711
2804
|
|
|
2712
2805
|
// src/components/forms/SearchField.tsx
|
|
2713
|
-
var
|
|
2806
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
2714
2807
|
function SearchField({
|
|
2715
2808
|
value,
|
|
2716
2809
|
onChange,
|
|
@@ -2725,7 +2818,7 @@ function SearchField({
|
|
|
2725
2818
|
...rest
|
|
2726
2819
|
}) {
|
|
2727
2820
|
const clear = onClear || (() => onChange(""));
|
|
2728
|
-
return /* @__PURE__ */ (0,
|
|
2821
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2729
2822
|
Input,
|
|
2730
2823
|
{
|
|
2731
2824
|
id,
|
|
@@ -2738,14 +2831,14 @@ function SearchField({
|
|
|
2738
2831
|
style,
|
|
2739
2832
|
className,
|
|
2740
2833
|
onChange: (e) => onChange(e.target.value),
|
|
2741
|
-
suffix: value ? /* @__PURE__ */ (0,
|
|
2834
|
+
suffix: value ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2742
2835
|
"button",
|
|
2743
2836
|
{
|
|
2744
2837
|
type: "button",
|
|
2745
2838
|
"aria-label": "Clear search",
|
|
2746
2839
|
onClick: clear,
|
|
2747
2840
|
style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
|
|
2748
|
-
children: /* @__PURE__ */ (0,
|
|
2841
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 }, "aria-hidden": "true" })
|
|
2749
2842
|
}
|
|
2750
2843
|
) : void 0,
|
|
2751
2844
|
...rest
|
|
@@ -2753,27 +2846,183 @@ function SearchField({
|
|
|
2753
2846
|
);
|
|
2754
2847
|
}
|
|
2755
2848
|
|
|
2756
|
-
// src/components/
|
|
2849
|
+
// src/components/data/TransferList.tsx
|
|
2850
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
2851
|
+
var emptyHasMore = {};
|
|
2852
|
+
function TransferList({
|
|
2853
|
+
left,
|
|
2854
|
+
right,
|
|
2855
|
+
keyOf,
|
|
2856
|
+
renderLabel,
|
|
2857
|
+
renderMeta,
|
|
2858
|
+
onMove,
|
|
2859
|
+
itemHeight = 44,
|
|
2860
|
+
listHeight = 440,
|
|
2861
|
+
className = ""
|
|
2862
|
+
}) {
|
|
2863
|
+
const [dragging, setDragging] = React16.useState(null);
|
|
2864
|
+
const [dragOverSide, setDragOverSide] = React16.useState(null);
|
|
2865
|
+
const startDrag = (e, item, from) => {
|
|
2866
|
+
const key = keyOf(item);
|
|
2867
|
+
setDragging({ key, from });
|
|
2868
|
+
e.dataTransfer.effectAllowed = "move";
|
|
2869
|
+
e.dataTransfer.setData("text/plain", String(key));
|
|
2870
|
+
};
|
|
2871
|
+
const endDrag = () => {
|
|
2872
|
+
setDragging(null);
|
|
2873
|
+
setDragOverSide(null);
|
|
2874
|
+
};
|
|
2875
|
+
const findItem = (side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key);
|
|
2876
|
+
const dropOnSide = (e, side) => {
|
|
2877
|
+
e.preventDefault();
|
|
2878
|
+
setDragOverSide(null);
|
|
2879
|
+
if (!dragging || dragging.from === side) return;
|
|
2880
|
+
const item = findItem(dragging.from, dragging.key);
|
|
2881
|
+
if (item !== void 0) onMove(item, dragging.from, side);
|
|
2882
|
+
setDragging(null);
|
|
2883
|
+
};
|
|
2884
|
+
const renderSide = (side, cfg, opposite) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
2885
|
+
"div",
|
|
2886
|
+
{
|
|
2887
|
+
style: {
|
|
2888
|
+
flex: 1,
|
|
2889
|
+
minWidth: 0,
|
|
2890
|
+
display: "flex",
|
|
2891
|
+
flexDirection: "column",
|
|
2892
|
+
gap: 8,
|
|
2893
|
+
padding: 10,
|
|
2894
|
+
borderRadius: 10,
|
|
2895
|
+
border: "1px solid " + (dragOverSide === side ? "var(--brand)" : "var(--border)"),
|
|
2896
|
+
background: "var(--surface)"
|
|
2897
|
+
},
|
|
2898
|
+
onDragOver: (e) => {
|
|
2899
|
+
if (!dragging || dragging.from === side) return;
|
|
2900
|
+
e.preventDefault();
|
|
2901
|
+
e.dataTransfer.dropEffect = "move";
|
|
2902
|
+
if (dragOverSide !== side) setDragOverSide(side);
|
|
2903
|
+
},
|
|
2904
|
+
onDragLeave: (e) => {
|
|
2905
|
+
if (e.currentTarget.contains(e.relatedTarget)) return;
|
|
2906
|
+
setDragOverSide((s) => s === side ? null : s);
|
|
2907
|
+
},
|
|
2908
|
+
onDrop: (e) => dropOnSide(e, side),
|
|
2909
|
+
children: [
|
|
2910
|
+
cfg.label ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "fd-overline fd-muted", children: [
|
|
2911
|
+
cfg.label,
|
|
2912
|
+
cfg.total != null ? " (" + cfg.total.toLocaleString() + ")" : ""
|
|
2913
|
+
] }) : null,
|
|
2914
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
2915
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(SearchField, { value: cfg.search, onChange: cfg.onSearchChange, placeholder: "Search", "aria-label": (cfg.label || side) + " search", style: { flex: 1 } }),
|
|
2916
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(SortMenu, { fields: cfg.sortFields, sort: cfg.sort, onSort: cfg.onSort })
|
|
2917
|
+
] }),
|
|
2918
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2919
|
+
VirtualList,
|
|
2920
|
+
{
|
|
2921
|
+
items: cfg.items,
|
|
2922
|
+
itemHeight,
|
|
2923
|
+
height: listHeight,
|
|
2924
|
+
keyOf,
|
|
2925
|
+
loading: cfg.loading,
|
|
2926
|
+
hasMore: cfg.hasMore || emptyHasMore,
|
|
2927
|
+
onNeedMore: cfg.onNeedMore,
|
|
2928
|
+
emptyState: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(EmptyState, { icon: "tray", title: "Nothing here" }),
|
|
2929
|
+
renderItem: (item) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2930
|
+
EntityRow,
|
|
2931
|
+
{
|
|
2932
|
+
title: renderLabel(item),
|
|
2933
|
+
meta: renderMeta ? renderMeta(item) : void 0,
|
|
2934
|
+
draggable: true,
|
|
2935
|
+
onDragStart: (e) => startDrag(e, item, side),
|
|
2936
|
+
onDragEnd: endDrag,
|
|
2937
|
+
style: { opacity: dragging && dragging.from === side && dragging.key === keyOf(item) ? 0.4 : 1 },
|
|
2938
|
+
action: {
|
|
2939
|
+
icon: side === "left" ? "plus" : "minus",
|
|
2940
|
+
label: (side === "left" ? "Move to " : "Move from ") + (side === "left" ? right.label || "the other list" : left.label || "the other list"),
|
|
2941
|
+
tone: side === "left" ? "add" : "remove",
|
|
2942
|
+
onClick: () => onMove(item, side, opposite)
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
)
|
|
2946
|
+
}
|
|
2947
|
+
)
|
|
2948
|
+
]
|
|
2949
|
+
}
|
|
2950
|
+
);
|
|
2951
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: ["fd-tlist", className].filter(Boolean).join(" "), style: { display: "flex", gap: 16, alignItems: "flex-start" }, children: [
|
|
2952
|
+
renderSide("left", left, "right"),
|
|
2953
|
+
renderSide("right", right, "left")
|
|
2954
|
+
] });
|
|
2955
|
+
}
|
|
2956
|
+
|
|
2957
|
+
// src/components/forms/Checkbox.tsx
|
|
2958
|
+
var React17 = __toESM(require("react"), 1);
|
|
2757
2959
|
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
2960
|
+
function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
|
|
2961
|
+
const ref = React17.useRef(null);
|
|
2962
|
+
React17.useEffect(() => {
|
|
2963
|
+
if (ref.current) ref.current.indeterminate = indeterminate;
|
|
2964
|
+
}, [indeterminate]);
|
|
2965
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
2966
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "fd-choice-input", children: [
|
|
2967
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("input", { ref, type: "checkbox", ...rest }),
|
|
2968
|
+
/* @__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" }) })
|
|
2969
|
+
] }),
|
|
2970
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "fd-choice-text", children: [
|
|
2971
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-choice-title", children: label }),
|
|
2972
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-choice-desc", children: description }) : null
|
|
2973
|
+
] })
|
|
2974
|
+
] });
|
|
2975
|
+
}
|
|
2976
|
+
|
|
2977
|
+
// src/components/forms/Radio.tsx
|
|
2978
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
2979
|
+
function Radio({ label, description, card = false, className = "", ...rest }) {
|
|
2980
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
2981
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "fd-choice-input", children: [
|
|
2982
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("input", { type: "radio", ...rest }),
|
|
2983
|
+
/* @__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" }) })
|
|
2984
|
+
] }),
|
|
2985
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "fd-choice-text", children: [
|
|
2986
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-choice-title", children: label }),
|
|
2987
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-choice-desc", children: description }) : null
|
|
2988
|
+
] })
|
|
2989
|
+
] });
|
|
2990
|
+
}
|
|
2991
|
+
|
|
2992
|
+
// src/components/forms/Switch.tsx
|
|
2993
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
2994
|
+
function Switch({ label, description, className = "", ...rest }) {
|
|
2995
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
|
|
2996
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("input", { type: "checkbox", role: "switch", ...rest }),
|
|
2997
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-switch-track", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-switch-thumb" }) }),
|
|
2998
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-choice-text", children: [
|
|
2999
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-switch-label", children: label }),
|
|
3000
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-choice-desc", children: description }) : null
|
|
3001
|
+
] }) : null
|
|
3002
|
+
] });
|
|
3003
|
+
}
|
|
3004
|
+
|
|
3005
|
+
// src/components/forms/Textarea.tsx
|
|
3006
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
2758
3007
|
function Textarea({ label, help, error, required = false, rows = 4, disabled = false, id, className = "", style, ...rest }) {
|
|
2759
3008
|
const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
|
|
2760
3009
|
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,
|
|
3010
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "fd-field", style, children: [
|
|
3011
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("label", { className: "fd-field-label", htmlFor: fieldId, children: [
|
|
2763
3012
|
label,
|
|
2764
|
-
required ? /* @__PURE__ */ (0,
|
|
3013
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-field-req", children: "*" }) : null
|
|
2765
3014
|
] }) : null,
|
|
2766
|
-
/* @__PURE__ */ (0,
|
|
2767
|
-
error ? /* @__PURE__ */ (0,
|
|
2768
|
-
/* @__PURE__ */ (0,
|
|
3015
|
+
/* @__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 }) }),
|
|
3016
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "fd-field-error", children: [
|
|
3017
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
2769
3018
|
error
|
|
2770
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3019
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
2771
3020
|
] });
|
|
2772
3021
|
}
|
|
2773
3022
|
|
|
2774
3023
|
// src/components/forms/NumberInput.tsx
|
|
2775
|
-
var
|
|
2776
|
-
var
|
|
3024
|
+
var React18 = __toESM(require("react"), 1);
|
|
3025
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
2777
3026
|
function NumberInput({
|
|
2778
3027
|
label,
|
|
2779
3028
|
help,
|
|
@@ -2797,10 +3046,10 @@ function NumberInput({
|
|
|
2797
3046
|
const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
|
|
2798
3047
|
return isNaN(n) ? null : n;
|
|
2799
3048
|
};
|
|
2800
|
-
const [text, setText] =
|
|
2801
|
-
const [editing, setEditing] =
|
|
2802
|
-
const timer =
|
|
2803
|
-
|
|
3049
|
+
const [text, setText] = React18.useState(value == null || value === "" ? "" : String(value));
|
|
3050
|
+
const [editing, setEditing] = React18.useState(false);
|
|
3051
|
+
const timer = React18.useRef(null);
|
|
3052
|
+
React18.useEffect(() => {
|
|
2804
3053
|
if (!editing) setText(value == null || value === "" ? "" : String(value));
|
|
2805
3054
|
}, [value, editing]);
|
|
2806
3055
|
const clamp = (n) => Math.min(max, Math.max(min, n));
|
|
@@ -2824,7 +3073,7 @@ function NumberInput({
|
|
|
2824
3073
|
const release = () => {
|
|
2825
3074
|
if (timer.current) clearTimeout(timer.current);
|
|
2826
3075
|
};
|
|
2827
|
-
|
|
3076
|
+
React18.useEffect(() => () => {
|
|
2828
3077
|
if (timer.current) clearTimeout(timer.current);
|
|
2829
3078
|
}, []);
|
|
2830
3079
|
const shown = editing ? text : (() => {
|
|
@@ -2832,14 +3081,14 @@ function NumberInput({
|
|
|
2832
3081
|
return n == null ? "" : format ? n.toLocaleString() : String(n);
|
|
2833
3082
|
})();
|
|
2834
3083
|
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,
|
|
3084
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
|
|
3085
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "fd-field-label", children: [
|
|
2837
3086
|
label,
|
|
2838
|
-
required ? /* @__PURE__ */ (0,
|
|
3087
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-field-req", children: "*" }) : null
|
|
2839
3088
|
] }) : null,
|
|
2840
|
-
/* @__PURE__ */ (0,
|
|
2841
|
-
prefix ? /* @__PURE__ */ (0,
|
|
2842
|
-
/* @__PURE__ */ (0,
|
|
3089
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: box, style: { gap: 8 }, children: [
|
|
3090
|
+
prefix ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
|
|
3091
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2843
3092
|
"input",
|
|
2844
3093
|
{
|
|
2845
3094
|
inputMode: "numeric",
|
|
@@ -2872,9 +3121,9 @@ function NumberInput({
|
|
|
2872
3121
|
}
|
|
2873
3122
|
}
|
|
2874
3123
|
),
|
|
2875
|
-
suffix ? /* @__PURE__ */ (0,
|
|
2876
|
-
/* @__PURE__ */ (0,
|
|
2877
|
-
/* @__PURE__ */ (0,
|
|
3124
|
+
suffix ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-input-affix", children: suffix }) : null,
|
|
3125
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "fd-row", style: { gap: 4, flex: "none" }, children: [
|
|
3126
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2878
3127
|
"button",
|
|
2879
3128
|
{
|
|
2880
3129
|
type: "button",
|
|
@@ -2884,10 +3133,10 @@ function NumberInput({
|
|
|
2884
3133
|
onPointerDown: () => hold(-1),
|
|
2885
3134
|
onPointerUp: release,
|
|
2886
3135
|
onPointerLeave: release,
|
|
2887
|
-
children: /* @__PURE__ */ (0,
|
|
3136
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-minus" })
|
|
2888
3137
|
}
|
|
2889
3138
|
),
|
|
2890
|
-
/* @__PURE__ */ (0,
|
|
3139
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2891
3140
|
"button",
|
|
2892
3141
|
{
|
|
2893
3142
|
type: "button",
|
|
@@ -2897,26 +3146,26 @@ function NumberInput({
|
|
|
2897
3146
|
onPointerDown: () => hold(1),
|
|
2898
3147
|
onPointerUp: release,
|
|
2899
3148
|
onPointerLeave: release,
|
|
2900
|
-
children: /* @__PURE__ */ (0,
|
|
3149
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-plus" })
|
|
2901
3150
|
}
|
|
2902
3151
|
)
|
|
2903
3152
|
] })
|
|
2904
3153
|
] }),
|
|
2905
|
-
error ? /* @__PURE__ */ (0,
|
|
2906
|
-
/* @__PURE__ */ (0,
|
|
3154
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "fd-field-error", children: [
|
|
3155
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
2907
3156
|
error
|
|
2908
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3157
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
2909
3158
|
] });
|
|
2910
3159
|
}
|
|
2911
3160
|
|
|
2912
3161
|
// src/components/forms/Select.tsx
|
|
2913
|
-
var
|
|
3162
|
+
var React19 = __toESM(require("react"), 1);
|
|
2914
3163
|
var import_react_dom4 = require("react-dom");
|
|
2915
|
-
var
|
|
3164
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
2916
3165
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
2917
3166
|
function usePopPos(open, ref, estH, estW) {
|
|
2918
|
-
const [pos, setPos] =
|
|
2919
|
-
|
|
3167
|
+
const [pos, setPos] = React19.useState(null);
|
|
3168
|
+
React19.useLayoutEffect(() => {
|
|
2920
3169
|
if (!open || !ref.current) {
|
|
2921
3170
|
setPos(null);
|
|
2922
3171
|
return;
|
|
@@ -2980,14 +3229,14 @@ function Select({
|
|
|
2980
3229
|
const vals = multiple ? Array.isArray(value) ? value : value ? [value] : [] : [];
|
|
2981
3230
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
2982
3231
|
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 =
|
|
3232
|
+
const [open, setOpen] = React19.useState(false);
|
|
3233
|
+
const [q, setQ] = React19.useState("");
|
|
3234
|
+
const [active, setActive] = React19.useState(-1);
|
|
3235
|
+
const rootRef = React19.useRef(null);
|
|
3236
|
+
const boxRef = React19.useRef(null);
|
|
3237
|
+
const popRef = React19.useRef(null);
|
|
3238
|
+
const listRef = React19.useRef(null);
|
|
3239
|
+
const typeBuf = React19.useRef({ s: "", t: 0 });
|
|
2991
3240
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
2992
3241
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
2993
3242
|
const pos = usePopPos(open, boxRef, hasSearch ? 390 : 340, 260);
|
|
@@ -3013,7 +3262,7 @@ function Select({
|
|
|
3013
3262
|
}
|
|
3014
3263
|
setOpen(!open);
|
|
3015
3264
|
};
|
|
3016
|
-
|
|
3265
|
+
React19.useEffect(() => {
|
|
3017
3266
|
if (!open) return;
|
|
3018
3267
|
const away = (e) => {
|
|
3019
3268
|
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
@@ -3023,7 +3272,7 @@ function Select({
|
|
|
3023
3272
|
document.addEventListener("pointerdown", away);
|
|
3024
3273
|
return () => document.removeEventListener("pointerdown", away);
|
|
3025
3274
|
}, [open]);
|
|
3026
|
-
|
|
3275
|
+
React19.useEffect(() => {
|
|
3027
3276
|
if (!open || active < 0 || !listRef.current) return;
|
|
3028
3277
|
const el = listRef.current.querySelector('[data-i="' + active + '"]');
|
|
3029
3278
|
if (el) {
|
|
@@ -3077,13 +3326,13 @@ function Select({
|
|
|
3077
3326
|
});
|
|
3078
3327
|
const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
|
|
3079
3328
|
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,
|
|
3329
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
3330
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "fd-field-label", htmlFor: fieldId, onClick: toggle, children: [
|
|
3082
3331
|
label,
|
|
3083
|
-
required ? /* @__PURE__ */ (0,
|
|
3332
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-field-req", children: "*" }) : null
|
|
3084
3333
|
] }) : null,
|
|
3085
|
-
/* @__PURE__ */ (0,
|
|
3086
|
-
/* @__PURE__ */ (0,
|
|
3334
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: box, style: { cursor: disabled ? "not-allowed" : "pointer" }, ref: boxRef, children: [
|
|
3335
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
3087
3336
|
"button",
|
|
3088
3337
|
{
|
|
3089
3338
|
type: "button",
|
|
@@ -3096,13 +3345,13 @@ function Select({
|
|
|
3096
3345
|
"aria-haspopup": "listbox",
|
|
3097
3346
|
style: { all: "unset", flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: 8, cursor: "inherit", overflow: "hidden" },
|
|
3098
3347
|
children: [
|
|
3099
|
-
selected && selected.icon ? /* @__PURE__ */ (0,
|
|
3100
|
-
/* @__PURE__ */ (0,
|
|
3101
|
-
multiple && chosen.length > 1 ? /* @__PURE__ */ (0,
|
|
3348
|
+
selected && selected.icon ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-" + selected.icon, style: { flex: "none", color: "var(--text-2)" } }) : null,
|
|
3349
|
+
/* @__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 }),
|
|
3350
|
+
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
3351
|
]
|
|
3103
3352
|
}
|
|
3104
3353
|
),
|
|
3105
|
-
clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ (0,
|
|
3354
|
+
clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3106
3355
|
"button",
|
|
3107
3356
|
{
|
|
3108
3357
|
type: "button",
|
|
@@ -3112,22 +3361,22 @@ function Select({
|
|
|
3112
3361
|
fire(multiple ? [] : "");
|
|
3113
3362
|
},
|
|
3114
3363
|
style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
|
|
3115
|
-
children: /* @__PURE__ */ (0,
|
|
3364
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 } })
|
|
3116
3365
|
}
|
|
3117
3366
|
) : null,
|
|
3118
|
-
loading ? /* @__PURE__ */ (0,
|
|
3367
|
+
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
3368
|
] }),
|
|
3120
3369
|
open && pos ? (0, import_react_dom4.createPortal)(
|
|
3121
|
-
/* @__PURE__ */ (0,
|
|
3370
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
3122
3371
|
"div",
|
|
3123
3372
|
{
|
|
3124
3373
|
className: "fd-pop" + (pos.up ? " is-up" : ""),
|
|
3125
3374
|
ref: popRef,
|
|
3126
3375
|
style: popStyle(pos, { minWidth: Math.max(pos.width, 260), maxWidth: 380, zIndex: 130, overflowY: "hidden" }),
|
|
3127
3376
|
children: [
|
|
3128
|
-
hasSearch ? /* @__PURE__ */ (0,
|
|
3129
|
-
/* @__PURE__ */ (0,
|
|
3130
|
-
/* @__PURE__ */ (0,
|
|
3377
|
+
hasSearch ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fd-pop-search", children: [
|
|
3378
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-magnifying-glass", style: { color: "var(--text-muted)", fontSize: 14 } }),
|
|
3379
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3131
3380
|
"input",
|
|
3132
3381
|
{
|
|
3133
3382
|
autoFocus: true,
|
|
@@ -3140,15 +3389,15 @@ function Select({
|
|
|
3140
3389
|
}
|
|
3141
3390
|
}
|
|
3142
3391
|
),
|
|
3143
|
-
q ? /* @__PURE__ */ (0,
|
|
3392
|
+
q ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
3144
3393
|
] }) : null,
|
|
3145
|
-
/* @__PURE__ */ (0,
|
|
3394
|
+
/* @__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
3395
|
'Nothing matches "',
|
|
3147
3396
|
q,
|
|
3148
3397
|
'".'
|
|
3149
|
-
] }) : groups.map((grp) => /* @__PURE__ */ (0,
|
|
3150
|
-
grp.g ? /* @__PURE__ */ (0,
|
|
3151
|
-
grp.items.map(({ o, i }) => /* @__PURE__ */ (0,
|
|
3398
|
+
] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(React19.Fragment, { children: [
|
|
3399
|
+
grp.g ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
|
|
3400
|
+
grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
3152
3401
|
"button",
|
|
3153
3402
|
{
|
|
3154
3403
|
type: "button",
|
|
@@ -3160,21 +3409,21 @@ function Select({
|
|
|
3160
3409
|
onMouseEnter: () => setActive(i),
|
|
3161
3410
|
onClick: () => pick(o),
|
|
3162
3411
|
children: [
|
|
3163
|
-
multiple ? /* @__PURE__ */ (0,
|
|
3164
|
-
o.icon ? /* @__PURE__ */ (0,
|
|
3165
|
-
/* @__PURE__ */ (0,
|
|
3166
|
-
/* @__PURE__ */ (0,
|
|
3167
|
-
o.description ? /* @__PURE__ */ (0,
|
|
3412
|
+
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,
|
|
3413
|
+
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,
|
|
3414
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { style: { flex: 1, minWidth: 0 }, children: [
|
|
3415
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-opt-label", children: o.label }),
|
|
3416
|
+
o.description ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-opt-desc", children: o.description }) : null
|
|
3168
3417
|
] }),
|
|
3169
|
-
o.meta ? /* @__PURE__ */ (0,
|
|
3170
|
-
multiple ? null : /* @__PURE__ */ (0,
|
|
3418
|
+
o.meta ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-opt-meta", children: o.meta }) : null,
|
|
3419
|
+
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
3420
|
]
|
|
3172
3421
|
},
|
|
3173
3422
|
String(o.value)
|
|
3174
3423
|
))
|
|
3175
3424
|
] }, grp.g || "_")) }),
|
|
3176
|
-
multiple ? /* @__PURE__ */ (0,
|
|
3177
|
-
/* @__PURE__ */ (0,
|
|
3425
|
+
multiple ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "8px 12px", borderTop: "1px solid var(--border)" }, children: [
|
|
3426
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3178
3427
|
"button",
|
|
3179
3428
|
{
|
|
3180
3429
|
type: "button",
|
|
@@ -3183,13 +3432,13 @@ function Select({
|
|
|
3183
3432
|
children: "Select all"
|
|
3184
3433
|
}
|
|
3185
3434
|
),
|
|
3186
|
-
/* @__PURE__ */ (0,
|
|
3187
|
-
/* @__PURE__ */ (0,
|
|
3435
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { style: { flex: 1 } }),
|
|
3436
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
3188
3437
|
vals.length,
|
|
3189
3438
|
" of ",
|
|
3190
3439
|
opts.length
|
|
3191
3440
|
] }),
|
|
3192
|
-
/* @__PURE__ */ (0,
|
|
3441
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3193
3442
|
"button",
|
|
3194
3443
|
{
|
|
3195
3444
|
type: "button",
|
|
@@ -3205,17 +3454,17 @@ function Select({
|
|
|
3205
3454
|
),
|
|
3206
3455
|
document.body
|
|
3207
3456
|
) : null,
|
|
3208
|
-
error ? /* @__PURE__ */ (0,
|
|
3209
|
-
/* @__PURE__ */ (0,
|
|
3457
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "fd-field-error", children: [
|
|
3458
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3210
3459
|
error
|
|
3211
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3460
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3212
3461
|
] });
|
|
3213
3462
|
}
|
|
3214
3463
|
|
|
3215
3464
|
// src/components/forms/DatePicker.tsx
|
|
3216
|
-
var
|
|
3465
|
+
var React20 = __toESM(require("react"), 1);
|
|
3217
3466
|
var import_react_dom5 = require("react-dom");
|
|
3218
|
-
var
|
|
3467
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
3219
3468
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
3220
3469
|
var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
3221
3470
|
var iso = (d) => d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
|
|
@@ -3229,8 +3478,8 @@ var fmt = (s) => {
|
|
|
3229
3478
|
return d ? MONTHS[d.getMonth()].slice(0, 3) + " " + d.getDate() + ", " + d.getFullYear() : "";
|
|
3230
3479
|
};
|
|
3231
3480
|
function usePopPos2(open, ref, estH, estW) {
|
|
3232
|
-
const [pos, setPos] =
|
|
3233
|
-
|
|
3481
|
+
const [pos, setPos] = React20.useState(null);
|
|
3482
|
+
React20.useLayoutEffect(() => {
|
|
3234
3483
|
if (!open || !ref.current) {
|
|
3235
3484
|
setPos(null);
|
|
3236
3485
|
return;
|
|
@@ -3274,10 +3523,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3274
3523
|
const today = /* @__PURE__ */ new Date();
|
|
3275
3524
|
const sel = range ? value || {} : { start: value, end: value };
|
|
3276
3525
|
const anchor = parse(sel.start) || parse(initialMonth) || today;
|
|
3277
|
-
const [vy, setVy] =
|
|
3278
|
-
const [vm, setVm] =
|
|
3279
|
-
const [mode2, setMode] =
|
|
3280
|
-
const [hover, setHover] =
|
|
3526
|
+
const [vy, setVy] = React20.useState(anchor.getFullYear());
|
|
3527
|
+
const [vm, setVm] = React20.useState(anchor.getMonth());
|
|
3528
|
+
const [mode2, setMode] = React20.useState("days");
|
|
3529
|
+
const [hover, setHover] = React20.useState(null);
|
|
3281
3530
|
const s = parse(sel.start), e = parse(sel.end);
|
|
3282
3531
|
const hoverEnd = range && s && !e && hover ? parse(hover) : null;
|
|
3283
3532
|
const inRange = (d) => {
|
|
@@ -3314,9 +3563,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3314
3563
|
const startPad = new Date(y, m, 1).getDay();
|
|
3315
3564
|
const cells = [];
|
|
3316
3565
|
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,
|
|
3566
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal-grid", style: { width: months > 1 ? 252 : "auto", flex: "none" }, onMouseLeave: () => setHover(null), children: [
|
|
3567
|
+
DOW.map((d) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-cal-dow", children: d }, d)),
|
|
3568
|
+
cells.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3320
3569
|
"button",
|
|
3321
3570
|
{
|
|
3322
3571
|
type: "button",
|
|
@@ -3330,20 +3579,20 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3330
3579
|
] });
|
|
3331
3580
|
};
|
|
3332
3581
|
const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
|
|
3333
|
-
return /* @__PURE__ */ (0,
|
|
3334
|
-
/* @__PURE__ */ (0,
|
|
3335
|
-
/* @__PURE__ */ (0,
|
|
3336
|
-
/* @__PURE__ */ (0,
|
|
3582
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, children: [
|
|
3583
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal-head", children: [
|
|
3584
|
+
/* @__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" }) }),
|
|
3585
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("button", { type: "button", className: "fd-cal-title", onClick: () => setMode(mode2 === "days" ? "months" : mode2 === "months" ? "years" : "days"), children: [
|
|
3337
3586
|
mode2 === "days" ? MONTHS[vm] + " " + vy : mode2 === "months" ? vy : vy - 5 + " \u2013 " + (vy + 6),
|
|
3338
|
-
/* @__PURE__ */ (0,
|
|
3587
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-caret-down", style: { fontSize: 10, marginLeft: 6, color: "var(--text-muted)" } })
|
|
3339
3588
|
] }),
|
|
3340
|
-
months > 1 && mode2 === "days" ? /* @__PURE__ */ (0,
|
|
3341
|
-
/* @__PURE__ */ (0,
|
|
3589
|
+
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,
|
|
3590
|
+
/* @__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
3591
|
] }),
|
|
3343
|
-
mode2 === "days" ? /* @__PURE__ */ (0,
|
|
3592
|
+
mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { style: { display: "flex", gap: 18 }, children: [
|
|
3344
3593
|
monthGrid(vy, vm),
|
|
3345
3594
|
months > 1 ? monthGrid(nextY, nextM) : null
|
|
3346
|
-
] }) : mode2 === "months" ? /* @__PURE__ */ (0,
|
|
3595
|
+
] }) : 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
3596
|
"button",
|
|
3348
3597
|
{
|
|
3349
3598
|
type: "button",
|
|
@@ -3355,7 +3604,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3355
3604
|
children: m.slice(0, 3)
|
|
3356
3605
|
},
|
|
3357
3606
|
m
|
|
3358
|
-
)) }) : /* @__PURE__ */ (0,
|
|
3607
|
+
)) }) : /* @__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
3608
|
"button",
|
|
3360
3609
|
{
|
|
3361
3610
|
type: "button",
|
|
@@ -3368,8 +3617,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3368
3617
|
},
|
|
3369
3618
|
y
|
|
3370
3619
|
)) }),
|
|
3371
|
-
/* @__PURE__ */ (0,
|
|
3372
|
-
/* @__PURE__ */ (0,
|
|
3620
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal-foot", children: [
|
|
3621
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3373
3622
|
"button",
|
|
3374
3623
|
{
|
|
3375
3624
|
type: "button",
|
|
@@ -3383,8 +3632,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3383
3632
|
children: "Today"
|
|
3384
3633
|
}
|
|
3385
3634
|
),
|
|
3386
|
-
/* @__PURE__ */ (0,
|
|
3387
|
-
range && sel.start ? /* @__PURE__ */ (0,
|
|
3635
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { style: { flex: 1 } }),
|
|
3636
|
+
range && sel.start ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
3388
3637
|
fmt(sel.start),
|
|
3389
3638
|
sel.end ? " \u2192 " + fmt(sel.end) : " \u2192 pick an end"
|
|
3390
3639
|
] }) : null
|
|
@@ -3392,12 +3641,12 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3392
3641
|
] });
|
|
3393
3642
|
}
|
|
3394
3643
|
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 =
|
|
3644
|
+
const [open, setOpen] = React20.useState(false);
|
|
3645
|
+
const rootRef = React20.useRef(null);
|
|
3646
|
+
const boxRef = React20.useRef(null);
|
|
3647
|
+
const popRef = React20.useRef(null);
|
|
3399
3648
|
const pos = usePopPos2(open, boxRef, 430, range ? 600 : 316);
|
|
3400
|
-
|
|
3649
|
+
React20.useEffect(() => {
|
|
3401
3650
|
if (!open) return;
|
|
3402
3651
|
const away = (e) => {
|
|
3403
3652
|
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
@@ -3418,14 +3667,14 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3418
3667
|
const toggle = () => {
|
|
3419
3668
|
if (!disabled) setOpen(!open);
|
|
3420
3669
|
};
|
|
3421
|
-
return /* @__PURE__ */ (0,
|
|
3422
|
-
label ? /* @__PURE__ */ (0,
|
|
3670
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
3671
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("label", { className: "fd-field-label", onClick: toggle, children: [
|
|
3423
3672
|
label,
|
|
3424
|
-
required ? /* @__PURE__ */ (0,
|
|
3673
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-field-req", children: "*" }) : null
|
|
3425
3674
|
] }) : null,
|
|
3426
|
-
/* @__PURE__ */ (0,
|
|
3427
|
-
/* @__PURE__ */ (0,
|
|
3428
|
-
/* @__PURE__ */ (0,
|
|
3675
|
+
/* @__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: [
|
|
3676
|
+
/* @__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" }) }),
|
|
3677
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3429
3678
|
"button",
|
|
3430
3679
|
{
|
|
3431
3680
|
type: "button",
|
|
@@ -3441,10 +3690,10 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3441
3690
|
children: display || placeholder || (range ? "Pick a date range" : "Pick a date")
|
|
3442
3691
|
}
|
|
3443
3692
|
),
|
|
3444
|
-
/* @__PURE__ */ (0,
|
|
3693
|
+
/* @__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
3694
|
] }),
|
|
3446
3695
|
open && pos ? (0, import_react_dom5.createPortal)(
|
|
3447
|
-
/* @__PURE__ */ (0,
|
|
3696
|
+
/* @__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
3697
|
Calendar,
|
|
3449
3698
|
{
|
|
3450
3699
|
range,
|
|
@@ -3458,21 +3707,21 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3458
3707
|
) }),
|
|
3459
3708
|
document.body
|
|
3460
3709
|
) : null,
|
|
3461
|
-
error ? /* @__PURE__ */ (0,
|
|
3462
|
-
/* @__PURE__ */ (0,
|
|
3710
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "fd-field-error", children: [
|
|
3711
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3463
3712
|
error
|
|
3464
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3713
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3465
3714
|
] });
|
|
3466
3715
|
}
|
|
3467
3716
|
|
|
3468
3717
|
// src/components/forms/TimePicker.tsx
|
|
3469
|
-
var
|
|
3718
|
+
var React21 = __toESM(require("react"), 1);
|
|
3470
3719
|
var import_react_dom6 = require("react-dom");
|
|
3471
|
-
var
|
|
3720
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
3472
3721
|
var pad = (n) => String(n).padStart(2, "0");
|
|
3473
3722
|
function usePopPos3(open, ref, estH, estW) {
|
|
3474
|
-
const [pos, setPos] =
|
|
3475
|
-
|
|
3723
|
+
const [pos, setPos] = React21.useState(null);
|
|
3724
|
+
React21.useLayoutEffect(() => {
|
|
3476
3725
|
if (!open || !ref.current) {
|
|
3477
3726
|
setPos(null);
|
|
3478
3727
|
return;
|
|
@@ -3518,9 +3767,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3518
3767
|
if (isNaN(m)) m = 0;
|
|
3519
3768
|
const pm = h24 >= 12;
|
|
3520
3769
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
3521
|
-
const [mode2, setMode] =
|
|
3522
|
-
const faceRef =
|
|
3523
|
-
const dragging =
|
|
3770
|
+
const [mode2, setMode] = React21.useState("h");
|
|
3771
|
+
const faceRef = React21.useRef(null);
|
|
3772
|
+
const dragging = React21.useRef(false);
|
|
3524
3773
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
3525
3774
|
const R = 108, NR = 80;
|
|
3526
3775
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -3555,12 +3804,12 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3555
3804
|
};
|
|
3556
3805
|
const handAngle = mode2 === "h" ? h12 % 12 * 30 : m * 6;
|
|
3557
3806
|
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,
|
|
3807
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { style: { padding: "4px 14px 14px" }, children: [
|
|
3808
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-clock-digits", children: [
|
|
3809
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", className: "fd-clock-digit" + (mode2 === "h" ? " is-active" : ""), onClick: () => setMode("h"), children: pad(h12) }),
|
|
3810
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { style: { fontSize: 24, fontWeight: 700, color: "var(--text-muted)" }, children: ":" }),
|
|
3811
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", className: "fd-clock-digit" + (mode2 === "m" ? " is-active" : ""), onClick: () => setMode("m"), children: pad(m) }),
|
|
3812
|
+
/* @__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
3813
|
"button",
|
|
3565
3814
|
{
|
|
3566
3815
|
type: "button",
|
|
@@ -3571,13 +3820,13 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3571
3820
|
ap
|
|
3572
3821
|
)) })
|
|
3573
3822
|
] }),
|
|
3574
|
-
/* @__PURE__ */ (0,
|
|
3575
|
-
/* @__PURE__ */ (0,
|
|
3576
|
-
/* @__PURE__ */ (0,
|
|
3577
|
-
minuteOff ? /* @__PURE__ */ (0,
|
|
3823
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-clock", ref: faceRef, onPointerDown: down, onPointerMove: move, onPointerUp: upH, children: [
|
|
3824
|
+
/* @__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%" } }),
|
|
3825
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-clock-pivot" }),
|
|
3826
|
+
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
3827
|
nums.map((n) => {
|
|
3579
3828
|
const a = angleOf(n) * Math.PI / 180;
|
|
3580
|
-
return /* @__PURE__ */ (0,
|
|
3829
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3581
3830
|
"span",
|
|
3582
3831
|
{
|
|
3583
3832
|
className: "fd-clock-num" + (n === selNum || mode2 === "m" && n === Math.round(m / 5) * 5 % 60 && m % 5 === 0 ? " is-sel" : ""),
|
|
@@ -3588,16 +3837,16 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3588
3837
|
);
|
|
3589
3838
|
})
|
|
3590
3839
|
] }),
|
|
3591
|
-
/* @__PURE__ */ (0,
|
|
3840
|
+
/* @__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
3841
|
] });
|
|
3593
3842
|
}
|
|
3594
3843
|
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 =
|
|
3844
|
+
const [open, setOpen] = React21.useState(false);
|
|
3845
|
+
const rootRef = React21.useRef(null);
|
|
3846
|
+
const boxRef = React21.useRef(null);
|
|
3847
|
+
const popRef = React21.useRef(null);
|
|
3599
3848
|
const pos = usePopPos3(open, boxRef, 420, 262);
|
|
3600
|
-
|
|
3849
|
+
React21.useEffect(() => {
|
|
3601
3850
|
if (!open) return;
|
|
3602
3851
|
const away = (e) => {
|
|
3603
3852
|
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
@@ -3622,14 +3871,14 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
3622
3871
|
const toggle = () => {
|
|
3623
3872
|
if (!disabled) setOpen(!open);
|
|
3624
3873
|
};
|
|
3625
|
-
return /* @__PURE__ */ (0,
|
|
3626
|
-
label ? /* @__PURE__ */ (0,
|
|
3874
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
3875
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("label", { className: "fd-field-label", onClick: toggle, children: [
|
|
3627
3876
|
label,
|
|
3628
|
-
required ? /* @__PURE__ */ (0,
|
|
3877
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-field-req", children: "*" }) : null
|
|
3629
3878
|
] }) : null,
|
|
3630
|
-
/* @__PURE__ */ (0,
|
|
3631
|
-
/* @__PURE__ */ (0,
|
|
3632
|
-
/* @__PURE__ */ (0,
|
|
3879
|
+
/* @__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: [
|
|
3880
|
+
/* @__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" }) }),
|
|
3881
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3633
3882
|
"button",
|
|
3634
3883
|
{
|
|
3635
3884
|
type: "button",
|
|
@@ -3644,13 +3893,13 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
3644
3893
|
children: disp() || placeholder
|
|
3645
3894
|
}
|
|
3646
3895
|
),
|
|
3647
|
-
/* @__PURE__ */ (0,
|
|
3896
|
+
/* @__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
3897
|
] }),
|
|
3649
3898
|
open && pos ? (0, import_react_dom6.createPortal)(
|
|
3650
|
-
/* @__PURE__ */ (0,
|
|
3651
|
-
/* @__PURE__ */ (0,
|
|
3652
|
-
/* @__PURE__ */ (0,
|
|
3653
|
-
/* @__PURE__ */ (0,
|
|
3899
|
+
/* @__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: [
|
|
3900
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ClockFace, { value: value || "09:00", onChange: (v) => onChange && onChange({ target: { value: v } }) }),
|
|
3901
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-cal-foot", style: { margin: "0 14px 12px", paddingTop: 10 }, children: [
|
|
3902
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3654
3903
|
"button",
|
|
3655
3904
|
{
|
|
3656
3905
|
type: "button",
|
|
@@ -3663,22 +3912,22 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
3663
3912
|
children: "Now"
|
|
3664
3913
|
}
|
|
3665
3914
|
),
|
|
3666
|
-
/* @__PURE__ */ (0,
|
|
3667
|
-
/* @__PURE__ */ (0,
|
|
3915
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { style: { flex: 1 } }),
|
|
3916
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", onClick: () => setOpen(false), children: "Done" })
|
|
3668
3917
|
] })
|
|
3669
3918
|
] }),
|
|
3670
3919
|
document.body
|
|
3671
3920
|
) : null,
|
|
3672
|
-
error ? /* @__PURE__ */ (0,
|
|
3673
|
-
/* @__PURE__ */ (0,
|
|
3921
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "fd-field-error", children: [
|
|
3922
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3674
3923
|
error
|
|
3675
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3924
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3676
3925
|
] });
|
|
3677
3926
|
}
|
|
3678
3927
|
|
|
3679
3928
|
// src/components/forms/Slider.tsx
|
|
3680
|
-
var
|
|
3681
|
-
var
|
|
3929
|
+
var React22 = __toESM(require("react"), 1);
|
|
3930
|
+
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
3682
3931
|
function Slider({
|
|
3683
3932
|
label,
|
|
3684
3933
|
min = 0,
|
|
@@ -3692,18 +3941,18 @@ function Slider({
|
|
|
3692
3941
|
className = "",
|
|
3693
3942
|
...rest
|
|
3694
3943
|
}) {
|
|
3695
|
-
const [dragging, setDragging] =
|
|
3944
|
+
const [dragging, setDragging] = React22.useState(false);
|
|
3696
3945
|
const v = value === void 0 ? min : Number(value);
|
|
3697
3946
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
3698
|
-
return /* @__PURE__ */ (0,
|
|
3699
|
-
label ? /* @__PURE__ */ (0,
|
|
3700
|
-
/* @__PURE__ */ (0,
|
|
3701
|
-
/* @__PURE__ */ (0,
|
|
3947
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
|
|
3948
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
3949
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-field-label", children: label }),
|
|
3950
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: format(v) })
|
|
3702
3951
|
] }) : null,
|
|
3703
|
-
/* @__PURE__ */ (0,
|
|
3704
|
-
/* @__PURE__ */ (0,
|
|
3705
|
-
showChip && dragging ? /* @__PURE__ */ (0,
|
|
3706
|
-
/* @__PURE__ */ (0,
|
|
3952
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "fd-slider", children: [
|
|
3953
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
3954
|
+
showChip && dragging ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-slider-chip", style: { left: pct + "%" }, children: format(v) }) : null,
|
|
3955
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3707
3956
|
"input",
|
|
3708
3957
|
{
|
|
3709
3958
|
type: "range",
|
|
@@ -3720,13 +3969,13 @@ function Slider({
|
|
|
3720
3969
|
}
|
|
3721
3970
|
)
|
|
3722
3971
|
] }),
|
|
3723
|
-
help ? /* @__PURE__ */ (0,
|
|
3972
|
+
help ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3724
3973
|
] });
|
|
3725
3974
|
}
|
|
3726
3975
|
|
|
3727
3976
|
// src/components/forms/RangeSlider.tsx
|
|
3728
|
-
var
|
|
3729
|
-
var
|
|
3977
|
+
var React23 = __toESM(require("react"), 1);
|
|
3978
|
+
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
3730
3979
|
function RangeSlider({
|
|
3731
3980
|
label,
|
|
3732
3981
|
min = 0,
|
|
@@ -3745,9 +3994,9 @@ function RangeSlider({
|
|
|
3745
3994
|
}) {
|
|
3746
3995
|
const fmt2 = format || ((v) => String(v));
|
|
3747
3996
|
const [a, b] = value || [min, max];
|
|
3748
|
-
const [drag, setDrag] =
|
|
3749
|
-
const [focus, setFocus] =
|
|
3750
|
-
const railRef =
|
|
3997
|
+
const [drag, setDrag] = React23.useState(null);
|
|
3998
|
+
const [focus, setFocus] = React23.useState(null);
|
|
3999
|
+
const railRef = React23.useRef(null);
|
|
3751
4000
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
3752
4001
|
const clampPair = (i, v) => {
|
|
3753
4002
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -3762,7 +4011,7 @@ function RangeSlider({
|
|
|
3762
4011
|
const r = railRef.current.getBoundingClientRect();
|
|
3763
4012
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
3764
4013
|
};
|
|
3765
|
-
|
|
4014
|
+
React23.useEffect(() => {
|
|
3766
4015
|
if (drag === null) return;
|
|
3767
4016
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
3768
4017
|
const upH = () => setDrag(null);
|
|
@@ -3783,7 +4032,7 @@ function RangeSlider({
|
|
|
3783
4032
|
};
|
|
3784
4033
|
const thin = S.length > 7 ? Math.ceil(S.length / 5) : 1;
|
|
3785
4034
|
const pair = value || [S[0].value, S[S.length - 1].value];
|
|
3786
|
-
return /* @__PURE__ */ (0,
|
|
4035
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3787
4036
|
RangeSlider,
|
|
3788
4037
|
{
|
|
3789
4038
|
...rest,
|
|
@@ -3831,23 +4080,23 @@ function RangeSlider({
|
|
|
3831
4080
|
};
|
|
3832
4081
|
const showChip = (i) => drag === i || focus === i;
|
|
3833
4082
|
const hasLabels = marks.some((m) => m.label);
|
|
3834
|
-
return /* @__PURE__ */ (0,
|
|
3835
|
-
label ? /* @__PURE__ */ (0,
|
|
3836
|
-
/* @__PURE__ */ (0,
|
|
3837
|
-
/* @__PURE__ */ (0,
|
|
4083
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), ...rest, children: [
|
|
4084
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
4085
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-field-label", children: label }),
|
|
4086
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: [
|
|
3838
4087
|
fmt2(a),
|
|
3839
4088
|
" \u2013 ",
|
|
3840
4089
|
fmt2(b)
|
|
3841
4090
|
] })
|
|
3842
4091
|
] }) : null,
|
|
3843
|
-
/* @__PURE__ */ (0,
|
|
3844
|
-
/* @__PURE__ */ (0,
|
|
3845
|
-
/* @__PURE__ */ (0,
|
|
3846
|
-
marks.map((m) => /* @__PURE__ */ (0,
|
|
3847
|
-
/* @__PURE__ */ (0,
|
|
3848
|
-
m.label ? /* @__PURE__ */ (0,
|
|
4092
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
|
|
4093
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-rail", ref: railRef }),
|
|
4094
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
|
|
4095
|
+
marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React23.Fragment, { children: [
|
|
4096
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
|
|
4097
|
+
m.label ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
|
|
3849
4098
|
] }, m.value)),
|
|
3850
|
-
[a, b].map((v, i) => /* @__PURE__ */ (0,
|
|
4099
|
+
[a, b].map((v, i) => /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3851
4100
|
"span",
|
|
3852
4101
|
{
|
|
3853
4102
|
className: "fd-range-thumb" + (drag === i ? " is-drag" : ""),
|
|
@@ -3862,18 +4111,18 @@ function RangeSlider({
|
|
|
3862
4111
|
onKeyDown: key(i),
|
|
3863
4112
|
onFocus: () => setFocus(i),
|
|
3864
4113
|
onBlur: () => setFocus(null),
|
|
3865
|
-
children: /* @__PURE__ */ (0,
|
|
4114
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-chip", style: { opacity: showChip(i) ? 1 : void 0 }, children: fmt2(v) })
|
|
3866
4115
|
},
|
|
3867
4116
|
i
|
|
3868
4117
|
))
|
|
3869
4118
|
] }),
|
|
3870
|
-
help ? /* @__PURE__ */ (0,
|
|
4119
|
+
help ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3871
4120
|
] });
|
|
3872
4121
|
}
|
|
3873
4122
|
|
|
3874
4123
|
// src/components/forms/Dropzone.tsx
|
|
3875
|
-
var
|
|
3876
|
-
var
|
|
4124
|
+
var React24 = __toESM(require("react"), 1);
|
|
4125
|
+
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
3877
4126
|
function Dropzone({
|
|
3878
4127
|
onFiles,
|
|
3879
4128
|
onReject,
|
|
@@ -3887,8 +4136,8 @@ function Dropzone({
|
|
|
3887
4136
|
className = "",
|
|
3888
4137
|
style
|
|
3889
4138
|
}) {
|
|
3890
|
-
const [over, setOver] =
|
|
3891
|
-
const depth =
|
|
4139
|
+
const [over, setOver] = React24.useState(false);
|
|
4140
|
+
const depth = React24.useRef(0);
|
|
3892
4141
|
const has = (e) => {
|
|
3893
4142
|
const dt = e.dataTransfer;
|
|
3894
4143
|
if (!dt) return false;
|
|
@@ -3918,7 +4167,7 @@ function Dropzone({
|
|
|
3918
4167
|
if (rejected.length && onReject) onReject(rejected);
|
|
3919
4168
|
if (accepted.length && onFiles) onFiles(accepted);
|
|
3920
4169
|
};
|
|
3921
|
-
return /* @__PURE__ */ (0,
|
|
4170
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
3922
4171
|
"div",
|
|
3923
4172
|
{
|
|
3924
4173
|
className: ["fd-dropzone", over ? "is-over" : "", className].filter(Boolean).join(" "),
|
|
@@ -3929,10 +4178,10 @@ function Dropzone({
|
|
|
3929
4178
|
onDrop: drop,
|
|
3930
4179
|
children: [
|
|
3931
4180
|
children,
|
|
3932
|
-
over ? /* @__PURE__ */ (0,
|
|
3933
|
-
/* @__PURE__ */ (0,
|
|
3934
|
-
/* @__PURE__ */ (0,
|
|
3935
|
-
hint ? /* @__PURE__ */ (0,
|
|
4181
|
+
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: [
|
|
4182
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-tray-arrow-down" }),
|
|
4183
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-dropzone-label", children: label }),
|
|
4184
|
+
hint ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-dropzone-hint", children: hint }) : null
|
|
3936
4185
|
] }) }) : null
|
|
3937
4186
|
]
|
|
3938
4187
|
}
|
|
@@ -3950,9 +4199,9 @@ function FilePickButton({
|
|
|
3950
4199
|
className = "",
|
|
3951
4200
|
children
|
|
3952
4201
|
}) {
|
|
3953
|
-
const ref =
|
|
3954
|
-
return /* @__PURE__ */ (0,
|
|
3955
|
-
/* @__PURE__ */ (0,
|
|
4202
|
+
const ref = React24.useRef(null);
|
|
4203
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(React24.Fragment, { children: [
|
|
4204
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3956
4205
|
"button",
|
|
3957
4206
|
{
|
|
3958
4207
|
type: "button",
|
|
@@ -3961,10 +4210,10 @@ function FilePickButton({
|
|
|
3961
4210
|
"aria-label": label,
|
|
3962
4211
|
title: label,
|
|
3963
4212
|
onClick: () => ref.current && ref.current.click(),
|
|
3964
|
-
children: children != null ? children : /* @__PURE__ */ (0,
|
|
4213
|
+
children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-" + icon, "aria-hidden": "true" })
|
|
3965
4214
|
}
|
|
3966
4215
|
),
|
|
3967
|
-
/* @__PURE__ */ (0,
|
|
4216
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3968
4217
|
"input",
|
|
3969
4218
|
{
|
|
3970
4219
|
ref,
|
|
@@ -3984,10 +4233,10 @@ function FilePickButton({
|
|
|
3984
4233
|
}
|
|
3985
4234
|
function useStagedFiles(upload, opts) {
|
|
3986
4235
|
const o = opts || {};
|
|
3987
|
-
const [items, setItems] =
|
|
3988
|
-
const controllers =
|
|
4236
|
+
const [items, setItems] = React24.useState([]);
|
|
4237
|
+
const controllers = React24.useRef({});
|
|
3989
4238
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
3990
|
-
const run =
|
|
4239
|
+
const run = React24.useCallback((att) => {
|
|
3991
4240
|
if (!upload) return;
|
|
3992
4241
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
3993
4242
|
controllers.current[att.id] = ac;
|
|
@@ -4004,14 +4253,14 @@ function useStagedFiles(upload, opts) {
|
|
|
4004
4253
|
delete controllers.current[att.id];
|
|
4005
4254
|
});
|
|
4006
4255
|
}, [upload]);
|
|
4007
|
-
const add =
|
|
4256
|
+
const add = React24.useCallback((files) => {
|
|
4008
4257
|
if (!upload) return [];
|
|
4009
4258
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
4010
4259
|
setItems((list) => list.concat(atts));
|
|
4011
4260
|
atts.forEach(run);
|
|
4012
4261
|
return atts;
|
|
4013
4262
|
}, [upload, run]);
|
|
4014
|
-
const remove =
|
|
4263
|
+
const remove = React24.useCallback((att) => {
|
|
4015
4264
|
const ac = controllers.current[att.id];
|
|
4016
4265
|
if (ac) {
|
|
4017
4266
|
try {
|
|
@@ -4022,10 +4271,10 @@ function useStagedFiles(upload, opts) {
|
|
|
4022
4271
|
}
|
|
4023
4272
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
4024
4273
|
}, []);
|
|
4025
|
-
const retry =
|
|
4274
|
+
const retry = React24.useCallback((att) => {
|
|
4026
4275
|
run(att);
|
|
4027
4276
|
}, [run]);
|
|
4028
|
-
const clear =
|
|
4277
|
+
const clear = React24.useCallback(() => {
|
|
4029
4278
|
Object.values(controllers.current).forEach((ac) => {
|
|
4030
4279
|
try {
|
|
4031
4280
|
ac && ac.abort();
|
|
@@ -4041,7 +4290,7 @@ function useStagedFiles(upload, opts) {
|
|
|
4041
4290
|
var DropzoneKit = { useStagedFiles };
|
|
4042
4291
|
|
|
4043
4292
|
// src/components/forms/FileGrid.tsx
|
|
4044
|
-
var
|
|
4293
|
+
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
4045
4294
|
var truncateMiddle = (name, max = 34) => {
|
|
4046
4295
|
if (!name || name.length <= max) return name;
|
|
4047
4296
|
const ext = /\.[A-Za-z0-9]+$/.exec(name);
|
|
@@ -4050,7 +4299,7 @@ var truncateMiddle = (name, max = 34) => {
|
|
|
4050
4299
|
return head + "\u2026" + tail;
|
|
4051
4300
|
};
|
|
4052
4301
|
function Progress({ value }) {
|
|
4053
|
-
return /* @__PURE__ */ (0,
|
|
4302
|
+
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
4303
|
}
|
|
4055
4304
|
function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false, className = "" }) {
|
|
4056
4305
|
if (!file) return null;
|
|
@@ -4059,8 +4308,8 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
4059
4308
|
const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
|
|
4060
4309
|
const meta = file.meta || (file.size ? formatBytes(file.size) : "");
|
|
4061
4310
|
const clickable = !!onOpen && !uploading;
|
|
4062
|
-
return /* @__PURE__ */ (0,
|
|
4063
|
-
/* @__PURE__ */ (0,
|
|
4311
|
+
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: [
|
|
4312
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
4064
4313
|
"button",
|
|
4065
4314
|
{
|
|
4066
4315
|
type: "button",
|
|
@@ -4069,16 +4318,16 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
4069
4318
|
onClick: clickable ? () => onOpen(file) : void 0,
|
|
4070
4319
|
title: file.name + (meta ? " \xB7 " + meta : ""),
|
|
4071
4320
|
children: [
|
|
4072
|
-
/* @__PURE__ */ (0,
|
|
4073
|
-
thumb ? /* @__PURE__ */ (0,
|
|
4074
|
-
(file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0,
|
|
4321
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-file-icon", children: [
|
|
4322
|
+
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" }),
|
|
4323
|
+
(file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-play fd-file-play", "aria-hidden": "true" }) : null
|
|
4075
4324
|
] }),
|
|
4076
|
-
/* @__PURE__ */ (0,
|
|
4077
|
-
/* @__PURE__ */ (0,
|
|
4078
|
-
/* @__PURE__ */ (0,
|
|
4079
|
-
/* @__PURE__ */ (0,
|
|
4325
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-file-text", children: [
|
|
4326
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-file-name", children: truncateMiddle(file.name, compact3 ? 26 : 40) }),
|
|
4327
|
+
/* @__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: [
|
|
4328
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
4080
4329
|
file.error
|
|
4081
|
-
] }) : uploading ? /* @__PURE__ */ (0,
|
|
4330
|
+
] }) : uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-tabular", children: [
|
|
4082
4331
|
Math.round(file.progress),
|
|
4083
4332
|
"% uploaded"
|
|
4084
4333
|
] }) : meta })
|
|
@@ -4086,29 +4335,29 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
4086
4335
|
]
|
|
4087
4336
|
}
|
|
4088
4337
|
),
|
|
4089
|
-
uploading ? /* @__PURE__ */ (0,
|
|
4090
|
-
file.error && onRetry ? /* @__PURE__ */ (0,
|
|
4091
|
-
onRemove ? /* @__PURE__ */ (0,
|
|
4338
|
+
uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Progress, { value: file.progress }) : null,
|
|
4339
|
+
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,
|
|
4340
|
+
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
4341
|
] });
|
|
4093
4342
|
}
|
|
4094
4343
|
function FileTile({ file, onOpen, onRemove, maxHeight = 200, className = "" }) {
|
|
4095
4344
|
if (!file) return null;
|
|
4096
4345
|
const src = file.thumb && file.thumb.url || file.blobUrl || file.url;
|
|
4097
4346
|
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,
|
|
4347
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("figure", { className: ["fd-tile", uploading ? "is-uploading" : "", file.error ? "is-error" : "", className].filter(Boolean).join(" "), children: [
|
|
4348
|
+
/* @__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" }) }) }),
|
|
4349
|
+
uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Progress, { value: file.progress }) : null,
|
|
4350
|
+
file.error ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("figcaption", { className: "fd-tile-err", children: [
|
|
4351
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
4103
4352
|
file.error
|
|
4104
4353
|
] }) : null,
|
|
4105
|
-
onRemove ? /* @__PURE__ */ (0,
|
|
4354
|
+
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
4355
|
] });
|
|
4107
4356
|
}
|
|
4108
4357
|
function FileStrip({ files = [], size = 68, onOpen, onRemove, onRetry, className = "" }) {
|
|
4109
4358
|
const list = files.filter(Boolean);
|
|
4110
4359
|
if (!list.length) return null;
|
|
4111
|
-
return /* @__PURE__ */ (0,
|
|
4360
|
+
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
4361
|
}
|
|
4113
4362
|
var shortName = (name, keep = 5) => {
|
|
4114
4363
|
const s = String(name || "file");
|
|
@@ -4122,19 +4371,19 @@ function FileCell({ file, onOpen, onRemove, onRetry }) {
|
|
|
4122
4371
|
const image = isImage(file.mime, file.name);
|
|
4123
4372
|
const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
|
|
4124
4373
|
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,
|
|
4374
|
+
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: [
|
|
4375
|
+
/* @__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: [
|
|
4376
|
+
thumb ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("img", { src: thumb, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-cell-doc", children: [
|
|
4377
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
|
|
4378
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-cell-name", children: shortName(file.name) }),
|
|
4379
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-cell-size", children: file.meta || formatBytes(file.size) })
|
|
4131
4380
|
] }),
|
|
4132
|
-
(file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0,
|
|
4381
|
+
(file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-play fd-cell-play", "aria-hidden": "true" }) : null
|
|
4133
4382
|
] }),
|
|
4134
|
-
uploading ? /* @__PURE__ */ (0,
|
|
4135
|
-
file.error ? /* @__PURE__ */ (0,
|
|
4136
|
-
file.error && onRetry ? /* @__PURE__ */ (0,
|
|
4137
|
-
onRemove ? /* @__PURE__ */ (0,
|
|
4383
|
+
uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Progress, { value: file.progress }) : null,
|
|
4384
|
+
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,
|
|
4385
|
+
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,
|
|
4386
|
+
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
4387
|
] });
|
|
4139
4388
|
}
|
|
4140
4389
|
function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeight = 200, compact: compact3 = false, className = "" }) {
|
|
@@ -4142,15 +4391,15 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
4142
4391
|
if (!list.length) return null;
|
|
4143
4392
|
const pics = tiles ? list.filter((f) => isImage(f.mime, f.name)) : [];
|
|
4144
4393
|
const rest = list.filter((f) => pics.indexOf(f) === -1);
|
|
4145
|
-
return /* @__PURE__ */ (0,
|
|
4146
|
-
pics.length ? /* @__PURE__ */ (0,
|
|
4147
|
-
rest.length ? /* @__PURE__ */ (0,
|
|
4394
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: ["fd-filegrid", className].filter(Boolean).join(" "), children: [
|
|
4395
|
+
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,
|
|
4396
|
+
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
4397
|
] });
|
|
4149
4398
|
}
|
|
4150
4399
|
|
|
4151
4400
|
// src/components/forms/MarkdownEditor.tsx
|
|
4152
|
-
var
|
|
4153
|
-
var
|
|
4401
|
+
var React25 = __toESM(require("react"), 1);
|
|
4402
|
+
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
4154
4403
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
4155
4404
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
4156
4405
|
function inlineParts(text) {
|
|
@@ -4363,7 +4612,7 @@ function syncDom(root, value) {
|
|
|
4363
4612
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
4364
4613
|
}
|
|
4365
4614
|
var LIST_CONT = RE_LI;
|
|
4366
|
-
var MarkdownEditor =
|
|
4615
|
+
var MarkdownEditor = React25.forwardRef(function MarkdownEditor2({
|
|
4367
4616
|
value = "",
|
|
4368
4617
|
onChange,
|
|
4369
4618
|
onSubmit,
|
|
@@ -4382,10 +4631,10 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4382
4631
|
className = "",
|
|
4383
4632
|
id
|
|
4384
4633
|
}, ref) {
|
|
4385
|
-
const boxRef =
|
|
4386
|
-
const composing =
|
|
4387
|
-
const pendingCaret =
|
|
4388
|
-
|
|
4634
|
+
const boxRef = React25.useRef(null);
|
|
4635
|
+
const composing = React25.useRef(false);
|
|
4636
|
+
const pendingCaret = React25.useRef(null);
|
|
4637
|
+
React25.useLayoutEffect(() => {
|
|
4389
4638
|
const root = boxRef.current;
|
|
4390
4639
|
if (!root || composing.current) return;
|
|
4391
4640
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -4394,7 +4643,7 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4394
4643
|
pendingCaret.current = null;
|
|
4395
4644
|
if (active && caret != null) placeCaret(root, caret);
|
|
4396
4645
|
}, [value]);
|
|
4397
|
-
|
|
4646
|
+
React25.useEffect(() => {
|
|
4398
4647
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
4399
4648
|
}, [autoFocus]);
|
|
4400
4649
|
const caretNow = () => {
|
|
@@ -4461,7 +4710,7 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4461
4710
|
api.replaceRange(from, to, next, from + next.length);
|
|
4462
4711
|
}
|
|
4463
4712
|
};
|
|
4464
|
-
|
|
4713
|
+
React25.useImperativeHandle(ref, () => api);
|
|
4465
4714
|
function detect(text, caret) {
|
|
4466
4715
|
if (!onTrigger) return;
|
|
4467
4716
|
const upto = text.slice(0, caret);
|
|
@@ -4574,8 +4823,8 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4574
4823
|
api.replaceRange(s.start, s.end, text.replace(/\r\n?/g, "\n"));
|
|
4575
4824
|
};
|
|
4576
4825
|
const lh = 1.55;
|
|
4577
|
-
return /* @__PURE__ */ (0,
|
|
4578
|
-
/* @__PURE__ */ (0,
|
|
4826
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: ["fd-rme-wrap", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "), children: [
|
|
4827
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4579
4828
|
"div",
|
|
4580
4829
|
{
|
|
4581
4830
|
ref: boxRef,
|
|
@@ -4608,15 +4857,15 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4608
4857
|
}
|
|
4609
4858
|
}
|
|
4610
4859
|
),
|
|
4611
|
-
!value ? /* @__PURE__ */ (0,
|
|
4860
|
+
!value ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-rme-ph", "aria-hidden": "true", children: placeholder }) : null
|
|
4612
4861
|
] });
|
|
4613
4862
|
});
|
|
4614
4863
|
|
|
4615
4864
|
// src/components/platform/AccountMenu.tsx
|
|
4616
|
-
var
|
|
4865
|
+
var React27 = __toESM(require("react"), 1);
|
|
4617
4866
|
|
|
4618
4867
|
// src/kits/session.ts
|
|
4619
|
-
var
|
|
4868
|
+
var React26 = __toESM(require("react"), 1);
|
|
4620
4869
|
var PERMISSION_CATALOG = [
|
|
4621
4870
|
{ group: "Plans", items: [
|
|
4622
4871
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -6183,8 +6432,8 @@ function roadmap(overrides) {
|
|
|
6183
6432
|
};
|
|
6184
6433
|
}
|
|
6185
6434
|
function useSession() {
|
|
6186
|
-
const [s, setS] =
|
|
6187
|
-
|
|
6435
|
+
const [s, setS] = React26.useState(getSession);
|
|
6436
|
+
React26.useEffect(() => subscribe(setS), []);
|
|
6188
6437
|
return s;
|
|
6189
6438
|
}
|
|
6190
6439
|
var SessionKit = {
|
|
@@ -6217,7 +6466,7 @@ var SessionKit = {
|
|
|
6217
6466
|
};
|
|
6218
6467
|
|
|
6219
6468
|
// src/components/platform/AccountMenu.tsx
|
|
6220
|
-
var
|
|
6469
|
+
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
6221
6470
|
var DEFAULT_LINKS = [
|
|
6222
6471
|
{ id: "profile", label: "Your profile", icon: "user-circle", href: "../admin/index.html#profile" },
|
|
6223
6472
|
{ id: "preferences", label: "Preferences", icon: "sliders-horizontal", href: "../admin/index.html#preferences" }
|
|
@@ -6228,7 +6477,7 @@ var DEFAULT_ADMIN_LINKS = [
|
|
|
6228
6477
|
{ id: "flags", label: "Feature flags", icon: "toggle-right", href: "../admin/index.html#flags", perm: "flags.manage" }
|
|
6229
6478
|
];
|
|
6230
6479
|
function Item({ item, onPick }) {
|
|
6231
|
-
return /* @__PURE__ */ (0,
|
|
6480
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
|
|
6232
6481
|
"button",
|
|
6233
6482
|
{
|
|
6234
6483
|
type: "button",
|
|
@@ -6236,9 +6485,9 @@ function Item({ item, onPick }) {
|
|
|
6236
6485
|
className: "fd-acct-item",
|
|
6237
6486
|
onClick: () => onPick(item),
|
|
6238
6487
|
children: [
|
|
6239
|
-
/* @__PURE__ */ (0,
|
|
6240
|
-
/* @__PURE__ */ (0,
|
|
6241
|
-
item.badge ? /* @__PURE__ */ (0,
|
|
6488
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }),
|
|
6489
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { flex: 1 }, children: item.label }),
|
|
6490
|
+
item.badge ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Badge, { tone: "neutral", children: item.badge }) : null
|
|
6242
6491
|
]
|
|
6243
6492
|
}
|
|
6244
6493
|
);
|
|
@@ -6254,9 +6503,9 @@ function AccountMenu({
|
|
|
6254
6503
|
...rest
|
|
6255
6504
|
}) {
|
|
6256
6505
|
const session = SessionKit.useSession();
|
|
6257
|
-
const [open, setOpen] =
|
|
6258
|
-
const [switching, setSwitching] =
|
|
6259
|
-
const ref =
|
|
6506
|
+
const [open, setOpen] = React27.useState(false);
|
|
6507
|
+
const [switching, setSwitching] = React27.useState(false);
|
|
6508
|
+
const ref = React27.useRef(null);
|
|
6260
6509
|
const user = session.user;
|
|
6261
6510
|
const visibleAdmin = adminLinks.filter((l) => !l.perm || SessionKit.can(l.perm));
|
|
6262
6511
|
const pick = (item) => {
|
|
@@ -6270,8 +6519,8 @@ function AccountMenu({
|
|
|
6270
6519
|
if (onSignOut) return onSignOut();
|
|
6271
6520
|
window.alert("Signed out. (Simulated \u2014 no auth provider is wired up.)");
|
|
6272
6521
|
};
|
|
6273
|
-
return /* @__PURE__ */ (0,
|
|
6274
|
-
/* @__PURE__ */ (0,
|
|
6522
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
|
|
6523
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
|
|
6275
6524
|
"button",
|
|
6276
6525
|
{
|
|
6277
6526
|
type: "button",
|
|
@@ -6283,32 +6532,32 @@ function AccountMenu({
|
|
|
6283
6532
|
onClick: () => setOpen((o) => !o),
|
|
6284
6533
|
...rest,
|
|
6285
6534
|
children: [
|
|
6286
|
-
/* @__PURE__ */ (0,
|
|
6287
|
-
/* @__PURE__ */ (0,
|
|
6535
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Avatar, { name: user.name, size: "sm" }),
|
|
6536
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
|
|
6288
6537
|
]
|
|
6289
6538
|
}
|
|
6290
6539
|
),
|
|
6291
|
-
/* @__PURE__ */ (0,
|
|
6292
|
-
/* @__PURE__ */ (0,
|
|
6293
|
-
/* @__PURE__ */ (0,
|
|
6294
|
-
/* @__PURE__ */ (0,
|
|
6295
|
-
/* @__PURE__ */ (0,
|
|
6296
|
-
/* @__PURE__ */ (0,
|
|
6540
|
+
/* @__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: [
|
|
6541
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
6542
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Avatar, { name: user.name }),
|
|
6543
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
|
|
6544
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
|
|
6545
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-body-sm fd-muted fd-table-trunc", children: user.email })
|
|
6297
6546
|
] })
|
|
6298
6547
|
] }),
|
|
6299
|
-
showRoles && session.roles.length ? /* @__PURE__ */ (0,
|
|
6300
|
-
/* @__PURE__ */ (0,
|
|
6301
|
-
visibleAdmin.length ? /* @__PURE__ */ (0,
|
|
6302
|
-
/* @__PURE__ */ (0,
|
|
6303
|
-
visibleAdmin.map((l) => /* @__PURE__ */ (0,
|
|
6548
|
+
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,
|
|
6549
|
+
/* @__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)) }),
|
|
6550
|
+
visibleAdmin.length ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
6551
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: "Administration" }),
|
|
6552
|
+
visibleAdmin.map((l) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Item, { item: l, onPick: pick }, l.id))
|
|
6304
6553
|
] }) : null,
|
|
6305
|
-
allowUserSwitch ? /* @__PURE__ */ (0,
|
|
6306
|
-
/* @__PURE__ */ (0,
|
|
6307
|
-
/* @__PURE__ */ (0,
|
|
6308
|
-
/* @__PURE__ */ (0,
|
|
6309
|
-
/* @__PURE__ */ (0,
|
|
6554
|
+
allowUserSwitch ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
6555
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
|
|
6556
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
|
|
6557
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
|
|
6558
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
|
|
6310
6559
|
] }),
|
|
6311
|
-
switching ? /* @__PURE__ */ (0,
|
|
6560
|
+
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
6561
|
"button",
|
|
6313
6562
|
{
|
|
6314
6563
|
type: "button",
|
|
@@ -6320,34 +6569,34 @@ function AccountMenu({
|
|
|
6320
6569
|
setSwitching(false);
|
|
6321
6570
|
},
|
|
6322
6571
|
children: [
|
|
6323
|
-
/* @__PURE__ */ (0,
|
|
6324
|
-
/* @__PURE__ */ (0,
|
|
6325
|
-
/* @__PURE__ */ (0,
|
|
6326
|
-
/* @__PURE__ */ (0,
|
|
6572
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Avatar, { name: u.name, size: "sm" }),
|
|
6573
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
|
|
6574
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
|
|
6575
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") })
|
|
6327
6576
|
] }),
|
|
6328
|
-
u.id === user.id ? /* @__PURE__ */ (0,
|
|
6577
|
+
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
6578
|
]
|
|
6330
6579
|
},
|
|
6331
6580
|
u.id
|
|
6332
6581
|
)) }) : null
|
|
6333
6582
|
] }) : null,
|
|
6334
|
-
/* @__PURE__ */ (0,
|
|
6335
|
-
/* @__PURE__ */ (0,
|
|
6336
|
-
/* @__PURE__ */ (0,
|
|
6583
|
+
/* @__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: [
|
|
6584
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
|
|
6585
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { flex: 1 }, children: "Sign out" })
|
|
6337
6586
|
] }) })
|
|
6338
6587
|
] }) })
|
|
6339
6588
|
] });
|
|
6340
6589
|
}
|
|
6341
6590
|
|
|
6342
6591
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
6343
|
-
var
|
|
6344
|
-
var
|
|
6592
|
+
var React28 = __toESM(require("react"), 1);
|
|
6593
|
+
var import_jsx_runtime57 = require("react/jsx-runtime");
|
|
6345
6594
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
6346
6595
|
function Json({ obj }) {
|
|
6347
|
-
return /* @__PURE__ */ (0,
|
|
6596
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
6348
6597
|
}
|
|
6349
6598
|
function Endpoint({ s, onRequest }) {
|
|
6350
|
-
const [tried, setTried] =
|
|
6599
|
+
const [tried, setTried] = React28.useState(null);
|
|
6351
6600
|
const run = async () => {
|
|
6352
6601
|
setTried("busy");
|
|
6353
6602
|
const t0 = (window.performance || Date).now();
|
|
@@ -6358,50 +6607,50 @@ function Endpoint({ s, onRequest }) {
|
|
|
6358
6607
|
setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
|
|
6359
6608
|
}
|
|
6360
6609
|
};
|
|
6361
|
-
return /* @__PURE__ */ (0,
|
|
6362
|
-
/* @__PURE__ */ (0,
|
|
6363
|
-
/* @__PURE__ */ (0,
|
|
6364
|
-
/* @__PURE__ */ (0,
|
|
6365
|
-
s.isList ? /* @__PURE__ */ (0,
|
|
6366
|
-
/* @__PURE__ */ (0,
|
|
6367
|
-
/* @__PURE__ */ (0,
|
|
6610
|
+
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: [
|
|
6611
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
|
|
6612
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
|
|
6613
|
+
/* @__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 }),
|
|
6614
|
+
s.isList ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
|
|
6615
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { style: { flex: 1 } }),
|
|
6616
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
6368
6617
|
s.latency[0],
|
|
6369
6618
|
"\u2013",
|
|
6370
6619
|
s.latency[1],
|
|
6371
6620
|
"ms"
|
|
6372
6621
|
] }),
|
|
6373
|
-
/* @__PURE__ */ (0,
|
|
6622
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
|
|
6374
6623
|
] }),
|
|
6375
|
-
/* @__PURE__ */ (0,
|
|
6376
|
-
/* @__PURE__ */ (0,
|
|
6377
|
-
/* @__PURE__ */ (0,
|
|
6378
|
-
/* @__PURE__ */ (0,
|
|
6379
|
-
s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0,
|
|
6624
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
|
|
6625
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6626
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
|
|
6627
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
|
|
6628
|
+
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
6629
|
] }),
|
|
6381
|
-
/* @__PURE__ */ (0,
|
|
6382
|
-
s.request ? /* @__PURE__ */ (0,
|
|
6383
|
-
/* @__PURE__ */ (0,
|
|
6384
|
-
/* @__PURE__ */ (0,
|
|
6630
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
|
|
6631
|
+
s.request ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6632
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Request body" }),
|
|
6633
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: s.request })
|
|
6385
6634
|
] }) : null,
|
|
6386
|
-
s.query ? /* @__PURE__ */ (0,
|
|
6387
|
-
/* @__PURE__ */ (0,
|
|
6388
|
-
/* @__PURE__ */ (0,
|
|
6635
|
+
s.query ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6636
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Query" }),
|
|
6637
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: s.query })
|
|
6389
6638
|
] }) : null,
|
|
6390
|
-
/* @__PURE__ */ (0,
|
|
6391
|
-
/* @__PURE__ */ (0,
|
|
6392
|
-
/* @__PURE__ */ (0,
|
|
6639
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6640
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Response 200" }),
|
|
6641
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: s.response })
|
|
6393
6642
|
] })
|
|
6394
6643
|
] }),
|
|
6395
|
-
s.notes ? /* @__PURE__ */ (0,
|
|
6396
|
-
tried && tried !== "busy" ? /* @__PURE__ */ (0,
|
|
6397
|
-
/* @__PURE__ */ (0,
|
|
6398
|
-
/* @__PURE__ */ (0,
|
|
6399
|
-
/* @__PURE__ */ (0,
|
|
6644
|
+
s.notes ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
|
|
6645
|
+
tried && tried !== "busy" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6646
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
6647
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
|
|
6648
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
|
|
6400
6649
|
tried.ms,
|
|
6401
6650
|
"ms"
|
|
6402
6651
|
] })
|
|
6403
6652
|
] }),
|
|
6404
|
-
/* @__PURE__ */ (0,
|
|
6653
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
|
|
6405
6654
|
] }) : null
|
|
6406
6655
|
] })
|
|
6407
6656
|
] }) });
|
|
@@ -6420,58 +6669,58 @@ function ApiSpecBrowser({
|
|
|
6420
6669
|
className = "",
|
|
6421
6670
|
...rest
|
|
6422
6671
|
}) {
|
|
6423
|
-
const [q, setQ] =
|
|
6424
|
-
const [method, setMethod] =
|
|
6425
|
-
const [mod, setMod] =
|
|
6426
|
-
const [listOnly, setListOnly] =
|
|
6672
|
+
const [q, setQ] = React28.useState("");
|
|
6673
|
+
const [method, setMethod] = React28.useState(null);
|
|
6674
|
+
const [mod, setMod] = React28.useState(null);
|
|
6675
|
+
const [listOnly, setListOnly] = React28.useState(false);
|
|
6427
6676
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
6428
6677
|
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
6678
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
6430
6679
|
const methods = [...new Set(spec.map((s) => s.method))];
|
|
6431
6680
|
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,
|
|
6681
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
|
|
6682
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
6683
|
+
kicker ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: kicker }) : null,
|
|
6684
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
6685
|
+
lede ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
|
|
6437
6686
|
] }),
|
|
6438
|
-
modules && modules.length ? /* @__PURE__ */ (0,
|
|
6439
|
-
/* @__PURE__ */ (0,
|
|
6440
|
-
/* @__PURE__ */ (0,
|
|
6441
|
-
/* @__PURE__ */ (0,
|
|
6687
|
+
modules && modules.length ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
6688
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
|
|
6689
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
6690
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
|
|
6442
6691
|
"All screens ",
|
|
6443
|
-
/* @__PURE__ */ (0,
|
|
6692
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: spec.length })
|
|
6444
6693
|
] }),
|
|
6445
|
-
modules.map((m) => /* @__PURE__ */ (0,
|
|
6694
|
+
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
6695
|
m.label,
|
|
6447
6696
|
" ",
|
|
6448
|
-
/* @__PURE__ */ (0,
|
|
6697
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
|
|
6449
6698
|
] }, m.id))
|
|
6450
6699
|
] }),
|
|
6451
|
-
activeModule ? /* @__PURE__ */ (0,
|
|
6700
|
+
activeModule ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
6452
6701
|
Flag,
|
|
6453
6702
|
{
|
|
6454
6703
|
tone: "info",
|
|
6455
6704
|
statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
|
|
6456
6705
|
cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
|
|
6457
|
-
actions: /* @__PURE__ */ (0,
|
|
6706
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
|
|
6458
6707
|
}
|
|
6459
6708
|
) : null
|
|
6460
6709
|
] }) : null,
|
|
6461
|
-
sourceNote ? /* @__PURE__ */ (0,
|
|
6462
|
-
/* @__PURE__ */ (0,
|
|
6463
|
-
/* @__PURE__ */ (0,
|
|
6464
|
-
methods.map((m) => /* @__PURE__ */ (0,
|
|
6710
|
+
sourceNote ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
|
|
6711
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
6712
|
+
/* @__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 } }),
|
|
6713
|
+
methods.map((m) => /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
|
|
6465
6714
|
m,
|
|
6466
6715
|
" ",
|
|
6467
|
-
/* @__PURE__ */ (0,
|
|
6716
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
|
|
6468
6717
|
] }, m)),
|
|
6469
|
-
listCount ? /* @__PURE__ */ (0,
|
|
6718
|
+
listCount ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
|
|
6470
6719
|
"Paged lists ",
|
|
6471
|
-
/* @__PURE__ */ (0,
|
|
6720
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: listCount })
|
|
6472
6721
|
] }) : null,
|
|
6473
|
-
/* @__PURE__ */ (0,
|
|
6474
|
-
/* @__PURE__ */ (0,
|
|
6722
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { style: { flex: 1 } }),
|
|
6723
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
6475
6724
|
hits.length,
|
|
6476
6725
|
" of ",
|
|
6477
6726
|
spec.length,
|
|
@@ -6479,31 +6728,31 @@ function ApiSpecBrowser({
|
|
|
6479
6728
|
listCount ? " \xB7 " + listCount + " paged" : ""
|
|
6480
6729
|
] })
|
|
6481
6730
|
] }),
|
|
6482
|
-
hits.length === 0 ? /* @__PURE__ */ (0,
|
|
6731
|
+
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
6732
|
const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
|
|
6484
6733
|
if (!items.length) return null;
|
|
6485
|
-
return /* @__PURE__ */ (0,
|
|
6486
|
-
/* @__PURE__ */ (0,
|
|
6487
|
-
items.map((s) => /* @__PURE__ */ (0,
|
|
6734
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 12 }, children: [
|
|
6735
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-label-lg", children: g }),
|
|
6736
|
+
items.map((s) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Endpoint, { s, onRequest }, s.id))
|
|
6488
6737
|
] }, g);
|
|
6489
6738
|
}),
|
|
6490
|
-
conventions && conventions.length ? /* @__PURE__ */ (0,
|
|
6491
|
-
/* @__PURE__ */ (0,
|
|
6492
|
-
/* @__PURE__ */ (0,
|
|
6739
|
+
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: [
|
|
6740
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
|
|
6741
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
|
|
6493
6742
|
] }, k)) }) }) : null,
|
|
6494
|
-
openQuestions && openQuestions.length ? /* @__PURE__ */ (0,
|
|
6495
|
-
/* @__PURE__ */ (0,
|
|
6496
|
-
/* @__PURE__ */ (0,
|
|
6497
|
-
/* @__PURE__ */ (0,
|
|
6498
|
-
/* @__PURE__ */ (0,
|
|
6743
|
+
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: [
|
|
6744
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Badge, { tone: "danger", children: id }),
|
|
6745
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
|
|
6746
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
|
|
6747
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-body-sm fd-muted", children: why })
|
|
6499
6748
|
] })
|
|
6500
6749
|
] }, id)) }) }) : null
|
|
6501
6750
|
] });
|
|
6502
6751
|
}
|
|
6503
6752
|
|
|
6504
6753
|
// src/components/platform/ProfilePage.tsx
|
|
6505
|
-
var
|
|
6506
|
-
var
|
|
6754
|
+
var React29 = __toESM(require("react"), 1);
|
|
6755
|
+
var import_jsx_runtime58 = require("react/jsx-runtime");
|
|
6507
6756
|
var TIMEZONES = ["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles", "America/Anchorage", "Pacific/Honolulu", "Europe/London", "Europe/Berlin"];
|
|
6508
6757
|
var NOTIFY = [
|
|
6509
6758
|
{ key: "planShared", label: "A plan is shared with me", detail: "Someone sends you a plan or a client link." },
|
|
@@ -6515,7 +6764,7 @@ var NOTIFY = [
|
|
|
6515
6764
|
function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSessions = true, className = "", ...rest }) {
|
|
6516
6765
|
const session = SessionKit.useSession();
|
|
6517
6766
|
const user = userProp || session.user;
|
|
6518
|
-
const [draft, setDraft] =
|
|
6767
|
+
const [draft, setDraft] = React29.useState(() => ({
|
|
6519
6768
|
name: user.name || "",
|
|
6520
6769
|
title: user.title || "",
|
|
6521
6770
|
email: user.email || "",
|
|
@@ -6524,8 +6773,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6524
6773
|
bio: user.bio || "",
|
|
6525
6774
|
notify: user.notify || { planShared: true, planChanged: true, goalMissed: true, flagChanged: false, weekly: true }
|
|
6526
6775
|
}));
|
|
6527
|
-
const [saving, setSaving] =
|
|
6528
|
-
const [saved, setSaved] =
|
|
6776
|
+
const [saving, setSaving] = React29.useState(false);
|
|
6777
|
+
const [saved, setSaved] = React29.useState(false);
|
|
6529
6778
|
const set = (k, v) => {
|
|
6530
6779
|
setDraft((d) => Object.assign({}, d, { [k]: v }));
|
|
6531
6780
|
setSaved(false);
|
|
@@ -6547,43 +6796,43 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6547
6796
|
{ id: "s2", device: "iPhone 15 \xB7 Safari", where: "Denver, CO", when: "2 hours ago" },
|
|
6548
6797
|
{ id: "s3", device: "Windows \xB7 Edge", where: "Chicago, IL", when: "Aug 12" }
|
|
6549
6798
|
];
|
|
6550
|
-
return /* @__PURE__ */ (0,
|
|
6551
|
-
/* @__PURE__ */ (0,
|
|
6552
|
-
/* @__PURE__ */ (0,
|
|
6553
|
-
/* @__PURE__ */ (0,
|
|
6554
|
-
/* @__PURE__ */ (0,
|
|
6799
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, ...rest, children: [
|
|
6800
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
6801
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
|
|
6802
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
|
|
6803
|
+
/* @__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
6804
|
] }),
|
|
6556
|
-
/* @__PURE__ */ (0,
|
|
6557
|
-
/* @__PURE__ */ (0,
|
|
6558
|
-
/* @__PURE__ */ (0,
|
|
6559
|
-
/* @__PURE__ */ (0,
|
|
6560
|
-
/* @__PURE__ */ (0,
|
|
6805
|
+
/* @__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: [
|
|
6806
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Avatar, { name: draft.name || user.name, size: "lg" }),
|
|
6807
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
|
|
6808
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: draft.name || user.name }),
|
|
6809
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
6561
6810
|
draft.title || "No title set",
|
|
6562
6811
|
" \xB7 ",
|
|
6563
6812
|
user.team || "No team"
|
|
6564
6813
|
] }),
|
|
6565
|
-
/* @__PURE__ */ (0,
|
|
6566
|
-
session.roles.map((r) => /* @__PURE__ */ (0,
|
|
6567
|
-
user.sso ? /* @__PURE__ */ (0,
|
|
6814
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
|
|
6815
|
+
session.roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
|
|
6816
|
+
user.sso ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
|
|
6568
6817
|
] })
|
|
6569
6818
|
] }),
|
|
6570
|
-
/* @__PURE__ */ (0,
|
|
6819
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", children: "Change photo" })
|
|
6571
6820
|
] }) }),
|
|
6572
|
-
/* @__PURE__ */ (0,
|
|
6821
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6573
6822
|
Card,
|
|
6574
6823
|
{
|
|
6575
|
-
title: /* @__PURE__ */ (0,
|
|
6576
|
-
/* @__PURE__ */ (0,
|
|
6577
|
-
/* @__PURE__ */ (0,
|
|
6824
|
+
title: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
6825
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: "Identity" }),
|
|
6826
|
+
/* @__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
6827
|
] }),
|
|
6579
6828
|
elevation: "flat",
|
|
6580
|
-
children: /* @__PURE__ */ (0,
|
|
6581
|
-
/* @__PURE__ */ (0,
|
|
6582
|
-
/* @__PURE__ */ (0,
|
|
6583
|
-
/* @__PURE__ */ (0,
|
|
6829
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
|
|
6830
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
|
|
6831
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Input, { label: "Full name", value: draft.name, onChange: (e) => set("name", e.target.value) }),
|
|
6832
|
+
/* @__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
6833
|
] }),
|
|
6585
|
-
/* @__PURE__ */ (0,
|
|
6586
|
-
/* @__PURE__ */ (0,
|
|
6834
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
|
|
6835
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6587
6836
|
Input,
|
|
6588
6837
|
{
|
|
6589
6838
|
label: "Work email",
|
|
@@ -6593,9 +6842,9 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6593
6842
|
help: user.sso ? "Managed by your identity provider \u2014 change it there." : "Contact an administrator to change this."
|
|
6594
6843
|
}
|
|
6595
6844
|
),
|
|
6596
|
-
/* @__PURE__ */ (0,
|
|
6845
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Input, { label: "Phone", value: draft.phone, onChange: (e) => set("phone", e.target.value), placeholder: "Optional" })
|
|
6597
6846
|
] }),
|
|
6598
|
-
/* @__PURE__ */ (0,
|
|
6847
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6599
6848
|
Textarea,
|
|
6600
6849
|
{
|
|
6601
6850
|
label: "Short bio",
|
|
@@ -6609,8 +6858,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6609
6858
|
] })
|
|
6610
6859
|
}
|
|
6611
6860
|
),
|
|
6612
|
-
/* @__PURE__ */ (0,
|
|
6613
|
-
/* @__PURE__ */ (0,
|
|
6861
|
+
/* @__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: [
|
|
6862
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6614
6863
|
Select,
|
|
6615
6864
|
{
|
|
6616
6865
|
label: "Time zone",
|
|
@@ -6620,28 +6869,28 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6620
6869
|
help: "Flight dates and schedules render in this zone."
|
|
6621
6870
|
}
|
|
6622
6871
|
),
|
|
6623
|
-
/* @__PURE__ */ (0,
|
|
6872
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Select, { label: "Start of week", options: ["Monday", "Sunday"], placeholder: "Monday" })
|
|
6624
6873
|
] }) }),
|
|
6625
|
-
/* @__PURE__ */ (0,
|
|
6874
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6626
6875
|
Card,
|
|
6627
6876
|
{
|
|
6628
|
-
title: /* @__PURE__ */ (0,
|
|
6629
|
-
/* @__PURE__ */ (0,
|
|
6630
|
-
/* @__PURE__ */ (0,
|
|
6877
|
+
title: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
6878
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: "Notifications" }),
|
|
6879
|
+
/* @__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
6880
|
] }),
|
|
6632
6881
|
elevation: "flat",
|
|
6633
|
-
children: /* @__PURE__ */ (0,
|
|
6882
|
+
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
6883
|
}
|
|
6635
6884
|
),
|
|
6636
|
-
/* @__PURE__ */ (0,
|
|
6885
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
|
|
6637
6886
|
Card,
|
|
6638
6887
|
{
|
|
6639
|
-
title: /* @__PURE__ */ (0,
|
|
6640
|
-
/* @__PURE__ */ (0,
|
|
6641
|
-
/* @__PURE__ */ (0,
|
|
6888
|
+
title: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
6889
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: "Access" }),
|
|
6890
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
|
|
6642
6891
|
] }),
|
|
6643
6892
|
elevation: "flat",
|
|
6644
|
-
action: /* @__PURE__ */ (0,
|
|
6893
|
+
action: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6645
6894
|
Button,
|
|
6646
6895
|
{
|
|
6647
6896
|
size: "sm",
|
|
@@ -6652,39 +6901,39 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6652
6901
|
}
|
|
6653
6902
|
),
|
|
6654
6903
|
children: [
|
|
6655
|
-
/* @__PURE__ */ (0,
|
|
6656
|
-
/* @__PURE__ */ (0,
|
|
6657
|
-
/* @__PURE__ */ (0,
|
|
6904
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
6905
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(CardRow, { label: "Roles", children: session.roles.map((r) => r.name).join(", ") || "None" }),
|
|
6906
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(CardRow, { label: "Permissions", children: [
|
|
6658
6907
|
session.permissions.length,
|
|
6659
6908
|
" granted"
|
|
6660
6909
|
] }),
|
|
6661
|
-
/* @__PURE__ */ (0,
|
|
6910
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
|
|
6662
6911
|
] }),
|
|
6663
|
-
/* @__PURE__ */ (0,
|
|
6912
|
+
/* @__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
6913
|
]
|
|
6665
6914
|
}
|
|
6666
6915
|
),
|
|
6667
|
-
showSessions ? /* @__PURE__ */ (0,
|
|
6916
|
+
showSessions ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6668
6917
|
Card,
|
|
6669
6918
|
{
|
|
6670
6919
|
title: "Signed-in devices",
|
|
6671
6920
|
elevation: "flat",
|
|
6672
|
-
action: /* @__PURE__ */ (0,
|
|
6673
|
-
children: /* @__PURE__ */ (0,
|
|
6674
|
-
/* @__PURE__ */ (0,
|
|
6675
|
-
/* @__PURE__ */ (0,
|
|
6676
|
-
/* @__PURE__ */ (0,
|
|
6677
|
-
/* @__PURE__ */ (0,
|
|
6921
|
+
action: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", children: "Sign out everywhere" }),
|
|
6922
|
+
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: [
|
|
6923
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
6924
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
|
|
6925
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
|
|
6926
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
6678
6927
|
s.where,
|
|
6679
6928
|
" \xB7 ",
|
|
6680
6929
|
s.when
|
|
6681
6930
|
] })
|
|
6682
6931
|
] }),
|
|
6683
|
-
s.current ? /* @__PURE__ */ (0,
|
|
6932
|
+
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
6933
|
] }, s.id)) })
|
|
6685
6934
|
}
|
|
6686
6935
|
) : null,
|
|
6687
|
-
/* @__PURE__ */ (0,
|
|
6936
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-row", style: {
|
|
6688
6937
|
gap: 10,
|
|
6689
6938
|
flexWrap: "wrap",
|
|
6690
6939
|
position: "sticky",
|
|
@@ -6695,8 +6944,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6695
6944
|
border: "1px solid var(--border)",
|
|
6696
6945
|
boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
|
|
6697
6946
|
}, children: [
|
|
6698
|
-
/* @__PURE__ */ (0,
|
|
6699
|
-
/* @__PURE__ */ (0,
|
|
6947
|
+
/* @__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" }),
|
|
6948
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
6700
6949
|
Button,
|
|
6701
6950
|
{
|
|
6702
6951
|
size: "sm",
|
|
@@ -6709,16 +6958,16 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6709
6958
|
children: "Discard"
|
|
6710
6959
|
}
|
|
6711
6960
|
),
|
|
6712
|
-
/* @__PURE__ */ (0,
|
|
6961
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty, loading: saving, onClick: save, children: "Save changes" })
|
|
6713
6962
|
] })
|
|
6714
6963
|
] });
|
|
6715
6964
|
}
|
|
6716
6965
|
|
|
6717
6966
|
// src/components/platform/RoadmapTimeline.tsx
|
|
6718
|
-
var
|
|
6967
|
+
var React31 = __toESM(require("react"), 1);
|
|
6719
6968
|
|
|
6720
6969
|
// src/kits/runtime.ts
|
|
6721
|
-
var
|
|
6970
|
+
var React30 = __toESM(require("react"), 1);
|
|
6722
6971
|
var WIRED_ENDPOINTS = [
|
|
6723
6972
|
// Nothing yet. Every id below would come from a real service:
|
|
6724
6973
|
// "plan.get", "placements.list", …
|
|
@@ -6889,8 +7138,8 @@ var RuntimeKit = {
|
|
|
6889
7138
|
};
|
|
6890
7139
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
6891
7140
|
function useRuntimeMode() {
|
|
6892
|
-
const [m, setM] =
|
|
6893
|
-
|
|
7141
|
+
const [m, setM] = React30.useState(RuntimeKit.getMode());
|
|
7142
|
+
React30.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
6894
7143
|
return m;
|
|
6895
7144
|
}
|
|
6896
7145
|
function useFeatureStatus(key) {
|
|
@@ -6909,7 +7158,7 @@ var UseRuntimeMode = useRuntimeMode;
|
|
|
6909
7158
|
var UseFeatureStatus = useFeatureStatus;
|
|
6910
7159
|
|
|
6911
7160
|
// src/components/platform/RoadmapTimeline.tsx
|
|
6912
|
-
var
|
|
7161
|
+
var import_jsx_runtime59 = require("react/jsx-runtime");
|
|
6913
7162
|
var STATUS = {
|
|
6914
7163
|
shipped: { tone: "success", icon: "check-circle", label: "Wired" },
|
|
6915
7164
|
next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
|
|
@@ -6924,45 +7173,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
6924
7173
|
const s = STATUS[item.status] || STATUS.planned;
|
|
6925
7174
|
const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
|
|
6926
7175
|
const blocking = deps.filter((d) => !d.implemented);
|
|
6927
|
-
return /* @__PURE__ */ (0,
|
|
6928
|
-
/* @__PURE__ */ (0,
|
|
6929
|
-
/* @__PURE__ */ (0,
|
|
6930
|
-
/* @__PURE__ */ (0,
|
|
6931
|
-
/* @__PURE__ */ (0,
|
|
7176
|
+
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: [
|
|
7177
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
7178
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
|
|
7179
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
|
|
7180
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Badge, { tone: s.tone, icon: s.icon, children: s.label })
|
|
6932
7181
|
] }),
|
|
6933
|
-
/* @__PURE__ */ (0,
|
|
6934
|
-
item.backend ? /* @__PURE__ */ (0,
|
|
6935
|
-
/* @__PURE__ */ (0,
|
|
6936
|
-
/* @__PURE__ */ (0,
|
|
7182
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
|
|
7183
|
+
item.backend ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
|
|
7184
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
|
|
7185
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
|
|
6937
7186
|
] }) : null,
|
|
6938
|
-
/* @__PURE__ */ (0,
|
|
6939
|
-
item.effort ? /* @__PURE__ */ (0,
|
|
6940
|
-
/* @__PURE__ */ (0,
|
|
7187
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
7188
|
+
item.effort ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
7189
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-hourglass-medium" }),
|
|
6941
7190
|
" ",
|
|
6942
7191
|
item.effort
|
|
6943
7192
|
] }) : null,
|
|
6944
|
-
/* @__PURE__ */ (0,
|
|
6945
|
-
/* @__PURE__ */ (0,
|
|
7193
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
7194
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-user" }),
|
|
6946
7195
|
" ",
|
|
6947
7196
|
item.owner
|
|
6948
7197
|
] }),
|
|
6949
|
-
item.screen ? /* @__PURE__ */ (0,
|
|
6950
|
-
/* @__PURE__ */ (0,
|
|
6951
|
-
/* @__PURE__ */ (0,
|
|
7198
|
+
item.screen ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
|
|
7199
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { flex: 1 } }),
|
|
7200
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
6952
7201
|
"button",
|
|
6953
7202
|
{
|
|
6954
7203
|
type: "button",
|
|
6955
7204
|
onClick: () => onOpenFlag && onOpenFlag(item.key),
|
|
6956
7205
|
style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
|
|
6957
|
-
children: /* @__PURE__ */ (0,
|
|
7206
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
|
|
6958
7207
|
}
|
|
6959
7208
|
)
|
|
6960
7209
|
] }),
|
|
6961
|
-
deps.length ? /* @__PURE__ */ (0,
|
|
6962
|
-
/* @__PURE__ */ (0,
|
|
6963
|
-
deps.map((d) => /* @__PURE__ */ (0,
|
|
7210
|
+
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: [
|
|
7211
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
|
|
7212
|
+
deps.map((d) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
|
|
6964
7213
|
] }) : null,
|
|
6965
|
-
blocking.length && !item.implemented ? /* @__PURE__ */ (0,
|
|
7214
|
+
blocking.length && !item.implemented ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
|
|
6966
7215
|
"Blocked until ",
|
|
6967
7216
|
blocking.map((d) => d.label).join(" and "),
|
|
6968
7217
|
" ",
|
|
@@ -6973,12 +7222,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
6973
7222
|
}
|
|
6974
7223
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
6975
7224
|
const session = SessionKit.useSession();
|
|
6976
|
-
const [project, setProject] =
|
|
6977
|
-
const [q, setQ] =
|
|
6978
|
-
const scrollRef =
|
|
6979
|
-
const nowRef =
|
|
6980
|
-
const rm =
|
|
6981
|
-
const byKey =
|
|
7225
|
+
const [project, setProject] = React31.useState("");
|
|
7226
|
+
const [q, setQ] = React31.useState("");
|
|
7227
|
+
const scrollRef = React31.useRef(null);
|
|
7228
|
+
const nowRef = React31.useRef(null);
|
|
7229
|
+
const rm = React31.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
7230
|
+
const byKey = React31.useMemo(() => {
|
|
6982
7231
|
const m = {};
|
|
6983
7232
|
rm.items.forEach((i) => {
|
|
6984
7233
|
m[i.key] = i;
|
|
@@ -6987,7 +7236,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
6987
7236
|
}, [rm]);
|
|
6988
7237
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
6989
7238
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
6990
|
-
|
|
7239
|
+
React31.useEffect(() => {
|
|
6991
7240
|
let raf1 = 0, raf2 = 0;
|
|
6992
7241
|
const place = () => {
|
|
6993
7242
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -7015,23 +7264,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7015
7264
|
}, 0);
|
|
7016
7265
|
const nextPhase = items.find((i) => !i.implemented);
|
|
7017
7266
|
let lastPhase = null;
|
|
7018
|
-
return /* @__PURE__ */ (0,
|
|
7019
|
-
/* @__PURE__ */ (0,
|
|
7020
|
-
/* @__PURE__ */ (0,
|
|
7021
|
-
/* @__PURE__ */ (0,
|
|
7022
|
-
/* @__PURE__ */ (0,
|
|
7267
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
|
|
7268
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
7269
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", children: "Architecture" }),
|
|
7270
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
7271
|
+
/* @__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
7272
|
] }),
|
|
7024
|
-
/* @__PURE__ */ (0,
|
|
7025
|
-
/* @__PURE__ */ (0,
|
|
7026
|
-
/* @__PURE__ */ (0,
|
|
7027
|
-
/* @__PURE__ */ (0,
|
|
7028
|
-
/* @__PURE__ */ (0,
|
|
7273
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-grid-stats is-thin", children: [
|
|
7274
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
|
|
7275
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
|
|
7276
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
|
|
7277
|
+
/* @__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
7278
|
] }),
|
|
7030
|
-
/* @__PURE__ */ (0,
|
|
7031
|
-
/* @__PURE__ */ (0,
|
|
7032
|
-
/* @__PURE__ */ (0,
|
|
7033
|
-
/* @__PURE__ */ (0,
|
|
7034
|
-
/* @__PURE__ */ (0,
|
|
7279
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
7280
|
+
/* @__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 } }),
|
|
7281
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
|
|
7282
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { flex: 1 } }),
|
|
7283
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
7035
7284
|
Button,
|
|
7036
7285
|
{
|
|
7037
7286
|
size: "sm",
|
|
@@ -7045,7 +7294,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7045
7294
|
}
|
|
7046
7295
|
)
|
|
7047
7296
|
] }),
|
|
7048
|
-
/* @__PURE__ */ (0,
|
|
7297
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
7049
7298
|
Flag,
|
|
7050
7299
|
{
|
|
7051
7300
|
tone: "info",
|
|
@@ -7054,60 +7303,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7054
7303
|
actions: null
|
|
7055
7304
|
}
|
|
7056
7305
|
),
|
|
7057
|
-
/* @__PURE__ */ (0,
|
|
7058
|
-
/* @__PURE__ */ (0,
|
|
7306
|
+
/* @__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: [
|
|
7307
|
+
/* @__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
7308
|
items.map((item, n) => {
|
|
7060
7309
|
const showPhase = item.phase !== lastPhase;
|
|
7061
7310
|
lastPhase = item.phase;
|
|
7062
7311
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
7063
7312
|
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,
|
|
7313
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React31.Fragment, { children: [
|
|
7314
|
+
showPhase ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-rm-era", children: [
|
|
7315
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
7316
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
7317
|
+
item.phase === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
7069
7318
|
fmtDate(item.phaseStart),
|
|
7070
7319
|
" \u2013 ",
|
|
7071
7320
|
fmtDate(item.date)
|
|
7072
7321
|
] }),
|
|
7073
|
-
/* @__PURE__ */ (0,
|
|
7322
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
7074
7323
|
"\xB7 ",
|
|
7075
7324
|
inPhase,
|
|
7076
7325
|
" feature",
|
|
7077
7326
|
inPhase === 1 ? "" : "s"
|
|
7078
7327
|
] })
|
|
7079
7328
|
] }),
|
|
7080
|
-
item.phaseWhy ? /* @__PURE__ */ (0,
|
|
7329
|
+
item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
|
|
7081
7330
|
] }) : null,
|
|
7082
|
-
isBoundary ? /* @__PURE__ */ (0,
|
|
7083
|
-
/* @__PURE__ */ (0,
|
|
7331
|
+
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: [
|
|
7332
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-map-pin" }),
|
|
7084
7333
|
" You are here \u2014 everything above is wired"
|
|
7085
7334
|
] }) }) : null,
|
|
7086
|
-
/* @__PURE__ */ (0,
|
|
7087
|
-
/* @__PURE__ */ (0,
|
|
7088
|
-
/* @__PURE__ */ (0,
|
|
7335
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-rm-row", children: [
|
|
7336
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
|
|
7337
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-rm-date", children: [
|
|
7089
7338
|
fmtDate(item.date),
|
|
7090
|
-
/* @__PURE__ */ (0,
|
|
7091
|
-
/* @__PURE__ */ (0,
|
|
7339
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("br", {}),
|
|
7340
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
|
|
7092
7341
|
] }),
|
|
7093
|
-
/* @__PURE__ */ (0,
|
|
7342
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
|
|
7094
7343
|
] })
|
|
7095
7344
|
] }, item.key);
|
|
7096
7345
|
}),
|
|
7097
|
-
!items.length ? /* @__PURE__ */ (0,
|
|
7346
|
+
!items.length ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
|
|
7098
7347
|
] }) }) }),
|
|
7099
|
-
/* @__PURE__ */ (0,
|
|
7348
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
|
|
7100
7349
|
"Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
|
|
7101
|
-
/* @__PURE__ */ (0,
|
|
7350
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("code", { className: "fd-mono", children: "implemented" }),
|
|
7102
7351
|
" field, so this page cannot drift from what the apps actually do."
|
|
7103
7352
|
] })
|
|
7104
7353
|
] });
|
|
7105
7354
|
}
|
|
7106
7355
|
|
|
7107
7356
|
// src/components/platform/ComingSoon.tsx
|
|
7108
|
-
var
|
|
7357
|
+
var React32 = __toESM(require("react"), 1);
|
|
7109
7358
|
var import_react_dom7 = require("react-dom");
|
|
7110
|
-
var
|
|
7359
|
+
var import_jsx_runtime60 = require("react/jsx-runtime");
|
|
7111
7360
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
7112
7361
|
function readBypassed() {
|
|
7113
7362
|
try {
|
|
@@ -7123,8 +7372,8 @@ function writeBypassed(list) {
|
|
|
7123
7372
|
}
|
|
7124
7373
|
}
|
|
7125
7374
|
function useBypass(key) {
|
|
7126
|
-
const [on, setOn] =
|
|
7127
|
-
|
|
7375
|
+
const [on, setOn] = React32.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
7376
|
+
React32.useEffect(() => {
|
|
7128
7377
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
7129
7378
|
}, [key]);
|
|
7130
7379
|
const set = (next) => {
|
|
@@ -7137,43 +7386,43 @@ function useBypass(key) {
|
|
|
7137
7386
|
return [on, set];
|
|
7138
7387
|
}
|
|
7139
7388
|
function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
|
|
7140
|
-
return /* @__PURE__ */ (0,
|
|
7141
|
-
/* @__PURE__ */ (0,
|
|
7142
|
-
/* @__PURE__ */ (0,
|
|
7389
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
|
|
7390
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-badge", children: [
|
|
7391
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
7143
7392
|
label
|
|
7144
7393
|
] }),
|
|
7145
|
-
detail ? /* @__PURE__ */ (0,
|
|
7146
|
-
backend ? /* @__PURE__ */ (0,
|
|
7147
|
-
/* @__PURE__ */ (0,
|
|
7394
|
+
detail ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-soon-detail", children: detail }) : null,
|
|
7395
|
+
backend ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-backend", children: [
|
|
7396
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-overline", children: "Needs" }),
|
|
7148
7397
|
" ",
|
|
7149
7398
|
backend
|
|
7150
7399
|
] }) : null,
|
|
7151
|
-
eta || effort || onRoadmap ? /* @__PURE__ */ (0,
|
|
7152
|
-
eta ? /* @__PURE__ */ (0,
|
|
7153
|
-
/* @__PURE__ */ (0,
|
|
7400
|
+
eta || effort || onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-meta", children: [
|
|
7401
|
+
eta ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { children: [
|
|
7402
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
|
|
7154
7403
|
" ",
|
|
7155
7404
|
eta
|
|
7156
7405
|
] }) : null,
|
|
7157
|
-
effort ? /* @__PURE__ */ (0,
|
|
7158
|
-
/* @__PURE__ */ (0,
|
|
7406
|
+
effort ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { children: [
|
|
7407
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
|
|
7159
7408
|
" ",
|
|
7160
7409
|
effort
|
|
7161
7410
|
] }) : null,
|
|
7162
|
-
onRoadmap ? /* @__PURE__ */ (0,
|
|
7411
|
+
onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
7163
7412
|
"See the roadmap ",
|
|
7164
|
-
/* @__PURE__ */ (0,
|
|
7413
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7165
7414
|
] }) : null
|
|
7166
7415
|
] }) : null,
|
|
7167
|
-
allowed ? /* @__PURE__ */ (0,
|
|
7168
|
-
/* @__PURE__ */ (0,
|
|
7416
|
+
allowed ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
|
|
7417
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-eye", "aria-hidden": "true" }),
|
|
7169
7418
|
" View and use it anyway"
|
|
7170
7419
|
] }) : null
|
|
7171
7420
|
] });
|
|
7172
7421
|
}
|
|
7173
7422
|
function useHoverCard(open) {
|
|
7174
|
-
const anchor =
|
|
7175
|
-
const [pos, setPos] =
|
|
7176
|
-
|
|
7423
|
+
const anchor = React32.useRef(null);
|
|
7424
|
+
const [pos, setPos] = React32.useState(null);
|
|
7425
|
+
React32.useLayoutEffect(() => {
|
|
7177
7426
|
if (!open || !anchor.current) {
|
|
7178
7427
|
setPos(null);
|
|
7179
7428
|
return;
|
|
@@ -7225,9 +7474,9 @@ function ComingSoon({
|
|
|
7225
7474
|
const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
|
|
7226
7475
|
if (inline) {
|
|
7227
7476
|
if (allowed && bypassed) {
|
|
7228
|
-
return /* @__PURE__ */ (0,
|
|
7477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
|
|
7229
7478
|
children,
|
|
7230
|
-
/* @__PURE__ */ (0,
|
|
7479
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7231
7480
|
"button",
|
|
7232
7481
|
{
|
|
7233
7482
|
type: "button",
|
|
@@ -7235,12 +7484,12 @@ function ComingSoon({
|
|
|
7235
7484
|
title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
|
|
7236
7485
|
onClick: () => setBypassed(false),
|
|
7237
7486
|
"aria-label": "Re-blur this unwired feature",
|
|
7238
|
-
children: /* @__PURE__ */ (0,
|
|
7487
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
7239
7488
|
}
|
|
7240
7489
|
)
|
|
7241
7490
|
] });
|
|
7242
7491
|
}
|
|
7243
|
-
return /* @__PURE__ */ (0,
|
|
7492
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7244
7493
|
InlineSoon,
|
|
7245
7494
|
{
|
|
7246
7495
|
label,
|
|
@@ -7260,20 +7509,20 @@ function ComingSoon({
|
|
|
7260
7509
|
);
|
|
7261
7510
|
}
|
|
7262
7511
|
if (allowed && bypassed) {
|
|
7263
|
-
return /* @__PURE__ */ (0,
|
|
7264
|
-
/* @__PURE__ */ (0,
|
|
7265
|
-
/* @__PURE__ */ (0,
|
|
7266
|
-
/* @__PURE__ */ (0,
|
|
7512
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
|
|
7513
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "fd-soon-bar", role: "status", children: [
|
|
7514
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-badge", children: [
|
|
7515
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
7267
7516
|
"Unwired feature \u2014 you are using it anyway"
|
|
7268
7517
|
] }),
|
|
7269
|
-
/* @__PURE__ */ (0,
|
|
7270
|
-
/* @__PURE__ */ (0,
|
|
7271
|
-
onRoadmap ? /* @__PURE__ */ (0,
|
|
7518
|
+
/* @__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." }),
|
|
7519
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-bar-actions", children: [
|
|
7520
|
+
onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
7272
7521
|
"Roadmap ",
|
|
7273
|
-
/* @__PURE__ */ (0,
|
|
7522
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7274
7523
|
] }) : null,
|
|
7275
|
-
/* @__PURE__ */ (0,
|
|
7276
|
-
/* @__PURE__ */ (0,
|
|
7524
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
|
|
7525
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
|
|
7277
7526
|
" Re-blur"
|
|
7278
7527
|
] })
|
|
7279
7528
|
] })
|
|
@@ -7281,10 +7530,10 @@ function ComingSoon({
|
|
|
7281
7530
|
children
|
|
7282
7531
|
] });
|
|
7283
7532
|
}
|
|
7284
|
-
return /* @__PURE__ */ (0,
|
|
7285
|
-
/* @__PURE__ */ (0,
|
|
7286
|
-
/* @__PURE__ */ (0,
|
|
7287
|
-
/* @__PURE__ */ (0,
|
|
7533
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
|
|
7534
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
7535
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "fd-soon-veil" }),
|
|
7536
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7288
7537
|
SoonCard,
|
|
7289
7538
|
{
|
|
7290
7539
|
label,
|
|
@@ -7300,9 +7549,9 @@ function ComingSoon({
|
|
|
7300
7549
|
] });
|
|
7301
7550
|
}
|
|
7302
7551
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
7303
|
-
const [open, setOpen] =
|
|
7552
|
+
const [open, setOpen] = React32.useState(false);
|
|
7304
7553
|
const [anchor, pos] = useHoverCard(open);
|
|
7305
|
-
const close =
|
|
7554
|
+
const close = React32.useRef(null);
|
|
7306
7555
|
const show = () => {
|
|
7307
7556
|
if (close.current) {
|
|
7308
7557
|
clearTimeout(close.current);
|
|
@@ -7318,10 +7567,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7318
7567
|
setOpen(false);
|
|
7319
7568
|
}, 140);
|
|
7320
7569
|
};
|
|
7321
|
-
|
|
7570
|
+
React32.useEffect(() => () => {
|
|
7322
7571
|
if (close.current) clearTimeout(close.current);
|
|
7323
7572
|
}, []);
|
|
7324
|
-
return /* @__PURE__ */ (0,
|
|
7573
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
|
|
7325
7574
|
"span",
|
|
7326
7575
|
{
|
|
7327
7576
|
ref: anchor,
|
|
@@ -7332,8 +7581,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7332
7581
|
onBlur: hide,
|
|
7333
7582
|
...rest,
|
|
7334
7583
|
children: [
|
|
7335
|
-
/* @__PURE__ */ (0,
|
|
7336
|
-
/* @__PURE__ */ (0,
|
|
7584
|
+
/* @__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 }),
|
|
7585
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7337
7586
|
"button",
|
|
7338
7587
|
{
|
|
7339
7588
|
type: "button",
|
|
@@ -7344,11 +7593,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7344
7593
|
onFocus: show,
|
|
7345
7594
|
onBlur: hide,
|
|
7346
7595
|
onClick: () => open ? setOpen(false) : show(),
|
|
7347
|
-
children: /* @__PURE__ */ (0,
|
|
7596
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
7348
7597
|
}
|
|
7349
7598
|
),
|
|
7350
7599
|
open && pos ? (0, import_react_dom7.createPortal)(
|
|
7351
|
-
/* @__PURE__ */ (0,
|
|
7600
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7352
7601
|
"div",
|
|
7353
7602
|
{
|
|
7354
7603
|
className: "fd-soon-note fd-soon-hovercard",
|
|
@@ -7356,7 +7605,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7356
7605
|
style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width },
|
|
7357
7606
|
onMouseEnter: show,
|
|
7358
7607
|
onMouseLeave: hide,
|
|
7359
|
-
children: /* @__PURE__ */ (0,
|
|
7608
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7360
7609
|
SoonCard,
|
|
7361
7610
|
{
|
|
7362
7611
|
label,
|
|
@@ -7386,10 +7635,10 @@ function formatEta(iso2) {
|
|
|
7386
7635
|
var FormatEta = formatEta;
|
|
7387
7636
|
|
|
7388
7637
|
// src/components/platform/Gate.tsx
|
|
7389
|
-
var
|
|
7638
|
+
var import_jsx_runtime61 = require("react/jsx-runtime");
|
|
7390
7639
|
function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
|
|
7391
7640
|
const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
|
|
7392
|
-
return /* @__PURE__ */ (0,
|
|
7641
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
|
|
7393
7642
|
"div",
|
|
7394
7643
|
{
|
|
7395
7644
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -7405,14 +7654,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
7405
7654
|
},
|
|
7406
7655
|
...rest,
|
|
7407
7656
|
children: [
|
|
7408
|
-
/* @__PURE__ */ (0,
|
|
7409
|
-
/* @__PURE__ */ (0,
|
|
7410
|
-
/* @__PURE__ */ (0,
|
|
7657
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
7658
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
7659
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
|
|
7411
7660
|
] }),
|
|
7412
|
-
/* @__PURE__ */ (0,
|
|
7413
|
-
need.length ? /* @__PURE__ */ (0,
|
|
7414
|
-
/* @__PURE__ */ (0,
|
|
7415
|
-
need.map((p) => /* @__PURE__ */ (0,
|
|
7661
|
+
/* @__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." }),
|
|
7662
|
+
need.length ? /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
|
|
7663
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-overline fd-muted", children: "Requires" }),
|
|
7664
|
+
need.map((p) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("code", { className: "fd-mono", style: {
|
|
7416
7665
|
fontSize: 11.5,
|
|
7417
7666
|
padding: "2px 7px",
|
|
7418
7667
|
borderRadius: 5,
|
|
@@ -7433,7 +7682,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, compact: compact3 =
|
|
|
7433
7682
|
if (ok) return children;
|
|
7434
7683
|
if (fallback !== void 0) return fallback;
|
|
7435
7684
|
if (silent) return null;
|
|
7436
|
-
return /* @__PURE__ */ (0,
|
|
7685
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
|
|
7437
7686
|
}
|
|
7438
7687
|
function FeatureGate({
|
|
7439
7688
|
flag,
|
|
@@ -7454,7 +7703,7 @@ function FeatureGate({
|
|
|
7454
7703
|
if (!preview) return fallback;
|
|
7455
7704
|
const f = SessionKit.findFlag(flag) || {};
|
|
7456
7705
|
const missing = rt.missing || [];
|
|
7457
|
-
return /* @__PURE__ */ (0,
|
|
7706
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
7458
7707
|
ComingSoon,
|
|
7459
7708
|
{
|
|
7460
7709
|
label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
|
|
@@ -7475,25 +7724,25 @@ function FeatureGate({
|
|
|
7475
7724
|
function PermissionHint({ perm, children }) {
|
|
7476
7725
|
SessionKit.useSession();
|
|
7477
7726
|
if (SessionKit.can(perm)) return children;
|
|
7478
|
-
return /* @__PURE__ */ (0,
|
|
7727
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
7479
7728
|
"span",
|
|
7480
7729
|
{
|
|
7481
7730
|
title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
|
|
7482
7731
|
style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
|
|
7483
7732
|
"aria-disabled": "true",
|
|
7484
|
-
children: /* @__PURE__ */ (0,
|
|
7733
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { style: { pointerEvents: "none" }, children })
|
|
7485
7734
|
}
|
|
7486
7735
|
);
|
|
7487
7736
|
}
|
|
7488
7737
|
|
|
7489
7738
|
// src/components/platform/ModeSwitch.tsx
|
|
7490
|
-
var
|
|
7491
|
-
var
|
|
7739
|
+
var React33 = __toESM(require("react"), 1);
|
|
7740
|
+
var import_jsx_runtime62 = require("react/jsx-runtime");
|
|
7492
7741
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
7493
7742
|
const mode2 = useRuntimeMode();
|
|
7494
|
-
const [open, setOpen] =
|
|
7495
|
-
const ref =
|
|
7496
|
-
|
|
7743
|
+
const [open, setOpen] = React33.useState(false);
|
|
7744
|
+
const ref = React33.useRef(null);
|
|
7745
|
+
React33.useEffect(() => {
|
|
7497
7746
|
if (!open) return;
|
|
7498
7747
|
const away = (e) => {
|
|
7499
7748
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -7515,8 +7764,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7515
7764
|
RuntimeKit.setMode(next);
|
|
7516
7765
|
setOpen(false);
|
|
7517
7766
|
};
|
|
7518
|
-
return /* @__PURE__ */ (0,
|
|
7519
|
-
/* @__PURE__ */ (0,
|
|
7767
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
|
|
7768
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
|
|
7520
7769
|
"button",
|
|
7521
7770
|
{
|
|
7522
7771
|
type: "button",
|
|
@@ -7526,29 +7775,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7526
7775
|
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
7776
|
className: "fd-mode-btn" + (test ? " is-test" : "") + (open ? " is-open" : ""),
|
|
7528
7777
|
children: [
|
|
7529
|
-
/* @__PURE__ */ (0,
|
|
7530
|
-
test && requestCount ? /* @__PURE__ */ (0,
|
|
7778
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
|
|
7779
|
+
test && requestCount ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
|
|
7531
7780
|
]
|
|
7532
7781
|
}
|
|
7533
7782
|
),
|
|
7534
|
-
open ? /* @__PURE__ */ (0,
|
|
7535
|
-
/* @__PURE__ */ (0,
|
|
7536
|
-
/* @__PURE__ */ (0,
|
|
7537
|
-
/* @__PURE__ */ (0,
|
|
7783
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-view-enter fd-mode-pop", children: [
|
|
7784
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
7785
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
|
|
7786
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
|
|
7538
7787
|
test ? "Test mode" : "Live mode"
|
|
7539
7788
|
] }),
|
|
7540
|
-
test ? /* @__PURE__ */ (0,
|
|
7789
|
+
test ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
7541
7790
|
requestCount,
|
|
7542
7791
|
" simulated request",
|
|
7543
7792
|
requestCount === 1 ? "" : "s"
|
|
7544
7793
|
] }) : null,
|
|
7545
|
-
/* @__PURE__ */ (0,
|
|
7546
|
-
test && onClearLog ? /* @__PURE__ */ (0,
|
|
7794
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { flex: 1 } }),
|
|
7795
|
+
test && onClearLog ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
|
|
7547
7796
|
] }),
|
|
7548
|
-
/* @__PURE__ */ (0,
|
|
7549
|
-
/* @__PURE__ */ (0,
|
|
7550
|
-
/* @__PURE__ */ (0,
|
|
7551
|
-
/* @__PURE__ */ (0,
|
|
7797
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
7798
|
+
/* @__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." }),
|
|
7799
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
|
|
7800
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
7552
7801
|
s.endpointsWired,
|
|
7553
7802
|
" endpoint",
|
|
7554
7803
|
s.endpointsWired === 1 ? "" : "s",
|
|
@@ -7558,58 +7807,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7558
7807
|
s.total,
|
|
7559
7808
|
" features complete"
|
|
7560
7809
|
] }),
|
|
7561
|
-
onOpenSpec ? /* @__PURE__ */ (0,
|
|
7562
|
-
/* @__PURE__ */ (0,
|
|
7563
|
-
/* @__PURE__ */ (0,
|
|
7810
|
+
onOpenSpec ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(import_jsx_runtime62.Fragment, { children: [
|
|
7811
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { flex: 1 } }),
|
|
7812
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => {
|
|
7564
7813
|
setOpen(false);
|
|
7565
7814
|
onOpenSpec();
|
|
7566
7815
|
}, children: [
|
|
7567
7816
|
"API spec ",
|
|
7568
|
-
/* @__PURE__ */ (0,
|
|
7817
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7569
7818
|
] })
|
|
7570
7819
|
] }) : null
|
|
7571
7820
|
] })
|
|
7572
7821
|
] }),
|
|
7573
|
-
/* @__PURE__ */ (0,
|
|
7574
|
-
/* @__PURE__ */ (0,
|
|
7575
|
-
/* @__PURE__ */ (0,
|
|
7576
|
-
/* @__PURE__ */ (0,
|
|
7577
|
-
/* @__PURE__ */ (0,
|
|
7578
|
-
/* @__PURE__ */ (0,
|
|
7822
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-mode-choice", children: [
|
|
7823
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
|
|
7824
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
7825
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-mode-opt-text", children: [
|
|
7826
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mode-opt-title", children: "Live mode" }),
|
|
7827
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
|
|
7579
7828
|
] }),
|
|
7580
|
-
!test ? /* @__PURE__ */ (0,
|
|
7829
|
+
!test ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
7581
7830
|
] }),
|
|
7582
|
-
/* @__PURE__ */ (0,
|
|
7583
|
-
/* @__PURE__ */ (0,
|
|
7584
|
-
/* @__PURE__ */ (0,
|
|
7585
|
-
/* @__PURE__ */ (0,
|
|
7586
|
-
/* @__PURE__ */ (0,
|
|
7831
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
|
|
7832
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
7833
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-mode-opt-text", children: [
|
|
7834
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mode-opt-title", children: "Test mode" }),
|
|
7835
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
|
|
7587
7836
|
] }),
|
|
7588
|
-
test ? /* @__PURE__ */ (0,
|
|
7837
|
+
test ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
7589
7838
|
] })
|
|
7590
7839
|
] }),
|
|
7591
|
-
test && renderLog ? /* @__PURE__ */ (0,
|
|
7840
|
+
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
7841
|
] }) : null
|
|
7593
7842
|
] });
|
|
7594
7843
|
}
|
|
7595
7844
|
function TestModeBar({ onExit }) {
|
|
7596
7845
|
const mode2 = useRuntimeMode();
|
|
7597
7846
|
if (mode2 !== "test") return null;
|
|
7598
|
-
return /* @__PURE__ */ (0,
|
|
7599
|
-
/* @__PURE__ */ (0,
|
|
7600
|
-
/* @__PURE__ */ (0,
|
|
7847
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "fd-testbar", role: "status", children: [
|
|
7848
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-badge fd-badge-warning", children: [
|
|
7849
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
7601
7850
|
"Test mode"
|
|
7602
7851
|
] }),
|
|
7603
|
-
/* @__PURE__ */ (0,
|
|
7604
|
-
/* @__PURE__ */ (0,
|
|
7605
|
-
/* @__PURE__ */ (0,
|
|
7852
|
+
/* @__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." }),
|
|
7853
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
|
|
7854
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
7606
7855
|
" Back to live mode"
|
|
7607
7856
|
] })
|
|
7608
7857
|
] });
|
|
7609
7858
|
}
|
|
7610
7859
|
|
|
7611
7860
|
// src/components/planner/ChannelMeta.tsx
|
|
7612
|
-
var
|
|
7861
|
+
var import_jsx_runtime63 = require("react/jsx-runtime");
|
|
7613
7862
|
var CHANNEL_WEIGHTS = {
|
|
7614
7863
|
"OOH": 50,
|
|
7615
7864
|
"DOOH": 50,
|
|
@@ -7662,9 +7911,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
7662
7911
|
const m = ChannelMeta(channel);
|
|
7663
7912
|
const wt = channelWeightOf(channel || "");
|
|
7664
7913
|
if (dot) {
|
|
7665
|
-
return /* @__PURE__ */ (0,
|
|
7914
|
+
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
7915
|
}
|
|
7667
|
-
return /* @__PURE__ */ (0,
|
|
7916
|
+
return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
|
|
7668
7917
|
"span",
|
|
7669
7918
|
{
|
|
7670
7919
|
className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
|
|
@@ -7672,16 +7921,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
7672
7921
|
style: { "--chan": m.color },
|
|
7673
7922
|
...rest,
|
|
7674
7923
|
children: [
|
|
7675
|
-
/* @__PURE__ */ (0,
|
|
7676
|
-
showLabel ? /* @__PURE__ */ (0,
|
|
7677
|
-
weight ? /* @__PURE__ */ (0,
|
|
7924
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
|
|
7925
|
+
showLabel ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-chan-label", children: m.label }) : null,
|
|
7926
|
+
weight ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-chan-weight", children: wt || 0 }) : null
|
|
7678
7927
|
]
|
|
7679
7928
|
}
|
|
7680
7929
|
);
|
|
7681
7930
|
}
|
|
7682
7931
|
|
|
7683
7932
|
// src/components/planner/SaturationDistribution.tsx
|
|
7684
|
-
var
|
|
7933
|
+
var import_jsx_runtime64 = require("react/jsx-runtime");
|
|
7685
7934
|
var BANDS2 = [
|
|
7686
7935
|
{ key: "weak", label: "Weak", n: 1, range: "< 50" },
|
|
7687
7936
|
{ key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
|
|
@@ -7692,18 +7941,18 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
7692
7941
|
const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
|
|
7693
7942
|
const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
|
|
7694
7943
|
const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
|
|
7695
|
-
return /* @__PURE__ */ (0,
|
|
7696
|
-
/* @__PURE__ */ (0,
|
|
7944
|
+
return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
7945
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
|
|
7697
7946
|
const mark = "var(--csi-" + g.n + "-mark)";
|
|
7698
7947
|
const active = selectedBand === g.key;
|
|
7699
|
-
return /* @__PURE__ */ (0,
|
|
7948
|
+
return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
|
|
7700
7949
|
"button",
|
|
7701
7950
|
{
|
|
7702
7951
|
type: "button",
|
|
7703
7952
|
onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
|
|
7704
7953
|
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
7954
|
children: [
|
|
7706
|
-
/* @__PURE__ */ (0,
|
|
7955
|
+
/* @__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
7956
|
"span",
|
|
7708
7957
|
{
|
|
7709
7958
|
title: c.name + " \xB7 " + c.crp,
|
|
@@ -7712,13 +7961,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
7712
7961
|
},
|
|
7713
7962
|
c.name
|
|
7714
7963
|
)) }),
|
|
7715
|
-
/* @__PURE__ */ (0,
|
|
7716
|
-
/* @__PURE__ */ (0,
|
|
7717
|
-
/* @__PURE__ */ (0,
|
|
7964
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
|
|
7965
|
+
/* @__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 }),
|
|
7966
|
+
/* @__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
7967
|
] }),
|
|
7719
|
-
/* @__PURE__ */ (0,
|
|
7720
|
-
/* @__PURE__ */ (0,
|
|
7721
|
-
/* @__PURE__ */ (0,
|
|
7968
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-stack", style: { gap: 1 }, children: [
|
|
7969
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-label-lg", children: g.label }),
|
|
7970
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
|
|
7722
7971
|
"CRP ",
|
|
7723
7972
|
g.range
|
|
7724
7973
|
] })
|
|
@@ -7728,10 +7977,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
7728
7977
|
g.key
|
|
7729
7978
|
);
|
|
7730
7979
|
}) }),
|
|
7731
|
-
floorBand ? /* @__PURE__ */ (0,
|
|
7732
|
-
/* @__PURE__ */ (0,
|
|
7733
|
-
/* @__PURE__ */ (0,
|
|
7734
|
-
/* @__PURE__ */ (0,
|
|
7980
|
+
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: [
|
|
7981
|
+
/* @__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)) }),
|
|
7982
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
|
|
7983
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("strong", { style: { color: "var(--text)" }, children: [
|
|
7735
7984
|
"Plan floor ",
|
|
7736
7985
|
floorScore
|
|
7737
7986
|
] }),
|
|
@@ -7742,21 +7991,21 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
7742
7991
|
}
|
|
7743
7992
|
|
|
7744
7993
|
// src/components/planner/MixGap.tsx
|
|
7745
|
-
var
|
|
7746
|
-
var
|
|
7994
|
+
var React34 = __toESM(require("react"), 1);
|
|
7995
|
+
var import_jsx_runtime65 = require("react/jsx-runtime");
|
|
7747
7996
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
7748
7997
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
7749
|
-
const [hover, setHover] =
|
|
7998
|
+
const [hover, setHover] = React34.useState(null);
|
|
7750
7999
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
7751
8000
|
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,
|
|
8001
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
|
|
8002
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
|
|
8003
|
+
[["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: [
|
|
8004
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
|
|
7756
8005
|
l
|
|
7757
8006
|
] }, l)),
|
|
7758
|
-
/* @__PURE__ */ (0,
|
|
7759
|
-
/* @__PURE__ */ (0,
|
|
8007
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
8008
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { width: 3, height: 14, background: "var(--n-500)" } }),
|
|
7760
8009
|
"Target"
|
|
7761
8010
|
] })
|
|
7762
8011
|
] }),
|
|
@@ -7764,7 +8013,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
7764
8013
|
const gap = r.realized - r.target;
|
|
7765
8014
|
const tone = toneOf(gap);
|
|
7766
8015
|
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,
|
|
8016
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
|
|
7768
8017
|
"div",
|
|
7769
8018
|
{
|
|
7770
8019
|
className: "fd-row",
|
|
@@ -7772,15 +8021,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
7772
8021
|
onMouseEnter: () => setHover(r.channel),
|
|
7773
8022
|
onMouseLeave: () => setHover(null),
|
|
7774
8023
|
children: [
|
|
7775
|
-
/* @__PURE__ */ (0,
|
|
7776
|
-
/* @__PURE__ */ (0,
|
|
7777
|
-
/* @__PURE__ */ (0,
|
|
7778
|
-
/* @__PURE__ */ (0,
|
|
7779
|
-
/* @__PURE__ */ (0,
|
|
8024
|
+
/* @__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" }) }),
|
|
8025
|
+
/* @__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: [
|
|
8026
|
+
/* @__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)" } }),
|
|
8027
|
+
/* @__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 } }),
|
|
8028
|
+
/* @__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
8029
|
r.realized,
|
|
7781
8030
|
"%"
|
|
7782
8031
|
] }),
|
|
7783
|
-
hover === r.channel ? /* @__PURE__ */ (0,
|
|
8032
|
+
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
8033
|
] }) })
|
|
7785
8034
|
]
|
|
7786
8035
|
},
|
|
@@ -7791,7 +8040,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
7791
8040
|
}
|
|
7792
8041
|
|
|
7793
8042
|
// src/components/planner/ChannelContribution.tsx
|
|
7794
|
-
var
|
|
8043
|
+
var import_jsx_runtime66 = require("react/jsx-runtime");
|
|
7795
8044
|
var money = (n) => "$" + Math.round(n).toLocaleString();
|
|
7796
8045
|
function ChannelContribution({
|
|
7797
8046
|
channels = [],
|
|
@@ -7807,9 +8056,9 @@ function ChannelContribution({
|
|
|
7807
8056
|
const grand = total !== void 0 ? total : base + bonus;
|
|
7808
8057
|
const pct = (v) => grand ? v / grand * 100 : 0;
|
|
7809
8058
|
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,
|
|
8059
|
+
return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
8060
|
+
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: [
|
|
8061
|
+
channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
|
|
7813
8062
|
"span",
|
|
7814
8063
|
{
|
|
7815
8064
|
title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
|
|
@@ -7818,7 +8067,7 @@ function ChannelContribution({
|
|
|
7818
8067
|
},
|
|
7819
8068
|
c.name
|
|
7820
8069
|
)),
|
|
7821
|
-
bonus > 0 ? /* @__PURE__ */ (0,
|
|
8070
|
+
bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
|
|
7822
8071
|
"span",
|
|
7823
8072
|
{
|
|
7824
8073
|
title: "Surround-sound bonus +" + bonusPct + "%",
|
|
@@ -7827,18 +8076,18 @@ function ChannelContribution({
|
|
|
7827
8076
|
}
|
|
7828
8077
|
) : null
|
|
7829
8078
|
] }),
|
|
7830
|
-
showTable ? /* @__PURE__ */ (0,
|
|
7831
|
-
/* @__PURE__ */ (0,
|
|
7832
|
-
/* @__PURE__ */ (0,
|
|
7833
|
-
/* @__PURE__ */ (0,
|
|
7834
|
-
/* @__PURE__ */ (0,
|
|
7835
|
-
/* @__PURE__ */ (0,
|
|
7836
|
-
/* @__PURE__ */ (0,
|
|
8079
|
+
showTable ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
|
|
8080
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { children: [
|
|
8081
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { style: { width: "34%" }, children: "Channel" }),
|
|
8082
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { style: { width: "16%" }, children: "Weight" }),
|
|
8083
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
|
|
8084
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
|
|
8085
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
|
|
7837
8086
|
] }) }),
|
|
7838
|
-
/* @__PURE__ */ (0,
|
|
7839
|
-
channels.map((c) => /* @__PURE__ */ (0,
|
|
7840
|
-
/* @__PURE__ */ (0,
|
|
7841
|
-
/* @__PURE__ */ (0,
|
|
8087
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tbody", { children: [
|
|
8088
|
+
channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { children: [
|
|
8089
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(ChannelTag, { channel: c.name, size: "sm" }) }),
|
|
8090
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
|
|
7842
8091
|
"span",
|
|
7843
8092
|
{
|
|
7844
8093
|
className: "fd-badge fd-badge-neutral",
|
|
@@ -7847,38 +8096,38 @@ function ChannelContribution({
|
|
|
7847
8096
|
children: "weight " + (channelWeightOf(c.name) || 0)
|
|
7848
8097
|
}
|
|
7849
8098
|
) }),
|
|
7850
|
-
/* @__PURE__ */ (0,
|
|
7851
|
-
/* @__PURE__ */ (0,
|
|
7852
|
-
/* @__PURE__ */ (0,
|
|
8099
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", children: c.spend }),
|
|
8100
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", children: c.crp.toFixed(1) }),
|
|
8101
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("td", { className: "is-num", children: [
|
|
7853
8102
|
pct(c.crp).toFixed(0),
|
|
7854
8103
|
"%"
|
|
7855
8104
|
] })
|
|
7856
8105
|
] }, c.name)),
|
|
7857
|
-
bonus > 0 ? /* @__PURE__ */ (0,
|
|
7858
|
-
/* @__PURE__ */ (0,
|
|
7859
|
-
/* @__PURE__ */ (0,
|
|
8106
|
+
bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { children: [
|
|
8107
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
|
|
8108
|
+
/* @__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
8109
|
"Surround-sound bonus"
|
|
7861
8110
|
] }) }),
|
|
7862
|
-
/* @__PURE__ */ (0,
|
|
8111
|
+
/* @__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
8112
|
"+",
|
|
7864
8113
|
bonusPct,
|
|
7865
8114
|
"% of +",
|
|
7866
8115
|
bonusMax,
|
|
7867
8116
|
"%"
|
|
7868
8117
|
] }) }),
|
|
7869
|
-
/* @__PURE__ */ (0,
|
|
7870
|
-
/* @__PURE__ */ (0,
|
|
7871
|
-
/* @__PURE__ */ (0,
|
|
8118
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num fd-muted", children: "\u2014" }),
|
|
8119
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", children: bonus.toFixed(1) }),
|
|
8120
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("td", { className: "is-num", children: [
|
|
7872
8121
|
pct(bonus).toFixed(0),
|
|
7873
8122
|
"%"
|
|
7874
8123
|
] })
|
|
7875
8124
|
] }) : null,
|
|
7876
|
-
/* @__PURE__ */ (0,
|
|
7877
|
-
/* @__PURE__ */ (0,
|
|
7878
|
-
/* @__PURE__ */ (0,
|
|
7879
|
-
/* @__PURE__ */ (0,
|
|
7880
|
-
/* @__PURE__ */ (0,
|
|
7881
|
-
/* @__PURE__ */ (0,
|
|
8125
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { style: { background: "var(--surface-2)" }, children: [
|
|
8126
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { style: { fontWeight: 700 }, children: "Campus total" }),
|
|
8127
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", {}),
|
|
8128
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
|
|
8129
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
|
|
8130
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
|
|
7882
8131
|
] })
|
|
7883
8132
|
] })
|
|
7884
8133
|
] }) : null
|
|
@@ -7886,8 +8135,8 @@ function ChannelContribution({
|
|
|
7886
8135
|
}
|
|
7887
8136
|
|
|
7888
8137
|
// src/components/planner/BudgetReallocator.tsx
|
|
7889
|
-
var
|
|
7890
|
-
var
|
|
8138
|
+
var React35 = __toESM(require("react"), 1);
|
|
8139
|
+
var import_jsx_runtime67 = require("react/jsx-runtime");
|
|
7891
8140
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
7892
8141
|
function BudgetReallocator({
|
|
7893
8142
|
campus,
|
|
@@ -7902,8 +8151,8 @@ function BudgetReallocator({
|
|
|
7902
8151
|
onCancel,
|
|
7903
8152
|
className = ""
|
|
7904
8153
|
}) {
|
|
7905
|
-
const [draft, setDraft] =
|
|
7906
|
-
|
|
8154
|
+
const [draft, setDraft] = React35.useState(spend);
|
|
8155
|
+
React35.useEffect(() => setDraft(spend), [spend]);
|
|
7907
8156
|
const dirty = draft !== spend;
|
|
7908
8157
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
7909
8158
|
const nextBand = bandFor(nextCrp);
|
|
@@ -7918,24 +8167,24 @@ function BudgetReallocator({
|
|
|
7918
8167
|
setDraft(spend);
|
|
7919
8168
|
if (onCancel) onCancel();
|
|
7920
8169
|
};
|
|
7921
|
-
return /* @__PURE__ */ (0,
|
|
8170
|
+
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
|
|
7922
8171
|
"div",
|
|
7923
8172
|
{
|
|
7924
8173
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
7925
8174
|
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
8175
|
children: [
|
|
7927
|
-
/* @__PURE__ */ (0,
|
|
7928
|
-
/* @__PURE__ */ (0,
|
|
7929
|
-
/* @__PURE__ */ (0,
|
|
7930
|
-
dirty ? /* @__PURE__ */ (0,
|
|
7931
|
-
/* @__PURE__ */ (0,
|
|
7932
|
-
/* @__PURE__ */ (0,
|
|
8176
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
8177
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
|
|
8178
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)(CsiBadge, { band: nowBand, crp, size: "medium" }),
|
|
8179
|
+
dirty ? /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(import_jsx_runtime67.Fragment, { children: [
|
|
8180
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
|
|
8181
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
|
|
7933
8182
|
] }) : null
|
|
7934
8183
|
] }),
|
|
7935
|
-
/* @__PURE__ */ (0,
|
|
7936
|
-
/* @__PURE__ */ (0,
|
|
7937
|
-
dirty ? /* @__PURE__ */ (0,
|
|
7938
|
-
/* @__PURE__ */ (0,
|
|
8184
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fd-slider", children: [
|
|
8185
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
8186
|
+
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,
|
|
8187
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
|
|
7939
8188
|
"input",
|
|
7940
8189
|
{
|
|
7941
8190
|
type: "range",
|
|
@@ -7951,13 +8200,13 @@ function BudgetReallocator({
|
|
|
7951
8200
|
}
|
|
7952
8201
|
)
|
|
7953
8202
|
] }),
|
|
7954
|
-
/* @__PURE__ */ (0,
|
|
7955
|
-
/* @__PURE__ */ (0,
|
|
7956
|
-
/* @__PURE__ */ (0,
|
|
7957
|
-
/* @__PURE__ */ (0,
|
|
8203
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
8204
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
|
|
8205
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
|
|
8206
|
+
/* @__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
8207
|
] }),
|
|
7959
|
-
/* @__PURE__ */ (0,
|
|
7960
|
-
/* @__PURE__ */ (0,
|
|
8208
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
|
|
8209
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
|
|
7961
8210
|
"button",
|
|
7962
8211
|
{
|
|
7963
8212
|
type: "button",
|
|
@@ -7976,7 +8225,7 @@ function BudgetReallocator({
|
|
|
7976
8225
|
}
|
|
7977
8226
|
|
|
7978
8227
|
// src/components/planner/SurroundSound.tsx
|
|
7979
|
-
var
|
|
8228
|
+
var import_jsx_runtime68 = require("react/jsx-runtime");
|
|
7980
8229
|
var CATEGORIES = [
|
|
7981
8230
|
{ key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
|
|
7982
8231
|
{ key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
|
|
@@ -7988,26 +8237,26 @@ var CATEGORIES = [
|
|
|
7988
8237
|
function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
|
|
7989
8238
|
const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
|
|
7990
8239
|
const single = present.length <= 2;
|
|
7991
|
-
return /* @__PURE__ */ (0,
|
|
7992
|
-
/* @__PURE__ */ (0,
|
|
8240
|
+
return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
|
|
8241
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
|
|
7993
8242
|
const on = present.includes(c.key);
|
|
7994
|
-
return /* @__PURE__ */ (0,
|
|
8243
|
+
return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
|
|
7995
8244
|
"span",
|
|
7996
8245
|
{
|
|
7997
8246
|
title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
|
|
7998
8247
|
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
8248
|
children: [
|
|
8000
|
-
/* @__PURE__ */ (0,
|
|
8001
|
-
/* @__PURE__ */ (0,
|
|
8249
|
+
/* @__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" }),
|
|
8250
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
|
|
8002
8251
|
]
|
|
8003
8252
|
},
|
|
8004
8253
|
c.key
|
|
8005
8254
|
);
|
|
8006
8255
|
}) }),
|
|
8007
|
-
/* @__PURE__ */ (0,
|
|
8008
|
-
/* @__PURE__ */ (0,
|
|
8009
|
-
/* @__PURE__ */ (0,
|
|
8010
|
-
/* @__PURE__ */ (0,
|
|
8256
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
8257
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
8258
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
|
|
8259
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
|
|
8011
8260
|
"+",
|
|
8012
8261
|
bonusPct,
|
|
8013
8262
|
"% of +",
|
|
@@ -8015,8 +8264,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
8015
8264
|
"%"
|
|
8016
8265
|
] })
|
|
8017
8266
|
] }),
|
|
8018
|
-
/* @__PURE__ */ (0,
|
|
8019
|
-
/* @__PURE__ */ (0,
|
|
8267
|
+
/* @__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)" } }) }),
|
|
8268
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
|
|
8020
8269
|
present.length,
|
|
8021
8270
|
" of 6 channel categories present.",
|
|
8022
8271
|
" ",
|
|
@@ -8028,10 +8277,10 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
8028
8277
|
}
|
|
8029
8278
|
|
|
8030
8279
|
// src/components/chat/AgentChatPanel.tsx
|
|
8031
|
-
var
|
|
8280
|
+
var React41 = __toESM(require("react"), 1);
|
|
8032
8281
|
|
|
8033
8282
|
// src/components/chat/chatEngine.ts
|
|
8034
|
-
var
|
|
8283
|
+
var React36 = __toESM(require("react"), 1);
|
|
8035
8284
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
8036
8285
|
var JOB_PENDING = ["queued", "running"];
|
|
8037
8286
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -8085,22 +8334,22 @@ function useChatEngine(opts) {
|
|
|
8085
8334
|
onClear,
|
|
8086
8335
|
onFeedback
|
|
8087
8336
|
} = 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
|
-
|
|
8337
|
+
const [status, setStatus] = React36.useState("idle");
|
|
8338
|
+
const [threadId, setThreadId] = React36.useState(null);
|
|
8339
|
+
const [messages, setMessages] = React36.useState([]);
|
|
8340
|
+
const [queue, setQueue] = React36.useState([]);
|
|
8341
|
+
const [fatal, setFatal] = React36.useState(null);
|
|
8342
|
+
const [busy, setBusy] = React36.useState(false);
|
|
8343
|
+
const [turnStartedAt, setTurnStartedAt] = React36.useState(null);
|
|
8344
|
+
const listRef = React36.useRef([]);
|
|
8345
|
+
const queueRef = React36.useRef([]);
|
|
8346
|
+
const busyRef = React36.useRef(false);
|
|
8347
|
+
const stoppedRef = React36.useRef(false);
|
|
8348
|
+
const abortRef = React36.useRef(null);
|
|
8349
|
+
const serverCount = React36.useRef(0);
|
|
8350
|
+
const threadRef = React36.useRef(null);
|
|
8351
|
+
const mounted = React36.useRef(true);
|
|
8352
|
+
React36.useEffect(() => {
|
|
8104
8353
|
mounted.current = true;
|
|
8105
8354
|
return () => {
|
|
8106
8355
|
mounted.current = false;
|
|
@@ -8122,14 +8371,14 @@ function useChatEngine(opts) {
|
|
|
8122
8371
|
}
|
|
8123
8372
|
return false;
|
|
8124
8373
|
};
|
|
8125
|
-
const loadThread =
|
|
8374
|
+
const loadThread = React36.useCallback(async (id) => {
|
|
8126
8375
|
const data = await apiAdapter.getThread(id);
|
|
8127
8376
|
const list = [...data && data.messages || []];
|
|
8128
8377
|
serverCount.current = list.length;
|
|
8129
8378
|
commit(list);
|
|
8130
8379
|
return list;
|
|
8131
8380
|
}, [apiAdapter]);
|
|
8132
|
-
|
|
8381
|
+
React36.useEffect(() => {
|
|
8133
8382
|
if (!apiAdapter) {
|
|
8134
8383
|
setStatus("idle");
|
|
8135
8384
|
setFatal(null);
|
|
@@ -8342,7 +8591,7 @@ function useChatEngine(opts) {
|
|
|
8342
8591
|
await dispatchTurn(turn);
|
|
8343
8592
|
}
|
|
8344
8593
|
}
|
|
8345
|
-
const send =
|
|
8594
|
+
const send = React36.useCallback((text, attachments) => {
|
|
8346
8595
|
const body = (text || "").trim();
|
|
8347
8596
|
if (!body && !(attachments && attachments.length)) return;
|
|
8348
8597
|
if (status === "disconnected") return;
|
|
@@ -8352,7 +8601,7 @@ function useChatEngine(opts) {
|
|
|
8352
8601
|
stoppedRef.current = false;
|
|
8353
8602
|
drain();
|
|
8354
8603
|
}, [status]);
|
|
8355
|
-
const stop =
|
|
8604
|
+
const stop = React36.useCallback(() => {
|
|
8356
8605
|
stoppedRef.current = true;
|
|
8357
8606
|
const ac = abortRef.current;
|
|
8358
8607
|
if (ac) {
|
|
@@ -8371,11 +8620,11 @@ function useChatEngine(opts) {
|
|
|
8371
8620
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
8372
8621
|
}
|
|
8373
8622
|
}, [apiAdapter]);
|
|
8374
|
-
const removeQueued =
|
|
8623
|
+
const removeQueued = React36.useCallback((id) => {
|
|
8375
8624
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
8376
8625
|
setQueue(queueRef.current.slice());
|
|
8377
8626
|
}, []);
|
|
8378
|
-
const retry =
|
|
8627
|
+
const retry = React36.useCallback(() => {
|
|
8379
8628
|
const list = listRef.current;
|
|
8380
8629
|
let at = -1;
|
|
8381
8630
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -8391,19 +8640,19 @@ function useChatEngine(opts) {
|
|
|
8391
8640
|
setQueue(queueRef.current.slice());
|
|
8392
8641
|
drain();
|
|
8393
8642
|
}, []);
|
|
8394
|
-
const clear =
|
|
8643
|
+
const clear = React36.useCallback(() => {
|
|
8395
8644
|
commit([]);
|
|
8396
8645
|
serverCount.current = 0;
|
|
8397
8646
|
queueRef.current = [];
|
|
8398
8647
|
setQueue([]);
|
|
8399
8648
|
onClear && onClear();
|
|
8400
8649
|
}, [onClear]);
|
|
8401
|
-
const setFeedback =
|
|
8650
|
+
const setFeedback = React36.useCallback((id, value) => {
|
|
8402
8651
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
8403
8652
|
const msg = listRef.current.find((m) => m.id === id);
|
|
8404
8653
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
8405
8654
|
}, [onFeedback]);
|
|
8406
|
-
const reload =
|
|
8655
|
+
const reload = React36.useCallback(async () => {
|
|
8407
8656
|
if (!threadRef.current) return;
|
|
8408
8657
|
setStatus("loading");
|
|
8409
8658
|
try {
|
|
@@ -8441,11 +8690,11 @@ var ChatKit = {
|
|
|
8441
8690
|
};
|
|
8442
8691
|
|
|
8443
8692
|
// src/components/chat/ChatTranscript.tsx
|
|
8444
|
-
var
|
|
8693
|
+
var React38 = __toESM(require("react"), 1);
|
|
8445
8694
|
|
|
8446
8695
|
// src/components/chat/ChatTurn.tsx
|
|
8447
|
-
var
|
|
8448
|
-
var
|
|
8696
|
+
var React37 = __toESM(require("react"), 1);
|
|
8697
|
+
var import_jsx_runtime69 = require("react/jsx-runtime");
|
|
8449
8698
|
function JsonView({ value }) {
|
|
8450
8699
|
let text;
|
|
8451
8700
|
try {
|
|
@@ -8453,67 +8702,67 @@ function JsonView({ value }) {
|
|
|
8453
8702
|
} catch (e) {
|
|
8454
8703
|
text = String(value);
|
|
8455
8704
|
}
|
|
8456
|
-
return /* @__PURE__ */ (0,
|
|
8705
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
|
|
8457
8706
|
}
|
|
8458
8707
|
function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
8459
8708
|
if (!packet) return null;
|
|
8460
8709
|
const s = schema || {};
|
|
8461
8710
|
const invalid = packet.valid === false;
|
|
8462
8711
|
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,
|
|
8712
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
|
|
8713
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("header", { className: "fdc-packet-head", children: [
|
|
8714
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
|
|
8715
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-packet-title", children: title }),
|
|
8716
|
+
packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
|
|
8717
|
+
invalid ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
|
|
8469
8718
|
] }),
|
|
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,
|
|
8719
|
+
invalid ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-packet-alert", role: "alert", children: [
|
|
8720
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
8721
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
|
|
8722
|
+
] }) : /* @__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 }) }),
|
|
8723
|
+
!invalid && onApply ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("footer", { className: "fdc-packet-foot", children: [
|
|
8724
|
+
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", {}),
|
|
8725
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
|
|
8726
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
|
|
8478
8727
|
applied ? "Applied" : s.applyLabel || "Apply"
|
|
8479
8728
|
] })
|
|
8480
8729
|
] }) : null
|
|
8481
8730
|
] });
|
|
8482
8731
|
}
|
|
8483
8732
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
8484
|
-
const [open, setOpen] =
|
|
8733
|
+
const [open, setOpen] = React37.useState(defaultOpen);
|
|
8485
8734
|
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,
|
|
8735
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
|
|
8736
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
8737
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-brain", "aria-hidden": "true" }),
|
|
8738
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
|
|
8739
|
+
streaming ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
8740
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
|
|
8741
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
|
|
8742
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {})
|
|
8494
8743
|
] }) : null,
|
|
8495
|
-
/* @__PURE__ */ (0,
|
|
8744
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
|
|
8496
8745
|
] }),
|
|
8497
|
-
open ? /* @__PURE__ */ (0,
|
|
8746
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "fdc-think-body", children: text }) : null
|
|
8498
8747
|
] });
|
|
8499
8748
|
}
|
|
8500
8749
|
function Citations({ items = [], onOpen }) {
|
|
8501
|
-
const [open, setOpen] =
|
|
8750
|
+
const [open, setOpen] = React37.useState(false);
|
|
8502
8751
|
if (!items.length) return null;
|
|
8503
|
-
return /* @__PURE__ */ (0,
|
|
8504
|
-
/* @__PURE__ */ (0,
|
|
8505
|
-
/* @__PURE__ */ (0,
|
|
8506
|
-
/* @__PURE__ */ (0,
|
|
8752
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-cites", children: [
|
|
8753
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
8754
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
|
|
8755
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { children: [
|
|
8507
8756
|
items.length,
|
|
8508
8757
|
" source",
|
|
8509
8758
|
items.length === 1 ? "" : "s"
|
|
8510
8759
|
] }),
|
|
8511
|
-
/* @__PURE__ */ (0,
|
|
8760
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
|
|
8512
8761
|
] }),
|
|
8513
|
-
open ? /* @__PURE__ */ (0,
|
|
8514
|
-
/* @__PURE__ */ (0,
|
|
8515
|
-
c.url ? /* @__PURE__ */ (0,
|
|
8516
|
-
c.detail ? /* @__PURE__ */ (0,
|
|
8762
|
+
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: [
|
|
8763
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
|
|
8764
|
+
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" }),
|
|
8765
|
+
c.detail ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-cite-detail", children: c.detail }) : null
|
|
8517
8766
|
] }, c.id || i)) }) : null
|
|
8518
8767
|
] });
|
|
8519
8768
|
}
|
|
@@ -8524,29 +8773,29 @@ function clampText(text, max) {
|
|
|
8524
8773
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
8525
8774
|
}
|
|
8526
8775
|
function MessageBody({ message: m, ctx }) {
|
|
8527
|
-
const [expanded, setExpanded] =
|
|
8776
|
+
const [expanded, setExpanded] = React37.useState(false);
|
|
8528
8777
|
const isUser = m.role === "user";
|
|
8529
8778
|
const raw = m.text || "";
|
|
8530
8779
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
8531
8780
|
const body = clamped != null ? clamped : raw;
|
|
8532
8781
|
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,
|
|
8782
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-body", children: [
|
|
8783
|
+
m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
|
|
8784
|
+
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,
|
|
8785
|
+
body ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
|
|
8786
|
+
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 }),
|
|
8787
|
+
m.streaming ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
|
|
8539
8788
|
] }) : null,
|
|
8540
|
-
clamped != null ? /* @__PURE__ */ (0,
|
|
8541
|
-
/* @__PURE__ */ (0,
|
|
8789
|
+
clamped != null ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
|
|
8790
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
|
|
8542
8791
|
"Show more",
|
|
8543
|
-
/* @__PURE__ */ (0,
|
|
8544
|
-
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0,
|
|
8545
|
-
/* @__PURE__ */ (0,
|
|
8792
|
+
/* @__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" })
|
|
8793
|
+
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
|
|
8794
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
|
|
8546
8795
|
"Show less"
|
|
8547
8796
|
] }) : null,
|
|
8548
|
-
m.attachments && m.attachments.length ? /* @__PURE__ */ (0,
|
|
8549
|
-
m.packet ? /* @__PURE__ */ (0,
|
|
8797
|
+
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,
|
|
8798
|
+
m.packet ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
|
|
8550
8799
|
PacketCard,
|
|
8551
8800
|
{
|
|
8552
8801
|
packet: m.packet,
|
|
@@ -8556,44 +8805,44 @@ function MessageBody({ message: m, ctx }) {
|
|
|
8556
8805
|
applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
|
|
8557
8806
|
}
|
|
8558
8807
|
) : 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,
|
|
8808
|
+
m.citations && m.citations.length ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
|
|
8809
|
+
m.working ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-working", role: "status", children: [
|
|
8810
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
8811
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
|
|
8812
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
|
|
8813
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {})
|
|
8565
8814
|
] }),
|
|
8566
|
-
/* @__PURE__ */ (0,
|
|
8815
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-working-label", children: [
|
|
8567
8816
|
m.resumed ? "Resuming" : "Working",
|
|
8568
|
-
m.job && m.job.status ? /* @__PURE__ */ (0,
|
|
8817
|
+
m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-working-job", children: [
|
|
8569
8818
|
" \xB7 ",
|
|
8570
8819
|
m.job.status
|
|
8571
8820
|
] }) : null,
|
|
8572
|
-
m.job && m.job.detail ? /* @__PURE__ */ (0,
|
|
8821
|
+
m.job && m.job.detail ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-working-job", children: [
|
|
8573
8822
|
" \xB7 ",
|
|
8574
8823
|
m.job.detail
|
|
8575
8824
|
] }) : null
|
|
8576
8825
|
] }),
|
|
8577
|
-
m.jobId ? /* @__PURE__ */ (0,
|
|
8826
|
+
m.jobId ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
|
|
8578
8827
|
] }) : null,
|
|
8579
|
-
m.stopped ? /* @__PURE__ */ (0,
|
|
8580
|
-
/* @__PURE__ */ (0,
|
|
8828
|
+
m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-stopped", children: [
|
|
8829
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
8581
8830
|
"Stopped"
|
|
8582
8831
|
] }) : null,
|
|
8583
|
-
m.error ? /* @__PURE__ */ (0,
|
|
8584
|
-
/* @__PURE__ */ (0,
|
|
8585
|
-
/* @__PURE__ */ (0,
|
|
8586
|
-
m.retryable && ctx.onRetry ? /* @__PURE__ */ (0,
|
|
8587
|
-
/* @__PURE__ */ (0,
|
|
8832
|
+
m.error ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-error", role: "alert", children: [
|
|
8833
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
8834
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
|
|
8835
|
+
m.retryable && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
|
|
8836
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
8588
8837
|
"Retry"
|
|
8589
8838
|
] }) : null
|
|
8590
8839
|
] }) : null
|
|
8591
8840
|
] });
|
|
8592
8841
|
}
|
|
8593
8842
|
function useCopyRun() {
|
|
8594
|
-
const [done, setDone] =
|
|
8595
|
-
const t =
|
|
8596
|
-
|
|
8843
|
+
const [done, setDone] = React37.useState(false);
|
|
8844
|
+
const t = React37.useRef(null);
|
|
8845
|
+
React37.useEffect(() => () => {
|
|
8597
8846
|
if (t.current) clearTimeout(t.current);
|
|
8598
8847
|
}, []);
|
|
8599
8848
|
return [done, (text) => {
|
|
@@ -8613,16 +8862,16 @@ function RunActions({ group, ctx }) {
|
|
|
8613
8862
|
const isAssistant = group.role === "assistant";
|
|
8614
8863
|
const fb = last.feedback;
|
|
8615
8864
|
if (!ctx.messageActions) return null;
|
|
8616
|
-
return /* @__PURE__ */ (0,
|
|
8617
|
-
/* @__PURE__ */ (0,
|
|
8618
|
-
/* @__PURE__ */ (0,
|
|
8619
|
-
/* @__PURE__ */ (0,
|
|
8865
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
|
|
8866
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
|
|
8867
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
|
|
8868
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
|
|
8620
8869
|
] }),
|
|
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,
|
|
8870
|
+
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,
|
|
8871
|
+
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,
|
|
8872
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(React37.Fragment, { children: [
|
|
8873
|
+
/* @__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" }) }),
|
|
8874
|
+
/* @__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
8875
|
] }) : null,
|
|
8627
8876
|
ctx.extraActions ? ctx.extraActions(group) : null
|
|
8628
8877
|
] });
|
|
@@ -8632,22 +8881,22 @@ function ChatTurn({ group, ctx }) {
|
|
|
8632
8881
|
const name = isUser ? ctx.userName : group.author || ctx.assistantName;
|
|
8633
8882
|
const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
|
|
8634
8883
|
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,
|
|
8884
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
|
|
8885
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-turn-head", children: [
|
|
8886
|
+
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,
|
|
8887
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-who", children: name }),
|
|
8888
|
+
stamp ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(RelativeTime, { className: "fdc-when", value: stamp }) : null,
|
|
8889
|
+
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
8890
|
] }),
|
|
8642
|
-
/* @__PURE__ */ (0,
|
|
8643
|
-
group.messages.map((m) => /* @__PURE__ */ (0,
|
|
8644
|
-
/* @__PURE__ */ (0,
|
|
8891
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-turn-body", children: [
|
|
8892
|
+
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)),
|
|
8893
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)(RunActions, { group, ctx })
|
|
8645
8894
|
] })
|
|
8646
8895
|
] });
|
|
8647
8896
|
}
|
|
8648
8897
|
|
|
8649
8898
|
// src/components/chat/ChatTranscript.tsx
|
|
8650
|
-
var
|
|
8899
|
+
var import_jsx_runtime70 = require("react/jsx-runtime");
|
|
8651
8900
|
var GROUP_WINDOW = 6e4;
|
|
8652
8901
|
var STICK_PX = 100;
|
|
8653
8902
|
function groupMessages(list) {
|
|
@@ -8680,25 +8929,25 @@ function dayLabel(key) {
|
|
|
8680
8929
|
}
|
|
8681
8930
|
function Suggestions({ items = [], onPick }) {
|
|
8682
8931
|
if (!items.length) return null;
|
|
8683
|
-
return /* @__PURE__ */ (0,
|
|
8932
|
+
return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
|
|
8684
8933
|
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,
|
|
8934
|
+
return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
|
|
8935
|
+
it.icon ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
|
|
8936
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "fdc-suggest-text", children: [
|
|
8937
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fdc-suggest-label", children: it.label }),
|
|
8938
|
+
it.description ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fdc-suggest-desc", children: it.description }) : null
|
|
8690
8939
|
] }),
|
|
8691
|
-
/* @__PURE__ */ (0,
|
|
8940
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
|
|
8692
8941
|
] }, it.id || i);
|
|
8693
8942
|
}) });
|
|
8694
8943
|
}
|
|
8695
8944
|
function LoadingTurns() {
|
|
8696
|
-
return /* @__PURE__ */ (0,
|
|
8697
|
-
/* @__PURE__ */ (0,
|
|
8698
|
-
/* @__PURE__ */ (0,
|
|
8699
|
-
/* @__PURE__ */ (0,
|
|
8700
|
-
/* @__PURE__ */ (0,
|
|
8701
|
-
/* @__PURE__ */ (0,
|
|
8945
|
+
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: [
|
|
8946
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
|
|
8947
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-skel-lines", children: [
|
|
8948
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
|
|
8949
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
|
|
8950
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
|
|
8702
8951
|
] })
|
|
8703
8952
|
] }, i)) });
|
|
8704
8953
|
}
|
|
@@ -8715,10 +8964,10 @@ function ChatTranscript({
|
|
|
8715
8964
|
renderEmpty,
|
|
8716
8965
|
className = ""
|
|
8717
8966
|
}) {
|
|
8718
|
-
const scroller =
|
|
8719
|
-
const stick =
|
|
8720
|
-
const [pill, setPill] =
|
|
8721
|
-
const seen =
|
|
8967
|
+
const scroller = React38.useRef(null);
|
|
8968
|
+
const stick = React38.useRef(true);
|
|
8969
|
+
const [pill, setPill] = React38.useState(0);
|
|
8970
|
+
const seen = React38.useRef(0);
|
|
8722
8971
|
const toBottom = (smooth) => {
|
|
8723
8972
|
const el = scroller.current;
|
|
8724
8973
|
if (!el) return;
|
|
@@ -8737,7 +8986,7 @@ function ChatTranscript({
|
|
|
8737
8986
|
seen.current = messages.length;
|
|
8738
8987
|
}
|
|
8739
8988
|
};
|
|
8740
|
-
|
|
8989
|
+
React38.useLayoutEffect(() => {
|
|
8741
8990
|
const el = scroller.current;
|
|
8742
8991
|
if (!el) return;
|
|
8743
8992
|
if (stick.current) {
|
|
@@ -8745,7 +8994,7 @@ function ChatTranscript({
|
|
|
8745
8994
|
seen.current = messages.length;
|
|
8746
8995
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
8747
8996
|
}, [messages]);
|
|
8748
|
-
|
|
8997
|
+
React38.useEffect(() => {
|
|
8749
8998
|
const el = scroller.current;
|
|
8750
8999
|
const inner = el && el.firstChild;
|
|
8751
9000
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -8755,38 +9004,38 @@ function ChatTranscript({
|
|
|
8755
9004
|
ro.observe(inner);
|
|
8756
9005
|
return () => ro.disconnect();
|
|
8757
9006
|
}, []);
|
|
8758
|
-
const groups =
|
|
9007
|
+
const groups = React38.useMemo(() => groupMessages(messages), [messages]);
|
|
8759
9008
|
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,
|
|
9009
|
+
return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
9010
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
9011
|
+
status === "loading" || status === "resolving" ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(LoadingTurns, {}) : null,
|
|
9012
|
+
status === "disconnected" ? /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-dead", children: [
|
|
9013
|
+
/* @__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" }) }),
|
|
9014
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
|
|
9015
|
+
/* @__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." }),
|
|
9016
|
+
ctx.onReconnect ? /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
|
|
9017
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
8769
9018
|
"Try again"
|
|
8770
9019
|
] }) : null
|
|
8771
9020
|
] }) : null,
|
|
8772
|
-
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0,
|
|
8773
|
-
/* @__PURE__ */ (0,
|
|
8774
|
-
/* @__PURE__ */ (0,
|
|
8775
|
-
emptyDescription ? /* @__PURE__ */ (0,
|
|
8776
|
-
/* @__PURE__ */ (0,
|
|
9021
|
+
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-empty", children: [
|
|
9022
|
+
/* @__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" }) }),
|
|
9023
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("h3", { className: "fdc-empty-title", children: emptyTitle }),
|
|
9024
|
+
emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
|
|
9025
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)(Suggestions, { items: suggestions, onPick })
|
|
8777
9026
|
] }) : null,
|
|
8778
9027
|
groups.map((g, i) => {
|
|
8779
9028
|
const prev = groups[i - 1];
|
|
8780
9029
|
const k = dayKey(g.messages[0].timestamp);
|
|
8781
9030
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
8782
|
-
return /* @__PURE__ */ (0,
|
|
8783
|
-
showDay ? /* @__PURE__ */ (0,
|
|
8784
|
-
/* @__PURE__ */ (0,
|
|
9031
|
+
return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(React38.Fragment, { children: [
|
|
9032
|
+
showDay ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { children: dayLabel(k) }) }) : null,
|
|
9033
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)(ChatTurn, { group: g, ctx })
|
|
8785
9034
|
] }, g.key || i);
|
|
8786
9035
|
})
|
|
8787
9036
|
] }),
|
|
8788
|
-
pill ? /* @__PURE__ */ (0,
|
|
8789
|
-
/* @__PURE__ */ (0,
|
|
9037
|
+
pill ? /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
|
|
9038
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
|
|
8790
9039
|
pill,
|
|
8791
9040
|
" new message",
|
|
8792
9041
|
pill === 1 ? "" : "s"
|
|
@@ -8796,8 +9045,8 @@ function ChatTranscript({
|
|
|
8796
9045
|
var TranscriptKit = { groupMessages };
|
|
8797
9046
|
|
|
8798
9047
|
// src/components/chat/ChatComposer.tsx
|
|
8799
|
-
var
|
|
8800
|
-
var
|
|
9048
|
+
var React39 = __toESM(require("react"), 1);
|
|
9049
|
+
var import_jsx_runtime71 = require("react/jsx-runtime");
|
|
8801
9050
|
function ChatComposer({
|
|
8802
9051
|
onSubmit,
|
|
8803
9052
|
onStop,
|
|
@@ -8824,17 +9073,17 @@ function ChatComposer({
|
|
|
8824
9073
|
onReject,
|
|
8825
9074
|
onOpenAttachment
|
|
8826
9075
|
}) {
|
|
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 =
|
|
9076
|
+
const [text, setText] = React39.useState(draft || "");
|
|
9077
|
+
const [trigger, setTrigger] = React39.useState(null);
|
|
9078
|
+
const [mentionItems, setMentionItems] = React39.useState([]);
|
|
9079
|
+
const [listening, setListening] = React39.useState(false);
|
|
9080
|
+
const [notice, setNotice] = React39.useState(null);
|
|
9081
|
+
const editor = React39.useRef(null);
|
|
9082
|
+
const wrap = React39.useRef(null);
|
|
9083
|
+
const stopVoice = React39.useRef(null);
|
|
8835
9084
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
8836
9085
|
} });
|
|
8837
|
-
|
|
9086
|
+
React39.useEffect(() => {
|
|
8838
9087
|
if (draft != null && draft !== text) setText(draft);
|
|
8839
9088
|
}, [draft]);
|
|
8840
9089
|
const change = (v) => {
|
|
@@ -8868,7 +9117,7 @@ function ChatComposer({
|
|
|
8868
9117
|
e.preventDefault();
|
|
8869
9118
|
staged.add(found.files);
|
|
8870
9119
|
};
|
|
8871
|
-
|
|
9120
|
+
React39.useEffect(() => {
|
|
8872
9121
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
8873
9122
|
setMentionItems([]);
|
|
8874
9123
|
return;
|
|
@@ -8886,7 +9135,7 @@ function ChatComposer({
|
|
|
8886
9135
|
const q = (trigger.query || "").toLowerCase();
|
|
8887
9136
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
8888
9137
|
}, [trigger, mentionSources]);
|
|
8889
|
-
const slashItems =
|
|
9138
|
+
const slashItems = React39.useMemo(() => {
|
|
8890
9139
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
8891
9140
|
const q = (trigger.query || "").toLowerCase();
|
|
8892
9141
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -8900,7 +9149,7 @@ function ChatComposer({
|
|
|
8900
9149
|
description: it.description,
|
|
8901
9150
|
icon: it.icon,
|
|
8902
9151
|
meta: mention.meta,
|
|
8903
|
-
shortcut: slash.shortcut ? /* @__PURE__ */ (0,
|
|
9152
|
+
shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
|
|
8904
9153
|
onSelect: () => {
|
|
8905
9154
|
const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
|
|
8906
9155
|
editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
|
|
@@ -8963,14 +9212,14 @@ function ChatComposer({
|
|
|
8963
9212
|
stopVoice.current = typeof res === "function" ? res : () => {
|
|
8964
9213
|
};
|
|
8965
9214
|
};
|
|
8966
|
-
return /* @__PURE__ */ (0,
|
|
8967
|
-
queue.length ? /* @__PURE__ */ (0,
|
|
8968
|
-
/* @__PURE__ */ (0,
|
|
8969
|
-
/* @__PURE__ */ (0,
|
|
8970
|
-
onRemoveQueued ? /* @__PURE__ */ (0,
|
|
9215
|
+
return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
|
|
9216
|
+
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: [
|
|
9217
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
|
|
9218
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "fdc-queue-text", children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
|
|
9219
|
+
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
9220
|
] }, q.id)) }) : null,
|
|
8972
9221
|
sessionBar,
|
|
8973
|
-
/* @__PURE__ */ (0,
|
|
9222
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
|
|
8974
9223
|
Dropzone,
|
|
8975
9224
|
{
|
|
8976
9225
|
className: "fdc-field",
|
|
@@ -8984,9 +9233,9 @@ function ChatComposer({
|
|
|
8984
9233
|
disabled: !fileUploadHandler || disabled,
|
|
8985
9234
|
label: "Drop to attach",
|
|
8986
9235
|
hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
|
|
8987
|
-
children: /* @__PURE__ */ (0,
|
|
8988
|
-
staged.items.length ? /* @__PURE__ */ (0,
|
|
8989
|
-
/* @__PURE__ */ (0,
|
|
9236
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { ref: wrap, className: "fdc-field-inner", children: [
|
|
9237
|
+
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,
|
|
9238
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
|
|
8990
9239
|
MarkdownEditor,
|
|
8991
9240
|
{
|
|
8992
9241
|
ref: editor,
|
|
@@ -9005,33 +9254,33 @@ function ChatComposer({
|
|
|
9005
9254
|
ariaLabel: "Message"
|
|
9006
9255
|
}
|
|
9007
9256
|
),
|
|
9008
|
-
/* @__PURE__ */ (0,
|
|
9009
|
-
fileUploadHandler ? /* @__PURE__ */ (0,
|
|
9010
|
-
voiceHandler ? /* @__PURE__ */ (0,
|
|
9257
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "fdc-tools", children: [
|
|
9258
|
+
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,
|
|
9259
|
+
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
9260
|
toolbarExtras,
|
|
9012
|
-
/* @__PURE__ */ (0,
|
|
9013
|
-
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0,
|
|
9261
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "fdc-tools-gap" }),
|
|
9262
|
+
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
9263
|
text.length,
|
|
9015
9264
|
"/",
|
|
9016
9265
|
maxLength
|
|
9017
9266
|
] }) : null,
|
|
9018
|
-
busy ? /* @__PURE__ */ (0,
|
|
9019
|
-
/* @__PURE__ */ (0,
|
|
9020
|
-
/* @__PURE__ */ (0,
|
|
9021
|
-
] }) : /* @__PURE__ */ (0,
|
|
9022
|
-
/* @__PURE__ */ (0,
|
|
9023
|
-
/* @__PURE__ */ (0,
|
|
9267
|
+
busy ? /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
|
|
9268
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
9269
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { children: "Stop" })
|
|
9270
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
|
|
9271
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
|
|
9272
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "fdc-send-label", children: "Send" })
|
|
9024
9273
|
] })
|
|
9025
9274
|
] })
|
|
9026
9275
|
] })
|
|
9027
9276
|
}
|
|
9028
9277
|
),
|
|
9029
|
-
notice ? /* @__PURE__ */ (0,
|
|
9030
|
-
/* @__PURE__ */ (0,
|
|
9278
|
+
notice ? /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "fdc-notice", role: "status", children: [
|
|
9279
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
9031
9280
|
notice
|
|
9032
9281
|
] }) : null,
|
|
9033
|
-
hint && !notice ? /* @__PURE__ */ (0,
|
|
9034
|
-
/* @__PURE__ */ (0,
|
|
9282
|
+
hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "fdc-hint", children: hint }) : null,
|
|
9283
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
|
|
9035
9284
|
Popover,
|
|
9036
9285
|
{
|
|
9037
9286
|
open: menuOpen,
|
|
@@ -9045,12 +9294,12 @@ function ChatComposer({
|
|
|
9045
9294
|
returnFocus: false,
|
|
9046
9295
|
closeOnOutside: true,
|
|
9047
9296
|
label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
|
|
9048
|
-
children: /* @__PURE__ */ (0,
|
|
9297
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
|
|
9049
9298
|
Menu,
|
|
9050
9299
|
{
|
|
9051
9300
|
items: menuItems,
|
|
9052
9301
|
autoFocus: false,
|
|
9053
|
-
header: /* @__PURE__ */ (0,
|
|
9302
|
+
header: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
|
|
9054
9303
|
onClose: () => setTrigger(null)
|
|
9055
9304
|
}
|
|
9056
9305
|
)
|
|
@@ -9060,12 +9309,12 @@ function ChatComposer({
|
|
|
9060
9309
|
}
|
|
9061
9310
|
|
|
9062
9311
|
// src/components/chat/ChatSessionBar.tsx
|
|
9063
|
-
var
|
|
9064
|
-
var
|
|
9312
|
+
var React40 = __toESM(require("react"), 1);
|
|
9313
|
+
var import_jsx_runtime72 = require("react/jsx-runtime");
|
|
9065
9314
|
var compact2 = meterFormats.compact;
|
|
9066
9315
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
9067
|
-
const [open, setOpen] =
|
|
9068
|
-
const anchor =
|
|
9316
|
+
const [open, setOpen] = React40.useState(false);
|
|
9317
|
+
const anchor = React40.useRef(null);
|
|
9069
9318
|
const stats = sessionStats || null;
|
|
9070
9319
|
const cu = contextUsage || null;
|
|
9071
9320
|
const limits = usageLimits || null;
|
|
@@ -9080,9 +9329,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9080
9329
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
9081
9330
|
if (cu) bits.push(pct + "% context");
|
|
9082
9331
|
const expandable = !!(cu || limits);
|
|
9083
|
-
return /* @__PURE__ */ (0,
|
|
9084
|
-
/* @__PURE__ */ (0,
|
|
9085
|
-
/* @__PURE__ */ (0,
|
|
9332
|
+
return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(React40.Fragment, { children: [
|
|
9333
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "fdc-bar", children: [
|
|
9334
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
|
|
9086
9335
|
"button",
|
|
9087
9336
|
{
|
|
9088
9337
|
type: "button",
|
|
@@ -9093,16 +9342,16 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9093
9342
|
"aria-expanded": expandable ? open : void 0,
|
|
9094
9343
|
"aria-label": expandable ? "Usage details" : void 0,
|
|
9095
9344
|
children: [
|
|
9096
|
-
cu ? /* @__PURE__ */ (0,
|
|
9097
|
-
/* @__PURE__ */ (0,
|
|
9098
|
-
expandable ? /* @__PURE__ */ (0,
|
|
9345
|
+
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,
|
|
9346
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "fdc-bar-text", children: bits.join(" \xB7 ") }),
|
|
9347
|
+
expandable ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
|
|
9099
9348
|
]
|
|
9100
9349
|
}
|
|
9101
9350
|
),
|
|
9102
9351
|
extras
|
|
9103
9352
|
] }),
|
|
9104
|
-
/* @__PURE__ */ (0,
|
|
9105
|
-
cu ? /* @__PURE__ */ (0,
|
|
9353
|
+
/* @__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: [
|
|
9354
|
+
cu ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
|
|
9106
9355
|
SegmentedMeter,
|
|
9107
9356
|
{
|
|
9108
9357
|
total,
|
|
@@ -9114,9 +9363,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9114
9363
|
remainderLabel: "Free"
|
|
9115
9364
|
}
|
|
9116
9365
|
) }) : null,
|
|
9117
|
-
limits && limits.length ? /* @__PURE__ */ (0,
|
|
9118
|
-
/* @__PURE__ */ (0,
|
|
9119
|
-
/* @__PURE__ */ (0,
|
|
9366
|
+
limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("section", { className: "fdc-usage-sec", children: [
|
|
9367
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
|
|
9368
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
|
|
9120
9369
|
QuotaRow,
|
|
9121
9370
|
{
|
|
9122
9371
|
label: l.label,
|
|
@@ -9126,32 +9375,32 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9126
9375
|
l.id
|
|
9127
9376
|
)) })
|
|
9128
9377
|
] }) : null,
|
|
9129
|
-
stats ? /* @__PURE__ */ (0,
|
|
9130
|
-
stats.elapsedMs ? /* @__PURE__ */ (0,
|
|
9131
|
-
/* @__PURE__ */ (0,
|
|
9132
|
-
/* @__PURE__ */ (0,
|
|
9378
|
+
stats ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
|
|
9379
|
+
stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { children: [
|
|
9380
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: "Session" }),
|
|
9381
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
|
|
9133
9382
|
] }) : null,
|
|
9134
|
-
stats.tokens ? /* @__PURE__ */ (0,
|
|
9135
|
-
/* @__PURE__ */ (0,
|
|
9136
|
-
/* @__PURE__ */ (0,
|
|
9383
|
+
stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { children: [
|
|
9384
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: "Tokens" }),
|
|
9385
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
|
|
9137
9386
|
] }) : null,
|
|
9138
|
-
stats.costUsd != null ? /* @__PURE__ */ (0,
|
|
9139
|
-
/* @__PURE__ */ (0,
|
|
9140
|
-
/* @__PURE__ */ (0,
|
|
9387
|
+
stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { children: [
|
|
9388
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: "Cost" }),
|
|
9389
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("b", { className: "fd-tabular", children: [
|
|
9141
9390
|
"$",
|
|
9142
9391
|
Number(stats.costUsd).toFixed(3)
|
|
9143
9392
|
] })
|
|
9144
9393
|
] }) : null,
|
|
9145
|
-
stats.turns ? /* @__PURE__ */ (0,
|
|
9146
|
-
/* @__PURE__ */ (0,
|
|
9147
|
-
/* @__PURE__ */ (0,
|
|
9394
|
+
stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { children: [
|
|
9395
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: "Turns" }),
|
|
9396
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("b", { className: "fd-tabular", children: stats.turns })
|
|
9148
9397
|
] }) : null
|
|
9149
9398
|
] }) : null,
|
|
9150
|
-
onClear ? /* @__PURE__ */ (0,
|
|
9399
|
+
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
9400
|
setOpen(false);
|
|
9152
9401
|
onClear();
|
|
9153
9402
|
}, children: [
|
|
9154
|
-
/* @__PURE__ */ (0,
|
|
9403
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
|
|
9155
9404
|
"Clear conversation"
|
|
9156
9405
|
] }) }) : null
|
|
9157
9406
|
] }) })
|
|
@@ -9188,7 +9437,7 @@ function ModelControls({
|
|
|
9188
9437
|
disabled: m.disabled,
|
|
9189
9438
|
checked: m.id === (current2 && current2.id),
|
|
9190
9439
|
meta: m.meta,
|
|
9191
|
-
shortcut: m.shortcut ? /* @__PURE__ */ (0,
|
|
9440
|
+
shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
|
|
9192
9441
|
onSelect: () => onModelChange && onModelChange(m.id)
|
|
9193
9442
|
});
|
|
9194
9443
|
const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
|
|
@@ -9201,15 +9450,15 @@ function ModelControls({
|
|
|
9201
9450
|
items.push({ kind: "section", label: "Fast mode" });
|
|
9202
9451
|
items.push({
|
|
9203
9452
|
kind: "custom",
|
|
9204
|
-
render: () => /* @__PURE__ */ (0,
|
|
9205
|
-
/* @__PURE__ */ (0,
|
|
9206
|
-
/* @__PURE__ */ (0,
|
|
9207
|
-
/* @__PURE__ */ (0,
|
|
9453
|
+
render: () => /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("label", { className: "fdc-switchrow", children: [
|
|
9454
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: fastModeLabel }),
|
|
9455
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
|
|
9456
|
+
/* @__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
9457
|
] })
|
|
9209
9458
|
});
|
|
9210
9459
|
}
|
|
9211
|
-
return /* @__PURE__ */ (0,
|
|
9212
|
-
/* @__PURE__ */ (0,
|
|
9460
|
+
return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(React40.Fragment, { children: [
|
|
9461
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
|
|
9213
9462
|
MenuButton,
|
|
9214
9463
|
{
|
|
9215
9464
|
items,
|
|
@@ -9220,7 +9469,7 @@ function ModelControls({
|
|
|
9220
9469
|
title: "Choose a model"
|
|
9221
9470
|
}
|
|
9222
9471
|
),
|
|
9223
|
-
effortLevels && effortLevels.length ? /* @__PURE__ */ (0,
|
|
9472
|
+
effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
|
|
9224
9473
|
MenuButton,
|
|
9225
9474
|
{
|
|
9226
9475
|
placement: "top-end",
|
|
@@ -9241,7 +9490,7 @@ function ModelControls({
|
|
|
9241
9490
|
}
|
|
9242
9491
|
|
|
9243
9492
|
// src/components/chat/AgentChatPanel.tsx
|
|
9244
|
-
var
|
|
9493
|
+
var import_jsx_runtime73 = require("react/jsx-runtime");
|
|
9245
9494
|
var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
|
|
9246
9495
|
function AgentChatPanel({
|
|
9247
9496
|
/* required */
|
|
@@ -9325,11 +9574,11 @@ function AgentChatPanel({
|
|
|
9325
9574
|
onFeedback,
|
|
9326
9575
|
onEditMessage
|
|
9327
9576
|
}) {
|
|
9328
|
-
const [panelWidth, setPanelWidth] =
|
|
9329
|
-
const [applied, setApplied] =
|
|
9330
|
-
const [draft, setDraft] =
|
|
9331
|
-
const dragging =
|
|
9332
|
-
|
|
9577
|
+
const [panelWidth, setPanelWidth] = React41.useState(width);
|
|
9578
|
+
const [applied, setApplied] = React41.useState({});
|
|
9579
|
+
const [draft, setDraft] = React41.useState("");
|
|
9580
|
+
const dragging = React41.useRef(null);
|
|
9581
|
+
React41.useEffect(() => setPanelWidth(width), [width]);
|
|
9333
9582
|
const engine = useChatEngine({
|
|
9334
9583
|
contextType,
|
|
9335
9584
|
contextId,
|
|
@@ -9395,7 +9644,7 @@ function AgentChatPanel({
|
|
|
9395
9644
|
onReconnect: engine.reload,
|
|
9396
9645
|
deadTitle: "The assistant isn\u2019t reachable"
|
|
9397
9646
|
};
|
|
9398
|
-
const sessionBar = /* @__PURE__ */ (0,
|
|
9647
|
+
const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9399
9648
|
ChatSessionBar,
|
|
9400
9649
|
{
|
|
9401
9650
|
sessionStats,
|
|
@@ -9404,7 +9653,7 @@ function AgentChatPanel({
|
|
|
9404
9653
|
onClear: engine.visible.length ? engine.clear : void 0
|
|
9405
9654
|
}
|
|
9406
9655
|
);
|
|
9407
|
-
const modelControls = /* @__PURE__ */ (0,
|
|
9656
|
+
const modelControls = /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9408
9657
|
ModelControls,
|
|
9409
9658
|
{
|
|
9410
9659
|
models,
|
|
@@ -9419,7 +9668,7 @@ function AgentChatPanel({
|
|
|
9419
9668
|
narrow
|
|
9420
9669
|
}
|
|
9421
9670
|
);
|
|
9422
|
-
const threadMenu = threads && threads.length ? /* @__PURE__ */ (0,
|
|
9671
|
+
const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9423
9672
|
MenuButton,
|
|
9424
9673
|
{
|
|
9425
9674
|
variant: "ghost",
|
|
@@ -9446,7 +9695,7 @@ function AgentChatPanel({
|
|
|
9446
9695
|
})))
|
|
9447
9696
|
}
|
|
9448
9697
|
) : null;
|
|
9449
|
-
return /* @__PURE__ */ (0,
|
|
9698
|
+
return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
|
|
9450
9699
|
"aside",
|
|
9451
9700
|
{
|
|
9452
9701
|
className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
|
|
@@ -9457,7 +9706,7 @@ function AgentChatPanel({
|
|
|
9457
9706
|
},
|
|
9458
9707
|
"aria-label": title,
|
|
9459
9708
|
children: [
|
|
9460
|
-
surface === "sidebar" && resizable ? /* @__PURE__ */ (0,
|
|
9709
|
+
surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9461
9710
|
"div",
|
|
9462
9711
|
{
|
|
9463
9712
|
className: "fdc-grip",
|
|
@@ -9472,20 +9721,20 @@ function AgentChatPanel({
|
|
|
9472
9721
|
}
|
|
9473
9722
|
}
|
|
9474
9723
|
) : null,
|
|
9475
|
-
showHeader ? /* @__PURE__ */ (0,
|
|
9476
|
-
/* @__PURE__ */ (0,
|
|
9477
|
-
/* @__PURE__ */ (0,
|
|
9478
|
-
/* @__PURE__ */ (0,
|
|
9479
|
-
subtitle ? /* @__PURE__ */ (0,
|
|
9724
|
+
showHeader ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("header", { className: "fdc-head", children: [
|
|
9725
|
+
/* @__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 }) }),
|
|
9726
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fdc-head-titles", children: [
|
|
9727
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-head-title", children: title }),
|
|
9728
|
+
subtitle ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-head-sub", children: subtitle }) : null
|
|
9480
9729
|
] }),
|
|
9481
|
-
/* @__PURE__ */ (0,
|
|
9730
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fdc-head-acts", children: [
|
|
9482
9731
|
headerActions,
|
|
9483
9732
|
threadMenu,
|
|
9484
|
-
onNewThread ? /* @__PURE__ */ (0,
|
|
9485
|
-
onClose ? /* @__PURE__ */ (0,
|
|
9733
|
+
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,
|
|
9734
|
+
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
9735
|
] })
|
|
9487
9736
|
] }) : null,
|
|
9488
|
-
/* @__PURE__ */ (0,
|
|
9737
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9489
9738
|
ChatTranscript,
|
|
9490
9739
|
{
|
|
9491
9740
|
messages: engine.visible,
|
|
@@ -9500,7 +9749,7 @@ function AgentChatPanel({
|
|
|
9500
9749
|
renderEmpty
|
|
9501
9750
|
}
|
|
9502
9751
|
),
|
|
9503
|
-
/* @__PURE__ */ (0,
|
|
9752
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9504
9753
|
ChatComposer,
|
|
9505
9754
|
{
|
|
9506
9755
|
onSubmit: (text, atts) => engine.send(text, atts),
|
|
@@ -9533,7 +9782,7 @@ function AgentChatPanel({
|
|
|
9533
9782
|
}
|
|
9534
9783
|
|
|
9535
9784
|
// src/kits/query.ts
|
|
9536
|
-
var
|
|
9785
|
+
var React42 = __toESM(require("react"), 1);
|
|
9537
9786
|
function eqFilter(get2) {
|
|
9538
9787
|
return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
|
|
9539
9788
|
}
|
|
@@ -9565,22 +9814,22 @@ function compare(a, b, dir) {
|
|
|
9565
9814
|
var API = null;
|
|
9566
9815
|
var PREFS = null;
|
|
9567
9816
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
9568
|
-
const [query, setQuery] =
|
|
9817
|
+
const [query, setQuery] = React42.useState(() => {
|
|
9569
9818
|
const store = PREFS || window.PlannerPrefs;
|
|
9570
9819
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
9571
9820
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
9572
9821
|
});
|
|
9573
|
-
const savePref =
|
|
9822
|
+
const savePref = React42.useCallback((patch2) => {
|
|
9574
9823
|
const store = PREFS || window.PlannerPrefs;
|
|
9575
9824
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
9576
9825
|
}, [prefsKey]);
|
|
9577
|
-
const [res, setRes] =
|
|
9578
|
-
const [loading, setLoading] =
|
|
9579
|
-
const seq2 =
|
|
9826
|
+
const [res, setRes] = React42.useState(null);
|
|
9827
|
+
const [loading, setLoading] = React42.useState(true);
|
|
9828
|
+
const seq2 = React42.useRef(0);
|
|
9580
9829
|
const depKey = (deps || []).join("|");
|
|
9581
9830
|
const paramKey = JSON.stringify(params || {});
|
|
9582
9831
|
const queryKey = JSON.stringify(query);
|
|
9583
|
-
|
|
9832
|
+
React42.useEffect(() => {
|
|
9584
9833
|
const id = ++seq2.current;
|
|
9585
9834
|
setLoading(true);
|
|
9586
9835
|
const t = setTimeout(() => {
|
|
@@ -9919,6 +10168,7 @@ function createVersionStore(initialState, options) {
|
|
|
9919
10168
|
Dropzone,
|
|
9920
10169
|
DropzoneKit,
|
|
9921
10170
|
EmptyState,
|
|
10171
|
+
EntityRow,
|
|
9922
10172
|
FeatureGate,
|
|
9923
10173
|
FileChip,
|
|
9924
10174
|
FileGrid,
|
|
@@ -9991,11 +10241,16 @@ function createVersionStore(initialState, options) {
|
|
|
9991
10241
|
Tooltip,
|
|
9992
10242
|
Topbar,
|
|
9993
10243
|
TranscriptKit,
|
|
10244
|
+
TransferList,
|
|
9994
10245
|
UseFeatureStatus,
|
|
9995
10246
|
UseRuntimeMode,
|
|
10247
|
+
VIRTUAL_LIST_BUFFER_ROWS,
|
|
10248
|
+
VirtualList,
|
|
9996
10249
|
acceptMatches,
|
|
9997
10250
|
anyOfFilter,
|
|
9998
10251
|
channelWeightOf,
|
|
10252
|
+
computeNeedMore,
|
|
10253
|
+
computeVirtualWindow,
|
|
9999
10254
|
createVersionStore,
|
|
10000
10255
|
eqFilter,
|
|
10001
10256
|
extensionOf,
|