@flytedan/flytebot-design-system 0.33.0 → 0.34.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 +448 -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 +448 -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,17 +3478,17 @@ 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
|
+
React25.useEffect(() => {
|
|
3485
3492
|
if (mode2 === "paste") pasteWrapRef.current?.querySelector("textarea")?.focus();
|
|
3486
3493
|
}, [mode2]);
|
|
3487
3494
|
const doResolve = () => {
|
|
@@ -3500,7 +3507,7 @@ function MultiSelectPanel({
|
|
|
3500
3507
|
setPasteError("This filter allows at most " + field.maxValues + " values; adding this list would make " + merged.size + ".");
|
|
3501
3508
|
return;
|
|
3502
3509
|
}
|
|
3503
|
-
const applied = commit(Array.from(merged.values())
|
|
3510
|
+
const applied = commit(Array.from(merged.values()));
|
|
3504
3511
|
if (!applied.ok) {
|
|
3505
3512
|
setPasteError(applied.reason);
|
|
3506
3513
|
return;
|
|
@@ -3642,10 +3649,9 @@ function MultiSelectPanel({
|
|
|
3642
3649
|
);
|
|
3643
3650
|
}
|
|
3644
3651
|
function useTextValidity(onFlip) {
|
|
3645
|
-
const invalidRef =
|
|
3646
|
-
const [, rerender] =
|
|
3647
|
-
const onFlipRef =
|
|
3648
|
-
onFlipRef.current = onFlip;
|
|
3652
|
+
const invalidRef = React25.useRef(/* @__PURE__ */ new Set());
|
|
3653
|
+
const [, rerender] = React25.useReducer((n) => n + 1, 0);
|
|
3654
|
+
const onFlipRef = useLatest(onFlip);
|
|
3649
3655
|
const record = (name, valid) => {
|
|
3650
3656
|
const invalid = invalidRef.current;
|
|
3651
3657
|
if (valid !== invalid.has(name)) return false;
|
|
@@ -3662,6 +3668,12 @@ function useTextValidity(onFlip) {
|
|
|
3662
3668
|
/** For an input that is about to unmount: it has nothing left to show. */
|
|
3663
3669
|
forget: (name) => {
|
|
3664
3670
|
record(name, true);
|
|
3671
|
+
},
|
|
3672
|
+
/** For a panel that is about to remount every input: each reports afresh on mount. */
|
|
3673
|
+
reset: () => {
|
|
3674
|
+
if (invalidRef.current.size === 0) return;
|
|
3675
|
+
invalidRef.current.clear();
|
|
3676
|
+
rerender();
|
|
3665
3677
|
}
|
|
3666
3678
|
};
|
|
3667
3679
|
}
|
|
@@ -3669,6 +3681,26 @@ function applicable(field, candidate, textValid) {
|
|
|
3669
3681
|
if (!textValid || candidate === void 0) return void 0;
|
|
3670
3682
|
return validateFilterValue(field, candidate).ok ? candidate : void 0;
|
|
3671
3683
|
}
|
|
3684
|
+
function sameValue(a, b) {
|
|
3685
|
+
if (a === b) return true;
|
|
3686
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
|
|
3687
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
3688
|
+
const left = a;
|
|
3689
|
+
const right = b;
|
|
3690
|
+
for (const key of /* @__PURE__ */ new Set([...Object.keys(left), ...Object.keys(right)])) {
|
|
3691
|
+
if (!sameValue(left[key], right[key])) return false;
|
|
3692
|
+
}
|
|
3693
|
+
return true;
|
|
3694
|
+
}
|
|
3695
|
+
function useReseedFromProps(value, applies, reseed) {
|
|
3696
|
+
const seen = React25.useRef(value);
|
|
3697
|
+
React25.useLayoutEffect(() => {
|
|
3698
|
+
if (seen.current === value) return;
|
|
3699
|
+
seen.current = value;
|
|
3700
|
+
if (!sameValue(value, applies())) reseed(value);
|
|
3701
|
+
}, [value, applies, reseed]);
|
|
3702
|
+
}
|
|
3703
|
+
var rangeDraft = (value) => ({ min: value?.min, max: value?.max });
|
|
3672
3704
|
function RangePanel({
|
|
3673
3705
|
field,
|
|
3674
3706
|
value,
|
|
@@ -3676,13 +3708,23 @@ function RangePanel({
|
|
|
3676
3708
|
onCommit,
|
|
3677
3709
|
onClose
|
|
3678
3710
|
}) {
|
|
3679
|
-
const [draft, setDraft] =
|
|
3680
|
-
const
|
|
3681
|
-
const
|
|
3711
|
+
const [draft, setDraft] = React25.useState(() => rangeDraft(value));
|
|
3712
|
+
const [seed, setSeed] = React25.useState(0);
|
|
3713
|
+
const draftRef = React25.useRef(draft);
|
|
3714
|
+
const shown = () => {
|
|
3682
3715
|
const { min, max } = draftRef.current;
|
|
3683
|
-
|
|
3716
|
+
return applicable(field, min == null && max == null ? void 0 : { min, max }, validity.allValid());
|
|
3717
|
+
};
|
|
3718
|
+
const publish = () => {
|
|
3719
|
+
onCommit(shown());
|
|
3684
3720
|
};
|
|
3685
3721
|
const validity = useTextValidity(publish);
|
|
3722
|
+
useReseedFromProps(value, shown, (next) => {
|
|
3723
|
+
draftRef.current = rangeDraft(next);
|
|
3724
|
+
setDraft(draftRef.current);
|
|
3725
|
+
validity.reset();
|
|
3726
|
+
setSeed((n) => n + 1);
|
|
3727
|
+
});
|
|
3686
3728
|
const draftMin = draft.min;
|
|
3687
3729
|
const draftMax = draft.max;
|
|
3688
3730
|
const isEmpty = draftMin == null && draftMax == null;
|
|
@@ -3719,7 +3761,8 @@ function RangePanel({
|
|
|
3719
3761
|
placeholder: field.minPlaceholder,
|
|
3720
3762
|
onChange: (e) => apply({ min: e.target.value }),
|
|
3721
3763
|
onValidityChange: validity.report("min")
|
|
3722
|
-
}
|
|
3764
|
+
},
|
|
3765
|
+
"min-" + seed
|
|
3723
3766
|
),
|
|
3724
3767
|
/* @__PURE__ */ jsx45(
|
|
3725
3768
|
NumberInput,
|
|
@@ -3734,12 +3777,20 @@ function RangePanel({
|
|
|
3734
3777
|
placeholder: field.maxPlaceholder,
|
|
3735
3778
|
onChange: (e) => apply({ max: e.target.value }),
|
|
3736
3779
|
onValidityChange: validity.report("max")
|
|
3737
|
-
}
|
|
3780
|
+
},
|
|
3781
|
+
"max-" + seed
|
|
3738
3782
|
)
|
|
3739
3783
|
] })
|
|
3740
3784
|
}
|
|
3741
3785
|
);
|
|
3742
3786
|
}
|
|
3787
|
+
function dateDraft(field, value) {
|
|
3788
|
+
return {
|
|
3789
|
+
kind: value?.kind ?? "withinDays",
|
|
3790
|
+
days: value?.kind === "withinDays" ? value.days : field.defaultDays ?? 30,
|
|
3791
|
+
between: value?.kind === "between" ? { from: value.from, to: value.to } : { from: "", to: "" }
|
|
3792
|
+
};
|
|
3793
|
+
}
|
|
3743
3794
|
function DatePanel({
|
|
3744
3795
|
field,
|
|
3745
3796
|
value,
|
|
@@ -3747,23 +3798,41 @@ function DatePanel({
|
|
|
3747
3798
|
onCommit,
|
|
3748
3799
|
onClose
|
|
3749
3800
|
}) {
|
|
3750
|
-
const defaultDays = field.defaultDays ?? 30;
|
|
3751
3801
|
const maxDays = effectiveMaxDays(field);
|
|
3752
|
-
const [
|
|
3753
|
-
const [
|
|
3754
|
-
|
|
3755
|
-
);
|
|
3756
|
-
const
|
|
3757
|
-
const [between, setBetween] =
|
|
3758
|
-
|
|
3759
|
-
);
|
|
3802
|
+
const [initial] = React25.useState(() => dateDraft(field, value));
|
|
3803
|
+
const [kind, setKind] = React25.useState(initial.kind);
|
|
3804
|
+
const [daysDraft, setDaysDraft] = React25.useState(initial.days);
|
|
3805
|
+
const daysRef = React25.useRef(daysDraft);
|
|
3806
|
+
const daysConfirmed = React25.useRef(value?.kind === "withinDays");
|
|
3807
|
+
const [between, setBetween] = React25.useState(initial.between);
|
|
3808
|
+
const [seed, setSeed] = React25.useState(0);
|
|
3760
3809
|
const shownWithinDays = () => {
|
|
3761
3810
|
const days = daysRef.current;
|
|
3762
3811
|
return applicable(field, days == null ? void 0 : { kind: "withinDays", days }, validity.allValid());
|
|
3763
3812
|
};
|
|
3764
|
-
const validity = useTextValidity(() =>
|
|
3813
|
+
const validity = useTextValidity(() => {
|
|
3814
|
+
daysConfirmed.current = true;
|
|
3815
|
+
onCommit(shownWithinDays());
|
|
3816
|
+
});
|
|
3817
|
+
const applies = () => {
|
|
3818
|
+
if (kind === "between") {
|
|
3819
|
+
return applicable(field, between.from && between.to ? { kind: "between", ...between } : void 0, true);
|
|
3820
|
+
}
|
|
3821
|
+
return daysConfirmed.current ? shownWithinDays() : void 0;
|
|
3822
|
+
};
|
|
3823
|
+
useReseedFromProps(value, applies, (next) => {
|
|
3824
|
+
const d = dateDraft(field, next);
|
|
3825
|
+
setKind(d.kind);
|
|
3826
|
+
daysRef.current = d.days;
|
|
3827
|
+
daysConfirmed.current = next?.kind === "withinDays";
|
|
3828
|
+
setDaysDraft(d.days);
|
|
3829
|
+
setBetween(d.between);
|
|
3830
|
+
validity.reset();
|
|
3831
|
+
setSeed((n) => n + 1);
|
|
3832
|
+
});
|
|
3765
3833
|
const applyWithinDays = (days) => {
|
|
3766
3834
|
daysRef.current = days;
|
|
3835
|
+
daysConfirmed.current = true;
|
|
3767
3836
|
setDaysDraft(days);
|
|
3768
3837
|
onCommit(shownWithinDays());
|
|
3769
3838
|
};
|
|
@@ -3778,8 +3847,10 @@ function DatePanel({
|
|
|
3778
3847
|
setBetween({ from: "", to: "" });
|
|
3779
3848
|
validity.forget("days");
|
|
3780
3849
|
} else {
|
|
3781
|
-
|
|
3782
|
-
|
|
3850
|
+
const { days } = dateDraft(field, void 0);
|
|
3851
|
+
daysRef.current = days;
|
|
3852
|
+
daysConfirmed.current = false;
|
|
3853
|
+
setDaysDraft(days);
|
|
3783
3854
|
}
|
|
3784
3855
|
onCommit(void 0);
|
|
3785
3856
|
};
|
|
@@ -3827,7 +3898,8 @@ function DatePanel({
|
|
|
3827
3898
|
value: daysDraft ?? "",
|
|
3828
3899
|
onChange: (e) => applyWithinDays(e.target.value),
|
|
3829
3900
|
onValidityChange: validity.report("days")
|
|
3830
|
-
}
|
|
3901
|
+
},
|
|
3902
|
+
"days-" + seed
|
|
3831
3903
|
) : /* @__PURE__ */ jsx45(
|
|
3832
3904
|
DatePicker,
|
|
3833
3905
|
{
|
|
@@ -3835,30 +3907,23 @@ function DatePanel({
|
|
|
3835
3907
|
label: "Date range",
|
|
3836
3908
|
value: { start: between.from, end: between.to },
|
|
3837
3909
|
onChange: (e) => applyBetween(e.target.value.start || "", e.target.value.end || "")
|
|
3838
|
-
}
|
|
3910
|
+
},
|
|
3911
|
+
"between-" + seed
|
|
3839
3912
|
)
|
|
3840
3913
|
] })
|
|
3841
3914
|
}
|
|
3842
3915
|
);
|
|
3843
3916
|
}
|
|
3844
3917
|
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 =
|
|
3918
|
+
const [panel, setPanel] = React25.useState(null);
|
|
3919
|
+
const editAnchorRef = React25.useRef(null);
|
|
3920
|
+
const addAnchorRef = React25.useRef(null);
|
|
3921
|
+
const textInputRef = React25.useRef(null);
|
|
3922
|
+
const optionsRef = React25.useRef(null);
|
|
3850
3923
|
if (process.env.NODE_ENV !== "production") {
|
|
3851
3924
|
for (const f of fields) assertValidFieldDefinition(f);
|
|
3852
3925
|
}
|
|
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;
|
|
3926
|
+
const latest = useLatest({ fields, filters, onFilterChange, onFilterRemove });
|
|
3862
3927
|
const commit = (field, candidate) => {
|
|
3863
3928
|
const current2 = latest.current.fields.find((f) => f.key === field.key);
|
|
3864
3929
|
if (!current2) return { ok: false, reason: "This filter is no longer available" };
|
|
@@ -3867,24 +3932,17 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
3867
3932
|
return { ok: true };
|
|
3868
3933
|
}
|
|
3869
3934
|
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
|
-
}
|
|
3935
|
+
if (result.ok) latest.current.onFilterChange(current2.key, candidate);
|
|
3874
3936
|
return result;
|
|
3875
3937
|
};
|
|
3876
3938
|
const removeField = (field) => {
|
|
3877
3939
|
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);
|
|
3940
|
+
if (isFieldSet(field, now[field.key])) remove(field.key);
|
|
3883
3941
|
};
|
|
3884
3942
|
const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
|
|
3885
3943
|
const startEditing = (key) => setPanel({ kind: "edit", key });
|
|
3886
3944
|
const closeEditing = () => setPanel(null);
|
|
3887
|
-
|
|
3945
|
+
React25.useEffect(() => {
|
|
3888
3946
|
if (!panel || panel.kind !== "edit") return;
|
|
3889
3947
|
if (editingField?.type === "text") {
|
|
3890
3948
|
textInputRef.current?.focus();
|
|
@@ -4090,7 +4148,7 @@ function StatTile({ label, value, sub, delta, invert = false, loading = false, c
|
|
|
4090
4148
|
}
|
|
4091
4149
|
|
|
4092
4150
|
// src/components/data/CodeBlock.tsx
|
|
4093
|
-
import * as
|
|
4151
|
+
import * as React26 from "react";
|
|
4094
4152
|
import { Fragment as Fragment6, jsx as jsx47, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
4095
4153
|
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
4154
|
var RULES = {
|
|
@@ -4246,13 +4304,13 @@ function tokenize(src, lang) {
|
|
|
4246
4304
|
return out;
|
|
4247
4305
|
}
|
|
4248
4306
|
function Highlighted({ code, lang }) {
|
|
4249
|
-
const toks =
|
|
4307
|
+
const toks = React26.useMemo(() => tokenize(code, lang), [code, lang]);
|
|
4250
4308
|
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
4309
|
}
|
|
4252
4310
|
function useCopy() {
|
|
4253
|
-
const [done, setDone] =
|
|
4254
|
-
const timer =
|
|
4255
|
-
|
|
4311
|
+
const [done, setDone] = React26.useState(false);
|
|
4312
|
+
const timer = React26.useRef(null);
|
|
4313
|
+
React26.useEffect(() => () => {
|
|
4256
4314
|
if (timer.current) clearTimeout(timer.current);
|
|
4257
4315
|
}, []);
|
|
4258
4316
|
const copy = (text) => {
|
|
@@ -4288,8 +4346,8 @@ function CodeBlock({
|
|
|
4288
4346
|
actions,
|
|
4289
4347
|
className = ""
|
|
4290
4348
|
}) {
|
|
4291
|
-
const [wrap, setWrap] =
|
|
4292
|
-
const [open, setOpen] =
|
|
4349
|
+
const [wrap, setWrap] = React26.useState(!!wrapDefault);
|
|
4350
|
+
const [open, setOpen] = React26.useState(false);
|
|
4293
4351
|
const [copied, copy] = useCopy();
|
|
4294
4352
|
const body = String(code).replace(/\n$/, "");
|
|
4295
4353
|
const lines = body.split("\n");
|
|
@@ -4318,7 +4376,7 @@ function CodeBlock({
|
|
|
4318
4376
|
] });
|
|
4319
4377
|
}
|
|
4320
4378
|
function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
|
|
4321
|
-
const [open, setOpen] =
|
|
4379
|
+
const [open, setOpen] = React26.useState(false);
|
|
4322
4380
|
const [copied, copy] = useCopy();
|
|
4323
4381
|
const raw = String(diff).replace(/\n$/, "");
|
|
4324
4382
|
const all = raw.split("\n").map((line) => {
|
|
@@ -4364,7 +4422,7 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
|
|
|
4364
4422
|
}
|
|
4365
4423
|
|
|
4366
4424
|
// src/components/data/Markdown.tsx
|
|
4367
|
-
import * as
|
|
4425
|
+
import * as React27 from "react";
|
|
4368
4426
|
import { jsx as jsx48, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
4369
4427
|
var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
|
|
4370
4428
|
var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
|
|
@@ -4403,7 +4461,7 @@ function inlineNodes(src, ctx, keyBase) {
|
|
|
4403
4461
|
const href = safeHref(g(2));
|
|
4404
4462
|
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
4463
|
} else if (kind === "cite") {
|
|
4406
|
-
out.push(ctx.renderCitation ? /* @__PURE__ */ jsx48(
|
|
4464
|
+
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
4465
|
} else if (kind === "strongem") out.push(/* @__PURE__ */ jsx48("strong", { children: /* @__PURE__ */ jsx48("em", { children: inlineNodes(g(1), ctx, key()) }) }, key()));
|
|
4408
4466
|
else if (kind === "strong") out.push(/* @__PURE__ */ jsx48("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
4409
4467
|
else if (kind === "em") out.push(/* @__PURE__ */ jsx48("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
@@ -4568,7 +4626,7 @@ function Markdown({
|
|
|
4568
4626
|
onLinkClick
|
|
4569
4627
|
}) {
|
|
4570
4628
|
const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
|
|
4571
|
-
const blocks =
|
|
4629
|
+
const blocks = React27.useMemo(() => parseBlocks(source), [source]);
|
|
4572
4630
|
return /* @__PURE__ */ jsx48("div", { className: ["fd-md", className].filter(Boolean).join(" "), children: renderBlocks(blocks, ctx, "b") });
|
|
4573
4631
|
}
|
|
4574
4632
|
function MarkdownInline({ source = "", className = "", onLinkClick }) {
|
|
@@ -4682,7 +4740,7 @@ function Pagination({
|
|
|
4682
4740
|
}
|
|
4683
4741
|
|
|
4684
4742
|
// src/components/data/RelativeTime.tsx
|
|
4685
|
-
import * as
|
|
4743
|
+
import * as React28 from "react";
|
|
4686
4744
|
import { jsxs as jsxs45 } from "react/jsx-runtime";
|
|
4687
4745
|
var MIN = 6e4;
|
|
4688
4746
|
var HOUR = 36e5;
|
|
@@ -4734,9 +4792,9 @@ function formatDuration(ms) {
|
|
|
4734
4792
|
return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
|
|
4735
4793
|
}
|
|
4736
4794
|
function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
|
|
4737
|
-
const [, force] =
|
|
4795
|
+
const [, force] = React28.useState(0);
|
|
4738
4796
|
const t = value instanceof Date ? value.getTime() : Date.parse(value);
|
|
4739
|
-
|
|
4797
|
+
React28.useEffect(() => {
|
|
4740
4798
|
if (!refresh2 || !t || isNaN(t)) return;
|
|
4741
4799
|
const abs = Math.abs(t - Date.now());
|
|
4742
4800
|
if (abs > DAY) return;
|
|
@@ -4752,7 +4810,7 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
|
|
|
4752
4810
|
}
|
|
4753
4811
|
|
|
4754
4812
|
// src/components/data/ScoreMeter.tsx
|
|
4755
|
-
import * as
|
|
4813
|
+
import * as React29 from "react";
|
|
4756
4814
|
import { jsx as jsx51, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
4757
4815
|
function ScoreMeter({
|
|
4758
4816
|
score,
|
|
@@ -4767,10 +4825,10 @@ function ScoreMeter({
|
|
|
4767
4825
|
breakdownWidth = 280,
|
|
4768
4826
|
className = ""
|
|
4769
4827
|
}) {
|
|
4770
|
-
const [open, setOpen] =
|
|
4771
|
-
const ref =
|
|
4828
|
+
const [open, setOpen] = React29.useState(false);
|
|
4829
|
+
const ref = React29.useRef(null);
|
|
4772
4830
|
const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
|
|
4773
|
-
const body = /* @__PURE__ */ jsxs46(
|
|
4831
|
+
const body = /* @__PURE__ */ jsxs46(React29.Fragment, { children: [
|
|
4774
4832
|
/* @__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
4833
|
showScore ? /* @__PURE__ */ jsx51("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
|
|
4776
4834
|
] });
|
|
@@ -4789,7 +4847,7 @@ function ScoreMeter({
|
|
|
4789
4847
|
}
|
|
4790
4848
|
);
|
|
4791
4849
|
}
|
|
4792
|
-
return /* @__PURE__ */ jsxs46(
|
|
4850
|
+
return /* @__PURE__ */ jsxs46(React29.Fragment, { children: [
|
|
4793
4851
|
/* @__PURE__ */ jsx51(
|
|
4794
4852
|
"button",
|
|
4795
4853
|
{
|
|
@@ -4820,13 +4878,13 @@ function ScoreMeter({
|
|
|
4820
4878
|
}
|
|
4821
4879
|
|
|
4822
4880
|
// src/components/data/SortMenu.tsx
|
|
4823
|
-
import * as
|
|
4881
|
+
import * as React30 from "react";
|
|
4824
4882
|
import { jsx as jsx52, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
4825
4883
|
function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", className = "", ...rest }) {
|
|
4826
|
-
const [open, setOpen] =
|
|
4884
|
+
const [open, setOpen] = React30.useState(false);
|
|
4827
4885
|
const zIndex = useOverlayLayer(open);
|
|
4828
|
-
const ref =
|
|
4829
|
-
|
|
4886
|
+
const ref = React30.useRef(null);
|
|
4887
|
+
React30.useEffect(() => {
|
|
4830
4888
|
if (!open) return;
|
|
4831
4889
|
const away = (e) => {
|
|
4832
4890
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -4888,7 +4946,7 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
|
|
|
4888
4946
|
}
|
|
4889
4947
|
|
|
4890
4948
|
// src/components/data/StepList.tsx
|
|
4891
|
-
import * as
|
|
4949
|
+
import * as React31 from "react";
|
|
4892
4950
|
import { jsx as jsx53, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
4893
4951
|
var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
|
|
4894
4952
|
function StepList({
|
|
@@ -4901,9 +4959,9 @@ function StepList({
|
|
|
4901
4959
|
dense = false,
|
|
4902
4960
|
className = ""
|
|
4903
4961
|
}) {
|
|
4904
|
-
const [openState, setOpenState] =
|
|
4962
|
+
const [openState, setOpenState] = React31.useState(defaultOpen);
|
|
4905
4963
|
const open = openProp == null ? openState : openProp;
|
|
4906
|
-
const [expanded, setExpanded] =
|
|
4964
|
+
const [expanded, setExpanded] = React31.useState({});
|
|
4907
4965
|
if (!steps.length) return null;
|
|
4908
4966
|
const running = steps.some((s) => s.status === "running");
|
|
4909
4967
|
const failed = steps.filter((s) => s.status === "error").length;
|
|
@@ -4961,7 +5019,7 @@ function StepList({
|
|
|
4961
5019
|
}
|
|
4962
5020
|
|
|
4963
5021
|
// src/components/data/VirtualList.tsx
|
|
4964
|
-
import * as
|
|
5022
|
+
import * as React32 from "react";
|
|
4965
5023
|
import { jsx as jsx54, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
4966
5024
|
var VIRTUAL_LIST_BUFFER_ROWS = 20;
|
|
4967
5025
|
var VIRTUAL_LIST_ROW_GAP = 6;
|
|
@@ -5013,35 +5071,35 @@ function VirtualList({
|
|
|
5013
5071
|
className = "",
|
|
5014
5072
|
style
|
|
5015
5073
|
}) {
|
|
5016
|
-
const [scrollTop, setScrollTop] =
|
|
5017
|
-
const loaded =
|
|
5074
|
+
const [scrollTop, setScrollTop] = React32.useState(0);
|
|
5075
|
+
const loaded = React32.useMemo(
|
|
5018
5076
|
() => ({ firstItemIndex, count: items.length }),
|
|
5019
5077
|
[firstItemIndex, items.length]
|
|
5020
5078
|
);
|
|
5021
5079
|
const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
|
|
5022
5080
|
const bandKey = firstItemIndex + ":" + items.length;
|
|
5023
|
-
const win =
|
|
5081
|
+
const win = React32.useMemo(
|
|
5024
5082
|
() => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
|
|
5025
5083
|
[scrollTop, height, itemHeight, total, loaded]
|
|
5026
5084
|
);
|
|
5027
|
-
const need =
|
|
5085
|
+
const need = React32.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
|
|
5028
5086
|
const wantStart = need.start && hasMore?.start !== false;
|
|
5029
5087
|
const wantEnd = need.end && hasMore?.end !== false;
|
|
5030
5088
|
const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
|
|
5031
5089
|
const askKey = bandKey + "@" + bucket2;
|
|
5032
|
-
const asked =
|
|
5033
|
-
|
|
5090
|
+
const asked = React32.useRef({ start: null, end: null });
|
|
5091
|
+
React32.useEffect(() => {
|
|
5034
5092
|
if (loading || !wantStart || asked.current.start === askKey) return;
|
|
5035
5093
|
asked.current.start = askKey;
|
|
5036
5094
|
onNeedMore("start", win);
|
|
5037
5095
|
}, [wantStart, loading, askKey, onNeedMore, win]);
|
|
5038
|
-
|
|
5096
|
+
React32.useEffect(() => {
|
|
5039
5097
|
if (loading || !wantEnd || asked.current.end === askKey) return;
|
|
5040
5098
|
asked.current.end = askKey;
|
|
5041
5099
|
onNeedMore("end", win);
|
|
5042
5100
|
}, [wantEnd, loading, askKey, onNeedMore, win]);
|
|
5043
|
-
const lastKeysRef =
|
|
5044
|
-
const newKeys =
|
|
5101
|
+
const lastKeysRef = React32.useRef(null);
|
|
5102
|
+
const newKeys = React32.useMemo(() => {
|
|
5045
5103
|
const prev = lastKeysRef.current;
|
|
5046
5104
|
if (!prev) return /* @__PURE__ */ new Set();
|
|
5047
5105
|
const fresh = /* @__PURE__ */ new Set();
|
|
@@ -5051,7 +5109,7 @@ function VirtualList({
|
|
|
5051
5109
|
}
|
|
5052
5110
|
return fresh;
|
|
5053
5111
|
}, [items]);
|
|
5054
|
-
|
|
5112
|
+
React32.useEffect(() => {
|
|
5055
5113
|
lastKeysRef.current = new Set(items.map(keyOf));
|
|
5056
5114
|
}, [items]);
|
|
5057
5115
|
const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
|
|
@@ -5096,7 +5154,7 @@ function VirtualList({
|
|
|
5096
5154
|
}
|
|
5097
5155
|
|
|
5098
5156
|
// src/components/data/EntityRow.tsx
|
|
5099
|
-
import * as
|
|
5157
|
+
import * as React33 from "react";
|
|
5100
5158
|
import { jsx as jsx55, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
5101
5159
|
var ENTITY_ROW_METRIC_WIDTH = 74;
|
|
5102
5160
|
var METRIC_TONE_COLOR = {
|
|
@@ -5109,7 +5167,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
|
|
|
5109
5167
|
const key = m.id || m.label || i;
|
|
5110
5168
|
const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
|
|
5111
5169
|
const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
|
|
5112
|
-
const content = /* @__PURE__ */ jsxs50(
|
|
5170
|
+
const content = /* @__PURE__ */ jsxs50(React33.Fragment, { children: [
|
|
5113
5171
|
m.icon ? /* @__PURE__ */ jsx55("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
|
|
5114
5172
|
/* @__PURE__ */ jsx55("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
|
|
5115
5173
|
/* @__PURE__ */ jsx55("span", { className: "fd-sr", children: " " + m.label })
|
|
@@ -5201,7 +5259,7 @@ function EntityRow({
|
|
|
5201
5259
|
}
|
|
5202
5260
|
|
|
5203
5261
|
// src/components/data/TransferList.tsx
|
|
5204
|
-
import * as
|
|
5262
|
+
import * as React34 from "react";
|
|
5205
5263
|
import { createPortal as createPortal4 } from "react-dom";
|
|
5206
5264
|
|
|
5207
5265
|
// src/components/forms/Input.tsx
|
|
@@ -5307,12 +5365,12 @@ function TransferList({
|
|
|
5307
5365
|
listHeight = 440,
|
|
5308
5366
|
className = ""
|
|
5309
5367
|
}) {
|
|
5310
|
-
const [drag, setDrag] =
|
|
5311
|
-
const [dragOverSide, setDragOverSide] =
|
|
5312
|
-
const dragRef =
|
|
5313
|
-
const armedRef =
|
|
5314
|
-
const sideRefs =
|
|
5315
|
-
const hitTestSide =
|
|
5368
|
+
const [drag, setDrag] = React34.useState(null);
|
|
5369
|
+
const [dragOverSide, setDragOverSide] = React34.useState(null);
|
|
5370
|
+
const dragRef = React34.useRef(null);
|
|
5371
|
+
const armedRef = React34.useRef(null);
|
|
5372
|
+
const sideRefs = React34.useRef({ left: null, right: null });
|
|
5373
|
+
const hitTestSide = React34.useCallback((x, y) => {
|
|
5316
5374
|
for (const side of ["left", "right"]) {
|
|
5317
5375
|
const el = sideRefs.current[side];
|
|
5318
5376
|
if (!el) continue;
|
|
@@ -5321,7 +5379,7 @@ function TransferList({
|
|
|
5321
5379
|
}
|
|
5322
5380
|
return null;
|
|
5323
5381
|
}, []);
|
|
5324
|
-
const findItem =
|
|
5382
|
+
const findItem = React34.useCallback(
|
|
5325
5383
|
(side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
|
|
5326
5384
|
[left.items, right.items, keyOf]
|
|
5327
5385
|
);
|
|
@@ -5343,7 +5401,7 @@ function TransferList({
|
|
|
5343
5401
|
height: rect.height
|
|
5344
5402
|
};
|
|
5345
5403
|
};
|
|
5346
|
-
|
|
5404
|
+
React34.useEffect(() => {
|
|
5347
5405
|
const onMovePointer = (e) => {
|
|
5348
5406
|
const armed = armedRef.current;
|
|
5349
5407
|
if (!armed || e.pointerId !== armed.pointerId) return;
|
|
@@ -5396,7 +5454,7 @@ function TransferList({
|
|
|
5396
5454
|
window.removeEventListener("pointercancel", endDrag);
|
|
5397
5455
|
};
|
|
5398
5456
|
}, [hitTestSide, findItem, onMove]);
|
|
5399
|
-
|
|
5457
|
+
React34.useEffect(() => {
|
|
5400
5458
|
if (!drag || typeof document === "undefined") return;
|
|
5401
5459
|
const prev = document.body.style.userSelect;
|
|
5402
5460
|
document.body.style.userSelect = "none";
|
|
@@ -5504,11 +5562,11 @@ function TransferList({
|
|
|
5504
5562
|
}
|
|
5505
5563
|
|
|
5506
5564
|
// src/components/forms/Checkbox.tsx
|
|
5507
|
-
import * as
|
|
5565
|
+
import * as React35 from "react";
|
|
5508
5566
|
import { jsx as jsx59, jsxs as jsxs53 } from "react/jsx-runtime";
|
|
5509
5567
|
function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
|
|
5510
|
-
const ref =
|
|
5511
|
-
|
|
5568
|
+
const ref = React35.useRef(null);
|
|
5569
|
+
React35.useEffect(() => {
|
|
5512
5570
|
if (ref.current) ref.current.indeterminate = indeterminate;
|
|
5513
5571
|
}, [indeterminate]);
|
|
5514
5572
|
return /* @__PURE__ */ jsxs53("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
@@ -5552,7 +5610,7 @@ function Switch({ label, description, className = "", ...rest }) {
|
|
|
5552
5610
|
}
|
|
5553
5611
|
|
|
5554
5612
|
// src/components/forms/Select.tsx
|
|
5555
|
-
import * as
|
|
5613
|
+
import * as React36 from "react";
|
|
5556
5614
|
import { jsx as jsx62, jsxs as jsxs56 } from "react/jsx-runtime";
|
|
5557
5615
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
5558
5616
|
function Select({
|
|
@@ -5579,12 +5637,12 @@ function Select({
|
|
|
5579
5637
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
5580
5638
|
const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
|
|
5581
5639
|
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 =
|
|
5640
|
+
const [open, setOpen] = React36.useState(false);
|
|
5641
|
+
const [q, setQ] = React36.useState("");
|
|
5642
|
+
const rootRef = React36.useRef(null);
|
|
5643
|
+
const boxRef = React36.useRef(null);
|
|
5644
|
+
const listRef = React36.useRef(null);
|
|
5645
|
+
const typeBuf = React36.useRef({ s: "", t: 0 });
|
|
5588
5646
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
5589
5647
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
5590
5648
|
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 +5781,7 @@ function Select({
|
|
|
5723
5781
|
),
|
|
5724
5782
|
q ? /* @__PURE__ */ jsx62("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
5725
5783
|
] }) : void 0,
|
|
5726
|
-
footer: multiple ? /* @__PURE__ */ jsxs56(
|
|
5784
|
+
footer: multiple ? /* @__PURE__ */ jsxs56(React36.Fragment, { children: [
|
|
5727
5785
|
/* @__PURE__ */ jsx62(
|
|
5728
5786
|
"button",
|
|
5729
5787
|
{
|
|
@@ -5754,7 +5812,7 @@ function Select({
|
|
|
5754
5812
|
'Nothing matches "',
|
|
5755
5813
|
q,
|
|
5756
5814
|
'".'
|
|
5757
|
-
] }) : groups.map((grp) => /* @__PURE__ */ jsxs56(
|
|
5815
|
+
] }) : groups.map((grp) => /* @__PURE__ */ jsxs56(React36.Fragment, { children: [
|
|
5758
5816
|
grp.g ? /* @__PURE__ */ jsx62("div", { className: "fd-pop-group", children: grp.g }) : null,
|
|
5759
5817
|
grp.items.map(({ o, i }) => /* @__PURE__ */ jsxs56(
|
|
5760
5818
|
"button",
|
|
@@ -5791,7 +5849,7 @@ function Select({
|
|
|
5791
5849
|
}
|
|
5792
5850
|
|
|
5793
5851
|
// src/components/forms/TimePicker.tsx
|
|
5794
|
-
import * as
|
|
5852
|
+
import * as React37 from "react";
|
|
5795
5853
|
import { jsx as jsx63, jsxs as jsxs57 } from "react/jsx-runtime";
|
|
5796
5854
|
var pad = (n) => String(n).padStart(2, "0");
|
|
5797
5855
|
function ClockFace({ value = "09:00", onChange }) {
|
|
@@ -5800,9 +5858,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
5800
5858
|
if (isNaN(m)) m = 0;
|
|
5801
5859
|
const pm = h24 >= 12;
|
|
5802
5860
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
5803
|
-
const [mode2, setMode] =
|
|
5804
|
-
const faceRef =
|
|
5805
|
-
const dragging =
|
|
5861
|
+
const [mode2, setMode] = React37.useState("h");
|
|
5862
|
+
const faceRef = React37.useRef(null);
|
|
5863
|
+
const dragging = React37.useRef(false);
|
|
5806
5864
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
5807
5865
|
const R = 108, NR = 80;
|
|
5808
5866
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -5875,9 +5933,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
5875
5933
|
}
|
|
5876
5934
|
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
|
|
5877
5935
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
5878
|
-
const [open, setOpen] =
|
|
5879
|
-
const rootRef =
|
|
5880
|
-
const boxRef =
|
|
5936
|
+
const [open, setOpen] = React37.useState(false);
|
|
5937
|
+
const rootRef = React37.useRef(null);
|
|
5938
|
+
const boxRef = React37.useRef(null);
|
|
5881
5939
|
const disp = () => {
|
|
5882
5940
|
if (!value) return "";
|
|
5883
5941
|
const [h, m] = value.split(":").map(Number);
|
|
@@ -5920,7 +5978,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
5920
5978
|
offset: 6,
|
|
5921
5979
|
width: 262,
|
|
5922
5980
|
role: "presentation",
|
|
5923
|
-
footer: /* @__PURE__ */ jsxs57(
|
|
5981
|
+
footer: /* @__PURE__ */ jsxs57(React37.Fragment, { children: [
|
|
5924
5982
|
/* @__PURE__ */ jsx63(
|
|
5925
5983
|
"button",
|
|
5926
5984
|
{
|
|
@@ -5948,7 +6006,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
5948
6006
|
}
|
|
5949
6007
|
|
|
5950
6008
|
// src/components/forms/Slider.tsx
|
|
5951
|
-
import * as
|
|
6009
|
+
import * as React38 from "react";
|
|
5952
6010
|
import { jsx as jsx64, jsxs as jsxs58 } from "react/jsx-runtime";
|
|
5953
6011
|
function Slider({
|
|
5954
6012
|
label,
|
|
@@ -5966,7 +6024,7 @@ function Slider({
|
|
|
5966
6024
|
...rest
|
|
5967
6025
|
}) {
|
|
5968
6026
|
const fieldId = useFieldId(id);
|
|
5969
|
-
const [dragging, setDragging] =
|
|
6027
|
+
const [dragging, setDragging] = React38.useState(false);
|
|
5970
6028
|
const v = value === void 0 ? min : Number(value);
|
|
5971
6029
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
5972
6030
|
return /* @__PURE__ */ jsxs58("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
|
|
@@ -6000,7 +6058,7 @@ function Slider({
|
|
|
6000
6058
|
}
|
|
6001
6059
|
|
|
6002
6060
|
// src/components/forms/RangeSlider.tsx
|
|
6003
|
-
import * as
|
|
6061
|
+
import * as React39 from "react";
|
|
6004
6062
|
import { jsx as jsx65, jsxs as jsxs59 } from "react/jsx-runtime";
|
|
6005
6063
|
function RangeSlider({
|
|
6006
6064
|
label,
|
|
@@ -6020,9 +6078,9 @@ function RangeSlider({
|
|
|
6020
6078
|
}) {
|
|
6021
6079
|
const fmt2 = format || ((v) => String(v));
|
|
6022
6080
|
const [a, b] = value || [min, max];
|
|
6023
|
-
const [drag, setDrag] =
|
|
6024
|
-
const [focus, setFocus] =
|
|
6025
|
-
const railRef =
|
|
6081
|
+
const [drag, setDrag] = React39.useState(null);
|
|
6082
|
+
const [focus, setFocus] = React39.useState(null);
|
|
6083
|
+
const railRef = React39.useRef(null);
|
|
6026
6084
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
6027
6085
|
const clampPair = (i, v) => {
|
|
6028
6086
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -6037,7 +6095,7 @@ function RangeSlider({
|
|
|
6037
6095
|
const r = railRef.current.getBoundingClientRect();
|
|
6038
6096
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
6039
6097
|
};
|
|
6040
|
-
|
|
6098
|
+
React39.useEffect(() => {
|
|
6041
6099
|
if (drag === null) return;
|
|
6042
6100
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
6043
6101
|
const upH = () => setDrag(null);
|
|
@@ -6118,7 +6176,7 @@ function RangeSlider({
|
|
|
6118
6176
|
/* @__PURE__ */ jsxs59("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
|
|
6119
6177
|
/* @__PURE__ */ jsx65("span", { className: "fd-range-rail", ref: railRef }),
|
|
6120
6178
|
/* @__PURE__ */ jsx65("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
|
|
6121
|
-
marks.map((m) => /* @__PURE__ */ jsxs59(
|
|
6179
|
+
marks.map((m) => /* @__PURE__ */ jsxs59(React39.Fragment, { children: [
|
|
6122
6180
|
/* @__PURE__ */ jsx65("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
|
|
6123
6181
|
m.label ? /* @__PURE__ */ jsx65("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
|
|
6124
6182
|
] }, m.value)),
|
|
@@ -6147,7 +6205,7 @@ function RangeSlider({
|
|
|
6147
6205
|
}
|
|
6148
6206
|
|
|
6149
6207
|
// src/components/forms/Dropzone.tsx
|
|
6150
|
-
import * as
|
|
6208
|
+
import * as React40 from "react";
|
|
6151
6209
|
import { jsx as jsx66, jsxs as jsxs60 } from "react/jsx-runtime";
|
|
6152
6210
|
function Dropzone({
|
|
6153
6211
|
onFiles,
|
|
@@ -6162,8 +6220,8 @@ function Dropzone({
|
|
|
6162
6220
|
className = "",
|
|
6163
6221
|
style
|
|
6164
6222
|
}) {
|
|
6165
|
-
const [over, setOver] =
|
|
6166
|
-
const depth =
|
|
6223
|
+
const [over, setOver] = React40.useState(false);
|
|
6224
|
+
const depth = React40.useRef(0);
|
|
6167
6225
|
const has = (e) => {
|
|
6168
6226
|
const dt = e.dataTransfer;
|
|
6169
6227
|
if (!dt) return false;
|
|
@@ -6225,8 +6283,8 @@ function FilePickButton({
|
|
|
6225
6283
|
className = "",
|
|
6226
6284
|
children
|
|
6227
6285
|
}) {
|
|
6228
|
-
const ref =
|
|
6229
|
-
return /* @__PURE__ */ jsxs60(
|
|
6286
|
+
const ref = React40.useRef(null);
|
|
6287
|
+
return /* @__PURE__ */ jsxs60(React40.Fragment, { children: [
|
|
6230
6288
|
/* @__PURE__ */ jsx66(
|
|
6231
6289
|
"button",
|
|
6232
6290
|
{
|
|
@@ -6259,10 +6317,10 @@ function FilePickButton({
|
|
|
6259
6317
|
}
|
|
6260
6318
|
function useStagedFiles(upload, opts) {
|
|
6261
6319
|
const o = opts || {};
|
|
6262
|
-
const [items, setItems] =
|
|
6263
|
-
const controllers =
|
|
6320
|
+
const [items, setItems] = React40.useState([]);
|
|
6321
|
+
const controllers = React40.useRef({});
|
|
6264
6322
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
6265
|
-
const run =
|
|
6323
|
+
const run = React40.useCallback((att) => {
|
|
6266
6324
|
if (!upload) return;
|
|
6267
6325
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
6268
6326
|
controllers.current[att.id] = ac;
|
|
@@ -6279,14 +6337,14 @@ function useStagedFiles(upload, opts) {
|
|
|
6279
6337
|
delete controllers.current[att.id];
|
|
6280
6338
|
});
|
|
6281
6339
|
}, [upload]);
|
|
6282
|
-
const add =
|
|
6340
|
+
const add = React40.useCallback((files) => {
|
|
6283
6341
|
if (!upload) return [];
|
|
6284
6342
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
6285
6343
|
setItems((list) => list.concat(atts));
|
|
6286
6344
|
atts.forEach(run);
|
|
6287
6345
|
return atts;
|
|
6288
6346
|
}, [upload, run]);
|
|
6289
|
-
const remove =
|
|
6347
|
+
const remove = React40.useCallback((att) => {
|
|
6290
6348
|
const ac = controllers.current[att.id];
|
|
6291
6349
|
if (ac) {
|
|
6292
6350
|
try {
|
|
@@ -6297,10 +6355,10 @@ function useStagedFiles(upload, opts) {
|
|
|
6297
6355
|
}
|
|
6298
6356
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
6299
6357
|
}, []);
|
|
6300
|
-
const retry =
|
|
6358
|
+
const retry = React40.useCallback((att) => {
|
|
6301
6359
|
run(att);
|
|
6302
6360
|
}, [run]);
|
|
6303
|
-
const clear =
|
|
6361
|
+
const clear = React40.useCallback(() => {
|
|
6304
6362
|
Object.values(controllers.current).forEach((ac) => {
|
|
6305
6363
|
try {
|
|
6306
6364
|
ac && ac.abort();
|
|
@@ -6424,7 +6482,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
6424
6482
|
}
|
|
6425
6483
|
|
|
6426
6484
|
// src/components/forms/MarkdownEditor.tsx
|
|
6427
|
-
import * as
|
|
6485
|
+
import * as React41 from "react";
|
|
6428
6486
|
import { jsx as jsx68, jsxs as jsxs62 } from "react/jsx-runtime";
|
|
6429
6487
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
6430
6488
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
@@ -6638,7 +6696,7 @@ function syncDom(root, value) {
|
|
|
6638
6696
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
6639
6697
|
}
|
|
6640
6698
|
var LIST_CONT = RE_LI;
|
|
6641
|
-
var MarkdownEditor =
|
|
6699
|
+
var MarkdownEditor = React41.forwardRef(function MarkdownEditor2({
|
|
6642
6700
|
value = "",
|
|
6643
6701
|
onChange,
|
|
6644
6702
|
onSubmit,
|
|
@@ -6657,10 +6715,10 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6657
6715
|
className = "",
|
|
6658
6716
|
id
|
|
6659
6717
|
}, ref) {
|
|
6660
|
-
const boxRef =
|
|
6661
|
-
const composing =
|
|
6662
|
-
const pendingCaret =
|
|
6663
|
-
|
|
6718
|
+
const boxRef = React41.useRef(null);
|
|
6719
|
+
const composing = React41.useRef(false);
|
|
6720
|
+
const pendingCaret = React41.useRef(null);
|
|
6721
|
+
React41.useLayoutEffect(() => {
|
|
6664
6722
|
const root = boxRef.current;
|
|
6665
6723
|
if (!root || composing.current) return;
|
|
6666
6724
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -6669,7 +6727,7 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6669
6727
|
pendingCaret.current = null;
|
|
6670
6728
|
if (active && caret != null) placeCaret(root, caret);
|
|
6671
6729
|
}, [value]);
|
|
6672
|
-
|
|
6730
|
+
React41.useEffect(() => {
|
|
6673
6731
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
6674
6732
|
}, [autoFocus]);
|
|
6675
6733
|
const caretNow = () => {
|
|
@@ -6736,7 +6794,7 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6736
6794
|
api.replaceRange(from, to, next, from + next.length);
|
|
6737
6795
|
}
|
|
6738
6796
|
};
|
|
6739
|
-
|
|
6797
|
+
React41.useImperativeHandle(ref, () => api);
|
|
6740
6798
|
function detect(text, caret) {
|
|
6741
6799
|
if (!onTrigger) return;
|
|
6742
6800
|
const upto = text.slice(0, caret);
|
|
@@ -6888,16 +6946,16 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6888
6946
|
});
|
|
6889
6947
|
|
|
6890
6948
|
// src/components/platform/AccountMenu.tsx
|
|
6891
|
-
import * as
|
|
6949
|
+
import * as React43 from "react";
|
|
6892
6950
|
|
|
6893
6951
|
// src/kits/sessionContext.tsx
|
|
6894
|
-
import * as
|
|
6895
|
-
var SessionContext =
|
|
6952
|
+
import * as React42 from "react";
|
|
6953
|
+
var SessionContext = React42.createContext(null);
|
|
6896
6954
|
function SessionProvider({ value, children }) {
|
|
6897
|
-
return
|
|
6955
|
+
return React42.createElement(SessionContext.Provider, { value }, children);
|
|
6898
6956
|
}
|
|
6899
6957
|
function useSessionContext() {
|
|
6900
|
-
const ctx =
|
|
6958
|
+
const ctx = React42.useContext(SessionContext);
|
|
6901
6959
|
if (!ctx) {
|
|
6902
6960
|
throw new Error(
|
|
6903
6961
|
"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 +6995,11 @@ function AccountMenu({
|
|
|
6937
6995
|
...rest
|
|
6938
6996
|
}) {
|
|
6939
6997
|
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 =
|
|
6998
|
+
const [open, setOpen] = React43.useState(false);
|
|
6999
|
+
const [switching, setSwitching] = React43.useState(false);
|
|
7000
|
+
const [signingOut, setSigningOut] = React43.useState(false);
|
|
7001
|
+
const [signOutError, setSignOutError] = React43.useState(null);
|
|
7002
|
+
const ref = React43.useRef(null);
|
|
6945
7003
|
const visibleLinks = links.filter((l) => !l.perm || can2(l.perm));
|
|
6946
7004
|
const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || can2(l.perm)) })).filter((g) => g.links.length);
|
|
6947
7005
|
const closeMenu = () => {
|
|
@@ -7066,13 +7124,13 @@ function AccountMenu({
|
|
|
7066
7124
|
}
|
|
7067
7125
|
|
|
7068
7126
|
// src/components/platform/AppSwitcher.tsx
|
|
7069
|
-
import * as
|
|
7127
|
+
import * as React44 from "react";
|
|
7070
7128
|
import { jsx as jsx70, jsxs as jsxs64 } from "react/jsx-runtime";
|
|
7071
7129
|
function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
7072
7130
|
const { apps: contextApps } = useSessionContext();
|
|
7073
7131
|
const apps = appsProp ?? contextApps ?? [];
|
|
7074
|
-
const [open, setOpen] =
|
|
7075
|
-
const anchorRef =
|
|
7132
|
+
const [open, setOpen] = React44.useState(false);
|
|
7133
|
+
const anchorRef = React44.useRef(null);
|
|
7076
7134
|
if (!apps.length) return null;
|
|
7077
7135
|
const items = apps.map((app) => ({
|
|
7078
7136
|
id: app.key,
|
|
@@ -7086,7 +7144,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7086
7144
|
window.location.href = app.url;
|
|
7087
7145
|
}
|
|
7088
7146
|
}));
|
|
7089
|
-
return /* @__PURE__ */ jsxs64(
|
|
7147
|
+
return /* @__PURE__ */ jsxs64(React44.Fragment, { children: [
|
|
7090
7148
|
/* @__PURE__ */ jsx70("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx70(
|
|
7091
7149
|
IconButton,
|
|
7092
7150
|
{
|
|
@@ -7115,10 +7173,10 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7115
7173
|
}
|
|
7116
7174
|
|
|
7117
7175
|
// src/components/platform/AppearanceMenu.tsx
|
|
7118
|
-
import * as
|
|
7176
|
+
import * as React46 from "react";
|
|
7119
7177
|
|
|
7120
7178
|
// src/kits/appearance.ts
|
|
7121
|
-
import * as
|
|
7179
|
+
import * as React45 from "react";
|
|
7122
7180
|
var DEFAULT_STORAGE_KEY = "fd-appearance";
|
|
7123
7181
|
var DEFAULT_PREFS = {
|
|
7124
7182
|
theme: "system",
|
|
@@ -7213,11 +7271,11 @@ function applyPrefs(prefs, root = document.documentElement) {
|
|
|
7213
7271
|
else root.removeAttribute("data-motion");
|
|
7214
7272
|
}
|
|
7215
7273
|
function useAppearancePrefs(store) {
|
|
7216
|
-
const prefs =
|
|
7217
|
-
|
|
7274
|
+
const prefs = React45.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
7275
|
+
React45.useEffect(() => {
|
|
7218
7276
|
applyPrefs(prefs);
|
|
7219
7277
|
}, [prefs]);
|
|
7220
|
-
|
|
7278
|
+
React45.useEffect(() => {
|
|
7221
7279
|
if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
7222
7280
|
return;
|
|
7223
7281
|
}
|
|
@@ -7226,7 +7284,7 @@ function useAppearancePrefs(store) {
|
|
|
7226
7284
|
mq.addEventListener("change", onChange);
|
|
7227
7285
|
return () => mq.removeEventListener("change", onChange);
|
|
7228
7286
|
}, [prefs]);
|
|
7229
|
-
const update =
|
|
7287
|
+
const update = React45.useCallback(
|
|
7230
7288
|
(patch) => {
|
|
7231
7289
|
store.write({ ...store.getSnapshot(), ...patch });
|
|
7232
7290
|
},
|
|
@@ -7249,15 +7307,15 @@ var TEXT_SCALE_OPTIONS = [
|
|
|
7249
7307
|
{ value: "xl", label: "XL" }
|
|
7250
7308
|
];
|
|
7251
7309
|
function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
|
|
7252
|
-
const store =
|
|
7310
|
+
const store = React46.useMemo(
|
|
7253
7311
|
() => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
|
|
7254
7312
|
[storeProp, storageKey, storage, defaults]
|
|
7255
7313
|
);
|
|
7256
7314
|
const [prefs, update] = useAppearancePrefs(store);
|
|
7257
|
-
const [open, setOpen] =
|
|
7258
|
-
const anchorRef =
|
|
7315
|
+
const [open, setOpen] = React46.useState(false);
|
|
7316
|
+
const anchorRef = React46.useRef(null);
|
|
7259
7317
|
const patch = (p) => update(p);
|
|
7260
|
-
return /* @__PURE__ */ jsxs65(
|
|
7318
|
+
return /* @__PURE__ */ jsxs65(React46.Fragment, { children: [
|
|
7261
7319
|
/* @__PURE__ */ jsx71("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx71(
|
|
7262
7320
|
IconButton,
|
|
7263
7321
|
{
|
|
@@ -7326,14 +7384,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7326
7384
|
}
|
|
7327
7385
|
|
|
7328
7386
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
7329
|
-
import * as
|
|
7387
|
+
import * as React47 from "react";
|
|
7330
7388
|
import { jsx as jsx72, jsxs as jsxs66 } from "react/jsx-runtime";
|
|
7331
7389
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
7332
7390
|
function Json({ obj }) {
|
|
7333
7391
|
return /* @__PURE__ */ jsx72("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
7334
7392
|
}
|
|
7335
7393
|
function Endpoint({ s, onRequest }) {
|
|
7336
|
-
const [tried, setTried] =
|
|
7394
|
+
const [tried, setTried] = React47.useState(null);
|
|
7337
7395
|
const run = async () => {
|
|
7338
7396
|
setTried("busy");
|
|
7339
7397
|
const t0 = (window.performance || Date).now();
|
|
@@ -7406,10 +7464,10 @@ function ApiSpecBrowser({
|
|
|
7406
7464
|
className = "",
|
|
7407
7465
|
...rest
|
|
7408
7466
|
}) {
|
|
7409
|
-
const [q, setQ] =
|
|
7410
|
-
const [method, setMethod] =
|
|
7411
|
-
const [mod, setMod] =
|
|
7412
|
-
const [listOnly, setListOnly] =
|
|
7467
|
+
const [q, setQ] = React47.useState("");
|
|
7468
|
+
const [method, setMethod] = React47.useState(null);
|
|
7469
|
+
const [mod, setMod] = React47.useState(null);
|
|
7470
|
+
const [listOnly, setListOnly] = React47.useState(false);
|
|
7413
7471
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
7414
7472
|
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
7473
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
@@ -7488,7 +7546,7 @@ function ApiSpecBrowser({
|
|
|
7488
7546
|
}
|
|
7489
7547
|
|
|
7490
7548
|
// src/components/platform/ProfilePage.tsx
|
|
7491
|
-
import * as
|
|
7549
|
+
import * as React48 from "react";
|
|
7492
7550
|
import { jsx as jsx73, jsxs as jsxs67 } from "react/jsx-runtime";
|
|
7493
7551
|
function fieldInitialValue(field, user) {
|
|
7494
7552
|
if (field.value) return field.value(user);
|
|
@@ -7524,21 +7582,21 @@ function ProfilePage({
|
|
|
7524
7582
|
}) {
|
|
7525
7583
|
const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
|
|
7526
7584
|
const user = userProp || sessionUser;
|
|
7527
|
-
const initialFieldValues =
|
|
7585
|
+
const initialFieldValues = React48.useMemo(() => {
|
|
7528
7586
|
const values2 = {};
|
|
7529
7587
|
for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
|
|
7530
7588
|
return values2;
|
|
7531
7589
|
}, [user.id, fields]);
|
|
7532
|
-
const initialNotify =
|
|
7590
|
+
const initialNotify = React48.useMemo(() => {
|
|
7533
7591
|
const values2 = {};
|
|
7534
7592
|
for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
|
|
7535
7593
|
return values2;
|
|
7536
7594
|
}, [user.id, notifications]);
|
|
7537
|
-
const [values, setValues] =
|
|
7538
|
-
const [notify, setNotify] =
|
|
7539
|
-
const [saving, setSaving] =
|
|
7540
|
-
const [saved, setSaved] =
|
|
7541
|
-
const [prevUserId, setPrevUserId] =
|
|
7595
|
+
const [values, setValues] = React48.useState(initialFieldValues);
|
|
7596
|
+
const [notify, setNotify] = React48.useState(initialNotify);
|
|
7597
|
+
const [saving, setSaving] = React48.useState(false);
|
|
7598
|
+
const [saved, setSaved] = React48.useState(false);
|
|
7599
|
+
const [prevUserId, setPrevUserId] = React48.useState(user.id);
|
|
7542
7600
|
if (user.id !== prevUserId) {
|
|
7543
7601
|
setPrevUserId(user.id);
|
|
7544
7602
|
setValues(initialFieldValues);
|
|
@@ -7726,11 +7784,11 @@ function ProfilePage({
|
|
|
7726
7784
|
}
|
|
7727
7785
|
|
|
7728
7786
|
// src/components/platform/SignInPage.tsx
|
|
7729
|
-
import * as
|
|
7787
|
+
import * as React49 from "react";
|
|
7730
7788
|
import { Fragment as Fragment18, jsx as jsx74, jsxs as jsxs68 } from "react/jsx-runtime";
|
|
7731
7789
|
function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
7732
|
-
const [signingIn, setSigningIn] =
|
|
7733
|
-
const [resuming, setResuming] =
|
|
7790
|
+
const [signingIn, setSigningIn] = React49.useState(false);
|
|
7791
|
+
const [resuming, setResuming] = React49.useState(false);
|
|
7734
7792
|
function handleSignIn() {
|
|
7735
7793
|
setSigningIn(true);
|
|
7736
7794
|
onSignIn();
|
|
@@ -7919,10 +7977,10 @@ function GoogleGlyph() {
|
|
|
7919
7977
|
}
|
|
7920
7978
|
|
|
7921
7979
|
// src/components/platform/RoadmapTimeline.tsx
|
|
7922
|
-
import * as
|
|
7980
|
+
import * as React52 from "react";
|
|
7923
7981
|
|
|
7924
7982
|
// src/kits/session.ts
|
|
7925
|
-
import * as
|
|
7983
|
+
import * as React50 from "react";
|
|
7926
7984
|
var PERMISSION_CATALOG = [
|
|
7927
7985
|
{ group: "Plans", items: [
|
|
7928
7986
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -9489,8 +9547,8 @@ function roadmap(overrides) {
|
|
|
9489
9547
|
};
|
|
9490
9548
|
}
|
|
9491
9549
|
function useSession() {
|
|
9492
|
-
const [s, setS] =
|
|
9493
|
-
|
|
9550
|
+
const [s, setS] = React50.useState(getSession);
|
|
9551
|
+
React50.useEffect(() => subscribe(setS), []);
|
|
9494
9552
|
return s;
|
|
9495
9553
|
}
|
|
9496
9554
|
var SessionKit = {
|
|
@@ -9523,7 +9581,7 @@ var SessionKit = {
|
|
|
9523
9581
|
};
|
|
9524
9582
|
function DemoSessionProvider({ children }) {
|
|
9525
9583
|
const session = useSession();
|
|
9526
|
-
const value =
|
|
9584
|
+
const value = React50.useMemo(
|
|
9527
9585
|
() => ({
|
|
9528
9586
|
user: session.user,
|
|
9529
9587
|
roles: session.roles,
|
|
@@ -9539,11 +9597,11 @@ function DemoSessionProvider({ children }) {
|
|
|
9539
9597
|
}),
|
|
9540
9598
|
[session]
|
|
9541
9599
|
);
|
|
9542
|
-
return
|
|
9600
|
+
return React50.createElement(SessionProvider, { value }, children);
|
|
9543
9601
|
}
|
|
9544
9602
|
|
|
9545
9603
|
// src/kits/runtime.ts
|
|
9546
|
-
import * as
|
|
9604
|
+
import * as React51 from "react";
|
|
9547
9605
|
var WIRED_ENDPOINTS = [
|
|
9548
9606
|
// Nothing yet. Every id below would come from a real service:
|
|
9549
9607
|
// "plan.get", "placements.list", …
|
|
@@ -9714,8 +9772,8 @@ var RuntimeKit = {
|
|
|
9714
9772
|
};
|
|
9715
9773
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
9716
9774
|
function useRuntimeMode() {
|
|
9717
|
-
const [m, setM] =
|
|
9718
|
-
|
|
9775
|
+
const [m, setM] = React51.useState(RuntimeKit.getMode());
|
|
9776
|
+
React51.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
9719
9777
|
return m;
|
|
9720
9778
|
}
|
|
9721
9779
|
function useFeatureStatus(key) {
|
|
@@ -9798,12 +9856,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
9798
9856
|
}
|
|
9799
9857
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
9800
9858
|
const session = SessionKit.useSession();
|
|
9801
|
-
const [project, setProject] =
|
|
9802
|
-
const [q, setQ] =
|
|
9803
|
-
const scrollRef =
|
|
9804
|
-
const nowRef =
|
|
9805
|
-
const rm =
|
|
9806
|
-
const byKey =
|
|
9859
|
+
const [project, setProject] = React52.useState("");
|
|
9860
|
+
const [q, setQ] = React52.useState("");
|
|
9861
|
+
const scrollRef = React52.useRef(null);
|
|
9862
|
+
const nowRef = React52.useRef(null);
|
|
9863
|
+
const rm = React52.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
9864
|
+
const byKey = React52.useMemo(() => {
|
|
9807
9865
|
const m = {};
|
|
9808
9866
|
rm.items.forEach((i) => {
|
|
9809
9867
|
m[i.key] = i;
|
|
@@ -9812,7 +9870,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
9812
9870
|
}, [rm]);
|
|
9813
9871
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
9814
9872
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
9815
|
-
|
|
9873
|
+
React52.useEffect(() => {
|
|
9816
9874
|
let raf1 = 0, raf2 = 0;
|
|
9817
9875
|
const place = () => {
|
|
9818
9876
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -9886,7 +9944,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
9886
9944
|
lastPhase = item.phase;
|
|
9887
9945
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
9888
9946
|
const isBoundary = n === firstPending;
|
|
9889
|
-
return /* @__PURE__ */ jsxs69(
|
|
9947
|
+
return /* @__PURE__ */ jsxs69(React52.Fragment, { children: [
|
|
9890
9948
|
showPhase ? /* @__PURE__ */ jsxs69("div", { className: "fd-rm-era", children: [
|
|
9891
9949
|
/* @__PURE__ */ jsxs69("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
9892
9950
|
/* @__PURE__ */ jsx75("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
@@ -9930,7 +9988,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
9930
9988
|
}
|
|
9931
9989
|
|
|
9932
9990
|
// src/components/platform/ComingSoon.tsx
|
|
9933
|
-
import * as
|
|
9991
|
+
import * as React53 from "react";
|
|
9934
9992
|
import { createPortal as createPortal5 } from "react-dom";
|
|
9935
9993
|
import { Fragment as Fragment20, jsx as jsx76, jsxs as jsxs70 } from "react/jsx-runtime";
|
|
9936
9994
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
@@ -9948,8 +10006,8 @@ function writeBypassed(list) {
|
|
|
9948
10006
|
}
|
|
9949
10007
|
}
|
|
9950
10008
|
function useBypass(key) {
|
|
9951
|
-
const [on, setOn] =
|
|
9952
|
-
|
|
10009
|
+
const [on, setOn] = React53.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
10010
|
+
React53.useEffect(() => {
|
|
9953
10011
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
9954
10012
|
}, [key]);
|
|
9955
10013
|
const set = (next) => {
|
|
@@ -9996,9 +10054,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
|
|
|
9996
10054
|
] });
|
|
9997
10055
|
}
|
|
9998
10056
|
function useHoverCard(open) {
|
|
9999
|
-
const anchor =
|
|
10000
|
-
const [pos, setPos] =
|
|
10001
|
-
|
|
10057
|
+
const anchor = React53.useRef(null);
|
|
10058
|
+
const [pos, setPos] = React53.useState(null);
|
|
10059
|
+
React53.useLayoutEffect(() => {
|
|
10002
10060
|
if (!open || !anchor.current) {
|
|
10003
10061
|
setPos(null);
|
|
10004
10062
|
return;
|
|
@@ -10125,10 +10183,10 @@ function ComingSoon({
|
|
|
10125
10183
|
] });
|
|
10126
10184
|
}
|
|
10127
10185
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
10128
|
-
const [open, setOpen] =
|
|
10186
|
+
const [open, setOpen] = React53.useState(false);
|
|
10129
10187
|
const [anchor, pos] = useHoverCard(open);
|
|
10130
10188
|
const zIndex = useOverlayLayer(open);
|
|
10131
|
-
const close =
|
|
10189
|
+
const close = React53.useRef(null);
|
|
10132
10190
|
const show = () => {
|
|
10133
10191
|
if (close.current) {
|
|
10134
10192
|
clearTimeout(close.current);
|
|
@@ -10144,7 +10202,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10144
10202
|
setOpen(false);
|
|
10145
10203
|
}, 140);
|
|
10146
10204
|
};
|
|
10147
|
-
|
|
10205
|
+
React53.useEffect(() => () => {
|
|
10148
10206
|
if (close.current) clearTimeout(close.current);
|
|
10149
10207
|
}, []);
|
|
10150
10208
|
return /* @__PURE__ */ jsxs70(
|
|
@@ -10315,14 +10373,14 @@ function PermissionHint({ perm, children }) {
|
|
|
10315
10373
|
}
|
|
10316
10374
|
|
|
10317
10375
|
// src/components/platform/ModeSwitch.tsx
|
|
10318
|
-
import * as
|
|
10376
|
+
import * as React54 from "react";
|
|
10319
10377
|
import { Fragment as Fragment21, jsx as jsx78, jsxs as jsxs72 } from "react/jsx-runtime";
|
|
10320
10378
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
10321
10379
|
const mode2 = useRuntimeMode();
|
|
10322
|
-
const [open, setOpen] =
|
|
10380
|
+
const [open, setOpen] = React54.useState(false);
|
|
10323
10381
|
const zIndex = useOverlayLayer(open);
|
|
10324
|
-
const ref =
|
|
10325
|
-
|
|
10382
|
+
const ref = React54.useRef(null);
|
|
10383
|
+
React54.useEffect(() => {
|
|
10326
10384
|
if (!open) return;
|
|
10327
10385
|
const away = (e) => {
|
|
10328
10386
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -10578,7 +10636,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
10578
10636
|
}
|
|
10579
10637
|
|
|
10580
10638
|
// src/components/planner/MixGap.tsx
|
|
10581
|
-
import * as
|
|
10639
|
+
import * as React55 from "react";
|
|
10582
10640
|
import { Fragment as Fragment22, jsx as jsx81, jsxs as jsxs75 } from "react/jsx-runtime";
|
|
10583
10641
|
var MIX_GAP_LAYOUT = {
|
|
10584
10642
|
trackHeight: 30,
|
|
@@ -10593,7 +10651,7 @@ function mixGapOffset(value, max) {
|
|
|
10593
10651
|
}
|
|
10594
10652
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
10595
10653
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
10596
|
-
const [hover, setHover] =
|
|
10654
|
+
const [hover, setHover] = React55.useState(null);
|
|
10597
10655
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
10598
10656
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
10599
10657
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
@@ -10736,7 +10794,7 @@ function ChannelContribution({
|
|
|
10736
10794
|
}
|
|
10737
10795
|
|
|
10738
10796
|
// src/components/planner/BudgetReallocator.tsx
|
|
10739
|
-
import * as
|
|
10797
|
+
import * as React56 from "react";
|
|
10740
10798
|
import { Fragment as Fragment23, jsx as jsx83, jsxs as jsxs77 } from "react/jsx-runtime";
|
|
10741
10799
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
10742
10800
|
function BudgetReallocator({
|
|
@@ -10752,8 +10810,8 @@ function BudgetReallocator({
|
|
|
10752
10810
|
onCancel,
|
|
10753
10811
|
className = ""
|
|
10754
10812
|
}) {
|
|
10755
|
-
const [draft, setDraft] =
|
|
10756
|
-
|
|
10813
|
+
const [draft, setDraft] = React56.useState(spend);
|
|
10814
|
+
React56.useEffect(() => setDraft(spend), [spend]);
|
|
10757
10815
|
const dirty = draft !== spend;
|
|
10758
10816
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
10759
10817
|
const nextBand = bandFor(nextCrp);
|
|
@@ -10768,10 +10826,10 @@ function BudgetReallocator({
|
|
|
10768
10826
|
setDraft(spend);
|
|
10769
10827
|
if (onCancel) onCancel();
|
|
10770
10828
|
};
|
|
10771
|
-
const trackRef =
|
|
10772
|
-
const chipRef =
|
|
10773
|
-
const [chipLeft, setChipLeft] =
|
|
10774
|
-
|
|
10829
|
+
const trackRef = React56.useRef(null);
|
|
10830
|
+
const chipRef = React56.useRef(null);
|
|
10831
|
+
const [chipLeft, setChipLeft] = React56.useState(null);
|
|
10832
|
+
React56.useLayoutEffect(() => {
|
|
10775
10833
|
const track = trackRef.current;
|
|
10776
10834
|
if (!dirty || !track) {
|
|
10777
10835
|
setChipLeft(null);
|
|
@@ -10958,7 +11016,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "" })
|
|
|
10958
11016
|
}
|
|
10959
11017
|
|
|
10960
11018
|
// src/components/planner/PreferenceMeter.tsx
|
|
10961
|
-
import * as
|
|
11019
|
+
import * as React57 from "react";
|
|
10962
11020
|
import { jsx as jsx86, jsxs as jsxs80 } from "react/jsx-runtime";
|
|
10963
11021
|
function preferenceScore(criteria) {
|
|
10964
11022
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
@@ -10988,7 +11046,7 @@ function PreferenceMeter({
|
|
|
10988
11046
|
className = ""
|
|
10989
11047
|
}) {
|
|
10990
11048
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
10991
|
-
const segments =
|
|
11049
|
+
const segments = React57.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
10992
11050
|
return /* @__PURE__ */ jsx86(
|
|
10993
11051
|
ScoreMeter,
|
|
10994
11052
|
{
|
|
@@ -11027,10 +11085,10 @@ function PreferenceMeter({
|
|
|
11027
11085
|
}
|
|
11028
11086
|
|
|
11029
11087
|
// src/components/chat/AgentChatPanel.tsx
|
|
11030
|
-
import * as
|
|
11088
|
+
import * as React63 from "react";
|
|
11031
11089
|
|
|
11032
11090
|
// src/components/chat/chatEngine.ts
|
|
11033
|
-
import * as
|
|
11091
|
+
import * as React58 from "react";
|
|
11034
11092
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
11035
11093
|
var JOB_PENDING = ["queued", "running"];
|
|
11036
11094
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -11084,22 +11142,22 @@ function useChatEngine(opts) {
|
|
|
11084
11142
|
onClear,
|
|
11085
11143
|
onFeedback
|
|
11086
11144
|
} = 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
|
-
|
|
11145
|
+
const [status, setStatus] = React58.useState("idle");
|
|
11146
|
+
const [threadId, setThreadId] = React58.useState(null);
|
|
11147
|
+
const [messages, setMessages] = React58.useState([]);
|
|
11148
|
+
const [queue, setQueue] = React58.useState([]);
|
|
11149
|
+
const [fatal, setFatal] = React58.useState(null);
|
|
11150
|
+
const [busy, setBusy] = React58.useState(false);
|
|
11151
|
+
const [turnStartedAt, setTurnStartedAt] = React58.useState(null);
|
|
11152
|
+
const listRef = React58.useRef([]);
|
|
11153
|
+
const queueRef = React58.useRef([]);
|
|
11154
|
+
const busyRef = React58.useRef(false);
|
|
11155
|
+
const stoppedRef = React58.useRef(false);
|
|
11156
|
+
const abortRef = React58.useRef(null);
|
|
11157
|
+
const serverCount = React58.useRef(0);
|
|
11158
|
+
const threadRef = React58.useRef(null);
|
|
11159
|
+
const mounted = React58.useRef(true);
|
|
11160
|
+
React58.useEffect(() => {
|
|
11103
11161
|
mounted.current = true;
|
|
11104
11162
|
return () => {
|
|
11105
11163
|
mounted.current = false;
|
|
@@ -11121,14 +11179,14 @@ function useChatEngine(opts) {
|
|
|
11121
11179
|
}
|
|
11122
11180
|
return false;
|
|
11123
11181
|
};
|
|
11124
|
-
const loadThread =
|
|
11182
|
+
const loadThread = React58.useCallback(async (id) => {
|
|
11125
11183
|
const data = await apiAdapter.getThread(id);
|
|
11126
11184
|
const list = [...data && data.messages || []];
|
|
11127
11185
|
serverCount.current = list.length;
|
|
11128
11186
|
commit(list);
|
|
11129
11187
|
return list;
|
|
11130
11188
|
}, [apiAdapter]);
|
|
11131
|
-
|
|
11189
|
+
React58.useEffect(() => {
|
|
11132
11190
|
if (!apiAdapter) {
|
|
11133
11191
|
setStatus("idle");
|
|
11134
11192
|
setFatal(null);
|
|
@@ -11341,7 +11399,7 @@ function useChatEngine(opts) {
|
|
|
11341
11399
|
await dispatchTurn(turn);
|
|
11342
11400
|
}
|
|
11343
11401
|
}
|
|
11344
|
-
const send =
|
|
11402
|
+
const send = React58.useCallback((text, attachments) => {
|
|
11345
11403
|
const body = (text || "").trim();
|
|
11346
11404
|
if (!body && !(attachments && attachments.length)) return;
|
|
11347
11405
|
if (status === "disconnected") return;
|
|
@@ -11351,7 +11409,7 @@ function useChatEngine(opts) {
|
|
|
11351
11409
|
stoppedRef.current = false;
|
|
11352
11410
|
drain();
|
|
11353
11411
|
}, [status]);
|
|
11354
|
-
const stop =
|
|
11412
|
+
const stop = React58.useCallback(() => {
|
|
11355
11413
|
stoppedRef.current = true;
|
|
11356
11414
|
const ac = abortRef.current;
|
|
11357
11415
|
if (ac) {
|
|
@@ -11370,11 +11428,11 @@ function useChatEngine(opts) {
|
|
|
11370
11428
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
11371
11429
|
}
|
|
11372
11430
|
}, [apiAdapter]);
|
|
11373
|
-
const removeQueued =
|
|
11431
|
+
const removeQueued = React58.useCallback((id) => {
|
|
11374
11432
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
11375
11433
|
setQueue(queueRef.current.slice());
|
|
11376
11434
|
}, []);
|
|
11377
|
-
const retry =
|
|
11435
|
+
const retry = React58.useCallback(() => {
|
|
11378
11436
|
const list = listRef.current;
|
|
11379
11437
|
let at = -1;
|
|
11380
11438
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -11390,19 +11448,19 @@ function useChatEngine(opts) {
|
|
|
11390
11448
|
setQueue(queueRef.current.slice());
|
|
11391
11449
|
drain();
|
|
11392
11450
|
}, []);
|
|
11393
|
-
const clear =
|
|
11451
|
+
const clear = React58.useCallback(() => {
|
|
11394
11452
|
commit([]);
|
|
11395
11453
|
serverCount.current = 0;
|
|
11396
11454
|
queueRef.current = [];
|
|
11397
11455
|
setQueue([]);
|
|
11398
11456
|
onClear && onClear();
|
|
11399
11457
|
}, [onClear]);
|
|
11400
|
-
const setFeedback =
|
|
11458
|
+
const setFeedback = React58.useCallback((id, value) => {
|
|
11401
11459
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
11402
11460
|
const msg = listRef.current.find((m) => m.id === id);
|
|
11403
11461
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
11404
11462
|
}, [onFeedback]);
|
|
11405
|
-
const reload =
|
|
11463
|
+
const reload = React58.useCallback(async () => {
|
|
11406
11464
|
if (!threadRef.current) return;
|
|
11407
11465
|
setStatus("loading");
|
|
11408
11466
|
try {
|
|
@@ -11440,10 +11498,10 @@ var ChatKit = {
|
|
|
11440
11498
|
};
|
|
11441
11499
|
|
|
11442
11500
|
// src/components/chat/ChatTranscript.tsx
|
|
11443
|
-
import * as
|
|
11501
|
+
import * as React60 from "react";
|
|
11444
11502
|
|
|
11445
11503
|
// src/components/chat/ChatTurn.tsx
|
|
11446
|
-
import * as
|
|
11504
|
+
import * as React59 from "react";
|
|
11447
11505
|
import { jsx as jsx87, jsxs as jsxs81 } from "react/jsx-runtime";
|
|
11448
11506
|
function JsonView({ value }) {
|
|
11449
11507
|
let text;
|
|
@@ -11480,7 +11538,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
|
11480
11538
|
] });
|
|
11481
11539
|
}
|
|
11482
11540
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
11483
|
-
const [open, setOpen] =
|
|
11541
|
+
const [open, setOpen] = React59.useState(defaultOpen);
|
|
11484
11542
|
if (!text) return null;
|
|
11485
11543
|
return /* @__PURE__ */ jsxs81("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
|
|
11486
11544
|
/* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -11497,7 +11555,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
|
11497
11555
|
] });
|
|
11498
11556
|
}
|
|
11499
11557
|
function Citations({ items = [], onOpen }) {
|
|
11500
|
-
const [open, setOpen] =
|
|
11558
|
+
const [open, setOpen] = React59.useState(false);
|
|
11501
11559
|
if (!items.length) return null;
|
|
11502
11560
|
return /* @__PURE__ */ jsxs81("div", { className: "fdc-cites", children: [
|
|
11503
11561
|
/* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -11523,7 +11581,7 @@ function clampText(text, max) {
|
|
|
11523
11581
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
11524
11582
|
}
|
|
11525
11583
|
function MessageBody({ message: m, ctx }) {
|
|
11526
|
-
const [expanded, setExpanded] =
|
|
11584
|
+
const [expanded, setExpanded] = React59.useState(false);
|
|
11527
11585
|
const isUser = m.role === "user";
|
|
11528
11586
|
const raw = m.text || "";
|
|
11529
11587
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
@@ -11590,9 +11648,9 @@ function MessageBody({ message: m, ctx }) {
|
|
|
11590
11648
|
] });
|
|
11591
11649
|
}
|
|
11592
11650
|
function useCopyRun() {
|
|
11593
|
-
const [done, setDone] =
|
|
11594
|
-
const t =
|
|
11595
|
-
|
|
11651
|
+
const [done, setDone] = React59.useState(false);
|
|
11652
|
+
const t = React59.useRef(null);
|
|
11653
|
+
React59.useEffect(() => () => {
|
|
11596
11654
|
if (t.current) clearTimeout(t.current);
|
|
11597
11655
|
}, []);
|
|
11598
11656
|
return [done, (text) => {
|
|
@@ -11619,7 +11677,7 @@ function RunActions({ group, ctx }) {
|
|
|
11619
11677
|
] }),
|
|
11620
11678
|
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
11679
|
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(
|
|
11680
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs81(React59.Fragment, { children: [
|
|
11623
11681
|
/* @__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
11682
|
/* @__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
11683
|
] }) : null,
|
|
@@ -11714,10 +11772,10 @@ function ChatTranscript({
|
|
|
11714
11772
|
renderEmpty,
|
|
11715
11773
|
className = ""
|
|
11716
11774
|
}) {
|
|
11717
|
-
const scroller =
|
|
11718
|
-
const stick =
|
|
11719
|
-
const [pill, setPill] =
|
|
11720
|
-
const seen =
|
|
11775
|
+
const scroller = React60.useRef(null);
|
|
11776
|
+
const stick = React60.useRef(true);
|
|
11777
|
+
const [pill, setPill] = React60.useState(0);
|
|
11778
|
+
const seen = React60.useRef(0);
|
|
11721
11779
|
const toBottom = (smooth) => {
|
|
11722
11780
|
const el = scroller.current;
|
|
11723
11781
|
if (!el) return;
|
|
@@ -11736,7 +11794,7 @@ function ChatTranscript({
|
|
|
11736
11794
|
seen.current = messages.length;
|
|
11737
11795
|
}
|
|
11738
11796
|
};
|
|
11739
|
-
|
|
11797
|
+
React60.useLayoutEffect(() => {
|
|
11740
11798
|
const el = scroller.current;
|
|
11741
11799
|
if (!el) return;
|
|
11742
11800
|
if (stick.current) {
|
|
@@ -11744,7 +11802,7 @@ function ChatTranscript({
|
|
|
11744
11802
|
seen.current = messages.length;
|
|
11745
11803
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
11746
11804
|
}, [messages]);
|
|
11747
|
-
|
|
11805
|
+
React60.useEffect(() => {
|
|
11748
11806
|
const el = scroller.current;
|
|
11749
11807
|
const inner = el && el.firstChild;
|
|
11750
11808
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -11754,7 +11812,7 @@ function ChatTranscript({
|
|
|
11754
11812
|
ro.observe(inner);
|
|
11755
11813
|
return () => ro.disconnect();
|
|
11756
11814
|
}, []);
|
|
11757
|
-
const groups =
|
|
11815
|
+
const groups = React60.useMemo(() => groupMessages(messages), [messages]);
|
|
11758
11816
|
const empty = !messages.length && status === "ready";
|
|
11759
11817
|
return /* @__PURE__ */ jsxs82("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
11760
11818
|
/* @__PURE__ */ jsxs82("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
@@ -11778,7 +11836,7 @@ function ChatTranscript({
|
|
|
11778
11836
|
const prev = groups[i - 1];
|
|
11779
11837
|
const k = dayKey(g.messages[0].timestamp);
|
|
11780
11838
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
11781
|
-
return /* @__PURE__ */ jsxs82(
|
|
11839
|
+
return /* @__PURE__ */ jsxs82(React60.Fragment, { children: [
|
|
11782
11840
|
showDay ? /* @__PURE__ */ jsx88("div", { className: "fdc-day", children: /* @__PURE__ */ jsx88("span", { children: dayLabel(k) }) }) : null,
|
|
11783
11841
|
/* @__PURE__ */ jsx88(ChatTurn, { group: g, ctx })
|
|
11784
11842
|
] }, g.key || i);
|
|
@@ -11795,7 +11853,7 @@ function ChatTranscript({
|
|
|
11795
11853
|
var TranscriptKit = { groupMessages };
|
|
11796
11854
|
|
|
11797
11855
|
// src/components/chat/ChatComposer.tsx
|
|
11798
|
-
import * as
|
|
11856
|
+
import * as React61 from "react";
|
|
11799
11857
|
import { jsx as jsx89, jsxs as jsxs83 } from "react/jsx-runtime";
|
|
11800
11858
|
function ChatComposer({
|
|
11801
11859
|
onSubmit,
|
|
@@ -11823,17 +11881,17 @@ function ChatComposer({
|
|
|
11823
11881
|
onReject,
|
|
11824
11882
|
onOpenAttachment
|
|
11825
11883
|
}) {
|
|
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 =
|
|
11884
|
+
const [text, setText] = React61.useState(draft || "");
|
|
11885
|
+
const [trigger, setTrigger] = React61.useState(null);
|
|
11886
|
+
const [mentionItems, setMentionItems] = React61.useState([]);
|
|
11887
|
+
const [listening, setListening] = React61.useState(false);
|
|
11888
|
+
const [notice, setNotice] = React61.useState(null);
|
|
11889
|
+
const editor = React61.useRef(null);
|
|
11890
|
+
const wrap = React61.useRef(null);
|
|
11891
|
+
const stopVoice = React61.useRef(null);
|
|
11834
11892
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
11835
11893
|
} });
|
|
11836
|
-
|
|
11894
|
+
React61.useEffect(() => {
|
|
11837
11895
|
if (draft != null && draft !== text) setText(draft);
|
|
11838
11896
|
}, [draft]);
|
|
11839
11897
|
const change = (v) => {
|
|
@@ -11869,7 +11927,7 @@ function ChatComposer({
|
|
|
11869
11927
|
e.preventDefault();
|
|
11870
11928
|
staged.add(found.files);
|
|
11871
11929
|
};
|
|
11872
|
-
|
|
11930
|
+
React61.useEffect(() => {
|
|
11873
11931
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
11874
11932
|
setMentionItems([]);
|
|
11875
11933
|
return;
|
|
@@ -11887,7 +11945,7 @@ function ChatComposer({
|
|
|
11887
11945
|
const q = (trigger.query || "").toLowerCase();
|
|
11888
11946
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
11889
11947
|
}, [trigger, mentionSources]);
|
|
11890
|
-
const slashItems =
|
|
11948
|
+
const slashItems = React61.useMemo(() => {
|
|
11891
11949
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
11892
11950
|
const q = (trigger.query || "").toLowerCase();
|
|
11893
11951
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -12061,12 +12119,12 @@ function ChatComposer({
|
|
|
12061
12119
|
}
|
|
12062
12120
|
|
|
12063
12121
|
// src/components/chat/ChatSessionBar.tsx
|
|
12064
|
-
import * as
|
|
12122
|
+
import * as React62 from "react";
|
|
12065
12123
|
import { jsx as jsx90, jsxs as jsxs84 } from "react/jsx-runtime";
|
|
12066
12124
|
var compact2 = meterFormats.compact;
|
|
12067
12125
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
12068
|
-
const [open, setOpen] =
|
|
12069
|
-
const anchor =
|
|
12126
|
+
const [open, setOpen] = React62.useState(false);
|
|
12127
|
+
const anchor = React62.useRef(null);
|
|
12070
12128
|
const stats = sessionStats || null;
|
|
12071
12129
|
const cu = contextUsage || null;
|
|
12072
12130
|
const limits = usageLimits || null;
|
|
@@ -12081,7 +12139,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12081
12139
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
12082
12140
|
if (cu) bits.push(pct + "% context");
|
|
12083
12141
|
const expandable = !!(cu || limits);
|
|
12084
|
-
return /* @__PURE__ */ jsxs84(
|
|
12142
|
+
return /* @__PURE__ */ jsxs84(React62.Fragment, { children: [
|
|
12085
12143
|
/* @__PURE__ */ jsxs84("div", { className: "fdc-bar", children: [
|
|
12086
12144
|
/* @__PURE__ */ jsxs84(
|
|
12087
12145
|
"button",
|
|
@@ -12222,7 +12280,7 @@ function ModelControls({
|
|
|
12222
12280
|
] })
|
|
12223
12281
|
});
|
|
12224
12282
|
}
|
|
12225
|
-
return /* @__PURE__ */ jsxs84(
|
|
12283
|
+
return /* @__PURE__ */ jsxs84(React62.Fragment, { children: [
|
|
12226
12284
|
/* @__PURE__ */ jsx90(
|
|
12227
12285
|
MenuButton,
|
|
12228
12286
|
{
|
|
@@ -12339,11 +12397,11 @@ function AgentChatPanel({
|
|
|
12339
12397
|
onFeedback,
|
|
12340
12398
|
onEditMessage
|
|
12341
12399
|
}) {
|
|
12342
|
-
const [panelWidth, setPanelWidth] =
|
|
12343
|
-
const [applied, setApplied] =
|
|
12344
|
-
const [draft, setDraft] =
|
|
12345
|
-
const dragging =
|
|
12346
|
-
|
|
12400
|
+
const [panelWidth, setPanelWidth] = React63.useState(width);
|
|
12401
|
+
const [applied, setApplied] = React63.useState({});
|
|
12402
|
+
const [draft, setDraft] = React63.useState("");
|
|
12403
|
+
const dragging = React63.useRef(null);
|
|
12404
|
+
React63.useEffect(() => setPanelWidth(width), [width]);
|
|
12347
12405
|
const engine = useChatEngine({
|
|
12348
12406
|
contextType,
|
|
12349
12407
|
contextId,
|
|
@@ -12547,7 +12605,7 @@ function AgentChatPanel({
|
|
|
12547
12605
|
}
|
|
12548
12606
|
|
|
12549
12607
|
// src/components/files/FileViewer.tsx
|
|
12550
|
-
import * as
|
|
12608
|
+
import * as React64 from "react";
|
|
12551
12609
|
import { jsx as jsx92, jsxs as jsxs86 } from "react/jsx-runtime";
|
|
12552
12610
|
function previewKindOf(file) {
|
|
12553
12611
|
const mime = (file.mime || "").toLowerCase();
|
|
@@ -12604,13 +12662,13 @@ function parseDelimited(text, delimiter) {
|
|
|
12604
12662
|
return rows;
|
|
12605
12663
|
}
|
|
12606
12664
|
function usePreview(file, kind, resolveUrl) {
|
|
12607
|
-
const [state, setState] =
|
|
12608
|
-
const [attempt, setAttempt] =
|
|
12609
|
-
const resolveRef =
|
|
12610
|
-
|
|
12665
|
+
const [state, setState] = React64.useState({ status: "loading" });
|
|
12666
|
+
const [attempt, setAttempt] = React64.useState(0);
|
|
12667
|
+
const resolveRef = React64.useRef(resolveUrl);
|
|
12668
|
+
React64.useEffect(() => {
|
|
12611
12669
|
resolveRef.current = resolveUrl;
|
|
12612
12670
|
}, [resolveUrl]);
|
|
12613
|
-
|
|
12671
|
+
React64.useEffect(() => {
|
|
12614
12672
|
if (kind === "none") {
|
|
12615
12673
|
setState({ status: "ready" });
|
|
12616
12674
|
return;
|
|
@@ -12640,7 +12698,7 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
12640
12698
|
if (ac) ac.abort();
|
|
12641
12699
|
};
|
|
12642
12700
|
}, [file.id, kind, attempt]);
|
|
12643
|
-
return { ...state, retry:
|
|
12701
|
+
return { ...state, retry: React64.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
12644
12702
|
}
|
|
12645
12703
|
function PreviewBody({ file, kind, state }) {
|
|
12646
12704
|
if (kind === "image") return /* @__PURE__ */ jsx92("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
@@ -12685,13 +12743,13 @@ function PreviewBody({ file, kind, state }) {
|
|
|
12685
12743
|
] });
|
|
12686
12744
|
}
|
|
12687
12745
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
12688
|
-
const kind =
|
|
12746
|
+
const kind = React64.useMemo(() => previewKindOf(file), [file]);
|
|
12689
12747
|
const preview = usePreview(file, kind, resolveUrl);
|
|
12690
|
-
const [tab, setTab] =
|
|
12691
|
-
const [downloading, setDownloading] =
|
|
12692
|
-
const [downloadError, setDownloadError] =
|
|
12748
|
+
const [tab, setTab] = React64.useState("preview");
|
|
12749
|
+
const [downloading, setDownloading] = React64.useState(false);
|
|
12750
|
+
const [downloadError, setDownloadError] = React64.useState(null);
|
|
12693
12751
|
const hasSide = sidePanel != null;
|
|
12694
|
-
|
|
12752
|
+
React64.useEffect(() => {
|
|
12695
12753
|
setTab("preview");
|
|
12696
12754
|
}, [file.id]);
|
|
12697
12755
|
const download = () => {
|
|
@@ -12758,7 +12816,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
12758
12816
|
}
|
|
12759
12817
|
|
|
12760
12818
|
// src/components/files/FileBrowser.tsx
|
|
12761
|
-
import * as
|
|
12819
|
+
import * as React65 from "react";
|
|
12762
12820
|
import { Fragment as Fragment27, jsx as jsx93, jsxs as jsxs87 } from "react/jsx-runtime";
|
|
12763
12821
|
function childrenOf(folders, parentId) {
|
|
12764
12822
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -12829,10 +12887,10 @@ function FolderPickerMenu({
|
|
|
12829
12887
|
destinations,
|
|
12830
12888
|
onPick
|
|
12831
12889
|
}) {
|
|
12832
|
-
const [open, setOpen] =
|
|
12890
|
+
const [open, setOpen] = React65.useState(false);
|
|
12833
12891
|
const zIndex = useOverlayLayer(open);
|
|
12834
|
-
const ref =
|
|
12835
|
-
|
|
12892
|
+
const ref = React65.useRef(null);
|
|
12893
|
+
React65.useEffect(() => {
|
|
12836
12894
|
if (!open) return;
|
|
12837
12895
|
const away = (e) => {
|
|
12838
12896
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -12884,8 +12942,8 @@ function FolderPickerMenu({
|
|
|
12884
12942
|
] });
|
|
12885
12943
|
}
|
|
12886
12944
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
12887
|
-
const [over, setOver] =
|
|
12888
|
-
const dragCounter =
|
|
12945
|
+
const [over, setOver] = React65.useState(false);
|
|
12946
|
+
const dragCounter = React65.useRef(0);
|
|
12889
12947
|
const dropHandlers = isDropTarget ? {
|
|
12890
12948
|
onDragEnter: (e) => {
|
|
12891
12949
|
if (!hasInternalPayload(e)) return;
|
|
@@ -12933,8 +12991,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
12933
12991
|
}
|
|
12934
12992
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
12935
12993
|
const kids = childrenOf(folders, folder.id);
|
|
12936
|
-
const [expanded, setExpanded] =
|
|
12937
|
-
|
|
12994
|
+
const [expanded, setExpanded] = React65.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
12995
|
+
React65.useEffect(() => {
|
|
12938
12996
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
12939
12997
|
}, [currentFolderId, folder.id, folders]);
|
|
12940
12998
|
const isCurrent = folder.id === currentFolderId;
|
|
@@ -13000,15 +13058,15 @@ function FileBrowser({
|
|
|
13000
13058
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
13001
13059
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
13002
13060
|
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 =
|
|
13061
|
+
const [createOpen, setCreateOpen] = React65.useState(false);
|
|
13062
|
+
const [createName, setCreateName] = React65.useState("");
|
|
13063
|
+
const [renameTarget, setRenameTarget] = React65.useState(null);
|
|
13064
|
+
const [renameValue, setRenameValue] = React65.useState("");
|
|
13065
|
+
const [deleteTarget, setDeleteTarget] = React65.useState(null);
|
|
13066
|
+
const uploadInputRef = React65.useRef(null);
|
|
13067
|
+
const crumbFolders = React65.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
13068
|
+
const subfolders = React65.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
13069
|
+
const currentFiles = React65.useMemo(
|
|
13012
13070
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
13013
13071
|
[files, currentFolderId]
|
|
13014
13072
|
);
|
|
@@ -13240,8 +13298,8 @@ function BreadcrumbCrumb({
|
|
|
13240
13298
|
isDropTarget,
|
|
13241
13299
|
onDropPayload
|
|
13242
13300
|
}) {
|
|
13243
|
-
const [over, setOver] =
|
|
13244
|
-
const dragCounter =
|
|
13301
|
+
const [over, setOver] = React65.useState(false);
|
|
13302
|
+
const dragCounter = React65.useRef(0);
|
|
13245
13303
|
const dropHandlers = isDropTarget ? {
|
|
13246
13304
|
onDragEnter: (e) => {
|
|
13247
13305
|
if (!hasInternalPayload(e)) return;
|
|
@@ -13270,7 +13328,7 @@ function BreadcrumbCrumb({
|
|
|
13270
13328
|
}
|
|
13271
13329
|
|
|
13272
13330
|
// src/kits/query.ts
|
|
13273
|
-
import * as
|
|
13331
|
+
import * as React66 from "react";
|
|
13274
13332
|
var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
|
|
13275
13333
|
var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
|
|
13276
13334
|
var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
|
|
@@ -13325,22 +13383,22 @@ function compare(a, b, dir) {
|
|
|
13325
13383
|
var API = null;
|
|
13326
13384
|
var PREFS = null;
|
|
13327
13385
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
13328
|
-
const [query, setQuery] =
|
|
13386
|
+
const [query, setQuery] = React66.useState(() => {
|
|
13329
13387
|
const store = PREFS || window.PlannerPrefs;
|
|
13330
13388
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
13331
13389
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
13332
13390
|
});
|
|
13333
|
-
const savePref =
|
|
13391
|
+
const savePref = React66.useCallback((patch2) => {
|
|
13334
13392
|
const store = PREFS || window.PlannerPrefs;
|
|
13335
13393
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
13336
13394
|
}, [prefsKey]);
|
|
13337
|
-
const [res, setRes] =
|
|
13338
|
-
const [loading, setLoading] =
|
|
13339
|
-
const seq2 =
|
|
13395
|
+
const [res, setRes] = React66.useState(null);
|
|
13396
|
+
const [loading, setLoading] = React66.useState(true);
|
|
13397
|
+
const seq2 = React66.useRef(0);
|
|
13340
13398
|
const depKey = (deps || []).join("|");
|
|
13341
13399
|
const paramKey = JSON.stringify(params || {});
|
|
13342
13400
|
const queryKey = JSON.stringify(query);
|
|
13343
|
-
|
|
13401
|
+
React66.useEffect(() => {
|
|
13344
13402
|
const id = ++seq2.current;
|
|
13345
13403
|
setLoading(true);
|
|
13346
13404
|
const t = setTimeout(() => {
|
|
@@ -13659,12 +13717,12 @@ function createVersionStore(initialState, options) {
|
|
|
13659
13717
|
}
|
|
13660
13718
|
|
|
13661
13719
|
// src/kits/documentTitle.ts
|
|
13662
|
-
import * as
|
|
13720
|
+
import * as React67 from "react";
|
|
13663
13721
|
function formatDocumentTitle(routeTitle, appName) {
|
|
13664
13722
|
return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
|
|
13665
13723
|
}
|
|
13666
13724
|
function useDocumentTitle(routeTitle, appName) {
|
|
13667
|
-
|
|
13725
|
+
React67.useEffect(() => {
|
|
13668
13726
|
if (typeof document === "undefined") return;
|
|
13669
13727
|
document.title = formatDocumentTitle(routeTitle, appName);
|
|
13670
13728
|
}, [routeTitle, appName]);
|