@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.js
CHANGED
|
@@ -1069,6 +1069,9 @@ var BANDS = {
|
|
|
1069
1069
|
strong: { n: 3, label: "Strong" },
|
|
1070
1070
|
dominant: { n: 4, label: "Dominant" }
|
|
1071
1071
|
};
|
|
1072
|
+
function formatCrp(crp) {
|
|
1073
|
+
return crp.toFixed(1);
|
|
1074
|
+
}
|
|
1072
1075
|
function CsiMeter({ band = "weak", size = 4, width = 5, gap = 2 }) {
|
|
1073
1076
|
const n = (BANDS[band] || BANDS.weak).n;
|
|
1074
1077
|
return /* @__PURE__ */ jsx26("span", { className: "fd-meter", style: { gap: gap + "px" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx26(
|
|
@@ -1091,7 +1094,7 @@ function CsiBadge({ band = "weak", crp, size = "compact", preview = false, alert
|
|
|
1091
1094
|
alert ? /* @__PURE__ */ jsx26("span", { className: "fd-badge-dot", style: { background: "var(--csi-alert)" }, "aria-label": "Fixable" }) : null,
|
|
1092
1095
|
/* @__PURE__ */ jsx26(CsiMeter, { band, size: size === "medium" ? 11 : 9, width: size === "medium" ? 4 : 3 }),
|
|
1093
1096
|
b.label,
|
|
1094
|
-
crp !== void 0 && crp !== null ? /* @__PURE__ */ jsx26("span", { className: "fd-csi-crp", children: crp }) : null
|
|
1097
|
+
crp !== void 0 && crp !== null ? /* @__PURE__ */ jsx26("span", { className: "fd-csi-crp", children: formatCrp(crp) }) : null
|
|
1095
1098
|
]
|
|
1096
1099
|
}
|
|
1097
1100
|
);
|
|
@@ -1100,7 +1103,7 @@ function CsiHero({ band = "weak", crp, label, className = "" }) {
|
|
|
1100
1103
|
const b = BANDS[band] || BANDS.weak;
|
|
1101
1104
|
const mark = "var(--csi-" + b.n + "-mark)";
|
|
1102
1105
|
return /* @__PURE__ */ jsxs21("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 10 }, children: [
|
|
1103
|
-
/* @__PURE__ */ jsx26("span", { className: "fd-csi-hero-num", style: { color: mark }, children: crp }),
|
|
1106
|
+
/* @__PURE__ */ jsx26("span", { className: "fd-csi-hero-num", style: { color: mark }, children: crp !== void 0 && crp !== null ? formatCrp(crp) : "" }),
|
|
1104
1107
|
/* @__PURE__ */ jsx26("span", { className: "fd-label-lg", style: { color: "var(--text-2)" }, children: label || b.label }),
|
|
1105
1108
|
/* @__PURE__ */ jsx26("span", { className: "fd-meter", style: { gap: 3, color: mark, width: 120 }, children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx26("span", { className: "fd-meter-seg" + (i <= b.n ? " is-on" : ""), style: { height: 6, flex: 1 } }, i)) })
|
|
1106
1109
|
] });
|
|
@@ -2428,56 +2431,140 @@ function StepList({
|
|
|
2428
2431
|
] });
|
|
2429
2432
|
}
|
|
2430
2433
|
|
|
2431
|
-
// src/components/
|
|
2434
|
+
// src/components/data/VirtualList.tsx
|
|
2432
2435
|
import * as React15 from "react";
|
|
2433
2436
|
import { jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2434
|
-
|
|
2435
|
-
|
|
2437
|
+
var VIRTUAL_LIST_BUFFER_ROWS = 20;
|
|
2438
|
+
function computeVirtualWindow(opts) {
|
|
2439
|
+
const { scrollTop, viewportHeight, itemHeight, itemCount, bufferRows = VIRTUAL_LIST_BUFFER_ROWS } = opts;
|
|
2440
|
+
if (itemCount <= 0 || itemHeight <= 0) {
|
|
2441
|
+
return { visibleStart: 0, visibleEnd: -1, startIndex: 0, endIndex: -1, totalHeight: 0, offsetY: 0 };
|
|
2442
|
+
}
|
|
2443
|
+
const lastPossible = itemCount - 1;
|
|
2444
|
+
const visibleStart = Math.min(lastPossible, Math.max(0, Math.floor(scrollTop / itemHeight)));
|
|
2445
|
+
const visibleRows = Math.max(1, Math.ceil(viewportHeight / itemHeight));
|
|
2446
|
+
const visibleEnd = Math.min(lastPossible, visibleStart + visibleRows - 1);
|
|
2447
|
+
const startIndex = Math.max(0, visibleStart - bufferRows);
|
|
2448
|
+
const endIndex = Math.min(lastPossible, visibleEnd + bufferRows);
|
|
2449
|
+
return {
|
|
2450
|
+
visibleStart,
|
|
2451
|
+
visibleEnd,
|
|
2452
|
+
startIndex,
|
|
2453
|
+
endIndex,
|
|
2454
|
+
totalHeight: itemCount * itemHeight,
|
|
2455
|
+
offsetY: startIndex * itemHeight
|
|
2456
|
+
};
|
|
2457
|
+
}
|
|
2458
|
+
function computeNeedMore(win, itemCount, bufferRows = VIRTUAL_LIST_BUFFER_ROWS) {
|
|
2459
|
+
if (itemCount <= 0) return { start: true, end: true };
|
|
2460
|
+
return {
|
|
2461
|
+
start: win.visibleStart <= bufferRows,
|
|
2462
|
+
end: itemCount - 1 - win.visibleEnd <= bufferRows
|
|
2463
|
+
};
|
|
2464
|
+
}
|
|
2465
|
+
function VirtualList({
|
|
2466
|
+
items,
|
|
2467
|
+
itemHeight,
|
|
2468
|
+
renderItem,
|
|
2469
|
+
onNeedMore,
|
|
2470
|
+
hasMore,
|
|
2471
|
+
loading = false,
|
|
2472
|
+
keyOf,
|
|
2473
|
+
height = 400,
|
|
2474
|
+
emptyState,
|
|
2475
|
+
className = "",
|
|
2476
|
+
style
|
|
2477
|
+
}) {
|
|
2478
|
+
const [scrollTop, setScrollTop] = React15.useState(0);
|
|
2479
|
+
const requested = React15.useRef({ start: null, end: null });
|
|
2480
|
+
const win = React15.useMemo(
|
|
2481
|
+
() => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: items.length }),
|
|
2482
|
+
[scrollTop, height, itemHeight, items.length]
|
|
2483
|
+
);
|
|
2484
|
+
const need = React15.useMemo(() => computeNeedMore(win, items.length), [win, items.length]);
|
|
2485
|
+
const wantStart = need.start && hasMore?.start !== false;
|
|
2486
|
+
const wantEnd = need.end && hasMore?.end !== false;
|
|
2436
2487
|
React15.useEffect(() => {
|
|
2437
|
-
if (
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
] })
|
|
2448
|
-
|
|
2488
|
+
if (loading || !wantStart || requested.current.start === items.length) return;
|
|
2489
|
+
requested.current.start = items.length;
|
|
2490
|
+
onNeedMore("start");
|
|
2491
|
+
}, [wantStart, loading, items.length, onNeedMore]);
|
|
2492
|
+
React15.useEffect(() => {
|
|
2493
|
+
if (loading || !wantEnd || requested.current.end === items.length) return;
|
|
2494
|
+
requested.current.end = items.length;
|
|
2495
|
+
onNeedMore("end");
|
|
2496
|
+
}, [wantEnd, loading, items.length, onNeedMore]);
|
|
2497
|
+
if (!items.length && !loading && emptyState) {
|
|
2498
|
+
return /* @__PURE__ */ jsx37("div", { className: ["fd-vlist", className].filter(Boolean).join(" "), style: { height, overflow: "auto", ...style }, children: emptyState });
|
|
2499
|
+
}
|
|
2500
|
+
const rows = [];
|
|
2501
|
+
for (let i = win.startIndex; i <= win.endIndex; i++) {
|
|
2502
|
+
const item = items[i];
|
|
2503
|
+
if (item === void 0) continue;
|
|
2504
|
+
rows.push(
|
|
2505
|
+
/* @__PURE__ */ jsx37("div", { style: { height: itemHeight, boxSizing: "border-box" }, children: renderItem(item, i) }, keyOf(item))
|
|
2506
|
+
);
|
|
2507
|
+
}
|
|
2508
|
+
return /* @__PURE__ */ jsxs33(
|
|
2509
|
+
"div",
|
|
2510
|
+
{
|
|
2511
|
+
className: ["fd-vlist", className].filter(Boolean).join(" "),
|
|
2512
|
+
style: { height, overflowY: "auto", overflowX: "hidden", position: "relative", ...style },
|
|
2513
|
+
onScroll: (e) => setScrollTop(e.currentTarget.scrollTop),
|
|
2514
|
+
children: [
|
|
2515
|
+
/* @__PURE__ */ jsx37("div", { style: { height: win.totalHeight, position: "relative" }, children: /* @__PURE__ */ jsx37("div", { style: { position: "absolute", top: win.offsetY, left: 0, right: 0 }, children: rows }) }),
|
|
2516
|
+
loading ? /* @__PURE__ */ jsx37("div", { style: { position: "sticky", bottom: 0, left: 0, right: 0, display: "grid", placeItems: "center", padding: "8px 0", background: "var(--surface)" }, children: /* @__PURE__ */ jsx37("span", { className: "fd-spinner", "aria-hidden": "true" }) }) : null
|
|
2517
|
+
]
|
|
2518
|
+
}
|
|
2519
|
+
);
|
|
2449
2520
|
}
|
|
2450
2521
|
|
|
2451
|
-
// src/components/
|
|
2522
|
+
// src/components/data/EntityRow.tsx
|
|
2452
2523
|
import { jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2453
|
-
function
|
|
2454
|
-
return /* @__PURE__ */ jsxs34(
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2524
|
+
function EntityRow({ title, meta, action, draggable = false, onDragStart, onDragEnd, style, className = "" }) {
|
|
2525
|
+
return /* @__PURE__ */ jsxs34(
|
|
2526
|
+
"div",
|
|
2527
|
+
{
|
|
2528
|
+
draggable,
|
|
2529
|
+
onDragStart,
|
|
2530
|
+
onDragEnd,
|
|
2531
|
+
className: ["fd-erow", className].filter(Boolean).join(" "),
|
|
2532
|
+
style: {
|
|
2533
|
+
display: "flex",
|
|
2534
|
+
alignItems: "center",
|
|
2535
|
+
gap: 8,
|
|
2536
|
+
height: "100%",
|
|
2537
|
+
padding: "0 8px",
|
|
2538
|
+
borderRadius: 6,
|
|
2539
|
+
cursor: draggable ? "grab" : void 0,
|
|
2540
|
+
...style
|
|
2541
|
+
},
|
|
2542
|
+
children: [
|
|
2543
|
+
draggable ? /* @__PURE__ */ jsx38("i", { className: "ph ph-dots-six-vertical", "aria-hidden": "true", style: { fontSize: 13, flex: "none", color: "var(--text-muted)" } }) : null,
|
|
2544
|
+
/* @__PURE__ */ jsxs34("span", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: 1 }, children: [
|
|
2545
|
+
/* @__PURE__ */ jsx38("span", { className: "fd-body-sm", style: { fontWeight: 600, color: "var(--text)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: title }),
|
|
2546
|
+
meta ? /* @__PURE__ */ jsx38("span", { style: { fontSize: "var(--overline-size)", color: "var(--text-muted)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: meta }) : null
|
|
2547
|
+
] }),
|
|
2548
|
+
action ? /* @__PURE__ */ jsx38(
|
|
2549
|
+
IconButton,
|
|
2550
|
+
{
|
|
2551
|
+
icon: action.icon,
|
|
2552
|
+
label: action.label,
|
|
2553
|
+
size: "sm",
|
|
2554
|
+
onClick: action.onClick,
|
|
2555
|
+
style: { color: action.tone === "add" ? "var(--ok-text)" : action.tone === "remove" ? "var(--danger-text)" : void 0 }
|
|
2556
|
+
}
|
|
2557
|
+
) : null
|
|
2558
|
+
]
|
|
2559
|
+
}
|
|
2560
|
+
);
|
|
2464
2561
|
}
|
|
2465
2562
|
|
|
2466
|
-
// src/components/
|
|
2467
|
-
import
|
|
2468
|
-
function Switch({ label, description, className = "", ...rest }) {
|
|
2469
|
-
return /* @__PURE__ */ jsxs35("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
|
|
2470
|
-
/* @__PURE__ */ jsx39("input", { type: "checkbox", role: "switch", ...rest }),
|
|
2471
|
-
/* @__PURE__ */ jsx39("span", { className: "fd-switch-track", children: /* @__PURE__ */ jsx39("span", { className: "fd-switch-thumb" }) }),
|
|
2472
|
-
label ? /* @__PURE__ */ jsxs35("span", { className: "fd-choice-text", children: [
|
|
2473
|
-
/* @__PURE__ */ jsx39("span", { className: "fd-switch-label", children: label }),
|
|
2474
|
-
description ? /* @__PURE__ */ jsx39("span", { className: "fd-choice-desc", children: description }) : null
|
|
2475
|
-
] }) : null
|
|
2476
|
-
] });
|
|
2477
|
-
}
|
|
2563
|
+
// src/components/data/TransferList.tsx
|
|
2564
|
+
import * as React16 from "react";
|
|
2478
2565
|
|
|
2479
2566
|
// src/components/forms/Input.tsx
|
|
2480
|
-
import { jsx as
|
|
2567
|
+
import { jsx as jsx39, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2481
2568
|
function Input({
|
|
2482
2569
|
label,
|
|
2483
2570
|
help,
|
|
@@ -2505,27 +2592,27 @@ function Input({
|
|
|
2505
2592
|
size === "lg" ? "fd-input-lg" : "",
|
|
2506
2593
|
className
|
|
2507
2594
|
].filter(Boolean).join(" ");
|
|
2508
|
-
return /* @__PURE__ */
|
|
2509
|
-
label ? /* @__PURE__ */
|
|
2595
|
+
return /* @__PURE__ */ jsxs35("div", { className: "fd-field", style, children: [
|
|
2596
|
+
label ? /* @__PURE__ */ jsxs35("label", { className: "fd-field-label", htmlFor: fieldId, children: [
|
|
2510
2597
|
label,
|
|
2511
|
-
required ? /* @__PURE__ */
|
|
2598
|
+
required ? /* @__PURE__ */ jsx39("span", { className: "fd-field-req", "aria-hidden": "true", children: "*" }) : null
|
|
2512
2599
|
] }) : null,
|
|
2513
|
-
/* @__PURE__ */
|
|
2514
|
-
icon ? /* @__PURE__ */
|
|
2515
|
-
prefix ? /* @__PURE__ */
|
|
2516
|
-
/* @__PURE__ */
|
|
2517
|
-
loading ? /* @__PURE__ */
|
|
2518
|
-
suffix && !loading ? /* @__PURE__ */
|
|
2600
|
+
/* @__PURE__ */ jsxs35("div", { className: box, children: [
|
|
2601
|
+
icon ? /* @__PURE__ */ jsx39("span", { className: "fd-input-icon", children: /* @__PURE__ */ jsx39("i", { className: "ph ph-" + icon, "aria-hidden": "true" }) }) : null,
|
|
2602
|
+
prefix ? /* @__PURE__ */ jsx39("span", { className: "fd-input-affix", children: prefix }) : null,
|
|
2603
|
+
/* @__PURE__ */ jsx39("input", { id: fieldId, disabled, style: inputStyle, "aria-invalid": error ? "true" : void 0, ...rest }),
|
|
2604
|
+
loading ? /* @__PURE__ */ jsx39("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading" }) : null,
|
|
2605
|
+
suffix && !loading ? /* @__PURE__ */ jsx39("span", { className: "fd-input-affix", children: suffix }) : null
|
|
2519
2606
|
] }),
|
|
2520
|
-
error ? /* @__PURE__ */
|
|
2521
|
-
/* @__PURE__ */
|
|
2607
|
+
error ? /* @__PURE__ */ jsxs35("span", { className: "fd-field-error", children: [
|
|
2608
|
+
/* @__PURE__ */ jsx39("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
2522
2609
|
error
|
|
2523
|
-
] }) : help ? /* @__PURE__ */
|
|
2610
|
+
] }) : help ? /* @__PURE__ */ jsx39("span", { className: "fd-field-help", children: help }) : null
|
|
2524
2611
|
] });
|
|
2525
2612
|
}
|
|
2526
2613
|
|
|
2527
2614
|
// src/components/forms/SearchField.tsx
|
|
2528
|
-
import { jsx as
|
|
2615
|
+
import { jsx as jsx40 } from "react/jsx-runtime";
|
|
2529
2616
|
function SearchField({
|
|
2530
2617
|
value,
|
|
2531
2618
|
onChange,
|
|
@@ -2540,7 +2627,7 @@ function SearchField({
|
|
|
2540
2627
|
...rest
|
|
2541
2628
|
}) {
|
|
2542
2629
|
const clear = onClear || (() => onChange(""));
|
|
2543
|
-
return /* @__PURE__ */
|
|
2630
|
+
return /* @__PURE__ */ jsx40(
|
|
2544
2631
|
Input,
|
|
2545
2632
|
{
|
|
2546
2633
|
id,
|
|
@@ -2553,14 +2640,14 @@ function SearchField({
|
|
|
2553
2640
|
style,
|
|
2554
2641
|
className,
|
|
2555
2642
|
onChange: (e) => onChange(e.target.value),
|
|
2556
|
-
suffix: value ? /* @__PURE__ */
|
|
2643
|
+
suffix: value ? /* @__PURE__ */ jsx40(
|
|
2557
2644
|
"button",
|
|
2558
2645
|
{
|
|
2559
2646
|
type: "button",
|
|
2560
2647
|
"aria-label": "Clear search",
|
|
2561
2648
|
onClick: clear,
|
|
2562
2649
|
style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
|
|
2563
|
-
children: /* @__PURE__ */
|
|
2650
|
+
children: /* @__PURE__ */ jsx40("i", { className: "ph ph-x-circle", style: { fontSize: 15 }, "aria-hidden": "true" })
|
|
2564
2651
|
}
|
|
2565
2652
|
) : void 0,
|
|
2566
2653
|
...rest
|
|
@@ -2568,27 +2655,183 @@ function SearchField({
|
|
|
2568
2655
|
);
|
|
2569
2656
|
}
|
|
2570
2657
|
|
|
2571
|
-
// src/components/
|
|
2658
|
+
// src/components/data/TransferList.tsx
|
|
2659
|
+
import { jsx as jsx41, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
2660
|
+
var emptyHasMore = {};
|
|
2661
|
+
function TransferList({
|
|
2662
|
+
left,
|
|
2663
|
+
right,
|
|
2664
|
+
keyOf,
|
|
2665
|
+
renderLabel,
|
|
2666
|
+
renderMeta,
|
|
2667
|
+
onMove,
|
|
2668
|
+
itemHeight = 44,
|
|
2669
|
+
listHeight = 440,
|
|
2670
|
+
className = ""
|
|
2671
|
+
}) {
|
|
2672
|
+
const [dragging, setDragging] = React16.useState(null);
|
|
2673
|
+
const [dragOverSide, setDragOverSide] = React16.useState(null);
|
|
2674
|
+
const startDrag = (e, item, from) => {
|
|
2675
|
+
const key = keyOf(item);
|
|
2676
|
+
setDragging({ key, from });
|
|
2677
|
+
e.dataTransfer.effectAllowed = "move";
|
|
2678
|
+
e.dataTransfer.setData("text/plain", String(key));
|
|
2679
|
+
};
|
|
2680
|
+
const endDrag = () => {
|
|
2681
|
+
setDragging(null);
|
|
2682
|
+
setDragOverSide(null);
|
|
2683
|
+
};
|
|
2684
|
+
const findItem = (side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key);
|
|
2685
|
+
const dropOnSide = (e, side) => {
|
|
2686
|
+
e.preventDefault();
|
|
2687
|
+
setDragOverSide(null);
|
|
2688
|
+
if (!dragging || dragging.from === side) return;
|
|
2689
|
+
const item = findItem(dragging.from, dragging.key);
|
|
2690
|
+
if (item !== void 0) onMove(item, dragging.from, side);
|
|
2691
|
+
setDragging(null);
|
|
2692
|
+
};
|
|
2693
|
+
const renderSide = (side, cfg, opposite) => /* @__PURE__ */ jsxs36(
|
|
2694
|
+
"div",
|
|
2695
|
+
{
|
|
2696
|
+
style: {
|
|
2697
|
+
flex: 1,
|
|
2698
|
+
minWidth: 0,
|
|
2699
|
+
display: "flex",
|
|
2700
|
+
flexDirection: "column",
|
|
2701
|
+
gap: 8,
|
|
2702
|
+
padding: 10,
|
|
2703
|
+
borderRadius: 10,
|
|
2704
|
+
border: "1px solid " + (dragOverSide === side ? "var(--brand)" : "var(--border)"),
|
|
2705
|
+
background: "var(--surface)"
|
|
2706
|
+
},
|
|
2707
|
+
onDragOver: (e) => {
|
|
2708
|
+
if (!dragging || dragging.from === side) return;
|
|
2709
|
+
e.preventDefault();
|
|
2710
|
+
e.dataTransfer.dropEffect = "move";
|
|
2711
|
+
if (dragOverSide !== side) setDragOverSide(side);
|
|
2712
|
+
},
|
|
2713
|
+
onDragLeave: (e) => {
|
|
2714
|
+
if (e.currentTarget.contains(e.relatedTarget)) return;
|
|
2715
|
+
setDragOverSide((s) => s === side ? null : s);
|
|
2716
|
+
},
|
|
2717
|
+
onDrop: (e) => dropOnSide(e, side),
|
|
2718
|
+
children: [
|
|
2719
|
+
cfg.label ? /* @__PURE__ */ jsxs36("span", { className: "fd-overline fd-muted", children: [
|
|
2720
|
+
cfg.label,
|
|
2721
|
+
cfg.total != null ? " (" + cfg.total.toLocaleString() + ")" : ""
|
|
2722
|
+
] }) : null,
|
|
2723
|
+
/* @__PURE__ */ jsxs36("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
2724
|
+
/* @__PURE__ */ jsx41(SearchField, { value: cfg.search, onChange: cfg.onSearchChange, placeholder: "Search", "aria-label": (cfg.label || side) + " search", style: { flex: 1 } }),
|
|
2725
|
+
/* @__PURE__ */ jsx41(SortMenu, { fields: cfg.sortFields, sort: cfg.sort, onSort: cfg.onSort })
|
|
2726
|
+
] }),
|
|
2727
|
+
/* @__PURE__ */ jsx41(
|
|
2728
|
+
VirtualList,
|
|
2729
|
+
{
|
|
2730
|
+
items: cfg.items,
|
|
2731
|
+
itemHeight,
|
|
2732
|
+
height: listHeight,
|
|
2733
|
+
keyOf,
|
|
2734
|
+
loading: cfg.loading,
|
|
2735
|
+
hasMore: cfg.hasMore || emptyHasMore,
|
|
2736
|
+
onNeedMore: cfg.onNeedMore,
|
|
2737
|
+
emptyState: /* @__PURE__ */ jsx41(EmptyState, { icon: "tray", title: "Nothing here" }),
|
|
2738
|
+
renderItem: (item) => /* @__PURE__ */ jsx41(
|
|
2739
|
+
EntityRow,
|
|
2740
|
+
{
|
|
2741
|
+
title: renderLabel(item),
|
|
2742
|
+
meta: renderMeta ? renderMeta(item) : void 0,
|
|
2743
|
+
draggable: true,
|
|
2744
|
+
onDragStart: (e) => startDrag(e, item, side),
|
|
2745
|
+
onDragEnd: endDrag,
|
|
2746
|
+
style: { opacity: dragging && dragging.from === side && dragging.key === keyOf(item) ? 0.4 : 1 },
|
|
2747
|
+
action: {
|
|
2748
|
+
icon: side === "left" ? "plus" : "minus",
|
|
2749
|
+
label: (side === "left" ? "Move to " : "Move from ") + (side === "left" ? right.label || "the other list" : left.label || "the other list"),
|
|
2750
|
+
tone: side === "left" ? "add" : "remove",
|
|
2751
|
+
onClick: () => onMove(item, side, opposite)
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2754
|
+
)
|
|
2755
|
+
}
|
|
2756
|
+
)
|
|
2757
|
+
]
|
|
2758
|
+
}
|
|
2759
|
+
);
|
|
2760
|
+
return /* @__PURE__ */ jsxs36("div", { className: ["fd-tlist", className].filter(Boolean).join(" "), style: { display: "flex", gap: 16, alignItems: "flex-start" }, children: [
|
|
2761
|
+
renderSide("left", left, "right"),
|
|
2762
|
+
renderSide("right", right, "left")
|
|
2763
|
+
] });
|
|
2764
|
+
}
|
|
2765
|
+
|
|
2766
|
+
// src/components/forms/Checkbox.tsx
|
|
2767
|
+
import * as React17 from "react";
|
|
2572
2768
|
import { jsx as jsx42, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
2769
|
+
function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
|
|
2770
|
+
const ref = React17.useRef(null);
|
|
2771
|
+
React17.useEffect(() => {
|
|
2772
|
+
if (ref.current) ref.current.indeterminate = indeterminate;
|
|
2773
|
+
}, [indeterminate]);
|
|
2774
|
+
return /* @__PURE__ */ jsxs37("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
2775
|
+
/* @__PURE__ */ jsxs37("span", { className: "fd-choice-input", children: [
|
|
2776
|
+
/* @__PURE__ */ jsx42("input", { ref, type: "checkbox", ...rest }),
|
|
2777
|
+
/* @__PURE__ */ jsx42("span", { className: "fd-choice-box", "aria-hidden": "true", children: /* @__PURE__ */ jsx42("i", { className: indeterminate ? "ph ph-minus" : "ph ph-check" }) })
|
|
2778
|
+
] }),
|
|
2779
|
+
/* @__PURE__ */ jsxs37("span", { className: "fd-choice-text", children: [
|
|
2780
|
+
/* @__PURE__ */ jsx42("span", { className: "fd-choice-title", children: label }),
|
|
2781
|
+
description ? /* @__PURE__ */ jsx42("span", { className: "fd-choice-desc", children: description }) : null
|
|
2782
|
+
] })
|
|
2783
|
+
] });
|
|
2784
|
+
}
|
|
2785
|
+
|
|
2786
|
+
// src/components/forms/Radio.tsx
|
|
2787
|
+
import { jsx as jsx43, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
2788
|
+
function Radio({ label, description, card = false, className = "", ...rest }) {
|
|
2789
|
+
return /* @__PURE__ */ jsxs38("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
2790
|
+
/* @__PURE__ */ jsxs38("span", { className: "fd-choice-input", children: [
|
|
2791
|
+
/* @__PURE__ */ jsx43("input", { type: "radio", ...rest }),
|
|
2792
|
+
/* @__PURE__ */ jsx43("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ jsx43("span", { className: "fd-choice-dot" }) })
|
|
2793
|
+
] }),
|
|
2794
|
+
/* @__PURE__ */ jsxs38("span", { className: "fd-choice-text", children: [
|
|
2795
|
+
/* @__PURE__ */ jsx43("span", { className: "fd-choice-title", children: label }),
|
|
2796
|
+
description ? /* @__PURE__ */ jsx43("span", { className: "fd-choice-desc", children: description }) : null
|
|
2797
|
+
] })
|
|
2798
|
+
] });
|
|
2799
|
+
}
|
|
2800
|
+
|
|
2801
|
+
// src/components/forms/Switch.tsx
|
|
2802
|
+
import { jsx as jsx44, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
2803
|
+
function Switch({ label, description, className = "", ...rest }) {
|
|
2804
|
+
return /* @__PURE__ */ jsxs39("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
|
|
2805
|
+
/* @__PURE__ */ jsx44("input", { type: "checkbox", role: "switch", ...rest }),
|
|
2806
|
+
/* @__PURE__ */ jsx44("span", { className: "fd-switch-track", children: /* @__PURE__ */ jsx44("span", { className: "fd-switch-thumb" }) }),
|
|
2807
|
+
label ? /* @__PURE__ */ jsxs39("span", { className: "fd-choice-text", children: [
|
|
2808
|
+
/* @__PURE__ */ jsx44("span", { className: "fd-switch-label", children: label }),
|
|
2809
|
+
description ? /* @__PURE__ */ jsx44("span", { className: "fd-choice-desc", children: description }) : null
|
|
2810
|
+
] }) : null
|
|
2811
|
+
] });
|
|
2812
|
+
}
|
|
2813
|
+
|
|
2814
|
+
// src/components/forms/Textarea.tsx
|
|
2815
|
+
import { jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
2573
2816
|
function Textarea({ label, help, error, required = false, rows = 4, disabled = false, id, className = "", style, ...rest }) {
|
|
2574
2817
|
const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
|
|
2575
2818
|
const box = ["fd-input", "fd-input-textarea", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : "", className].filter(Boolean).join(" ");
|
|
2576
|
-
return /* @__PURE__ */
|
|
2577
|
-
label ? /* @__PURE__ */
|
|
2819
|
+
return /* @__PURE__ */ jsxs40("div", { className: "fd-field", style, children: [
|
|
2820
|
+
label ? /* @__PURE__ */ jsxs40("label", { className: "fd-field-label", htmlFor: fieldId, children: [
|
|
2578
2821
|
label,
|
|
2579
|
-
required ? /* @__PURE__ */
|
|
2822
|
+
required ? /* @__PURE__ */ jsx45("span", { className: "fd-field-req", children: "*" }) : null
|
|
2580
2823
|
] }) : null,
|
|
2581
|
-
/* @__PURE__ */
|
|
2582
|
-
error ? /* @__PURE__ */
|
|
2583
|
-
/* @__PURE__ */
|
|
2824
|
+
/* @__PURE__ */ jsx45("div", { className: box, children: /* @__PURE__ */ jsx45("textarea", { id: fieldId, rows, disabled, "aria-invalid": error ? "true" : void 0, ...rest }) }),
|
|
2825
|
+
error ? /* @__PURE__ */ jsxs40("span", { className: "fd-field-error", children: [
|
|
2826
|
+
/* @__PURE__ */ jsx45("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
2584
2827
|
error
|
|
2585
|
-
] }) : help ? /* @__PURE__ */
|
|
2828
|
+
] }) : help ? /* @__PURE__ */ jsx45("span", { className: "fd-field-help", children: help }) : null
|
|
2586
2829
|
] });
|
|
2587
2830
|
}
|
|
2588
2831
|
|
|
2589
2832
|
// src/components/forms/NumberInput.tsx
|
|
2590
|
-
import * as
|
|
2591
|
-
import { jsx as
|
|
2833
|
+
import * as React18 from "react";
|
|
2834
|
+
import { jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
2592
2835
|
function NumberInput({
|
|
2593
2836
|
label,
|
|
2594
2837
|
help,
|
|
@@ -2612,10 +2855,10 @@ function NumberInput({
|
|
|
2612
2855
|
const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
|
|
2613
2856
|
return isNaN(n) ? null : n;
|
|
2614
2857
|
};
|
|
2615
|
-
const [text, setText] =
|
|
2616
|
-
const [editing, setEditing] =
|
|
2617
|
-
const timer =
|
|
2618
|
-
|
|
2858
|
+
const [text, setText] = React18.useState(value == null || value === "" ? "" : String(value));
|
|
2859
|
+
const [editing, setEditing] = React18.useState(false);
|
|
2860
|
+
const timer = React18.useRef(null);
|
|
2861
|
+
React18.useEffect(() => {
|
|
2619
2862
|
if (!editing) setText(value == null || value === "" ? "" : String(value));
|
|
2620
2863
|
}, [value, editing]);
|
|
2621
2864
|
const clamp = (n) => Math.min(max, Math.max(min, n));
|
|
@@ -2639,7 +2882,7 @@ function NumberInput({
|
|
|
2639
2882
|
const release = () => {
|
|
2640
2883
|
if (timer.current) clearTimeout(timer.current);
|
|
2641
2884
|
};
|
|
2642
|
-
|
|
2885
|
+
React18.useEffect(() => () => {
|
|
2643
2886
|
if (timer.current) clearTimeout(timer.current);
|
|
2644
2887
|
}, []);
|
|
2645
2888
|
const shown = editing ? text : (() => {
|
|
@@ -2647,14 +2890,14 @@ function NumberInput({
|
|
|
2647
2890
|
return n == null ? "" : format ? n.toLocaleString() : String(n);
|
|
2648
2891
|
})();
|
|
2649
2892
|
const box = ["fd-input", "fd-input-num", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
2650
|
-
return /* @__PURE__ */
|
|
2651
|
-
label ? /* @__PURE__ */
|
|
2893
|
+
return /* @__PURE__ */ jsxs41("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
|
|
2894
|
+
label ? /* @__PURE__ */ jsxs41("label", { className: "fd-field-label", children: [
|
|
2652
2895
|
label,
|
|
2653
|
-
required ? /* @__PURE__ */
|
|
2896
|
+
required ? /* @__PURE__ */ jsx46("span", { className: "fd-field-req", children: "*" }) : null
|
|
2654
2897
|
] }) : null,
|
|
2655
|
-
/* @__PURE__ */
|
|
2656
|
-
prefix ? /* @__PURE__ */
|
|
2657
|
-
/* @__PURE__ */
|
|
2898
|
+
/* @__PURE__ */ jsxs41("div", { className: box, style: { gap: 8 }, children: [
|
|
2899
|
+
prefix ? /* @__PURE__ */ jsx46("span", { className: "fd-input-affix", children: prefix }) : null,
|
|
2900
|
+
/* @__PURE__ */ jsx46(
|
|
2658
2901
|
"input",
|
|
2659
2902
|
{
|
|
2660
2903
|
inputMode: "numeric",
|
|
@@ -2687,9 +2930,9 @@ function NumberInput({
|
|
|
2687
2930
|
}
|
|
2688
2931
|
}
|
|
2689
2932
|
),
|
|
2690
|
-
suffix ? /* @__PURE__ */
|
|
2691
|
-
/* @__PURE__ */
|
|
2692
|
-
/* @__PURE__ */
|
|
2933
|
+
suffix ? /* @__PURE__ */ jsx46("span", { className: "fd-input-affix", children: suffix }) : null,
|
|
2934
|
+
/* @__PURE__ */ jsxs41("span", { className: "fd-row", style: { gap: 4, flex: "none" }, children: [
|
|
2935
|
+
/* @__PURE__ */ jsx46(
|
|
2693
2936
|
"button",
|
|
2694
2937
|
{
|
|
2695
2938
|
type: "button",
|
|
@@ -2699,10 +2942,10 @@ function NumberInput({
|
|
|
2699
2942
|
onPointerDown: () => hold(-1),
|
|
2700
2943
|
onPointerUp: release,
|
|
2701
2944
|
onPointerLeave: release,
|
|
2702
|
-
children: /* @__PURE__ */
|
|
2945
|
+
children: /* @__PURE__ */ jsx46("i", { className: "ph ph-minus" })
|
|
2703
2946
|
}
|
|
2704
2947
|
),
|
|
2705
|
-
/* @__PURE__ */
|
|
2948
|
+
/* @__PURE__ */ jsx46(
|
|
2706
2949
|
"button",
|
|
2707
2950
|
{
|
|
2708
2951
|
type: "button",
|
|
@@ -2712,26 +2955,26 @@ function NumberInput({
|
|
|
2712
2955
|
onPointerDown: () => hold(1),
|
|
2713
2956
|
onPointerUp: release,
|
|
2714
2957
|
onPointerLeave: release,
|
|
2715
|
-
children: /* @__PURE__ */
|
|
2958
|
+
children: /* @__PURE__ */ jsx46("i", { className: "ph ph-plus" })
|
|
2716
2959
|
}
|
|
2717
2960
|
)
|
|
2718
2961
|
] })
|
|
2719
2962
|
] }),
|
|
2720
|
-
error ? /* @__PURE__ */
|
|
2721
|
-
/* @__PURE__ */
|
|
2963
|
+
error ? /* @__PURE__ */ jsxs41("span", { className: "fd-field-error", children: [
|
|
2964
|
+
/* @__PURE__ */ jsx46("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
2722
2965
|
error
|
|
2723
|
-
] }) : help ? /* @__PURE__ */
|
|
2966
|
+
] }) : help ? /* @__PURE__ */ jsx46("span", { className: "fd-field-help", children: help }) : null
|
|
2724
2967
|
] });
|
|
2725
2968
|
}
|
|
2726
2969
|
|
|
2727
2970
|
// src/components/forms/Select.tsx
|
|
2728
|
-
import * as
|
|
2971
|
+
import * as React19 from "react";
|
|
2729
2972
|
import { createPortal as createPortal4 } from "react-dom";
|
|
2730
|
-
import { jsx as
|
|
2973
|
+
import { jsx as jsx47, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
2731
2974
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
2732
2975
|
function usePopPos(open, ref, estH, estW) {
|
|
2733
|
-
const [pos, setPos] =
|
|
2734
|
-
|
|
2976
|
+
const [pos, setPos] = React19.useState(null);
|
|
2977
|
+
React19.useLayoutEffect(() => {
|
|
2735
2978
|
if (!open || !ref.current) {
|
|
2736
2979
|
setPos(null);
|
|
2737
2980
|
return;
|
|
@@ -2795,14 +3038,14 @@ function Select({
|
|
|
2795
3038
|
const vals = multiple ? Array.isArray(value) ? value : value ? [value] : [] : [];
|
|
2796
3039
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
2797
3040
|
const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
|
|
2798
|
-
const [open, setOpen] =
|
|
2799
|
-
const [q, setQ] =
|
|
2800
|
-
const [active, setActive] =
|
|
2801
|
-
const rootRef =
|
|
2802
|
-
const boxRef =
|
|
2803
|
-
const popRef =
|
|
2804
|
-
const listRef =
|
|
2805
|
-
const typeBuf =
|
|
3041
|
+
const [open, setOpen] = React19.useState(false);
|
|
3042
|
+
const [q, setQ] = React19.useState("");
|
|
3043
|
+
const [active, setActive] = React19.useState(-1);
|
|
3044
|
+
const rootRef = React19.useRef(null);
|
|
3045
|
+
const boxRef = React19.useRef(null);
|
|
3046
|
+
const popRef = React19.useRef(null);
|
|
3047
|
+
const listRef = React19.useRef(null);
|
|
3048
|
+
const typeBuf = React19.useRef({ s: "", t: 0 });
|
|
2806
3049
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
2807
3050
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
2808
3051
|
const pos = usePopPos(open, boxRef, hasSearch ? 390 : 340, 260);
|
|
@@ -2828,7 +3071,7 @@ function Select({
|
|
|
2828
3071
|
}
|
|
2829
3072
|
setOpen(!open);
|
|
2830
3073
|
};
|
|
2831
|
-
|
|
3074
|
+
React19.useEffect(() => {
|
|
2832
3075
|
if (!open) return;
|
|
2833
3076
|
const away = (e) => {
|
|
2834
3077
|
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
@@ -2838,7 +3081,7 @@ function Select({
|
|
|
2838
3081
|
document.addEventListener("pointerdown", away);
|
|
2839
3082
|
return () => document.removeEventListener("pointerdown", away);
|
|
2840
3083
|
}, [open]);
|
|
2841
|
-
|
|
3084
|
+
React19.useEffect(() => {
|
|
2842
3085
|
if (!open || active < 0 || !listRef.current) return;
|
|
2843
3086
|
const el = listRef.current.querySelector('[data-i="' + active + '"]');
|
|
2844
3087
|
if (el) {
|
|
@@ -2892,13 +3135,13 @@ function Select({
|
|
|
2892
3135
|
});
|
|
2893
3136
|
const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
|
|
2894
3137
|
const box = ["fd-input", "fd-select", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
2895
|
-
return /* @__PURE__ */
|
|
2896
|
-
label ? /* @__PURE__ */
|
|
3138
|
+
return /* @__PURE__ */ jsxs42("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
3139
|
+
label ? /* @__PURE__ */ jsxs42("label", { className: "fd-field-label", htmlFor: fieldId, onClick: toggle, children: [
|
|
2897
3140
|
label,
|
|
2898
|
-
required ? /* @__PURE__ */
|
|
3141
|
+
required ? /* @__PURE__ */ jsx47("span", { className: "fd-field-req", children: "*" }) : null
|
|
2899
3142
|
] }) : null,
|
|
2900
|
-
/* @__PURE__ */
|
|
2901
|
-
/* @__PURE__ */
|
|
3143
|
+
/* @__PURE__ */ jsxs42("div", { className: box, style: { cursor: disabled ? "not-allowed" : "pointer" }, ref: boxRef, children: [
|
|
3144
|
+
/* @__PURE__ */ jsxs42(
|
|
2902
3145
|
"button",
|
|
2903
3146
|
{
|
|
2904
3147
|
type: "button",
|
|
@@ -2911,13 +3154,13 @@ function Select({
|
|
|
2911
3154
|
"aria-haspopup": "listbox",
|
|
2912
3155
|
style: { all: "unset", flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: 8, cursor: "inherit", overflow: "hidden" },
|
|
2913
3156
|
children: [
|
|
2914
|
-
selected && selected.icon ? /* @__PURE__ */
|
|
2915
|
-
/* @__PURE__ */
|
|
2916
|
-
multiple && chosen.length > 1 ? /* @__PURE__ */
|
|
3157
|
+
selected && selected.icon ? /* @__PURE__ */ jsx47("i", { className: "ph ph-" + selected.icon, style: { flex: "none", color: "var(--text-2)" } }) : null,
|
|
3158
|
+
/* @__PURE__ */ jsx47("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: (multiple ? chosen.length : selected) ? "var(--text)" : "var(--text-muted)" }, children: boxText }),
|
|
3159
|
+
multiple && chosen.length > 1 ? /* @__PURE__ */ jsx47("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
|
|
2917
3160
|
]
|
|
2918
3161
|
}
|
|
2919
3162
|
),
|
|
2920
|
-
clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */
|
|
3163
|
+
clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ jsx47(
|
|
2921
3164
|
"button",
|
|
2922
3165
|
{
|
|
2923
3166
|
type: "button",
|
|
@@ -2927,22 +3170,22 @@ function Select({
|
|
|
2927
3170
|
fire(multiple ? [] : "");
|
|
2928
3171
|
},
|
|
2929
3172
|
style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
|
|
2930
|
-
children: /* @__PURE__ */
|
|
3173
|
+
children: /* @__PURE__ */ jsx47("i", { className: "ph ph-x-circle", style: { fontSize: 15 } })
|
|
2931
3174
|
}
|
|
2932
3175
|
) : null,
|
|
2933
|
-
loading ? /* @__PURE__ */
|
|
3176
|
+
loading ? /* @__PURE__ */ jsx47("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading options" }) : /* @__PURE__ */ jsx47("span", { className: "fd-select-caret", onClick: toggle, children: /* @__PURE__ */ jsx47("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
|
|
2934
3177
|
] }),
|
|
2935
3178
|
open && pos ? createPortal4(
|
|
2936
|
-
/* @__PURE__ */
|
|
3179
|
+
/* @__PURE__ */ jsxs42(
|
|
2937
3180
|
"div",
|
|
2938
3181
|
{
|
|
2939
3182
|
className: "fd-pop" + (pos.up ? " is-up" : ""),
|
|
2940
3183
|
ref: popRef,
|
|
2941
3184
|
style: popStyle(pos, { minWidth: Math.max(pos.width, 260), maxWidth: 380, zIndex: 130, overflowY: "hidden" }),
|
|
2942
3185
|
children: [
|
|
2943
|
-
hasSearch ? /* @__PURE__ */
|
|
2944
|
-
/* @__PURE__ */
|
|
2945
|
-
/* @__PURE__ */
|
|
3186
|
+
hasSearch ? /* @__PURE__ */ jsxs42("div", { className: "fd-pop-search", children: [
|
|
3187
|
+
/* @__PURE__ */ jsx47("i", { className: "ph ph-magnifying-glass", style: { color: "var(--text-muted)", fontSize: 14 } }),
|
|
3188
|
+
/* @__PURE__ */ jsx47(
|
|
2946
3189
|
"input",
|
|
2947
3190
|
{
|
|
2948
3191
|
autoFocus: true,
|
|
@@ -2955,15 +3198,15 @@ function Select({
|
|
|
2955
3198
|
}
|
|
2956
3199
|
}
|
|
2957
3200
|
),
|
|
2958
|
-
q ? /* @__PURE__ */
|
|
3201
|
+
q ? /* @__PURE__ */ jsx47("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
2959
3202
|
] }) : null,
|
|
2960
|
-
/* @__PURE__ */
|
|
3203
|
+
/* @__PURE__ */ jsx47("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__ */ jsxs42("div", { className: "fd-pop-empty", children: [
|
|
2961
3204
|
'Nothing matches "',
|
|
2962
3205
|
q,
|
|
2963
3206
|
'".'
|
|
2964
|
-
] }) : groups.map((grp) => /* @__PURE__ */
|
|
2965
|
-
grp.g ? /* @__PURE__ */
|
|
2966
|
-
grp.items.map(({ o, i }) => /* @__PURE__ */
|
|
3207
|
+
] }) : groups.map((grp) => /* @__PURE__ */ jsxs42(React19.Fragment, { children: [
|
|
3208
|
+
grp.g ? /* @__PURE__ */ jsx47("div", { className: "fd-pop-group", children: grp.g }) : null,
|
|
3209
|
+
grp.items.map(({ o, i }) => /* @__PURE__ */ jsxs42(
|
|
2967
3210
|
"button",
|
|
2968
3211
|
{
|
|
2969
3212
|
type: "button",
|
|
@@ -2975,21 +3218,21 @@ function Select({
|
|
|
2975
3218
|
onMouseEnter: () => setActive(i),
|
|
2976
3219
|
onClick: () => pick(o),
|
|
2977
3220
|
children: [
|
|
2978
|
-
multiple ? /* @__PURE__ */
|
|
2979
|
-
o.icon ? /* @__PURE__ */
|
|
2980
|
-
/* @__PURE__ */
|
|
2981
|
-
/* @__PURE__ */
|
|
2982
|
-
o.description ? /* @__PURE__ */
|
|
3221
|
+
multiple ? /* @__PURE__ */ jsx47("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__ */ jsx47("i", { className: "ph ph-check", style: { fontSize: 11 } }) : null }) : null,
|
|
3222
|
+
o.icon ? /* @__PURE__ */ jsx47("span", { className: "fd-opt-icon", children: /* @__PURE__ */ jsx47("i", { className: "ph ph-" + o.icon }) }) : null,
|
|
3223
|
+
/* @__PURE__ */ jsxs42("span", { style: { flex: 1, minWidth: 0 }, children: [
|
|
3224
|
+
/* @__PURE__ */ jsx47("span", { className: "fd-opt-label", children: o.label }),
|
|
3225
|
+
o.description ? /* @__PURE__ */ jsx47("span", { className: "fd-opt-desc", children: o.description }) : null
|
|
2983
3226
|
] }),
|
|
2984
|
-
o.meta ? /* @__PURE__ */
|
|
2985
|
-
multiple ? null : /* @__PURE__ */
|
|
3227
|
+
o.meta ? /* @__PURE__ */ jsx47("span", { className: "fd-opt-meta", children: o.meta }) : null,
|
|
3228
|
+
multiple ? null : /* @__PURE__ */ jsx47("span", { className: "fd-opt-check", children: o.value === value ? /* @__PURE__ */ jsx47("i", { className: "ph ph-check" }) : null })
|
|
2986
3229
|
]
|
|
2987
3230
|
},
|
|
2988
3231
|
String(o.value)
|
|
2989
3232
|
))
|
|
2990
3233
|
] }, grp.g || "_")) }),
|
|
2991
|
-
multiple ? /* @__PURE__ */
|
|
2992
|
-
/* @__PURE__ */
|
|
3234
|
+
multiple ? /* @__PURE__ */ jsxs42("div", { className: "fd-row", style: { gap: 10, padding: "8px 12px", borderTop: "1px solid var(--border)" }, children: [
|
|
3235
|
+
/* @__PURE__ */ jsx47(
|
|
2993
3236
|
"button",
|
|
2994
3237
|
{
|
|
2995
3238
|
type: "button",
|
|
@@ -2998,13 +3241,13 @@ function Select({
|
|
|
2998
3241
|
children: "Select all"
|
|
2999
3242
|
}
|
|
3000
3243
|
),
|
|
3001
|
-
/* @__PURE__ */
|
|
3002
|
-
/* @__PURE__ */
|
|
3244
|
+
/* @__PURE__ */ jsx47("span", { style: { flex: 1 } }),
|
|
3245
|
+
/* @__PURE__ */ jsxs42("span", { className: "fd-body-sm fd-muted", children: [
|
|
3003
3246
|
vals.length,
|
|
3004
3247
|
" of ",
|
|
3005
3248
|
opts.length
|
|
3006
3249
|
] }),
|
|
3007
|
-
/* @__PURE__ */
|
|
3250
|
+
/* @__PURE__ */ jsx47(
|
|
3008
3251
|
"button",
|
|
3009
3252
|
{
|
|
3010
3253
|
type: "button",
|
|
@@ -3020,17 +3263,17 @@ function Select({
|
|
|
3020
3263
|
),
|
|
3021
3264
|
document.body
|
|
3022
3265
|
) : null,
|
|
3023
|
-
error ? /* @__PURE__ */
|
|
3024
|
-
/* @__PURE__ */
|
|
3266
|
+
error ? /* @__PURE__ */ jsxs42("span", { className: "fd-field-error", children: [
|
|
3267
|
+
/* @__PURE__ */ jsx47("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3025
3268
|
error
|
|
3026
|
-
] }) : help ? /* @__PURE__ */
|
|
3269
|
+
] }) : help ? /* @__PURE__ */ jsx47("span", { className: "fd-field-help", children: help }) : null
|
|
3027
3270
|
] });
|
|
3028
3271
|
}
|
|
3029
3272
|
|
|
3030
3273
|
// src/components/forms/DatePicker.tsx
|
|
3031
|
-
import * as
|
|
3274
|
+
import * as React20 from "react";
|
|
3032
3275
|
import { createPortal as createPortal5 } from "react-dom";
|
|
3033
|
-
import { jsx as
|
|
3276
|
+
import { jsx as jsx48, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
3034
3277
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
3035
3278
|
var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
3036
3279
|
var iso = (d) => d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
|
|
@@ -3044,8 +3287,8 @@ var fmt = (s) => {
|
|
|
3044
3287
|
return d ? MONTHS[d.getMonth()].slice(0, 3) + " " + d.getDate() + ", " + d.getFullYear() : "";
|
|
3045
3288
|
};
|
|
3046
3289
|
function usePopPos2(open, ref, estH, estW) {
|
|
3047
|
-
const [pos, setPos] =
|
|
3048
|
-
|
|
3290
|
+
const [pos, setPos] = React20.useState(null);
|
|
3291
|
+
React20.useLayoutEffect(() => {
|
|
3049
3292
|
if (!open || !ref.current) {
|
|
3050
3293
|
setPos(null);
|
|
3051
3294
|
return;
|
|
@@ -3089,10 +3332,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3089
3332
|
const today = /* @__PURE__ */ new Date();
|
|
3090
3333
|
const sel = range ? value || {} : { start: value, end: value };
|
|
3091
3334
|
const anchor = parse(sel.start) || parse(initialMonth) || today;
|
|
3092
|
-
const [vy, setVy] =
|
|
3093
|
-
const [vm, setVm] =
|
|
3094
|
-
const [mode2, setMode] =
|
|
3095
|
-
const [hover, setHover] =
|
|
3335
|
+
const [vy, setVy] = React20.useState(anchor.getFullYear());
|
|
3336
|
+
const [vm, setVm] = React20.useState(anchor.getMonth());
|
|
3337
|
+
const [mode2, setMode] = React20.useState("days");
|
|
3338
|
+
const [hover, setHover] = React20.useState(null);
|
|
3096
3339
|
const s = parse(sel.start), e = parse(sel.end);
|
|
3097
3340
|
const hoverEnd = range && s && !e && hover ? parse(hover) : null;
|
|
3098
3341
|
const inRange = (d) => {
|
|
@@ -3129,9 +3372,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3129
3372
|
const startPad = new Date(y, m, 1).getDay();
|
|
3130
3373
|
const cells = [];
|
|
3131
3374
|
for (let i = 0; i < 42; i++) cells.push(new Date(y, m, i - startPad + 1));
|
|
3132
|
-
return /* @__PURE__ */
|
|
3133
|
-
DOW.map((d) => /* @__PURE__ */
|
|
3134
|
-
cells.map((d, i) => /* @__PURE__ */
|
|
3375
|
+
return /* @__PURE__ */ jsxs43("div", { className: "fd-cal-grid", style: { width: months > 1 ? 252 : "auto", flex: "none" }, onMouseLeave: () => setHover(null), children: [
|
|
3376
|
+
DOW.map((d) => /* @__PURE__ */ jsx48("span", { className: "fd-cal-dow", children: d }, d)),
|
|
3377
|
+
cells.map((d, i) => /* @__PURE__ */ jsx48(
|
|
3135
3378
|
"button",
|
|
3136
3379
|
{
|
|
3137
3380
|
type: "button",
|
|
@@ -3145,20 +3388,20 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3145
3388
|
] });
|
|
3146
3389
|
};
|
|
3147
3390
|
const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
|
|
3148
|
-
return /* @__PURE__ */
|
|
3149
|
-
/* @__PURE__ */
|
|
3150
|
-
/* @__PURE__ */
|
|
3151
|
-
/* @__PURE__ */
|
|
3391
|
+
return /* @__PURE__ */ jsxs43("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, children: [
|
|
3392
|
+
/* @__PURE__ */ jsxs43("div", { className: "fd-cal-head", children: [
|
|
3393
|
+
/* @__PURE__ */ jsx48("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__ */ jsx48("i", { className: "ph ph-caret-left" }) }),
|
|
3394
|
+
/* @__PURE__ */ jsxs43("button", { type: "button", className: "fd-cal-title", onClick: () => setMode(mode2 === "days" ? "months" : mode2 === "months" ? "years" : "days"), children: [
|
|
3152
3395
|
mode2 === "days" ? MONTHS[vm] + " " + vy : mode2 === "months" ? vy : vy - 5 + " \u2013 " + (vy + 6),
|
|
3153
|
-
/* @__PURE__ */
|
|
3396
|
+
/* @__PURE__ */ jsx48("i", { className: "ph ph-caret-down", style: { fontSize: 10, marginLeft: 6, color: "var(--text-muted)" } })
|
|
3154
3397
|
] }),
|
|
3155
|
-
months > 1 && mode2 === "days" ? /* @__PURE__ */
|
|
3156
|
-
/* @__PURE__ */
|
|
3398
|
+
months > 1 && mode2 === "days" ? /* @__PURE__ */ jsx48("span", { className: "fd-cal-title", style: { cursor: "default", background: "none" }, children: MONTHS[nextM] + " " + nextY }) : null,
|
|
3399
|
+
/* @__PURE__ */ jsx48("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__ */ jsx48("i", { className: "ph ph-caret-right" }) })
|
|
3157
3400
|
] }),
|
|
3158
|
-
mode2 === "days" ? /* @__PURE__ */
|
|
3401
|
+
mode2 === "days" ? /* @__PURE__ */ jsxs43("div", { style: { display: "flex", gap: 18 }, children: [
|
|
3159
3402
|
monthGrid(vy, vm),
|
|
3160
3403
|
months > 1 ? monthGrid(nextY, nextM) : null
|
|
3161
|
-
] }) : mode2 === "months" ? /* @__PURE__ */
|
|
3404
|
+
] }) : mode2 === "months" ? /* @__PURE__ */ jsx48("div", { className: "fd-cal-grid-months", children: MONTHS.map((m, i) => /* @__PURE__ */ jsx48(
|
|
3162
3405
|
"button",
|
|
3163
3406
|
{
|
|
3164
3407
|
type: "button",
|
|
@@ -3170,7 +3413,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3170
3413
|
children: m.slice(0, 3)
|
|
3171
3414
|
},
|
|
3172
3415
|
m
|
|
3173
|
-
)) }) : /* @__PURE__ */
|
|
3416
|
+
)) }) : /* @__PURE__ */ jsx48("div", { className: "fd-cal-grid-months", children: Array.from({ length: 12 }, (_, i) => vy - 5 + i).map((y) => /* @__PURE__ */ jsx48(
|
|
3174
3417
|
"button",
|
|
3175
3418
|
{
|
|
3176
3419
|
type: "button",
|
|
@@ -3183,8 +3426,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3183
3426
|
},
|
|
3184
3427
|
y
|
|
3185
3428
|
)) }),
|
|
3186
|
-
/* @__PURE__ */
|
|
3187
|
-
/* @__PURE__ */
|
|
3429
|
+
/* @__PURE__ */ jsxs43("div", { className: "fd-cal-foot", children: [
|
|
3430
|
+
/* @__PURE__ */ jsx48(
|
|
3188
3431
|
"button",
|
|
3189
3432
|
{
|
|
3190
3433
|
type: "button",
|
|
@@ -3198,8 +3441,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3198
3441
|
children: "Today"
|
|
3199
3442
|
}
|
|
3200
3443
|
),
|
|
3201
|
-
/* @__PURE__ */
|
|
3202
|
-
range && sel.start ? /* @__PURE__ */
|
|
3444
|
+
/* @__PURE__ */ jsx48("span", { style: { flex: 1 } }),
|
|
3445
|
+
range && sel.start ? /* @__PURE__ */ jsxs43("span", { className: "fd-body-sm fd-muted", children: [
|
|
3203
3446
|
fmt(sel.start),
|
|
3204
3447
|
sel.end ? " \u2192 " + fmt(sel.end) : " \u2192 pick an end"
|
|
3205
3448
|
] }) : null
|
|
@@ -3207,12 +3450,12 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3207
3450
|
] });
|
|
3208
3451
|
}
|
|
3209
3452
|
function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, className = "", style, ...rest }) {
|
|
3210
|
-
const [open, setOpen] =
|
|
3211
|
-
const rootRef =
|
|
3212
|
-
const boxRef =
|
|
3213
|
-
const popRef =
|
|
3453
|
+
const [open, setOpen] = React20.useState(false);
|
|
3454
|
+
const rootRef = React20.useRef(null);
|
|
3455
|
+
const boxRef = React20.useRef(null);
|
|
3456
|
+
const popRef = React20.useRef(null);
|
|
3214
3457
|
const pos = usePopPos2(open, boxRef, 430, range ? 600 : 316);
|
|
3215
|
-
|
|
3458
|
+
React20.useEffect(() => {
|
|
3216
3459
|
if (!open) return;
|
|
3217
3460
|
const away = (e) => {
|
|
3218
3461
|
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
@@ -3233,14 +3476,14 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3233
3476
|
const toggle = () => {
|
|
3234
3477
|
if (!disabled) setOpen(!open);
|
|
3235
3478
|
};
|
|
3236
|
-
return /* @__PURE__ */
|
|
3237
|
-
label ? /* @__PURE__ */
|
|
3479
|
+
return /* @__PURE__ */ jsxs43("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
3480
|
+
label ? /* @__PURE__ */ jsxs43("label", { className: "fd-field-label", onClick: toggle, children: [
|
|
3238
3481
|
label,
|
|
3239
|
-
required ? /* @__PURE__ */
|
|
3482
|
+
required ? /* @__PURE__ */ jsx48("span", { className: "fd-field-req", children: "*" }) : null
|
|
3240
3483
|
] }) : null,
|
|
3241
|
-
/* @__PURE__ */
|
|
3242
|
-
/* @__PURE__ */
|
|
3243
|
-
/* @__PURE__ */
|
|
3484
|
+
/* @__PURE__ */ jsxs43("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: [
|
|
3485
|
+
/* @__PURE__ */ jsx48("span", { className: "fd-input-icon", children: /* @__PURE__ */ jsx48("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }) }),
|
|
3486
|
+
/* @__PURE__ */ jsx48(
|
|
3244
3487
|
"button",
|
|
3245
3488
|
{
|
|
3246
3489
|
type: "button",
|
|
@@ -3256,10 +3499,10 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3256
3499
|
children: display || placeholder || (range ? "Pick a date range" : "Pick a date")
|
|
3257
3500
|
}
|
|
3258
3501
|
),
|
|
3259
|
-
/* @__PURE__ */
|
|
3502
|
+
/* @__PURE__ */ jsx48("span", { className: "fd-select-caret", children: /* @__PURE__ */ jsx48("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
|
|
3260
3503
|
] }),
|
|
3261
3504
|
open && pos ? createPortal5(
|
|
3262
|
-
/* @__PURE__ */
|
|
3505
|
+
/* @__PURE__ */ jsx48("div", { className: "fd-pop" + (pos.up ? " is-up" : ""), ref: popRef, style: popStyle2(pos, { width: "max-content", minWidth: 0, zIndex: 130 }), children: /* @__PURE__ */ jsx48(
|
|
3263
3506
|
Calendar,
|
|
3264
3507
|
{
|
|
3265
3508
|
range,
|
|
@@ -3273,21 +3516,21 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3273
3516
|
) }),
|
|
3274
3517
|
document.body
|
|
3275
3518
|
) : null,
|
|
3276
|
-
error ? /* @__PURE__ */
|
|
3277
|
-
/* @__PURE__ */
|
|
3519
|
+
error ? /* @__PURE__ */ jsxs43("span", { className: "fd-field-error", children: [
|
|
3520
|
+
/* @__PURE__ */ jsx48("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3278
3521
|
error
|
|
3279
|
-
] }) : help ? /* @__PURE__ */
|
|
3522
|
+
] }) : help ? /* @__PURE__ */ jsx48("span", { className: "fd-field-help", children: help }) : null
|
|
3280
3523
|
] });
|
|
3281
3524
|
}
|
|
3282
3525
|
|
|
3283
3526
|
// src/components/forms/TimePicker.tsx
|
|
3284
|
-
import * as
|
|
3527
|
+
import * as React21 from "react";
|
|
3285
3528
|
import { createPortal as createPortal6 } from "react-dom";
|
|
3286
|
-
import { jsx as
|
|
3529
|
+
import { jsx as jsx49, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
3287
3530
|
var pad = (n) => String(n).padStart(2, "0");
|
|
3288
3531
|
function usePopPos3(open, ref, estH, estW) {
|
|
3289
|
-
const [pos, setPos] =
|
|
3290
|
-
|
|
3532
|
+
const [pos, setPos] = React21.useState(null);
|
|
3533
|
+
React21.useLayoutEffect(() => {
|
|
3291
3534
|
if (!open || !ref.current) {
|
|
3292
3535
|
setPos(null);
|
|
3293
3536
|
return;
|
|
@@ -3333,9 +3576,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3333
3576
|
if (isNaN(m)) m = 0;
|
|
3334
3577
|
const pm = h24 >= 12;
|
|
3335
3578
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
3336
|
-
const [mode2, setMode] =
|
|
3337
|
-
const faceRef =
|
|
3338
|
-
const dragging =
|
|
3579
|
+
const [mode2, setMode] = React21.useState("h");
|
|
3580
|
+
const faceRef = React21.useRef(null);
|
|
3581
|
+
const dragging = React21.useRef(false);
|
|
3339
3582
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
3340
3583
|
const R = 108, NR = 80;
|
|
3341
3584
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -3370,12 +3613,12 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3370
3613
|
};
|
|
3371
3614
|
const handAngle = mode2 === "h" ? h12 % 12 * 30 : m * 6;
|
|
3372
3615
|
const minuteOff = mode2 === "m" && m % 5 !== 0;
|
|
3373
|
-
return /* @__PURE__ */
|
|
3374
|
-
/* @__PURE__ */
|
|
3375
|
-
/* @__PURE__ */
|
|
3376
|
-
/* @__PURE__ */
|
|
3377
|
-
/* @__PURE__ */
|
|
3378
|
-
/* @__PURE__ */
|
|
3616
|
+
return /* @__PURE__ */ jsxs44("div", { style: { padding: "4px 14px 14px" }, children: [
|
|
3617
|
+
/* @__PURE__ */ jsxs44("div", { className: "fd-clock-digits", children: [
|
|
3618
|
+
/* @__PURE__ */ jsx49("button", { type: "button", className: "fd-clock-digit" + (mode2 === "h" ? " is-active" : ""), onClick: () => setMode("h"), children: pad(h12) }),
|
|
3619
|
+
/* @__PURE__ */ jsx49("span", { style: { fontSize: 24, fontWeight: 700, color: "var(--text-muted)" }, children: ":" }),
|
|
3620
|
+
/* @__PURE__ */ jsx49("button", { type: "button", className: "fd-clock-digit" + (mode2 === "m" ? " is-active" : ""), onClick: () => setMode("m"), children: pad(m) }),
|
|
3621
|
+
/* @__PURE__ */ jsx49("span", { className: "fd-stack", style: { gap: 3, marginLeft: 8 }, children: ["AM", "PM"].map((ap) => /* @__PURE__ */ jsx49(
|
|
3379
3622
|
"button",
|
|
3380
3623
|
{
|
|
3381
3624
|
type: "button",
|
|
@@ -3386,13 +3629,13 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3386
3629
|
ap
|
|
3387
3630
|
)) })
|
|
3388
3631
|
] }),
|
|
3389
|
-
/* @__PURE__ */
|
|
3390
|
-
/* @__PURE__ */
|
|
3391
|
-
/* @__PURE__ */
|
|
3392
|
-
minuteOff ? /* @__PURE__ */
|
|
3632
|
+
/* @__PURE__ */ jsxs44("div", { className: "fd-clock", ref: faceRef, onPointerDown: down, onPointerMove: move, onPointerUp: upH, children: [
|
|
3633
|
+
/* @__PURE__ */ jsx49("span", { className: "fd-clock-hand", style: { height: NR - (minuteOff ? 14 : 16), transform: "translateX(-50%) rotate(" + handAngle + "deg)", bottom: "50%" } }),
|
|
3634
|
+
/* @__PURE__ */ jsx49("span", { className: "fd-clock-pivot" }),
|
|
3635
|
+
minuteOff ? /* @__PURE__ */ jsx49("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,
|
|
3393
3636
|
nums.map((n) => {
|
|
3394
3637
|
const a = angleOf(n) * Math.PI / 180;
|
|
3395
|
-
return /* @__PURE__ */
|
|
3638
|
+
return /* @__PURE__ */ jsx49(
|
|
3396
3639
|
"span",
|
|
3397
3640
|
{
|
|
3398
3641
|
className: "fd-clock-num" + (n === selNum || mode2 === "m" && n === Math.round(m / 5) * 5 % 60 && m % 5 === 0 ? " is-sel" : ""),
|
|
@@ -3403,16 +3646,16 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
3403
3646
|
);
|
|
3404
3647
|
})
|
|
3405
3648
|
] }),
|
|
3406
|
-
/* @__PURE__ */
|
|
3649
|
+
/* @__PURE__ */ jsx49("div", { className: "fd-row", style: { justifyContent: "center", gap: 6 }, children: /* @__PURE__ */ jsx49("span", { className: "fd-body-sm fd-muted", children: mode2 === "h" ? "Pick the hour \u2014 drag or tap" : "Now the minutes" }) })
|
|
3407
3650
|
] });
|
|
3408
3651
|
}
|
|
3409
3652
|
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", className = "", style }) {
|
|
3410
|
-
const [open, setOpen] =
|
|
3411
|
-
const rootRef =
|
|
3412
|
-
const boxRef =
|
|
3413
|
-
const popRef =
|
|
3653
|
+
const [open, setOpen] = React21.useState(false);
|
|
3654
|
+
const rootRef = React21.useRef(null);
|
|
3655
|
+
const boxRef = React21.useRef(null);
|
|
3656
|
+
const popRef = React21.useRef(null);
|
|
3414
3657
|
const pos = usePopPos3(open, boxRef, 420, 262);
|
|
3415
|
-
|
|
3658
|
+
React21.useEffect(() => {
|
|
3416
3659
|
if (!open) return;
|
|
3417
3660
|
const away = (e) => {
|
|
3418
3661
|
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
@@ -3437,14 +3680,14 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
3437
3680
|
const toggle = () => {
|
|
3438
3681
|
if (!disabled) setOpen(!open);
|
|
3439
3682
|
};
|
|
3440
|
-
return /* @__PURE__ */
|
|
3441
|
-
label ? /* @__PURE__ */
|
|
3683
|
+
return /* @__PURE__ */ jsxs44("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
3684
|
+
label ? /* @__PURE__ */ jsxs44("label", { className: "fd-field-label", onClick: toggle, children: [
|
|
3442
3685
|
label,
|
|
3443
|
-
required ? /* @__PURE__ */
|
|
3686
|
+
required ? /* @__PURE__ */ jsx49("span", { className: "fd-field-req", children: "*" }) : null
|
|
3444
3687
|
] }) : null,
|
|
3445
|
-
/* @__PURE__ */
|
|
3446
|
-
/* @__PURE__ */
|
|
3447
|
-
/* @__PURE__ */
|
|
3688
|
+
/* @__PURE__ */ jsxs44("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: [
|
|
3689
|
+
/* @__PURE__ */ jsx49("span", { className: "fd-input-icon", children: /* @__PURE__ */ jsx49("i", { className: "ph ph-clock", "aria-hidden": "true" }) }),
|
|
3690
|
+
/* @__PURE__ */ jsx49(
|
|
3448
3691
|
"button",
|
|
3449
3692
|
{
|
|
3450
3693
|
type: "button",
|
|
@@ -3459,13 +3702,13 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
3459
3702
|
children: disp() || placeholder
|
|
3460
3703
|
}
|
|
3461
3704
|
),
|
|
3462
|
-
/* @__PURE__ */
|
|
3705
|
+
/* @__PURE__ */ jsx49("span", { className: "fd-select-caret", children: /* @__PURE__ */ jsx49("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
|
|
3463
3706
|
] }),
|
|
3464
3707
|
open && pos ? createPortal6(
|
|
3465
|
-
/* @__PURE__ */
|
|
3466
|
-
/* @__PURE__ */
|
|
3467
|
-
/* @__PURE__ */
|
|
3468
|
-
/* @__PURE__ */
|
|
3708
|
+
/* @__PURE__ */ jsxs44("div", { className: "fd-pop" + (pos.up ? " is-up" : ""), ref: popRef, style: popStyle3(pos, { width: 262, minWidth: 0, zIndex: 130 }), children: [
|
|
3709
|
+
/* @__PURE__ */ jsx49(ClockFace, { value: value || "09:00", onChange: (v) => onChange && onChange({ target: { value: v } }) }),
|
|
3710
|
+
/* @__PURE__ */ jsxs44("div", { className: "fd-cal-foot", style: { margin: "0 14px 12px", paddingTop: 10 }, children: [
|
|
3711
|
+
/* @__PURE__ */ jsx49(
|
|
3469
3712
|
"button",
|
|
3470
3713
|
{
|
|
3471
3714
|
type: "button",
|
|
@@ -3478,22 +3721,22 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
3478
3721
|
children: "Now"
|
|
3479
3722
|
}
|
|
3480
3723
|
),
|
|
3481
|
-
/* @__PURE__ */
|
|
3482
|
-
/* @__PURE__ */
|
|
3724
|
+
/* @__PURE__ */ jsx49("span", { style: { flex: 1 } }),
|
|
3725
|
+
/* @__PURE__ */ jsx49("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", onClick: () => setOpen(false), children: "Done" })
|
|
3483
3726
|
] })
|
|
3484
3727
|
] }),
|
|
3485
3728
|
document.body
|
|
3486
3729
|
) : null,
|
|
3487
|
-
error ? /* @__PURE__ */
|
|
3488
|
-
/* @__PURE__ */
|
|
3730
|
+
error ? /* @__PURE__ */ jsxs44("span", { className: "fd-field-error", children: [
|
|
3731
|
+
/* @__PURE__ */ jsx49("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3489
3732
|
error
|
|
3490
|
-
] }) : help ? /* @__PURE__ */
|
|
3733
|
+
] }) : help ? /* @__PURE__ */ jsx49("span", { className: "fd-field-help", children: help }) : null
|
|
3491
3734
|
] });
|
|
3492
3735
|
}
|
|
3493
3736
|
|
|
3494
3737
|
// src/components/forms/Slider.tsx
|
|
3495
|
-
import * as
|
|
3496
|
-
import { jsx as
|
|
3738
|
+
import * as React22 from "react";
|
|
3739
|
+
import { jsx as jsx50, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
3497
3740
|
function Slider({
|
|
3498
3741
|
label,
|
|
3499
3742
|
min = 0,
|
|
@@ -3507,18 +3750,18 @@ function Slider({
|
|
|
3507
3750
|
className = "",
|
|
3508
3751
|
...rest
|
|
3509
3752
|
}) {
|
|
3510
|
-
const [dragging, setDragging] =
|
|
3753
|
+
const [dragging, setDragging] = React22.useState(false);
|
|
3511
3754
|
const v = value === void 0 ? min : Number(value);
|
|
3512
3755
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
3513
|
-
return /* @__PURE__ */
|
|
3514
|
-
label ? /* @__PURE__ */
|
|
3515
|
-
/* @__PURE__ */
|
|
3516
|
-
/* @__PURE__ */
|
|
3756
|
+
return /* @__PURE__ */ jsxs45("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
|
|
3757
|
+
label ? /* @__PURE__ */ jsxs45("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
3758
|
+
/* @__PURE__ */ jsx50("span", { className: "fd-field-label", children: label }),
|
|
3759
|
+
/* @__PURE__ */ jsx50("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: format(v) })
|
|
3517
3760
|
] }) : null,
|
|
3518
|
-
/* @__PURE__ */
|
|
3519
|
-
/* @__PURE__ */
|
|
3520
|
-
showChip && dragging ? /* @__PURE__ */
|
|
3521
|
-
/* @__PURE__ */
|
|
3761
|
+
/* @__PURE__ */ jsxs45("div", { className: "fd-slider", children: [
|
|
3762
|
+
/* @__PURE__ */ jsx50("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
3763
|
+
showChip && dragging ? /* @__PURE__ */ jsx50("span", { className: "fd-slider-chip", style: { left: pct + "%" }, children: format(v) }) : null,
|
|
3764
|
+
/* @__PURE__ */ jsx50(
|
|
3522
3765
|
"input",
|
|
3523
3766
|
{
|
|
3524
3767
|
type: "range",
|
|
@@ -3535,13 +3778,13 @@ function Slider({
|
|
|
3535
3778
|
}
|
|
3536
3779
|
)
|
|
3537
3780
|
] }),
|
|
3538
|
-
help ? /* @__PURE__ */
|
|
3781
|
+
help ? /* @__PURE__ */ jsx50("span", { className: "fd-field-help", children: help }) : null
|
|
3539
3782
|
] });
|
|
3540
3783
|
}
|
|
3541
3784
|
|
|
3542
3785
|
// src/components/forms/RangeSlider.tsx
|
|
3543
|
-
import * as
|
|
3544
|
-
import { jsx as
|
|
3786
|
+
import * as React23 from "react";
|
|
3787
|
+
import { jsx as jsx51, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
3545
3788
|
function RangeSlider({
|
|
3546
3789
|
label,
|
|
3547
3790
|
min = 0,
|
|
@@ -3560,9 +3803,9 @@ function RangeSlider({
|
|
|
3560
3803
|
}) {
|
|
3561
3804
|
const fmt2 = format || ((v) => String(v));
|
|
3562
3805
|
const [a, b] = value || [min, max];
|
|
3563
|
-
const [drag, setDrag] =
|
|
3564
|
-
const [focus, setFocus] =
|
|
3565
|
-
const railRef =
|
|
3806
|
+
const [drag, setDrag] = React23.useState(null);
|
|
3807
|
+
const [focus, setFocus] = React23.useState(null);
|
|
3808
|
+
const railRef = React23.useRef(null);
|
|
3566
3809
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
3567
3810
|
const clampPair = (i, v) => {
|
|
3568
3811
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -3577,7 +3820,7 @@ function RangeSlider({
|
|
|
3577
3820
|
const r = railRef.current.getBoundingClientRect();
|
|
3578
3821
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
3579
3822
|
};
|
|
3580
|
-
|
|
3823
|
+
React23.useEffect(() => {
|
|
3581
3824
|
if (drag === null) return;
|
|
3582
3825
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
3583
3826
|
const upH = () => setDrag(null);
|
|
@@ -3598,7 +3841,7 @@ function RangeSlider({
|
|
|
3598
3841
|
};
|
|
3599
3842
|
const thin = S.length > 7 ? Math.ceil(S.length / 5) : 1;
|
|
3600
3843
|
const pair = value || [S[0].value, S[S.length - 1].value];
|
|
3601
|
-
return /* @__PURE__ */
|
|
3844
|
+
return /* @__PURE__ */ jsx51(
|
|
3602
3845
|
RangeSlider,
|
|
3603
3846
|
{
|
|
3604
3847
|
...rest,
|
|
@@ -3646,23 +3889,23 @@ function RangeSlider({
|
|
|
3646
3889
|
};
|
|
3647
3890
|
const showChip = (i) => drag === i || focus === i;
|
|
3648
3891
|
const hasLabels = marks.some((m) => m.label);
|
|
3649
|
-
return /* @__PURE__ */
|
|
3650
|
-
label ? /* @__PURE__ */
|
|
3651
|
-
/* @__PURE__ */
|
|
3652
|
-
/* @__PURE__ */
|
|
3892
|
+
return /* @__PURE__ */ jsxs46("div", { className: ["fd-field", className].filter(Boolean).join(" "), ...rest, children: [
|
|
3893
|
+
label ? /* @__PURE__ */ jsxs46("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
3894
|
+
/* @__PURE__ */ jsx51("span", { className: "fd-field-label", children: label }),
|
|
3895
|
+
/* @__PURE__ */ jsxs46("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: [
|
|
3653
3896
|
fmt2(a),
|
|
3654
3897
|
" \u2013 ",
|
|
3655
3898
|
fmt2(b)
|
|
3656
3899
|
] })
|
|
3657
3900
|
] }) : null,
|
|
3658
|
-
/* @__PURE__ */
|
|
3659
|
-
/* @__PURE__ */
|
|
3660
|
-
/* @__PURE__ */
|
|
3661
|
-
marks.map((m) => /* @__PURE__ */
|
|
3662
|
-
/* @__PURE__ */
|
|
3663
|
-
m.label ? /* @__PURE__ */
|
|
3901
|
+
/* @__PURE__ */ jsxs46("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
|
|
3902
|
+
/* @__PURE__ */ jsx51("span", { className: "fd-range-rail", ref: railRef }),
|
|
3903
|
+
/* @__PURE__ */ jsx51("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
|
|
3904
|
+
marks.map((m) => /* @__PURE__ */ jsxs46(React23.Fragment, { children: [
|
|
3905
|
+
/* @__PURE__ */ jsx51("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
|
|
3906
|
+
m.label ? /* @__PURE__ */ jsx51("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
|
|
3664
3907
|
] }, m.value)),
|
|
3665
|
-
[a, b].map((v, i) => /* @__PURE__ */
|
|
3908
|
+
[a, b].map((v, i) => /* @__PURE__ */ jsx51(
|
|
3666
3909
|
"span",
|
|
3667
3910
|
{
|
|
3668
3911
|
className: "fd-range-thumb" + (drag === i ? " is-drag" : ""),
|
|
@@ -3677,18 +3920,18 @@ function RangeSlider({
|
|
|
3677
3920
|
onKeyDown: key(i),
|
|
3678
3921
|
onFocus: () => setFocus(i),
|
|
3679
3922
|
onBlur: () => setFocus(null),
|
|
3680
|
-
children: /* @__PURE__ */
|
|
3923
|
+
children: /* @__PURE__ */ jsx51("span", { className: "fd-range-chip", style: { opacity: showChip(i) ? 1 : void 0 }, children: fmt2(v) })
|
|
3681
3924
|
},
|
|
3682
3925
|
i
|
|
3683
3926
|
))
|
|
3684
3927
|
] }),
|
|
3685
|
-
help ? /* @__PURE__ */
|
|
3928
|
+
help ? /* @__PURE__ */ jsx51("span", { className: "fd-field-help", children: help }) : null
|
|
3686
3929
|
] });
|
|
3687
3930
|
}
|
|
3688
3931
|
|
|
3689
3932
|
// src/components/forms/Dropzone.tsx
|
|
3690
|
-
import * as
|
|
3691
|
-
import { jsx as
|
|
3933
|
+
import * as React24 from "react";
|
|
3934
|
+
import { jsx as jsx52, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
3692
3935
|
function Dropzone({
|
|
3693
3936
|
onFiles,
|
|
3694
3937
|
onReject,
|
|
@@ -3702,8 +3945,8 @@ function Dropzone({
|
|
|
3702
3945
|
className = "",
|
|
3703
3946
|
style
|
|
3704
3947
|
}) {
|
|
3705
|
-
const [over, setOver] =
|
|
3706
|
-
const depth =
|
|
3948
|
+
const [over, setOver] = React24.useState(false);
|
|
3949
|
+
const depth = React24.useRef(0);
|
|
3707
3950
|
const has = (e) => {
|
|
3708
3951
|
const dt = e.dataTransfer;
|
|
3709
3952
|
if (!dt) return false;
|
|
@@ -3733,7 +3976,7 @@ function Dropzone({
|
|
|
3733
3976
|
if (rejected.length && onReject) onReject(rejected);
|
|
3734
3977
|
if (accepted.length && onFiles) onFiles(accepted);
|
|
3735
3978
|
};
|
|
3736
|
-
return /* @__PURE__ */
|
|
3979
|
+
return /* @__PURE__ */ jsxs47(
|
|
3737
3980
|
"div",
|
|
3738
3981
|
{
|
|
3739
3982
|
className: ["fd-dropzone", over ? "is-over" : "", className].filter(Boolean).join(" "),
|
|
@@ -3744,10 +3987,10 @@ function Dropzone({
|
|
|
3744
3987
|
onDrop: drop,
|
|
3745
3988
|
children: [
|
|
3746
3989
|
children,
|
|
3747
|
-
over ? /* @__PURE__ */
|
|
3748
|
-
/* @__PURE__ */
|
|
3749
|
-
/* @__PURE__ */
|
|
3750
|
-
hint ? /* @__PURE__ */
|
|
3990
|
+
over ? /* @__PURE__ */ jsx52("div", { className: "fd-dropzone-veil", "aria-hidden": "true", children: /* @__PURE__ */ jsxs47("div", { className: "fd-dropzone-card", children: [
|
|
3991
|
+
/* @__PURE__ */ jsx52("i", { className: "ph ph-tray-arrow-down" }),
|
|
3992
|
+
/* @__PURE__ */ jsx52("span", { className: "fd-dropzone-label", children: label }),
|
|
3993
|
+
hint ? /* @__PURE__ */ jsx52("span", { className: "fd-dropzone-hint", children: hint }) : null
|
|
3751
3994
|
] }) }) : null
|
|
3752
3995
|
]
|
|
3753
3996
|
}
|
|
@@ -3765,9 +4008,9 @@ function FilePickButton({
|
|
|
3765
4008
|
className = "",
|
|
3766
4009
|
children
|
|
3767
4010
|
}) {
|
|
3768
|
-
const ref =
|
|
3769
|
-
return /* @__PURE__ */
|
|
3770
|
-
/* @__PURE__ */
|
|
4011
|
+
const ref = React24.useRef(null);
|
|
4012
|
+
return /* @__PURE__ */ jsxs47(React24.Fragment, { children: [
|
|
4013
|
+
/* @__PURE__ */ jsx52(
|
|
3771
4014
|
"button",
|
|
3772
4015
|
{
|
|
3773
4016
|
type: "button",
|
|
@@ -3776,10 +4019,10 @@ function FilePickButton({
|
|
|
3776
4019
|
"aria-label": label,
|
|
3777
4020
|
title: label,
|
|
3778
4021
|
onClick: () => ref.current && ref.current.click(),
|
|
3779
|
-
children: children != null ? children : /* @__PURE__ */
|
|
4022
|
+
children: children != null ? children : /* @__PURE__ */ jsx52("i", { className: "ph ph-" + icon, "aria-hidden": "true" })
|
|
3780
4023
|
}
|
|
3781
4024
|
),
|
|
3782
|
-
/* @__PURE__ */
|
|
4025
|
+
/* @__PURE__ */ jsx52(
|
|
3783
4026
|
"input",
|
|
3784
4027
|
{
|
|
3785
4028
|
ref,
|
|
@@ -3799,10 +4042,10 @@ function FilePickButton({
|
|
|
3799
4042
|
}
|
|
3800
4043
|
function useStagedFiles(upload, opts) {
|
|
3801
4044
|
const o = opts || {};
|
|
3802
|
-
const [items, setItems] =
|
|
3803
|
-
const controllers =
|
|
4045
|
+
const [items, setItems] = React24.useState([]);
|
|
4046
|
+
const controllers = React24.useRef({});
|
|
3804
4047
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
3805
|
-
const run =
|
|
4048
|
+
const run = React24.useCallback((att) => {
|
|
3806
4049
|
if (!upload) return;
|
|
3807
4050
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
3808
4051
|
controllers.current[att.id] = ac;
|
|
@@ -3819,14 +4062,14 @@ function useStagedFiles(upload, opts) {
|
|
|
3819
4062
|
delete controllers.current[att.id];
|
|
3820
4063
|
});
|
|
3821
4064
|
}, [upload]);
|
|
3822
|
-
const add =
|
|
4065
|
+
const add = React24.useCallback((files) => {
|
|
3823
4066
|
if (!upload) return [];
|
|
3824
4067
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
3825
4068
|
setItems((list) => list.concat(atts));
|
|
3826
4069
|
atts.forEach(run);
|
|
3827
4070
|
return atts;
|
|
3828
4071
|
}, [upload, run]);
|
|
3829
|
-
const remove =
|
|
4072
|
+
const remove = React24.useCallback((att) => {
|
|
3830
4073
|
const ac = controllers.current[att.id];
|
|
3831
4074
|
if (ac) {
|
|
3832
4075
|
try {
|
|
@@ -3837,10 +4080,10 @@ function useStagedFiles(upload, opts) {
|
|
|
3837
4080
|
}
|
|
3838
4081
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
3839
4082
|
}, []);
|
|
3840
|
-
const retry =
|
|
4083
|
+
const retry = React24.useCallback((att) => {
|
|
3841
4084
|
run(att);
|
|
3842
4085
|
}, [run]);
|
|
3843
|
-
const clear =
|
|
4086
|
+
const clear = React24.useCallback(() => {
|
|
3844
4087
|
Object.values(controllers.current).forEach((ac) => {
|
|
3845
4088
|
try {
|
|
3846
4089
|
ac && ac.abort();
|
|
@@ -3856,7 +4099,7 @@ function useStagedFiles(upload, opts) {
|
|
|
3856
4099
|
var DropzoneKit = { useStagedFiles };
|
|
3857
4100
|
|
|
3858
4101
|
// src/components/forms/FileGrid.tsx
|
|
3859
|
-
import { jsx as
|
|
4102
|
+
import { jsx as jsx53, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
3860
4103
|
var truncateMiddle = (name, max = 34) => {
|
|
3861
4104
|
if (!name || name.length <= max) return name;
|
|
3862
4105
|
const ext = /\.[A-Za-z0-9]+$/.exec(name);
|
|
@@ -3865,7 +4108,7 @@ var truncateMiddle = (name, max = 34) => {
|
|
|
3865
4108
|
return head + "\u2026" + tail;
|
|
3866
4109
|
};
|
|
3867
4110
|
function Progress({ value }) {
|
|
3868
|
-
return /* @__PURE__ */
|
|
4111
|
+
return /* @__PURE__ */ jsx53("span", { className: "fd-file-prog", role: "progressbar", "aria-valuenow": Math.round(value), "aria-valuemin": 0, "aria-valuemax": 100, children: /* @__PURE__ */ jsx53("span", { className: "fd-file-prog-fill", style: { width: Math.max(4, Math.min(100, value)) + "%" } }) });
|
|
3869
4112
|
}
|
|
3870
4113
|
function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false, className = "" }) {
|
|
3871
4114
|
if (!file) return null;
|
|
@@ -3874,8 +4117,8 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
3874
4117
|
const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
|
|
3875
4118
|
const meta = file.meta || (file.size ? formatBytes(file.size) : "");
|
|
3876
4119
|
const clickable = !!onOpen && !uploading;
|
|
3877
|
-
return /* @__PURE__ */
|
|
3878
|
-
/* @__PURE__ */
|
|
4120
|
+
return /* @__PURE__ */ jsxs48("div", { className: ["fd-file", compact3 ? "is-compact" : "", file.error ? "is-error" : "", uploading ? "is-uploading" : "", className].filter(Boolean).join(" "), children: [
|
|
4121
|
+
/* @__PURE__ */ jsxs48(
|
|
3879
4122
|
"button",
|
|
3880
4123
|
{
|
|
3881
4124
|
type: "button",
|
|
@@ -3884,16 +4127,16 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
3884
4127
|
onClick: clickable ? () => onOpen(file) : void 0,
|
|
3885
4128
|
title: file.name + (meta ? " \xB7 " + meta : ""),
|
|
3886
4129
|
children: [
|
|
3887
|
-
/* @__PURE__ */
|
|
3888
|
-
thumb ? /* @__PURE__ */
|
|
3889
|
-
(file.mime || "").startsWith("video/") ? /* @__PURE__ */
|
|
4130
|
+
/* @__PURE__ */ jsxs48("span", { className: "fd-file-icon", children: [
|
|
4131
|
+
thumb ? /* @__PURE__ */ jsx53("img", { src: thumb, alt: "" }) : /* @__PURE__ */ jsx53("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
|
|
4132
|
+
(file.mime || "").startsWith("video/") ? /* @__PURE__ */ jsx53("i", { className: "ph ph-play fd-file-play", "aria-hidden": "true" }) : null
|
|
3890
4133
|
] }),
|
|
3891
|
-
/* @__PURE__ */
|
|
3892
|
-
/* @__PURE__ */
|
|
3893
|
-
/* @__PURE__ */
|
|
3894
|
-
/* @__PURE__ */
|
|
4134
|
+
/* @__PURE__ */ jsxs48("span", { className: "fd-file-text", children: [
|
|
4135
|
+
/* @__PURE__ */ jsx53("span", { className: "fd-file-name", children: truncateMiddle(file.name, compact3 ? 26 : 40) }),
|
|
4136
|
+
/* @__PURE__ */ jsx53("span", { className: "fd-file-meta", children: file.error ? /* @__PURE__ */ jsxs48("span", { className: "fd-file-err", children: [
|
|
4137
|
+
/* @__PURE__ */ jsx53("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3895
4138
|
file.error
|
|
3896
|
-
] }) : uploading ? /* @__PURE__ */
|
|
4139
|
+
] }) : uploading ? /* @__PURE__ */ jsxs48("span", { className: "fd-tabular", children: [
|
|
3897
4140
|
Math.round(file.progress),
|
|
3898
4141
|
"% uploaded"
|
|
3899
4142
|
] }) : meta })
|
|
@@ -3901,29 +4144,29 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
3901
4144
|
]
|
|
3902
4145
|
}
|
|
3903
4146
|
),
|
|
3904
|
-
uploading ? /* @__PURE__ */
|
|
3905
|
-
file.error && onRetry ? /* @__PURE__ */
|
|
3906
|
-
onRemove ? /* @__PURE__ */
|
|
4147
|
+
uploading ? /* @__PURE__ */ jsx53(Progress, { value: file.progress }) : null,
|
|
4148
|
+
file.error && onRetry ? /* @__PURE__ */ jsx53("button", { type: "button", className: "fd-file-act", onClick: () => onRetry(file), "aria-label": "Retry upload of " + file.name, children: /* @__PURE__ */ jsx53("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
4149
|
+
onRemove ? /* @__PURE__ */ jsx53("button", { type: "button", className: "fd-file-act", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ jsx53("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
3907
4150
|
] });
|
|
3908
4151
|
}
|
|
3909
4152
|
function FileTile({ file, onOpen, onRemove, maxHeight = 200, className = "" }) {
|
|
3910
4153
|
if (!file) return null;
|
|
3911
4154
|
const src = file.thumb && file.thumb.url || file.blobUrl || file.url;
|
|
3912
4155
|
const uploading = file.progress != null && file.progress < 100 && !file.error;
|
|
3913
|
-
return /* @__PURE__ */
|
|
3914
|
-
/* @__PURE__ */
|
|
3915
|
-
uploading ? /* @__PURE__ */
|
|
3916
|
-
file.error ? /* @__PURE__ */
|
|
3917
|
-
/* @__PURE__ */
|
|
4156
|
+
return /* @__PURE__ */ jsxs48("figure", { className: ["fd-tile", uploading ? "is-uploading" : "", file.error ? "is-error" : "", className].filter(Boolean).join(" "), children: [
|
|
4157
|
+
/* @__PURE__ */ jsx53("button", { type: "button", className: "fd-tile-btn", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen, children: src ? /* @__PURE__ */ jsx53("img", { src, alt: file.name || "", style: { maxHeight }, loading: "lazy" }) : /* @__PURE__ */ jsx53("span", { className: "fd-tile-fallback", children: /* @__PURE__ */ jsx53("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }) }) }),
|
|
4158
|
+
uploading ? /* @__PURE__ */ jsx53(Progress, { value: file.progress }) : null,
|
|
4159
|
+
file.error ? /* @__PURE__ */ jsxs48("figcaption", { className: "fd-tile-err", children: [
|
|
4160
|
+
/* @__PURE__ */ jsx53("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3918
4161
|
file.error
|
|
3919
4162
|
] }) : null,
|
|
3920
|
-
onRemove ? /* @__PURE__ */
|
|
4163
|
+
onRemove ? /* @__PURE__ */ jsx53("button", { type: "button", className: "fd-tile-x", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ jsx53("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
3921
4164
|
] });
|
|
3922
4165
|
}
|
|
3923
4166
|
function FileStrip({ files = [], size = 68, onOpen, onRemove, onRetry, className = "" }) {
|
|
3924
4167
|
const list = files.filter(Boolean);
|
|
3925
4168
|
if (!list.length) return null;
|
|
3926
|
-
return /* @__PURE__ */
|
|
4169
|
+
return /* @__PURE__ */ jsx53("div", { className: ["fd-filestrip", className].filter(Boolean).join(" "), style: { "--fd-cell": size + "px" }, children: list.map((f) => /* @__PURE__ */ jsx53(FileCell, { file: f, onOpen, onRemove, onRetry }, f.id || f.name)) });
|
|
3927
4170
|
}
|
|
3928
4171
|
var shortName = (name, keep = 5) => {
|
|
3929
4172
|
const s = String(name || "file");
|
|
@@ -3937,19 +4180,19 @@ function FileCell({ file, onOpen, onRemove, onRetry }) {
|
|
|
3937
4180
|
const image = isImage(file.mime, file.name);
|
|
3938
4181
|
const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
|
|
3939
4182
|
const label = file.name + (file.size ? " \xB7 " + formatBytes(file.size) : "");
|
|
3940
|
-
return /* @__PURE__ */
|
|
3941
|
-
/* @__PURE__ */
|
|
3942
|
-
thumb ? /* @__PURE__ */
|
|
3943
|
-
/* @__PURE__ */
|
|
3944
|
-
/* @__PURE__ */
|
|
3945
|
-
/* @__PURE__ */
|
|
4183
|
+
return /* @__PURE__ */ jsxs48("div", { className: ["fd-cell", file.error ? "is-error" : "", uploading ? "is-uploading" : ""].filter(Boolean).join(" "), title: file.error ? file.name + " \u2014 " + file.error : label, children: [
|
|
4184
|
+
/* @__PURE__ */ jsxs48("button", { type: "button", className: "fd-cell-main", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen || uploading, "aria-label": "Open " + file.name, children: [
|
|
4185
|
+
thumb ? /* @__PURE__ */ jsx53("img", { src: thumb, alt: "" }) : /* @__PURE__ */ jsxs48("span", { className: "fd-cell-doc", children: [
|
|
4186
|
+
/* @__PURE__ */ jsx53("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
|
|
4187
|
+
/* @__PURE__ */ jsx53("span", { className: "fd-cell-name", children: shortName(file.name) }),
|
|
4188
|
+
/* @__PURE__ */ jsx53("span", { className: "fd-cell-size", children: file.meta || formatBytes(file.size) })
|
|
3946
4189
|
] }),
|
|
3947
|
-
(file.mime || "").startsWith("video/") ? /* @__PURE__ */
|
|
4190
|
+
(file.mime || "").startsWith("video/") ? /* @__PURE__ */ jsx53("i", { className: "ph ph-play fd-cell-play", "aria-hidden": "true" }) : null
|
|
3948
4191
|
] }),
|
|
3949
|
-
uploading ? /* @__PURE__ */
|
|
3950
|
-
file.error ? /* @__PURE__ */
|
|
3951
|
-
file.error && onRetry ? /* @__PURE__ */
|
|
3952
|
-
onRemove ? /* @__PURE__ */
|
|
4192
|
+
uploading ? /* @__PURE__ */ jsx53(Progress, { value: file.progress }) : null,
|
|
4193
|
+
file.error ? /* @__PURE__ */ jsx53("span", { className: "fd-cell-err", "aria-hidden": "true", children: /* @__PURE__ */ jsx53("i", { className: "ph ph-warning-circle" }) }) : null,
|
|
4194
|
+
file.error && onRetry ? /* @__PURE__ */ jsx53("button", { type: "button", className: "fd-cell-x is-retry", onClick: () => onRetry(file), "aria-label": "Retry upload of " + file.name, children: /* @__PURE__ */ jsx53("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
4195
|
+
onRemove ? /* @__PURE__ */ jsx53("button", { type: "button", className: "fd-cell-x", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ jsx53("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
3953
4196
|
] });
|
|
3954
4197
|
}
|
|
3955
4198
|
function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeight = 200, compact: compact3 = false, className = "" }) {
|
|
@@ -3957,15 +4200,15 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
3957
4200
|
if (!list.length) return null;
|
|
3958
4201
|
const pics = tiles ? list.filter((f) => isImage(f.mime, f.name)) : [];
|
|
3959
4202
|
const rest = list.filter((f) => pics.indexOf(f) === -1);
|
|
3960
|
-
return /* @__PURE__ */
|
|
3961
|
-
pics.length ? /* @__PURE__ */
|
|
3962
|
-
rest.length ? /* @__PURE__ */
|
|
4203
|
+
return /* @__PURE__ */ jsxs48("div", { className: ["fd-filegrid", className].filter(Boolean).join(" "), children: [
|
|
4204
|
+
pics.length ? /* @__PURE__ */ jsx53("div", { className: "fd-filegrid-tiles", children: pics.map((f) => /* @__PURE__ */ jsx53(FileTile, { file: f, onOpen, onRemove, maxHeight }, f.id || f.name)) }) : null,
|
|
4205
|
+
rest.length ? /* @__PURE__ */ jsx53("div", { className: "fd-filegrid-chips", children: rest.map((f) => /* @__PURE__ */ jsx53(FileChip, { file: f, onOpen, onRemove, onRetry, compact: compact3 }, f.id || f.name)) }) : null
|
|
3963
4206
|
] });
|
|
3964
4207
|
}
|
|
3965
4208
|
|
|
3966
4209
|
// src/components/forms/MarkdownEditor.tsx
|
|
3967
|
-
import * as
|
|
3968
|
-
import { jsx as
|
|
4210
|
+
import * as React25 from "react";
|
|
4211
|
+
import { jsx as jsx54, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
3969
4212
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
3970
4213
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
3971
4214
|
function inlineParts(text) {
|
|
@@ -4178,7 +4421,7 @@ function syncDom(root, value) {
|
|
|
4178
4421
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
4179
4422
|
}
|
|
4180
4423
|
var LIST_CONT = RE_LI;
|
|
4181
|
-
var MarkdownEditor =
|
|
4424
|
+
var MarkdownEditor = React25.forwardRef(function MarkdownEditor2({
|
|
4182
4425
|
value = "",
|
|
4183
4426
|
onChange,
|
|
4184
4427
|
onSubmit,
|
|
@@ -4197,10 +4440,10 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4197
4440
|
className = "",
|
|
4198
4441
|
id
|
|
4199
4442
|
}, ref) {
|
|
4200
|
-
const boxRef =
|
|
4201
|
-
const composing =
|
|
4202
|
-
const pendingCaret =
|
|
4203
|
-
|
|
4443
|
+
const boxRef = React25.useRef(null);
|
|
4444
|
+
const composing = React25.useRef(false);
|
|
4445
|
+
const pendingCaret = React25.useRef(null);
|
|
4446
|
+
React25.useLayoutEffect(() => {
|
|
4204
4447
|
const root = boxRef.current;
|
|
4205
4448
|
if (!root || composing.current) return;
|
|
4206
4449
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -4209,7 +4452,7 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4209
4452
|
pendingCaret.current = null;
|
|
4210
4453
|
if (active && caret != null) placeCaret(root, caret);
|
|
4211
4454
|
}, [value]);
|
|
4212
|
-
|
|
4455
|
+
React25.useEffect(() => {
|
|
4213
4456
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
4214
4457
|
}, [autoFocus]);
|
|
4215
4458
|
const caretNow = () => {
|
|
@@ -4276,7 +4519,7 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4276
4519
|
api.replaceRange(from, to, next, from + next.length);
|
|
4277
4520
|
}
|
|
4278
4521
|
};
|
|
4279
|
-
|
|
4522
|
+
React25.useImperativeHandle(ref, () => api);
|
|
4280
4523
|
function detect(text, caret) {
|
|
4281
4524
|
if (!onTrigger) return;
|
|
4282
4525
|
const upto = text.slice(0, caret);
|
|
@@ -4389,8 +4632,8 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4389
4632
|
api.replaceRange(s.start, s.end, text.replace(/\r\n?/g, "\n"));
|
|
4390
4633
|
};
|
|
4391
4634
|
const lh = 1.55;
|
|
4392
|
-
return /* @__PURE__ */
|
|
4393
|
-
/* @__PURE__ */
|
|
4635
|
+
return /* @__PURE__ */ jsxs49("div", { className: ["fd-rme-wrap", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "), children: [
|
|
4636
|
+
/* @__PURE__ */ jsx54(
|
|
4394
4637
|
"div",
|
|
4395
4638
|
{
|
|
4396
4639
|
ref: boxRef,
|
|
@@ -4423,15 +4666,15 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
|
|
|
4423
4666
|
}
|
|
4424
4667
|
}
|
|
4425
4668
|
),
|
|
4426
|
-
!value ? /* @__PURE__ */
|
|
4669
|
+
!value ? /* @__PURE__ */ jsx54("span", { className: "fd-rme-ph", "aria-hidden": "true", children: placeholder }) : null
|
|
4427
4670
|
] });
|
|
4428
4671
|
});
|
|
4429
4672
|
|
|
4430
4673
|
// src/components/platform/AccountMenu.tsx
|
|
4431
|
-
import * as
|
|
4674
|
+
import * as React27 from "react";
|
|
4432
4675
|
|
|
4433
4676
|
// src/kits/session.ts
|
|
4434
|
-
import * as
|
|
4677
|
+
import * as React26 from "react";
|
|
4435
4678
|
var PERMISSION_CATALOG = [
|
|
4436
4679
|
{ group: "Plans", items: [
|
|
4437
4680
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -5998,8 +6241,8 @@ function roadmap(overrides) {
|
|
|
5998
6241
|
};
|
|
5999
6242
|
}
|
|
6000
6243
|
function useSession() {
|
|
6001
|
-
const [s, setS] =
|
|
6002
|
-
|
|
6244
|
+
const [s, setS] = React26.useState(getSession);
|
|
6245
|
+
React26.useEffect(() => subscribe(setS), []);
|
|
6003
6246
|
return s;
|
|
6004
6247
|
}
|
|
6005
6248
|
var SessionKit = {
|
|
@@ -6032,7 +6275,7 @@ var SessionKit = {
|
|
|
6032
6275
|
};
|
|
6033
6276
|
|
|
6034
6277
|
// src/components/platform/AccountMenu.tsx
|
|
6035
|
-
import { Fragment as Fragment11, jsx as
|
|
6278
|
+
import { Fragment as Fragment11, jsx as jsx55, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
6036
6279
|
var DEFAULT_LINKS = [
|
|
6037
6280
|
{ id: "profile", label: "Your profile", icon: "user-circle", href: "../admin/index.html#profile" },
|
|
6038
6281
|
{ id: "preferences", label: "Preferences", icon: "sliders-horizontal", href: "../admin/index.html#preferences" }
|
|
@@ -6043,7 +6286,7 @@ var DEFAULT_ADMIN_LINKS = [
|
|
|
6043
6286
|
{ id: "flags", label: "Feature flags", icon: "toggle-right", href: "../admin/index.html#flags", perm: "flags.manage" }
|
|
6044
6287
|
];
|
|
6045
6288
|
function Item({ item, onPick }) {
|
|
6046
|
-
return /* @__PURE__ */
|
|
6289
|
+
return /* @__PURE__ */ jsxs50(
|
|
6047
6290
|
"button",
|
|
6048
6291
|
{
|
|
6049
6292
|
type: "button",
|
|
@@ -6051,9 +6294,9 @@ function Item({ item, onPick }) {
|
|
|
6051
6294
|
className: "fd-acct-item",
|
|
6052
6295
|
onClick: () => onPick(item),
|
|
6053
6296
|
children: [
|
|
6054
|
-
/* @__PURE__ */
|
|
6055
|
-
/* @__PURE__ */
|
|
6056
|
-
item.badge ? /* @__PURE__ */
|
|
6297
|
+
/* @__PURE__ */ jsx55("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }),
|
|
6298
|
+
/* @__PURE__ */ jsx55("span", { style: { flex: 1 }, children: item.label }),
|
|
6299
|
+
item.badge ? /* @__PURE__ */ jsx55(Badge, { tone: "neutral", children: item.badge }) : null
|
|
6057
6300
|
]
|
|
6058
6301
|
}
|
|
6059
6302
|
);
|
|
@@ -6069,9 +6312,9 @@ function AccountMenu({
|
|
|
6069
6312
|
...rest
|
|
6070
6313
|
}) {
|
|
6071
6314
|
const session = SessionKit.useSession();
|
|
6072
|
-
const [open, setOpen] =
|
|
6073
|
-
const [switching, setSwitching] =
|
|
6074
|
-
const ref =
|
|
6315
|
+
const [open, setOpen] = React27.useState(false);
|
|
6316
|
+
const [switching, setSwitching] = React27.useState(false);
|
|
6317
|
+
const ref = React27.useRef(null);
|
|
6075
6318
|
const user = session.user;
|
|
6076
6319
|
const visibleAdmin = adminLinks.filter((l) => !l.perm || SessionKit.can(l.perm));
|
|
6077
6320
|
const pick = (item) => {
|
|
@@ -6085,8 +6328,8 @@ function AccountMenu({
|
|
|
6085
6328
|
if (onSignOut) return onSignOut();
|
|
6086
6329
|
window.alert("Signed out. (Simulated \u2014 no auth provider is wired up.)");
|
|
6087
6330
|
};
|
|
6088
|
-
return /* @__PURE__ */
|
|
6089
|
-
/* @__PURE__ */
|
|
6331
|
+
return /* @__PURE__ */ jsxs50(Fragment11, { children: [
|
|
6332
|
+
/* @__PURE__ */ jsxs50(
|
|
6090
6333
|
"button",
|
|
6091
6334
|
{
|
|
6092
6335
|
type: "button",
|
|
@@ -6098,32 +6341,32 @@ function AccountMenu({
|
|
|
6098
6341
|
onClick: () => setOpen((o) => !o),
|
|
6099
6342
|
...rest,
|
|
6100
6343
|
children: [
|
|
6101
|
-
/* @__PURE__ */
|
|
6102
|
-
/* @__PURE__ */
|
|
6344
|
+
/* @__PURE__ */ jsx55(Avatar, { name: user.name, size: "sm" }),
|
|
6345
|
+
/* @__PURE__ */ jsx55("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
|
|
6103
6346
|
]
|
|
6104
6347
|
}
|
|
6105
6348
|
),
|
|
6106
|
-
/* @__PURE__ */
|
|
6107
|
-
/* @__PURE__ */
|
|
6108
|
-
/* @__PURE__ */
|
|
6109
|
-
/* @__PURE__ */
|
|
6110
|
-
/* @__PURE__ */
|
|
6111
|
-
/* @__PURE__ */
|
|
6349
|
+
/* @__PURE__ */ jsx55(Popover, { open, anchorRef: ref, onClose: () => setOpen(false), placement: "bottom-end", width: 272, children: /* @__PURE__ */ jsxs50("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
|
|
6350
|
+
/* @__PURE__ */ jsxs50("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
6351
|
+
/* @__PURE__ */ jsx55(Avatar, { name: user.name }),
|
|
6352
|
+
/* @__PURE__ */ jsxs50("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
|
|
6353
|
+
/* @__PURE__ */ jsx55("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
|
|
6354
|
+
/* @__PURE__ */ jsx55("span", { className: "fd-body-sm fd-muted fd-table-trunc", children: user.email })
|
|
6112
6355
|
] })
|
|
6113
6356
|
] }),
|
|
6114
|
-
showRoles && session.roles.length ? /* @__PURE__ */
|
|
6115
|
-
/* @__PURE__ */
|
|
6116
|
-
visibleAdmin.length ? /* @__PURE__ */
|
|
6117
|
-
/* @__PURE__ */
|
|
6118
|
-
visibleAdmin.map((l) => /* @__PURE__ */
|
|
6357
|
+
showRoles && session.roles.length ? /* @__PURE__ */ jsx55("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: session.roles.map((r) => /* @__PURE__ */ jsx55(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
|
|
6358
|
+
/* @__PURE__ */ jsx55("div", { className: "fd-acct-group", children: links.map((l) => /* @__PURE__ */ jsx55(Item, { item: l, onPick: pick }, l.id)) }),
|
|
6359
|
+
visibleAdmin.length ? /* @__PURE__ */ jsxs50("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
6360
|
+
/* @__PURE__ */ jsx55("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: "Administration" }),
|
|
6361
|
+
visibleAdmin.map((l) => /* @__PURE__ */ jsx55(Item, { item: l, onPick: pick }, l.id))
|
|
6119
6362
|
] }) : null,
|
|
6120
|
-
allowUserSwitch ? /* @__PURE__ */
|
|
6121
|
-
/* @__PURE__ */
|
|
6122
|
-
/* @__PURE__ */
|
|
6123
|
-
/* @__PURE__ */
|
|
6124
|
-
/* @__PURE__ */
|
|
6363
|
+
allowUserSwitch ? /* @__PURE__ */ jsxs50("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
6364
|
+
/* @__PURE__ */ jsxs50("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
|
|
6365
|
+
/* @__PURE__ */ jsx55("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
|
|
6366
|
+
/* @__PURE__ */ jsx55("span", { style: { flex: 1 }, children: "View as another member" }),
|
|
6367
|
+
/* @__PURE__ */ jsx55("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
|
|
6125
6368
|
] }),
|
|
6126
|
-
switching ? /* @__PURE__ */
|
|
6369
|
+
switching ? /* @__PURE__ */ jsx55("div", { className: "fd-stack", style: { gap: 0, maxHeight: 208, overflowY: "auto" }, children: session.allUsers.filter((u) => u.status === "active").map((u) => /* @__PURE__ */ jsxs50(
|
|
6127
6370
|
"button",
|
|
6128
6371
|
{
|
|
6129
6372
|
type: "button",
|
|
@@ -6135,34 +6378,34 @@ function AccountMenu({
|
|
|
6135
6378
|
setSwitching(false);
|
|
6136
6379
|
},
|
|
6137
6380
|
children: [
|
|
6138
|
-
/* @__PURE__ */
|
|
6139
|
-
/* @__PURE__ */
|
|
6140
|
-
/* @__PURE__ */
|
|
6141
|
-
/* @__PURE__ */
|
|
6381
|
+
/* @__PURE__ */ jsx55(Avatar, { name: u.name, size: "sm" }),
|
|
6382
|
+
/* @__PURE__ */ jsxs50("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
|
|
6383
|
+
/* @__PURE__ */ jsx55("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
|
|
6384
|
+
/* @__PURE__ */ jsx55("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") })
|
|
6142
6385
|
] }),
|
|
6143
|
-
u.id === user.id ? /* @__PURE__ */
|
|
6386
|
+
u.id === user.id ? /* @__PURE__ */ jsx55("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
|
|
6144
6387
|
]
|
|
6145
6388
|
},
|
|
6146
6389
|
u.id
|
|
6147
6390
|
)) }) : null
|
|
6148
6391
|
] }) : null,
|
|
6149
|
-
/* @__PURE__ */
|
|
6150
|
-
/* @__PURE__ */
|
|
6151
|
-
/* @__PURE__ */
|
|
6392
|
+
/* @__PURE__ */ jsx55("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: /* @__PURE__ */ jsxs50("button", { type: "button", role: "menuitem", className: "fd-acct-item", "data-danger": "true", onClick: signOut, children: [
|
|
6393
|
+
/* @__PURE__ */ jsx55("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
|
|
6394
|
+
/* @__PURE__ */ jsx55("span", { style: { flex: 1 }, children: "Sign out" })
|
|
6152
6395
|
] }) })
|
|
6153
6396
|
] }) })
|
|
6154
6397
|
] });
|
|
6155
6398
|
}
|
|
6156
6399
|
|
|
6157
6400
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
6158
|
-
import * as
|
|
6159
|
-
import { jsx as
|
|
6401
|
+
import * as React28 from "react";
|
|
6402
|
+
import { jsx as jsx56, jsxs as jsxs51 } from "react/jsx-runtime";
|
|
6160
6403
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
6161
6404
|
function Json({ obj }) {
|
|
6162
|
-
return /* @__PURE__ */
|
|
6405
|
+
return /* @__PURE__ */ jsx56("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
6163
6406
|
}
|
|
6164
6407
|
function Endpoint({ s, onRequest }) {
|
|
6165
|
-
const [tried, setTried] =
|
|
6408
|
+
const [tried, setTried] = React28.useState(null);
|
|
6166
6409
|
const run = async () => {
|
|
6167
6410
|
setTried("busy");
|
|
6168
6411
|
const t0 = (window.performance || Date).now();
|
|
@@ -6173,50 +6416,50 @@ function Endpoint({ s, onRequest }) {
|
|
|
6173
6416
|
setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
|
|
6174
6417
|
}
|
|
6175
6418
|
};
|
|
6176
|
-
return /* @__PURE__ */
|
|
6177
|
-
/* @__PURE__ */
|
|
6178
|
-
/* @__PURE__ */
|
|
6179
|
-
/* @__PURE__ */
|
|
6180
|
-
s.isList ? /* @__PURE__ */
|
|
6181
|
-
/* @__PURE__ */
|
|
6182
|
-
/* @__PURE__ */
|
|
6419
|
+
return /* @__PURE__ */ jsx56(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
6420
|
+
/* @__PURE__ */ jsxs51("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
|
|
6421
|
+
/* @__PURE__ */ jsx56(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
|
|
6422
|
+
/* @__PURE__ */ jsx56("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
|
|
6423
|
+
s.isList ? /* @__PURE__ */ jsx56(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
|
|
6424
|
+
/* @__PURE__ */ jsx56("span", { style: { flex: 1 } }),
|
|
6425
|
+
/* @__PURE__ */ jsxs51("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
6183
6426
|
s.latency[0],
|
|
6184
6427
|
"\u2013",
|
|
6185
6428
|
s.latency[1],
|
|
6186
6429
|
"ms"
|
|
6187
6430
|
] }),
|
|
6188
|
-
/* @__PURE__ */
|
|
6431
|
+
/* @__PURE__ */ jsx56(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
|
|
6189
6432
|
] }),
|
|
6190
|
-
/* @__PURE__ */
|
|
6191
|
-
/* @__PURE__ */
|
|
6192
|
-
/* @__PURE__ */
|
|
6193
|
-
/* @__PURE__ */
|
|
6194
|
-
s.usedBy && s.usedBy.length ? /* @__PURE__ */
|
|
6433
|
+
/* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
|
|
6434
|
+
/* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6435
|
+
/* @__PURE__ */ jsx56("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
|
|
6436
|
+
/* @__PURE__ */ jsx56("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
|
|
6437
|
+
s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx56("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx56(Tag, { children: u }, u)) }) : null
|
|
6195
6438
|
] }),
|
|
6196
|
-
/* @__PURE__ */
|
|
6197
|
-
s.request ? /* @__PURE__ */
|
|
6198
|
-
/* @__PURE__ */
|
|
6199
|
-
/* @__PURE__ */
|
|
6439
|
+
/* @__PURE__ */ jsxs51("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
|
|
6440
|
+
s.request ? /* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6441
|
+
/* @__PURE__ */ jsx56("span", { className: "fd-overline fd-muted", children: "Request body" }),
|
|
6442
|
+
/* @__PURE__ */ jsx56(Json, { obj: s.request })
|
|
6200
6443
|
] }) : null,
|
|
6201
|
-
s.query ? /* @__PURE__ */
|
|
6202
|
-
/* @__PURE__ */
|
|
6203
|
-
/* @__PURE__ */
|
|
6444
|
+
s.query ? /* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6445
|
+
/* @__PURE__ */ jsx56("span", { className: "fd-overline fd-muted", children: "Query" }),
|
|
6446
|
+
/* @__PURE__ */ jsx56(Json, { obj: s.query })
|
|
6204
6447
|
] }) : null,
|
|
6205
|
-
/* @__PURE__ */
|
|
6206
|
-
/* @__PURE__ */
|
|
6207
|
-
/* @__PURE__ */
|
|
6448
|
+
/* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6449
|
+
/* @__PURE__ */ jsx56("span", { className: "fd-overline fd-muted", children: "Response 200" }),
|
|
6450
|
+
/* @__PURE__ */ jsx56(Json, { obj: s.response })
|
|
6208
6451
|
] })
|
|
6209
6452
|
] }),
|
|
6210
|
-
s.notes ? /* @__PURE__ */
|
|
6211
|
-
tried && tried !== "busy" ? /* @__PURE__ */
|
|
6212
|
-
/* @__PURE__ */
|
|
6213
|
-
/* @__PURE__ */
|
|
6214
|
-
/* @__PURE__ */
|
|
6453
|
+
s.notes ? /* @__PURE__ */ jsx56(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
|
|
6454
|
+
tried && tried !== "busy" ? /* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6455
|
+
/* @__PURE__ */ jsxs51("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
6456
|
+
/* @__PURE__ */ jsx56("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
|
|
6457
|
+
/* @__PURE__ */ jsxs51(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
|
|
6215
6458
|
tried.ms,
|
|
6216
6459
|
"ms"
|
|
6217
6460
|
] })
|
|
6218
6461
|
] }),
|
|
6219
|
-
/* @__PURE__ */
|
|
6462
|
+
/* @__PURE__ */ jsx56(Json, { obj: tried.error ? { error: tried.error } : tried.data })
|
|
6220
6463
|
] }) : null
|
|
6221
6464
|
] })
|
|
6222
6465
|
] }) });
|
|
@@ -6235,58 +6478,58 @@ function ApiSpecBrowser({
|
|
|
6235
6478
|
className = "",
|
|
6236
6479
|
...rest
|
|
6237
6480
|
}) {
|
|
6238
|
-
const [q, setQ] =
|
|
6239
|
-
const [method, setMethod] =
|
|
6240
|
-
const [mod, setMod] =
|
|
6241
|
-
const [listOnly, setListOnly] =
|
|
6481
|
+
const [q, setQ] = React28.useState("");
|
|
6482
|
+
const [method, setMethod] = React28.useState(null);
|
|
6483
|
+
const [mod, setMod] = React28.useState(null);
|
|
6484
|
+
const [listOnly, setListOnly] = React28.useState(false);
|
|
6242
6485
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
6243
6486
|
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())));
|
|
6244
6487
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
6245
6488
|
const methods = [...new Set(spec.map((s) => s.method))];
|
|
6246
6489
|
const listCount = spec.filter((s) => s.isList).length;
|
|
6247
|
-
return /* @__PURE__ */
|
|
6248
|
-
/* @__PURE__ */
|
|
6249
|
-
kicker ? /* @__PURE__ */
|
|
6250
|
-
/* @__PURE__ */
|
|
6251
|
-
lede ? /* @__PURE__ */
|
|
6490
|
+
return /* @__PURE__ */ jsxs51("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
|
|
6491
|
+
/* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
6492
|
+
kicker ? /* @__PURE__ */ jsx56("span", { className: "fd-overline fd-muted", children: kicker }) : null,
|
|
6493
|
+
/* @__PURE__ */ jsx56("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
6494
|
+
lede ? /* @__PURE__ */ jsx56("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
|
|
6252
6495
|
] }),
|
|
6253
|
-
modules && modules.length ? /* @__PURE__ */
|
|
6254
|
-
/* @__PURE__ */
|
|
6255
|
-
/* @__PURE__ */
|
|
6256
|
-
/* @__PURE__ */
|
|
6496
|
+
modules && modules.length ? /* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
6497
|
+
/* @__PURE__ */ jsx56("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
|
|
6498
|
+
/* @__PURE__ */ jsxs51("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
6499
|
+
/* @__PURE__ */ jsxs51(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
|
|
6257
6500
|
"All screens ",
|
|
6258
|
-
/* @__PURE__ */
|
|
6501
|
+
/* @__PURE__ */ jsx56("span", { className: "fd-mono", children: spec.length })
|
|
6259
6502
|
] }),
|
|
6260
|
-
modules.map((m) => /* @__PURE__ */
|
|
6503
|
+
modules.map((m) => /* @__PURE__ */ jsxs51(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
|
|
6261
6504
|
m.label,
|
|
6262
6505
|
" ",
|
|
6263
|
-
/* @__PURE__ */
|
|
6506
|
+
/* @__PURE__ */ jsx56("span", { className: "fd-mono", children: m.endpoints.length })
|
|
6264
6507
|
] }, m.id))
|
|
6265
6508
|
] }),
|
|
6266
|
-
activeModule ? /* @__PURE__ */
|
|
6509
|
+
activeModule ? /* @__PURE__ */ jsx56(
|
|
6267
6510
|
Flag,
|
|
6268
6511
|
{
|
|
6269
6512
|
tone: "info",
|
|
6270
6513
|
statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
|
|
6271
6514
|
cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
|
|
6272
|
-
actions: /* @__PURE__ */
|
|
6515
|
+
actions: /* @__PURE__ */ jsx56(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
|
|
6273
6516
|
}
|
|
6274
6517
|
) : null
|
|
6275
6518
|
] }) : null,
|
|
6276
|
-
sourceNote ? /* @__PURE__ */
|
|
6277
|
-
/* @__PURE__ */
|
|
6278
|
-
/* @__PURE__ */
|
|
6279
|
-
methods.map((m) => /* @__PURE__ */
|
|
6519
|
+
sourceNote ? /* @__PURE__ */ jsx56(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
|
|
6520
|
+
/* @__PURE__ */ jsxs51("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
6521
|
+
/* @__PURE__ */ jsx56(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
|
|
6522
|
+
methods.map((m) => /* @__PURE__ */ jsxs51(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
|
|
6280
6523
|
m,
|
|
6281
6524
|
" ",
|
|
6282
|
-
/* @__PURE__ */
|
|
6525
|
+
/* @__PURE__ */ jsx56("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
|
|
6283
6526
|
] }, m)),
|
|
6284
|
-
listCount ? /* @__PURE__ */
|
|
6527
|
+
listCount ? /* @__PURE__ */ jsxs51(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
|
|
6285
6528
|
"Paged lists ",
|
|
6286
|
-
/* @__PURE__ */
|
|
6529
|
+
/* @__PURE__ */ jsx56("span", { className: "fd-mono", children: listCount })
|
|
6287
6530
|
] }) : null,
|
|
6288
|
-
/* @__PURE__ */
|
|
6289
|
-
/* @__PURE__ */
|
|
6531
|
+
/* @__PURE__ */ jsx56("span", { style: { flex: 1 } }),
|
|
6532
|
+
/* @__PURE__ */ jsxs51("span", { className: "fd-body-sm fd-muted", children: [
|
|
6290
6533
|
hits.length,
|
|
6291
6534
|
" of ",
|
|
6292
6535
|
spec.length,
|
|
@@ -6294,31 +6537,31 @@ function ApiSpecBrowser({
|
|
|
6294
6537
|
listCount ? " \xB7 " + listCount + " paged" : ""
|
|
6295
6538
|
] })
|
|
6296
6539
|
] }),
|
|
6297
|
-
hits.length === 0 ? /* @__PURE__ */
|
|
6540
|
+
hits.length === 0 ? /* @__PURE__ */ jsx56(Card, { elevation: "flat", children: /* @__PURE__ */ jsx56("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
|
|
6298
6541
|
const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
|
|
6299
6542
|
if (!items.length) return null;
|
|
6300
|
-
return /* @__PURE__ */
|
|
6301
|
-
/* @__PURE__ */
|
|
6302
|
-
items.map((s) => /* @__PURE__ */
|
|
6543
|
+
return /* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 12 }, children: [
|
|
6544
|
+
/* @__PURE__ */ jsx56("span", { className: "fd-label-lg", children: g }),
|
|
6545
|
+
items.map((s) => /* @__PURE__ */ jsx56(Endpoint, { s, onRequest }, s.id))
|
|
6303
6546
|
] }, g);
|
|
6304
6547
|
}),
|
|
6305
|
-
conventions && conventions.length ? /* @__PURE__ */
|
|
6306
|
-
/* @__PURE__ */
|
|
6307
|
-
/* @__PURE__ */
|
|
6548
|
+
conventions && conventions.length ? /* @__PURE__ */ jsx56(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx56("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs51("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
|
|
6549
|
+
/* @__PURE__ */ jsx56("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
|
|
6550
|
+
/* @__PURE__ */ jsx56("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
|
|
6308
6551
|
] }, k)) }) }) : null,
|
|
6309
|
-
openQuestions && openQuestions.length ? /* @__PURE__ */
|
|
6310
|
-
/* @__PURE__ */
|
|
6311
|
-
/* @__PURE__ */
|
|
6312
|
-
/* @__PURE__ */
|
|
6313
|
-
/* @__PURE__ */
|
|
6552
|
+
openQuestions && openQuestions.length ? /* @__PURE__ */ jsx56(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx56("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs51("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
|
|
6553
|
+
/* @__PURE__ */ jsx56(Badge, { tone: "danger", children: id }),
|
|
6554
|
+
/* @__PURE__ */ jsxs51("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
|
|
6555
|
+
/* @__PURE__ */ jsx56("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
|
|
6556
|
+
/* @__PURE__ */ jsx56("span", { className: "fd-body-sm fd-muted", children: why })
|
|
6314
6557
|
] })
|
|
6315
6558
|
] }, id)) }) }) : null
|
|
6316
6559
|
] });
|
|
6317
6560
|
}
|
|
6318
6561
|
|
|
6319
6562
|
// src/components/platform/ProfilePage.tsx
|
|
6320
|
-
import * as
|
|
6321
|
-
import { jsx as
|
|
6563
|
+
import * as React29 from "react";
|
|
6564
|
+
import { jsx as jsx57, jsxs as jsxs52 } from "react/jsx-runtime";
|
|
6322
6565
|
var TIMEZONES = ["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles", "America/Anchorage", "Pacific/Honolulu", "Europe/London", "Europe/Berlin"];
|
|
6323
6566
|
var NOTIFY = [
|
|
6324
6567
|
{ key: "planShared", label: "A plan is shared with me", detail: "Someone sends you a plan or a client link." },
|
|
@@ -6330,7 +6573,7 @@ var NOTIFY = [
|
|
|
6330
6573
|
function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSessions = true, className = "", ...rest }) {
|
|
6331
6574
|
const session = SessionKit.useSession();
|
|
6332
6575
|
const user = userProp || session.user;
|
|
6333
|
-
const [draft, setDraft] =
|
|
6576
|
+
const [draft, setDraft] = React29.useState(() => ({
|
|
6334
6577
|
name: user.name || "",
|
|
6335
6578
|
title: user.title || "",
|
|
6336
6579
|
email: user.email || "",
|
|
@@ -6339,8 +6582,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6339
6582
|
bio: user.bio || "",
|
|
6340
6583
|
notify: user.notify || { planShared: true, planChanged: true, goalMissed: true, flagChanged: false, weekly: true }
|
|
6341
6584
|
}));
|
|
6342
|
-
const [saving, setSaving] =
|
|
6343
|
-
const [saved, setSaved] =
|
|
6585
|
+
const [saving, setSaving] = React29.useState(false);
|
|
6586
|
+
const [saved, setSaved] = React29.useState(false);
|
|
6344
6587
|
const set = (k, v) => {
|
|
6345
6588
|
setDraft((d) => Object.assign({}, d, { [k]: v }));
|
|
6346
6589
|
setSaved(false);
|
|
@@ -6362,43 +6605,43 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6362
6605
|
{ id: "s2", device: "iPhone 15 \xB7 Safari", where: "Denver, CO", when: "2 hours ago" },
|
|
6363
6606
|
{ id: "s3", device: "Windows \xB7 Edge", where: "Chicago, IL", when: "Aug 12" }
|
|
6364
6607
|
];
|
|
6365
|
-
return /* @__PURE__ */
|
|
6366
|
-
/* @__PURE__ */
|
|
6367
|
-
/* @__PURE__ */
|
|
6368
|
-
/* @__PURE__ */
|
|
6369
|
-
/* @__PURE__ */
|
|
6608
|
+
return /* @__PURE__ */ jsxs52("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, ...rest, children: [
|
|
6609
|
+
/* @__PURE__ */ jsxs52("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
6610
|
+
/* @__PURE__ */ jsx57("span", { className: "fd-overline fd-muted", children: "Account" }),
|
|
6611
|
+
/* @__PURE__ */ jsx57("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
|
|
6612
|
+
/* @__PURE__ */ jsx57("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." })
|
|
6370
6613
|
] }),
|
|
6371
|
-
/* @__PURE__ */
|
|
6372
|
-
/* @__PURE__ */
|
|
6373
|
-
/* @__PURE__ */
|
|
6374
|
-
/* @__PURE__ */
|
|
6375
|
-
/* @__PURE__ */
|
|
6614
|
+
/* @__PURE__ */ jsx57(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs52("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
|
|
6615
|
+
/* @__PURE__ */ jsx57(Avatar, { name: draft.name || user.name, size: "lg" }),
|
|
6616
|
+
/* @__PURE__ */ jsxs52("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
|
|
6617
|
+
/* @__PURE__ */ jsx57("span", { className: "fd-h3", style: { margin: 0 }, children: draft.name || user.name }),
|
|
6618
|
+
/* @__PURE__ */ jsxs52("span", { className: "fd-body-sm fd-muted", children: [
|
|
6376
6619
|
draft.title || "No title set",
|
|
6377
6620
|
" \xB7 ",
|
|
6378
6621
|
user.team || "No team"
|
|
6379
6622
|
] }),
|
|
6380
|
-
/* @__PURE__ */
|
|
6381
|
-
session.roles.map((r) => /* @__PURE__ */
|
|
6382
|
-
user.sso ? /* @__PURE__ */
|
|
6623
|
+
/* @__PURE__ */ jsxs52("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
|
|
6624
|
+
session.roles.map((r) => /* @__PURE__ */ jsx57(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
|
|
6625
|
+
user.sso ? /* @__PURE__ */ jsx57(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
|
|
6383
6626
|
] })
|
|
6384
6627
|
] }),
|
|
6385
|
-
/* @__PURE__ */
|
|
6628
|
+
/* @__PURE__ */ jsx57(Button, { variant: "secondary", size: "sm", icon: "image", children: "Change photo" })
|
|
6386
6629
|
] }) }),
|
|
6387
|
-
/* @__PURE__ */
|
|
6630
|
+
/* @__PURE__ */ jsx57(
|
|
6388
6631
|
Card,
|
|
6389
6632
|
{
|
|
6390
|
-
title: /* @__PURE__ */
|
|
6391
|
-
/* @__PURE__ */
|
|
6392
|
-
/* @__PURE__ */
|
|
6633
|
+
title: /* @__PURE__ */ jsxs52("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
6634
|
+
/* @__PURE__ */ jsx57("span", { children: "Identity" }),
|
|
6635
|
+
/* @__PURE__ */ jsx57("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Name and title appear on plans you share" })
|
|
6393
6636
|
] }),
|
|
6394
6637
|
elevation: "flat",
|
|
6395
|
-
children: /* @__PURE__ */
|
|
6396
|
-
/* @__PURE__ */
|
|
6397
|
-
/* @__PURE__ */
|
|
6398
|
-
/* @__PURE__ */
|
|
6638
|
+
children: /* @__PURE__ */ jsxs52("div", { className: "fd-stack", style: { gap: 14 }, children: [
|
|
6639
|
+
/* @__PURE__ */ jsxs52("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
|
|
6640
|
+
/* @__PURE__ */ jsx57(Input, { label: "Full name", value: draft.name, onChange: (e) => set("name", e.target.value) }),
|
|
6641
|
+
/* @__PURE__ */ jsx57(Input, { label: "Job title", value: draft.title, onChange: (e) => set("title", e.target.value), placeholder: "e.g. Senior media planner" })
|
|
6399
6642
|
] }),
|
|
6400
|
-
/* @__PURE__ */
|
|
6401
|
-
/* @__PURE__ */
|
|
6643
|
+
/* @__PURE__ */ jsxs52("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
|
|
6644
|
+
/* @__PURE__ */ jsx57(
|
|
6402
6645
|
Input,
|
|
6403
6646
|
{
|
|
6404
6647
|
label: "Work email",
|
|
@@ -6408,9 +6651,9 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6408
6651
|
help: user.sso ? "Managed by your identity provider \u2014 change it there." : "Contact an administrator to change this."
|
|
6409
6652
|
}
|
|
6410
6653
|
),
|
|
6411
|
-
/* @__PURE__ */
|
|
6654
|
+
/* @__PURE__ */ jsx57(Input, { label: "Phone", value: draft.phone, onChange: (e) => set("phone", e.target.value), placeholder: "Optional" })
|
|
6412
6655
|
] }),
|
|
6413
|
-
/* @__PURE__ */
|
|
6656
|
+
/* @__PURE__ */ jsx57(
|
|
6414
6657
|
Textarea,
|
|
6415
6658
|
{
|
|
6416
6659
|
label: "Short bio",
|
|
@@ -6424,8 +6667,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6424
6667
|
] })
|
|
6425
6668
|
}
|
|
6426
6669
|
),
|
|
6427
|
-
/* @__PURE__ */
|
|
6428
|
-
/* @__PURE__ */
|
|
6670
|
+
/* @__PURE__ */ jsx57(Card, { title: "Working preferences", elevation: "flat", children: /* @__PURE__ */ jsxs52("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
|
|
6671
|
+
/* @__PURE__ */ jsx57(
|
|
6429
6672
|
Select,
|
|
6430
6673
|
{
|
|
6431
6674
|
label: "Time zone",
|
|
@@ -6435,28 +6678,28 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6435
6678
|
help: "Flight dates and schedules render in this zone."
|
|
6436
6679
|
}
|
|
6437
6680
|
),
|
|
6438
|
-
/* @__PURE__ */
|
|
6681
|
+
/* @__PURE__ */ jsx57(Select, { label: "Start of week", options: ["Monday", "Sunday"], placeholder: "Monday" })
|
|
6439
6682
|
] }) }),
|
|
6440
|
-
/* @__PURE__ */
|
|
6683
|
+
/* @__PURE__ */ jsx57(
|
|
6441
6684
|
Card,
|
|
6442
6685
|
{
|
|
6443
|
-
title: /* @__PURE__ */
|
|
6444
|
-
/* @__PURE__ */
|
|
6445
|
-
/* @__PURE__ */
|
|
6686
|
+
title: /* @__PURE__ */ jsxs52("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
6687
|
+
/* @__PURE__ */ jsx57("span", { children: "Notifications" }),
|
|
6688
|
+
/* @__PURE__ */ jsx57("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Email only for now \u2014 in-app notifications are on the roadmap" })
|
|
6446
6689
|
] }),
|
|
6447
6690
|
elevation: "flat",
|
|
6448
|
-
children: /* @__PURE__ */
|
|
6691
|
+
children: /* @__PURE__ */ jsx57("div", { className: "fd-stack", style: { gap: 14 }, children: NOTIFY.map((n) => /* @__PURE__ */ jsx57(Switch, { checked: !!draft.notify[n.key], onChange: () => setNotify(n.key), label: n.label, description: n.detail }, n.key)) })
|
|
6449
6692
|
}
|
|
6450
6693
|
),
|
|
6451
|
-
/* @__PURE__ */
|
|
6694
|
+
/* @__PURE__ */ jsxs52(
|
|
6452
6695
|
Card,
|
|
6453
6696
|
{
|
|
6454
|
-
title: /* @__PURE__ */
|
|
6455
|
-
/* @__PURE__ */
|
|
6456
|
-
/* @__PURE__ */
|
|
6697
|
+
title: /* @__PURE__ */ jsxs52("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
6698
|
+
/* @__PURE__ */ jsx57("span", { children: "Access" }),
|
|
6699
|
+
/* @__PURE__ */ jsx57("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
|
|
6457
6700
|
] }),
|
|
6458
6701
|
elevation: "flat",
|
|
6459
|
-
action: /* @__PURE__ */
|
|
6702
|
+
action: /* @__PURE__ */ jsx57(
|
|
6460
6703
|
Button,
|
|
6461
6704
|
{
|
|
6462
6705
|
size: "sm",
|
|
@@ -6467,39 +6710,39 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6467
6710
|
}
|
|
6468
6711
|
),
|
|
6469
6712
|
children: [
|
|
6470
|
-
/* @__PURE__ */
|
|
6471
|
-
/* @__PURE__ */
|
|
6472
|
-
/* @__PURE__ */
|
|
6713
|
+
/* @__PURE__ */ jsxs52("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
6714
|
+
/* @__PURE__ */ jsx57(CardRow, { label: "Roles", children: session.roles.map((r) => r.name).join(", ") || "None" }),
|
|
6715
|
+
/* @__PURE__ */ jsxs52(CardRow, { label: "Permissions", children: [
|
|
6473
6716
|
session.permissions.length,
|
|
6474
6717
|
" granted"
|
|
6475
6718
|
] }),
|
|
6476
|
-
/* @__PURE__ */
|
|
6719
|
+
/* @__PURE__ */ jsx57(CardRow, { label: "Member since", children: user.joined || "\u2014" })
|
|
6477
6720
|
] }),
|
|
6478
|
-
/* @__PURE__ */
|
|
6721
|
+
/* @__PURE__ */ jsx57("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." })
|
|
6479
6722
|
]
|
|
6480
6723
|
}
|
|
6481
6724
|
),
|
|
6482
|
-
showSessions ? /* @__PURE__ */
|
|
6725
|
+
showSessions ? /* @__PURE__ */ jsx57(
|
|
6483
6726
|
Card,
|
|
6484
6727
|
{
|
|
6485
6728
|
title: "Signed-in devices",
|
|
6486
6729
|
elevation: "flat",
|
|
6487
|
-
action: /* @__PURE__ */
|
|
6488
|
-
children: /* @__PURE__ */
|
|
6489
|
-
/* @__PURE__ */
|
|
6490
|
-
/* @__PURE__ */
|
|
6491
|
-
/* @__PURE__ */
|
|
6492
|
-
/* @__PURE__ */
|
|
6730
|
+
action: /* @__PURE__ */ jsx57(Button, { size: "sm", variant: "ghost", icon: "sign-out", children: "Sign out everywhere" }),
|
|
6731
|
+
children: /* @__PURE__ */ jsx57("div", { className: "fd-stack", style: { gap: 0 }, children: liveSessions.map((s) => /* @__PURE__ */ jsxs52("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
|
|
6732
|
+
/* @__PURE__ */ jsx57("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
6733
|
+
/* @__PURE__ */ jsxs52("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
|
|
6734
|
+
/* @__PURE__ */ jsx57("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
|
|
6735
|
+
/* @__PURE__ */ jsxs52("span", { className: "fd-body-sm fd-muted", children: [
|
|
6493
6736
|
s.where,
|
|
6494
6737
|
" \xB7 ",
|
|
6495
6738
|
s.when
|
|
6496
6739
|
] })
|
|
6497
6740
|
] }),
|
|
6498
|
-
s.current ? /* @__PURE__ */
|
|
6741
|
+
s.current ? /* @__PURE__ */ jsx57(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx57(Button, { size: "sm", variant: "ghost", children: "Revoke" })
|
|
6499
6742
|
] }, s.id)) })
|
|
6500
6743
|
}
|
|
6501
6744
|
) : null,
|
|
6502
|
-
/* @__PURE__ */
|
|
6745
|
+
/* @__PURE__ */ jsxs52("div", { className: "fd-row", style: {
|
|
6503
6746
|
gap: 10,
|
|
6504
6747
|
flexWrap: "wrap",
|
|
6505
6748
|
position: "sticky",
|
|
@@ -6510,8 +6753,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6510
6753
|
border: "1px solid var(--border)",
|
|
6511
6754
|
boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
|
|
6512
6755
|
}, children: [
|
|
6513
|
-
/* @__PURE__ */
|
|
6514
|
-
/* @__PURE__ */
|
|
6756
|
+
/* @__PURE__ */ jsx57("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
|
|
6757
|
+
/* @__PURE__ */ jsx57(
|
|
6515
6758
|
Button,
|
|
6516
6759
|
{
|
|
6517
6760
|
size: "sm",
|
|
@@ -6524,16 +6767,16 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
6524
6767
|
children: "Discard"
|
|
6525
6768
|
}
|
|
6526
6769
|
),
|
|
6527
|
-
/* @__PURE__ */
|
|
6770
|
+
/* @__PURE__ */ jsx57(Button, { size: "sm", icon: "check", disabled: !dirty, loading: saving, onClick: save, children: "Save changes" })
|
|
6528
6771
|
] })
|
|
6529
6772
|
] });
|
|
6530
6773
|
}
|
|
6531
6774
|
|
|
6532
6775
|
// src/components/platform/RoadmapTimeline.tsx
|
|
6533
|
-
import * as
|
|
6776
|
+
import * as React31 from "react";
|
|
6534
6777
|
|
|
6535
6778
|
// src/kits/runtime.ts
|
|
6536
|
-
import * as
|
|
6779
|
+
import * as React30 from "react";
|
|
6537
6780
|
var WIRED_ENDPOINTS = [
|
|
6538
6781
|
// Nothing yet. Every id below would come from a real service:
|
|
6539
6782
|
// "plan.get", "placements.list", …
|
|
@@ -6704,8 +6947,8 @@ var RuntimeKit = {
|
|
|
6704
6947
|
};
|
|
6705
6948
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
6706
6949
|
function useRuntimeMode() {
|
|
6707
|
-
const [m, setM] =
|
|
6708
|
-
|
|
6950
|
+
const [m, setM] = React30.useState(RuntimeKit.getMode());
|
|
6951
|
+
React30.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
6709
6952
|
return m;
|
|
6710
6953
|
}
|
|
6711
6954
|
function useFeatureStatus(key) {
|
|
@@ -6724,7 +6967,7 @@ var UseRuntimeMode = useRuntimeMode;
|
|
|
6724
6967
|
var UseFeatureStatus = useFeatureStatus;
|
|
6725
6968
|
|
|
6726
6969
|
// src/components/platform/RoadmapTimeline.tsx
|
|
6727
|
-
import { jsx as
|
|
6970
|
+
import { jsx as jsx58, jsxs as jsxs53 } from "react/jsx-runtime";
|
|
6728
6971
|
var STATUS = {
|
|
6729
6972
|
shipped: { tone: "success", icon: "check-circle", label: "Wired" },
|
|
6730
6973
|
next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
|
|
@@ -6739,45 +6982,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
6739
6982
|
const s = STATUS[item.status] || STATUS.planned;
|
|
6740
6983
|
const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
|
|
6741
6984
|
const blocking = deps.filter((d) => !d.implemented);
|
|
6742
|
-
return /* @__PURE__ */
|
|
6743
|
-
/* @__PURE__ */
|
|
6744
|
-
/* @__PURE__ */
|
|
6745
|
-
/* @__PURE__ */
|
|
6746
|
-
/* @__PURE__ */
|
|
6985
|
+
return /* @__PURE__ */ jsx58(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs53("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
6986
|
+
/* @__PURE__ */ jsxs53("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
6987
|
+
/* @__PURE__ */ jsx58("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
|
|
6988
|
+
/* @__PURE__ */ jsx58(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
|
|
6989
|
+
/* @__PURE__ */ jsx58(Badge, { tone: s.tone, icon: s.icon, children: s.label })
|
|
6747
6990
|
] }),
|
|
6748
|
-
/* @__PURE__ */
|
|
6749
|
-
item.backend ? /* @__PURE__ */
|
|
6750
|
-
/* @__PURE__ */
|
|
6751
|
-
/* @__PURE__ */
|
|
6991
|
+
/* @__PURE__ */ jsx58("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
|
|
6992
|
+
item.backend ? /* @__PURE__ */ jsxs53("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
|
|
6993
|
+
/* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
|
|
6994
|
+
/* @__PURE__ */ jsx58("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
|
|
6752
6995
|
] }) : null,
|
|
6753
|
-
/* @__PURE__ */
|
|
6754
|
-
item.effort ? /* @__PURE__ */
|
|
6755
|
-
/* @__PURE__ */
|
|
6996
|
+
/* @__PURE__ */ jsxs53("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
6997
|
+
item.effort ? /* @__PURE__ */ jsxs53("span", { className: "fd-body-sm fd-muted", children: [
|
|
6998
|
+
/* @__PURE__ */ jsx58("i", { className: "ph ph-hourglass-medium" }),
|
|
6756
6999
|
" ",
|
|
6757
7000
|
item.effort
|
|
6758
7001
|
] }) : null,
|
|
6759
|
-
/* @__PURE__ */
|
|
6760
|
-
/* @__PURE__ */
|
|
7002
|
+
/* @__PURE__ */ jsxs53("span", { className: "fd-body-sm fd-muted", children: [
|
|
7003
|
+
/* @__PURE__ */ jsx58("i", { className: "ph ph-user" }),
|
|
6761
7004
|
" ",
|
|
6762
7005
|
item.owner
|
|
6763
7006
|
] }),
|
|
6764
|
-
item.screen ? /* @__PURE__ */
|
|
6765
|
-
/* @__PURE__ */
|
|
6766
|
-
/* @__PURE__ */
|
|
7007
|
+
item.screen ? /* @__PURE__ */ jsx58(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
|
|
7008
|
+
/* @__PURE__ */ jsx58("span", { style: { flex: 1 } }),
|
|
7009
|
+
/* @__PURE__ */ jsx58(
|
|
6767
7010
|
"button",
|
|
6768
7011
|
{
|
|
6769
7012
|
type: "button",
|
|
6770
7013
|
onClick: () => onOpenFlag && onOpenFlag(item.key),
|
|
6771
7014
|
style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
|
|
6772
|
-
children: /* @__PURE__ */
|
|
7015
|
+
children: /* @__PURE__ */ jsx58("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
|
|
6773
7016
|
}
|
|
6774
7017
|
)
|
|
6775
7018
|
] }),
|
|
6776
|
-
deps.length ? /* @__PURE__ */
|
|
6777
|
-
/* @__PURE__ */
|
|
6778
|
-
deps.map((d) => /* @__PURE__ */
|
|
7019
|
+
deps.length ? /* @__PURE__ */ jsxs53("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
|
|
7020
|
+
/* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
|
|
7021
|
+
deps.map((d) => /* @__PURE__ */ jsx58(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
|
|
6779
7022
|
] }) : null,
|
|
6780
|
-
blocking.length && !item.implemented ? /* @__PURE__ */
|
|
7023
|
+
blocking.length && !item.implemented ? /* @__PURE__ */ jsxs53("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
|
|
6781
7024
|
"Blocked until ",
|
|
6782
7025
|
blocking.map((d) => d.label).join(" and "),
|
|
6783
7026
|
" ",
|
|
@@ -6788,12 +7031,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
6788
7031
|
}
|
|
6789
7032
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
6790
7033
|
const session = SessionKit.useSession();
|
|
6791
|
-
const [project, setProject] =
|
|
6792
|
-
const [q, setQ] =
|
|
6793
|
-
const scrollRef =
|
|
6794
|
-
const nowRef =
|
|
6795
|
-
const rm =
|
|
6796
|
-
const byKey =
|
|
7034
|
+
const [project, setProject] = React31.useState("");
|
|
7035
|
+
const [q, setQ] = React31.useState("");
|
|
7036
|
+
const scrollRef = React31.useRef(null);
|
|
7037
|
+
const nowRef = React31.useRef(null);
|
|
7038
|
+
const rm = React31.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
7039
|
+
const byKey = React31.useMemo(() => {
|
|
6797
7040
|
const m = {};
|
|
6798
7041
|
rm.items.forEach((i) => {
|
|
6799
7042
|
m[i.key] = i;
|
|
@@ -6802,7 +7045,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
6802
7045
|
}, [rm]);
|
|
6803
7046
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
6804
7047
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
6805
|
-
|
|
7048
|
+
React31.useEffect(() => {
|
|
6806
7049
|
let raf1 = 0, raf2 = 0;
|
|
6807
7050
|
const place = () => {
|
|
6808
7051
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -6830,23 +7073,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
6830
7073
|
}, 0);
|
|
6831
7074
|
const nextPhase = items.find((i) => !i.implemented);
|
|
6832
7075
|
let lastPhase = null;
|
|
6833
|
-
return /* @__PURE__ */
|
|
6834
|
-
/* @__PURE__ */
|
|
6835
|
-
/* @__PURE__ */
|
|
6836
|
-
/* @__PURE__ */
|
|
6837
|
-
/* @__PURE__ */
|
|
7076
|
+
return /* @__PURE__ */ jsxs53("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
|
|
7077
|
+
/* @__PURE__ */ jsxs53("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
7078
|
+
/* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", children: "Architecture" }),
|
|
7079
|
+
/* @__PURE__ */ jsx58("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
7080
|
+
/* @__PURE__ */ jsx58("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." })
|
|
6838
7081
|
] }),
|
|
6839
|
-
/* @__PURE__ */
|
|
6840
|
-
/* @__PURE__ */
|
|
6841
|
-
/* @__PURE__ */
|
|
6842
|
-
/* @__PURE__ */
|
|
6843
|
-
/* @__PURE__ */
|
|
7082
|
+
/* @__PURE__ */ jsxs53("div", { className: "fd-grid-stats is-thin", children: [
|
|
7083
|
+
/* @__PURE__ */ jsx58(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
|
|
7084
|
+
/* @__PURE__ */ jsx58(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
|
|
7085
|
+
/* @__PURE__ */ jsx58(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
|
|
7086
|
+
/* @__PURE__ */ jsx58(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
|
|
6844
7087
|
] }),
|
|
6845
|
-
/* @__PURE__ */
|
|
6846
|
-
/* @__PURE__ */
|
|
6847
|
-
/* @__PURE__ */
|
|
6848
|
-
/* @__PURE__ */
|
|
6849
|
-
/* @__PURE__ */
|
|
7088
|
+
/* @__PURE__ */ jsxs53("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
7089
|
+
/* @__PURE__ */ jsx58(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 } }),
|
|
7090
|
+
/* @__PURE__ */ jsx58(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
|
|
7091
|
+
/* @__PURE__ */ jsx58("span", { style: { flex: 1 } }),
|
|
7092
|
+
/* @__PURE__ */ jsx58(
|
|
6850
7093
|
Button,
|
|
6851
7094
|
{
|
|
6852
7095
|
size: "sm",
|
|
@@ -6860,7 +7103,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
6860
7103
|
}
|
|
6861
7104
|
)
|
|
6862
7105
|
] }),
|
|
6863
|
-
/* @__PURE__ */
|
|
7106
|
+
/* @__PURE__ */ jsx58(
|
|
6864
7107
|
Flag,
|
|
6865
7108
|
{
|
|
6866
7109
|
tone: "info",
|
|
@@ -6869,60 +7112,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
6869
7112
|
actions: null
|
|
6870
7113
|
}
|
|
6871
7114
|
),
|
|
6872
|
-
/* @__PURE__ */
|
|
6873
|
-
/* @__PURE__ */
|
|
7115
|
+
/* @__PURE__ */ jsx58("div", { className: "fd-rm", children: /* @__PURE__ */ jsx58("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs53("div", { className: "fd-rm-track", children: [
|
|
7116
|
+
/* @__PURE__ */ jsx58("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx58("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
|
|
6874
7117
|
items.map((item, n) => {
|
|
6875
7118
|
const showPhase = item.phase !== lastPhase;
|
|
6876
7119
|
lastPhase = item.phase;
|
|
6877
7120
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
6878
7121
|
const isBoundary = n === firstPending;
|
|
6879
|
-
return /* @__PURE__ */
|
|
6880
|
-
showPhase ? /* @__PURE__ */
|
|
6881
|
-
/* @__PURE__ */
|
|
6882
|
-
/* @__PURE__ */
|
|
6883
|
-
item.phase === 0 ? null : /* @__PURE__ */
|
|
7122
|
+
return /* @__PURE__ */ jsxs53(React31.Fragment, { children: [
|
|
7123
|
+
showPhase ? /* @__PURE__ */ jsxs53("div", { className: "fd-rm-era", children: [
|
|
7124
|
+
/* @__PURE__ */ jsxs53("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
7125
|
+
/* @__PURE__ */ jsx58("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
7126
|
+
item.phase === 0 ? null : /* @__PURE__ */ jsxs53("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
6884
7127
|
fmtDate(item.phaseStart),
|
|
6885
7128
|
" \u2013 ",
|
|
6886
7129
|
fmtDate(item.date)
|
|
6887
7130
|
] }),
|
|
6888
|
-
/* @__PURE__ */
|
|
7131
|
+
/* @__PURE__ */ jsxs53("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
6889
7132
|
"\xB7 ",
|
|
6890
7133
|
inPhase,
|
|
6891
7134
|
" feature",
|
|
6892
7135
|
inPhase === 1 ? "" : "s"
|
|
6893
7136
|
] })
|
|
6894
7137
|
] }),
|
|
6895
|
-
item.phaseWhy ? /* @__PURE__ */
|
|
7138
|
+
item.phaseWhy ? /* @__PURE__ */ jsx58("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
|
|
6896
7139
|
] }) : null,
|
|
6897
|
-
isBoundary ? /* @__PURE__ */
|
|
6898
|
-
/* @__PURE__ */
|
|
7140
|
+
isBoundary ? /* @__PURE__ */ jsx58("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs53("span", { className: "fd-rm-now-pill", children: [
|
|
7141
|
+
/* @__PURE__ */ jsx58("i", { className: "ph ph-map-pin" }),
|
|
6899
7142
|
" You are here \u2014 everything above is wired"
|
|
6900
7143
|
] }) }) : null,
|
|
6901
|
-
/* @__PURE__ */
|
|
6902
|
-
/* @__PURE__ */
|
|
6903
|
-
/* @__PURE__ */
|
|
7144
|
+
/* @__PURE__ */ jsxs53("div", { className: "fd-rm-row", children: [
|
|
7145
|
+
/* @__PURE__ */ jsx58("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
|
|
7146
|
+
/* @__PURE__ */ jsxs53("div", { className: "fd-rm-date", children: [
|
|
6904
7147
|
fmtDate(item.date),
|
|
6905
|
-
/* @__PURE__ */
|
|
6906
|
-
/* @__PURE__ */
|
|
7148
|
+
/* @__PURE__ */ jsx58("br", {}),
|
|
7149
|
+
/* @__PURE__ */ jsx58("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
|
|
6907
7150
|
] }),
|
|
6908
|
-
/* @__PURE__ */
|
|
7151
|
+
/* @__PURE__ */ jsx58(RoadmapCard, { item, byKey, onOpenFlag })
|
|
6909
7152
|
] })
|
|
6910
7153
|
] }, item.key);
|
|
6911
7154
|
}),
|
|
6912
|
-
!items.length ? /* @__PURE__ */
|
|
7155
|
+
!items.length ? /* @__PURE__ */ jsx58("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
|
|
6913
7156
|
] }) }) }),
|
|
6914
|
-
/* @__PURE__ */
|
|
7157
|
+
/* @__PURE__ */ jsxs53("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
|
|
6915
7158
|
"Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
|
|
6916
|
-
/* @__PURE__ */
|
|
7159
|
+
/* @__PURE__ */ jsx58("code", { className: "fd-mono", children: "implemented" }),
|
|
6917
7160
|
" field, so this page cannot drift from what the apps actually do."
|
|
6918
7161
|
] })
|
|
6919
7162
|
] });
|
|
6920
7163
|
}
|
|
6921
7164
|
|
|
6922
7165
|
// src/components/platform/ComingSoon.tsx
|
|
6923
|
-
import * as
|
|
7166
|
+
import * as React32 from "react";
|
|
6924
7167
|
import { createPortal as createPortal7 } from "react-dom";
|
|
6925
|
-
import { Fragment as Fragment13, jsx as
|
|
7168
|
+
import { Fragment as Fragment13, jsx as jsx59, jsxs as jsxs54 } from "react/jsx-runtime";
|
|
6926
7169
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
6927
7170
|
function readBypassed() {
|
|
6928
7171
|
try {
|
|
@@ -6938,8 +7181,8 @@ function writeBypassed(list) {
|
|
|
6938
7181
|
}
|
|
6939
7182
|
}
|
|
6940
7183
|
function useBypass(key) {
|
|
6941
|
-
const [on, setOn] =
|
|
6942
|
-
|
|
7184
|
+
const [on, setOn] = React32.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
7185
|
+
React32.useEffect(() => {
|
|
6943
7186
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
6944
7187
|
}, [key]);
|
|
6945
7188
|
const set = (next) => {
|
|
@@ -6952,43 +7195,43 @@ function useBypass(key) {
|
|
|
6952
7195
|
return [on, set];
|
|
6953
7196
|
}
|
|
6954
7197
|
function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
|
|
6955
|
-
return /* @__PURE__ */
|
|
6956
|
-
/* @__PURE__ */
|
|
6957
|
-
/* @__PURE__ */
|
|
7198
|
+
return /* @__PURE__ */ jsxs54(Fragment13, { children: [
|
|
7199
|
+
/* @__PURE__ */ jsxs54("span", { className: "fd-soon-badge", children: [
|
|
7200
|
+
/* @__PURE__ */ jsx59("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
6958
7201
|
label
|
|
6959
7202
|
] }),
|
|
6960
|
-
detail ? /* @__PURE__ */
|
|
6961
|
-
backend ? /* @__PURE__ */
|
|
6962
|
-
/* @__PURE__ */
|
|
7203
|
+
detail ? /* @__PURE__ */ jsx59("span", { className: "fd-soon-detail", children: detail }) : null,
|
|
7204
|
+
backend ? /* @__PURE__ */ jsxs54("span", { className: "fd-soon-backend", children: [
|
|
7205
|
+
/* @__PURE__ */ jsx59("span", { className: "fd-overline", children: "Needs" }),
|
|
6963
7206
|
" ",
|
|
6964
7207
|
backend
|
|
6965
7208
|
] }) : null,
|
|
6966
|
-
eta || effort || onRoadmap ? /* @__PURE__ */
|
|
6967
|
-
eta ? /* @__PURE__ */
|
|
6968
|
-
/* @__PURE__ */
|
|
7209
|
+
eta || effort || onRoadmap ? /* @__PURE__ */ jsxs54("span", { className: "fd-soon-meta", children: [
|
|
7210
|
+
eta ? /* @__PURE__ */ jsxs54("span", { children: [
|
|
7211
|
+
/* @__PURE__ */ jsx59("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
|
|
6969
7212
|
" ",
|
|
6970
7213
|
eta
|
|
6971
7214
|
] }) : null,
|
|
6972
|
-
effort ? /* @__PURE__ */
|
|
6973
|
-
/* @__PURE__ */
|
|
7215
|
+
effort ? /* @__PURE__ */ jsxs54("span", { children: [
|
|
7216
|
+
/* @__PURE__ */ jsx59("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
|
|
6974
7217
|
" ",
|
|
6975
7218
|
effort
|
|
6976
7219
|
] }) : null,
|
|
6977
|
-
onRoadmap ? /* @__PURE__ */
|
|
7220
|
+
onRoadmap ? /* @__PURE__ */ jsxs54("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
6978
7221
|
"See the roadmap ",
|
|
6979
|
-
/* @__PURE__ */
|
|
7222
|
+
/* @__PURE__ */ jsx59("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
6980
7223
|
] }) : null
|
|
6981
7224
|
] }) : null,
|
|
6982
|
-
allowed ? /* @__PURE__ */
|
|
6983
|
-
/* @__PURE__ */
|
|
7225
|
+
allowed ? /* @__PURE__ */ jsxs54("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
|
|
7226
|
+
/* @__PURE__ */ jsx59("i", { className: "ph ph-eye", "aria-hidden": "true" }),
|
|
6984
7227
|
" View and use it anyway"
|
|
6985
7228
|
] }) : null
|
|
6986
7229
|
] });
|
|
6987
7230
|
}
|
|
6988
7231
|
function useHoverCard(open) {
|
|
6989
|
-
const anchor =
|
|
6990
|
-
const [pos, setPos] =
|
|
6991
|
-
|
|
7232
|
+
const anchor = React32.useRef(null);
|
|
7233
|
+
const [pos, setPos] = React32.useState(null);
|
|
7234
|
+
React32.useLayoutEffect(() => {
|
|
6992
7235
|
if (!open || !anchor.current) {
|
|
6993
7236
|
setPos(null);
|
|
6994
7237
|
return;
|
|
@@ -7040,9 +7283,9 @@ function ComingSoon({
|
|
|
7040
7283
|
const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
|
|
7041
7284
|
if (inline) {
|
|
7042
7285
|
if (allowed && bypassed) {
|
|
7043
|
-
return /* @__PURE__ */
|
|
7286
|
+
return /* @__PURE__ */ jsxs54("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
|
|
7044
7287
|
children,
|
|
7045
|
-
/* @__PURE__ */
|
|
7288
|
+
/* @__PURE__ */ jsx59(
|
|
7046
7289
|
"button",
|
|
7047
7290
|
{
|
|
7048
7291
|
type: "button",
|
|
@@ -7050,12 +7293,12 @@ function ComingSoon({
|
|
|
7050
7293
|
title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
|
|
7051
7294
|
onClick: () => setBypassed(false),
|
|
7052
7295
|
"aria-label": "Re-blur this unwired feature",
|
|
7053
|
-
children: /* @__PURE__ */
|
|
7296
|
+
children: /* @__PURE__ */ jsx59("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
7054
7297
|
}
|
|
7055
7298
|
)
|
|
7056
7299
|
] });
|
|
7057
7300
|
}
|
|
7058
|
-
return /* @__PURE__ */
|
|
7301
|
+
return /* @__PURE__ */ jsx59(
|
|
7059
7302
|
InlineSoon,
|
|
7060
7303
|
{
|
|
7061
7304
|
label,
|
|
@@ -7075,20 +7318,20 @@ function ComingSoon({
|
|
|
7075
7318
|
);
|
|
7076
7319
|
}
|
|
7077
7320
|
if (allowed && bypassed) {
|
|
7078
|
-
return /* @__PURE__ */
|
|
7079
|
-
/* @__PURE__ */
|
|
7080
|
-
/* @__PURE__ */
|
|
7081
|
-
/* @__PURE__ */
|
|
7321
|
+
return /* @__PURE__ */ jsxs54("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
|
|
7322
|
+
/* @__PURE__ */ jsxs54("div", { className: "fd-soon-bar", role: "status", children: [
|
|
7323
|
+
/* @__PURE__ */ jsxs54("span", { className: "fd-soon-badge", children: [
|
|
7324
|
+
/* @__PURE__ */ jsx59("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
7082
7325
|
"Unwired feature \u2014 you are using it anyway"
|
|
7083
7326
|
] }),
|
|
7084
|
-
/* @__PURE__ */
|
|
7085
|
-
/* @__PURE__ */
|
|
7086
|
-
onRoadmap ? /* @__PURE__ */
|
|
7327
|
+
/* @__PURE__ */ jsx59("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
|
|
7328
|
+
/* @__PURE__ */ jsxs54("span", { className: "fd-soon-bar-actions", children: [
|
|
7329
|
+
onRoadmap ? /* @__PURE__ */ jsxs54("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
7087
7330
|
"Roadmap ",
|
|
7088
|
-
/* @__PURE__ */
|
|
7331
|
+
/* @__PURE__ */ jsx59("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7089
7332
|
] }) : null,
|
|
7090
|
-
/* @__PURE__ */
|
|
7091
|
-
/* @__PURE__ */
|
|
7333
|
+
/* @__PURE__ */ jsxs54("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
|
|
7334
|
+
/* @__PURE__ */ jsx59("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
|
|
7092
7335
|
" Re-blur"
|
|
7093
7336
|
] })
|
|
7094
7337
|
] })
|
|
@@ -7096,10 +7339,10 @@ function ComingSoon({
|
|
|
7096
7339
|
children
|
|
7097
7340
|
] });
|
|
7098
7341
|
}
|
|
7099
|
-
return /* @__PURE__ */
|
|
7100
|
-
/* @__PURE__ */
|
|
7101
|
-
/* @__PURE__ */
|
|
7102
|
-
/* @__PURE__ */
|
|
7342
|
+
return /* @__PURE__ */ jsxs54("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
|
|
7343
|
+
/* @__PURE__ */ jsx59("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
7344
|
+
/* @__PURE__ */ jsx59("div", { className: "fd-soon-veil" }),
|
|
7345
|
+
/* @__PURE__ */ jsx59("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx59(
|
|
7103
7346
|
SoonCard,
|
|
7104
7347
|
{
|
|
7105
7348
|
label,
|
|
@@ -7115,9 +7358,9 @@ function ComingSoon({
|
|
|
7115
7358
|
] });
|
|
7116
7359
|
}
|
|
7117
7360
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
7118
|
-
const [open, setOpen] =
|
|
7361
|
+
const [open, setOpen] = React32.useState(false);
|
|
7119
7362
|
const [anchor, pos] = useHoverCard(open);
|
|
7120
|
-
const close =
|
|
7363
|
+
const close = React32.useRef(null);
|
|
7121
7364
|
const show = () => {
|
|
7122
7365
|
if (close.current) {
|
|
7123
7366
|
clearTimeout(close.current);
|
|
@@ -7133,10 +7376,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7133
7376
|
setOpen(false);
|
|
7134
7377
|
}, 140);
|
|
7135
7378
|
};
|
|
7136
|
-
|
|
7379
|
+
React32.useEffect(() => () => {
|
|
7137
7380
|
if (close.current) clearTimeout(close.current);
|
|
7138
7381
|
}, []);
|
|
7139
|
-
return /* @__PURE__ */
|
|
7382
|
+
return /* @__PURE__ */ jsxs54(
|
|
7140
7383
|
"span",
|
|
7141
7384
|
{
|
|
7142
7385
|
ref: anchor,
|
|
@@ -7147,8 +7390,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7147
7390
|
onBlur: hide,
|
|
7148
7391
|
...rest,
|
|
7149
7392
|
children: [
|
|
7150
|
-
/* @__PURE__ */
|
|
7151
|
-
/* @__PURE__ */
|
|
7393
|
+
/* @__PURE__ */ jsx59("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
7394
|
+
/* @__PURE__ */ jsx59(
|
|
7152
7395
|
"button",
|
|
7153
7396
|
{
|
|
7154
7397
|
type: "button",
|
|
@@ -7159,11 +7402,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7159
7402
|
onFocus: show,
|
|
7160
7403
|
onBlur: hide,
|
|
7161
7404
|
onClick: () => open ? setOpen(false) : show(),
|
|
7162
|
-
children: /* @__PURE__ */
|
|
7405
|
+
children: /* @__PURE__ */ jsx59("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
7163
7406
|
}
|
|
7164
7407
|
),
|
|
7165
7408
|
open && pos ? createPortal7(
|
|
7166
|
-
/* @__PURE__ */
|
|
7409
|
+
/* @__PURE__ */ jsx59(
|
|
7167
7410
|
"div",
|
|
7168
7411
|
{
|
|
7169
7412
|
className: "fd-soon-note fd-soon-hovercard",
|
|
@@ -7171,7 +7414,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7171
7414
|
style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width },
|
|
7172
7415
|
onMouseEnter: show,
|
|
7173
7416
|
onMouseLeave: hide,
|
|
7174
|
-
children: /* @__PURE__ */
|
|
7417
|
+
children: /* @__PURE__ */ jsx59(
|
|
7175
7418
|
SoonCard,
|
|
7176
7419
|
{
|
|
7177
7420
|
label,
|
|
@@ -7201,10 +7444,10 @@ function formatEta(iso2) {
|
|
|
7201
7444
|
var FormatEta = formatEta;
|
|
7202
7445
|
|
|
7203
7446
|
// src/components/platform/Gate.tsx
|
|
7204
|
-
import { jsx as
|
|
7447
|
+
import { jsx as jsx60, jsxs as jsxs55 } from "react/jsx-runtime";
|
|
7205
7448
|
function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
|
|
7206
7449
|
const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
|
|
7207
|
-
return /* @__PURE__ */
|
|
7450
|
+
return /* @__PURE__ */ jsxs55(
|
|
7208
7451
|
"div",
|
|
7209
7452
|
{
|
|
7210
7453
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -7220,14 +7463,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
7220
7463
|
},
|
|
7221
7464
|
...rest,
|
|
7222
7465
|
children: [
|
|
7223
|
-
/* @__PURE__ */
|
|
7224
|
-
/* @__PURE__ */
|
|
7225
|
-
/* @__PURE__ */
|
|
7466
|
+
/* @__PURE__ */ jsxs55("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
7467
|
+
/* @__PURE__ */ jsx60("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
7468
|
+
/* @__PURE__ */ jsx60("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
|
|
7226
7469
|
] }),
|
|
7227
|
-
/* @__PURE__ */
|
|
7228
|
-
need.length ? /* @__PURE__ */
|
|
7229
|
-
/* @__PURE__ */
|
|
7230
|
-
need.map((p) => /* @__PURE__ */
|
|
7470
|
+
/* @__PURE__ */ jsx60("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." }),
|
|
7471
|
+
need.length ? /* @__PURE__ */ jsxs55("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
|
|
7472
|
+
/* @__PURE__ */ jsx60("span", { className: "fd-overline fd-muted", children: "Requires" }),
|
|
7473
|
+
need.map((p) => /* @__PURE__ */ jsx60("code", { className: "fd-mono", style: {
|
|
7231
7474
|
fontSize: 11.5,
|
|
7232
7475
|
padding: "2px 7px",
|
|
7233
7476
|
borderRadius: 5,
|
|
@@ -7248,7 +7491,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, compact: compact3 =
|
|
|
7248
7491
|
if (ok) return children;
|
|
7249
7492
|
if (fallback !== void 0) return fallback;
|
|
7250
7493
|
if (silent) return null;
|
|
7251
|
-
return /* @__PURE__ */
|
|
7494
|
+
return /* @__PURE__ */ jsx60(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
|
|
7252
7495
|
}
|
|
7253
7496
|
function FeatureGate({
|
|
7254
7497
|
flag,
|
|
@@ -7269,7 +7512,7 @@ function FeatureGate({
|
|
|
7269
7512
|
if (!preview) return fallback;
|
|
7270
7513
|
const f = SessionKit.findFlag(flag) || {};
|
|
7271
7514
|
const missing = rt.missing || [];
|
|
7272
|
-
return /* @__PURE__ */
|
|
7515
|
+
return /* @__PURE__ */ jsx60(
|
|
7273
7516
|
ComingSoon,
|
|
7274
7517
|
{
|
|
7275
7518
|
label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
|
|
@@ -7290,25 +7533,25 @@ function FeatureGate({
|
|
|
7290
7533
|
function PermissionHint({ perm, children }) {
|
|
7291
7534
|
SessionKit.useSession();
|
|
7292
7535
|
if (SessionKit.can(perm)) return children;
|
|
7293
|
-
return /* @__PURE__ */
|
|
7536
|
+
return /* @__PURE__ */ jsx60(
|
|
7294
7537
|
"span",
|
|
7295
7538
|
{
|
|
7296
7539
|
title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
|
|
7297
7540
|
style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
|
|
7298
7541
|
"aria-disabled": "true",
|
|
7299
|
-
children: /* @__PURE__ */
|
|
7542
|
+
children: /* @__PURE__ */ jsx60("span", { style: { pointerEvents: "none" }, children })
|
|
7300
7543
|
}
|
|
7301
7544
|
);
|
|
7302
7545
|
}
|
|
7303
7546
|
|
|
7304
7547
|
// src/components/platform/ModeSwitch.tsx
|
|
7305
|
-
import * as
|
|
7306
|
-
import { Fragment as Fragment14, jsx as
|
|
7548
|
+
import * as React33 from "react";
|
|
7549
|
+
import { Fragment as Fragment14, jsx as jsx61, jsxs as jsxs56 } from "react/jsx-runtime";
|
|
7307
7550
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
7308
7551
|
const mode2 = useRuntimeMode();
|
|
7309
|
-
const [open, setOpen] =
|
|
7310
|
-
const ref =
|
|
7311
|
-
|
|
7552
|
+
const [open, setOpen] = React33.useState(false);
|
|
7553
|
+
const ref = React33.useRef(null);
|
|
7554
|
+
React33.useEffect(() => {
|
|
7312
7555
|
if (!open) return;
|
|
7313
7556
|
const away = (e) => {
|
|
7314
7557
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -7330,8 +7573,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7330
7573
|
RuntimeKit.setMode(next);
|
|
7331
7574
|
setOpen(false);
|
|
7332
7575
|
};
|
|
7333
|
-
return /* @__PURE__ */
|
|
7334
|
-
/* @__PURE__ */
|
|
7576
|
+
return /* @__PURE__ */ jsxs56("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
|
|
7577
|
+
/* @__PURE__ */ jsxs56(
|
|
7335
7578
|
"button",
|
|
7336
7579
|
{
|
|
7337
7580
|
type: "button",
|
|
@@ -7341,29 +7584,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7341
7584
|
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.",
|
|
7342
7585
|
className: "fd-mode-btn" + (test ? " is-test" : "") + (open ? " is-open" : ""),
|
|
7343
7586
|
children: [
|
|
7344
|
-
/* @__PURE__ */
|
|
7345
|
-
test && requestCount ? /* @__PURE__ */
|
|
7587
|
+
/* @__PURE__ */ jsx61("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
|
|
7588
|
+
test && requestCount ? /* @__PURE__ */ jsx61("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
|
|
7346
7589
|
]
|
|
7347
7590
|
}
|
|
7348
7591
|
),
|
|
7349
|
-
open ? /* @__PURE__ */
|
|
7350
|
-
/* @__PURE__ */
|
|
7351
|
-
/* @__PURE__ */
|
|
7352
|
-
/* @__PURE__ */
|
|
7592
|
+
open ? /* @__PURE__ */ jsxs56("span", { className: "fd-view-enter fd-mode-pop", children: [
|
|
7593
|
+
/* @__PURE__ */ jsxs56("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
7594
|
+
/* @__PURE__ */ jsxs56("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
|
|
7595
|
+
/* @__PURE__ */ jsx61("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
|
|
7353
7596
|
test ? "Test mode" : "Live mode"
|
|
7354
7597
|
] }),
|
|
7355
|
-
test ? /* @__PURE__ */
|
|
7598
|
+
test ? /* @__PURE__ */ jsxs56("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
7356
7599
|
requestCount,
|
|
7357
7600
|
" simulated request",
|
|
7358
7601
|
requestCount === 1 ? "" : "s"
|
|
7359
7602
|
] }) : null,
|
|
7360
|
-
/* @__PURE__ */
|
|
7361
|
-
test && onClearLog ? /* @__PURE__ */
|
|
7603
|
+
/* @__PURE__ */ jsx61("span", { style: { flex: 1 } }),
|
|
7604
|
+
test && onClearLog ? /* @__PURE__ */ jsx61("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
|
|
7362
7605
|
] }),
|
|
7363
|
-
/* @__PURE__ */
|
|
7364
|
-
/* @__PURE__ */
|
|
7365
|
-
/* @__PURE__ */
|
|
7366
|
-
/* @__PURE__ */
|
|
7606
|
+
/* @__PURE__ */ jsxs56("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
7607
|
+
/* @__PURE__ */ jsx61("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." }),
|
|
7608
|
+
/* @__PURE__ */ jsxs56("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
|
|
7609
|
+
/* @__PURE__ */ jsxs56("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
7367
7610
|
s.endpointsWired,
|
|
7368
7611
|
" endpoint",
|
|
7369
7612
|
s.endpointsWired === 1 ? "" : "s",
|
|
@@ -7373,58 +7616,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7373
7616
|
s.total,
|
|
7374
7617
|
" features complete"
|
|
7375
7618
|
] }),
|
|
7376
|
-
onOpenSpec ? /* @__PURE__ */
|
|
7377
|
-
/* @__PURE__ */
|
|
7378
|
-
/* @__PURE__ */
|
|
7619
|
+
onOpenSpec ? /* @__PURE__ */ jsxs56(Fragment14, { children: [
|
|
7620
|
+
/* @__PURE__ */ jsx61("span", { style: { flex: 1 } }),
|
|
7621
|
+
/* @__PURE__ */ jsxs56("button", { type: "button", className: "fd-soon-link", onClick: () => {
|
|
7379
7622
|
setOpen(false);
|
|
7380
7623
|
onOpenSpec();
|
|
7381
7624
|
}, children: [
|
|
7382
7625
|
"API spec ",
|
|
7383
|
-
/* @__PURE__ */
|
|
7626
|
+
/* @__PURE__ */ jsx61("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7384
7627
|
] })
|
|
7385
7628
|
] }) : null
|
|
7386
7629
|
] })
|
|
7387
7630
|
] }),
|
|
7388
|
-
/* @__PURE__ */
|
|
7389
|
-
/* @__PURE__ */
|
|
7390
|
-
/* @__PURE__ */
|
|
7391
|
-
/* @__PURE__ */
|
|
7392
|
-
/* @__PURE__ */
|
|
7393
|
-
/* @__PURE__ */
|
|
7631
|
+
/* @__PURE__ */ jsxs56("span", { className: "fd-mode-choice", children: [
|
|
7632
|
+
/* @__PURE__ */ jsxs56("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
|
|
7633
|
+
/* @__PURE__ */ jsx61("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
7634
|
+
/* @__PURE__ */ jsxs56("span", { className: "fd-mode-opt-text", children: [
|
|
7635
|
+
/* @__PURE__ */ jsx61("span", { className: "fd-mode-opt-title", children: "Live mode" }),
|
|
7636
|
+
/* @__PURE__ */ jsx61("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
|
|
7394
7637
|
] }),
|
|
7395
|
-
!test ? /* @__PURE__ */
|
|
7638
|
+
!test ? /* @__PURE__ */ jsx61("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
7396
7639
|
] }),
|
|
7397
|
-
/* @__PURE__ */
|
|
7398
|
-
/* @__PURE__ */
|
|
7399
|
-
/* @__PURE__ */
|
|
7400
|
-
/* @__PURE__ */
|
|
7401
|
-
/* @__PURE__ */
|
|
7640
|
+
/* @__PURE__ */ jsxs56("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
|
|
7641
|
+
/* @__PURE__ */ jsx61("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
7642
|
+
/* @__PURE__ */ jsxs56("span", { className: "fd-mode-opt-text", children: [
|
|
7643
|
+
/* @__PURE__ */ jsx61("span", { className: "fd-mode-opt-title", children: "Test mode" }),
|
|
7644
|
+
/* @__PURE__ */ jsx61("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
|
|
7402
7645
|
] }),
|
|
7403
|
-
test ? /* @__PURE__ */
|
|
7646
|
+
test ? /* @__PURE__ */ jsx61("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
7404
7647
|
] })
|
|
7405
7648
|
] }),
|
|
7406
|
-
test && renderLog ? /* @__PURE__ */
|
|
7649
|
+
test && renderLog ? /* @__PURE__ */ jsx61("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
|
|
7407
7650
|
] }) : null
|
|
7408
7651
|
] });
|
|
7409
7652
|
}
|
|
7410
7653
|
function TestModeBar({ onExit }) {
|
|
7411
7654
|
const mode2 = useRuntimeMode();
|
|
7412
7655
|
if (mode2 !== "test") return null;
|
|
7413
|
-
return /* @__PURE__ */
|
|
7414
|
-
/* @__PURE__ */
|
|
7415
|
-
/* @__PURE__ */
|
|
7656
|
+
return /* @__PURE__ */ jsxs56("div", { className: "fd-testbar", role: "status", children: [
|
|
7657
|
+
/* @__PURE__ */ jsxs56("span", { className: "fd-badge fd-badge-warning", children: [
|
|
7658
|
+
/* @__PURE__ */ jsx61("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
7416
7659
|
"Test mode"
|
|
7417
7660
|
] }),
|
|
7418
|
-
/* @__PURE__ */
|
|
7419
|
-
/* @__PURE__ */
|
|
7420
|
-
/* @__PURE__ */
|
|
7661
|
+
/* @__PURE__ */ jsx61("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
|
|
7662
|
+
/* @__PURE__ */ jsxs56("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
|
|
7663
|
+
/* @__PURE__ */ jsx61("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
7421
7664
|
" Back to live mode"
|
|
7422
7665
|
] })
|
|
7423
7666
|
] });
|
|
7424
7667
|
}
|
|
7425
7668
|
|
|
7426
7669
|
// src/components/planner/ChannelMeta.tsx
|
|
7427
|
-
import { jsx as
|
|
7670
|
+
import { jsx as jsx62, jsxs as jsxs57 } from "react/jsx-runtime";
|
|
7428
7671
|
var CHANNEL_WEIGHTS = {
|
|
7429
7672
|
"OOH": 50,
|
|
7430
7673
|
"DOOH": 50,
|
|
@@ -7477,9 +7720,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
7477
7720
|
const m = ChannelMeta(channel);
|
|
7478
7721
|
const wt = channelWeightOf(channel || "");
|
|
7479
7722
|
if (dot) {
|
|
7480
|
-
return /* @__PURE__ */
|
|
7723
|
+
return /* @__PURE__ */ jsx62("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
|
|
7481
7724
|
}
|
|
7482
|
-
return /* @__PURE__ */
|
|
7725
|
+
return /* @__PURE__ */ jsxs57(
|
|
7483
7726
|
"span",
|
|
7484
7727
|
{
|
|
7485
7728
|
className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
|
|
@@ -7487,16 +7730,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
7487
7730
|
style: { "--chan": m.color },
|
|
7488
7731
|
...rest,
|
|
7489
7732
|
children: [
|
|
7490
|
-
/* @__PURE__ */
|
|
7491
|
-
showLabel ? /* @__PURE__ */
|
|
7492
|
-
weight ? /* @__PURE__ */
|
|
7733
|
+
/* @__PURE__ */ jsx62("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
|
|
7734
|
+
showLabel ? /* @__PURE__ */ jsx62("span", { className: "fd-chan-label", children: m.label }) : null,
|
|
7735
|
+
weight ? /* @__PURE__ */ jsx62("span", { className: "fd-chan-weight", children: wt || 0 }) : null
|
|
7493
7736
|
]
|
|
7494
7737
|
}
|
|
7495
7738
|
);
|
|
7496
7739
|
}
|
|
7497
7740
|
|
|
7498
7741
|
// src/components/planner/SaturationDistribution.tsx
|
|
7499
|
-
import { jsx as
|
|
7742
|
+
import { jsx as jsx63, jsxs as jsxs58 } from "react/jsx-runtime";
|
|
7500
7743
|
var BANDS2 = [
|
|
7501
7744
|
{ key: "weak", label: "Weak", n: 1, range: "< 50" },
|
|
7502
7745
|
{ key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
|
|
@@ -7507,18 +7750,18 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
7507
7750
|
const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
|
|
7508
7751
|
const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
|
|
7509
7752
|
const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
|
|
7510
|
-
return /* @__PURE__ */
|
|
7511
|
-
/* @__PURE__ */
|
|
7753
|
+
return /* @__PURE__ */ jsxs58("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
7754
|
+
/* @__PURE__ */ jsx63("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
|
|
7512
7755
|
const mark = "var(--csi-" + g.n + "-mark)";
|
|
7513
7756
|
const active = selectedBand === g.key;
|
|
7514
|
-
return /* @__PURE__ */
|
|
7757
|
+
return /* @__PURE__ */ jsxs58(
|
|
7515
7758
|
"button",
|
|
7516
7759
|
{
|
|
7517
7760
|
type: "button",
|
|
7518
7761
|
onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
|
|
7519
7762
|
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)" },
|
|
7520
7763
|
children: [
|
|
7521
|
-
/* @__PURE__ */
|
|
7764
|
+
/* @__PURE__ */ jsx63("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx63("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => /* @__PURE__ */ jsx63(
|
|
7522
7765
|
"span",
|
|
7523
7766
|
{
|
|
7524
7767
|
title: c.name + " \xB7 " + c.crp,
|
|
@@ -7527,13 +7770,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
7527
7770
|
},
|
|
7528
7771
|
c.name
|
|
7529
7772
|
)) }),
|
|
7530
|
-
/* @__PURE__ */
|
|
7531
|
-
/* @__PURE__ */
|
|
7532
|
-
/* @__PURE__ */
|
|
7773
|
+
/* @__PURE__ */ jsxs58("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
|
|
7774
|
+
/* @__PURE__ */ jsx63("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
|
|
7775
|
+
/* @__PURE__ */ jsx63("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx63("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
|
|
7533
7776
|
] }),
|
|
7534
|
-
/* @__PURE__ */
|
|
7535
|
-
/* @__PURE__ */
|
|
7536
|
-
/* @__PURE__ */
|
|
7777
|
+
/* @__PURE__ */ jsxs58("span", { className: "fd-stack", style: { gap: 1 }, children: [
|
|
7778
|
+
/* @__PURE__ */ jsx63("span", { className: "fd-label-lg", children: g.label }),
|
|
7779
|
+
/* @__PURE__ */ jsxs58("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
|
|
7537
7780
|
"CRP ",
|
|
7538
7781
|
g.range
|
|
7539
7782
|
] })
|
|
@@ -7543,10 +7786,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
7543
7786
|
g.key
|
|
7544
7787
|
);
|
|
7545
7788
|
}) }),
|
|
7546
|
-
floorBand ? /* @__PURE__ */
|
|
7547
|
-
/* @__PURE__ */
|
|
7548
|
-
/* @__PURE__ */
|
|
7549
|
-
/* @__PURE__ */
|
|
7789
|
+
floorBand ? /* @__PURE__ */ jsxs58("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: [
|
|
7790
|
+
/* @__PURE__ */ jsx63("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx63("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
|
|
7791
|
+
/* @__PURE__ */ jsxs58("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
|
|
7792
|
+
/* @__PURE__ */ jsxs58("strong", { style: { color: "var(--text)" }, children: [
|
|
7550
7793
|
"Plan floor ",
|
|
7551
7794
|
floorScore
|
|
7552
7795
|
] }),
|
|
@@ -7557,21 +7800,21 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
7557
7800
|
}
|
|
7558
7801
|
|
|
7559
7802
|
// src/components/planner/MixGap.tsx
|
|
7560
|
-
import * as
|
|
7561
|
-
import { Fragment as Fragment15, jsx as
|
|
7803
|
+
import * as React34 from "react";
|
|
7804
|
+
import { Fragment as Fragment15, jsx as jsx64, jsxs as jsxs59 } from "react/jsx-runtime";
|
|
7562
7805
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
7563
7806
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
7564
|
-
const [hover, setHover] =
|
|
7807
|
+
const [hover, setHover] = React34.useState(null);
|
|
7565
7808
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
7566
7809
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
7567
|
-
return /* @__PURE__ */
|
|
7568
|
-
/* @__PURE__ */
|
|
7569
|
-
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */
|
|
7570
|
-
/* @__PURE__ */
|
|
7810
|
+
return /* @__PURE__ */ jsxs59("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
|
|
7811
|
+
/* @__PURE__ */ jsxs59("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
|
|
7812
|
+
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs59("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
7813
|
+
/* @__PURE__ */ jsx64("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
|
|
7571
7814
|
l
|
|
7572
7815
|
] }, l)),
|
|
7573
|
-
/* @__PURE__ */
|
|
7574
|
-
/* @__PURE__ */
|
|
7816
|
+
/* @__PURE__ */ jsxs59("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
7817
|
+
/* @__PURE__ */ jsx64("span", { style: { width: 3, height: 14, background: "var(--n-500)" } }),
|
|
7575
7818
|
"Target"
|
|
7576
7819
|
] })
|
|
7577
7820
|
] }),
|
|
@@ -7579,7 +7822,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
7579
7822
|
const gap = r.realized - r.target;
|
|
7580
7823
|
const tone = toneOf(gap);
|
|
7581
7824
|
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 : "");
|
|
7582
|
-
return /* @__PURE__ */
|
|
7825
|
+
return /* @__PURE__ */ jsxs59(
|
|
7583
7826
|
"div",
|
|
7584
7827
|
{
|
|
7585
7828
|
className: "fd-row",
|
|
@@ -7587,15 +7830,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
7587
7830
|
onMouseEnter: () => setHover(r.channel),
|
|
7588
7831
|
onMouseLeave: () => setHover(null),
|
|
7589
7832
|
children: [
|
|
7590
|
-
/* @__PURE__ */
|
|
7591
|
-
/* @__PURE__ */
|
|
7592
|
-
/* @__PURE__ */
|
|
7593
|
-
/* @__PURE__ */
|
|
7594
|
-
/* @__PURE__ */
|
|
7833
|
+
/* @__PURE__ */ jsx64("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx64(ChannelTag, { channel: r.channel, size: "sm" }) }),
|
|
7834
|
+
/* @__PURE__ */ jsx64("span", { style: { position: "relative", flex: 1, height: 22, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx64("span", { className: "fd-skel", style: { position: "absolute", inset: "5px 0", borderRadius: 3 } }) : /* @__PURE__ */ jsxs59(Fragment15, { children: [
|
|
7835
|
+
/* @__PURE__ */ jsx64("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)" } }),
|
|
7836
|
+
/* @__PURE__ */ jsx64("span", { style: { position: "absolute", left: r.target / max * 100 + "%", top: 0, width: 3, height: 22, background: "var(--n-500)", borderRadius: 1 } }),
|
|
7837
|
+
/* @__PURE__ */ jsxs59("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: [
|
|
7595
7838
|
r.realized,
|
|
7596
7839
|
"%"
|
|
7597
7840
|
] }),
|
|
7598
|
-
hover === r.channel ? /* @__PURE__ */
|
|
7841
|
+
hover === r.channel ? /* @__PURE__ */ jsx64("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
|
|
7599
7842
|
] }) })
|
|
7600
7843
|
]
|
|
7601
7844
|
},
|
|
@@ -7606,7 +7849,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
7606
7849
|
}
|
|
7607
7850
|
|
|
7608
7851
|
// src/components/planner/ChannelContribution.tsx
|
|
7609
|
-
import { jsx as
|
|
7852
|
+
import { jsx as jsx65, jsxs as jsxs60 } from "react/jsx-runtime";
|
|
7610
7853
|
var money = (n) => "$" + Math.round(n).toLocaleString();
|
|
7611
7854
|
function ChannelContribution({
|
|
7612
7855
|
channels = [],
|
|
@@ -7622,9 +7865,9 @@ function ChannelContribution({
|
|
|
7622
7865
|
const grand = total !== void 0 ? total : base + bonus;
|
|
7623
7866
|
const pct = (v) => grand ? v / grand * 100 : 0;
|
|
7624
7867
|
const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
|
|
7625
|
-
return /* @__PURE__ */
|
|
7626
|
-
loading ? /* @__PURE__ */
|
|
7627
|
-
channels.map((c) => /* @__PURE__ */
|
|
7868
|
+
return /* @__PURE__ */ jsxs60("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
7869
|
+
loading ? /* @__PURE__ */ jsx65("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs60("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
|
|
7870
|
+
channels.map((c) => /* @__PURE__ */ jsx65(
|
|
7628
7871
|
"span",
|
|
7629
7872
|
{
|
|
7630
7873
|
title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
|
|
@@ -7633,7 +7876,7 @@ function ChannelContribution({
|
|
|
7633
7876
|
},
|
|
7634
7877
|
c.name
|
|
7635
7878
|
)),
|
|
7636
|
-
bonus > 0 ? /* @__PURE__ */
|
|
7879
|
+
bonus > 0 ? /* @__PURE__ */ jsx65(
|
|
7637
7880
|
"span",
|
|
7638
7881
|
{
|
|
7639
7882
|
title: "Surround-sound bonus +" + bonusPct + "%",
|
|
@@ -7642,18 +7885,18 @@ function ChannelContribution({
|
|
|
7642
7885
|
}
|
|
7643
7886
|
) : null
|
|
7644
7887
|
] }),
|
|
7645
|
-
showTable ? /* @__PURE__ */
|
|
7646
|
-
/* @__PURE__ */
|
|
7647
|
-
/* @__PURE__ */
|
|
7648
|
-
/* @__PURE__ */
|
|
7649
|
-
/* @__PURE__ */
|
|
7650
|
-
/* @__PURE__ */
|
|
7651
|
-
/* @__PURE__ */
|
|
7888
|
+
showTable ? /* @__PURE__ */ jsxs60("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
|
|
7889
|
+
/* @__PURE__ */ jsx65("thead", { children: /* @__PURE__ */ jsxs60("tr", { children: [
|
|
7890
|
+
/* @__PURE__ */ jsx65("th", { style: { width: "34%" }, children: "Channel" }),
|
|
7891
|
+
/* @__PURE__ */ jsx65("th", { style: { width: "16%" }, children: "Weight" }),
|
|
7892
|
+
/* @__PURE__ */ jsx65("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
|
|
7893
|
+
/* @__PURE__ */ jsx65("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
|
|
7894
|
+
/* @__PURE__ */ jsx65("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
|
|
7652
7895
|
] }) }),
|
|
7653
|
-
/* @__PURE__ */
|
|
7654
|
-
channels.map((c) => /* @__PURE__ */
|
|
7655
|
-
/* @__PURE__ */
|
|
7656
|
-
/* @__PURE__ */
|
|
7896
|
+
/* @__PURE__ */ jsxs60("tbody", { children: [
|
|
7897
|
+
channels.map((c) => /* @__PURE__ */ jsxs60("tr", { children: [
|
|
7898
|
+
/* @__PURE__ */ jsx65("td", { children: /* @__PURE__ */ jsx65(ChannelTag, { channel: c.name, size: "sm" }) }),
|
|
7899
|
+
/* @__PURE__ */ jsx65("td", { children: /* @__PURE__ */ jsx65(
|
|
7657
7900
|
"span",
|
|
7658
7901
|
{
|
|
7659
7902
|
className: "fd-badge fd-badge-neutral",
|
|
@@ -7662,38 +7905,38 @@ function ChannelContribution({
|
|
|
7662
7905
|
children: "weight " + (channelWeightOf(c.name) || 0)
|
|
7663
7906
|
}
|
|
7664
7907
|
) }),
|
|
7665
|
-
/* @__PURE__ */
|
|
7666
|
-
/* @__PURE__ */
|
|
7667
|
-
/* @__PURE__ */
|
|
7908
|
+
/* @__PURE__ */ jsx65("td", { className: "is-num", children: c.spend }),
|
|
7909
|
+
/* @__PURE__ */ jsx65("td", { className: "is-num", children: c.crp.toFixed(1) }),
|
|
7910
|
+
/* @__PURE__ */ jsxs60("td", { className: "is-num", children: [
|
|
7668
7911
|
pct(c.crp).toFixed(0),
|
|
7669
7912
|
"%"
|
|
7670
7913
|
] })
|
|
7671
7914
|
] }, c.name)),
|
|
7672
|
-
bonus > 0 ? /* @__PURE__ */
|
|
7673
|
-
/* @__PURE__ */
|
|
7674
|
-
/* @__PURE__ */
|
|
7915
|
+
bonus > 0 ? /* @__PURE__ */ jsxs60("tr", { children: [
|
|
7916
|
+
/* @__PURE__ */ jsx65("td", { children: /* @__PURE__ */ jsxs60("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
|
|
7917
|
+
/* @__PURE__ */ jsx65("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" } }),
|
|
7675
7918
|
"Surround-sound bonus"
|
|
7676
7919
|
] }) }),
|
|
7677
|
-
/* @__PURE__ */
|
|
7920
|
+
/* @__PURE__ */ jsx65("td", { children: /* @__PURE__ */ jsxs60("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
|
|
7678
7921
|
"+",
|
|
7679
7922
|
bonusPct,
|
|
7680
7923
|
"% of +",
|
|
7681
7924
|
bonusMax,
|
|
7682
7925
|
"%"
|
|
7683
7926
|
] }) }),
|
|
7684
|
-
/* @__PURE__ */
|
|
7685
|
-
/* @__PURE__ */
|
|
7686
|
-
/* @__PURE__ */
|
|
7927
|
+
/* @__PURE__ */ jsx65("td", { className: "is-num fd-muted", children: "\u2014" }),
|
|
7928
|
+
/* @__PURE__ */ jsx65("td", { className: "is-num", children: bonus.toFixed(1) }),
|
|
7929
|
+
/* @__PURE__ */ jsxs60("td", { className: "is-num", children: [
|
|
7687
7930
|
pct(bonus).toFixed(0),
|
|
7688
7931
|
"%"
|
|
7689
7932
|
] })
|
|
7690
7933
|
] }) : null,
|
|
7691
|
-
/* @__PURE__ */
|
|
7692
|
-
/* @__PURE__ */
|
|
7693
|
-
/* @__PURE__ */
|
|
7694
|
-
/* @__PURE__ */
|
|
7695
|
-
/* @__PURE__ */
|
|
7696
|
-
/* @__PURE__ */
|
|
7934
|
+
/* @__PURE__ */ jsxs60("tr", { style: { background: "var(--surface-2)" }, children: [
|
|
7935
|
+
/* @__PURE__ */ jsx65("td", { style: { fontWeight: 700 }, children: "Campus total" }),
|
|
7936
|
+
/* @__PURE__ */ jsx65("td", {}),
|
|
7937
|
+
/* @__PURE__ */ jsx65("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
|
|
7938
|
+
/* @__PURE__ */ jsx65("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
|
|
7939
|
+
/* @__PURE__ */ jsx65("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
|
|
7697
7940
|
] })
|
|
7698
7941
|
] })
|
|
7699
7942
|
] }) : null
|
|
@@ -7701,8 +7944,8 @@ function ChannelContribution({
|
|
|
7701
7944
|
}
|
|
7702
7945
|
|
|
7703
7946
|
// src/components/planner/BudgetReallocator.tsx
|
|
7704
|
-
import * as
|
|
7705
|
-
import { Fragment as Fragment16, jsx as
|
|
7947
|
+
import * as React35 from "react";
|
|
7948
|
+
import { Fragment as Fragment16, jsx as jsx66, jsxs as jsxs61 } from "react/jsx-runtime";
|
|
7706
7949
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
7707
7950
|
function BudgetReallocator({
|
|
7708
7951
|
campus,
|
|
@@ -7717,8 +7960,8 @@ function BudgetReallocator({
|
|
|
7717
7960
|
onCancel,
|
|
7718
7961
|
className = ""
|
|
7719
7962
|
}) {
|
|
7720
|
-
const [draft, setDraft] =
|
|
7721
|
-
|
|
7963
|
+
const [draft, setDraft] = React35.useState(spend);
|
|
7964
|
+
React35.useEffect(() => setDraft(spend), [spend]);
|
|
7722
7965
|
const dirty = draft !== spend;
|
|
7723
7966
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
7724
7967
|
const nextBand = bandFor(nextCrp);
|
|
@@ -7733,24 +7976,24 @@ function BudgetReallocator({
|
|
|
7733
7976
|
setDraft(spend);
|
|
7734
7977
|
if (onCancel) onCancel();
|
|
7735
7978
|
};
|
|
7736
|
-
return /* @__PURE__ */
|
|
7979
|
+
return /* @__PURE__ */ jsxs61(
|
|
7737
7980
|
"div",
|
|
7738
7981
|
{
|
|
7739
7982
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
7740
7983
|
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)" },
|
|
7741
7984
|
children: [
|
|
7742
|
-
/* @__PURE__ */
|
|
7743
|
-
/* @__PURE__ */
|
|
7744
|
-
/* @__PURE__ */
|
|
7745
|
-
dirty ? /* @__PURE__ */
|
|
7746
|
-
/* @__PURE__ */
|
|
7747
|
-
/* @__PURE__ */
|
|
7985
|
+
/* @__PURE__ */ jsxs61("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
7986
|
+
/* @__PURE__ */ jsx66("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
|
|
7987
|
+
/* @__PURE__ */ jsx66(CsiBadge, { band: nowBand, crp, size: "medium" }),
|
|
7988
|
+
dirty ? /* @__PURE__ */ jsxs61(Fragment16, { children: [
|
|
7989
|
+
/* @__PURE__ */ jsx66("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
|
|
7990
|
+
/* @__PURE__ */ jsx66(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
|
|
7748
7991
|
] }) : null
|
|
7749
7992
|
] }),
|
|
7750
|
-
/* @__PURE__ */
|
|
7751
|
-
/* @__PURE__ */
|
|
7752
|
-
dirty ? /* @__PURE__ */
|
|
7753
|
-
/* @__PURE__ */
|
|
7993
|
+
/* @__PURE__ */ jsxs61("div", { className: "fd-slider", children: [
|
|
7994
|
+
/* @__PURE__ */ jsx66("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
7995
|
+
dirty ? /* @__PURE__ */ jsx66("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,
|
|
7996
|
+
/* @__PURE__ */ jsx66(
|
|
7754
7997
|
"input",
|
|
7755
7998
|
{
|
|
7756
7999
|
type: "range",
|
|
@@ -7766,13 +8009,13 @@ function BudgetReallocator({
|
|
|
7766
8009
|
}
|
|
7767
8010
|
)
|
|
7768
8011
|
] }),
|
|
7769
|
-
/* @__PURE__ */
|
|
7770
|
-
/* @__PURE__ */
|
|
7771
|
-
/* @__PURE__ */
|
|
7772
|
-
/* @__PURE__ */
|
|
8012
|
+
/* @__PURE__ */ jsxs61("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
8013
|
+
/* @__PURE__ */ jsxs61("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
|
|
8014
|
+
/* @__PURE__ */ jsx66("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
|
|
8015
|
+
/* @__PURE__ */ jsx66("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
|
|
7773
8016
|
] }),
|
|
7774
|
-
/* @__PURE__ */
|
|
7775
|
-
/* @__PURE__ */
|
|
8017
|
+
/* @__PURE__ */ jsx66("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
|
|
8018
|
+
/* @__PURE__ */ jsx66(
|
|
7776
8019
|
"button",
|
|
7777
8020
|
{
|
|
7778
8021
|
type: "button",
|
|
@@ -7791,7 +8034,7 @@ function BudgetReallocator({
|
|
|
7791
8034
|
}
|
|
7792
8035
|
|
|
7793
8036
|
// src/components/planner/SurroundSound.tsx
|
|
7794
|
-
import { jsx as
|
|
8037
|
+
import { jsx as jsx67, jsxs as jsxs62 } from "react/jsx-runtime";
|
|
7795
8038
|
var CATEGORIES = [
|
|
7796
8039
|
{ key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
|
|
7797
8040
|
{ key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
|
|
@@ -7803,26 +8046,26 @@ var CATEGORIES = [
|
|
|
7803
8046
|
function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
|
|
7804
8047
|
const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
|
|
7805
8048
|
const single = present.length <= 2;
|
|
7806
|
-
return /* @__PURE__ */
|
|
7807
|
-
/* @__PURE__ */
|
|
8049
|
+
return /* @__PURE__ */ jsxs62("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
|
|
8050
|
+
/* @__PURE__ */ jsx67("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
|
|
7808
8051
|
const on = present.includes(c.key);
|
|
7809
|
-
return /* @__PURE__ */
|
|
8052
|
+
return /* @__PURE__ */ jsxs62(
|
|
7810
8053
|
"span",
|
|
7811
8054
|
{
|
|
7812
8055
|
title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
|
|
7813
8056
|
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)" },
|
|
7814
8057
|
children: [
|
|
7815
|
-
/* @__PURE__ */
|
|
7816
|
-
/* @__PURE__ */
|
|
8058
|
+
/* @__PURE__ */ jsx67("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
8059
|
+
/* @__PURE__ */ jsx67("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
|
|
7817
8060
|
]
|
|
7818
8061
|
},
|
|
7819
8062
|
c.key
|
|
7820
8063
|
);
|
|
7821
8064
|
}) }),
|
|
7822
|
-
/* @__PURE__ */
|
|
7823
|
-
/* @__PURE__ */
|
|
7824
|
-
/* @__PURE__ */
|
|
7825
|
-
/* @__PURE__ */
|
|
8065
|
+
/* @__PURE__ */ jsxs62("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
8066
|
+
/* @__PURE__ */ jsxs62("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
8067
|
+
/* @__PURE__ */ jsx67("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
|
|
8068
|
+
/* @__PURE__ */ jsxs62("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
|
|
7826
8069
|
"+",
|
|
7827
8070
|
bonusPct,
|
|
7828
8071
|
"% of +",
|
|
@@ -7830,8 +8073,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
7830
8073
|
"%"
|
|
7831
8074
|
] })
|
|
7832
8075
|
] }),
|
|
7833
|
-
/* @__PURE__ */
|
|
7834
|
-
/* @__PURE__ */
|
|
8076
|
+
/* @__PURE__ */ jsx67("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx67("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
|
|
8077
|
+
/* @__PURE__ */ jsxs62("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
|
|
7835
8078
|
present.length,
|
|
7836
8079
|
" of 6 channel categories present.",
|
|
7837
8080
|
" ",
|
|
@@ -7843,10 +8086,10 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
7843
8086
|
}
|
|
7844
8087
|
|
|
7845
8088
|
// src/components/chat/AgentChatPanel.tsx
|
|
7846
|
-
import * as
|
|
8089
|
+
import * as React41 from "react";
|
|
7847
8090
|
|
|
7848
8091
|
// src/components/chat/chatEngine.ts
|
|
7849
|
-
import * as
|
|
8092
|
+
import * as React36 from "react";
|
|
7850
8093
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
7851
8094
|
var JOB_PENDING = ["queued", "running"];
|
|
7852
8095
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -7900,22 +8143,22 @@ function useChatEngine(opts) {
|
|
|
7900
8143
|
onClear,
|
|
7901
8144
|
onFeedback
|
|
7902
8145
|
} = opts || {};
|
|
7903
|
-
const [status, setStatus] =
|
|
7904
|
-
const [threadId, setThreadId] =
|
|
7905
|
-
const [messages, setMessages] =
|
|
7906
|
-
const [queue, setQueue] =
|
|
7907
|
-
const [fatal, setFatal] =
|
|
7908
|
-
const [busy, setBusy] =
|
|
7909
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
7910
|
-
const listRef =
|
|
7911
|
-
const queueRef =
|
|
7912
|
-
const busyRef =
|
|
7913
|
-
const stoppedRef =
|
|
7914
|
-
const abortRef =
|
|
7915
|
-
const serverCount =
|
|
7916
|
-
const threadRef =
|
|
7917
|
-
const mounted =
|
|
7918
|
-
|
|
8146
|
+
const [status, setStatus] = React36.useState("idle");
|
|
8147
|
+
const [threadId, setThreadId] = React36.useState(null);
|
|
8148
|
+
const [messages, setMessages] = React36.useState([]);
|
|
8149
|
+
const [queue, setQueue] = React36.useState([]);
|
|
8150
|
+
const [fatal, setFatal] = React36.useState(null);
|
|
8151
|
+
const [busy, setBusy] = React36.useState(false);
|
|
8152
|
+
const [turnStartedAt, setTurnStartedAt] = React36.useState(null);
|
|
8153
|
+
const listRef = React36.useRef([]);
|
|
8154
|
+
const queueRef = React36.useRef([]);
|
|
8155
|
+
const busyRef = React36.useRef(false);
|
|
8156
|
+
const stoppedRef = React36.useRef(false);
|
|
8157
|
+
const abortRef = React36.useRef(null);
|
|
8158
|
+
const serverCount = React36.useRef(0);
|
|
8159
|
+
const threadRef = React36.useRef(null);
|
|
8160
|
+
const mounted = React36.useRef(true);
|
|
8161
|
+
React36.useEffect(() => {
|
|
7919
8162
|
mounted.current = true;
|
|
7920
8163
|
return () => {
|
|
7921
8164
|
mounted.current = false;
|
|
@@ -7937,14 +8180,14 @@ function useChatEngine(opts) {
|
|
|
7937
8180
|
}
|
|
7938
8181
|
return false;
|
|
7939
8182
|
};
|
|
7940
|
-
const loadThread =
|
|
8183
|
+
const loadThread = React36.useCallback(async (id) => {
|
|
7941
8184
|
const data = await apiAdapter.getThread(id);
|
|
7942
8185
|
const list = [...data && data.messages || []];
|
|
7943
8186
|
serverCount.current = list.length;
|
|
7944
8187
|
commit(list);
|
|
7945
8188
|
return list;
|
|
7946
8189
|
}, [apiAdapter]);
|
|
7947
|
-
|
|
8190
|
+
React36.useEffect(() => {
|
|
7948
8191
|
if (!apiAdapter) {
|
|
7949
8192
|
setStatus("idle");
|
|
7950
8193
|
setFatal(null);
|
|
@@ -8157,7 +8400,7 @@ function useChatEngine(opts) {
|
|
|
8157
8400
|
await dispatchTurn(turn);
|
|
8158
8401
|
}
|
|
8159
8402
|
}
|
|
8160
|
-
const send =
|
|
8403
|
+
const send = React36.useCallback((text, attachments) => {
|
|
8161
8404
|
const body = (text || "").trim();
|
|
8162
8405
|
if (!body && !(attachments && attachments.length)) return;
|
|
8163
8406
|
if (status === "disconnected") return;
|
|
@@ -8167,7 +8410,7 @@ function useChatEngine(opts) {
|
|
|
8167
8410
|
stoppedRef.current = false;
|
|
8168
8411
|
drain();
|
|
8169
8412
|
}, [status]);
|
|
8170
|
-
const stop =
|
|
8413
|
+
const stop = React36.useCallback(() => {
|
|
8171
8414
|
stoppedRef.current = true;
|
|
8172
8415
|
const ac = abortRef.current;
|
|
8173
8416
|
if (ac) {
|
|
@@ -8186,11 +8429,11 @@ function useChatEngine(opts) {
|
|
|
8186
8429
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
8187
8430
|
}
|
|
8188
8431
|
}, [apiAdapter]);
|
|
8189
|
-
const removeQueued =
|
|
8432
|
+
const removeQueued = React36.useCallback((id) => {
|
|
8190
8433
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
8191
8434
|
setQueue(queueRef.current.slice());
|
|
8192
8435
|
}, []);
|
|
8193
|
-
const retry =
|
|
8436
|
+
const retry = React36.useCallback(() => {
|
|
8194
8437
|
const list = listRef.current;
|
|
8195
8438
|
let at = -1;
|
|
8196
8439
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -8206,19 +8449,19 @@ function useChatEngine(opts) {
|
|
|
8206
8449
|
setQueue(queueRef.current.slice());
|
|
8207
8450
|
drain();
|
|
8208
8451
|
}, []);
|
|
8209
|
-
const clear =
|
|
8452
|
+
const clear = React36.useCallback(() => {
|
|
8210
8453
|
commit([]);
|
|
8211
8454
|
serverCount.current = 0;
|
|
8212
8455
|
queueRef.current = [];
|
|
8213
8456
|
setQueue([]);
|
|
8214
8457
|
onClear && onClear();
|
|
8215
8458
|
}, [onClear]);
|
|
8216
|
-
const setFeedback =
|
|
8459
|
+
const setFeedback = React36.useCallback((id, value) => {
|
|
8217
8460
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
8218
8461
|
const msg = listRef.current.find((m) => m.id === id);
|
|
8219
8462
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
8220
8463
|
}, [onFeedback]);
|
|
8221
|
-
const reload =
|
|
8464
|
+
const reload = React36.useCallback(async () => {
|
|
8222
8465
|
if (!threadRef.current) return;
|
|
8223
8466
|
setStatus("loading");
|
|
8224
8467
|
try {
|
|
@@ -8256,11 +8499,11 @@ var ChatKit = {
|
|
|
8256
8499
|
};
|
|
8257
8500
|
|
|
8258
8501
|
// src/components/chat/ChatTranscript.tsx
|
|
8259
|
-
import * as
|
|
8502
|
+
import * as React38 from "react";
|
|
8260
8503
|
|
|
8261
8504
|
// src/components/chat/ChatTurn.tsx
|
|
8262
|
-
import * as
|
|
8263
|
-
import { jsx as
|
|
8505
|
+
import * as React37 from "react";
|
|
8506
|
+
import { jsx as jsx68, jsxs as jsxs63 } from "react/jsx-runtime";
|
|
8264
8507
|
function JsonView({ value }) {
|
|
8265
8508
|
let text;
|
|
8266
8509
|
try {
|
|
@@ -8268,67 +8511,67 @@ function JsonView({ value }) {
|
|
|
8268
8511
|
} catch (e) {
|
|
8269
8512
|
text = String(value);
|
|
8270
8513
|
}
|
|
8271
|
-
return /* @__PURE__ */
|
|
8514
|
+
return /* @__PURE__ */ jsx68(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
|
|
8272
8515
|
}
|
|
8273
8516
|
function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
8274
8517
|
if (!packet) return null;
|
|
8275
8518
|
const s = schema || {};
|
|
8276
8519
|
const invalid = packet.valid === false;
|
|
8277
8520
|
const title = s.heading || packet.type;
|
|
8278
|
-
return /* @__PURE__ */
|
|
8279
|
-
/* @__PURE__ */
|
|
8280
|
-
/* @__PURE__ */
|
|
8281
|
-
/* @__PURE__ */
|
|
8282
|
-
packet.repaired ? /* @__PURE__ */
|
|
8283
|
-
invalid ? /* @__PURE__ */
|
|
8521
|
+
return /* @__PURE__ */ jsxs63("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
|
|
8522
|
+
/* @__PURE__ */ jsxs63("header", { className: "fdc-packet-head", children: [
|
|
8523
|
+
/* @__PURE__ */ jsx68("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
|
|
8524
|
+
/* @__PURE__ */ jsx68("span", { className: "fdc-packet-title", children: title }),
|
|
8525
|
+
packet.repaired ? /* @__PURE__ */ jsx68("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
|
|
8526
|
+
invalid ? /* @__PURE__ */ jsx68("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
|
|
8284
8527
|
] }),
|
|
8285
|
-
invalid ? /* @__PURE__ */
|
|
8286
|
-
/* @__PURE__ */
|
|
8287
|
-
/* @__PURE__ */
|
|
8288
|
-
] }) : /* @__PURE__ */
|
|
8289
|
-
!invalid && onApply ? /* @__PURE__ */
|
|
8290
|
-
packet.repaired ? /* @__PURE__ */
|
|
8291
|
-
/* @__PURE__ */
|
|
8292
|
-
/* @__PURE__ */
|
|
8528
|
+
invalid ? /* @__PURE__ */ jsxs63("div", { className: "fdc-packet-alert", role: "alert", children: [
|
|
8529
|
+
/* @__PURE__ */ jsx68("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
8530
|
+
/* @__PURE__ */ jsx68("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
|
|
8531
|
+
] }) : /* @__PURE__ */ jsx68("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx68(JsonView, { value: packet.payload }) }),
|
|
8532
|
+
!invalid && onApply ? /* @__PURE__ */ jsxs63("footer", { className: "fdc-packet-foot", children: [
|
|
8533
|
+
packet.repaired ? /* @__PURE__ */ jsx68("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx68("span", {}),
|
|
8534
|
+
/* @__PURE__ */ jsxs63("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
|
|
8535
|
+
/* @__PURE__ */ jsx68("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
|
|
8293
8536
|
applied ? "Applied" : s.applyLabel || "Apply"
|
|
8294
8537
|
] })
|
|
8295
8538
|
] }) : null
|
|
8296
8539
|
] });
|
|
8297
8540
|
}
|
|
8298
8541
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
8299
|
-
const [open, setOpen] =
|
|
8542
|
+
const [open, setOpen] = React37.useState(defaultOpen);
|
|
8300
8543
|
if (!text) return null;
|
|
8301
|
-
return /* @__PURE__ */
|
|
8302
|
-
/* @__PURE__ */
|
|
8303
|
-
/* @__PURE__ */
|
|
8304
|
-
/* @__PURE__ */
|
|
8305
|
-
streaming ? /* @__PURE__ */
|
|
8306
|
-
/* @__PURE__ */
|
|
8307
|
-
/* @__PURE__ */
|
|
8308
|
-
/* @__PURE__ */
|
|
8544
|
+
return /* @__PURE__ */ jsxs63("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
|
|
8545
|
+
/* @__PURE__ */ jsxs63("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
8546
|
+
/* @__PURE__ */ jsx68("i", { className: "ph ph-brain", "aria-hidden": "true" }),
|
|
8547
|
+
/* @__PURE__ */ jsx68("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
|
|
8548
|
+
streaming ? /* @__PURE__ */ jsxs63("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
8549
|
+
/* @__PURE__ */ jsx68("span", {}),
|
|
8550
|
+
/* @__PURE__ */ jsx68("span", {}),
|
|
8551
|
+
/* @__PURE__ */ jsx68("span", {})
|
|
8309
8552
|
] }) : null,
|
|
8310
|
-
/* @__PURE__ */
|
|
8553
|
+
/* @__PURE__ */ jsx68("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
|
|
8311
8554
|
] }),
|
|
8312
|
-
open ? /* @__PURE__ */
|
|
8555
|
+
open ? /* @__PURE__ */ jsx68("div", { className: "fdc-think-body", children: text }) : null
|
|
8313
8556
|
] });
|
|
8314
8557
|
}
|
|
8315
8558
|
function Citations({ items = [], onOpen }) {
|
|
8316
|
-
const [open, setOpen] =
|
|
8559
|
+
const [open, setOpen] = React37.useState(false);
|
|
8317
8560
|
if (!items.length) return null;
|
|
8318
|
-
return /* @__PURE__ */
|
|
8319
|
-
/* @__PURE__ */
|
|
8320
|
-
/* @__PURE__ */
|
|
8321
|
-
/* @__PURE__ */
|
|
8561
|
+
return /* @__PURE__ */ jsxs63("div", { className: "fdc-cites", children: [
|
|
8562
|
+
/* @__PURE__ */ jsxs63("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
8563
|
+
/* @__PURE__ */ jsx68("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
|
|
8564
|
+
/* @__PURE__ */ jsxs63("span", { children: [
|
|
8322
8565
|
items.length,
|
|
8323
8566
|
" source",
|
|
8324
8567
|
items.length === 1 ? "" : "s"
|
|
8325
8568
|
] }),
|
|
8326
|
-
/* @__PURE__ */
|
|
8569
|
+
/* @__PURE__ */ jsx68("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
|
|
8327
8570
|
] }),
|
|
8328
|
-
open ? /* @__PURE__ */
|
|
8329
|
-
/* @__PURE__ */
|
|
8330
|
-
c.url ? /* @__PURE__ */
|
|
8331
|
-
c.detail ? /* @__PURE__ */
|
|
8571
|
+
open ? /* @__PURE__ */ jsx68("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs63("li", { children: [
|
|
8572
|
+
/* @__PURE__ */ jsx68("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
|
|
8573
|
+
c.url ? /* @__PURE__ */ jsx68("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx68("span", { children: c.title || "Source" }),
|
|
8574
|
+
c.detail ? /* @__PURE__ */ jsx68("span", { className: "fdc-cite-detail", children: c.detail }) : null
|
|
8332
8575
|
] }, c.id || i)) }) : null
|
|
8333
8576
|
] });
|
|
8334
8577
|
}
|
|
@@ -8339,29 +8582,29 @@ function clampText(text, max) {
|
|
|
8339
8582
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
8340
8583
|
}
|
|
8341
8584
|
function MessageBody({ message: m, ctx }) {
|
|
8342
|
-
const [expanded, setExpanded] =
|
|
8585
|
+
const [expanded, setExpanded] = React37.useState(false);
|
|
8343
8586
|
const isUser = m.role === "user";
|
|
8344
8587
|
const raw = m.text || "";
|
|
8345
8588
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
8346
8589
|
const body = clamped != null ? clamped : raw;
|
|
8347
8590
|
const showMd = ctx.markdown && !isUser;
|
|
8348
|
-
return /* @__PURE__ */
|
|
8349
|
-
m.thinking && ctx.showThinking ? /* @__PURE__ */
|
|
8350
|
-
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */
|
|
8351
|
-
body ? /* @__PURE__ */
|
|
8352
|
-
showMd ? /* @__PURE__ */
|
|
8353
|
-
m.streaming ? /* @__PURE__ */
|
|
8591
|
+
return /* @__PURE__ */ jsxs63("div", { className: "fdc-body", children: [
|
|
8592
|
+
m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx68(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
|
|
8593
|
+
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx68(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
|
|
8594
|
+
body ? /* @__PURE__ */ jsxs63("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
|
|
8595
|
+
showMd ? /* @__PURE__ */ jsx68(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx68("div", { className: "fdc-plain", children: body }),
|
|
8596
|
+
m.streaming ? /* @__PURE__ */ jsx68("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
|
|
8354
8597
|
] }) : null,
|
|
8355
|
-
clamped != null ? /* @__PURE__ */
|
|
8356
|
-
/* @__PURE__ */
|
|
8598
|
+
clamped != null ? /* @__PURE__ */ jsxs63("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
|
|
8599
|
+
/* @__PURE__ */ jsx68("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
|
|
8357
8600
|
"Show more",
|
|
8358
|
-
/* @__PURE__ */
|
|
8359
|
-
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */
|
|
8360
|
-
/* @__PURE__ */
|
|
8601
|
+
/* @__PURE__ */ jsx68("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
|
|
8602
|
+
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs63("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
|
|
8603
|
+
/* @__PURE__ */ jsx68("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
|
|
8361
8604
|
"Show less"
|
|
8362
8605
|
] }) : null,
|
|
8363
|
-
m.attachments && m.attachments.length ? /* @__PURE__ */
|
|
8364
|
-
m.packet ? /* @__PURE__ */
|
|
8606
|
+
m.attachments && m.attachments.length ? /* @__PURE__ */ jsx68(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
|
|
8607
|
+
m.packet ? /* @__PURE__ */ jsx68(
|
|
8365
8608
|
PacketCard,
|
|
8366
8609
|
{
|
|
8367
8610
|
packet: m.packet,
|
|
@@ -8371,44 +8614,44 @@ function MessageBody({ message: m, ctx }) {
|
|
|
8371
8614
|
applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
|
|
8372
8615
|
}
|
|
8373
8616
|
) : null,
|
|
8374
|
-
m.citations && m.citations.length ? /* @__PURE__ */
|
|
8375
|
-
m.working ? /* @__PURE__ */
|
|
8376
|
-
/* @__PURE__ */
|
|
8377
|
-
/* @__PURE__ */
|
|
8378
|
-
/* @__PURE__ */
|
|
8379
|
-
/* @__PURE__ */
|
|
8617
|
+
m.citations && m.citations.length ? /* @__PURE__ */ jsx68(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
|
|
8618
|
+
m.working ? /* @__PURE__ */ jsxs63("div", { className: "fdc-working", role: "status", children: [
|
|
8619
|
+
/* @__PURE__ */ jsxs63("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
8620
|
+
/* @__PURE__ */ jsx68("span", {}),
|
|
8621
|
+
/* @__PURE__ */ jsx68("span", {}),
|
|
8622
|
+
/* @__PURE__ */ jsx68("span", {})
|
|
8380
8623
|
] }),
|
|
8381
|
-
/* @__PURE__ */
|
|
8624
|
+
/* @__PURE__ */ jsxs63("span", { className: "fdc-working-label", children: [
|
|
8382
8625
|
m.resumed ? "Resuming" : "Working",
|
|
8383
|
-
m.job && m.job.status ? /* @__PURE__ */
|
|
8626
|
+
m.job && m.job.status ? /* @__PURE__ */ jsxs63("span", { className: "fdc-working-job", children: [
|
|
8384
8627
|
" \xB7 ",
|
|
8385
8628
|
m.job.status
|
|
8386
8629
|
] }) : null,
|
|
8387
|
-
m.job && m.job.detail ? /* @__PURE__ */
|
|
8630
|
+
m.job && m.job.detail ? /* @__PURE__ */ jsxs63("span", { className: "fdc-working-job", children: [
|
|
8388
8631
|
" \xB7 ",
|
|
8389
8632
|
m.job.detail
|
|
8390
8633
|
] }) : null
|
|
8391
8634
|
] }),
|
|
8392
|
-
m.jobId ? /* @__PURE__ */
|
|
8635
|
+
m.jobId ? /* @__PURE__ */ jsx68("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
|
|
8393
8636
|
] }) : null,
|
|
8394
|
-
m.stopped ? /* @__PURE__ */
|
|
8395
|
-
/* @__PURE__ */
|
|
8637
|
+
m.stopped ? /* @__PURE__ */ jsxs63("div", { className: "fdc-stopped", children: [
|
|
8638
|
+
/* @__PURE__ */ jsx68("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
8396
8639
|
"Stopped"
|
|
8397
8640
|
] }) : null,
|
|
8398
|
-
m.error ? /* @__PURE__ */
|
|
8399
|
-
/* @__PURE__ */
|
|
8400
|
-
/* @__PURE__ */
|
|
8401
|
-
m.retryable && ctx.onRetry ? /* @__PURE__ */
|
|
8402
|
-
/* @__PURE__ */
|
|
8641
|
+
m.error ? /* @__PURE__ */ jsxs63("div", { className: "fdc-error", role: "alert", children: [
|
|
8642
|
+
/* @__PURE__ */ jsx68("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
8643
|
+
/* @__PURE__ */ jsx68("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
|
|
8644
|
+
m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs63("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
|
|
8645
|
+
/* @__PURE__ */ jsx68("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
8403
8646
|
"Retry"
|
|
8404
8647
|
] }) : null
|
|
8405
8648
|
] }) : null
|
|
8406
8649
|
] });
|
|
8407
8650
|
}
|
|
8408
8651
|
function useCopyRun() {
|
|
8409
|
-
const [done, setDone] =
|
|
8410
|
-
const t =
|
|
8411
|
-
|
|
8652
|
+
const [done, setDone] = React37.useState(false);
|
|
8653
|
+
const t = React37.useRef(null);
|
|
8654
|
+
React37.useEffect(() => () => {
|
|
8412
8655
|
if (t.current) clearTimeout(t.current);
|
|
8413
8656
|
}, []);
|
|
8414
8657
|
return [done, (text) => {
|
|
@@ -8428,16 +8671,16 @@ function RunActions({ group, ctx }) {
|
|
|
8428
8671
|
const isAssistant = group.role === "assistant";
|
|
8429
8672
|
const fb = last.feedback;
|
|
8430
8673
|
if (!ctx.messageActions) return null;
|
|
8431
|
-
return /* @__PURE__ */
|
|
8432
|
-
/* @__PURE__ */
|
|
8433
|
-
/* @__PURE__ */
|
|
8434
|
-
/* @__PURE__ */
|
|
8674
|
+
return /* @__PURE__ */ jsxs63("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
|
|
8675
|
+
/* @__PURE__ */ jsxs63("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
|
|
8676
|
+
/* @__PURE__ */ jsx68("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
|
|
8677
|
+
/* @__PURE__ */ jsx68("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
|
|
8435
8678
|
] }),
|
|
8436
|
-
isAssistant && ctx.onRetry ? /* @__PURE__ */
|
|
8437
|
-
group.role === "user" && ctx.onEdit ? /* @__PURE__ */
|
|
8438
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */
|
|
8439
|
-
/* @__PURE__ */
|
|
8440
|
-
/* @__PURE__ */
|
|
8679
|
+
isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx68("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx68("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
8680
|
+
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx68("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx68("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
8681
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs63(React37.Fragment, { children: [
|
|
8682
|
+
/* @__PURE__ */ jsx68("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__ */ jsx68("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
8683
|
+
/* @__PURE__ */ jsx68("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__ */ jsx68("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
8441
8684
|
] }) : null,
|
|
8442
8685
|
ctx.extraActions ? ctx.extraActions(group) : null
|
|
8443
8686
|
] });
|
|
@@ -8447,22 +8690,22 @@ function ChatTurn({ group, ctx }) {
|
|
|
8447
8690
|
const name = isUser ? ctx.userName : group.author || ctx.assistantName;
|
|
8448
8691
|
const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
|
|
8449
8692
|
const stamp = group.messages[0].timestamp;
|
|
8450
|
-
return /* @__PURE__ */
|
|
8451
|
-
/* @__PURE__ */
|
|
8452
|
-
ctx.showAvatars ? /* @__PURE__ */
|
|
8453
|
-
/* @__PURE__ */
|
|
8454
|
-
stamp ? /* @__PURE__ */
|
|
8455
|
-
group.messages.some((m) => m.model) ? /* @__PURE__ */
|
|
8693
|
+
return /* @__PURE__ */ jsxs63("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
|
|
8694
|
+
/* @__PURE__ */ jsxs63("div", { className: "fdc-turn-head", children: [
|
|
8695
|
+
ctx.showAvatars ? /* @__PURE__ */ jsx68("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx68("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx68("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx68("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
|
|
8696
|
+
/* @__PURE__ */ jsx68("span", { className: "fdc-who", children: name }),
|
|
8697
|
+
stamp ? /* @__PURE__ */ jsx68(RelativeTime, { className: "fdc-when", value: stamp }) : null,
|
|
8698
|
+
group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx68("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
|
|
8456
8699
|
] }),
|
|
8457
|
-
/* @__PURE__ */
|
|
8458
|
-
group.messages.map((m) => /* @__PURE__ */
|
|
8459
|
-
/* @__PURE__ */
|
|
8700
|
+
/* @__PURE__ */ jsxs63("div", { className: "fdc-turn-body", children: [
|
|
8701
|
+
group.messages.map((m) => /* @__PURE__ */ jsx68("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx68(MessageBody, { message: m, ctx }) }, m.id)),
|
|
8702
|
+
/* @__PURE__ */ jsx68(RunActions, { group, ctx })
|
|
8460
8703
|
] })
|
|
8461
8704
|
] });
|
|
8462
8705
|
}
|
|
8463
8706
|
|
|
8464
8707
|
// src/components/chat/ChatTranscript.tsx
|
|
8465
|
-
import { jsx as
|
|
8708
|
+
import { jsx as jsx69, jsxs as jsxs64 } from "react/jsx-runtime";
|
|
8466
8709
|
var GROUP_WINDOW = 6e4;
|
|
8467
8710
|
var STICK_PX = 100;
|
|
8468
8711
|
function groupMessages(list) {
|
|
@@ -8495,25 +8738,25 @@ function dayLabel(key) {
|
|
|
8495
8738
|
}
|
|
8496
8739
|
function Suggestions({ items = [], onPick }) {
|
|
8497
8740
|
if (!items.length) return null;
|
|
8498
|
-
return /* @__PURE__ */
|
|
8741
|
+
return /* @__PURE__ */ jsx69("div", { className: "fdc-suggest", children: items.map((s, i) => {
|
|
8499
8742
|
const it = typeof s === "string" ? { label: s, text: s } : s;
|
|
8500
|
-
return /* @__PURE__ */
|
|
8501
|
-
it.icon ? /* @__PURE__ */
|
|
8502
|
-
/* @__PURE__ */
|
|
8503
|
-
/* @__PURE__ */
|
|
8504
|
-
it.description ? /* @__PURE__ */
|
|
8743
|
+
return /* @__PURE__ */ jsxs64("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
|
|
8744
|
+
it.icon ? /* @__PURE__ */ jsx69("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
|
|
8745
|
+
/* @__PURE__ */ jsxs64("span", { className: "fdc-suggest-text", children: [
|
|
8746
|
+
/* @__PURE__ */ jsx69("span", { className: "fdc-suggest-label", children: it.label }),
|
|
8747
|
+
it.description ? /* @__PURE__ */ jsx69("span", { className: "fdc-suggest-desc", children: it.description }) : null
|
|
8505
8748
|
] }),
|
|
8506
|
-
/* @__PURE__ */
|
|
8749
|
+
/* @__PURE__ */ jsx69("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
|
|
8507
8750
|
] }, it.id || i);
|
|
8508
8751
|
}) });
|
|
8509
8752
|
}
|
|
8510
8753
|
function LoadingTurns() {
|
|
8511
|
-
return /* @__PURE__ */
|
|
8512
|
-
/* @__PURE__ */
|
|
8513
|
-
/* @__PURE__ */
|
|
8514
|
-
/* @__PURE__ */
|
|
8515
|
-
/* @__PURE__ */
|
|
8516
|
-
/* @__PURE__ */
|
|
8754
|
+
return /* @__PURE__ */ jsx69("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs64("div", { className: "fdc-skel-turn", children: [
|
|
8755
|
+
/* @__PURE__ */ jsx69("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
|
|
8756
|
+
/* @__PURE__ */ jsxs64("div", { className: "fdc-skel-lines", children: [
|
|
8757
|
+
/* @__PURE__ */ jsx69("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
|
|
8758
|
+
/* @__PURE__ */ jsx69("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
|
|
8759
|
+
/* @__PURE__ */ jsx69("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
|
|
8517
8760
|
] })
|
|
8518
8761
|
] }, i)) });
|
|
8519
8762
|
}
|
|
@@ -8530,10 +8773,10 @@ function ChatTranscript({
|
|
|
8530
8773
|
renderEmpty,
|
|
8531
8774
|
className = ""
|
|
8532
8775
|
}) {
|
|
8533
|
-
const scroller =
|
|
8534
|
-
const stick =
|
|
8535
|
-
const [pill, setPill] =
|
|
8536
|
-
const seen =
|
|
8776
|
+
const scroller = React38.useRef(null);
|
|
8777
|
+
const stick = React38.useRef(true);
|
|
8778
|
+
const [pill, setPill] = React38.useState(0);
|
|
8779
|
+
const seen = React38.useRef(0);
|
|
8537
8780
|
const toBottom = (smooth) => {
|
|
8538
8781
|
const el = scroller.current;
|
|
8539
8782
|
if (!el) return;
|
|
@@ -8552,7 +8795,7 @@ function ChatTranscript({
|
|
|
8552
8795
|
seen.current = messages.length;
|
|
8553
8796
|
}
|
|
8554
8797
|
};
|
|
8555
|
-
|
|
8798
|
+
React38.useLayoutEffect(() => {
|
|
8556
8799
|
const el = scroller.current;
|
|
8557
8800
|
if (!el) return;
|
|
8558
8801
|
if (stick.current) {
|
|
@@ -8560,7 +8803,7 @@ function ChatTranscript({
|
|
|
8560
8803
|
seen.current = messages.length;
|
|
8561
8804
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
8562
8805
|
}, [messages]);
|
|
8563
|
-
|
|
8806
|
+
React38.useEffect(() => {
|
|
8564
8807
|
const el = scroller.current;
|
|
8565
8808
|
const inner = el && el.firstChild;
|
|
8566
8809
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -8570,38 +8813,38 @@ function ChatTranscript({
|
|
|
8570
8813
|
ro.observe(inner);
|
|
8571
8814
|
return () => ro.disconnect();
|
|
8572
8815
|
}, []);
|
|
8573
|
-
const groups =
|
|
8816
|
+
const groups = React38.useMemo(() => groupMessages(messages), [messages]);
|
|
8574
8817
|
const empty = !messages.length && status === "ready";
|
|
8575
|
-
return /* @__PURE__ */
|
|
8576
|
-
/* @__PURE__ */
|
|
8577
|
-
status === "loading" || status === "resolving" ? /* @__PURE__ */
|
|
8578
|
-
status === "disconnected" ? /* @__PURE__ */
|
|
8579
|
-
/* @__PURE__ */
|
|
8580
|
-
/* @__PURE__ */
|
|
8581
|
-
/* @__PURE__ */
|
|
8582
|
-
ctx.onReconnect ? /* @__PURE__ */
|
|
8583
|
-
/* @__PURE__ */
|
|
8818
|
+
return /* @__PURE__ */ jsxs64("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
8819
|
+
/* @__PURE__ */ jsxs64("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
8820
|
+
status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx69(LoadingTurns, {}) : null,
|
|
8821
|
+
status === "disconnected" ? /* @__PURE__ */ jsxs64("div", { className: "fdc-dead", children: [
|
|
8822
|
+
/* @__PURE__ */ jsx69("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx69("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
|
|
8823
|
+
/* @__PURE__ */ jsx69("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
|
|
8824
|
+
/* @__PURE__ */ jsx69("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." }),
|
|
8825
|
+
ctx.onReconnect ? /* @__PURE__ */ jsxs64("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
|
|
8826
|
+
/* @__PURE__ */ jsx69("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
8584
8827
|
"Try again"
|
|
8585
8828
|
] }) : null
|
|
8586
8829
|
] }) : null,
|
|
8587
|
-
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */
|
|
8588
|
-
/* @__PURE__ */
|
|
8589
|
-
/* @__PURE__ */
|
|
8590
|
-
emptyDescription ? /* @__PURE__ */
|
|
8591
|
-
/* @__PURE__ */
|
|
8830
|
+
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs64("div", { className: "fdc-empty", children: [
|
|
8831
|
+
/* @__PURE__ */ jsx69("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx69("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
|
|
8832
|
+
/* @__PURE__ */ jsx69("h3", { className: "fdc-empty-title", children: emptyTitle }),
|
|
8833
|
+
emptyDescription ? /* @__PURE__ */ jsx69("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
|
|
8834
|
+
/* @__PURE__ */ jsx69(Suggestions, { items: suggestions, onPick })
|
|
8592
8835
|
] }) : null,
|
|
8593
8836
|
groups.map((g, i) => {
|
|
8594
8837
|
const prev = groups[i - 1];
|
|
8595
8838
|
const k = dayKey(g.messages[0].timestamp);
|
|
8596
8839
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
8597
|
-
return /* @__PURE__ */
|
|
8598
|
-
showDay ? /* @__PURE__ */
|
|
8599
|
-
/* @__PURE__ */
|
|
8840
|
+
return /* @__PURE__ */ jsxs64(React38.Fragment, { children: [
|
|
8841
|
+
showDay ? /* @__PURE__ */ jsx69("div", { className: "fdc-day", children: /* @__PURE__ */ jsx69("span", { children: dayLabel(k) }) }) : null,
|
|
8842
|
+
/* @__PURE__ */ jsx69(ChatTurn, { group: g, ctx })
|
|
8600
8843
|
] }, g.key || i);
|
|
8601
8844
|
})
|
|
8602
8845
|
] }),
|
|
8603
|
-
pill ? /* @__PURE__ */
|
|
8604
|
-
/* @__PURE__ */
|
|
8846
|
+
pill ? /* @__PURE__ */ jsxs64("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
|
|
8847
|
+
/* @__PURE__ */ jsx69("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
|
|
8605
8848
|
pill,
|
|
8606
8849
|
" new message",
|
|
8607
8850
|
pill === 1 ? "" : "s"
|
|
@@ -8611,8 +8854,8 @@ function ChatTranscript({
|
|
|
8611
8854
|
var TranscriptKit = { groupMessages };
|
|
8612
8855
|
|
|
8613
8856
|
// src/components/chat/ChatComposer.tsx
|
|
8614
|
-
import * as
|
|
8615
|
-
import { jsx as
|
|
8857
|
+
import * as React39 from "react";
|
|
8858
|
+
import { jsx as jsx70, jsxs as jsxs65 } from "react/jsx-runtime";
|
|
8616
8859
|
function ChatComposer({
|
|
8617
8860
|
onSubmit,
|
|
8618
8861
|
onStop,
|
|
@@ -8639,17 +8882,17 @@ function ChatComposer({
|
|
|
8639
8882
|
onReject,
|
|
8640
8883
|
onOpenAttachment
|
|
8641
8884
|
}) {
|
|
8642
|
-
const [text, setText] =
|
|
8643
|
-
const [trigger, setTrigger] =
|
|
8644
|
-
const [mentionItems, setMentionItems] =
|
|
8645
|
-
const [listening, setListening] =
|
|
8646
|
-
const [notice, setNotice] =
|
|
8647
|
-
const editor =
|
|
8648
|
-
const wrap =
|
|
8649
|
-
const stopVoice =
|
|
8885
|
+
const [text, setText] = React39.useState(draft || "");
|
|
8886
|
+
const [trigger, setTrigger] = React39.useState(null);
|
|
8887
|
+
const [mentionItems, setMentionItems] = React39.useState([]);
|
|
8888
|
+
const [listening, setListening] = React39.useState(false);
|
|
8889
|
+
const [notice, setNotice] = React39.useState(null);
|
|
8890
|
+
const editor = React39.useRef(null);
|
|
8891
|
+
const wrap = React39.useRef(null);
|
|
8892
|
+
const stopVoice = React39.useRef(null);
|
|
8650
8893
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
8651
8894
|
} });
|
|
8652
|
-
|
|
8895
|
+
React39.useEffect(() => {
|
|
8653
8896
|
if (draft != null && draft !== text) setText(draft);
|
|
8654
8897
|
}, [draft]);
|
|
8655
8898
|
const change = (v) => {
|
|
@@ -8683,7 +8926,7 @@ function ChatComposer({
|
|
|
8683
8926
|
e.preventDefault();
|
|
8684
8927
|
staged.add(found.files);
|
|
8685
8928
|
};
|
|
8686
|
-
|
|
8929
|
+
React39.useEffect(() => {
|
|
8687
8930
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
8688
8931
|
setMentionItems([]);
|
|
8689
8932
|
return;
|
|
@@ -8701,7 +8944,7 @@ function ChatComposer({
|
|
|
8701
8944
|
const q = (trigger.query || "").toLowerCase();
|
|
8702
8945
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
8703
8946
|
}, [trigger, mentionSources]);
|
|
8704
|
-
const slashItems =
|
|
8947
|
+
const slashItems = React39.useMemo(() => {
|
|
8705
8948
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
8706
8949
|
const q = (trigger.query || "").toLowerCase();
|
|
8707
8950
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -8715,7 +8958,7 @@ function ChatComposer({
|
|
|
8715
8958
|
description: it.description,
|
|
8716
8959
|
icon: it.icon,
|
|
8717
8960
|
meta: mention.meta,
|
|
8718
|
-
shortcut: slash.shortcut ? /* @__PURE__ */
|
|
8961
|
+
shortcut: slash.shortcut ? /* @__PURE__ */ jsx70(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
|
|
8719
8962
|
onSelect: () => {
|
|
8720
8963
|
const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
|
|
8721
8964
|
editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
|
|
@@ -8778,14 +9021,14 @@ function ChatComposer({
|
|
|
8778
9021
|
stopVoice.current = typeof res === "function" ? res : () => {
|
|
8779
9022
|
};
|
|
8780
9023
|
};
|
|
8781
|
-
return /* @__PURE__ */
|
|
8782
|
-
queue.length ? /* @__PURE__ */
|
|
8783
|
-
/* @__PURE__ */
|
|
8784
|
-
/* @__PURE__ */
|
|
8785
|
-
onRemoveQueued ? /* @__PURE__ */
|
|
9024
|
+
return /* @__PURE__ */ jsxs65("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
|
|
9025
|
+
queue.length ? /* @__PURE__ */ jsx70("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs65("div", { className: "fdc-queue-row", children: [
|
|
9026
|
+
/* @__PURE__ */ jsx70("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
|
|
9027
|
+
/* @__PURE__ */ jsx70("span", { className: "fdc-queue-text", children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
|
|
9028
|
+
onRemoveQueued ? /* @__PURE__ */ jsx70("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx70("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
8786
9029
|
] }, q.id)) }) : null,
|
|
8787
9030
|
sessionBar,
|
|
8788
|
-
/* @__PURE__ */
|
|
9031
|
+
/* @__PURE__ */ jsx70(
|
|
8789
9032
|
Dropzone,
|
|
8790
9033
|
{
|
|
8791
9034
|
className: "fdc-field",
|
|
@@ -8799,9 +9042,9 @@ function ChatComposer({
|
|
|
8799
9042
|
disabled: !fileUploadHandler || disabled,
|
|
8800
9043
|
label: "Drop to attach",
|
|
8801
9044
|
hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
|
|
8802
|
-
children: /* @__PURE__ */
|
|
8803
|
-
staged.items.length ? /* @__PURE__ */
|
|
8804
|
-
/* @__PURE__ */
|
|
9045
|
+
children: /* @__PURE__ */ jsxs65("div", { ref: wrap, className: "fdc-field-inner", children: [
|
|
9046
|
+
staged.items.length ? /* @__PURE__ */ jsx70("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx70(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
|
|
9047
|
+
/* @__PURE__ */ jsx70(
|
|
8805
9048
|
MarkdownEditor,
|
|
8806
9049
|
{
|
|
8807
9050
|
ref: editor,
|
|
@@ -8820,33 +9063,33 @@ function ChatComposer({
|
|
|
8820
9063
|
ariaLabel: "Message"
|
|
8821
9064
|
}
|
|
8822
9065
|
),
|
|
8823
|
-
/* @__PURE__ */
|
|
8824
|
-
fileUploadHandler ? /* @__PURE__ */
|
|
8825
|
-
voiceHandler ? /* @__PURE__ */
|
|
9066
|
+
/* @__PURE__ */ jsxs65("div", { className: "fdc-tools", children: [
|
|
9067
|
+
fileUploadHandler ? /* @__PURE__ */ jsx70(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
|
|
9068
|
+
voiceHandler ? /* @__PURE__ */ jsx70("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx70("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
|
|
8826
9069
|
toolbarExtras,
|
|
8827
|
-
/* @__PURE__ */
|
|
8828
|
-
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */
|
|
9070
|
+
/* @__PURE__ */ jsx70("span", { className: "fdc-tools-gap" }),
|
|
9071
|
+
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs65("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
|
|
8829
9072
|
text.length,
|
|
8830
9073
|
"/",
|
|
8831
9074
|
maxLength
|
|
8832
9075
|
] }) : null,
|
|
8833
|
-
busy ? /* @__PURE__ */
|
|
8834
|
-
/* @__PURE__ */
|
|
8835
|
-
/* @__PURE__ */
|
|
8836
|
-
] }) : /* @__PURE__ */
|
|
8837
|
-
/* @__PURE__ */
|
|
8838
|
-
/* @__PURE__ */
|
|
9076
|
+
busy ? /* @__PURE__ */ jsxs65("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
|
|
9077
|
+
/* @__PURE__ */ jsx70("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
9078
|
+
/* @__PURE__ */ jsx70("span", { children: "Stop" })
|
|
9079
|
+
] }) : /* @__PURE__ */ jsxs65("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
|
|
9080
|
+
/* @__PURE__ */ jsx70("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
|
|
9081
|
+
/* @__PURE__ */ jsx70("span", { className: "fdc-send-label", children: "Send" })
|
|
8839
9082
|
] })
|
|
8840
9083
|
] })
|
|
8841
9084
|
] })
|
|
8842
9085
|
}
|
|
8843
9086
|
),
|
|
8844
|
-
notice ? /* @__PURE__ */
|
|
8845
|
-
/* @__PURE__ */
|
|
9087
|
+
notice ? /* @__PURE__ */ jsxs65("div", { className: "fdc-notice", role: "status", children: [
|
|
9088
|
+
/* @__PURE__ */ jsx70("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
8846
9089
|
notice
|
|
8847
9090
|
] }) : null,
|
|
8848
|
-
hint && !notice ? /* @__PURE__ */
|
|
8849
|
-
/* @__PURE__ */
|
|
9091
|
+
hint && !notice ? /* @__PURE__ */ jsx70("div", { className: "fdc-hint", children: hint }) : null,
|
|
9092
|
+
/* @__PURE__ */ jsx70(
|
|
8850
9093
|
Popover,
|
|
8851
9094
|
{
|
|
8852
9095
|
open: menuOpen,
|
|
@@ -8860,12 +9103,12 @@ function ChatComposer({
|
|
|
8860
9103
|
returnFocus: false,
|
|
8861
9104
|
closeOnOutside: true,
|
|
8862
9105
|
label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
|
|
8863
|
-
children: /* @__PURE__ */
|
|
9106
|
+
children: /* @__PURE__ */ jsx70(
|
|
8864
9107
|
Menu,
|
|
8865
9108
|
{
|
|
8866
9109
|
items: menuItems,
|
|
8867
9110
|
autoFocus: false,
|
|
8868
|
-
header: /* @__PURE__ */
|
|
9111
|
+
header: /* @__PURE__ */ jsx70("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
|
|
8869
9112
|
onClose: () => setTrigger(null)
|
|
8870
9113
|
}
|
|
8871
9114
|
)
|
|
@@ -8875,12 +9118,12 @@ function ChatComposer({
|
|
|
8875
9118
|
}
|
|
8876
9119
|
|
|
8877
9120
|
// src/components/chat/ChatSessionBar.tsx
|
|
8878
|
-
import * as
|
|
8879
|
-
import { jsx as
|
|
9121
|
+
import * as React40 from "react";
|
|
9122
|
+
import { jsx as jsx71, jsxs as jsxs66 } from "react/jsx-runtime";
|
|
8880
9123
|
var compact2 = meterFormats.compact;
|
|
8881
9124
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
8882
|
-
const [open, setOpen] =
|
|
8883
|
-
const anchor =
|
|
9125
|
+
const [open, setOpen] = React40.useState(false);
|
|
9126
|
+
const anchor = React40.useRef(null);
|
|
8884
9127
|
const stats = sessionStats || null;
|
|
8885
9128
|
const cu = contextUsage || null;
|
|
8886
9129
|
const limits = usageLimits || null;
|
|
@@ -8895,9 +9138,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
8895
9138
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
8896
9139
|
if (cu) bits.push(pct + "% context");
|
|
8897
9140
|
const expandable = !!(cu || limits);
|
|
8898
|
-
return /* @__PURE__ */
|
|
8899
|
-
/* @__PURE__ */
|
|
8900
|
-
/* @__PURE__ */
|
|
9141
|
+
return /* @__PURE__ */ jsxs66(React40.Fragment, { children: [
|
|
9142
|
+
/* @__PURE__ */ jsxs66("div", { className: "fdc-bar", children: [
|
|
9143
|
+
/* @__PURE__ */ jsxs66(
|
|
8901
9144
|
"button",
|
|
8902
9145
|
{
|
|
8903
9146
|
type: "button",
|
|
@@ -8908,16 +9151,16 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
8908
9151
|
"aria-expanded": expandable ? open : void 0,
|
|
8909
9152
|
"aria-label": expandable ? "Usage details" : void 0,
|
|
8910
9153
|
children: [
|
|
8911
|
-
cu ? /* @__PURE__ */
|
|
8912
|
-
/* @__PURE__ */
|
|
8913
|
-
expandable ? /* @__PURE__ */
|
|
9154
|
+
cu ? /* @__PURE__ */ jsx71("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx71(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
|
|
9155
|
+
/* @__PURE__ */ jsx71("span", { className: "fdc-bar-text", children: bits.join(" \xB7 ") }),
|
|
9156
|
+
expandable ? /* @__PURE__ */ jsx71("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
|
|
8914
9157
|
]
|
|
8915
9158
|
}
|
|
8916
9159
|
),
|
|
8917
9160
|
extras
|
|
8918
9161
|
] }),
|
|
8919
|
-
/* @__PURE__ */
|
|
8920
|
-
cu ? /* @__PURE__ */
|
|
9162
|
+
/* @__PURE__ */ jsx71(Popover, { open, anchorRef: anchor, placement: "top-start", onClose: () => setOpen(false), minWidth: 330, maxHeight: 460, padded: true, label: "Usage", children: /* @__PURE__ */ jsxs66("div", { className: "fdc-usage", children: [
|
|
9163
|
+
cu ? /* @__PURE__ */ jsx71("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx71(
|
|
8921
9164
|
SegmentedMeter,
|
|
8922
9165
|
{
|
|
8923
9166
|
total,
|
|
@@ -8929,9 +9172,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
8929
9172
|
remainderLabel: "Free"
|
|
8930
9173
|
}
|
|
8931
9174
|
) }) : null,
|
|
8932
|
-
limits && limits.length ? /* @__PURE__ */
|
|
8933
|
-
/* @__PURE__ */
|
|
8934
|
-
/* @__PURE__ */
|
|
9175
|
+
limits && limits.length ? /* @__PURE__ */ jsxs66("section", { className: "fdc-usage-sec", children: [
|
|
9176
|
+
/* @__PURE__ */ jsx71("h4", { className: "fdc-usage-h", children: "Usage limits" }),
|
|
9177
|
+
/* @__PURE__ */ jsx71("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx71(
|
|
8935
9178
|
QuotaRow,
|
|
8936
9179
|
{
|
|
8937
9180
|
label: l.label,
|
|
@@ -8941,32 +9184,32 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
8941
9184
|
l.id
|
|
8942
9185
|
)) })
|
|
8943
9186
|
] }) : null,
|
|
8944
|
-
stats ? /* @__PURE__ */
|
|
8945
|
-
stats.elapsedMs ? /* @__PURE__ */
|
|
8946
|
-
/* @__PURE__ */
|
|
8947
|
-
/* @__PURE__ */
|
|
9187
|
+
stats ? /* @__PURE__ */ jsxs66("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
|
|
9188
|
+
stats.elapsedMs ? /* @__PURE__ */ jsxs66("div", { children: [
|
|
9189
|
+
/* @__PURE__ */ jsx71("span", { children: "Session" }),
|
|
9190
|
+
/* @__PURE__ */ jsx71("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
|
|
8948
9191
|
] }) : null,
|
|
8949
|
-
stats.tokens ? /* @__PURE__ */
|
|
8950
|
-
/* @__PURE__ */
|
|
8951
|
-
/* @__PURE__ */
|
|
9192
|
+
stats.tokens ? /* @__PURE__ */ jsxs66("div", { children: [
|
|
9193
|
+
/* @__PURE__ */ jsx71("span", { children: "Tokens" }),
|
|
9194
|
+
/* @__PURE__ */ jsx71("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
|
|
8952
9195
|
] }) : null,
|
|
8953
|
-
stats.costUsd != null ? /* @__PURE__ */
|
|
8954
|
-
/* @__PURE__ */
|
|
8955
|
-
/* @__PURE__ */
|
|
9196
|
+
stats.costUsd != null ? /* @__PURE__ */ jsxs66("div", { children: [
|
|
9197
|
+
/* @__PURE__ */ jsx71("span", { children: "Cost" }),
|
|
9198
|
+
/* @__PURE__ */ jsxs66("b", { className: "fd-tabular", children: [
|
|
8956
9199
|
"$",
|
|
8957
9200
|
Number(stats.costUsd).toFixed(3)
|
|
8958
9201
|
] })
|
|
8959
9202
|
] }) : null,
|
|
8960
|
-
stats.turns ? /* @__PURE__ */
|
|
8961
|
-
/* @__PURE__ */
|
|
8962
|
-
/* @__PURE__ */
|
|
9203
|
+
stats.turns ? /* @__PURE__ */ jsxs66("div", { children: [
|
|
9204
|
+
/* @__PURE__ */ jsx71("span", { children: "Turns" }),
|
|
9205
|
+
/* @__PURE__ */ jsx71("b", { className: "fd-tabular", children: stats.turns })
|
|
8963
9206
|
] }) : null
|
|
8964
9207
|
] }) : null,
|
|
8965
|
-
onClear ? /* @__PURE__ */
|
|
9208
|
+
onClear ? /* @__PURE__ */ jsx71("footer", { className: "fdc-usage-foot", children: /* @__PURE__ */ jsxs66("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
|
|
8966
9209
|
setOpen(false);
|
|
8967
9210
|
onClear();
|
|
8968
9211
|
}, children: [
|
|
8969
|
-
/* @__PURE__ */
|
|
9212
|
+
/* @__PURE__ */ jsx71("i", { className: "ph ph-trash", "aria-hidden": "true" }),
|
|
8970
9213
|
"Clear conversation"
|
|
8971
9214
|
] }) }) : null
|
|
8972
9215
|
] }) })
|
|
@@ -9003,7 +9246,7 @@ function ModelControls({
|
|
|
9003
9246
|
disabled: m.disabled,
|
|
9004
9247
|
checked: m.id === (current2 && current2.id),
|
|
9005
9248
|
meta: m.meta,
|
|
9006
|
-
shortcut: m.shortcut ? /* @__PURE__ */
|
|
9249
|
+
shortcut: m.shortcut ? /* @__PURE__ */ jsx71(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
|
|
9007
9250
|
onSelect: () => onModelChange && onModelChange(m.id)
|
|
9008
9251
|
});
|
|
9009
9252
|
const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
|
|
@@ -9016,15 +9259,15 @@ function ModelControls({
|
|
|
9016
9259
|
items.push({ kind: "section", label: "Fast mode" });
|
|
9017
9260
|
items.push({
|
|
9018
9261
|
kind: "custom",
|
|
9019
|
-
render: () => /* @__PURE__ */
|
|
9020
|
-
/* @__PURE__ */
|
|
9021
|
-
/* @__PURE__ */
|
|
9022
|
-
/* @__PURE__ */
|
|
9262
|
+
render: () => /* @__PURE__ */ jsxs66("label", { className: "fdc-switchrow", children: [
|
|
9263
|
+
/* @__PURE__ */ jsx71("span", { children: fastModeLabel }),
|
|
9264
|
+
/* @__PURE__ */ jsx71("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
|
|
9265
|
+
/* @__PURE__ */ jsx71("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx71("span", { className: "fd-switch-thumb" }) })
|
|
9023
9266
|
] })
|
|
9024
9267
|
});
|
|
9025
9268
|
}
|
|
9026
|
-
return /* @__PURE__ */
|
|
9027
|
-
/* @__PURE__ */
|
|
9269
|
+
return /* @__PURE__ */ jsxs66(React40.Fragment, { children: [
|
|
9270
|
+
/* @__PURE__ */ jsx71(
|
|
9028
9271
|
MenuButton,
|
|
9029
9272
|
{
|
|
9030
9273
|
items,
|
|
@@ -9035,7 +9278,7 @@ function ModelControls({
|
|
|
9035
9278
|
title: "Choose a model"
|
|
9036
9279
|
}
|
|
9037
9280
|
),
|
|
9038
|
-
effortLevels && effortLevels.length ? /* @__PURE__ */
|
|
9281
|
+
effortLevels && effortLevels.length ? /* @__PURE__ */ jsx71(
|
|
9039
9282
|
MenuButton,
|
|
9040
9283
|
{
|
|
9041
9284
|
placement: "top-end",
|
|
@@ -9056,7 +9299,7 @@ function ModelControls({
|
|
|
9056
9299
|
}
|
|
9057
9300
|
|
|
9058
9301
|
// src/components/chat/AgentChatPanel.tsx
|
|
9059
|
-
import { jsx as
|
|
9302
|
+
import { jsx as jsx72, jsxs as jsxs67 } from "react/jsx-runtime";
|
|
9060
9303
|
var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
|
|
9061
9304
|
function AgentChatPanel({
|
|
9062
9305
|
/* required */
|
|
@@ -9140,11 +9383,11 @@ function AgentChatPanel({
|
|
|
9140
9383
|
onFeedback,
|
|
9141
9384
|
onEditMessage
|
|
9142
9385
|
}) {
|
|
9143
|
-
const [panelWidth, setPanelWidth] =
|
|
9144
|
-
const [applied, setApplied] =
|
|
9145
|
-
const [draft, setDraft] =
|
|
9146
|
-
const dragging =
|
|
9147
|
-
|
|
9386
|
+
const [panelWidth, setPanelWidth] = React41.useState(width);
|
|
9387
|
+
const [applied, setApplied] = React41.useState({});
|
|
9388
|
+
const [draft, setDraft] = React41.useState("");
|
|
9389
|
+
const dragging = React41.useRef(null);
|
|
9390
|
+
React41.useEffect(() => setPanelWidth(width), [width]);
|
|
9148
9391
|
const engine = useChatEngine({
|
|
9149
9392
|
contextType,
|
|
9150
9393
|
contextId,
|
|
@@ -9210,7 +9453,7 @@ function AgentChatPanel({
|
|
|
9210
9453
|
onReconnect: engine.reload,
|
|
9211
9454
|
deadTitle: "The assistant isn\u2019t reachable"
|
|
9212
9455
|
};
|
|
9213
|
-
const sessionBar = /* @__PURE__ */
|
|
9456
|
+
const sessionBar = /* @__PURE__ */ jsx72(
|
|
9214
9457
|
ChatSessionBar,
|
|
9215
9458
|
{
|
|
9216
9459
|
sessionStats,
|
|
@@ -9219,7 +9462,7 @@ function AgentChatPanel({
|
|
|
9219
9462
|
onClear: engine.visible.length ? engine.clear : void 0
|
|
9220
9463
|
}
|
|
9221
9464
|
);
|
|
9222
|
-
const modelControls = /* @__PURE__ */
|
|
9465
|
+
const modelControls = /* @__PURE__ */ jsx72(
|
|
9223
9466
|
ModelControls,
|
|
9224
9467
|
{
|
|
9225
9468
|
models,
|
|
@@ -9234,7 +9477,7 @@ function AgentChatPanel({
|
|
|
9234
9477
|
narrow
|
|
9235
9478
|
}
|
|
9236
9479
|
);
|
|
9237
|
-
const threadMenu = threads && threads.length ? /* @__PURE__ */
|
|
9480
|
+
const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx72(
|
|
9238
9481
|
MenuButton,
|
|
9239
9482
|
{
|
|
9240
9483
|
variant: "ghost",
|
|
@@ -9261,7 +9504,7 @@ function AgentChatPanel({
|
|
|
9261
9504
|
})))
|
|
9262
9505
|
}
|
|
9263
9506
|
) : null;
|
|
9264
|
-
return /* @__PURE__ */
|
|
9507
|
+
return /* @__PURE__ */ jsxs67(
|
|
9265
9508
|
"aside",
|
|
9266
9509
|
{
|
|
9267
9510
|
className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
|
|
@@ -9272,7 +9515,7 @@ function AgentChatPanel({
|
|
|
9272
9515
|
},
|
|
9273
9516
|
"aria-label": title,
|
|
9274
9517
|
children: [
|
|
9275
|
-
surface === "sidebar" && resizable ? /* @__PURE__ */
|
|
9518
|
+
surface === "sidebar" && resizable ? /* @__PURE__ */ jsx72(
|
|
9276
9519
|
"div",
|
|
9277
9520
|
{
|
|
9278
9521
|
className: "fdc-grip",
|
|
@@ -9287,20 +9530,20 @@ function AgentChatPanel({
|
|
|
9287
9530
|
}
|
|
9288
9531
|
}
|
|
9289
9532
|
) : null,
|
|
9290
|
-
showHeader ? /* @__PURE__ */
|
|
9291
|
-
/* @__PURE__ */
|
|
9292
|
-
/* @__PURE__ */
|
|
9293
|
-
/* @__PURE__ */
|
|
9294
|
-
subtitle ? /* @__PURE__ */
|
|
9533
|
+
showHeader ? /* @__PURE__ */ jsxs67("header", { className: "fdc-head", children: [
|
|
9534
|
+
/* @__PURE__ */ jsx72("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx72("i", { className: "ph ph-" + assistantIcon }) }),
|
|
9535
|
+
/* @__PURE__ */ jsxs67("span", { className: "fdc-head-titles", children: [
|
|
9536
|
+
/* @__PURE__ */ jsx72("span", { className: "fdc-head-title", children: title }),
|
|
9537
|
+
subtitle ? /* @__PURE__ */ jsx72("span", { className: "fdc-head-sub", children: subtitle }) : null
|
|
9295
9538
|
] }),
|
|
9296
|
-
/* @__PURE__ */
|
|
9539
|
+
/* @__PURE__ */ jsxs67("span", { className: "fdc-head-acts", children: [
|
|
9297
9540
|
headerActions,
|
|
9298
9541
|
threadMenu,
|
|
9299
|
-
onNewThread ? /* @__PURE__ */
|
|
9300
|
-
onClose ? /* @__PURE__ */
|
|
9542
|
+
onNewThread ? /* @__PURE__ */ jsx72("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx72("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
|
|
9543
|
+
onClose ? /* @__PURE__ */ jsx72("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx72("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
9301
9544
|
] })
|
|
9302
9545
|
] }) : null,
|
|
9303
|
-
/* @__PURE__ */
|
|
9546
|
+
/* @__PURE__ */ jsx72(
|
|
9304
9547
|
ChatTranscript,
|
|
9305
9548
|
{
|
|
9306
9549
|
messages: engine.visible,
|
|
@@ -9315,7 +9558,7 @@ function AgentChatPanel({
|
|
|
9315
9558
|
renderEmpty
|
|
9316
9559
|
}
|
|
9317
9560
|
),
|
|
9318
|
-
/* @__PURE__ */
|
|
9561
|
+
/* @__PURE__ */ jsx72(
|
|
9319
9562
|
ChatComposer,
|
|
9320
9563
|
{
|
|
9321
9564
|
onSubmit: (text, atts) => engine.send(text, atts),
|
|
@@ -9348,7 +9591,7 @@ function AgentChatPanel({
|
|
|
9348
9591
|
}
|
|
9349
9592
|
|
|
9350
9593
|
// src/kits/query.ts
|
|
9351
|
-
import * as
|
|
9594
|
+
import * as React42 from "react";
|
|
9352
9595
|
function eqFilter(get2) {
|
|
9353
9596
|
return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
|
|
9354
9597
|
}
|
|
@@ -9380,22 +9623,22 @@ function compare(a, b, dir) {
|
|
|
9380
9623
|
var API = null;
|
|
9381
9624
|
var PREFS = null;
|
|
9382
9625
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
9383
|
-
const [query, setQuery] =
|
|
9626
|
+
const [query, setQuery] = React42.useState(() => {
|
|
9384
9627
|
const store = PREFS || window.PlannerPrefs;
|
|
9385
9628
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
9386
9629
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
9387
9630
|
});
|
|
9388
|
-
const savePref =
|
|
9631
|
+
const savePref = React42.useCallback((patch2) => {
|
|
9389
9632
|
const store = PREFS || window.PlannerPrefs;
|
|
9390
9633
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
9391
9634
|
}, [prefsKey]);
|
|
9392
|
-
const [res, setRes] =
|
|
9393
|
-
const [loading, setLoading] =
|
|
9394
|
-
const seq2 =
|
|
9635
|
+
const [res, setRes] = React42.useState(null);
|
|
9636
|
+
const [loading, setLoading] = React42.useState(true);
|
|
9637
|
+
const seq2 = React42.useRef(0);
|
|
9395
9638
|
const depKey = (deps || []).join("|");
|
|
9396
9639
|
const paramKey = JSON.stringify(params || {});
|
|
9397
9640
|
const queryKey = JSON.stringify(query);
|
|
9398
|
-
|
|
9641
|
+
React42.useEffect(() => {
|
|
9399
9642
|
const id = ++seq2.current;
|
|
9400
9643
|
setLoading(true);
|
|
9401
9644
|
const t = setTimeout(() => {
|
|
@@ -9733,6 +9976,7 @@ export {
|
|
|
9733
9976
|
Dropzone,
|
|
9734
9977
|
DropzoneKit,
|
|
9735
9978
|
EmptyState,
|
|
9979
|
+
EntityRow,
|
|
9736
9980
|
FeatureGate,
|
|
9737
9981
|
FileChip,
|
|
9738
9982
|
FileGrid,
|
|
@@ -9805,11 +10049,16 @@ export {
|
|
|
9805
10049
|
Tooltip,
|
|
9806
10050
|
Topbar,
|
|
9807
10051
|
TranscriptKit,
|
|
10052
|
+
TransferList,
|
|
9808
10053
|
UseFeatureStatus,
|
|
9809
10054
|
UseRuntimeMode,
|
|
10055
|
+
VIRTUAL_LIST_BUFFER_ROWS,
|
|
10056
|
+
VirtualList,
|
|
9810
10057
|
acceptMatches,
|
|
9811
10058
|
anyOfFilter,
|
|
9812
10059
|
channelWeightOf,
|
|
10060
|
+
computeNeedMore,
|
|
10061
|
+
computeVirtualWindow,
|
|
9813
10062
|
createVersionStore,
|
|
9814
10063
|
eqFilter,
|
|
9815
10064
|
extensionOf,
|