@flytedan/flytebot-design-system 0.33.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -2
- package/dist/index.cjs +478 -390
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -8
- package/dist/index.d.ts +21 -8
- package/dist/index.js +478 -390
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2731,10 +2731,10 @@ function DataTable({
|
|
|
2731
2731
|
}
|
|
2732
2732
|
|
|
2733
2733
|
// src/components/data/FilterBar.tsx
|
|
2734
|
-
import * as
|
|
2734
|
+
import * as React25 from "react";
|
|
2735
2735
|
|
|
2736
2736
|
// src/components/forms/NumberInput.tsx
|
|
2737
|
-
import * as
|
|
2737
|
+
import * as React22 from "react";
|
|
2738
2738
|
|
|
2739
2739
|
// src/components/forms/field.tsx
|
|
2740
2740
|
import * as React20 from "react";
|
|
@@ -2755,6 +2755,16 @@ function useTriggerLabelling(label, id) {
|
|
|
2755
2755
|
return { fieldId, labelId, ariaLabelledBy: label ? labelId + " " + fieldId : void 0 };
|
|
2756
2756
|
}
|
|
2757
2757
|
|
|
2758
|
+
// src/components/useLatest.ts
|
|
2759
|
+
import * as React21 from "react";
|
|
2760
|
+
function useLatest(value) {
|
|
2761
|
+
const ref = React21.useRef(value);
|
|
2762
|
+
React21.useInsertionEffect(() => {
|
|
2763
|
+
ref.current = value;
|
|
2764
|
+
});
|
|
2765
|
+
return ref;
|
|
2766
|
+
}
|
|
2767
|
+
|
|
2758
2768
|
// src/components/forms/NumberInput.tsx
|
|
2759
2769
|
import { jsx as jsx42, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
2760
2770
|
var HOLD_DELAY_MS = 400;
|
|
@@ -2832,24 +2842,22 @@ function NumberInput({
|
|
|
2832
2842
|
const n = typeof v === "number" ? v : parseNumberText(v);
|
|
2833
2843
|
return n == null || Number.isNaN(n) ? null : n;
|
|
2834
2844
|
};
|
|
2835
|
-
const [text, setText] =
|
|
2836
|
-
const [editing, setEditing] =
|
|
2845
|
+
const [text, setText] = React22.useState(() => toText(value));
|
|
2846
|
+
const [editing, setEditing] = React22.useState(false);
|
|
2837
2847
|
const parsed = parseNumberText(text);
|
|
2838
2848
|
const invalidMessage = parsed == null ? null : Number.isNaN(parsed) ? "Enter a number" : integer && !Number.isInteger(parsed) ? "Enter a whole number" : parsed < lo ? "Must be \u2265 " + lo : parsed > hi ? "Must be \u2264 " + hi : null;
|
|
2839
2849
|
const valid = invalidMessage == null;
|
|
2840
|
-
const committedRef =
|
|
2841
|
-
const onChangeRef =
|
|
2842
|
-
|
|
2843
|
-
const
|
|
2844
|
-
|
|
2845
|
-
const focusedRef = React21.useRef(false);
|
|
2846
|
-
React21.useEffect(() => {
|
|
2850
|
+
const committedRef = React22.useRef(toNumber(value));
|
|
2851
|
+
const onChangeRef = useLatest(onChange);
|
|
2852
|
+
const onValidityChangeRef = useLatest(onValidityChange);
|
|
2853
|
+
const focusedRef = React22.useRef(false);
|
|
2854
|
+
React22.useEffect(() => {
|
|
2847
2855
|
committedRef.current = toNumber(value);
|
|
2848
2856
|
if (!focusedRef.current) setText(toText(value));
|
|
2849
2857
|
}, [value]);
|
|
2850
|
-
|
|
2858
|
+
React22.useLayoutEffect(() => {
|
|
2851
2859
|
onValidityChangeRef.current?.(valid);
|
|
2852
|
-
}, [valid]);
|
|
2860
|
+
}, [valid, onValidityChangeRef]);
|
|
2853
2861
|
const fire = (n) => {
|
|
2854
2862
|
committedRef.current = n ?? null;
|
|
2855
2863
|
onChangeRef.current?.({ target: { value: n } });
|
|
@@ -2862,9 +2870,8 @@ function NumberInput({
|
|
|
2862
2870
|
fire(next);
|
|
2863
2871
|
return true;
|
|
2864
2872
|
};
|
|
2865
|
-
const bumpRef =
|
|
2866
|
-
|
|
2867
|
-
const holdTimer = React21.useRef(null);
|
|
2873
|
+
const bumpRef = useLatest(bump);
|
|
2874
|
+
const holdTimer = React22.useRef(null);
|
|
2868
2875
|
const release = () => {
|
|
2869
2876
|
if (holdTimer.current) clearTimeout(holdTimer.current);
|
|
2870
2877
|
holdTimer.current = null;
|
|
@@ -2883,7 +2890,7 @@ function NumberInput({
|
|
|
2883
2890
|
};
|
|
2884
2891
|
holdTimer.current = setTimeout(tick, HOLD_DELAY_MS);
|
|
2885
2892
|
};
|
|
2886
|
-
|
|
2893
|
+
React22.useEffect(() => () => {
|
|
2887
2894
|
if (holdTimer.current) clearTimeout(holdTimer.current);
|
|
2888
2895
|
}, []);
|
|
2889
2896
|
const current2 = committedRef.current;
|
|
@@ -2986,7 +2993,7 @@ function NumberInput({
|
|
|
2986
2993
|
}
|
|
2987
2994
|
|
|
2988
2995
|
// src/components/forms/DatePicker.tsx
|
|
2989
|
-
import * as
|
|
2996
|
+
import * as React23 from "react";
|
|
2990
2997
|
import { jsx as jsx43, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
2991
2998
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
2992
2999
|
var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
@@ -3004,10 +3011,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3004
3011
|
const today = /* @__PURE__ */ new Date();
|
|
3005
3012
|
const sel = range ? value || {} : { start: value, end: value };
|
|
3006
3013
|
const anchor = parse(sel.start) || parse(initialMonth) || today;
|
|
3007
|
-
const [vy, setVy] =
|
|
3008
|
-
const [vm, setVm] =
|
|
3009
|
-
const [mode2, setMode] =
|
|
3010
|
-
const [hover, setHover] =
|
|
3014
|
+
const [vy, setVy] = React23.useState(anchor.getFullYear());
|
|
3015
|
+
const [vm, setVm] = React23.useState(anchor.getMonth());
|
|
3016
|
+
const [mode2, setMode] = React23.useState("days");
|
|
3017
|
+
const [hover, setHover] = React23.useState(null);
|
|
3011
3018
|
const s = parse(sel.start), e = parse(sel.end);
|
|
3012
3019
|
const hoverEnd = range && s && !e && hover ? parse(hover) : null;
|
|
3013
3020
|
const inRange = (d) => {
|
|
@@ -3123,9 +3130,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3123
3130
|
}
|
|
3124
3131
|
function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, ...rest }) {
|
|
3125
3132
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
3126
|
-
const [open, setOpen] =
|
|
3127
|
-
const rootRef =
|
|
3128
|
-
const boxRef =
|
|
3133
|
+
const [open, setOpen] = React23.useState(false);
|
|
3134
|
+
const rootRef = React23.useRef(null);
|
|
3135
|
+
const boxRef = React23.useRef(null);
|
|
3129
3136
|
const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
|
|
3130
3137
|
const toggle = () => {
|
|
3131
3138
|
if (!disabled) setOpen(!open);
|
|
@@ -3203,9 +3210,9 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
|
|
|
3203
3210
|
}
|
|
3204
3211
|
|
|
3205
3212
|
// src/components/forms/listbox.ts
|
|
3206
|
-
import * as
|
|
3213
|
+
import * as React24 from "react";
|
|
3207
3214
|
function useListboxNav({ count, onSelect }) {
|
|
3208
|
-
const [active, setActive] =
|
|
3215
|
+
const [active, setActive] = React24.useState(-1);
|
|
3209
3216
|
return {
|
|
3210
3217
|
active,
|
|
3211
3218
|
setActive,
|
|
@@ -3218,7 +3225,7 @@ function useListboxNav({ count, onSelect }) {
|
|
|
3218
3225
|
};
|
|
3219
3226
|
}
|
|
3220
3227
|
function useListboxScrollIntoView(active, listRef, enabled) {
|
|
3221
|
-
|
|
3228
|
+
React24.useEffect(() => {
|
|
3222
3229
|
if (!enabled || active < 0 || !listRef.current) return;
|
|
3223
3230
|
const list = listRef.current;
|
|
3224
3231
|
const el = list.querySelector('[data-i="' + active + '"]');
|
|
@@ -3405,40 +3412,40 @@ function MultiSelectPanel({
|
|
|
3405
3412
|
onClose
|
|
3406
3413
|
}) {
|
|
3407
3414
|
const allowedOps = operatorsFor(field);
|
|
3408
|
-
const [draftOperator, setDraftOperator] =
|
|
3415
|
+
const [draftOperator, setDraftOperator] = React25.useState(value?.operator ?? allowedOps[0]);
|
|
3409
3416
|
const operator = allowedOps.length === 1 ? allowedOps[0] : value?.operator ?? draftOperator;
|
|
3410
3417
|
const selected = value?.values ?? [];
|
|
3411
|
-
const selectedRef =
|
|
3412
|
-
|
|
3413
|
-
const
|
|
3414
|
-
|
|
3415
|
-
const mountedRef = React24.useRef(true);
|
|
3416
|
-
React24.useEffect(() => {
|
|
3418
|
+
const selectedRef = useLatest(selected);
|
|
3419
|
+
const operatorRef = useLatest(operator);
|
|
3420
|
+
const mountedRef = React25.useRef(true);
|
|
3421
|
+
React25.useEffect(() => {
|
|
3417
3422
|
mountedRef.current = true;
|
|
3418
3423
|
return () => {
|
|
3419
3424
|
mountedRef.current = false;
|
|
3420
3425
|
};
|
|
3421
3426
|
}, []);
|
|
3422
|
-
const commit = (nextValues, nextOperator =
|
|
3427
|
+
const commit = (nextValues, nextOperator = operatorRef.current) => {
|
|
3428
|
+
setDraftOperator(nextOperator);
|
|
3429
|
+
return onCommit({ operator: nextOperator, values: nextValues });
|
|
3430
|
+
};
|
|
3423
3431
|
const setOperator = (op) => {
|
|
3424
|
-
setDraftOperator(op);
|
|
3425
3432
|
if (selectedRef.current.length > 0) commit(selectedRef.current, op);
|
|
3433
|
+
else setDraftOperator(op);
|
|
3426
3434
|
};
|
|
3427
|
-
const [mode2, setMode] =
|
|
3428
|
-
const [query, setQuery] =
|
|
3429
|
-
const [asyncState, setAsyncState] =
|
|
3435
|
+
const [mode2, setMode] = React25.useState("search");
|
|
3436
|
+
const [query, setQuery] = React25.useState("");
|
|
3437
|
+
const [asyncState, setAsyncState] = React25.useState(
|
|
3430
3438
|
{ options: null, loading: !!field.loadOptions, error: false }
|
|
3431
3439
|
);
|
|
3432
|
-
const [retryTick, setRetryTick] =
|
|
3433
|
-
const inputRef =
|
|
3434
|
-
const listRef =
|
|
3435
|
-
const listId =
|
|
3436
|
-
const loadOptionsRef =
|
|
3437
|
-
|
|
3438
|
-
React24.useEffect(() => {
|
|
3440
|
+
const [retryTick, setRetryTick] = React25.useState(0);
|
|
3441
|
+
const inputRef = React25.useRef(null);
|
|
3442
|
+
const listRef = React25.useRef(null);
|
|
3443
|
+
const listId = React25.useId();
|
|
3444
|
+
const loadOptionsRef = useLatest(field.loadOptions);
|
|
3445
|
+
React25.useEffect(() => {
|
|
3439
3446
|
inputRef.current?.focus();
|
|
3440
3447
|
}, []);
|
|
3441
|
-
|
|
3448
|
+
React25.useEffect(() => {
|
|
3442
3449
|
const load = loadOptionsRef.current;
|
|
3443
3450
|
if (!load) return;
|
|
3444
3451
|
const controller = new AbortController();
|
|
@@ -3456,7 +3463,7 @@ function MultiSelectPanel({
|
|
|
3456
3463
|
clearTimeout(t);
|
|
3457
3464
|
controller.abort();
|
|
3458
3465
|
};
|
|
3459
|
-
}, [query, retryTick]);
|
|
3466
|
+
}, [query, retryTick, loadOptionsRef]);
|
|
3460
3467
|
const options = field.loadOptions ? asyncState.options ?? [] : (field.options ?? []).filter((o) => o.label.toLowerCase().includes(query.toLowerCase()));
|
|
3461
3468
|
const showLoading = !!field.loadOptions && asyncState.loading;
|
|
3462
3469
|
const showError = !!field.loadOptions && asyncState.error;
|
|
@@ -3471,19 +3478,24 @@ function MultiSelectPanel({
|
|
|
3471
3478
|
};
|
|
3472
3479
|
const nav = useListboxNav({ count: options.length, onSelect: (i) => toggle(options[i]) });
|
|
3473
3480
|
useListboxScrollIntoView(nav.active, listRef, hasListbox);
|
|
3474
|
-
|
|
3481
|
+
React25.useEffect(() => {
|
|
3475
3482
|
nav.setActive(0);
|
|
3476
3483
|
}, [query, options.length]);
|
|
3477
3484
|
const activeId = hasListbox && options[nav.active] ? listId + "-opt-" + nav.active : void 0;
|
|
3478
3485
|
const liveMessage = showLoading ? "Loading\u2026" : showError ? "Couldn't load options." : options.length === 0 ? "No matches" : atLimit ? "Limit reached: at most " + field.maxValues + " values" : "";
|
|
3479
|
-
const [pasteText, setPasteText] =
|
|
3480
|
-
const [pasteLoading, setPasteLoading] =
|
|
3481
|
-
const [unmatchedTokens, setUnmatchedTokens] =
|
|
3482
|
-
const [pasteError, setPasteError] =
|
|
3483
|
-
const pasteWrapRef =
|
|
3484
|
-
|
|
3486
|
+
const [pasteText, setPasteText] = React25.useState("");
|
|
3487
|
+
const [pasteLoading, setPasteLoading] = React25.useState(false);
|
|
3488
|
+
const [unmatchedTokens, setUnmatchedTokens] = React25.useState([]);
|
|
3489
|
+
const [pasteError, setPasteError] = React25.useState(null);
|
|
3490
|
+
const pasteWrapRef = React25.useRef(null);
|
|
3491
|
+
const [resolvedAt, setResolvedAt] = React25.useState(0);
|
|
3492
|
+
React25.useEffect(() => {
|
|
3485
3493
|
if (mode2 === "paste") pasteWrapRef.current?.querySelector("textarea")?.focus();
|
|
3486
3494
|
}, [mode2]);
|
|
3495
|
+
React25.useLayoutEffect(() => {
|
|
3496
|
+
if (resolvedAt === 0) return;
|
|
3497
|
+
pasteWrapRef.current?.querySelector("textarea")?.focus();
|
|
3498
|
+
}, [resolvedAt]);
|
|
3487
3499
|
const doResolve = () => {
|
|
3488
3500
|
if (!field.resolve) return;
|
|
3489
3501
|
const tokens = Array.from(new Set(pasteText.split(/[\n,]/).map((t) => t.trim()).filter(Boolean)));
|
|
@@ -3500,12 +3512,13 @@ function MultiSelectPanel({
|
|
|
3500
3512
|
setPasteError("This filter allows at most " + field.maxValues + " values; adding this list would make " + merged.size + ".");
|
|
3501
3513
|
return;
|
|
3502
3514
|
}
|
|
3503
|
-
const applied = commit(Array.from(merged.values())
|
|
3515
|
+
const applied = commit(Array.from(merged.values()));
|
|
3504
3516
|
if (!applied.ok) {
|
|
3505
3517
|
setPasteError(applied.reason);
|
|
3506
3518
|
return;
|
|
3507
3519
|
}
|
|
3508
3520
|
setPasteText("");
|
|
3521
|
+
setResolvedAt((n) => n + 1);
|
|
3509
3522
|
}, (err) => {
|
|
3510
3523
|
if (!mountedRef.current) return;
|
|
3511
3524
|
setPasteLoading(false);
|
|
@@ -3642,10 +3655,9 @@ function MultiSelectPanel({
|
|
|
3642
3655
|
);
|
|
3643
3656
|
}
|
|
3644
3657
|
function useTextValidity(onFlip) {
|
|
3645
|
-
const invalidRef =
|
|
3646
|
-
const [, rerender] =
|
|
3647
|
-
const onFlipRef =
|
|
3648
|
-
onFlipRef.current = onFlip;
|
|
3658
|
+
const invalidRef = React25.useRef(/* @__PURE__ */ new Set());
|
|
3659
|
+
const [, rerender] = React25.useReducer((n) => n + 1, 0);
|
|
3660
|
+
const onFlipRef = useLatest(onFlip);
|
|
3649
3661
|
const record = (name, valid) => {
|
|
3650
3662
|
const invalid = invalidRef.current;
|
|
3651
3663
|
if (valid !== invalid.has(name)) return false;
|
|
@@ -3662,6 +3674,12 @@ function useTextValidity(onFlip) {
|
|
|
3662
3674
|
/** For an input that is about to unmount: it has nothing left to show. */
|
|
3663
3675
|
forget: (name) => {
|
|
3664
3676
|
record(name, true);
|
|
3677
|
+
},
|
|
3678
|
+
/** For a panel that is about to remount every input: each reports afresh on mount. */
|
|
3679
|
+
reset: () => {
|
|
3680
|
+
if (invalidRef.current.size === 0) return;
|
|
3681
|
+
invalidRef.current.clear();
|
|
3682
|
+
rerender();
|
|
3665
3683
|
}
|
|
3666
3684
|
};
|
|
3667
3685
|
}
|
|
@@ -3669,6 +3687,40 @@ function applicable(field, candidate, textValid) {
|
|
|
3669
3687
|
if (!textValid || candidate === void 0) return void 0;
|
|
3670
3688
|
return validateFilterValue(field, candidate).ok ? candidate : void 0;
|
|
3671
3689
|
}
|
|
3690
|
+
function sameValue(a, b) {
|
|
3691
|
+
if (a === b) return true;
|
|
3692
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
|
|
3693
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
3694
|
+
const left = a;
|
|
3695
|
+
const right = b;
|
|
3696
|
+
for (const key of /* @__PURE__ */ new Set([...Object.keys(left), ...Object.keys(right)])) {
|
|
3697
|
+
if (!sameValue(left[key], right[key])) return false;
|
|
3698
|
+
}
|
|
3699
|
+
return true;
|
|
3700
|
+
}
|
|
3701
|
+
function useReseedFromProps(value, applies, reseed) {
|
|
3702
|
+
const seen = React25.useRef(value);
|
|
3703
|
+
React25.useLayoutEffect(() => {
|
|
3704
|
+
if (seen.current === value) return;
|
|
3705
|
+
seen.current = value;
|
|
3706
|
+
if (!sameValue(value, applies())) reseed(value);
|
|
3707
|
+
}, [value, applies, reseed]);
|
|
3708
|
+
}
|
|
3709
|
+
function usePreserveFocusAcrossRemount(seed) {
|
|
3710
|
+
const pendingId = React25.useRef(null);
|
|
3711
|
+
const capture = (ids) => {
|
|
3712
|
+
const active = document.activeElement;
|
|
3713
|
+
pendingId.current = active instanceof HTMLElement && ids.includes(active.id) ? active.id : null;
|
|
3714
|
+
};
|
|
3715
|
+
React25.useLayoutEffect(() => {
|
|
3716
|
+
const id = pendingId.current;
|
|
3717
|
+
if (!id) return;
|
|
3718
|
+
pendingId.current = null;
|
|
3719
|
+
document.getElementById(id)?.focus();
|
|
3720
|
+
}, [seed]);
|
|
3721
|
+
return capture;
|
|
3722
|
+
}
|
|
3723
|
+
var rangeDraft = (value) => ({ min: value?.min, max: value?.max });
|
|
3672
3724
|
function RangePanel({
|
|
3673
3725
|
field,
|
|
3674
3726
|
value,
|
|
@@ -3676,13 +3728,27 @@ function RangePanel({
|
|
|
3676
3728
|
onCommit,
|
|
3677
3729
|
onClose
|
|
3678
3730
|
}) {
|
|
3679
|
-
const [draft, setDraft] =
|
|
3680
|
-
const
|
|
3681
|
-
const
|
|
3731
|
+
const [draft, setDraft] = React25.useState(() => rangeDraft(value));
|
|
3732
|
+
const [seed, setSeed] = React25.useState(0);
|
|
3733
|
+
const preserveFocus = usePreserveFocusAcrossRemount(seed);
|
|
3734
|
+
const minId = field.key + "-min";
|
|
3735
|
+
const maxId = field.key + "-max";
|
|
3736
|
+
const draftRef = React25.useRef(draft);
|
|
3737
|
+
const shown = () => {
|
|
3682
3738
|
const { min, max } = draftRef.current;
|
|
3683
|
-
|
|
3739
|
+
return applicable(field, min == null && max == null ? void 0 : { min, max }, validity.allValid());
|
|
3740
|
+
};
|
|
3741
|
+
const publish = () => {
|
|
3742
|
+
onCommit(shown());
|
|
3684
3743
|
};
|
|
3685
3744
|
const validity = useTextValidity(publish);
|
|
3745
|
+
useReseedFromProps(value, shown, (next) => {
|
|
3746
|
+
preserveFocus([minId, maxId]);
|
|
3747
|
+
draftRef.current = rangeDraft(next);
|
|
3748
|
+
setDraft(draftRef.current);
|
|
3749
|
+
validity.reset();
|
|
3750
|
+
setSeed((n) => n + 1);
|
|
3751
|
+
});
|
|
3686
3752
|
const draftMin = draft.min;
|
|
3687
3753
|
const draftMax = draft.max;
|
|
3688
3754
|
const isEmpty = draftMin == null && draftMax == null;
|
|
@@ -3710,6 +3776,7 @@ function RangePanel({
|
|
|
3710
3776
|
/* @__PURE__ */ jsx45(
|
|
3711
3777
|
NumberInput,
|
|
3712
3778
|
{
|
|
3779
|
+
id: minId,
|
|
3713
3780
|
label: field.minLabel || "At least",
|
|
3714
3781
|
value: draftMin ?? "",
|
|
3715
3782
|
min: field.min,
|
|
@@ -3719,11 +3786,13 @@ function RangePanel({
|
|
|
3719
3786
|
placeholder: field.minPlaceholder,
|
|
3720
3787
|
onChange: (e) => apply({ min: e.target.value }),
|
|
3721
3788
|
onValidityChange: validity.report("min")
|
|
3722
|
-
}
|
|
3789
|
+
},
|
|
3790
|
+
"min-" + seed
|
|
3723
3791
|
),
|
|
3724
3792
|
/* @__PURE__ */ jsx45(
|
|
3725
3793
|
NumberInput,
|
|
3726
3794
|
{
|
|
3795
|
+
id: maxId,
|
|
3727
3796
|
label: field.maxLabel || "At most",
|
|
3728
3797
|
value: draftMax ?? "",
|
|
3729
3798
|
min: field.min,
|
|
@@ -3734,12 +3803,20 @@ function RangePanel({
|
|
|
3734
3803
|
placeholder: field.maxPlaceholder,
|
|
3735
3804
|
onChange: (e) => apply({ max: e.target.value }),
|
|
3736
3805
|
onValidityChange: validity.report("max")
|
|
3737
|
-
}
|
|
3806
|
+
},
|
|
3807
|
+
"max-" + seed
|
|
3738
3808
|
)
|
|
3739
3809
|
] })
|
|
3740
3810
|
}
|
|
3741
3811
|
);
|
|
3742
3812
|
}
|
|
3813
|
+
function dateDraft(field, value) {
|
|
3814
|
+
return {
|
|
3815
|
+
kind: value?.kind ?? "withinDays",
|
|
3816
|
+
days: value?.kind === "withinDays" ? value.days : field.defaultDays ?? 30,
|
|
3817
|
+
between: value?.kind === "between" ? { from: value.from, to: value.to } : { from: "", to: "" }
|
|
3818
|
+
};
|
|
3819
|
+
}
|
|
3743
3820
|
function DatePanel({
|
|
3744
3821
|
field,
|
|
3745
3822
|
value,
|
|
@@ -3747,23 +3824,44 @@ function DatePanel({
|
|
|
3747
3824
|
onCommit,
|
|
3748
3825
|
onClose
|
|
3749
3826
|
}) {
|
|
3750
|
-
const defaultDays = field.defaultDays ?? 30;
|
|
3751
3827
|
const maxDays = effectiveMaxDays(field);
|
|
3752
|
-
const [
|
|
3753
|
-
const [
|
|
3754
|
-
|
|
3755
|
-
);
|
|
3756
|
-
const
|
|
3757
|
-
const [between, setBetween] =
|
|
3758
|
-
|
|
3759
|
-
);
|
|
3828
|
+
const [initial] = React25.useState(() => dateDraft(field, value));
|
|
3829
|
+
const [kind, setKind] = React25.useState(initial.kind);
|
|
3830
|
+
const [daysDraft, setDaysDraft] = React25.useState(initial.days);
|
|
3831
|
+
const daysRef = React25.useRef(daysDraft);
|
|
3832
|
+
const daysConfirmed = React25.useRef(value?.kind === "withinDays");
|
|
3833
|
+
const [between, setBetween] = React25.useState(initial.between);
|
|
3834
|
+
const [seed, setSeed] = React25.useState(0);
|
|
3835
|
+
const preserveFocus = usePreserveFocusAcrossRemount(seed);
|
|
3836
|
+
const daysId = field.key + "-days";
|
|
3760
3837
|
const shownWithinDays = () => {
|
|
3761
3838
|
const days = daysRef.current;
|
|
3762
3839
|
return applicable(field, days == null ? void 0 : { kind: "withinDays", days }, validity.allValid());
|
|
3763
3840
|
};
|
|
3764
|
-
const validity = useTextValidity(() =>
|
|
3841
|
+
const validity = useTextValidity(() => {
|
|
3842
|
+
daysConfirmed.current = true;
|
|
3843
|
+
onCommit(shownWithinDays());
|
|
3844
|
+
});
|
|
3845
|
+
const applies = () => {
|
|
3846
|
+
if (kind === "between") {
|
|
3847
|
+
return applicable(field, between.from && between.to ? { kind: "between", ...between } : void 0, true);
|
|
3848
|
+
}
|
|
3849
|
+
return daysConfirmed.current ? shownWithinDays() : void 0;
|
|
3850
|
+
};
|
|
3851
|
+
useReseedFromProps(value, applies, (next) => {
|
|
3852
|
+
preserveFocus([daysId]);
|
|
3853
|
+
const d = dateDraft(field, next);
|
|
3854
|
+
setKind(d.kind);
|
|
3855
|
+
daysRef.current = d.days;
|
|
3856
|
+
daysConfirmed.current = next?.kind === "withinDays";
|
|
3857
|
+
setDaysDraft(d.days);
|
|
3858
|
+
setBetween(d.between);
|
|
3859
|
+
validity.reset();
|
|
3860
|
+
setSeed((n) => n + 1);
|
|
3861
|
+
});
|
|
3765
3862
|
const applyWithinDays = (days) => {
|
|
3766
3863
|
daysRef.current = days;
|
|
3864
|
+
daysConfirmed.current = true;
|
|
3767
3865
|
setDaysDraft(days);
|
|
3768
3866
|
onCommit(shownWithinDays());
|
|
3769
3867
|
};
|
|
@@ -3778,8 +3876,10 @@ function DatePanel({
|
|
|
3778
3876
|
setBetween({ from: "", to: "" });
|
|
3779
3877
|
validity.forget("days");
|
|
3780
3878
|
} else {
|
|
3781
|
-
|
|
3782
|
-
|
|
3879
|
+
const { days } = dateDraft(field, void 0);
|
|
3880
|
+
daysRef.current = days;
|
|
3881
|
+
daysConfirmed.current = false;
|
|
3882
|
+
setDaysDraft(days);
|
|
3783
3883
|
}
|
|
3784
3884
|
onCommit(void 0);
|
|
3785
3885
|
};
|
|
@@ -3819,6 +3919,7 @@ function DatePanel({
|
|
|
3819
3919
|
kind === "withinDays" ? /* @__PURE__ */ jsx45(
|
|
3820
3920
|
NumberInput,
|
|
3821
3921
|
{
|
|
3922
|
+
id: daysId,
|
|
3822
3923
|
label: "Days",
|
|
3823
3924
|
min: 1,
|
|
3824
3925
|
max: maxDays,
|
|
@@ -3827,7 +3928,8 @@ function DatePanel({
|
|
|
3827
3928
|
value: daysDraft ?? "",
|
|
3828
3929
|
onChange: (e) => applyWithinDays(e.target.value),
|
|
3829
3930
|
onValidityChange: validity.report("days")
|
|
3830
|
-
}
|
|
3931
|
+
},
|
|
3932
|
+
"days-" + seed
|
|
3831
3933
|
) : /* @__PURE__ */ jsx45(
|
|
3832
3934
|
DatePicker,
|
|
3833
3935
|
{
|
|
@@ -3835,30 +3937,23 @@ function DatePanel({
|
|
|
3835
3937
|
label: "Date range",
|
|
3836
3938
|
value: { start: between.from, end: between.to },
|
|
3837
3939
|
onChange: (e) => applyBetween(e.target.value.start || "", e.target.value.end || "")
|
|
3838
|
-
}
|
|
3940
|
+
},
|
|
3941
|
+
"between-" + seed
|
|
3839
3942
|
)
|
|
3840
3943
|
] })
|
|
3841
3944
|
}
|
|
3842
3945
|
);
|
|
3843
3946
|
}
|
|
3844
3947
|
function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align = "left", className = "", ...rest }) {
|
|
3845
|
-
const [panel, setPanel] =
|
|
3846
|
-
const editAnchorRef =
|
|
3847
|
-
const addAnchorRef =
|
|
3848
|
-
const textInputRef =
|
|
3849
|
-
const optionsRef =
|
|
3948
|
+
const [panel, setPanel] = React25.useState(null);
|
|
3949
|
+
const editAnchorRef = React25.useRef(null);
|
|
3950
|
+
const addAnchorRef = React25.useRef(null);
|
|
3951
|
+
const textInputRef = React25.useRef(null);
|
|
3952
|
+
const optionsRef = React25.useRef(null);
|
|
3850
3953
|
if (process.env.NODE_ENV !== "production") {
|
|
3851
3954
|
for (const f of fields) assertValidFieldDefinition(f);
|
|
3852
3955
|
}
|
|
3853
|
-
const latest =
|
|
3854
|
-
const filtersProp = React24.useRef(filters);
|
|
3855
|
-
if (filters !== filtersProp.current) {
|
|
3856
|
-
filtersProp.current = filters;
|
|
3857
|
-
latest.current.filters = filters;
|
|
3858
|
-
}
|
|
3859
|
-
latest.current.fields = fields;
|
|
3860
|
-
latest.current.onFilterChange = onFilterChange;
|
|
3861
|
-
latest.current.onFilterRemove = onFilterRemove;
|
|
3956
|
+
const latest = useLatest({ fields, filters, onFilterChange, onFilterRemove });
|
|
3862
3957
|
const commit = (field, candidate) => {
|
|
3863
3958
|
const current2 = latest.current.fields.find((f) => f.key === field.key);
|
|
3864
3959
|
if (!current2) return { ok: false, reason: "This filter is no longer available" };
|
|
@@ -3867,24 +3962,17 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
3867
3962
|
return { ok: true };
|
|
3868
3963
|
}
|
|
3869
3964
|
const result = validateFilterValue(current2, candidate);
|
|
3870
|
-
if (result.ok)
|
|
3871
|
-
latest.current.filters = { ...latest.current.filters, [current2.key]: candidate };
|
|
3872
|
-
latest.current.onFilterChange(current2.key, candidate);
|
|
3873
|
-
}
|
|
3965
|
+
if (result.ok) latest.current.onFilterChange(current2.key, candidate);
|
|
3874
3966
|
return result;
|
|
3875
3967
|
};
|
|
3876
3968
|
const removeField = (field) => {
|
|
3877
3969
|
const { filters: now, onFilterRemove: remove } = latest.current;
|
|
3878
|
-
if (
|
|
3879
|
-
const next = { ...now };
|
|
3880
|
-
delete next[field.key];
|
|
3881
|
-
latest.current.filters = next;
|
|
3882
|
-
remove(field.key);
|
|
3970
|
+
if (isFieldSet(field, now[field.key])) remove(field.key);
|
|
3883
3971
|
};
|
|
3884
3972
|
const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
|
|
3885
3973
|
const startEditing = (key) => setPanel({ kind: "edit", key });
|
|
3886
3974
|
const closeEditing = () => setPanel(null);
|
|
3887
|
-
|
|
3975
|
+
React25.useEffect(() => {
|
|
3888
3976
|
if (!panel || panel.kind !== "edit") return;
|
|
3889
3977
|
if (editingField?.type === "text") {
|
|
3890
3978
|
textInputRef.current?.focus();
|
|
@@ -4090,7 +4178,7 @@ function StatTile({ label, value, sub, delta, invert = false, loading = false, c
|
|
|
4090
4178
|
}
|
|
4091
4179
|
|
|
4092
4180
|
// src/components/data/CodeBlock.tsx
|
|
4093
|
-
import * as
|
|
4181
|
+
import * as React26 from "react";
|
|
4094
4182
|
import { Fragment as Fragment6, jsx as jsx47, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
4095
4183
|
var JS_KW = /^(?:const|let|var|function|return|if|else|for|while|do|new|class|extends|import|from|export|default|await|async|try|catch|finally|throw|typeof|instanceof|of|in|switch|case|break|continue|delete|void|yield|static|get|set|this|super|interface|type|enum|implements|public|private|protected|readonly|abstract|as|satisfies|declare|namespace)$/;
|
|
4096
4184
|
var RULES = {
|
|
@@ -4246,13 +4334,13 @@ function tokenize(src, lang) {
|
|
|
4246
4334
|
return out;
|
|
4247
4335
|
}
|
|
4248
4336
|
function Highlighted({ code, lang }) {
|
|
4249
|
-
const toks =
|
|
4337
|
+
const toks = React26.useMemo(() => tokenize(code, lang), [code, lang]);
|
|
4250
4338
|
return /* @__PURE__ */ jsx47(Fragment6, { children: toks.map((tk, i) => tk.c ? /* @__PURE__ */ jsx47("span", { className: "tok-" + tk.c, children: tk.t }, i) : tk.t) });
|
|
4251
4339
|
}
|
|
4252
4340
|
function useCopy() {
|
|
4253
|
-
const [done, setDone] =
|
|
4254
|
-
const timer =
|
|
4255
|
-
|
|
4341
|
+
const [done, setDone] = React26.useState(false);
|
|
4342
|
+
const timer = React26.useRef(null);
|
|
4343
|
+
React26.useEffect(() => () => {
|
|
4256
4344
|
if (timer.current) clearTimeout(timer.current);
|
|
4257
4345
|
}, []);
|
|
4258
4346
|
const copy = (text) => {
|
|
@@ -4288,8 +4376,8 @@ function CodeBlock({
|
|
|
4288
4376
|
actions,
|
|
4289
4377
|
className = ""
|
|
4290
4378
|
}) {
|
|
4291
|
-
const [wrap, setWrap] =
|
|
4292
|
-
const [open, setOpen] =
|
|
4379
|
+
const [wrap, setWrap] = React26.useState(!!wrapDefault);
|
|
4380
|
+
const [open, setOpen] = React26.useState(false);
|
|
4293
4381
|
const [copied, copy] = useCopy();
|
|
4294
4382
|
const body = String(code).replace(/\n$/, "");
|
|
4295
4383
|
const lines = body.split("\n");
|
|
@@ -4318,7 +4406,7 @@ function CodeBlock({
|
|
|
4318
4406
|
] });
|
|
4319
4407
|
}
|
|
4320
4408
|
function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
|
|
4321
|
-
const [open, setOpen] =
|
|
4409
|
+
const [open, setOpen] = React26.useState(false);
|
|
4322
4410
|
const [copied, copy] = useCopy();
|
|
4323
4411
|
const raw = String(diff).replace(/\n$/, "");
|
|
4324
4412
|
const all = raw.split("\n").map((line) => {
|
|
@@ -4364,7 +4452,7 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
|
|
|
4364
4452
|
}
|
|
4365
4453
|
|
|
4366
4454
|
// src/components/data/Markdown.tsx
|
|
4367
|
-
import * as
|
|
4455
|
+
import * as React27 from "react";
|
|
4368
4456
|
import { jsx as jsx48, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
4369
4457
|
var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
|
|
4370
4458
|
var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
|
|
@@ -4403,7 +4491,7 @@ function inlineNodes(src, ctx, keyBase) {
|
|
|
4403
4491
|
const href = safeHref(g(2));
|
|
4404
4492
|
out.push(href ? /* @__PURE__ */ jsx48("a", { href, title: g(3) || void 0, target: /^https?:/i.test(href) ? "_blank" : void 0, rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: inlineNodes(g(1), ctx, key()) }, key()) : /* @__PURE__ */ jsx48("span", { children: g(1) }, key()));
|
|
4405
4493
|
} else if (kind === "cite") {
|
|
4406
|
-
out.push(ctx.renderCitation ? /* @__PURE__ */ jsx48(
|
|
4494
|
+
out.push(ctx.renderCitation ? /* @__PURE__ */ jsx48(React27.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ jsx48("sup", { className: "fd-md-cite", children: g(1) }, key()));
|
|
4407
4495
|
} else if (kind === "strongem") out.push(/* @__PURE__ */ jsx48("strong", { children: /* @__PURE__ */ jsx48("em", { children: inlineNodes(g(1), ctx, key()) }) }, key()));
|
|
4408
4496
|
else if (kind === "strong") out.push(/* @__PURE__ */ jsx48("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
4409
4497
|
else if (kind === "em") out.push(/* @__PURE__ */ jsx48("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
@@ -4568,7 +4656,7 @@ function Markdown({
|
|
|
4568
4656
|
onLinkClick
|
|
4569
4657
|
}) {
|
|
4570
4658
|
const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
|
|
4571
|
-
const blocks =
|
|
4659
|
+
const blocks = React27.useMemo(() => parseBlocks(source), [source]);
|
|
4572
4660
|
return /* @__PURE__ */ jsx48("div", { className: ["fd-md", className].filter(Boolean).join(" "), children: renderBlocks(blocks, ctx, "b") });
|
|
4573
4661
|
}
|
|
4574
4662
|
function MarkdownInline({ source = "", className = "", onLinkClick }) {
|
|
@@ -4682,7 +4770,7 @@ function Pagination({
|
|
|
4682
4770
|
}
|
|
4683
4771
|
|
|
4684
4772
|
// src/components/data/RelativeTime.tsx
|
|
4685
|
-
import * as
|
|
4773
|
+
import * as React28 from "react";
|
|
4686
4774
|
import { jsxs as jsxs45 } from "react/jsx-runtime";
|
|
4687
4775
|
var MIN = 6e4;
|
|
4688
4776
|
var HOUR = 36e5;
|
|
@@ -4734,9 +4822,9 @@ function formatDuration(ms) {
|
|
|
4734
4822
|
return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
|
|
4735
4823
|
}
|
|
4736
4824
|
function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
|
|
4737
|
-
const [, force] =
|
|
4825
|
+
const [, force] = React28.useState(0);
|
|
4738
4826
|
const t = value instanceof Date ? value.getTime() : Date.parse(value);
|
|
4739
|
-
|
|
4827
|
+
React28.useEffect(() => {
|
|
4740
4828
|
if (!refresh2 || !t || isNaN(t)) return;
|
|
4741
4829
|
const abs = Math.abs(t - Date.now());
|
|
4742
4830
|
if (abs > DAY) return;
|
|
@@ -4752,7 +4840,7 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
|
|
|
4752
4840
|
}
|
|
4753
4841
|
|
|
4754
4842
|
// src/components/data/ScoreMeter.tsx
|
|
4755
|
-
import * as
|
|
4843
|
+
import * as React29 from "react";
|
|
4756
4844
|
import { jsx as jsx51, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
4757
4845
|
function ScoreMeter({
|
|
4758
4846
|
score,
|
|
@@ -4767,10 +4855,10 @@ function ScoreMeter({
|
|
|
4767
4855
|
breakdownWidth = 280,
|
|
4768
4856
|
className = ""
|
|
4769
4857
|
}) {
|
|
4770
|
-
const [open, setOpen] =
|
|
4771
|
-
const ref =
|
|
4858
|
+
const [open, setOpen] = React29.useState(false);
|
|
4859
|
+
const ref = React29.useRef(null);
|
|
4772
4860
|
const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
|
|
4773
|
-
const body = /* @__PURE__ */ jsxs46(
|
|
4861
|
+
const body = /* @__PURE__ */ jsxs46(React29.Fragment, { children: [
|
|
4774
4862
|
/* @__PURE__ */ jsx51("span", { className: "fd-scoremeter-rail", style: { width }, "aria-hidden": "true", children: /* @__PURE__ */ jsx51(SegmentedMeter, { total: 100, segments, height, showTotal: false, showPercent: false, legend: false }) }),
|
|
4775
4863
|
showScore ? /* @__PURE__ */ jsx51("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
|
|
4776
4864
|
] });
|
|
@@ -4789,7 +4877,7 @@ function ScoreMeter({
|
|
|
4789
4877
|
}
|
|
4790
4878
|
);
|
|
4791
4879
|
}
|
|
4792
|
-
return /* @__PURE__ */ jsxs46(
|
|
4880
|
+
return /* @__PURE__ */ jsxs46(React29.Fragment, { children: [
|
|
4793
4881
|
/* @__PURE__ */ jsx51(
|
|
4794
4882
|
"button",
|
|
4795
4883
|
{
|
|
@@ -4820,13 +4908,13 @@ function ScoreMeter({
|
|
|
4820
4908
|
}
|
|
4821
4909
|
|
|
4822
4910
|
// src/components/data/SortMenu.tsx
|
|
4823
|
-
import * as
|
|
4911
|
+
import * as React30 from "react";
|
|
4824
4912
|
import { jsx as jsx52, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
4825
4913
|
function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", className = "", ...rest }) {
|
|
4826
|
-
const [open, setOpen] =
|
|
4914
|
+
const [open, setOpen] = React30.useState(false);
|
|
4827
4915
|
const zIndex = useOverlayLayer(open);
|
|
4828
|
-
const ref =
|
|
4829
|
-
|
|
4916
|
+
const ref = React30.useRef(null);
|
|
4917
|
+
React30.useEffect(() => {
|
|
4830
4918
|
if (!open) return;
|
|
4831
4919
|
const away = (e) => {
|
|
4832
4920
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -4888,7 +4976,7 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
|
|
|
4888
4976
|
}
|
|
4889
4977
|
|
|
4890
4978
|
// src/components/data/StepList.tsx
|
|
4891
|
-
import * as
|
|
4979
|
+
import * as React31 from "react";
|
|
4892
4980
|
import { jsx as jsx53, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
4893
4981
|
var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
|
|
4894
4982
|
function StepList({
|
|
@@ -4901,9 +4989,9 @@ function StepList({
|
|
|
4901
4989
|
dense = false,
|
|
4902
4990
|
className = ""
|
|
4903
4991
|
}) {
|
|
4904
|
-
const [openState, setOpenState] =
|
|
4992
|
+
const [openState, setOpenState] = React31.useState(defaultOpen);
|
|
4905
4993
|
const open = openProp == null ? openState : openProp;
|
|
4906
|
-
const [expanded, setExpanded] =
|
|
4994
|
+
const [expanded, setExpanded] = React31.useState({});
|
|
4907
4995
|
if (!steps.length) return null;
|
|
4908
4996
|
const running = steps.some((s) => s.status === "running");
|
|
4909
4997
|
const failed = steps.filter((s) => s.status === "error").length;
|
|
@@ -4961,7 +5049,7 @@ function StepList({
|
|
|
4961
5049
|
}
|
|
4962
5050
|
|
|
4963
5051
|
// src/components/data/VirtualList.tsx
|
|
4964
|
-
import * as
|
|
5052
|
+
import * as React32 from "react";
|
|
4965
5053
|
import { jsx as jsx54, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
4966
5054
|
var VIRTUAL_LIST_BUFFER_ROWS = 20;
|
|
4967
5055
|
var VIRTUAL_LIST_ROW_GAP = 6;
|
|
@@ -5013,35 +5101,35 @@ function VirtualList({
|
|
|
5013
5101
|
className = "",
|
|
5014
5102
|
style
|
|
5015
5103
|
}) {
|
|
5016
|
-
const [scrollTop, setScrollTop] =
|
|
5017
|
-
const loaded =
|
|
5104
|
+
const [scrollTop, setScrollTop] = React32.useState(0);
|
|
5105
|
+
const loaded = React32.useMemo(
|
|
5018
5106
|
() => ({ firstItemIndex, count: items.length }),
|
|
5019
5107
|
[firstItemIndex, items.length]
|
|
5020
5108
|
);
|
|
5021
5109
|
const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
|
|
5022
5110
|
const bandKey = firstItemIndex + ":" + items.length;
|
|
5023
|
-
const win =
|
|
5111
|
+
const win = React32.useMemo(
|
|
5024
5112
|
() => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
|
|
5025
5113
|
[scrollTop, height, itemHeight, total, loaded]
|
|
5026
5114
|
);
|
|
5027
|
-
const need =
|
|
5115
|
+
const need = React32.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
|
|
5028
5116
|
const wantStart = need.start && hasMore?.start !== false;
|
|
5029
5117
|
const wantEnd = need.end && hasMore?.end !== false;
|
|
5030
5118
|
const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
|
|
5031
5119
|
const askKey = bandKey + "@" + bucket2;
|
|
5032
|
-
const asked =
|
|
5033
|
-
|
|
5120
|
+
const asked = React32.useRef({ start: null, end: null });
|
|
5121
|
+
React32.useEffect(() => {
|
|
5034
5122
|
if (loading || !wantStart || asked.current.start === askKey) return;
|
|
5035
5123
|
asked.current.start = askKey;
|
|
5036
5124
|
onNeedMore("start", win);
|
|
5037
5125
|
}, [wantStart, loading, askKey, onNeedMore, win]);
|
|
5038
|
-
|
|
5126
|
+
React32.useEffect(() => {
|
|
5039
5127
|
if (loading || !wantEnd || asked.current.end === askKey) return;
|
|
5040
5128
|
asked.current.end = askKey;
|
|
5041
5129
|
onNeedMore("end", win);
|
|
5042
5130
|
}, [wantEnd, loading, askKey, onNeedMore, win]);
|
|
5043
|
-
const lastKeysRef =
|
|
5044
|
-
const newKeys =
|
|
5131
|
+
const lastKeysRef = React32.useRef(null);
|
|
5132
|
+
const newKeys = React32.useMemo(() => {
|
|
5045
5133
|
const prev = lastKeysRef.current;
|
|
5046
5134
|
if (!prev) return /* @__PURE__ */ new Set();
|
|
5047
5135
|
const fresh = /* @__PURE__ */ new Set();
|
|
@@ -5051,7 +5139,7 @@ function VirtualList({
|
|
|
5051
5139
|
}
|
|
5052
5140
|
return fresh;
|
|
5053
5141
|
}, [items]);
|
|
5054
|
-
|
|
5142
|
+
React32.useEffect(() => {
|
|
5055
5143
|
lastKeysRef.current = new Set(items.map(keyOf));
|
|
5056
5144
|
}, [items]);
|
|
5057
5145
|
const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
|
|
@@ -5096,7 +5184,7 @@ function VirtualList({
|
|
|
5096
5184
|
}
|
|
5097
5185
|
|
|
5098
5186
|
// src/components/data/EntityRow.tsx
|
|
5099
|
-
import * as
|
|
5187
|
+
import * as React33 from "react";
|
|
5100
5188
|
import { jsx as jsx55, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
5101
5189
|
var ENTITY_ROW_METRIC_WIDTH = 74;
|
|
5102
5190
|
var METRIC_TONE_COLOR = {
|
|
@@ -5109,7 +5197,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
|
|
|
5109
5197
|
const key = m.id || m.label || i;
|
|
5110
5198
|
const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
|
|
5111
5199
|
const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
|
|
5112
|
-
const content = /* @__PURE__ */ jsxs50(
|
|
5200
|
+
const content = /* @__PURE__ */ jsxs50(React33.Fragment, { children: [
|
|
5113
5201
|
m.icon ? /* @__PURE__ */ jsx55("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
|
|
5114
5202
|
/* @__PURE__ */ jsx55("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
|
|
5115
5203
|
/* @__PURE__ */ jsx55("span", { className: "fd-sr", children: " " + m.label })
|
|
@@ -5201,7 +5289,7 @@ function EntityRow({
|
|
|
5201
5289
|
}
|
|
5202
5290
|
|
|
5203
5291
|
// src/components/data/TransferList.tsx
|
|
5204
|
-
import * as
|
|
5292
|
+
import * as React34 from "react";
|
|
5205
5293
|
import { createPortal as createPortal4 } from "react-dom";
|
|
5206
5294
|
|
|
5207
5295
|
// src/components/forms/Input.tsx
|
|
@@ -5307,12 +5395,12 @@ function TransferList({
|
|
|
5307
5395
|
listHeight = 440,
|
|
5308
5396
|
className = ""
|
|
5309
5397
|
}) {
|
|
5310
|
-
const [drag, setDrag] =
|
|
5311
|
-
const [dragOverSide, setDragOverSide] =
|
|
5312
|
-
const dragRef =
|
|
5313
|
-
const armedRef =
|
|
5314
|
-
const sideRefs =
|
|
5315
|
-
const hitTestSide =
|
|
5398
|
+
const [drag, setDrag] = React34.useState(null);
|
|
5399
|
+
const [dragOverSide, setDragOverSide] = React34.useState(null);
|
|
5400
|
+
const dragRef = React34.useRef(null);
|
|
5401
|
+
const armedRef = React34.useRef(null);
|
|
5402
|
+
const sideRefs = React34.useRef({ left: null, right: null });
|
|
5403
|
+
const hitTestSide = React34.useCallback((x, y) => {
|
|
5316
5404
|
for (const side of ["left", "right"]) {
|
|
5317
5405
|
const el = sideRefs.current[side];
|
|
5318
5406
|
if (!el) continue;
|
|
@@ -5321,7 +5409,7 @@ function TransferList({
|
|
|
5321
5409
|
}
|
|
5322
5410
|
return null;
|
|
5323
5411
|
}, []);
|
|
5324
|
-
const findItem =
|
|
5412
|
+
const findItem = React34.useCallback(
|
|
5325
5413
|
(side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
|
|
5326
5414
|
[left.items, right.items, keyOf]
|
|
5327
5415
|
);
|
|
@@ -5343,7 +5431,7 @@ function TransferList({
|
|
|
5343
5431
|
height: rect.height
|
|
5344
5432
|
};
|
|
5345
5433
|
};
|
|
5346
|
-
|
|
5434
|
+
React34.useEffect(() => {
|
|
5347
5435
|
const onMovePointer = (e) => {
|
|
5348
5436
|
const armed = armedRef.current;
|
|
5349
5437
|
if (!armed || e.pointerId !== armed.pointerId) return;
|
|
@@ -5396,7 +5484,7 @@ function TransferList({
|
|
|
5396
5484
|
window.removeEventListener("pointercancel", endDrag);
|
|
5397
5485
|
};
|
|
5398
5486
|
}, [hitTestSide, findItem, onMove]);
|
|
5399
|
-
|
|
5487
|
+
React34.useEffect(() => {
|
|
5400
5488
|
if (!drag || typeof document === "undefined") return;
|
|
5401
5489
|
const prev = document.body.style.userSelect;
|
|
5402
5490
|
document.body.style.userSelect = "none";
|
|
@@ -5504,11 +5592,11 @@ function TransferList({
|
|
|
5504
5592
|
}
|
|
5505
5593
|
|
|
5506
5594
|
// src/components/forms/Checkbox.tsx
|
|
5507
|
-
import * as
|
|
5595
|
+
import * as React35 from "react";
|
|
5508
5596
|
import { jsx as jsx59, jsxs as jsxs53 } from "react/jsx-runtime";
|
|
5509
5597
|
function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
|
|
5510
|
-
const ref =
|
|
5511
|
-
|
|
5598
|
+
const ref = React35.useRef(null);
|
|
5599
|
+
React35.useEffect(() => {
|
|
5512
5600
|
if (ref.current) ref.current.indeterminate = indeterminate;
|
|
5513
5601
|
}, [indeterminate]);
|
|
5514
5602
|
return /* @__PURE__ */ jsxs53("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
@@ -5552,7 +5640,7 @@ function Switch({ label, description, className = "", ...rest }) {
|
|
|
5552
5640
|
}
|
|
5553
5641
|
|
|
5554
5642
|
// src/components/forms/Select.tsx
|
|
5555
|
-
import * as
|
|
5643
|
+
import * as React36 from "react";
|
|
5556
5644
|
import { jsx as jsx62, jsxs as jsxs56 } from "react/jsx-runtime";
|
|
5557
5645
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
5558
5646
|
function Select({
|
|
@@ -5579,12 +5667,12 @@ function Select({
|
|
|
5579
5667
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
5580
5668
|
const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
|
|
5581
5669
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
5582
|
-
const [open, setOpen] =
|
|
5583
|
-
const [q, setQ] =
|
|
5584
|
-
const rootRef =
|
|
5585
|
-
const boxRef =
|
|
5586
|
-
const listRef =
|
|
5587
|
-
const typeBuf =
|
|
5670
|
+
const [open, setOpen] = React36.useState(false);
|
|
5671
|
+
const [q, setQ] = React36.useState("");
|
|
5672
|
+
const rootRef = React36.useRef(null);
|
|
5673
|
+
const boxRef = React36.useRef(null);
|
|
5674
|
+
const listRef = React36.useRef(null);
|
|
5675
|
+
const typeBuf = React36.useRef({ s: "", t: 0 });
|
|
5588
5676
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
5589
5677
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
5590
5678
|
const boxText = multiple ? chosen.length === 0 ? placeholder : chosen.length === 1 ? chosen[0].label : summary ? summary(chosen.map((o) => o.value)) : chosen.length + " selected" : selected ? selected.label : placeholder;
|
|
@@ -5723,7 +5811,7 @@ function Select({
|
|
|
5723
5811
|
),
|
|
5724
5812
|
q ? /* @__PURE__ */ jsx62("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
5725
5813
|
] }) : void 0,
|
|
5726
|
-
footer: multiple ? /* @__PURE__ */ jsxs56(
|
|
5814
|
+
footer: multiple ? /* @__PURE__ */ jsxs56(React36.Fragment, { children: [
|
|
5727
5815
|
/* @__PURE__ */ jsx62(
|
|
5728
5816
|
"button",
|
|
5729
5817
|
{
|
|
@@ -5754,7 +5842,7 @@ function Select({
|
|
|
5754
5842
|
'Nothing matches "',
|
|
5755
5843
|
q,
|
|
5756
5844
|
'".'
|
|
5757
|
-
] }) : groups.map((grp) => /* @__PURE__ */ jsxs56(
|
|
5845
|
+
] }) : groups.map((grp) => /* @__PURE__ */ jsxs56(React36.Fragment, { children: [
|
|
5758
5846
|
grp.g ? /* @__PURE__ */ jsx62("div", { className: "fd-pop-group", children: grp.g }) : null,
|
|
5759
5847
|
grp.items.map(({ o, i }) => /* @__PURE__ */ jsxs56(
|
|
5760
5848
|
"button",
|
|
@@ -5791,7 +5879,7 @@ function Select({
|
|
|
5791
5879
|
}
|
|
5792
5880
|
|
|
5793
5881
|
// src/components/forms/TimePicker.tsx
|
|
5794
|
-
import * as
|
|
5882
|
+
import * as React37 from "react";
|
|
5795
5883
|
import { jsx as jsx63, jsxs as jsxs57 } from "react/jsx-runtime";
|
|
5796
5884
|
var pad = (n) => String(n).padStart(2, "0");
|
|
5797
5885
|
function ClockFace({ value = "09:00", onChange }) {
|
|
@@ -5800,9 +5888,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
5800
5888
|
if (isNaN(m)) m = 0;
|
|
5801
5889
|
const pm = h24 >= 12;
|
|
5802
5890
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
5803
|
-
const [mode2, setMode] =
|
|
5804
|
-
const faceRef =
|
|
5805
|
-
const dragging =
|
|
5891
|
+
const [mode2, setMode] = React37.useState("h");
|
|
5892
|
+
const faceRef = React37.useRef(null);
|
|
5893
|
+
const dragging = React37.useRef(false);
|
|
5806
5894
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
5807
5895
|
const R = 108, NR = 80;
|
|
5808
5896
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -5875,9 +5963,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
5875
5963
|
}
|
|
5876
5964
|
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
|
|
5877
5965
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
5878
|
-
const [open, setOpen] =
|
|
5879
|
-
const rootRef =
|
|
5880
|
-
const boxRef =
|
|
5966
|
+
const [open, setOpen] = React37.useState(false);
|
|
5967
|
+
const rootRef = React37.useRef(null);
|
|
5968
|
+
const boxRef = React37.useRef(null);
|
|
5881
5969
|
const disp = () => {
|
|
5882
5970
|
if (!value) return "";
|
|
5883
5971
|
const [h, m] = value.split(":").map(Number);
|
|
@@ -5920,7 +6008,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
5920
6008
|
offset: 6,
|
|
5921
6009
|
width: 262,
|
|
5922
6010
|
role: "presentation",
|
|
5923
|
-
footer: /* @__PURE__ */ jsxs57(
|
|
6011
|
+
footer: /* @__PURE__ */ jsxs57(React37.Fragment, { children: [
|
|
5924
6012
|
/* @__PURE__ */ jsx63(
|
|
5925
6013
|
"button",
|
|
5926
6014
|
{
|
|
@@ -5948,7 +6036,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
5948
6036
|
}
|
|
5949
6037
|
|
|
5950
6038
|
// src/components/forms/Slider.tsx
|
|
5951
|
-
import * as
|
|
6039
|
+
import * as React38 from "react";
|
|
5952
6040
|
import { jsx as jsx64, jsxs as jsxs58 } from "react/jsx-runtime";
|
|
5953
6041
|
function Slider({
|
|
5954
6042
|
label,
|
|
@@ -5966,7 +6054,7 @@ function Slider({
|
|
|
5966
6054
|
...rest
|
|
5967
6055
|
}) {
|
|
5968
6056
|
const fieldId = useFieldId(id);
|
|
5969
|
-
const [dragging, setDragging] =
|
|
6057
|
+
const [dragging, setDragging] = React38.useState(false);
|
|
5970
6058
|
const v = value === void 0 ? min : Number(value);
|
|
5971
6059
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
5972
6060
|
return /* @__PURE__ */ jsxs58("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
|
|
@@ -6000,7 +6088,7 @@ function Slider({
|
|
|
6000
6088
|
}
|
|
6001
6089
|
|
|
6002
6090
|
// src/components/forms/RangeSlider.tsx
|
|
6003
|
-
import * as
|
|
6091
|
+
import * as React39 from "react";
|
|
6004
6092
|
import { jsx as jsx65, jsxs as jsxs59 } from "react/jsx-runtime";
|
|
6005
6093
|
function RangeSlider({
|
|
6006
6094
|
label,
|
|
@@ -6020,9 +6108,9 @@ function RangeSlider({
|
|
|
6020
6108
|
}) {
|
|
6021
6109
|
const fmt2 = format || ((v) => String(v));
|
|
6022
6110
|
const [a, b] = value || [min, max];
|
|
6023
|
-
const [drag, setDrag] =
|
|
6024
|
-
const [focus, setFocus] =
|
|
6025
|
-
const railRef =
|
|
6111
|
+
const [drag, setDrag] = React39.useState(null);
|
|
6112
|
+
const [focus, setFocus] = React39.useState(null);
|
|
6113
|
+
const railRef = React39.useRef(null);
|
|
6026
6114
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
6027
6115
|
const clampPair = (i, v) => {
|
|
6028
6116
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -6037,7 +6125,7 @@ function RangeSlider({
|
|
|
6037
6125
|
const r = railRef.current.getBoundingClientRect();
|
|
6038
6126
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
6039
6127
|
};
|
|
6040
|
-
|
|
6128
|
+
React39.useEffect(() => {
|
|
6041
6129
|
if (drag === null) return;
|
|
6042
6130
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
6043
6131
|
const upH = () => setDrag(null);
|
|
@@ -6118,7 +6206,7 @@ function RangeSlider({
|
|
|
6118
6206
|
/* @__PURE__ */ jsxs59("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
|
|
6119
6207
|
/* @__PURE__ */ jsx65("span", { className: "fd-range-rail", ref: railRef }),
|
|
6120
6208
|
/* @__PURE__ */ jsx65("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
|
|
6121
|
-
marks.map((m) => /* @__PURE__ */ jsxs59(
|
|
6209
|
+
marks.map((m) => /* @__PURE__ */ jsxs59(React39.Fragment, { children: [
|
|
6122
6210
|
/* @__PURE__ */ jsx65("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
|
|
6123
6211
|
m.label ? /* @__PURE__ */ jsx65("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
|
|
6124
6212
|
] }, m.value)),
|
|
@@ -6147,7 +6235,7 @@ function RangeSlider({
|
|
|
6147
6235
|
}
|
|
6148
6236
|
|
|
6149
6237
|
// src/components/forms/Dropzone.tsx
|
|
6150
|
-
import * as
|
|
6238
|
+
import * as React40 from "react";
|
|
6151
6239
|
import { jsx as jsx66, jsxs as jsxs60 } from "react/jsx-runtime";
|
|
6152
6240
|
function Dropzone({
|
|
6153
6241
|
onFiles,
|
|
@@ -6162,8 +6250,8 @@ function Dropzone({
|
|
|
6162
6250
|
className = "",
|
|
6163
6251
|
style
|
|
6164
6252
|
}) {
|
|
6165
|
-
const [over, setOver] =
|
|
6166
|
-
const depth =
|
|
6253
|
+
const [over, setOver] = React40.useState(false);
|
|
6254
|
+
const depth = React40.useRef(0);
|
|
6167
6255
|
const has = (e) => {
|
|
6168
6256
|
const dt = e.dataTransfer;
|
|
6169
6257
|
if (!dt) return false;
|
|
@@ -6225,8 +6313,8 @@ function FilePickButton({
|
|
|
6225
6313
|
className = "",
|
|
6226
6314
|
children
|
|
6227
6315
|
}) {
|
|
6228
|
-
const ref =
|
|
6229
|
-
return /* @__PURE__ */ jsxs60(
|
|
6316
|
+
const ref = React40.useRef(null);
|
|
6317
|
+
return /* @__PURE__ */ jsxs60(React40.Fragment, { children: [
|
|
6230
6318
|
/* @__PURE__ */ jsx66(
|
|
6231
6319
|
"button",
|
|
6232
6320
|
{
|
|
@@ -6259,10 +6347,10 @@ function FilePickButton({
|
|
|
6259
6347
|
}
|
|
6260
6348
|
function useStagedFiles(upload, opts) {
|
|
6261
6349
|
const o = opts || {};
|
|
6262
|
-
const [items, setItems] =
|
|
6263
|
-
const controllers =
|
|
6350
|
+
const [items, setItems] = React40.useState([]);
|
|
6351
|
+
const controllers = React40.useRef({});
|
|
6264
6352
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
6265
|
-
const run =
|
|
6353
|
+
const run = React40.useCallback((att) => {
|
|
6266
6354
|
if (!upload) return;
|
|
6267
6355
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
6268
6356
|
controllers.current[att.id] = ac;
|
|
@@ -6279,14 +6367,14 @@ function useStagedFiles(upload, opts) {
|
|
|
6279
6367
|
delete controllers.current[att.id];
|
|
6280
6368
|
});
|
|
6281
6369
|
}, [upload]);
|
|
6282
|
-
const add =
|
|
6370
|
+
const add = React40.useCallback((files) => {
|
|
6283
6371
|
if (!upload) return [];
|
|
6284
6372
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
6285
6373
|
setItems((list) => list.concat(atts));
|
|
6286
6374
|
atts.forEach(run);
|
|
6287
6375
|
return atts;
|
|
6288
6376
|
}, [upload, run]);
|
|
6289
|
-
const remove =
|
|
6377
|
+
const remove = React40.useCallback((att) => {
|
|
6290
6378
|
const ac = controllers.current[att.id];
|
|
6291
6379
|
if (ac) {
|
|
6292
6380
|
try {
|
|
@@ -6297,10 +6385,10 @@ function useStagedFiles(upload, opts) {
|
|
|
6297
6385
|
}
|
|
6298
6386
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
6299
6387
|
}, []);
|
|
6300
|
-
const retry =
|
|
6388
|
+
const retry = React40.useCallback((att) => {
|
|
6301
6389
|
run(att);
|
|
6302
6390
|
}, [run]);
|
|
6303
|
-
const clear =
|
|
6391
|
+
const clear = React40.useCallback(() => {
|
|
6304
6392
|
Object.values(controllers.current).forEach((ac) => {
|
|
6305
6393
|
try {
|
|
6306
6394
|
ac && ac.abort();
|
|
@@ -6424,7 +6512,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
6424
6512
|
}
|
|
6425
6513
|
|
|
6426
6514
|
// src/components/forms/MarkdownEditor.tsx
|
|
6427
|
-
import * as
|
|
6515
|
+
import * as React41 from "react";
|
|
6428
6516
|
import { jsx as jsx68, jsxs as jsxs62 } from "react/jsx-runtime";
|
|
6429
6517
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
6430
6518
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
@@ -6638,7 +6726,7 @@ function syncDom(root, value) {
|
|
|
6638
6726
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
6639
6727
|
}
|
|
6640
6728
|
var LIST_CONT = RE_LI;
|
|
6641
|
-
var MarkdownEditor =
|
|
6729
|
+
var MarkdownEditor = React41.forwardRef(function MarkdownEditor2({
|
|
6642
6730
|
value = "",
|
|
6643
6731
|
onChange,
|
|
6644
6732
|
onSubmit,
|
|
@@ -6657,10 +6745,10 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6657
6745
|
className = "",
|
|
6658
6746
|
id
|
|
6659
6747
|
}, ref) {
|
|
6660
|
-
const boxRef =
|
|
6661
|
-
const composing =
|
|
6662
|
-
const pendingCaret =
|
|
6663
|
-
|
|
6748
|
+
const boxRef = React41.useRef(null);
|
|
6749
|
+
const composing = React41.useRef(false);
|
|
6750
|
+
const pendingCaret = React41.useRef(null);
|
|
6751
|
+
React41.useLayoutEffect(() => {
|
|
6664
6752
|
const root = boxRef.current;
|
|
6665
6753
|
if (!root || composing.current) return;
|
|
6666
6754
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -6669,7 +6757,7 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6669
6757
|
pendingCaret.current = null;
|
|
6670
6758
|
if (active && caret != null) placeCaret(root, caret);
|
|
6671
6759
|
}, [value]);
|
|
6672
|
-
|
|
6760
|
+
React41.useEffect(() => {
|
|
6673
6761
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
6674
6762
|
}, [autoFocus]);
|
|
6675
6763
|
const caretNow = () => {
|
|
@@ -6736,7 +6824,7 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6736
6824
|
api.replaceRange(from, to, next, from + next.length);
|
|
6737
6825
|
}
|
|
6738
6826
|
};
|
|
6739
|
-
|
|
6827
|
+
React41.useImperativeHandle(ref, () => api);
|
|
6740
6828
|
function detect(text, caret) {
|
|
6741
6829
|
if (!onTrigger) return;
|
|
6742
6830
|
const upto = text.slice(0, caret);
|
|
@@ -6888,16 +6976,16 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6888
6976
|
});
|
|
6889
6977
|
|
|
6890
6978
|
// src/components/platform/AccountMenu.tsx
|
|
6891
|
-
import * as
|
|
6979
|
+
import * as React43 from "react";
|
|
6892
6980
|
|
|
6893
6981
|
// src/kits/sessionContext.tsx
|
|
6894
|
-
import * as
|
|
6895
|
-
var SessionContext =
|
|
6982
|
+
import * as React42 from "react";
|
|
6983
|
+
var SessionContext = React42.createContext(null);
|
|
6896
6984
|
function SessionProvider({ value, children }) {
|
|
6897
|
-
return
|
|
6985
|
+
return React42.createElement(SessionContext.Provider, { value }, children);
|
|
6898
6986
|
}
|
|
6899
6987
|
function useSessionContext() {
|
|
6900
|
-
const ctx =
|
|
6988
|
+
const ctx = React42.useContext(SessionContext);
|
|
6901
6989
|
if (!ctx) {
|
|
6902
6990
|
throw new Error(
|
|
6903
6991
|
"useSessionContext() was called outside a <SessionProvider>. Wrap your app root in <SessionProvider value={...}> with your real session, or \u2014 in the docs site or a demo \u2014 in <DemoSessionProvider>, before rendering AccountMenu, Gate, ProfilePage or AppSwitcher."
|
|
@@ -6937,11 +7025,11 @@ function AccountMenu({
|
|
|
6937
7025
|
...rest
|
|
6938
7026
|
}) {
|
|
6939
7027
|
const { user, roles, can: can2, signOut: ctxSignOut, demo } = useSessionContext();
|
|
6940
|
-
const [open, setOpen] =
|
|
6941
|
-
const [switching, setSwitching] =
|
|
6942
|
-
const [signingOut, setSigningOut] =
|
|
6943
|
-
const [signOutError, setSignOutError] =
|
|
6944
|
-
const ref =
|
|
7028
|
+
const [open, setOpen] = React43.useState(false);
|
|
7029
|
+
const [switching, setSwitching] = React43.useState(false);
|
|
7030
|
+
const [signingOut, setSigningOut] = React43.useState(false);
|
|
7031
|
+
const [signOutError, setSignOutError] = React43.useState(null);
|
|
7032
|
+
const ref = React43.useRef(null);
|
|
6945
7033
|
const visibleLinks = links.filter((l) => !l.perm || can2(l.perm));
|
|
6946
7034
|
const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || can2(l.perm)) })).filter((g) => g.links.length);
|
|
6947
7035
|
const closeMenu = () => {
|
|
@@ -7066,13 +7154,13 @@ function AccountMenu({
|
|
|
7066
7154
|
}
|
|
7067
7155
|
|
|
7068
7156
|
// src/components/platform/AppSwitcher.tsx
|
|
7069
|
-
import * as
|
|
7157
|
+
import * as React44 from "react";
|
|
7070
7158
|
import { jsx as jsx70, jsxs as jsxs64 } from "react/jsx-runtime";
|
|
7071
7159
|
function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
7072
7160
|
const { apps: contextApps } = useSessionContext();
|
|
7073
7161
|
const apps = appsProp ?? contextApps ?? [];
|
|
7074
|
-
const [open, setOpen] =
|
|
7075
|
-
const anchorRef =
|
|
7162
|
+
const [open, setOpen] = React44.useState(false);
|
|
7163
|
+
const anchorRef = React44.useRef(null);
|
|
7076
7164
|
if (!apps.length) return null;
|
|
7077
7165
|
const items = apps.map((app) => ({
|
|
7078
7166
|
id: app.key,
|
|
@@ -7086,7 +7174,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7086
7174
|
window.location.href = app.url;
|
|
7087
7175
|
}
|
|
7088
7176
|
}));
|
|
7089
|
-
return /* @__PURE__ */ jsxs64(
|
|
7177
|
+
return /* @__PURE__ */ jsxs64(React44.Fragment, { children: [
|
|
7090
7178
|
/* @__PURE__ */ jsx70("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx70(
|
|
7091
7179
|
IconButton,
|
|
7092
7180
|
{
|
|
@@ -7115,10 +7203,10 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7115
7203
|
}
|
|
7116
7204
|
|
|
7117
7205
|
// src/components/platform/AppearanceMenu.tsx
|
|
7118
|
-
import * as
|
|
7206
|
+
import * as React46 from "react";
|
|
7119
7207
|
|
|
7120
7208
|
// src/kits/appearance.ts
|
|
7121
|
-
import * as
|
|
7209
|
+
import * as React45 from "react";
|
|
7122
7210
|
var DEFAULT_STORAGE_KEY = "fd-appearance";
|
|
7123
7211
|
var DEFAULT_PREFS = {
|
|
7124
7212
|
theme: "system",
|
|
@@ -7213,11 +7301,11 @@ function applyPrefs(prefs, root = document.documentElement) {
|
|
|
7213
7301
|
else root.removeAttribute("data-motion");
|
|
7214
7302
|
}
|
|
7215
7303
|
function useAppearancePrefs(store) {
|
|
7216
|
-
const prefs =
|
|
7217
|
-
|
|
7304
|
+
const prefs = React45.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
7305
|
+
React45.useEffect(() => {
|
|
7218
7306
|
applyPrefs(prefs);
|
|
7219
7307
|
}, [prefs]);
|
|
7220
|
-
|
|
7308
|
+
React45.useEffect(() => {
|
|
7221
7309
|
if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
7222
7310
|
return;
|
|
7223
7311
|
}
|
|
@@ -7226,7 +7314,7 @@ function useAppearancePrefs(store) {
|
|
|
7226
7314
|
mq.addEventListener("change", onChange);
|
|
7227
7315
|
return () => mq.removeEventListener("change", onChange);
|
|
7228
7316
|
}, [prefs]);
|
|
7229
|
-
const update =
|
|
7317
|
+
const update = React45.useCallback(
|
|
7230
7318
|
(patch) => {
|
|
7231
7319
|
store.write({ ...store.getSnapshot(), ...patch });
|
|
7232
7320
|
},
|
|
@@ -7249,15 +7337,15 @@ var TEXT_SCALE_OPTIONS = [
|
|
|
7249
7337
|
{ value: "xl", label: "XL" }
|
|
7250
7338
|
];
|
|
7251
7339
|
function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
|
|
7252
|
-
const store =
|
|
7340
|
+
const store = React46.useMemo(
|
|
7253
7341
|
() => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
|
|
7254
7342
|
[storeProp, storageKey, storage, defaults]
|
|
7255
7343
|
);
|
|
7256
7344
|
const [prefs, update] = useAppearancePrefs(store);
|
|
7257
|
-
const [open, setOpen] =
|
|
7258
|
-
const anchorRef =
|
|
7345
|
+
const [open, setOpen] = React46.useState(false);
|
|
7346
|
+
const anchorRef = React46.useRef(null);
|
|
7259
7347
|
const patch = (p) => update(p);
|
|
7260
|
-
return /* @__PURE__ */ jsxs65(
|
|
7348
|
+
return /* @__PURE__ */ jsxs65(React46.Fragment, { children: [
|
|
7261
7349
|
/* @__PURE__ */ jsx71("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx71(
|
|
7262
7350
|
IconButton,
|
|
7263
7351
|
{
|
|
@@ -7326,14 +7414,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7326
7414
|
}
|
|
7327
7415
|
|
|
7328
7416
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
7329
|
-
import * as
|
|
7417
|
+
import * as React47 from "react";
|
|
7330
7418
|
import { jsx as jsx72, jsxs as jsxs66 } from "react/jsx-runtime";
|
|
7331
7419
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
7332
7420
|
function Json({ obj }) {
|
|
7333
7421
|
return /* @__PURE__ */ jsx72("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
7334
7422
|
}
|
|
7335
7423
|
function Endpoint({ s, onRequest }) {
|
|
7336
|
-
const [tried, setTried] =
|
|
7424
|
+
const [tried, setTried] = React47.useState(null);
|
|
7337
7425
|
const run = async () => {
|
|
7338
7426
|
setTried("busy");
|
|
7339
7427
|
const t0 = (window.performance || Date).now();
|
|
@@ -7406,10 +7494,10 @@ function ApiSpecBrowser({
|
|
|
7406
7494
|
className = "",
|
|
7407
7495
|
...rest
|
|
7408
7496
|
}) {
|
|
7409
|
-
const [q, setQ] =
|
|
7410
|
-
const [method, setMethod] =
|
|
7411
|
-
const [mod, setMod] =
|
|
7412
|
-
const [listOnly, setListOnly] =
|
|
7497
|
+
const [q, setQ] = React47.useState("");
|
|
7498
|
+
const [method, setMethod] = React47.useState(null);
|
|
7499
|
+
const [mod, setMod] = React47.useState(null);
|
|
7500
|
+
const [listOnly, setListOnly] = React47.useState(false);
|
|
7413
7501
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
7414
7502
|
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())));
|
|
7415
7503
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
@@ -7488,7 +7576,7 @@ function ApiSpecBrowser({
|
|
|
7488
7576
|
}
|
|
7489
7577
|
|
|
7490
7578
|
// src/components/platform/ProfilePage.tsx
|
|
7491
|
-
import * as
|
|
7579
|
+
import * as React48 from "react";
|
|
7492
7580
|
import { jsx as jsx73, jsxs as jsxs67 } from "react/jsx-runtime";
|
|
7493
7581
|
function fieldInitialValue(field, user) {
|
|
7494
7582
|
if (field.value) return field.value(user);
|
|
@@ -7524,21 +7612,21 @@ function ProfilePage({
|
|
|
7524
7612
|
}) {
|
|
7525
7613
|
const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
|
|
7526
7614
|
const user = userProp || sessionUser;
|
|
7527
|
-
const initialFieldValues =
|
|
7615
|
+
const initialFieldValues = React48.useMemo(() => {
|
|
7528
7616
|
const values2 = {};
|
|
7529
7617
|
for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
|
|
7530
7618
|
return values2;
|
|
7531
7619
|
}, [user.id, fields]);
|
|
7532
|
-
const initialNotify =
|
|
7620
|
+
const initialNotify = React48.useMemo(() => {
|
|
7533
7621
|
const values2 = {};
|
|
7534
7622
|
for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
|
|
7535
7623
|
return values2;
|
|
7536
7624
|
}, [user.id, notifications]);
|
|
7537
|
-
const [values, setValues] =
|
|
7538
|
-
const [notify, setNotify] =
|
|
7539
|
-
const [saving, setSaving] =
|
|
7540
|
-
const [saved, setSaved] =
|
|
7541
|
-
const [prevUserId, setPrevUserId] =
|
|
7625
|
+
const [values, setValues] = React48.useState(initialFieldValues);
|
|
7626
|
+
const [notify, setNotify] = React48.useState(initialNotify);
|
|
7627
|
+
const [saving, setSaving] = React48.useState(false);
|
|
7628
|
+
const [saved, setSaved] = React48.useState(false);
|
|
7629
|
+
const [prevUserId, setPrevUserId] = React48.useState(user.id);
|
|
7542
7630
|
if (user.id !== prevUserId) {
|
|
7543
7631
|
setPrevUserId(user.id);
|
|
7544
7632
|
setValues(initialFieldValues);
|
|
@@ -7726,11 +7814,11 @@ function ProfilePage({
|
|
|
7726
7814
|
}
|
|
7727
7815
|
|
|
7728
7816
|
// src/components/platform/SignInPage.tsx
|
|
7729
|
-
import * as
|
|
7817
|
+
import * as React49 from "react";
|
|
7730
7818
|
import { Fragment as Fragment18, jsx as jsx74, jsxs as jsxs68 } from "react/jsx-runtime";
|
|
7731
7819
|
function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
7732
|
-
const [signingIn, setSigningIn] =
|
|
7733
|
-
const [resuming, setResuming] =
|
|
7820
|
+
const [signingIn, setSigningIn] = React49.useState(false);
|
|
7821
|
+
const [resuming, setResuming] = React49.useState(false);
|
|
7734
7822
|
function handleSignIn() {
|
|
7735
7823
|
setSigningIn(true);
|
|
7736
7824
|
onSignIn();
|
|
@@ -7919,10 +8007,10 @@ function GoogleGlyph() {
|
|
|
7919
8007
|
}
|
|
7920
8008
|
|
|
7921
8009
|
// src/components/platform/RoadmapTimeline.tsx
|
|
7922
|
-
import * as
|
|
8010
|
+
import * as React52 from "react";
|
|
7923
8011
|
|
|
7924
8012
|
// src/kits/session.ts
|
|
7925
|
-
import * as
|
|
8013
|
+
import * as React50 from "react";
|
|
7926
8014
|
var PERMISSION_CATALOG = [
|
|
7927
8015
|
{ group: "Plans", items: [
|
|
7928
8016
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -9489,8 +9577,8 @@ function roadmap(overrides) {
|
|
|
9489
9577
|
};
|
|
9490
9578
|
}
|
|
9491
9579
|
function useSession() {
|
|
9492
|
-
const [s, setS] =
|
|
9493
|
-
|
|
9580
|
+
const [s, setS] = React50.useState(getSession);
|
|
9581
|
+
React50.useEffect(() => subscribe(setS), []);
|
|
9494
9582
|
return s;
|
|
9495
9583
|
}
|
|
9496
9584
|
var SessionKit = {
|
|
@@ -9523,7 +9611,7 @@ var SessionKit = {
|
|
|
9523
9611
|
};
|
|
9524
9612
|
function DemoSessionProvider({ children }) {
|
|
9525
9613
|
const session = useSession();
|
|
9526
|
-
const value =
|
|
9614
|
+
const value = React50.useMemo(
|
|
9527
9615
|
() => ({
|
|
9528
9616
|
user: session.user,
|
|
9529
9617
|
roles: session.roles,
|
|
@@ -9539,11 +9627,11 @@ function DemoSessionProvider({ children }) {
|
|
|
9539
9627
|
}),
|
|
9540
9628
|
[session]
|
|
9541
9629
|
);
|
|
9542
|
-
return
|
|
9630
|
+
return React50.createElement(SessionProvider, { value }, children);
|
|
9543
9631
|
}
|
|
9544
9632
|
|
|
9545
9633
|
// src/kits/runtime.ts
|
|
9546
|
-
import * as
|
|
9634
|
+
import * as React51 from "react";
|
|
9547
9635
|
var WIRED_ENDPOINTS = [
|
|
9548
9636
|
// Nothing yet. Every id below would come from a real service:
|
|
9549
9637
|
// "plan.get", "placements.list", …
|
|
@@ -9714,8 +9802,8 @@ var RuntimeKit = {
|
|
|
9714
9802
|
};
|
|
9715
9803
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
9716
9804
|
function useRuntimeMode() {
|
|
9717
|
-
const [m, setM] =
|
|
9718
|
-
|
|
9805
|
+
const [m, setM] = React51.useState(RuntimeKit.getMode());
|
|
9806
|
+
React51.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
9719
9807
|
return m;
|
|
9720
9808
|
}
|
|
9721
9809
|
function useFeatureStatus(key) {
|
|
@@ -9798,12 +9886,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
9798
9886
|
}
|
|
9799
9887
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
9800
9888
|
const session = SessionKit.useSession();
|
|
9801
|
-
const [project, setProject] =
|
|
9802
|
-
const [q, setQ] =
|
|
9803
|
-
const scrollRef =
|
|
9804
|
-
const nowRef =
|
|
9805
|
-
const rm =
|
|
9806
|
-
const byKey =
|
|
9889
|
+
const [project, setProject] = React52.useState("");
|
|
9890
|
+
const [q, setQ] = React52.useState("");
|
|
9891
|
+
const scrollRef = React52.useRef(null);
|
|
9892
|
+
const nowRef = React52.useRef(null);
|
|
9893
|
+
const rm = React52.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
9894
|
+
const byKey = React52.useMemo(() => {
|
|
9807
9895
|
const m = {};
|
|
9808
9896
|
rm.items.forEach((i) => {
|
|
9809
9897
|
m[i.key] = i;
|
|
@@ -9812,7 +9900,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
9812
9900
|
}, [rm]);
|
|
9813
9901
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
9814
9902
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
9815
|
-
|
|
9903
|
+
React52.useEffect(() => {
|
|
9816
9904
|
let raf1 = 0, raf2 = 0;
|
|
9817
9905
|
const place = () => {
|
|
9818
9906
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -9886,7 +9974,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
9886
9974
|
lastPhase = item.phase;
|
|
9887
9975
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
9888
9976
|
const isBoundary = n === firstPending;
|
|
9889
|
-
return /* @__PURE__ */ jsxs69(
|
|
9977
|
+
return /* @__PURE__ */ jsxs69(React52.Fragment, { children: [
|
|
9890
9978
|
showPhase ? /* @__PURE__ */ jsxs69("div", { className: "fd-rm-era", children: [
|
|
9891
9979
|
/* @__PURE__ */ jsxs69("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
9892
9980
|
/* @__PURE__ */ jsx75("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
@@ -9930,7 +10018,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
9930
10018
|
}
|
|
9931
10019
|
|
|
9932
10020
|
// src/components/platform/ComingSoon.tsx
|
|
9933
|
-
import * as
|
|
10021
|
+
import * as React53 from "react";
|
|
9934
10022
|
import { createPortal as createPortal5 } from "react-dom";
|
|
9935
10023
|
import { Fragment as Fragment20, jsx as jsx76, jsxs as jsxs70 } from "react/jsx-runtime";
|
|
9936
10024
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
@@ -9948,8 +10036,8 @@ function writeBypassed(list) {
|
|
|
9948
10036
|
}
|
|
9949
10037
|
}
|
|
9950
10038
|
function useBypass(key) {
|
|
9951
|
-
const [on, setOn] =
|
|
9952
|
-
|
|
10039
|
+
const [on, setOn] = React53.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
10040
|
+
React53.useEffect(() => {
|
|
9953
10041
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
9954
10042
|
}, [key]);
|
|
9955
10043
|
const set = (next) => {
|
|
@@ -9996,9 +10084,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
|
|
|
9996
10084
|
] });
|
|
9997
10085
|
}
|
|
9998
10086
|
function useHoverCard(open) {
|
|
9999
|
-
const anchor =
|
|
10000
|
-
const [pos, setPos] =
|
|
10001
|
-
|
|
10087
|
+
const anchor = React53.useRef(null);
|
|
10088
|
+
const [pos, setPos] = React53.useState(null);
|
|
10089
|
+
React53.useLayoutEffect(() => {
|
|
10002
10090
|
if (!open || !anchor.current) {
|
|
10003
10091
|
setPos(null);
|
|
10004
10092
|
return;
|
|
@@ -10125,10 +10213,10 @@ function ComingSoon({
|
|
|
10125
10213
|
] });
|
|
10126
10214
|
}
|
|
10127
10215
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
10128
|
-
const [open, setOpen] =
|
|
10216
|
+
const [open, setOpen] = React53.useState(false);
|
|
10129
10217
|
const [anchor, pos] = useHoverCard(open);
|
|
10130
10218
|
const zIndex = useOverlayLayer(open);
|
|
10131
|
-
const close =
|
|
10219
|
+
const close = React53.useRef(null);
|
|
10132
10220
|
const show = () => {
|
|
10133
10221
|
if (close.current) {
|
|
10134
10222
|
clearTimeout(close.current);
|
|
@@ -10144,7 +10232,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10144
10232
|
setOpen(false);
|
|
10145
10233
|
}, 140);
|
|
10146
10234
|
};
|
|
10147
|
-
|
|
10235
|
+
React53.useEffect(() => () => {
|
|
10148
10236
|
if (close.current) clearTimeout(close.current);
|
|
10149
10237
|
}, []);
|
|
10150
10238
|
return /* @__PURE__ */ jsxs70(
|
|
@@ -10315,14 +10403,14 @@ function PermissionHint({ perm, children }) {
|
|
|
10315
10403
|
}
|
|
10316
10404
|
|
|
10317
10405
|
// src/components/platform/ModeSwitch.tsx
|
|
10318
|
-
import * as
|
|
10406
|
+
import * as React54 from "react";
|
|
10319
10407
|
import { Fragment as Fragment21, jsx as jsx78, jsxs as jsxs72 } from "react/jsx-runtime";
|
|
10320
10408
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
10321
10409
|
const mode2 = useRuntimeMode();
|
|
10322
|
-
const [open, setOpen] =
|
|
10410
|
+
const [open, setOpen] = React54.useState(false);
|
|
10323
10411
|
const zIndex = useOverlayLayer(open);
|
|
10324
|
-
const ref =
|
|
10325
|
-
|
|
10412
|
+
const ref = React54.useRef(null);
|
|
10413
|
+
React54.useEffect(() => {
|
|
10326
10414
|
if (!open) return;
|
|
10327
10415
|
const away = (e) => {
|
|
10328
10416
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -10578,7 +10666,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
10578
10666
|
}
|
|
10579
10667
|
|
|
10580
10668
|
// src/components/planner/MixGap.tsx
|
|
10581
|
-
import * as
|
|
10669
|
+
import * as React55 from "react";
|
|
10582
10670
|
import { Fragment as Fragment22, jsx as jsx81, jsxs as jsxs75 } from "react/jsx-runtime";
|
|
10583
10671
|
var MIX_GAP_LAYOUT = {
|
|
10584
10672
|
trackHeight: 30,
|
|
@@ -10593,7 +10681,7 @@ function mixGapOffset(value, max) {
|
|
|
10593
10681
|
}
|
|
10594
10682
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
10595
10683
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
10596
|
-
const [hover, setHover] =
|
|
10684
|
+
const [hover, setHover] = React55.useState(null);
|
|
10597
10685
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
10598
10686
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
10599
10687
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
@@ -10736,7 +10824,7 @@ function ChannelContribution({
|
|
|
10736
10824
|
}
|
|
10737
10825
|
|
|
10738
10826
|
// src/components/planner/BudgetReallocator.tsx
|
|
10739
|
-
import * as
|
|
10827
|
+
import * as React56 from "react";
|
|
10740
10828
|
import { Fragment as Fragment23, jsx as jsx83, jsxs as jsxs77 } from "react/jsx-runtime";
|
|
10741
10829
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
10742
10830
|
function BudgetReallocator({
|
|
@@ -10752,8 +10840,8 @@ function BudgetReallocator({
|
|
|
10752
10840
|
onCancel,
|
|
10753
10841
|
className = ""
|
|
10754
10842
|
}) {
|
|
10755
|
-
const [draft, setDraft] =
|
|
10756
|
-
|
|
10843
|
+
const [draft, setDraft] = React56.useState(spend);
|
|
10844
|
+
React56.useEffect(() => setDraft(spend), [spend]);
|
|
10757
10845
|
const dirty = draft !== spend;
|
|
10758
10846
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
10759
10847
|
const nextBand = bandFor(nextCrp);
|
|
@@ -10768,10 +10856,10 @@ function BudgetReallocator({
|
|
|
10768
10856
|
setDraft(spend);
|
|
10769
10857
|
if (onCancel) onCancel();
|
|
10770
10858
|
};
|
|
10771
|
-
const trackRef =
|
|
10772
|
-
const chipRef =
|
|
10773
|
-
const [chipLeft, setChipLeft] =
|
|
10774
|
-
|
|
10859
|
+
const trackRef = React56.useRef(null);
|
|
10860
|
+
const chipRef = React56.useRef(null);
|
|
10861
|
+
const [chipLeft, setChipLeft] = React56.useState(null);
|
|
10862
|
+
React56.useLayoutEffect(() => {
|
|
10775
10863
|
const track = trackRef.current;
|
|
10776
10864
|
if (!dirty || !track) {
|
|
10777
10865
|
setChipLeft(null);
|
|
@@ -10958,7 +11046,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "" })
|
|
|
10958
11046
|
}
|
|
10959
11047
|
|
|
10960
11048
|
// src/components/planner/PreferenceMeter.tsx
|
|
10961
|
-
import * as
|
|
11049
|
+
import * as React57 from "react";
|
|
10962
11050
|
import { jsx as jsx86, jsxs as jsxs80 } from "react/jsx-runtime";
|
|
10963
11051
|
function preferenceScore(criteria) {
|
|
10964
11052
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
@@ -10988,7 +11076,7 @@ function PreferenceMeter({
|
|
|
10988
11076
|
className = ""
|
|
10989
11077
|
}) {
|
|
10990
11078
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
10991
|
-
const segments =
|
|
11079
|
+
const segments = React57.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
10992
11080
|
return /* @__PURE__ */ jsx86(
|
|
10993
11081
|
ScoreMeter,
|
|
10994
11082
|
{
|
|
@@ -11027,10 +11115,10 @@ function PreferenceMeter({
|
|
|
11027
11115
|
}
|
|
11028
11116
|
|
|
11029
11117
|
// src/components/chat/AgentChatPanel.tsx
|
|
11030
|
-
import * as
|
|
11118
|
+
import * as React63 from "react";
|
|
11031
11119
|
|
|
11032
11120
|
// src/components/chat/chatEngine.ts
|
|
11033
|
-
import * as
|
|
11121
|
+
import * as React58 from "react";
|
|
11034
11122
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
11035
11123
|
var JOB_PENDING = ["queued", "running"];
|
|
11036
11124
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -11084,22 +11172,22 @@ function useChatEngine(opts) {
|
|
|
11084
11172
|
onClear,
|
|
11085
11173
|
onFeedback
|
|
11086
11174
|
} = opts || {};
|
|
11087
|
-
const [status, setStatus] =
|
|
11088
|
-
const [threadId, setThreadId] =
|
|
11089
|
-
const [messages, setMessages] =
|
|
11090
|
-
const [queue, setQueue] =
|
|
11091
|
-
const [fatal, setFatal] =
|
|
11092
|
-
const [busy, setBusy] =
|
|
11093
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
11094
|
-
const listRef =
|
|
11095
|
-
const queueRef =
|
|
11096
|
-
const busyRef =
|
|
11097
|
-
const stoppedRef =
|
|
11098
|
-
const abortRef =
|
|
11099
|
-
const serverCount =
|
|
11100
|
-
const threadRef =
|
|
11101
|
-
const mounted =
|
|
11102
|
-
|
|
11175
|
+
const [status, setStatus] = React58.useState("idle");
|
|
11176
|
+
const [threadId, setThreadId] = React58.useState(null);
|
|
11177
|
+
const [messages, setMessages] = React58.useState([]);
|
|
11178
|
+
const [queue, setQueue] = React58.useState([]);
|
|
11179
|
+
const [fatal, setFatal] = React58.useState(null);
|
|
11180
|
+
const [busy, setBusy] = React58.useState(false);
|
|
11181
|
+
const [turnStartedAt, setTurnStartedAt] = React58.useState(null);
|
|
11182
|
+
const listRef = React58.useRef([]);
|
|
11183
|
+
const queueRef = React58.useRef([]);
|
|
11184
|
+
const busyRef = React58.useRef(false);
|
|
11185
|
+
const stoppedRef = React58.useRef(false);
|
|
11186
|
+
const abortRef = React58.useRef(null);
|
|
11187
|
+
const serverCount = React58.useRef(0);
|
|
11188
|
+
const threadRef = React58.useRef(null);
|
|
11189
|
+
const mounted = React58.useRef(true);
|
|
11190
|
+
React58.useEffect(() => {
|
|
11103
11191
|
mounted.current = true;
|
|
11104
11192
|
return () => {
|
|
11105
11193
|
mounted.current = false;
|
|
@@ -11121,14 +11209,14 @@ function useChatEngine(opts) {
|
|
|
11121
11209
|
}
|
|
11122
11210
|
return false;
|
|
11123
11211
|
};
|
|
11124
|
-
const loadThread =
|
|
11212
|
+
const loadThread = React58.useCallback(async (id) => {
|
|
11125
11213
|
const data = await apiAdapter.getThread(id);
|
|
11126
11214
|
const list = [...data && data.messages || []];
|
|
11127
11215
|
serverCount.current = list.length;
|
|
11128
11216
|
commit(list);
|
|
11129
11217
|
return list;
|
|
11130
11218
|
}, [apiAdapter]);
|
|
11131
|
-
|
|
11219
|
+
React58.useEffect(() => {
|
|
11132
11220
|
if (!apiAdapter) {
|
|
11133
11221
|
setStatus("idle");
|
|
11134
11222
|
setFatal(null);
|
|
@@ -11341,7 +11429,7 @@ function useChatEngine(opts) {
|
|
|
11341
11429
|
await dispatchTurn(turn);
|
|
11342
11430
|
}
|
|
11343
11431
|
}
|
|
11344
|
-
const send =
|
|
11432
|
+
const send = React58.useCallback((text, attachments) => {
|
|
11345
11433
|
const body = (text || "").trim();
|
|
11346
11434
|
if (!body && !(attachments && attachments.length)) return;
|
|
11347
11435
|
if (status === "disconnected") return;
|
|
@@ -11351,7 +11439,7 @@ function useChatEngine(opts) {
|
|
|
11351
11439
|
stoppedRef.current = false;
|
|
11352
11440
|
drain();
|
|
11353
11441
|
}, [status]);
|
|
11354
|
-
const stop =
|
|
11442
|
+
const stop = React58.useCallback(() => {
|
|
11355
11443
|
stoppedRef.current = true;
|
|
11356
11444
|
const ac = abortRef.current;
|
|
11357
11445
|
if (ac) {
|
|
@@ -11370,11 +11458,11 @@ function useChatEngine(opts) {
|
|
|
11370
11458
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
11371
11459
|
}
|
|
11372
11460
|
}, [apiAdapter]);
|
|
11373
|
-
const removeQueued =
|
|
11461
|
+
const removeQueued = React58.useCallback((id) => {
|
|
11374
11462
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
11375
11463
|
setQueue(queueRef.current.slice());
|
|
11376
11464
|
}, []);
|
|
11377
|
-
const retry =
|
|
11465
|
+
const retry = React58.useCallback(() => {
|
|
11378
11466
|
const list = listRef.current;
|
|
11379
11467
|
let at = -1;
|
|
11380
11468
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -11390,19 +11478,19 @@ function useChatEngine(opts) {
|
|
|
11390
11478
|
setQueue(queueRef.current.slice());
|
|
11391
11479
|
drain();
|
|
11392
11480
|
}, []);
|
|
11393
|
-
const clear =
|
|
11481
|
+
const clear = React58.useCallback(() => {
|
|
11394
11482
|
commit([]);
|
|
11395
11483
|
serverCount.current = 0;
|
|
11396
11484
|
queueRef.current = [];
|
|
11397
11485
|
setQueue([]);
|
|
11398
11486
|
onClear && onClear();
|
|
11399
11487
|
}, [onClear]);
|
|
11400
|
-
const setFeedback =
|
|
11488
|
+
const setFeedback = React58.useCallback((id, value) => {
|
|
11401
11489
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
11402
11490
|
const msg = listRef.current.find((m) => m.id === id);
|
|
11403
11491
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
11404
11492
|
}, [onFeedback]);
|
|
11405
|
-
const reload =
|
|
11493
|
+
const reload = React58.useCallback(async () => {
|
|
11406
11494
|
if (!threadRef.current) return;
|
|
11407
11495
|
setStatus("loading");
|
|
11408
11496
|
try {
|
|
@@ -11440,10 +11528,10 @@ var ChatKit = {
|
|
|
11440
11528
|
};
|
|
11441
11529
|
|
|
11442
11530
|
// src/components/chat/ChatTranscript.tsx
|
|
11443
|
-
import * as
|
|
11531
|
+
import * as React60 from "react";
|
|
11444
11532
|
|
|
11445
11533
|
// src/components/chat/ChatTurn.tsx
|
|
11446
|
-
import * as
|
|
11534
|
+
import * as React59 from "react";
|
|
11447
11535
|
import { jsx as jsx87, jsxs as jsxs81 } from "react/jsx-runtime";
|
|
11448
11536
|
function JsonView({ value }) {
|
|
11449
11537
|
let text;
|
|
@@ -11480,7 +11568,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
|
11480
11568
|
] });
|
|
11481
11569
|
}
|
|
11482
11570
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
11483
|
-
const [open, setOpen] =
|
|
11571
|
+
const [open, setOpen] = React59.useState(defaultOpen);
|
|
11484
11572
|
if (!text) return null;
|
|
11485
11573
|
return /* @__PURE__ */ jsxs81("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
|
|
11486
11574
|
/* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -11497,7 +11585,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
|
11497
11585
|
] });
|
|
11498
11586
|
}
|
|
11499
11587
|
function Citations({ items = [], onOpen }) {
|
|
11500
|
-
const [open, setOpen] =
|
|
11588
|
+
const [open, setOpen] = React59.useState(false);
|
|
11501
11589
|
if (!items.length) return null;
|
|
11502
11590
|
return /* @__PURE__ */ jsxs81("div", { className: "fdc-cites", children: [
|
|
11503
11591
|
/* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -11523,7 +11611,7 @@ function clampText(text, max) {
|
|
|
11523
11611
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
11524
11612
|
}
|
|
11525
11613
|
function MessageBody({ message: m, ctx }) {
|
|
11526
|
-
const [expanded, setExpanded] =
|
|
11614
|
+
const [expanded, setExpanded] = React59.useState(false);
|
|
11527
11615
|
const isUser = m.role === "user";
|
|
11528
11616
|
const raw = m.text || "";
|
|
11529
11617
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
@@ -11590,9 +11678,9 @@ function MessageBody({ message: m, ctx }) {
|
|
|
11590
11678
|
] });
|
|
11591
11679
|
}
|
|
11592
11680
|
function useCopyRun() {
|
|
11593
|
-
const [done, setDone] =
|
|
11594
|
-
const t =
|
|
11595
|
-
|
|
11681
|
+
const [done, setDone] = React59.useState(false);
|
|
11682
|
+
const t = React59.useRef(null);
|
|
11683
|
+
React59.useEffect(() => () => {
|
|
11596
11684
|
if (t.current) clearTimeout(t.current);
|
|
11597
11685
|
}, []);
|
|
11598
11686
|
return [done, (text) => {
|
|
@@ -11619,7 +11707,7 @@ function RunActions({ group, ctx }) {
|
|
|
11619
11707
|
] }),
|
|
11620
11708
|
isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx87("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx87("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
11621
11709
|
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx87("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx87("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
11622
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs81(
|
|
11710
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs81(React59.Fragment, { children: [
|
|
11623
11711
|
/* @__PURE__ */ jsx87("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__ */ jsx87("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
11624
11712
|
/* @__PURE__ */ jsx87("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__ */ jsx87("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
11625
11713
|
] }) : null,
|
|
@@ -11714,10 +11802,10 @@ function ChatTranscript({
|
|
|
11714
11802
|
renderEmpty,
|
|
11715
11803
|
className = ""
|
|
11716
11804
|
}) {
|
|
11717
|
-
const scroller =
|
|
11718
|
-
const stick =
|
|
11719
|
-
const [pill, setPill] =
|
|
11720
|
-
const seen =
|
|
11805
|
+
const scroller = React60.useRef(null);
|
|
11806
|
+
const stick = React60.useRef(true);
|
|
11807
|
+
const [pill, setPill] = React60.useState(0);
|
|
11808
|
+
const seen = React60.useRef(0);
|
|
11721
11809
|
const toBottom = (smooth) => {
|
|
11722
11810
|
const el = scroller.current;
|
|
11723
11811
|
if (!el) return;
|
|
@@ -11736,7 +11824,7 @@ function ChatTranscript({
|
|
|
11736
11824
|
seen.current = messages.length;
|
|
11737
11825
|
}
|
|
11738
11826
|
};
|
|
11739
|
-
|
|
11827
|
+
React60.useLayoutEffect(() => {
|
|
11740
11828
|
const el = scroller.current;
|
|
11741
11829
|
if (!el) return;
|
|
11742
11830
|
if (stick.current) {
|
|
@@ -11744,7 +11832,7 @@ function ChatTranscript({
|
|
|
11744
11832
|
seen.current = messages.length;
|
|
11745
11833
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
11746
11834
|
}, [messages]);
|
|
11747
|
-
|
|
11835
|
+
React60.useEffect(() => {
|
|
11748
11836
|
const el = scroller.current;
|
|
11749
11837
|
const inner = el && el.firstChild;
|
|
11750
11838
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -11754,7 +11842,7 @@ function ChatTranscript({
|
|
|
11754
11842
|
ro.observe(inner);
|
|
11755
11843
|
return () => ro.disconnect();
|
|
11756
11844
|
}, []);
|
|
11757
|
-
const groups =
|
|
11845
|
+
const groups = React60.useMemo(() => groupMessages(messages), [messages]);
|
|
11758
11846
|
const empty = !messages.length && status === "ready";
|
|
11759
11847
|
return /* @__PURE__ */ jsxs82("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
11760
11848
|
/* @__PURE__ */ jsxs82("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
@@ -11778,7 +11866,7 @@ function ChatTranscript({
|
|
|
11778
11866
|
const prev = groups[i - 1];
|
|
11779
11867
|
const k = dayKey(g.messages[0].timestamp);
|
|
11780
11868
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
11781
|
-
return /* @__PURE__ */ jsxs82(
|
|
11869
|
+
return /* @__PURE__ */ jsxs82(React60.Fragment, { children: [
|
|
11782
11870
|
showDay ? /* @__PURE__ */ jsx88("div", { className: "fdc-day", children: /* @__PURE__ */ jsx88("span", { children: dayLabel(k) }) }) : null,
|
|
11783
11871
|
/* @__PURE__ */ jsx88(ChatTurn, { group: g, ctx })
|
|
11784
11872
|
] }, g.key || i);
|
|
@@ -11795,7 +11883,7 @@ function ChatTranscript({
|
|
|
11795
11883
|
var TranscriptKit = { groupMessages };
|
|
11796
11884
|
|
|
11797
11885
|
// src/components/chat/ChatComposer.tsx
|
|
11798
|
-
import * as
|
|
11886
|
+
import * as React61 from "react";
|
|
11799
11887
|
import { jsx as jsx89, jsxs as jsxs83 } from "react/jsx-runtime";
|
|
11800
11888
|
function ChatComposer({
|
|
11801
11889
|
onSubmit,
|
|
@@ -11823,17 +11911,17 @@ function ChatComposer({
|
|
|
11823
11911
|
onReject,
|
|
11824
11912
|
onOpenAttachment
|
|
11825
11913
|
}) {
|
|
11826
|
-
const [text, setText] =
|
|
11827
|
-
const [trigger, setTrigger] =
|
|
11828
|
-
const [mentionItems, setMentionItems] =
|
|
11829
|
-
const [listening, setListening] =
|
|
11830
|
-
const [notice, setNotice] =
|
|
11831
|
-
const editor =
|
|
11832
|
-
const wrap =
|
|
11833
|
-
const stopVoice =
|
|
11914
|
+
const [text, setText] = React61.useState(draft || "");
|
|
11915
|
+
const [trigger, setTrigger] = React61.useState(null);
|
|
11916
|
+
const [mentionItems, setMentionItems] = React61.useState([]);
|
|
11917
|
+
const [listening, setListening] = React61.useState(false);
|
|
11918
|
+
const [notice, setNotice] = React61.useState(null);
|
|
11919
|
+
const editor = React61.useRef(null);
|
|
11920
|
+
const wrap = React61.useRef(null);
|
|
11921
|
+
const stopVoice = React61.useRef(null);
|
|
11834
11922
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
11835
11923
|
} });
|
|
11836
|
-
|
|
11924
|
+
React61.useEffect(() => {
|
|
11837
11925
|
if (draft != null && draft !== text) setText(draft);
|
|
11838
11926
|
}, [draft]);
|
|
11839
11927
|
const change = (v) => {
|
|
@@ -11869,7 +11957,7 @@ function ChatComposer({
|
|
|
11869
11957
|
e.preventDefault();
|
|
11870
11958
|
staged.add(found.files);
|
|
11871
11959
|
};
|
|
11872
|
-
|
|
11960
|
+
React61.useEffect(() => {
|
|
11873
11961
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
11874
11962
|
setMentionItems([]);
|
|
11875
11963
|
return;
|
|
@@ -11887,7 +11975,7 @@ function ChatComposer({
|
|
|
11887
11975
|
const q = (trigger.query || "").toLowerCase();
|
|
11888
11976
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
11889
11977
|
}, [trigger, mentionSources]);
|
|
11890
|
-
const slashItems =
|
|
11978
|
+
const slashItems = React61.useMemo(() => {
|
|
11891
11979
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
11892
11980
|
const q = (trigger.query || "").toLowerCase();
|
|
11893
11981
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -12061,12 +12149,12 @@ function ChatComposer({
|
|
|
12061
12149
|
}
|
|
12062
12150
|
|
|
12063
12151
|
// src/components/chat/ChatSessionBar.tsx
|
|
12064
|
-
import * as
|
|
12152
|
+
import * as React62 from "react";
|
|
12065
12153
|
import { jsx as jsx90, jsxs as jsxs84 } from "react/jsx-runtime";
|
|
12066
12154
|
var compact2 = meterFormats.compact;
|
|
12067
12155
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
12068
|
-
const [open, setOpen] =
|
|
12069
|
-
const anchor =
|
|
12156
|
+
const [open, setOpen] = React62.useState(false);
|
|
12157
|
+
const anchor = React62.useRef(null);
|
|
12070
12158
|
const stats = sessionStats || null;
|
|
12071
12159
|
const cu = contextUsage || null;
|
|
12072
12160
|
const limits = usageLimits || null;
|
|
@@ -12081,7 +12169,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12081
12169
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
12082
12170
|
if (cu) bits.push(pct + "% context");
|
|
12083
12171
|
const expandable = !!(cu || limits);
|
|
12084
|
-
return /* @__PURE__ */ jsxs84(
|
|
12172
|
+
return /* @__PURE__ */ jsxs84(React62.Fragment, { children: [
|
|
12085
12173
|
/* @__PURE__ */ jsxs84("div", { className: "fdc-bar", children: [
|
|
12086
12174
|
/* @__PURE__ */ jsxs84(
|
|
12087
12175
|
"button",
|
|
@@ -12222,7 +12310,7 @@ function ModelControls({
|
|
|
12222
12310
|
] })
|
|
12223
12311
|
});
|
|
12224
12312
|
}
|
|
12225
|
-
return /* @__PURE__ */ jsxs84(
|
|
12313
|
+
return /* @__PURE__ */ jsxs84(React62.Fragment, { children: [
|
|
12226
12314
|
/* @__PURE__ */ jsx90(
|
|
12227
12315
|
MenuButton,
|
|
12228
12316
|
{
|
|
@@ -12339,11 +12427,11 @@ function AgentChatPanel({
|
|
|
12339
12427
|
onFeedback,
|
|
12340
12428
|
onEditMessage
|
|
12341
12429
|
}) {
|
|
12342
|
-
const [panelWidth, setPanelWidth] =
|
|
12343
|
-
const [applied, setApplied] =
|
|
12344
|
-
const [draft, setDraft] =
|
|
12345
|
-
const dragging =
|
|
12346
|
-
|
|
12430
|
+
const [panelWidth, setPanelWidth] = React63.useState(width);
|
|
12431
|
+
const [applied, setApplied] = React63.useState({});
|
|
12432
|
+
const [draft, setDraft] = React63.useState("");
|
|
12433
|
+
const dragging = React63.useRef(null);
|
|
12434
|
+
React63.useEffect(() => setPanelWidth(width), [width]);
|
|
12347
12435
|
const engine = useChatEngine({
|
|
12348
12436
|
contextType,
|
|
12349
12437
|
contextId,
|
|
@@ -12547,7 +12635,7 @@ function AgentChatPanel({
|
|
|
12547
12635
|
}
|
|
12548
12636
|
|
|
12549
12637
|
// src/components/files/FileViewer.tsx
|
|
12550
|
-
import * as
|
|
12638
|
+
import * as React64 from "react";
|
|
12551
12639
|
import { jsx as jsx92, jsxs as jsxs86 } from "react/jsx-runtime";
|
|
12552
12640
|
function previewKindOf(file) {
|
|
12553
12641
|
const mime = (file.mime || "").toLowerCase();
|
|
@@ -12604,13 +12692,13 @@ function parseDelimited(text, delimiter) {
|
|
|
12604
12692
|
return rows;
|
|
12605
12693
|
}
|
|
12606
12694
|
function usePreview(file, kind, resolveUrl) {
|
|
12607
|
-
const [state, setState] =
|
|
12608
|
-
const [attempt, setAttempt] =
|
|
12609
|
-
const resolveRef =
|
|
12610
|
-
|
|
12695
|
+
const [state, setState] = React64.useState({ status: "loading" });
|
|
12696
|
+
const [attempt, setAttempt] = React64.useState(0);
|
|
12697
|
+
const resolveRef = React64.useRef(resolveUrl);
|
|
12698
|
+
React64.useEffect(() => {
|
|
12611
12699
|
resolveRef.current = resolveUrl;
|
|
12612
12700
|
}, [resolveUrl]);
|
|
12613
|
-
|
|
12701
|
+
React64.useEffect(() => {
|
|
12614
12702
|
if (kind === "none") {
|
|
12615
12703
|
setState({ status: "ready" });
|
|
12616
12704
|
return;
|
|
@@ -12640,7 +12728,7 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
12640
12728
|
if (ac) ac.abort();
|
|
12641
12729
|
};
|
|
12642
12730
|
}, [file.id, kind, attempt]);
|
|
12643
|
-
return { ...state, retry:
|
|
12731
|
+
return { ...state, retry: React64.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
12644
12732
|
}
|
|
12645
12733
|
function PreviewBody({ file, kind, state }) {
|
|
12646
12734
|
if (kind === "image") return /* @__PURE__ */ jsx92("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
@@ -12685,13 +12773,13 @@ function PreviewBody({ file, kind, state }) {
|
|
|
12685
12773
|
] });
|
|
12686
12774
|
}
|
|
12687
12775
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
12688
|
-
const kind =
|
|
12776
|
+
const kind = React64.useMemo(() => previewKindOf(file), [file]);
|
|
12689
12777
|
const preview = usePreview(file, kind, resolveUrl);
|
|
12690
|
-
const [tab, setTab] =
|
|
12691
|
-
const [downloading, setDownloading] =
|
|
12692
|
-
const [downloadError, setDownloadError] =
|
|
12778
|
+
const [tab, setTab] = React64.useState("preview");
|
|
12779
|
+
const [downloading, setDownloading] = React64.useState(false);
|
|
12780
|
+
const [downloadError, setDownloadError] = React64.useState(null);
|
|
12693
12781
|
const hasSide = sidePanel != null;
|
|
12694
|
-
|
|
12782
|
+
React64.useEffect(() => {
|
|
12695
12783
|
setTab("preview");
|
|
12696
12784
|
}, [file.id]);
|
|
12697
12785
|
const download = () => {
|
|
@@ -12758,7 +12846,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
12758
12846
|
}
|
|
12759
12847
|
|
|
12760
12848
|
// src/components/files/FileBrowser.tsx
|
|
12761
|
-
import * as
|
|
12849
|
+
import * as React65 from "react";
|
|
12762
12850
|
import { Fragment as Fragment27, jsx as jsx93, jsxs as jsxs87 } from "react/jsx-runtime";
|
|
12763
12851
|
function childrenOf(folders, parentId) {
|
|
12764
12852
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -12829,10 +12917,10 @@ function FolderPickerMenu({
|
|
|
12829
12917
|
destinations,
|
|
12830
12918
|
onPick
|
|
12831
12919
|
}) {
|
|
12832
|
-
const [open, setOpen] =
|
|
12920
|
+
const [open, setOpen] = React65.useState(false);
|
|
12833
12921
|
const zIndex = useOverlayLayer(open);
|
|
12834
|
-
const ref =
|
|
12835
|
-
|
|
12922
|
+
const ref = React65.useRef(null);
|
|
12923
|
+
React65.useEffect(() => {
|
|
12836
12924
|
if (!open) return;
|
|
12837
12925
|
const away = (e) => {
|
|
12838
12926
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -12884,8 +12972,8 @@ function FolderPickerMenu({
|
|
|
12884
12972
|
] });
|
|
12885
12973
|
}
|
|
12886
12974
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
12887
|
-
const [over, setOver] =
|
|
12888
|
-
const dragCounter =
|
|
12975
|
+
const [over, setOver] = React65.useState(false);
|
|
12976
|
+
const dragCounter = React65.useRef(0);
|
|
12889
12977
|
const dropHandlers = isDropTarget ? {
|
|
12890
12978
|
onDragEnter: (e) => {
|
|
12891
12979
|
if (!hasInternalPayload(e)) return;
|
|
@@ -12933,8 +13021,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
12933
13021
|
}
|
|
12934
13022
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
12935
13023
|
const kids = childrenOf(folders, folder.id);
|
|
12936
|
-
const [expanded, setExpanded] =
|
|
12937
|
-
|
|
13024
|
+
const [expanded, setExpanded] = React65.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
13025
|
+
React65.useEffect(() => {
|
|
12938
13026
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
12939
13027
|
}, [currentFolderId, folder.id, folders]);
|
|
12940
13028
|
const isCurrent = folder.id === currentFolderId;
|
|
@@ -13000,15 +13088,15 @@ function FileBrowser({
|
|
|
13000
13088
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
13001
13089
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
13002
13090
|
const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
|
|
13003
|
-
const [createOpen, setCreateOpen] =
|
|
13004
|
-
const [createName, setCreateName] =
|
|
13005
|
-
const [renameTarget, setRenameTarget] =
|
|
13006
|
-
const [renameValue, setRenameValue] =
|
|
13007
|
-
const [deleteTarget, setDeleteTarget] =
|
|
13008
|
-
const uploadInputRef =
|
|
13009
|
-
const crumbFolders =
|
|
13010
|
-
const subfolders =
|
|
13011
|
-
const currentFiles =
|
|
13091
|
+
const [createOpen, setCreateOpen] = React65.useState(false);
|
|
13092
|
+
const [createName, setCreateName] = React65.useState("");
|
|
13093
|
+
const [renameTarget, setRenameTarget] = React65.useState(null);
|
|
13094
|
+
const [renameValue, setRenameValue] = React65.useState("");
|
|
13095
|
+
const [deleteTarget, setDeleteTarget] = React65.useState(null);
|
|
13096
|
+
const uploadInputRef = React65.useRef(null);
|
|
13097
|
+
const crumbFolders = React65.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
13098
|
+
const subfolders = React65.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
13099
|
+
const currentFiles = React65.useMemo(
|
|
13012
13100
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
13013
13101
|
[files, currentFolderId]
|
|
13014
13102
|
);
|
|
@@ -13240,8 +13328,8 @@ function BreadcrumbCrumb({
|
|
|
13240
13328
|
isDropTarget,
|
|
13241
13329
|
onDropPayload
|
|
13242
13330
|
}) {
|
|
13243
|
-
const [over, setOver] =
|
|
13244
|
-
const dragCounter =
|
|
13331
|
+
const [over, setOver] = React65.useState(false);
|
|
13332
|
+
const dragCounter = React65.useRef(0);
|
|
13245
13333
|
const dropHandlers = isDropTarget ? {
|
|
13246
13334
|
onDragEnter: (e) => {
|
|
13247
13335
|
if (!hasInternalPayload(e)) return;
|
|
@@ -13270,7 +13358,7 @@ function BreadcrumbCrumb({
|
|
|
13270
13358
|
}
|
|
13271
13359
|
|
|
13272
13360
|
// src/kits/query.ts
|
|
13273
|
-
import * as
|
|
13361
|
+
import * as React66 from "react";
|
|
13274
13362
|
var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
|
|
13275
13363
|
var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
|
|
13276
13364
|
var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
|
|
@@ -13325,22 +13413,22 @@ function compare(a, b, dir) {
|
|
|
13325
13413
|
var API = null;
|
|
13326
13414
|
var PREFS = null;
|
|
13327
13415
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
13328
|
-
const [query, setQuery] =
|
|
13416
|
+
const [query, setQuery] = React66.useState(() => {
|
|
13329
13417
|
const store = PREFS || window.PlannerPrefs;
|
|
13330
13418
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
13331
13419
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
13332
13420
|
});
|
|
13333
|
-
const savePref =
|
|
13421
|
+
const savePref = React66.useCallback((patch2) => {
|
|
13334
13422
|
const store = PREFS || window.PlannerPrefs;
|
|
13335
13423
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
13336
13424
|
}, [prefsKey]);
|
|
13337
|
-
const [res, setRes] =
|
|
13338
|
-
const [loading, setLoading] =
|
|
13339
|
-
const seq2 =
|
|
13425
|
+
const [res, setRes] = React66.useState(null);
|
|
13426
|
+
const [loading, setLoading] = React66.useState(true);
|
|
13427
|
+
const seq2 = React66.useRef(0);
|
|
13340
13428
|
const depKey = (deps || []).join("|");
|
|
13341
13429
|
const paramKey = JSON.stringify(params || {});
|
|
13342
13430
|
const queryKey = JSON.stringify(query);
|
|
13343
|
-
|
|
13431
|
+
React66.useEffect(() => {
|
|
13344
13432
|
const id = ++seq2.current;
|
|
13345
13433
|
setLoading(true);
|
|
13346
13434
|
const t = setTimeout(() => {
|
|
@@ -13659,12 +13747,12 @@ function createVersionStore(initialState, options) {
|
|
|
13659
13747
|
}
|
|
13660
13748
|
|
|
13661
13749
|
// src/kits/documentTitle.ts
|
|
13662
|
-
import * as
|
|
13750
|
+
import * as React67 from "react";
|
|
13663
13751
|
function formatDocumentTitle(routeTitle, appName) {
|
|
13664
13752
|
return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
|
|
13665
13753
|
}
|
|
13666
13754
|
function useDocumentTitle(routeTitle, appName) {
|
|
13667
|
-
|
|
13755
|
+
React67.useEffect(() => {
|
|
13668
13756
|
if (typeof document === "undefined") return;
|
|
13669
13757
|
document.title = formatDocumentTitle(routeTitle, appName);
|
|
13670
13758
|
}, [routeTitle, appName]);
|