@flytedan/flytebot-design-system 0.33.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -2
- package/dist/index.cjs +478 -390
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -8
- package/dist/index.d.ts +21 -8
- package/dist/index.js +478 -390
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2971,10 +2971,10 @@ function DataTable({
|
|
|
2971
2971
|
}
|
|
2972
2972
|
|
|
2973
2973
|
// src/components/data/FilterBar.tsx
|
|
2974
|
-
var
|
|
2974
|
+
var React25 = __toESM(require("react"), 1);
|
|
2975
2975
|
|
|
2976
2976
|
// src/components/forms/NumberInput.tsx
|
|
2977
|
-
var
|
|
2977
|
+
var React22 = __toESM(require("react"), 1);
|
|
2978
2978
|
|
|
2979
2979
|
// src/components/forms/field.tsx
|
|
2980
2980
|
var React20 = __toESM(require("react"), 1);
|
|
@@ -2995,6 +2995,16 @@ function useTriggerLabelling(label, id) {
|
|
|
2995
2995
|
return { fieldId, labelId, ariaLabelledBy: label ? labelId + " " + fieldId : void 0 };
|
|
2996
2996
|
}
|
|
2997
2997
|
|
|
2998
|
+
// src/components/useLatest.ts
|
|
2999
|
+
var React21 = __toESM(require("react"), 1);
|
|
3000
|
+
function useLatest(value) {
|
|
3001
|
+
const ref = React21.useRef(value);
|
|
3002
|
+
React21.useInsertionEffect(() => {
|
|
3003
|
+
ref.current = value;
|
|
3004
|
+
});
|
|
3005
|
+
return ref;
|
|
3006
|
+
}
|
|
3007
|
+
|
|
2998
3008
|
// src/components/forms/NumberInput.tsx
|
|
2999
3009
|
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
3000
3010
|
var HOLD_DELAY_MS = 400;
|
|
@@ -3072,24 +3082,22 @@ function NumberInput({
|
|
|
3072
3082
|
const n = typeof v === "number" ? v : parseNumberText(v);
|
|
3073
3083
|
return n == null || Number.isNaN(n) ? null : n;
|
|
3074
3084
|
};
|
|
3075
|
-
const [text, setText] =
|
|
3076
|
-
const [editing, setEditing] =
|
|
3085
|
+
const [text, setText] = React22.useState(() => toText(value));
|
|
3086
|
+
const [editing, setEditing] = React22.useState(false);
|
|
3077
3087
|
const parsed = parseNumberText(text);
|
|
3078
3088
|
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;
|
|
3079
3089
|
const valid = invalidMessage == null;
|
|
3080
|
-
const committedRef =
|
|
3081
|
-
const onChangeRef =
|
|
3082
|
-
|
|
3083
|
-
const
|
|
3084
|
-
|
|
3085
|
-
const focusedRef = React21.useRef(false);
|
|
3086
|
-
React21.useEffect(() => {
|
|
3090
|
+
const committedRef = React22.useRef(toNumber(value));
|
|
3091
|
+
const onChangeRef = useLatest(onChange);
|
|
3092
|
+
const onValidityChangeRef = useLatest(onValidityChange);
|
|
3093
|
+
const focusedRef = React22.useRef(false);
|
|
3094
|
+
React22.useEffect(() => {
|
|
3087
3095
|
committedRef.current = toNumber(value);
|
|
3088
3096
|
if (!focusedRef.current) setText(toText(value));
|
|
3089
3097
|
}, [value]);
|
|
3090
|
-
|
|
3098
|
+
React22.useLayoutEffect(() => {
|
|
3091
3099
|
onValidityChangeRef.current?.(valid);
|
|
3092
|
-
}, [valid]);
|
|
3100
|
+
}, [valid, onValidityChangeRef]);
|
|
3093
3101
|
const fire = (n) => {
|
|
3094
3102
|
committedRef.current = n ?? null;
|
|
3095
3103
|
onChangeRef.current?.({ target: { value: n } });
|
|
@@ -3102,9 +3110,8 @@ function NumberInput({
|
|
|
3102
3110
|
fire(next);
|
|
3103
3111
|
return true;
|
|
3104
3112
|
};
|
|
3105
|
-
const bumpRef =
|
|
3106
|
-
|
|
3107
|
-
const holdTimer = React21.useRef(null);
|
|
3113
|
+
const bumpRef = useLatest(bump);
|
|
3114
|
+
const holdTimer = React22.useRef(null);
|
|
3108
3115
|
const release = () => {
|
|
3109
3116
|
if (holdTimer.current) clearTimeout(holdTimer.current);
|
|
3110
3117
|
holdTimer.current = null;
|
|
@@ -3123,7 +3130,7 @@ function NumberInput({
|
|
|
3123
3130
|
};
|
|
3124
3131
|
holdTimer.current = setTimeout(tick, HOLD_DELAY_MS);
|
|
3125
3132
|
};
|
|
3126
|
-
|
|
3133
|
+
React22.useEffect(() => () => {
|
|
3127
3134
|
if (holdTimer.current) clearTimeout(holdTimer.current);
|
|
3128
3135
|
}, []);
|
|
3129
3136
|
const current2 = committedRef.current;
|
|
@@ -3226,7 +3233,7 @@ function NumberInput({
|
|
|
3226
3233
|
}
|
|
3227
3234
|
|
|
3228
3235
|
// src/components/forms/DatePicker.tsx
|
|
3229
|
-
var
|
|
3236
|
+
var React23 = __toESM(require("react"), 1);
|
|
3230
3237
|
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
3231
3238
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
3232
3239
|
var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
@@ -3244,10 +3251,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3244
3251
|
const today = /* @__PURE__ */ new Date();
|
|
3245
3252
|
const sel = range ? value || {} : { start: value, end: value };
|
|
3246
3253
|
const anchor = parse(sel.start) || parse(initialMonth) || today;
|
|
3247
|
-
const [vy, setVy] =
|
|
3248
|
-
const [vm, setVm] =
|
|
3249
|
-
const [mode2, setMode] =
|
|
3250
|
-
const [hover, setHover] =
|
|
3254
|
+
const [vy, setVy] = React23.useState(anchor.getFullYear());
|
|
3255
|
+
const [vm, setVm] = React23.useState(anchor.getMonth());
|
|
3256
|
+
const [mode2, setMode] = React23.useState("days");
|
|
3257
|
+
const [hover, setHover] = React23.useState(null);
|
|
3251
3258
|
const s = parse(sel.start), e = parse(sel.end);
|
|
3252
3259
|
const hoverEnd = range && s && !e && hover ? parse(hover) : null;
|
|
3253
3260
|
const inRange = (d) => {
|
|
@@ -3363,9 +3370,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3363
3370
|
}
|
|
3364
3371
|
function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, ...rest }) {
|
|
3365
3372
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
3366
|
-
const [open, setOpen] =
|
|
3367
|
-
const rootRef =
|
|
3368
|
-
const boxRef =
|
|
3373
|
+
const [open, setOpen] = React23.useState(false);
|
|
3374
|
+
const rootRef = React23.useRef(null);
|
|
3375
|
+
const boxRef = React23.useRef(null);
|
|
3369
3376
|
const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
|
|
3370
3377
|
const toggle = () => {
|
|
3371
3378
|
if (!disabled) setOpen(!open);
|
|
@@ -3443,9 +3450,9 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
|
|
|
3443
3450
|
}
|
|
3444
3451
|
|
|
3445
3452
|
// src/components/forms/listbox.ts
|
|
3446
|
-
var
|
|
3453
|
+
var React24 = __toESM(require("react"), 1);
|
|
3447
3454
|
function useListboxNav({ count, onSelect }) {
|
|
3448
|
-
const [active, setActive] =
|
|
3455
|
+
const [active, setActive] = React24.useState(-1);
|
|
3449
3456
|
return {
|
|
3450
3457
|
active,
|
|
3451
3458
|
setActive,
|
|
@@ -3458,7 +3465,7 @@ function useListboxNav({ count, onSelect }) {
|
|
|
3458
3465
|
};
|
|
3459
3466
|
}
|
|
3460
3467
|
function useListboxScrollIntoView(active, listRef, enabled) {
|
|
3461
|
-
|
|
3468
|
+
React24.useEffect(() => {
|
|
3462
3469
|
if (!enabled || active < 0 || !listRef.current) return;
|
|
3463
3470
|
const list = listRef.current;
|
|
3464
3471
|
const el = list.querySelector('[data-i="' + active + '"]');
|
|
@@ -3645,40 +3652,40 @@ function MultiSelectPanel({
|
|
|
3645
3652
|
onClose
|
|
3646
3653
|
}) {
|
|
3647
3654
|
const allowedOps = operatorsFor(field);
|
|
3648
|
-
const [draftOperator, setDraftOperator] =
|
|
3655
|
+
const [draftOperator, setDraftOperator] = React25.useState(value?.operator ?? allowedOps[0]);
|
|
3649
3656
|
const operator = allowedOps.length === 1 ? allowedOps[0] : value?.operator ?? draftOperator;
|
|
3650
3657
|
const selected = value?.values ?? [];
|
|
3651
|
-
const selectedRef =
|
|
3652
|
-
|
|
3653
|
-
const
|
|
3654
|
-
|
|
3655
|
-
const mountedRef = React24.useRef(true);
|
|
3656
|
-
React24.useEffect(() => {
|
|
3658
|
+
const selectedRef = useLatest(selected);
|
|
3659
|
+
const operatorRef = useLatest(operator);
|
|
3660
|
+
const mountedRef = React25.useRef(true);
|
|
3661
|
+
React25.useEffect(() => {
|
|
3657
3662
|
mountedRef.current = true;
|
|
3658
3663
|
return () => {
|
|
3659
3664
|
mountedRef.current = false;
|
|
3660
3665
|
};
|
|
3661
3666
|
}, []);
|
|
3662
|
-
const commit = (nextValues, nextOperator =
|
|
3667
|
+
const commit = (nextValues, nextOperator = operatorRef.current) => {
|
|
3668
|
+
setDraftOperator(nextOperator);
|
|
3669
|
+
return onCommit({ operator: nextOperator, values: nextValues });
|
|
3670
|
+
};
|
|
3663
3671
|
const setOperator = (op) => {
|
|
3664
|
-
setDraftOperator(op);
|
|
3665
3672
|
if (selectedRef.current.length > 0) commit(selectedRef.current, op);
|
|
3673
|
+
else setDraftOperator(op);
|
|
3666
3674
|
};
|
|
3667
|
-
const [mode2, setMode] =
|
|
3668
|
-
const [query, setQuery] =
|
|
3669
|
-
const [asyncState, setAsyncState] =
|
|
3675
|
+
const [mode2, setMode] = React25.useState("search");
|
|
3676
|
+
const [query, setQuery] = React25.useState("");
|
|
3677
|
+
const [asyncState, setAsyncState] = React25.useState(
|
|
3670
3678
|
{ options: null, loading: !!field.loadOptions, error: false }
|
|
3671
3679
|
);
|
|
3672
|
-
const [retryTick, setRetryTick] =
|
|
3673
|
-
const inputRef =
|
|
3674
|
-
const listRef =
|
|
3675
|
-
const listId =
|
|
3676
|
-
const loadOptionsRef =
|
|
3677
|
-
|
|
3678
|
-
React24.useEffect(() => {
|
|
3680
|
+
const [retryTick, setRetryTick] = React25.useState(0);
|
|
3681
|
+
const inputRef = React25.useRef(null);
|
|
3682
|
+
const listRef = React25.useRef(null);
|
|
3683
|
+
const listId = React25.useId();
|
|
3684
|
+
const loadOptionsRef = useLatest(field.loadOptions);
|
|
3685
|
+
React25.useEffect(() => {
|
|
3679
3686
|
inputRef.current?.focus();
|
|
3680
3687
|
}, []);
|
|
3681
|
-
|
|
3688
|
+
React25.useEffect(() => {
|
|
3682
3689
|
const load = loadOptionsRef.current;
|
|
3683
3690
|
if (!load) return;
|
|
3684
3691
|
const controller = new AbortController();
|
|
@@ -3696,7 +3703,7 @@ function MultiSelectPanel({
|
|
|
3696
3703
|
clearTimeout(t);
|
|
3697
3704
|
controller.abort();
|
|
3698
3705
|
};
|
|
3699
|
-
}, [query, retryTick]);
|
|
3706
|
+
}, [query, retryTick, loadOptionsRef]);
|
|
3700
3707
|
const options = field.loadOptions ? asyncState.options ?? [] : (field.options ?? []).filter((o) => o.label.toLowerCase().includes(query.toLowerCase()));
|
|
3701
3708
|
const showLoading = !!field.loadOptions && asyncState.loading;
|
|
3702
3709
|
const showError = !!field.loadOptions && asyncState.error;
|
|
@@ -3711,19 +3718,24 @@ function MultiSelectPanel({
|
|
|
3711
3718
|
};
|
|
3712
3719
|
const nav = useListboxNav({ count: options.length, onSelect: (i) => toggle(options[i]) });
|
|
3713
3720
|
useListboxScrollIntoView(nav.active, listRef, hasListbox);
|
|
3714
|
-
|
|
3721
|
+
React25.useEffect(() => {
|
|
3715
3722
|
nav.setActive(0);
|
|
3716
3723
|
}, [query, options.length]);
|
|
3717
3724
|
const activeId = hasListbox && options[nav.active] ? listId + "-opt-" + nav.active : void 0;
|
|
3718
3725
|
const liveMessage = showLoading ? "Loading\u2026" : showError ? "Couldn't load options." : options.length === 0 ? "No matches" : atLimit ? "Limit reached: at most " + field.maxValues + " values" : "";
|
|
3719
|
-
const [pasteText, setPasteText] =
|
|
3720
|
-
const [pasteLoading, setPasteLoading] =
|
|
3721
|
-
const [unmatchedTokens, setUnmatchedTokens] =
|
|
3722
|
-
const [pasteError, setPasteError] =
|
|
3723
|
-
const pasteWrapRef =
|
|
3724
|
-
|
|
3726
|
+
const [pasteText, setPasteText] = React25.useState("");
|
|
3727
|
+
const [pasteLoading, setPasteLoading] = React25.useState(false);
|
|
3728
|
+
const [unmatchedTokens, setUnmatchedTokens] = React25.useState([]);
|
|
3729
|
+
const [pasteError, setPasteError] = React25.useState(null);
|
|
3730
|
+
const pasteWrapRef = React25.useRef(null);
|
|
3731
|
+
const [resolvedAt, setResolvedAt] = React25.useState(0);
|
|
3732
|
+
React25.useEffect(() => {
|
|
3725
3733
|
if (mode2 === "paste") pasteWrapRef.current?.querySelector("textarea")?.focus();
|
|
3726
3734
|
}, [mode2]);
|
|
3735
|
+
React25.useLayoutEffect(() => {
|
|
3736
|
+
if (resolvedAt === 0) return;
|
|
3737
|
+
pasteWrapRef.current?.querySelector("textarea")?.focus();
|
|
3738
|
+
}, [resolvedAt]);
|
|
3727
3739
|
const doResolve = () => {
|
|
3728
3740
|
if (!field.resolve) return;
|
|
3729
3741
|
const tokens = Array.from(new Set(pasteText.split(/[\n,]/).map((t) => t.trim()).filter(Boolean)));
|
|
@@ -3740,12 +3752,13 @@ function MultiSelectPanel({
|
|
|
3740
3752
|
setPasteError("This filter allows at most " + field.maxValues + " values; adding this list would make " + merged.size + ".");
|
|
3741
3753
|
return;
|
|
3742
3754
|
}
|
|
3743
|
-
const applied = commit(Array.from(merged.values())
|
|
3755
|
+
const applied = commit(Array.from(merged.values()));
|
|
3744
3756
|
if (!applied.ok) {
|
|
3745
3757
|
setPasteError(applied.reason);
|
|
3746
3758
|
return;
|
|
3747
3759
|
}
|
|
3748
3760
|
setPasteText("");
|
|
3761
|
+
setResolvedAt((n) => n + 1);
|
|
3749
3762
|
}, (err) => {
|
|
3750
3763
|
if (!mountedRef.current) return;
|
|
3751
3764
|
setPasteLoading(false);
|
|
@@ -3882,10 +3895,9 @@ function MultiSelectPanel({
|
|
|
3882
3895
|
);
|
|
3883
3896
|
}
|
|
3884
3897
|
function useTextValidity(onFlip) {
|
|
3885
|
-
const invalidRef =
|
|
3886
|
-
const [, rerender] =
|
|
3887
|
-
const onFlipRef =
|
|
3888
|
-
onFlipRef.current = onFlip;
|
|
3898
|
+
const invalidRef = React25.useRef(/* @__PURE__ */ new Set());
|
|
3899
|
+
const [, rerender] = React25.useReducer((n) => n + 1, 0);
|
|
3900
|
+
const onFlipRef = useLatest(onFlip);
|
|
3889
3901
|
const record = (name, valid) => {
|
|
3890
3902
|
const invalid = invalidRef.current;
|
|
3891
3903
|
if (valid !== invalid.has(name)) return false;
|
|
@@ -3902,6 +3914,12 @@ function useTextValidity(onFlip) {
|
|
|
3902
3914
|
/** For an input that is about to unmount: it has nothing left to show. */
|
|
3903
3915
|
forget: (name) => {
|
|
3904
3916
|
record(name, true);
|
|
3917
|
+
},
|
|
3918
|
+
/** For a panel that is about to remount every input: each reports afresh on mount. */
|
|
3919
|
+
reset: () => {
|
|
3920
|
+
if (invalidRef.current.size === 0) return;
|
|
3921
|
+
invalidRef.current.clear();
|
|
3922
|
+
rerender();
|
|
3905
3923
|
}
|
|
3906
3924
|
};
|
|
3907
3925
|
}
|
|
@@ -3909,6 +3927,40 @@ function applicable(field, candidate, textValid) {
|
|
|
3909
3927
|
if (!textValid || candidate === void 0) return void 0;
|
|
3910
3928
|
return validateFilterValue(field, candidate).ok ? candidate : void 0;
|
|
3911
3929
|
}
|
|
3930
|
+
function sameValue(a, b) {
|
|
3931
|
+
if (a === b) return true;
|
|
3932
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
|
|
3933
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
3934
|
+
const left = a;
|
|
3935
|
+
const right = b;
|
|
3936
|
+
for (const key of /* @__PURE__ */ new Set([...Object.keys(left), ...Object.keys(right)])) {
|
|
3937
|
+
if (!sameValue(left[key], right[key])) return false;
|
|
3938
|
+
}
|
|
3939
|
+
return true;
|
|
3940
|
+
}
|
|
3941
|
+
function useReseedFromProps(value, applies, reseed) {
|
|
3942
|
+
const seen = React25.useRef(value);
|
|
3943
|
+
React25.useLayoutEffect(() => {
|
|
3944
|
+
if (seen.current === value) return;
|
|
3945
|
+
seen.current = value;
|
|
3946
|
+
if (!sameValue(value, applies())) reseed(value);
|
|
3947
|
+
}, [value, applies, reseed]);
|
|
3948
|
+
}
|
|
3949
|
+
function usePreserveFocusAcrossRemount(seed) {
|
|
3950
|
+
const pendingId = React25.useRef(null);
|
|
3951
|
+
const capture = (ids) => {
|
|
3952
|
+
const active = document.activeElement;
|
|
3953
|
+
pendingId.current = active instanceof HTMLElement && ids.includes(active.id) ? active.id : null;
|
|
3954
|
+
};
|
|
3955
|
+
React25.useLayoutEffect(() => {
|
|
3956
|
+
const id = pendingId.current;
|
|
3957
|
+
if (!id) return;
|
|
3958
|
+
pendingId.current = null;
|
|
3959
|
+
document.getElementById(id)?.focus();
|
|
3960
|
+
}, [seed]);
|
|
3961
|
+
return capture;
|
|
3962
|
+
}
|
|
3963
|
+
var rangeDraft = (value) => ({ min: value?.min, max: value?.max });
|
|
3912
3964
|
function RangePanel({
|
|
3913
3965
|
field,
|
|
3914
3966
|
value,
|
|
@@ -3916,13 +3968,27 @@ function RangePanel({
|
|
|
3916
3968
|
onCommit,
|
|
3917
3969
|
onClose
|
|
3918
3970
|
}) {
|
|
3919
|
-
const [draft, setDraft] =
|
|
3920
|
-
const
|
|
3921
|
-
const
|
|
3971
|
+
const [draft, setDraft] = React25.useState(() => rangeDraft(value));
|
|
3972
|
+
const [seed, setSeed] = React25.useState(0);
|
|
3973
|
+
const preserveFocus = usePreserveFocusAcrossRemount(seed);
|
|
3974
|
+
const minId = field.key + "-min";
|
|
3975
|
+
const maxId = field.key + "-max";
|
|
3976
|
+
const draftRef = React25.useRef(draft);
|
|
3977
|
+
const shown = () => {
|
|
3922
3978
|
const { min, max } = draftRef.current;
|
|
3923
|
-
|
|
3979
|
+
return applicable(field, min == null && max == null ? void 0 : { min, max }, validity.allValid());
|
|
3980
|
+
};
|
|
3981
|
+
const publish = () => {
|
|
3982
|
+
onCommit(shown());
|
|
3924
3983
|
};
|
|
3925
3984
|
const validity = useTextValidity(publish);
|
|
3985
|
+
useReseedFromProps(value, shown, (next) => {
|
|
3986
|
+
preserveFocus([minId, maxId]);
|
|
3987
|
+
draftRef.current = rangeDraft(next);
|
|
3988
|
+
setDraft(draftRef.current);
|
|
3989
|
+
validity.reset();
|
|
3990
|
+
setSeed((n) => n + 1);
|
|
3991
|
+
});
|
|
3926
3992
|
const draftMin = draft.min;
|
|
3927
3993
|
const draftMax = draft.max;
|
|
3928
3994
|
const isEmpty = draftMin == null && draftMax == null;
|
|
@@ -3950,6 +4016,7 @@ function RangePanel({
|
|
|
3950
4016
|
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3951
4017
|
NumberInput,
|
|
3952
4018
|
{
|
|
4019
|
+
id: minId,
|
|
3953
4020
|
label: field.minLabel || "At least",
|
|
3954
4021
|
value: draftMin ?? "",
|
|
3955
4022
|
min: field.min,
|
|
@@ -3959,11 +4026,13 @@ function RangePanel({
|
|
|
3959
4026
|
placeholder: field.minPlaceholder,
|
|
3960
4027
|
onChange: (e) => apply({ min: e.target.value }),
|
|
3961
4028
|
onValidityChange: validity.report("min")
|
|
3962
|
-
}
|
|
4029
|
+
},
|
|
4030
|
+
"min-" + seed
|
|
3963
4031
|
),
|
|
3964
4032
|
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3965
4033
|
NumberInput,
|
|
3966
4034
|
{
|
|
4035
|
+
id: maxId,
|
|
3967
4036
|
label: field.maxLabel || "At most",
|
|
3968
4037
|
value: draftMax ?? "",
|
|
3969
4038
|
min: field.min,
|
|
@@ -3974,12 +4043,20 @@ function RangePanel({
|
|
|
3974
4043
|
placeholder: field.maxPlaceholder,
|
|
3975
4044
|
onChange: (e) => apply({ max: e.target.value }),
|
|
3976
4045
|
onValidityChange: validity.report("max")
|
|
3977
|
-
}
|
|
4046
|
+
},
|
|
4047
|
+
"max-" + seed
|
|
3978
4048
|
)
|
|
3979
4049
|
] })
|
|
3980
4050
|
}
|
|
3981
4051
|
);
|
|
3982
4052
|
}
|
|
4053
|
+
function dateDraft(field, value) {
|
|
4054
|
+
return {
|
|
4055
|
+
kind: value?.kind ?? "withinDays",
|
|
4056
|
+
days: value?.kind === "withinDays" ? value.days : field.defaultDays ?? 30,
|
|
4057
|
+
between: value?.kind === "between" ? { from: value.from, to: value.to } : { from: "", to: "" }
|
|
4058
|
+
};
|
|
4059
|
+
}
|
|
3983
4060
|
function DatePanel({
|
|
3984
4061
|
field,
|
|
3985
4062
|
value,
|
|
@@ -3987,23 +4064,44 @@ function DatePanel({
|
|
|
3987
4064
|
onCommit,
|
|
3988
4065
|
onClose
|
|
3989
4066
|
}) {
|
|
3990
|
-
const defaultDays = field.defaultDays ?? 30;
|
|
3991
4067
|
const maxDays = effectiveMaxDays(field);
|
|
3992
|
-
const [
|
|
3993
|
-
const [
|
|
3994
|
-
|
|
3995
|
-
);
|
|
3996
|
-
const
|
|
3997
|
-
const [between, setBetween] =
|
|
3998
|
-
|
|
3999
|
-
);
|
|
4068
|
+
const [initial] = React25.useState(() => dateDraft(field, value));
|
|
4069
|
+
const [kind, setKind] = React25.useState(initial.kind);
|
|
4070
|
+
const [daysDraft, setDaysDraft] = React25.useState(initial.days);
|
|
4071
|
+
const daysRef = React25.useRef(daysDraft);
|
|
4072
|
+
const daysConfirmed = React25.useRef(value?.kind === "withinDays");
|
|
4073
|
+
const [between, setBetween] = React25.useState(initial.between);
|
|
4074
|
+
const [seed, setSeed] = React25.useState(0);
|
|
4075
|
+
const preserveFocus = usePreserveFocusAcrossRemount(seed);
|
|
4076
|
+
const daysId = field.key + "-days";
|
|
4000
4077
|
const shownWithinDays = () => {
|
|
4001
4078
|
const days = daysRef.current;
|
|
4002
4079
|
return applicable(field, days == null ? void 0 : { kind: "withinDays", days }, validity.allValid());
|
|
4003
4080
|
};
|
|
4004
|
-
const validity = useTextValidity(() =>
|
|
4081
|
+
const validity = useTextValidity(() => {
|
|
4082
|
+
daysConfirmed.current = true;
|
|
4083
|
+
onCommit(shownWithinDays());
|
|
4084
|
+
});
|
|
4085
|
+
const applies = () => {
|
|
4086
|
+
if (kind === "between") {
|
|
4087
|
+
return applicable(field, between.from && between.to ? { kind: "between", ...between } : void 0, true);
|
|
4088
|
+
}
|
|
4089
|
+
return daysConfirmed.current ? shownWithinDays() : void 0;
|
|
4090
|
+
};
|
|
4091
|
+
useReseedFromProps(value, applies, (next) => {
|
|
4092
|
+
preserveFocus([daysId]);
|
|
4093
|
+
const d = dateDraft(field, next);
|
|
4094
|
+
setKind(d.kind);
|
|
4095
|
+
daysRef.current = d.days;
|
|
4096
|
+
daysConfirmed.current = next?.kind === "withinDays";
|
|
4097
|
+
setDaysDraft(d.days);
|
|
4098
|
+
setBetween(d.between);
|
|
4099
|
+
validity.reset();
|
|
4100
|
+
setSeed((n) => n + 1);
|
|
4101
|
+
});
|
|
4005
4102
|
const applyWithinDays = (days) => {
|
|
4006
4103
|
daysRef.current = days;
|
|
4104
|
+
daysConfirmed.current = true;
|
|
4007
4105
|
setDaysDraft(days);
|
|
4008
4106
|
onCommit(shownWithinDays());
|
|
4009
4107
|
};
|
|
@@ -4018,8 +4116,10 @@ function DatePanel({
|
|
|
4018
4116
|
setBetween({ from: "", to: "" });
|
|
4019
4117
|
validity.forget("days");
|
|
4020
4118
|
} else {
|
|
4021
|
-
|
|
4022
|
-
|
|
4119
|
+
const { days } = dateDraft(field, void 0);
|
|
4120
|
+
daysRef.current = days;
|
|
4121
|
+
daysConfirmed.current = false;
|
|
4122
|
+
setDaysDraft(days);
|
|
4023
4123
|
}
|
|
4024
4124
|
onCommit(void 0);
|
|
4025
4125
|
};
|
|
@@ -4059,6 +4159,7 @@ function DatePanel({
|
|
|
4059
4159
|
kind === "withinDays" ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
4060
4160
|
NumberInput,
|
|
4061
4161
|
{
|
|
4162
|
+
id: daysId,
|
|
4062
4163
|
label: "Days",
|
|
4063
4164
|
min: 1,
|
|
4064
4165
|
max: maxDays,
|
|
@@ -4067,7 +4168,8 @@ function DatePanel({
|
|
|
4067
4168
|
value: daysDraft ?? "",
|
|
4068
4169
|
onChange: (e) => applyWithinDays(e.target.value),
|
|
4069
4170
|
onValidityChange: validity.report("days")
|
|
4070
|
-
}
|
|
4171
|
+
},
|
|
4172
|
+
"days-" + seed
|
|
4071
4173
|
) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
4072
4174
|
DatePicker,
|
|
4073
4175
|
{
|
|
@@ -4075,30 +4177,23 @@ function DatePanel({
|
|
|
4075
4177
|
label: "Date range",
|
|
4076
4178
|
value: { start: between.from, end: between.to },
|
|
4077
4179
|
onChange: (e) => applyBetween(e.target.value.start || "", e.target.value.end || "")
|
|
4078
|
-
}
|
|
4180
|
+
},
|
|
4181
|
+
"between-" + seed
|
|
4079
4182
|
)
|
|
4080
4183
|
] })
|
|
4081
4184
|
}
|
|
4082
4185
|
);
|
|
4083
4186
|
}
|
|
4084
4187
|
function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align = "left", className = "", ...rest }) {
|
|
4085
|
-
const [panel, setPanel] =
|
|
4086
|
-
const editAnchorRef =
|
|
4087
|
-
const addAnchorRef =
|
|
4088
|
-
const textInputRef =
|
|
4089
|
-
const optionsRef =
|
|
4188
|
+
const [panel, setPanel] = React25.useState(null);
|
|
4189
|
+
const editAnchorRef = React25.useRef(null);
|
|
4190
|
+
const addAnchorRef = React25.useRef(null);
|
|
4191
|
+
const textInputRef = React25.useRef(null);
|
|
4192
|
+
const optionsRef = React25.useRef(null);
|
|
4090
4193
|
if (process.env.NODE_ENV !== "production") {
|
|
4091
4194
|
for (const f of fields) assertValidFieldDefinition(f);
|
|
4092
4195
|
}
|
|
4093
|
-
const latest =
|
|
4094
|
-
const filtersProp = React24.useRef(filters);
|
|
4095
|
-
if (filters !== filtersProp.current) {
|
|
4096
|
-
filtersProp.current = filters;
|
|
4097
|
-
latest.current.filters = filters;
|
|
4098
|
-
}
|
|
4099
|
-
latest.current.fields = fields;
|
|
4100
|
-
latest.current.onFilterChange = onFilterChange;
|
|
4101
|
-
latest.current.onFilterRemove = onFilterRemove;
|
|
4196
|
+
const latest = useLatest({ fields, filters, onFilterChange, onFilterRemove });
|
|
4102
4197
|
const commit = (field, candidate) => {
|
|
4103
4198
|
const current2 = latest.current.fields.find((f) => f.key === field.key);
|
|
4104
4199
|
if (!current2) return { ok: false, reason: "This filter is no longer available" };
|
|
@@ -4107,24 +4202,17 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
4107
4202
|
return { ok: true };
|
|
4108
4203
|
}
|
|
4109
4204
|
const result = validateFilterValue(current2, candidate);
|
|
4110
|
-
if (result.ok)
|
|
4111
|
-
latest.current.filters = { ...latest.current.filters, [current2.key]: candidate };
|
|
4112
|
-
latest.current.onFilterChange(current2.key, candidate);
|
|
4113
|
-
}
|
|
4205
|
+
if (result.ok) latest.current.onFilterChange(current2.key, candidate);
|
|
4114
4206
|
return result;
|
|
4115
4207
|
};
|
|
4116
4208
|
const removeField = (field) => {
|
|
4117
4209
|
const { filters: now, onFilterRemove: remove } = latest.current;
|
|
4118
|
-
if (
|
|
4119
|
-
const next = { ...now };
|
|
4120
|
-
delete next[field.key];
|
|
4121
|
-
latest.current.filters = next;
|
|
4122
|
-
remove(field.key);
|
|
4210
|
+
if (isFieldSet(field, now[field.key])) remove(field.key);
|
|
4123
4211
|
};
|
|
4124
4212
|
const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
|
|
4125
4213
|
const startEditing = (key) => setPanel({ kind: "edit", key });
|
|
4126
4214
|
const closeEditing = () => setPanel(null);
|
|
4127
|
-
|
|
4215
|
+
React25.useEffect(() => {
|
|
4128
4216
|
if (!panel || panel.kind !== "edit") return;
|
|
4129
4217
|
if (editingField?.type === "text") {
|
|
4130
4218
|
textInputRef.current?.focus();
|
|
@@ -4330,7 +4418,7 @@ function StatTile({ label, value, sub, delta, invert = false, loading = false, c
|
|
|
4330
4418
|
}
|
|
4331
4419
|
|
|
4332
4420
|
// src/components/data/CodeBlock.tsx
|
|
4333
|
-
var
|
|
4421
|
+
var React26 = __toESM(require("react"), 1);
|
|
4334
4422
|
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
4335
4423
|
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)$/;
|
|
4336
4424
|
var RULES = {
|
|
@@ -4486,13 +4574,13 @@ function tokenize(src, lang) {
|
|
|
4486
4574
|
return out;
|
|
4487
4575
|
}
|
|
4488
4576
|
function Highlighted({ code, lang }) {
|
|
4489
|
-
const toks =
|
|
4577
|
+
const toks = React26.useMemo(() => tokenize(code, lang), [code, lang]);
|
|
4490
4578
|
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_jsx_runtime47.Fragment, { children: toks.map((tk, i) => tk.c ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "tok-" + tk.c, children: tk.t }, i) : tk.t) });
|
|
4491
4579
|
}
|
|
4492
4580
|
function useCopy() {
|
|
4493
|
-
const [done, setDone] =
|
|
4494
|
-
const timer =
|
|
4495
|
-
|
|
4581
|
+
const [done, setDone] = React26.useState(false);
|
|
4582
|
+
const timer = React26.useRef(null);
|
|
4583
|
+
React26.useEffect(() => () => {
|
|
4496
4584
|
if (timer.current) clearTimeout(timer.current);
|
|
4497
4585
|
}, []);
|
|
4498
4586
|
const copy = (text) => {
|
|
@@ -4528,8 +4616,8 @@ function CodeBlock({
|
|
|
4528
4616
|
actions,
|
|
4529
4617
|
className = ""
|
|
4530
4618
|
}) {
|
|
4531
|
-
const [wrap, setWrap] =
|
|
4532
|
-
const [open, setOpen] =
|
|
4619
|
+
const [wrap, setWrap] = React26.useState(!!wrapDefault);
|
|
4620
|
+
const [open, setOpen] = React26.useState(false);
|
|
4533
4621
|
const [copied, copy] = useCopy();
|
|
4534
4622
|
const body = String(code).replace(/\n$/, "");
|
|
4535
4623
|
const lines = body.split("\n");
|
|
@@ -4558,7 +4646,7 @@ function CodeBlock({
|
|
|
4558
4646
|
] });
|
|
4559
4647
|
}
|
|
4560
4648
|
function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
|
|
4561
|
-
const [open, setOpen] =
|
|
4649
|
+
const [open, setOpen] = React26.useState(false);
|
|
4562
4650
|
const [copied, copy] = useCopy();
|
|
4563
4651
|
const raw = String(diff).replace(/\n$/, "");
|
|
4564
4652
|
const all = raw.split("\n").map((line) => {
|
|
@@ -4604,7 +4692,7 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
|
|
|
4604
4692
|
}
|
|
4605
4693
|
|
|
4606
4694
|
// src/components/data/Markdown.tsx
|
|
4607
|
-
var
|
|
4695
|
+
var React27 = __toESM(require("react"), 1);
|
|
4608
4696
|
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
4609
4697
|
var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
|
|
4610
4698
|
var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
|
|
@@ -4643,7 +4731,7 @@ function inlineNodes(src, ctx, keyBase) {
|
|
|
4643
4731
|
const href = safeHref(g(2));
|
|
4644
4732
|
out.push(href ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("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__ */ (0, import_jsx_runtime48.jsx)("span", { children: g(1) }, key()));
|
|
4645
4733
|
} else if (kind === "cite") {
|
|
4646
|
-
out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
4734
|
+
out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(React27.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("sup", { className: "fd-md-cite", children: g(1) }, key()));
|
|
4647
4735
|
} else if (kind === "strongem") out.push(/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("strong", { children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("em", { children: inlineNodes(g(1), ctx, key()) }) }, key()));
|
|
4648
4736
|
else if (kind === "strong") out.push(/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
4649
4737
|
else if (kind === "em") out.push(/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
@@ -4808,7 +4896,7 @@ function Markdown({
|
|
|
4808
4896
|
onLinkClick
|
|
4809
4897
|
}) {
|
|
4810
4898
|
const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
|
|
4811
|
-
const blocks =
|
|
4899
|
+
const blocks = React27.useMemo(() => parseBlocks(source), [source]);
|
|
4812
4900
|
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: ["fd-md", className].filter(Boolean).join(" "), children: renderBlocks(blocks, ctx, "b") });
|
|
4813
4901
|
}
|
|
4814
4902
|
function MarkdownInline({ source = "", className = "", onLinkClick }) {
|
|
@@ -4922,7 +5010,7 @@ function Pagination({
|
|
|
4922
5010
|
}
|
|
4923
5011
|
|
|
4924
5012
|
// src/components/data/RelativeTime.tsx
|
|
4925
|
-
var
|
|
5013
|
+
var React28 = __toESM(require("react"), 1);
|
|
4926
5014
|
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
4927
5015
|
var MIN = 6e4;
|
|
4928
5016
|
var HOUR = 36e5;
|
|
@@ -4974,9 +5062,9 @@ function formatDuration(ms) {
|
|
|
4974
5062
|
return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
|
|
4975
5063
|
}
|
|
4976
5064
|
function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
|
|
4977
|
-
const [, force] =
|
|
5065
|
+
const [, force] = React28.useState(0);
|
|
4978
5066
|
const t = value instanceof Date ? value.getTime() : Date.parse(value);
|
|
4979
|
-
|
|
5067
|
+
React28.useEffect(() => {
|
|
4980
5068
|
if (!refresh2 || !t || isNaN(t)) return;
|
|
4981
5069
|
const abs = Math.abs(t - Date.now());
|
|
4982
5070
|
if (abs > DAY) return;
|
|
@@ -4992,7 +5080,7 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
|
|
|
4992
5080
|
}
|
|
4993
5081
|
|
|
4994
5082
|
// src/components/data/ScoreMeter.tsx
|
|
4995
|
-
var
|
|
5083
|
+
var React29 = __toESM(require("react"), 1);
|
|
4996
5084
|
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
4997
5085
|
function ScoreMeter({
|
|
4998
5086
|
score,
|
|
@@ -5007,10 +5095,10 @@ function ScoreMeter({
|
|
|
5007
5095
|
breakdownWidth = 280,
|
|
5008
5096
|
className = ""
|
|
5009
5097
|
}) {
|
|
5010
|
-
const [open, setOpen] =
|
|
5011
|
-
const ref =
|
|
5098
|
+
const [open, setOpen] = React29.useState(false);
|
|
5099
|
+
const ref = React29.useRef(null);
|
|
5012
5100
|
const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
|
|
5013
|
-
const body = /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
5101
|
+
const body = /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React29.Fragment, { children: [
|
|
5014
5102
|
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-scoremeter-rail", style: { width }, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(SegmentedMeter, { total: 100, segments, height, showTotal: false, showPercent: false, legend: false }) }),
|
|
5015
5103
|
showScore ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
|
|
5016
5104
|
] });
|
|
@@ -5029,7 +5117,7 @@ function ScoreMeter({
|
|
|
5029
5117
|
}
|
|
5030
5118
|
);
|
|
5031
5119
|
}
|
|
5032
|
-
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
5120
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React29.Fragment, { children: [
|
|
5033
5121
|
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
5034
5122
|
"button",
|
|
5035
5123
|
{
|
|
@@ -5060,13 +5148,13 @@ function ScoreMeter({
|
|
|
5060
5148
|
}
|
|
5061
5149
|
|
|
5062
5150
|
// src/components/data/SortMenu.tsx
|
|
5063
|
-
var
|
|
5151
|
+
var React30 = __toESM(require("react"), 1);
|
|
5064
5152
|
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
5065
5153
|
function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", className = "", ...rest }) {
|
|
5066
|
-
const [open, setOpen] =
|
|
5154
|
+
const [open, setOpen] = React30.useState(false);
|
|
5067
5155
|
const zIndex = useOverlayLayer(open);
|
|
5068
|
-
const ref =
|
|
5069
|
-
|
|
5156
|
+
const ref = React30.useRef(null);
|
|
5157
|
+
React30.useEffect(() => {
|
|
5070
5158
|
if (!open) return;
|
|
5071
5159
|
const away = (e) => {
|
|
5072
5160
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -5128,7 +5216,7 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
|
|
|
5128
5216
|
}
|
|
5129
5217
|
|
|
5130
5218
|
// src/components/data/StepList.tsx
|
|
5131
|
-
var
|
|
5219
|
+
var React31 = __toESM(require("react"), 1);
|
|
5132
5220
|
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
5133
5221
|
var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
|
|
5134
5222
|
function StepList({
|
|
@@ -5141,9 +5229,9 @@ function StepList({
|
|
|
5141
5229
|
dense = false,
|
|
5142
5230
|
className = ""
|
|
5143
5231
|
}) {
|
|
5144
|
-
const [openState, setOpenState] =
|
|
5232
|
+
const [openState, setOpenState] = React31.useState(defaultOpen);
|
|
5145
5233
|
const open = openProp == null ? openState : openProp;
|
|
5146
|
-
const [expanded, setExpanded] =
|
|
5234
|
+
const [expanded, setExpanded] = React31.useState({});
|
|
5147
5235
|
if (!steps.length) return null;
|
|
5148
5236
|
const running = steps.some((s) => s.status === "running");
|
|
5149
5237
|
const failed = steps.filter((s) => s.status === "error").length;
|
|
@@ -5201,7 +5289,7 @@ function StepList({
|
|
|
5201
5289
|
}
|
|
5202
5290
|
|
|
5203
5291
|
// src/components/data/VirtualList.tsx
|
|
5204
|
-
var
|
|
5292
|
+
var React32 = __toESM(require("react"), 1);
|
|
5205
5293
|
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
5206
5294
|
var VIRTUAL_LIST_BUFFER_ROWS = 20;
|
|
5207
5295
|
var VIRTUAL_LIST_ROW_GAP = 6;
|
|
@@ -5253,35 +5341,35 @@ function VirtualList({
|
|
|
5253
5341
|
className = "",
|
|
5254
5342
|
style
|
|
5255
5343
|
}) {
|
|
5256
|
-
const [scrollTop, setScrollTop] =
|
|
5257
|
-
const loaded =
|
|
5344
|
+
const [scrollTop, setScrollTop] = React32.useState(0);
|
|
5345
|
+
const loaded = React32.useMemo(
|
|
5258
5346
|
() => ({ firstItemIndex, count: items.length }),
|
|
5259
5347
|
[firstItemIndex, items.length]
|
|
5260
5348
|
);
|
|
5261
5349
|
const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
|
|
5262
5350
|
const bandKey = firstItemIndex + ":" + items.length;
|
|
5263
|
-
const win =
|
|
5351
|
+
const win = React32.useMemo(
|
|
5264
5352
|
() => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
|
|
5265
5353
|
[scrollTop, height, itemHeight, total, loaded]
|
|
5266
5354
|
);
|
|
5267
|
-
const need =
|
|
5355
|
+
const need = React32.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
|
|
5268
5356
|
const wantStart = need.start && hasMore?.start !== false;
|
|
5269
5357
|
const wantEnd = need.end && hasMore?.end !== false;
|
|
5270
5358
|
const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
|
|
5271
5359
|
const askKey = bandKey + "@" + bucket2;
|
|
5272
|
-
const asked =
|
|
5273
|
-
|
|
5360
|
+
const asked = React32.useRef({ start: null, end: null });
|
|
5361
|
+
React32.useEffect(() => {
|
|
5274
5362
|
if (loading || !wantStart || asked.current.start === askKey) return;
|
|
5275
5363
|
asked.current.start = askKey;
|
|
5276
5364
|
onNeedMore("start", win);
|
|
5277
5365
|
}, [wantStart, loading, askKey, onNeedMore, win]);
|
|
5278
|
-
|
|
5366
|
+
React32.useEffect(() => {
|
|
5279
5367
|
if (loading || !wantEnd || asked.current.end === askKey) return;
|
|
5280
5368
|
asked.current.end = askKey;
|
|
5281
5369
|
onNeedMore("end", win);
|
|
5282
5370
|
}, [wantEnd, loading, askKey, onNeedMore, win]);
|
|
5283
|
-
const lastKeysRef =
|
|
5284
|
-
const newKeys =
|
|
5371
|
+
const lastKeysRef = React32.useRef(null);
|
|
5372
|
+
const newKeys = React32.useMemo(() => {
|
|
5285
5373
|
const prev = lastKeysRef.current;
|
|
5286
5374
|
if (!prev) return /* @__PURE__ */ new Set();
|
|
5287
5375
|
const fresh = /* @__PURE__ */ new Set();
|
|
@@ -5291,7 +5379,7 @@ function VirtualList({
|
|
|
5291
5379
|
}
|
|
5292
5380
|
return fresh;
|
|
5293
5381
|
}, [items]);
|
|
5294
|
-
|
|
5382
|
+
React32.useEffect(() => {
|
|
5295
5383
|
lastKeysRef.current = new Set(items.map(keyOf));
|
|
5296
5384
|
}, [items]);
|
|
5297
5385
|
const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
|
|
@@ -5336,7 +5424,7 @@ function VirtualList({
|
|
|
5336
5424
|
}
|
|
5337
5425
|
|
|
5338
5426
|
// src/components/data/EntityRow.tsx
|
|
5339
|
-
var
|
|
5427
|
+
var React33 = __toESM(require("react"), 1);
|
|
5340
5428
|
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
5341
5429
|
var ENTITY_ROW_METRIC_WIDTH = 74;
|
|
5342
5430
|
var METRIC_TONE_COLOR = {
|
|
@@ -5349,7 +5437,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
|
|
|
5349
5437
|
const key = m.id || m.label || i;
|
|
5350
5438
|
const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
|
|
5351
5439
|
const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
|
|
5352
|
-
const content = /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
|
|
5440
|
+
const content = /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(React33.Fragment, { children: [
|
|
5353
5441
|
m.icon ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
|
|
5354
5442
|
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
|
|
5355
5443
|
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-sr", children: " " + m.label })
|
|
@@ -5441,7 +5529,7 @@ function EntityRow({
|
|
|
5441
5529
|
}
|
|
5442
5530
|
|
|
5443
5531
|
// src/components/data/TransferList.tsx
|
|
5444
|
-
var
|
|
5532
|
+
var React34 = __toESM(require("react"), 1);
|
|
5445
5533
|
var import_react_dom5 = require("react-dom");
|
|
5446
5534
|
|
|
5447
5535
|
// src/components/forms/Input.tsx
|
|
@@ -5547,12 +5635,12 @@ function TransferList({
|
|
|
5547
5635
|
listHeight = 440,
|
|
5548
5636
|
className = ""
|
|
5549
5637
|
}) {
|
|
5550
|
-
const [drag, setDrag] =
|
|
5551
|
-
const [dragOverSide, setDragOverSide] =
|
|
5552
|
-
const dragRef =
|
|
5553
|
-
const armedRef =
|
|
5554
|
-
const sideRefs =
|
|
5555
|
-
const hitTestSide =
|
|
5638
|
+
const [drag, setDrag] = React34.useState(null);
|
|
5639
|
+
const [dragOverSide, setDragOverSide] = React34.useState(null);
|
|
5640
|
+
const dragRef = React34.useRef(null);
|
|
5641
|
+
const armedRef = React34.useRef(null);
|
|
5642
|
+
const sideRefs = React34.useRef({ left: null, right: null });
|
|
5643
|
+
const hitTestSide = React34.useCallback((x, y) => {
|
|
5556
5644
|
for (const side of ["left", "right"]) {
|
|
5557
5645
|
const el = sideRefs.current[side];
|
|
5558
5646
|
if (!el) continue;
|
|
@@ -5561,7 +5649,7 @@ function TransferList({
|
|
|
5561
5649
|
}
|
|
5562
5650
|
return null;
|
|
5563
5651
|
}, []);
|
|
5564
|
-
const findItem =
|
|
5652
|
+
const findItem = React34.useCallback(
|
|
5565
5653
|
(side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
|
|
5566
5654
|
[left.items, right.items, keyOf]
|
|
5567
5655
|
);
|
|
@@ -5583,7 +5671,7 @@ function TransferList({
|
|
|
5583
5671
|
height: rect.height
|
|
5584
5672
|
};
|
|
5585
5673
|
};
|
|
5586
|
-
|
|
5674
|
+
React34.useEffect(() => {
|
|
5587
5675
|
const onMovePointer = (e) => {
|
|
5588
5676
|
const armed = armedRef.current;
|
|
5589
5677
|
if (!armed || e.pointerId !== armed.pointerId) return;
|
|
@@ -5636,7 +5724,7 @@ function TransferList({
|
|
|
5636
5724
|
window.removeEventListener("pointercancel", endDrag);
|
|
5637
5725
|
};
|
|
5638
5726
|
}, [hitTestSide, findItem, onMove]);
|
|
5639
|
-
|
|
5727
|
+
React34.useEffect(() => {
|
|
5640
5728
|
if (!drag || typeof document === "undefined") return;
|
|
5641
5729
|
const prev = document.body.style.userSelect;
|
|
5642
5730
|
document.body.style.userSelect = "none";
|
|
@@ -5744,11 +5832,11 @@ function TransferList({
|
|
|
5744
5832
|
}
|
|
5745
5833
|
|
|
5746
5834
|
// src/components/forms/Checkbox.tsx
|
|
5747
|
-
var
|
|
5835
|
+
var React35 = __toESM(require("react"), 1);
|
|
5748
5836
|
var import_jsx_runtime60 = require("react/jsx-runtime");
|
|
5749
5837
|
function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
|
|
5750
|
-
const ref =
|
|
5751
|
-
|
|
5838
|
+
const ref = React35.useRef(null);
|
|
5839
|
+
React35.useEffect(() => {
|
|
5752
5840
|
if (ref.current) ref.current.indeterminate = indeterminate;
|
|
5753
5841
|
}, [indeterminate]);
|
|
5754
5842
|
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
@@ -5792,7 +5880,7 @@ function Switch({ label, description, className = "", ...rest }) {
|
|
|
5792
5880
|
}
|
|
5793
5881
|
|
|
5794
5882
|
// src/components/forms/Select.tsx
|
|
5795
|
-
var
|
|
5883
|
+
var React36 = __toESM(require("react"), 1);
|
|
5796
5884
|
var import_jsx_runtime63 = require("react/jsx-runtime");
|
|
5797
5885
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
5798
5886
|
function Select({
|
|
@@ -5819,12 +5907,12 @@ function Select({
|
|
|
5819
5907
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
5820
5908
|
const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
|
|
5821
5909
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
5822
|
-
const [open, setOpen] =
|
|
5823
|
-
const [q, setQ] =
|
|
5824
|
-
const rootRef =
|
|
5825
|
-
const boxRef =
|
|
5826
|
-
const listRef =
|
|
5827
|
-
const typeBuf =
|
|
5910
|
+
const [open, setOpen] = React36.useState(false);
|
|
5911
|
+
const [q, setQ] = React36.useState("");
|
|
5912
|
+
const rootRef = React36.useRef(null);
|
|
5913
|
+
const boxRef = React36.useRef(null);
|
|
5914
|
+
const listRef = React36.useRef(null);
|
|
5915
|
+
const typeBuf = React36.useRef({ s: "", t: 0 });
|
|
5828
5916
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
5829
5917
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
5830
5918
|
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;
|
|
@@ -5963,7 +6051,7 @@ function Select({
|
|
|
5963
6051
|
),
|
|
5964
6052
|
q ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
5965
6053
|
] }) : void 0,
|
|
5966
|
-
footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
|
|
6054
|
+
footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(React36.Fragment, { children: [
|
|
5967
6055
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
|
|
5968
6056
|
"button",
|
|
5969
6057
|
{
|
|
@@ -5994,7 +6082,7 @@ function Select({
|
|
|
5994
6082
|
'Nothing matches "',
|
|
5995
6083
|
q,
|
|
5996
6084
|
'".'
|
|
5997
|
-
] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
|
|
6085
|
+
] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(React36.Fragment, { children: [
|
|
5998
6086
|
grp.g ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
|
|
5999
6087
|
grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
|
|
6000
6088
|
"button",
|
|
@@ -6031,7 +6119,7 @@ function Select({
|
|
|
6031
6119
|
}
|
|
6032
6120
|
|
|
6033
6121
|
// src/components/forms/TimePicker.tsx
|
|
6034
|
-
var
|
|
6122
|
+
var React37 = __toESM(require("react"), 1);
|
|
6035
6123
|
var import_jsx_runtime64 = require("react/jsx-runtime");
|
|
6036
6124
|
var pad = (n) => String(n).padStart(2, "0");
|
|
6037
6125
|
function ClockFace({ value = "09:00", onChange }) {
|
|
@@ -6040,9 +6128,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
6040
6128
|
if (isNaN(m)) m = 0;
|
|
6041
6129
|
const pm = h24 >= 12;
|
|
6042
6130
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
6043
|
-
const [mode2, setMode] =
|
|
6044
|
-
const faceRef =
|
|
6045
|
-
const dragging =
|
|
6131
|
+
const [mode2, setMode] = React37.useState("h");
|
|
6132
|
+
const faceRef = React37.useRef(null);
|
|
6133
|
+
const dragging = React37.useRef(false);
|
|
6046
6134
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
6047
6135
|
const R = 108, NR = 80;
|
|
6048
6136
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -6115,9 +6203,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
6115
6203
|
}
|
|
6116
6204
|
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
|
|
6117
6205
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
6118
|
-
const [open, setOpen] =
|
|
6119
|
-
const rootRef =
|
|
6120
|
-
const boxRef =
|
|
6206
|
+
const [open, setOpen] = React37.useState(false);
|
|
6207
|
+
const rootRef = React37.useRef(null);
|
|
6208
|
+
const boxRef = React37.useRef(null);
|
|
6121
6209
|
const disp = () => {
|
|
6122
6210
|
if (!value) return "";
|
|
6123
6211
|
const [h, m] = value.split(":").map(Number);
|
|
@@ -6160,7 +6248,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
6160
6248
|
offset: 6,
|
|
6161
6249
|
width: 262,
|
|
6162
6250
|
role: "presentation",
|
|
6163
|
-
footer: /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
|
|
6251
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(React37.Fragment, { children: [
|
|
6164
6252
|
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
|
|
6165
6253
|
"button",
|
|
6166
6254
|
{
|
|
@@ -6188,7 +6276,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
6188
6276
|
}
|
|
6189
6277
|
|
|
6190
6278
|
// src/components/forms/Slider.tsx
|
|
6191
|
-
var
|
|
6279
|
+
var React38 = __toESM(require("react"), 1);
|
|
6192
6280
|
var import_jsx_runtime65 = require("react/jsx-runtime");
|
|
6193
6281
|
function Slider({
|
|
6194
6282
|
label,
|
|
@@ -6206,7 +6294,7 @@ function Slider({
|
|
|
6206
6294
|
...rest
|
|
6207
6295
|
}) {
|
|
6208
6296
|
const fieldId = useFieldId(id);
|
|
6209
|
-
const [dragging, setDragging] =
|
|
6297
|
+
const [dragging, setDragging] = React38.useState(false);
|
|
6210
6298
|
const v = value === void 0 ? min : Number(value);
|
|
6211
6299
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
6212
6300
|
return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
|
|
@@ -6240,7 +6328,7 @@ function Slider({
|
|
|
6240
6328
|
}
|
|
6241
6329
|
|
|
6242
6330
|
// src/components/forms/RangeSlider.tsx
|
|
6243
|
-
var
|
|
6331
|
+
var React39 = __toESM(require("react"), 1);
|
|
6244
6332
|
var import_jsx_runtime66 = require("react/jsx-runtime");
|
|
6245
6333
|
function RangeSlider({
|
|
6246
6334
|
label,
|
|
@@ -6260,9 +6348,9 @@ function RangeSlider({
|
|
|
6260
6348
|
}) {
|
|
6261
6349
|
const fmt2 = format || ((v) => String(v));
|
|
6262
6350
|
const [a, b] = value || [min, max];
|
|
6263
|
-
const [drag, setDrag] =
|
|
6264
|
-
const [focus, setFocus] =
|
|
6265
|
-
const railRef =
|
|
6351
|
+
const [drag, setDrag] = React39.useState(null);
|
|
6352
|
+
const [focus, setFocus] = React39.useState(null);
|
|
6353
|
+
const railRef = React39.useRef(null);
|
|
6266
6354
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
6267
6355
|
const clampPair = (i, v) => {
|
|
6268
6356
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -6277,7 +6365,7 @@ function RangeSlider({
|
|
|
6277
6365
|
const r = railRef.current.getBoundingClientRect();
|
|
6278
6366
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
6279
6367
|
};
|
|
6280
|
-
|
|
6368
|
+
React39.useEffect(() => {
|
|
6281
6369
|
if (drag === null) return;
|
|
6282
6370
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
6283
6371
|
const upH = () => setDrag(null);
|
|
@@ -6358,7 +6446,7 @@ function RangeSlider({
|
|
|
6358
6446
|
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
|
|
6359
6447
|
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-range-rail", ref: railRef }),
|
|
6360
6448
|
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
|
|
6361
|
-
marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
|
|
6449
|
+
marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(React39.Fragment, { children: [
|
|
6362
6450
|
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
|
|
6363
6451
|
m.label ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
|
|
6364
6452
|
] }, m.value)),
|
|
@@ -6387,7 +6475,7 @@ function RangeSlider({
|
|
|
6387
6475
|
}
|
|
6388
6476
|
|
|
6389
6477
|
// src/components/forms/Dropzone.tsx
|
|
6390
|
-
var
|
|
6478
|
+
var React40 = __toESM(require("react"), 1);
|
|
6391
6479
|
var import_jsx_runtime67 = require("react/jsx-runtime");
|
|
6392
6480
|
function Dropzone({
|
|
6393
6481
|
onFiles,
|
|
@@ -6402,8 +6490,8 @@ function Dropzone({
|
|
|
6402
6490
|
className = "",
|
|
6403
6491
|
style
|
|
6404
6492
|
}) {
|
|
6405
|
-
const [over, setOver] =
|
|
6406
|
-
const depth =
|
|
6493
|
+
const [over, setOver] = React40.useState(false);
|
|
6494
|
+
const depth = React40.useRef(0);
|
|
6407
6495
|
const has = (e) => {
|
|
6408
6496
|
const dt = e.dataTransfer;
|
|
6409
6497
|
if (!dt) return false;
|
|
@@ -6465,8 +6553,8 @@ function FilePickButton({
|
|
|
6465
6553
|
className = "",
|
|
6466
6554
|
children
|
|
6467
6555
|
}) {
|
|
6468
|
-
const ref =
|
|
6469
|
-
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
|
|
6556
|
+
const ref = React40.useRef(null);
|
|
6557
|
+
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(React40.Fragment, { children: [
|
|
6470
6558
|
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
|
|
6471
6559
|
"button",
|
|
6472
6560
|
{
|
|
@@ -6499,10 +6587,10 @@ function FilePickButton({
|
|
|
6499
6587
|
}
|
|
6500
6588
|
function useStagedFiles(upload, opts) {
|
|
6501
6589
|
const o = opts || {};
|
|
6502
|
-
const [items, setItems] =
|
|
6503
|
-
const controllers =
|
|
6590
|
+
const [items, setItems] = React40.useState([]);
|
|
6591
|
+
const controllers = React40.useRef({});
|
|
6504
6592
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
6505
|
-
const run =
|
|
6593
|
+
const run = React40.useCallback((att) => {
|
|
6506
6594
|
if (!upload) return;
|
|
6507
6595
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
6508
6596
|
controllers.current[att.id] = ac;
|
|
@@ -6519,14 +6607,14 @@ function useStagedFiles(upload, opts) {
|
|
|
6519
6607
|
delete controllers.current[att.id];
|
|
6520
6608
|
});
|
|
6521
6609
|
}, [upload]);
|
|
6522
|
-
const add =
|
|
6610
|
+
const add = React40.useCallback((files) => {
|
|
6523
6611
|
if (!upload) return [];
|
|
6524
6612
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
6525
6613
|
setItems((list) => list.concat(atts));
|
|
6526
6614
|
atts.forEach(run);
|
|
6527
6615
|
return atts;
|
|
6528
6616
|
}, [upload, run]);
|
|
6529
|
-
const remove =
|
|
6617
|
+
const remove = React40.useCallback((att) => {
|
|
6530
6618
|
const ac = controllers.current[att.id];
|
|
6531
6619
|
if (ac) {
|
|
6532
6620
|
try {
|
|
@@ -6537,10 +6625,10 @@ function useStagedFiles(upload, opts) {
|
|
|
6537
6625
|
}
|
|
6538
6626
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
6539
6627
|
}, []);
|
|
6540
|
-
const retry =
|
|
6628
|
+
const retry = React40.useCallback((att) => {
|
|
6541
6629
|
run(att);
|
|
6542
6630
|
}, [run]);
|
|
6543
|
-
const clear =
|
|
6631
|
+
const clear = React40.useCallback(() => {
|
|
6544
6632
|
Object.values(controllers.current).forEach((ac) => {
|
|
6545
6633
|
try {
|
|
6546
6634
|
ac && ac.abort();
|
|
@@ -6664,7 +6752,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
6664
6752
|
}
|
|
6665
6753
|
|
|
6666
6754
|
// src/components/forms/MarkdownEditor.tsx
|
|
6667
|
-
var
|
|
6755
|
+
var React41 = __toESM(require("react"), 1);
|
|
6668
6756
|
var import_jsx_runtime69 = require("react/jsx-runtime");
|
|
6669
6757
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
6670
6758
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
@@ -6878,7 +6966,7 @@ function syncDom(root, value) {
|
|
|
6878
6966
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
6879
6967
|
}
|
|
6880
6968
|
var LIST_CONT = RE_LI;
|
|
6881
|
-
var MarkdownEditor =
|
|
6969
|
+
var MarkdownEditor = React41.forwardRef(function MarkdownEditor2({
|
|
6882
6970
|
value = "",
|
|
6883
6971
|
onChange,
|
|
6884
6972
|
onSubmit,
|
|
@@ -6897,10 +6985,10 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6897
6985
|
className = "",
|
|
6898
6986
|
id
|
|
6899
6987
|
}, ref) {
|
|
6900
|
-
const boxRef =
|
|
6901
|
-
const composing =
|
|
6902
|
-
const pendingCaret =
|
|
6903
|
-
|
|
6988
|
+
const boxRef = React41.useRef(null);
|
|
6989
|
+
const composing = React41.useRef(false);
|
|
6990
|
+
const pendingCaret = React41.useRef(null);
|
|
6991
|
+
React41.useLayoutEffect(() => {
|
|
6904
6992
|
const root = boxRef.current;
|
|
6905
6993
|
if (!root || composing.current) return;
|
|
6906
6994
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -6909,7 +6997,7 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6909
6997
|
pendingCaret.current = null;
|
|
6910
6998
|
if (active && caret != null) placeCaret(root, caret);
|
|
6911
6999
|
}, [value]);
|
|
6912
|
-
|
|
7000
|
+
React41.useEffect(() => {
|
|
6913
7001
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
6914
7002
|
}, [autoFocus]);
|
|
6915
7003
|
const caretNow = () => {
|
|
@@ -6976,7 +7064,7 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6976
7064
|
api.replaceRange(from, to, next, from + next.length);
|
|
6977
7065
|
}
|
|
6978
7066
|
};
|
|
6979
|
-
|
|
7067
|
+
React41.useImperativeHandle(ref, () => api);
|
|
6980
7068
|
function detect(text, caret) {
|
|
6981
7069
|
if (!onTrigger) return;
|
|
6982
7070
|
const upto = text.slice(0, caret);
|
|
@@ -7128,16 +7216,16 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
7128
7216
|
});
|
|
7129
7217
|
|
|
7130
7218
|
// src/components/platform/AccountMenu.tsx
|
|
7131
|
-
var
|
|
7219
|
+
var React43 = __toESM(require("react"), 1);
|
|
7132
7220
|
|
|
7133
7221
|
// src/kits/sessionContext.tsx
|
|
7134
|
-
var
|
|
7135
|
-
var SessionContext =
|
|
7222
|
+
var React42 = __toESM(require("react"), 1);
|
|
7223
|
+
var SessionContext = React42.createContext(null);
|
|
7136
7224
|
function SessionProvider({ value, children }) {
|
|
7137
|
-
return
|
|
7225
|
+
return React42.createElement(SessionContext.Provider, { value }, children);
|
|
7138
7226
|
}
|
|
7139
7227
|
function useSessionContext() {
|
|
7140
|
-
const ctx =
|
|
7228
|
+
const ctx = React42.useContext(SessionContext);
|
|
7141
7229
|
if (!ctx) {
|
|
7142
7230
|
throw new Error(
|
|
7143
7231
|
"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."
|
|
@@ -7177,11 +7265,11 @@ function AccountMenu({
|
|
|
7177
7265
|
...rest
|
|
7178
7266
|
}) {
|
|
7179
7267
|
const { user, roles, can: can2, signOut: ctxSignOut, demo } = useSessionContext();
|
|
7180
|
-
const [open, setOpen] =
|
|
7181
|
-
const [switching, setSwitching] =
|
|
7182
|
-
const [signingOut, setSigningOut] =
|
|
7183
|
-
const [signOutError, setSignOutError] =
|
|
7184
|
-
const ref =
|
|
7268
|
+
const [open, setOpen] = React43.useState(false);
|
|
7269
|
+
const [switching, setSwitching] = React43.useState(false);
|
|
7270
|
+
const [signingOut, setSigningOut] = React43.useState(false);
|
|
7271
|
+
const [signOutError, setSignOutError] = React43.useState(null);
|
|
7272
|
+
const ref = React43.useRef(null);
|
|
7185
7273
|
const visibleLinks = links.filter((l) => !l.perm || can2(l.perm));
|
|
7186
7274
|
const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || can2(l.perm)) })).filter((g) => g.links.length);
|
|
7187
7275
|
const closeMenu = () => {
|
|
@@ -7306,13 +7394,13 @@ function AccountMenu({
|
|
|
7306
7394
|
}
|
|
7307
7395
|
|
|
7308
7396
|
// src/components/platform/AppSwitcher.tsx
|
|
7309
|
-
var
|
|
7397
|
+
var React44 = __toESM(require("react"), 1);
|
|
7310
7398
|
var import_jsx_runtime71 = require("react/jsx-runtime");
|
|
7311
7399
|
function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
7312
7400
|
const { apps: contextApps } = useSessionContext();
|
|
7313
7401
|
const apps = appsProp ?? contextApps ?? [];
|
|
7314
|
-
const [open, setOpen] =
|
|
7315
|
-
const anchorRef =
|
|
7402
|
+
const [open, setOpen] = React44.useState(false);
|
|
7403
|
+
const anchorRef = React44.useRef(null);
|
|
7316
7404
|
if (!apps.length) return null;
|
|
7317
7405
|
const items = apps.map((app) => ({
|
|
7318
7406
|
id: app.key,
|
|
@@ -7326,7 +7414,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7326
7414
|
window.location.href = app.url;
|
|
7327
7415
|
}
|
|
7328
7416
|
}));
|
|
7329
|
-
return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
|
|
7417
|
+
return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(React44.Fragment, { children: [
|
|
7330
7418
|
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
|
|
7331
7419
|
IconButton,
|
|
7332
7420
|
{
|
|
@@ -7355,10 +7443,10 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7355
7443
|
}
|
|
7356
7444
|
|
|
7357
7445
|
// src/components/platform/AppearanceMenu.tsx
|
|
7358
|
-
var
|
|
7446
|
+
var React46 = __toESM(require("react"), 1);
|
|
7359
7447
|
|
|
7360
7448
|
// src/kits/appearance.ts
|
|
7361
|
-
var
|
|
7449
|
+
var React45 = __toESM(require("react"), 1);
|
|
7362
7450
|
var DEFAULT_STORAGE_KEY = "fd-appearance";
|
|
7363
7451
|
var DEFAULT_PREFS = {
|
|
7364
7452
|
theme: "system",
|
|
@@ -7453,11 +7541,11 @@ function applyPrefs(prefs, root = document.documentElement) {
|
|
|
7453
7541
|
else root.removeAttribute("data-motion");
|
|
7454
7542
|
}
|
|
7455
7543
|
function useAppearancePrefs(store) {
|
|
7456
|
-
const prefs =
|
|
7457
|
-
|
|
7544
|
+
const prefs = React45.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
7545
|
+
React45.useEffect(() => {
|
|
7458
7546
|
applyPrefs(prefs);
|
|
7459
7547
|
}, [prefs]);
|
|
7460
|
-
|
|
7548
|
+
React45.useEffect(() => {
|
|
7461
7549
|
if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
7462
7550
|
return;
|
|
7463
7551
|
}
|
|
@@ -7466,7 +7554,7 @@ function useAppearancePrefs(store) {
|
|
|
7466
7554
|
mq.addEventListener("change", onChange);
|
|
7467
7555
|
return () => mq.removeEventListener("change", onChange);
|
|
7468
7556
|
}, [prefs]);
|
|
7469
|
-
const update =
|
|
7557
|
+
const update = React45.useCallback(
|
|
7470
7558
|
(patch) => {
|
|
7471
7559
|
store.write({ ...store.getSnapshot(), ...patch });
|
|
7472
7560
|
},
|
|
@@ -7489,15 +7577,15 @@ var TEXT_SCALE_OPTIONS = [
|
|
|
7489
7577
|
{ value: "xl", label: "XL" }
|
|
7490
7578
|
];
|
|
7491
7579
|
function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
|
|
7492
|
-
const store =
|
|
7580
|
+
const store = React46.useMemo(
|
|
7493
7581
|
() => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
|
|
7494
7582
|
[storeProp, storageKey, storage, defaults]
|
|
7495
7583
|
);
|
|
7496
7584
|
const [prefs, update] = useAppearancePrefs(store);
|
|
7497
|
-
const [open, setOpen] =
|
|
7498
|
-
const anchorRef =
|
|
7585
|
+
const [open, setOpen] = React46.useState(false);
|
|
7586
|
+
const anchorRef = React46.useRef(null);
|
|
7499
7587
|
const patch = (p) => update(p);
|
|
7500
|
-
return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
|
|
7588
|
+
return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(React46.Fragment, { children: [
|
|
7501
7589
|
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
|
|
7502
7590
|
IconButton,
|
|
7503
7591
|
{
|
|
@@ -7566,14 +7654,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7566
7654
|
}
|
|
7567
7655
|
|
|
7568
7656
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
7569
|
-
var
|
|
7657
|
+
var React47 = __toESM(require("react"), 1);
|
|
7570
7658
|
var import_jsx_runtime73 = require("react/jsx-runtime");
|
|
7571
7659
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
7572
7660
|
function Json({ obj }) {
|
|
7573
7661
|
return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
7574
7662
|
}
|
|
7575
7663
|
function Endpoint({ s, onRequest }) {
|
|
7576
|
-
const [tried, setTried] =
|
|
7664
|
+
const [tried, setTried] = React47.useState(null);
|
|
7577
7665
|
const run = async () => {
|
|
7578
7666
|
setTried("busy");
|
|
7579
7667
|
const t0 = (window.performance || Date).now();
|
|
@@ -7646,10 +7734,10 @@ function ApiSpecBrowser({
|
|
|
7646
7734
|
className = "",
|
|
7647
7735
|
...rest
|
|
7648
7736
|
}) {
|
|
7649
|
-
const [q, setQ] =
|
|
7650
|
-
const [method, setMethod] =
|
|
7651
|
-
const [mod, setMod] =
|
|
7652
|
-
const [listOnly, setListOnly] =
|
|
7737
|
+
const [q, setQ] = React47.useState("");
|
|
7738
|
+
const [method, setMethod] = React47.useState(null);
|
|
7739
|
+
const [mod, setMod] = React47.useState(null);
|
|
7740
|
+
const [listOnly, setListOnly] = React47.useState(false);
|
|
7653
7741
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
7654
7742
|
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())));
|
|
7655
7743
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
@@ -7728,7 +7816,7 @@ function ApiSpecBrowser({
|
|
|
7728
7816
|
}
|
|
7729
7817
|
|
|
7730
7818
|
// src/components/platform/ProfilePage.tsx
|
|
7731
|
-
var
|
|
7819
|
+
var React48 = __toESM(require("react"), 1);
|
|
7732
7820
|
var import_jsx_runtime74 = require("react/jsx-runtime");
|
|
7733
7821
|
function fieldInitialValue(field, user) {
|
|
7734
7822
|
if (field.value) return field.value(user);
|
|
@@ -7764,21 +7852,21 @@ function ProfilePage({
|
|
|
7764
7852
|
}) {
|
|
7765
7853
|
const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
|
|
7766
7854
|
const user = userProp || sessionUser;
|
|
7767
|
-
const initialFieldValues =
|
|
7855
|
+
const initialFieldValues = React48.useMemo(() => {
|
|
7768
7856
|
const values2 = {};
|
|
7769
7857
|
for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
|
|
7770
7858
|
return values2;
|
|
7771
7859
|
}, [user.id, fields]);
|
|
7772
|
-
const initialNotify =
|
|
7860
|
+
const initialNotify = React48.useMemo(() => {
|
|
7773
7861
|
const values2 = {};
|
|
7774
7862
|
for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
|
|
7775
7863
|
return values2;
|
|
7776
7864
|
}, [user.id, notifications]);
|
|
7777
|
-
const [values, setValues] =
|
|
7778
|
-
const [notify, setNotify] =
|
|
7779
|
-
const [saving, setSaving] =
|
|
7780
|
-
const [saved, setSaved] =
|
|
7781
|
-
const [prevUserId, setPrevUserId] =
|
|
7865
|
+
const [values, setValues] = React48.useState(initialFieldValues);
|
|
7866
|
+
const [notify, setNotify] = React48.useState(initialNotify);
|
|
7867
|
+
const [saving, setSaving] = React48.useState(false);
|
|
7868
|
+
const [saved, setSaved] = React48.useState(false);
|
|
7869
|
+
const [prevUserId, setPrevUserId] = React48.useState(user.id);
|
|
7782
7870
|
if (user.id !== prevUserId) {
|
|
7783
7871
|
setPrevUserId(user.id);
|
|
7784
7872
|
setValues(initialFieldValues);
|
|
@@ -7966,11 +8054,11 @@ function ProfilePage({
|
|
|
7966
8054
|
}
|
|
7967
8055
|
|
|
7968
8056
|
// src/components/platform/SignInPage.tsx
|
|
7969
|
-
var
|
|
8057
|
+
var React49 = __toESM(require("react"), 1);
|
|
7970
8058
|
var import_jsx_runtime75 = require("react/jsx-runtime");
|
|
7971
8059
|
function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
7972
|
-
const [signingIn, setSigningIn] =
|
|
7973
|
-
const [resuming, setResuming] =
|
|
8060
|
+
const [signingIn, setSigningIn] = React49.useState(false);
|
|
8061
|
+
const [resuming, setResuming] = React49.useState(false);
|
|
7974
8062
|
function handleSignIn() {
|
|
7975
8063
|
setSigningIn(true);
|
|
7976
8064
|
onSignIn();
|
|
@@ -8159,10 +8247,10 @@ function GoogleGlyph() {
|
|
|
8159
8247
|
}
|
|
8160
8248
|
|
|
8161
8249
|
// src/components/platform/RoadmapTimeline.tsx
|
|
8162
|
-
var
|
|
8250
|
+
var React52 = __toESM(require("react"), 1);
|
|
8163
8251
|
|
|
8164
8252
|
// src/kits/session.ts
|
|
8165
|
-
var
|
|
8253
|
+
var React50 = __toESM(require("react"), 1);
|
|
8166
8254
|
var PERMISSION_CATALOG = [
|
|
8167
8255
|
{ group: "Plans", items: [
|
|
8168
8256
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -9729,8 +9817,8 @@ function roadmap(overrides) {
|
|
|
9729
9817
|
};
|
|
9730
9818
|
}
|
|
9731
9819
|
function useSession() {
|
|
9732
|
-
const [s, setS] =
|
|
9733
|
-
|
|
9820
|
+
const [s, setS] = React50.useState(getSession);
|
|
9821
|
+
React50.useEffect(() => subscribe(setS), []);
|
|
9734
9822
|
return s;
|
|
9735
9823
|
}
|
|
9736
9824
|
var SessionKit = {
|
|
@@ -9763,7 +9851,7 @@ var SessionKit = {
|
|
|
9763
9851
|
};
|
|
9764
9852
|
function DemoSessionProvider({ children }) {
|
|
9765
9853
|
const session = useSession();
|
|
9766
|
-
const value =
|
|
9854
|
+
const value = React50.useMemo(
|
|
9767
9855
|
() => ({
|
|
9768
9856
|
user: session.user,
|
|
9769
9857
|
roles: session.roles,
|
|
@@ -9779,11 +9867,11 @@ function DemoSessionProvider({ children }) {
|
|
|
9779
9867
|
}),
|
|
9780
9868
|
[session]
|
|
9781
9869
|
);
|
|
9782
|
-
return
|
|
9870
|
+
return React50.createElement(SessionProvider, { value }, children);
|
|
9783
9871
|
}
|
|
9784
9872
|
|
|
9785
9873
|
// src/kits/runtime.ts
|
|
9786
|
-
var
|
|
9874
|
+
var React51 = __toESM(require("react"), 1);
|
|
9787
9875
|
var WIRED_ENDPOINTS = [
|
|
9788
9876
|
// Nothing yet. Every id below would come from a real service:
|
|
9789
9877
|
// "plan.get", "placements.list", …
|
|
@@ -9954,8 +10042,8 @@ var RuntimeKit = {
|
|
|
9954
10042
|
};
|
|
9955
10043
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
9956
10044
|
function useRuntimeMode() {
|
|
9957
|
-
const [m, setM] =
|
|
9958
|
-
|
|
10045
|
+
const [m, setM] = React51.useState(RuntimeKit.getMode());
|
|
10046
|
+
React51.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
9959
10047
|
return m;
|
|
9960
10048
|
}
|
|
9961
10049
|
function useFeatureStatus(key) {
|
|
@@ -10038,12 +10126,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
10038
10126
|
}
|
|
10039
10127
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
10040
10128
|
const session = SessionKit.useSession();
|
|
10041
|
-
const [project, setProject] =
|
|
10042
|
-
const [q, setQ] =
|
|
10043
|
-
const scrollRef =
|
|
10044
|
-
const nowRef =
|
|
10045
|
-
const rm =
|
|
10046
|
-
const byKey =
|
|
10129
|
+
const [project, setProject] = React52.useState("");
|
|
10130
|
+
const [q, setQ] = React52.useState("");
|
|
10131
|
+
const scrollRef = React52.useRef(null);
|
|
10132
|
+
const nowRef = React52.useRef(null);
|
|
10133
|
+
const rm = React52.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
10134
|
+
const byKey = React52.useMemo(() => {
|
|
10047
10135
|
const m = {};
|
|
10048
10136
|
rm.items.forEach((i) => {
|
|
10049
10137
|
m[i.key] = i;
|
|
@@ -10052,7 +10140,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10052
10140
|
}, [rm]);
|
|
10053
10141
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
10054
10142
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
10055
|
-
|
|
10143
|
+
React52.useEffect(() => {
|
|
10056
10144
|
let raf1 = 0, raf2 = 0;
|
|
10057
10145
|
const place = () => {
|
|
10058
10146
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -10126,7 +10214,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10126
10214
|
lastPhase = item.phase;
|
|
10127
10215
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
10128
10216
|
const isBoundary = n === firstPending;
|
|
10129
|
-
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
|
|
10217
|
+
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React52.Fragment, { children: [
|
|
10130
10218
|
showPhase ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-rm-era", children: [
|
|
10131
10219
|
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
10132
10220
|
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
@@ -10170,7 +10258,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10170
10258
|
}
|
|
10171
10259
|
|
|
10172
10260
|
// src/components/platform/ComingSoon.tsx
|
|
10173
|
-
var
|
|
10261
|
+
var React53 = __toESM(require("react"), 1);
|
|
10174
10262
|
var import_react_dom6 = require("react-dom");
|
|
10175
10263
|
var import_jsx_runtime77 = require("react/jsx-runtime");
|
|
10176
10264
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
@@ -10188,8 +10276,8 @@ function writeBypassed(list) {
|
|
|
10188
10276
|
}
|
|
10189
10277
|
}
|
|
10190
10278
|
function useBypass(key) {
|
|
10191
|
-
const [on, setOn] =
|
|
10192
|
-
|
|
10279
|
+
const [on, setOn] = React53.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
10280
|
+
React53.useEffect(() => {
|
|
10193
10281
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
10194
10282
|
}, [key]);
|
|
10195
10283
|
const set = (next) => {
|
|
@@ -10236,9 +10324,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
|
|
|
10236
10324
|
] });
|
|
10237
10325
|
}
|
|
10238
10326
|
function useHoverCard(open) {
|
|
10239
|
-
const anchor =
|
|
10240
|
-
const [pos, setPos] =
|
|
10241
|
-
|
|
10327
|
+
const anchor = React53.useRef(null);
|
|
10328
|
+
const [pos, setPos] = React53.useState(null);
|
|
10329
|
+
React53.useLayoutEffect(() => {
|
|
10242
10330
|
if (!open || !anchor.current) {
|
|
10243
10331
|
setPos(null);
|
|
10244
10332
|
return;
|
|
@@ -10365,10 +10453,10 @@ function ComingSoon({
|
|
|
10365
10453
|
] });
|
|
10366
10454
|
}
|
|
10367
10455
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
10368
|
-
const [open, setOpen] =
|
|
10456
|
+
const [open, setOpen] = React53.useState(false);
|
|
10369
10457
|
const [anchor, pos] = useHoverCard(open);
|
|
10370
10458
|
const zIndex = useOverlayLayer(open);
|
|
10371
|
-
const close =
|
|
10459
|
+
const close = React53.useRef(null);
|
|
10372
10460
|
const show = () => {
|
|
10373
10461
|
if (close.current) {
|
|
10374
10462
|
clearTimeout(close.current);
|
|
@@ -10384,7 +10472,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10384
10472
|
setOpen(false);
|
|
10385
10473
|
}, 140);
|
|
10386
10474
|
};
|
|
10387
|
-
|
|
10475
|
+
React53.useEffect(() => () => {
|
|
10388
10476
|
if (close.current) clearTimeout(close.current);
|
|
10389
10477
|
}, []);
|
|
10390
10478
|
return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(
|
|
@@ -10555,14 +10643,14 @@ function PermissionHint({ perm, children }) {
|
|
|
10555
10643
|
}
|
|
10556
10644
|
|
|
10557
10645
|
// src/components/platform/ModeSwitch.tsx
|
|
10558
|
-
var
|
|
10646
|
+
var React54 = __toESM(require("react"), 1);
|
|
10559
10647
|
var import_jsx_runtime79 = require("react/jsx-runtime");
|
|
10560
10648
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
10561
10649
|
const mode2 = useRuntimeMode();
|
|
10562
|
-
const [open, setOpen] =
|
|
10650
|
+
const [open, setOpen] = React54.useState(false);
|
|
10563
10651
|
const zIndex = useOverlayLayer(open);
|
|
10564
|
-
const ref =
|
|
10565
|
-
|
|
10652
|
+
const ref = React54.useRef(null);
|
|
10653
|
+
React54.useEffect(() => {
|
|
10566
10654
|
if (!open) return;
|
|
10567
10655
|
const away = (e) => {
|
|
10568
10656
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -10818,7 +10906,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
10818
10906
|
}
|
|
10819
10907
|
|
|
10820
10908
|
// src/components/planner/MixGap.tsx
|
|
10821
|
-
var
|
|
10909
|
+
var React55 = __toESM(require("react"), 1);
|
|
10822
10910
|
var import_jsx_runtime82 = require("react/jsx-runtime");
|
|
10823
10911
|
var MIX_GAP_LAYOUT = {
|
|
10824
10912
|
trackHeight: 30,
|
|
@@ -10833,7 +10921,7 @@ function mixGapOffset(value, max) {
|
|
|
10833
10921
|
}
|
|
10834
10922
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
10835
10923
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
10836
|
-
const [hover, setHover] =
|
|
10924
|
+
const [hover, setHover] = React55.useState(null);
|
|
10837
10925
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
10838
10926
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
10839
10927
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
@@ -10976,7 +11064,7 @@ function ChannelContribution({
|
|
|
10976
11064
|
}
|
|
10977
11065
|
|
|
10978
11066
|
// src/components/planner/BudgetReallocator.tsx
|
|
10979
|
-
var
|
|
11067
|
+
var React56 = __toESM(require("react"), 1);
|
|
10980
11068
|
var import_jsx_runtime84 = require("react/jsx-runtime");
|
|
10981
11069
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
10982
11070
|
function BudgetReallocator({
|
|
@@ -10992,8 +11080,8 @@ function BudgetReallocator({
|
|
|
10992
11080
|
onCancel,
|
|
10993
11081
|
className = ""
|
|
10994
11082
|
}) {
|
|
10995
|
-
const [draft, setDraft] =
|
|
10996
|
-
|
|
11083
|
+
const [draft, setDraft] = React56.useState(spend);
|
|
11084
|
+
React56.useEffect(() => setDraft(spend), [spend]);
|
|
10997
11085
|
const dirty = draft !== spend;
|
|
10998
11086
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
10999
11087
|
const nextBand = bandFor(nextCrp);
|
|
@@ -11008,10 +11096,10 @@ function BudgetReallocator({
|
|
|
11008
11096
|
setDraft(spend);
|
|
11009
11097
|
if (onCancel) onCancel();
|
|
11010
11098
|
};
|
|
11011
|
-
const trackRef =
|
|
11012
|
-
const chipRef =
|
|
11013
|
-
const [chipLeft, setChipLeft] =
|
|
11014
|
-
|
|
11099
|
+
const trackRef = React56.useRef(null);
|
|
11100
|
+
const chipRef = React56.useRef(null);
|
|
11101
|
+
const [chipLeft, setChipLeft] = React56.useState(null);
|
|
11102
|
+
React56.useLayoutEffect(() => {
|
|
11015
11103
|
const track = trackRef.current;
|
|
11016
11104
|
if (!dirty || !track) {
|
|
11017
11105
|
setChipLeft(null);
|
|
@@ -11198,7 +11286,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "" })
|
|
|
11198
11286
|
}
|
|
11199
11287
|
|
|
11200
11288
|
// src/components/planner/PreferenceMeter.tsx
|
|
11201
|
-
var
|
|
11289
|
+
var React57 = __toESM(require("react"), 1);
|
|
11202
11290
|
var import_jsx_runtime87 = require("react/jsx-runtime");
|
|
11203
11291
|
function preferenceScore(criteria) {
|
|
11204
11292
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
@@ -11228,7 +11316,7 @@ function PreferenceMeter({
|
|
|
11228
11316
|
className = ""
|
|
11229
11317
|
}) {
|
|
11230
11318
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
11231
|
-
const segments =
|
|
11319
|
+
const segments = React57.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
11232
11320
|
return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
|
|
11233
11321
|
ScoreMeter,
|
|
11234
11322
|
{
|
|
@@ -11267,10 +11355,10 @@ function PreferenceMeter({
|
|
|
11267
11355
|
}
|
|
11268
11356
|
|
|
11269
11357
|
// src/components/chat/AgentChatPanel.tsx
|
|
11270
|
-
var
|
|
11358
|
+
var React63 = __toESM(require("react"), 1);
|
|
11271
11359
|
|
|
11272
11360
|
// src/components/chat/chatEngine.ts
|
|
11273
|
-
var
|
|
11361
|
+
var React58 = __toESM(require("react"), 1);
|
|
11274
11362
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
11275
11363
|
var JOB_PENDING = ["queued", "running"];
|
|
11276
11364
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -11324,22 +11412,22 @@ function useChatEngine(opts) {
|
|
|
11324
11412
|
onClear,
|
|
11325
11413
|
onFeedback
|
|
11326
11414
|
} = opts || {};
|
|
11327
|
-
const [status, setStatus] =
|
|
11328
|
-
const [threadId, setThreadId] =
|
|
11329
|
-
const [messages, setMessages] =
|
|
11330
|
-
const [queue, setQueue] =
|
|
11331
|
-
const [fatal, setFatal] =
|
|
11332
|
-
const [busy, setBusy] =
|
|
11333
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
11334
|
-
const listRef =
|
|
11335
|
-
const queueRef =
|
|
11336
|
-
const busyRef =
|
|
11337
|
-
const stoppedRef =
|
|
11338
|
-
const abortRef =
|
|
11339
|
-
const serverCount =
|
|
11340
|
-
const threadRef =
|
|
11341
|
-
const mounted =
|
|
11342
|
-
|
|
11415
|
+
const [status, setStatus] = React58.useState("idle");
|
|
11416
|
+
const [threadId, setThreadId] = React58.useState(null);
|
|
11417
|
+
const [messages, setMessages] = React58.useState([]);
|
|
11418
|
+
const [queue, setQueue] = React58.useState([]);
|
|
11419
|
+
const [fatal, setFatal] = React58.useState(null);
|
|
11420
|
+
const [busy, setBusy] = React58.useState(false);
|
|
11421
|
+
const [turnStartedAt, setTurnStartedAt] = React58.useState(null);
|
|
11422
|
+
const listRef = React58.useRef([]);
|
|
11423
|
+
const queueRef = React58.useRef([]);
|
|
11424
|
+
const busyRef = React58.useRef(false);
|
|
11425
|
+
const stoppedRef = React58.useRef(false);
|
|
11426
|
+
const abortRef = React58.useRef(null);
|
|
11427
|
+
const serverCount = React58.useRef(0);
|
|
11428
|
+
const threadRef = React58.useRef(null);
|
|
11429
|
+
const mounted = React58.useRef(true);
|
|
11430
|
+
React58.useEffect(() => {
|
|
11343
11431
|
mounted.current = true;
|
|
11344
11432
|
return () => {
|
|
11345
11433
|
mounted.current = false;
|
|
@@ -11361,14 +11449,14 @@ function useChatEngine(opts) {
|
|
|
11361
11449
|
}
|
|
11362
11450
|
return false;
|
|
11363
11451
|
};
|
|
11364
|
-
const loadThread =
|
|
11452
|
+
const loadThread = React58.useCallback(async (id) => {
|
|
11365
11453
|
const data = await apiAdapter.getThread(id);
|
|
11366
11454
|
const list = [...data && data.messages || []];
|
|
11367
11455
|
serverCount.current = list.length;
|
|
11368
11456
|
commit(list);
|
|
11369
11457
|
return list;
|
|
11370
11458
|
}, [apiAdapter]);
|
|
11371
|
-
|
|
11459
|
+
React58.useEffect(() => {
|
|
11372
11460
|
if (!apiAdapter) {
|
|
11373
11461
|
setStatus("idle");
|
|
11374
11462
|
setFatal(null);
|
|
@@ -11581,7 +11669,7 @@ function useChatEngine(opts) {
|
|
|
11581
11669
|
await dispatchTurn(turn);
|
|
11582
11670
|
}
|
|
11583
11671
|
}
|
|
11584
|
-
const send =
|
|
11672
|
+
const send = React58.useCallback((text, attachments) => {
|
|
11585
11673
|
const body = (text || "").trim();
|
|
11586
11674
|
if (!body && !(attachments && attachments.length)) return;
|
|
11587
11675
|
if (status === "disconnected") return;
|
|
@@ -11591,7 +11679,7 @@ function useChatEngine(opts) {
|
|
|
11591
11679
|
stoppedRef.current = false;
|
|
11592
11680
|
drain();
|
|
11593
11681
|
}, [status]);
|
|
11594
|
-
const stop =
|
|
11682
|
+
const stop = React58.useCallback(() => {
|
|
11595
11683
|
stoppedRef.current = true;
|
|
11596
11684
|
const ac = abortRef.current;
|
|
11597
11685
|
if (ac) {
|
|
@@ -11610,11 +11698,11 @@ function useChatEngine(opts) {
|
|
|
11610
11698
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
11611
11699
|
}
|
|
11612
11700
|
}, [apiAdapter]);
|
|
11613
|
-
const removeQueued =
|
|
11701
|
+
const removeQueued = React58.useCallback((id) => {
|
|
11614
11702
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
11615
11703
|
setQueue(queueRef.current.slice());
|
|
11616
11704
|
}, []);
|
|
11617
|
-
const retry =
|
|
11705
|
+
const retry = React58.useCallback(() => {
|
|
11618
11706
|
const list = listRef.current;
|
|
11619
11707
|
let at = -1;
|
|
11620
11708
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -11630,19 +11718,19 @@ function useChatEngine(opts) {
|
|
|
11630
11718
|
setQueue(queueRef.current.slice());
|
|
11631
11719
|
drain();
|
|
11632
11720
|
}, []);
|
|
11633
|
-
const clear =
|
|
11721
|
+
const clear = React58.useCallback(() => {
|
|
11634
11722
|
commit([]);
|
|
11635
11723
|
serverCount.current = 0;
|
|
11636
11724
|
queueRef.current = [];
|
|
11637
11725
|
setQueue([]);
|
|
11638
11726
|
onClear && onClear();
|
|
11639
11727
|
}, [onClear]);
|
|
11640
|
-
const setFeedback =
|
|
11728
|
+
const setFeedback = React58.useCallback((id, value) => {
|
|
11641
11729
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
11642
11730
|
const msg = listRef.current.find((m) => m.id === id);
|
|
11643
11731
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
11644
11732
|
}, [onFeedback]);
|
|
11645
|
-
const reload =
|
|
11733
|
+
const reload = React58.useCallback(async () => {
|
|
11646
11734
|
if (!threadRef.current) return;
|
|
11647
11735
|
setStatus("loading");
|
|
11648
11736
|
try {
|
|
@@ -11680,10 +11768,10 @@ var ChatKit = {
|
|
|
11680
11768
|
};
|
|
11681
11769
|
|
|
11682
11770
|
// src/components/chat/ChatTranscript.tsx
|
|
11683
|
-
var
|
|
11771
|
+
var React60 = __toESM(require("react"), 1);
|
|
11684
11772
|
|
|
11685
11773
|
// src/components/chat/ChatTurn.tsx
|
|
11686
|
-
var
|
|
11774
|
+
var React59 = __toESM(require("react"), 1);
|
|
11687
11775
|
var import_jsx_runtime88 = require("react/jsx-runtime");
|
|
11688
11776
|
function JsonView({ value }) {
|
|
11689
11777
|
let text;
|
|
@@ -11720,7 +11808,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
|
11720
11808
|
] });
|
|
11721
11809
|
}
|
|
11722
11810
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
11723
|
-
const [open, setOpen] =
|
|
11811
|
+
const [open, setOpen] = React59.useState(defaultOpen);
|
|
11724
11812
|
if (!text) return null;
|
|
11725
11813
|
return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
|
|
11726
11814
|
/* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -11737,7 +11825,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
|
11737
11825
|
] });
|
|
11738
11826
|
}
|
|
11739
11827
|
function Citations({ items = [], onOpen }) {
|
|
11740
|
-
const [open, setOpen] =
|
|
11828
|
+
const [open, setOpen] = React59.useState(false);
|
|
11741
11829
|
if (!items.length) return null;
|
|
11742
11830
|
return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fdc-cites", children: [
|
|
11743
11831
|
/* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -11763,7 +11851,7 @@ function clampText(text, max) {
|
|
|
11763
11851
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
11764
11852
|
}
|
|
11765
11853
|
function MessageBody({ message: m, ctx }) {
|
|
11766
|
-
const [expanded, setExpanded] =
|
|
11854
|
+
const [expanded, setExpanded] = React59.useState(false);
|
|
11767
11855
|
const isUser = m.role === "user";
|
|
11768
11856
|
const raw = m.text || "";
|
|
11769
11857
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
@@ -11830,9 +11918,9 @@ function MessageBody({ message: m, ctx }) {
|
|
|
11830
11918
|
] });
|
|
11831
11919
|
}
|
|
11832
11920
|
function useCopyRun() {
|
|
11833
|
-
const [done, setDone] =
|
|
11834
|
-
const t =
|
|
11835
|
-
|
|
11921
|
+
const [done, setDone] = React59.useState(false);
|
|
11922
|
+
const t = React59.useRef(null);
|
|
11923
|
+
React59.useEffect(() => () => {
|
|
11836
11924
|
if (t.current) clearTimeout(t.current);
|
|
11837
11925
|
}, []);
|
|
11838
11926
|
return [done, (text) => {
|
|
@@ -11859,7 +11947,7 @@ function RunActions({ group, ctx }) {
|
|
|
11859
11947
|
] }),
|
|
11860
11948
|
isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
11861
11949
|
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
11862
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(
|
|
11950
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(React59.Fragment, { children: [
|
|
11863
11951
|
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
11864
11952
|
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
11865
11953
|
] }) : null,
|
|
@@ -11954,10 +12042,10 @@ function ChatTranscript({
|
|
|
11954
12042
|
renderEmpty,
|
|
11955
12043
|
className = ""
|
|
11956
12044
|
}) {
|
|
11957
|
-
const scroller =
|
|
11958
|
-
const stick =
|
|
11959
|
-
const [pill, setPill] =
|
|
11960
|
-
const seen =
|
|
12045
|
+
const scroller = React60.useRef(null);
|
|
12046
|
+
const stick = React60.useRef(true);
|
|
12047
|
+
const [pill, setPill] = React60.useState(0);
|
|
12048
|
+
const seen = React60.useRef(0);
|
|
11961
12049
|
const toBottom = (smooth) => {
|
|
11962
12050
|
const el = scroller.current;
|
|
11963
12051
|
if (!el) return;
|
|
@@ -11976,7 +12064,7 @@ function ChatTranscript({
|
|
|
11976
12064
|
seen.current = messages.length;
|
|
11977
12065
|
}
|
|
11978
12066
|
};
|
|
11979
|
-
|
|
12067
|
+
React60.useLayoutEffect(() => {
|
|
11980
12068
|
const el = scroller.current;
|
|
11981
12069
|
if (!el) return;
|
|
11982
12070
|
if (stick.current) {
|
|
@@ -11984,7 +12072,7 @@ function ChatTranscript({
|
|
|
11984
12072
|
seen.current = messages.length;
|
|
11985
12073
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
11986
12074
|
}, [messages]);
|
|
11987
|
-
|
|
12075
|
+
React60.useEffect(() => {
|
|
11988
12076
|
const el = scroller.current;
|
|
11989
12077
|
const inner = el && el.firstChild;
|
|
11990
12078
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -11994,7 +12082,7 @@ function ChatTranscript({
|
|
|
11994
12082
|
ro.observe(inner);
|
|
11995
12083
|
return () => ro.disconnect();
|
|
11996
12084
|
}, []);
|
|
11997
|
-
const groups =
|
|
12085
|
+
const groups = React60.useMemo(() => groupMessages(messages), [messages]);
|
|
11998
12086
|
const empty = !messages.length && status === "ready";
|
|
11999
12087
|
return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
12000
12088
|
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
@@ -12018,7 +12106,7 @@ function ChatTranscript({
|
|
|
12018
12106
|
const prev = groups[i - 1];
|
|
12019
12107
|
const k = dayKey(g.messages[0].timestamp);
|
|
12020
12108
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
12021
|
-
return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
|
|
12109
|
+
return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(React60.Fragment, { children: [
|
|
12022
12110
|
showDay ? /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { children: dayLabel(k) }) }) : null,
|
|
12023
12111
|
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(ChatTurn, { group: g, ctx })
|
|
12024
12112
|
] }, g.key || i);
|
|
@@ -12035,7 +12123,7 @@ function ChatTranscript({
|
|
|
12035
12123
|
var TranscriptKit = { groupMessages };
|
|
12036
12124
|
|
|
12037
12125
|
// src/components/chat/ChatComposer.tsx
|
|
12038
|
-
var
|
|
12126
|
+
var React61 = __toESM(require("react"), 1);
|
|
12039
12127
|
var import_jsx_runtime90 = require("react/jsx-runtime");
|
|
12040
12128
|
function ChatComposer({
|
|
12041
12129
|
onSubmit,
|
|
@@ -12063,17 +12151,17 @@ function ChatComposer({
|
|
|
12063
12151
|
onReject,
|
|
12064
12152
|
onOpenAttachment
|
|
12065
12153
|
}) {
|
|
12066
|
-
const [text, setText] =
|
|
12067
|
-
const [trigger, setTrigger] =
|
|
12068
|
-
const [mentionItems, setMentionItems] =
|
|
12069
|
-
const [listening, setListening] =
|
|
12070
|
-
const [notice, setNotice] =
|
|
12071
|
-
const editor =
|
|
12072
|
-
const wrap =
|
|
12073
|
-
const stopVoice =
|
|
12154
|
+
const [text, setText] = React61.useState(draft || "");
|
|
12155
|
+
const [trigger, setTrigger] = React61.useState(null);
|
|
12156
|
+
const [mentionItems, setMentionItems] = React61.useState([]);
|
|
12157
|
+
const [listening, setListening] = React61.useState(false);
|
|
12158
|
+
const [notice, setNotice] = React61.useState(null);
|
|
12159
|
+
const editor = React61.useRef(null);
|
|
12160
|
+
const wrap = React61.useRef(null);
|
|
12161
|
+
const stopVoice = React61.useRef(null);
|
|
12074
12162
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
12075
12163
|
} });
|
|
12076
|
-
|
|
12164
|
+
React61.useEffect(() => {
|
|
12077
12165
|
if (draft != null && draft !== text) setText(draft);
|
|
12078
12166
|
}, [draft]);
|
|
12079
12167
|
const change = (v) => {
|
|
@@ -12109,7 +12197,7 @@ function ChatComposer({
|
|
|
12109
12197
|
e.preventDefault();
|
|
12110
12198
|
staged.add(found.files);
|
|
12111
12199
|
};
|
|
12112
|
-
|
|
12200
|
+
React61.useEffect(() => {
|
|
12113
12201
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
12114
12202
|
setMentionItems([]);
|
|
12115
12203
|
return;
|
|
@@ -12127,7 +12215,7 @@ function ChatComposer({
|
|
|
12127
12215
|
const q = (trigger.query || "").toLowerCase();
|
|
12128
12216
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
12129
12217
|
}, [trigger, mentionSources]);
|
|
12130
|
-
const slashItems =
|
|
12218
|
+
const slashItems = React61.useMemo(() => {
|
|
12131
12219
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
12132
12220
|
const q = (trigger.query || "").toLowerCase();
|
|
12133
12221
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -12301,12 +12389,12 @@ function ChatComposer({
|
|
|
12301
12389
|
}
|
|
12302
12390
|
|
|
12303
12391
|
// src/components/chat/ChatSessionBar.tsx
|
|
12304
|
-
var
|
|
12392
|
+
var React62 = __toESM(require("react"), 1);
|
|
12305
12393
|
var import_jsx_runtime91 = require("react/jsx-runtime");
|
|
12306
12394
|
var compact2 = meterFormats.compact;
|
|
12307
12395
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
12308
|
-
const [open, setOpen] =
|
|
12309
|
-
const anchor =
|
|
12396
|
+
const [open, setOpen] = React62.useState(false);
|
|
12397
|
+
const anchor = React62.useRef(null);
|
|
12310
12398
|
const stats = sessionStats || null;
|
|
12311
12399
|
const cu = contextUsage || null;
|
|
12312
12400
|
const limits = usageLimits || null;
|
|
@@ -12321,7 +12409,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12321
12409
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
12322
12410
|
if (cu) bits.push(pct + "% context");
|
|
12323
12411
|
const expandable = !!(cu || limits);
|
|
12324
|
-
return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
|
|
12412
|
+
return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(React62.Fragment, { children: [
|
|
12325
12413
|
/* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-bar", children: [
|
|
12326
12414
|
/* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
|
|
12327
12415
|
"button",
|
|
@@ -12462,7 +12550,7 @@ function ModelControls({
|
|
|
12462
12550
|
] })
|
|
12463
12551
|
});
|
|
12464
12552
|
}
|
|
12465
|
-
return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
|
|
12553
|
+
return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(React62.Fragment, { children: [
|
|
12466
12554
|
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
|
|
12467
12555
|
MenuButton,
|
|
12468
12556
|
{
|
|
@@ -12579,11 +12667,11 @@ function AgentChatPanel({
|
|
|
12579
12667
|
onFeedback,
|
|
12580
12668
|
onEditMessage
|
|
12581
12669
|
}) {
|
|
12582
|
-
const [panelWidth, setPanelWidth] =
|
|
12583
|
-
const [applied, setApplied] =
|
|
12584
|
-
const [draft, setDraft] =
|
|
12585
|
-
const dragging =
|
|
12586
|
-
|
|
12670
|
+
const [panelWidth, setPanelWidth] = React63.useState(width);
|
|
12671
|
+
const [applied, setApplied] = React63.useState({});
|
|
12672
|
+
const [draft, setDraft] = React63.useState("");
|
|
12673
|
+
const dragging = React63.useRef(null);
|
|
12674
|
+
React63.useEffect(() => setPanelWidth(width), [width]);
|
|
12587
12675
|
const engine = useChatEngine({
|
|
12588
12676
|
contextType,
|
|
12589
12677
|
contextId,
|
|
@@ -12787,7 +12875,7 @@ function AgentChatPanel({
|
|
|
12787
12875
|
}
|
|
12788
12876
|
|
|
12789
12877
|
// src/components/files/FileViewer.tsx
|
|
12790
|
-
var
|
|
12878
|
+
var React64 = __toESM(require("react"), 1);
|
|
12791
12879
|
var import_jsx_runtime93 = require("react/jsx-runtime");
|
|
12792
12880
|
function previewKindOf(file) {
|
|
12793
12881
|
const mime = (file.mime || "").toLowerCase();
|
|
@@ -12844,13 +12932,13 @@ function parseDelimited(text, delimiter) {
|
|
|
12844
12932
|
return rows;
|
|
12845
12933
|
}
|
|
12846
12934
|
function usePreview(file, kind, resolveUrl) {
|
|
12847
|
-
const [state, setState] =
|
|
12848
|
-
const [attempt, setAttempt] =
|
|
12849
|
-
const resolveRef =
|
|
12850
|
-
|
|
12935
|
+
const [state, setState] = React64.useState({ status: "loading" });
|
|
12936
|
+
const [attempt, setAttempt] = React64.useState(0);
|
|
12937
|
+
const resolveRef = React64.useRef(resolveUrl);
|
|
12938
|
+
React64.useEffect(() => {
|
|
12851
12939
|
resolveRef.current = resolveUrl;
|
|
12852
12940
|
}, [resolveUrl]);
|
|
12853
|
-
|
|
12941
|
+
React64.useEffect(() => {
|
|
12854
12942
|
if (kind === "none") {
|
|
12855
12943
|
setState({ status: "ready" });
|
|
12856
12944
|
return;
|
|
@@ -12880,7 +12968,7 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
12880
12968
|
if (ac) ac.abort();
|
|
12881
12969
|
};
|
|
12882
12970
|
}, [file.id, kind, attempt]);
|
|
12883
|
-
return { ...state, retry:
|
|
12971
|
+
return { ...state, retry: React64.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
12884
12972
|
}
|
|
12885
12973
|
function PreviewBody({ file, kind, state }) {
|
|
12886
12974
|
if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
@@ -12925,13 +13013,13 @@ function PreviewBody({ file, kind, state }) {
|
|
|
12925
13013
|
] });
|
|
12926
13014
|
}
|
|
12927
13015
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
12928
|
-
const kind =
|
|
13016
|
+
const kind = React64.useMemo(() => previewKindOf(file), [file]);
|
|
12929
13017
|
const preview = usePreview(file, kind, resolveUrl);
|
|
12930
|
-
const [tab, setTab] =
|
|
12931
|
-
const [downloading, setDownloading] =
|
|
12932
|
-
const [downloadError, setDownloadError] =
|
|
13018
|
+
const [tab, setTab] = React64.useState("preview");
|
|
13019
|
+
const [downloading, setDownloading] = React64.useState(false);
|
|
13020
|
+
const [downloadError, setDownloadError] = React64.useState(null);
|
|
12933
13021
|
const hasSide = sidePanel != null;
|
|
12934
|
-
|
|
13022
|
+
React64.useEffect(() => {
|
|
12935
13023
|
setTab("preview");
|
|
12936
13024
|
}, [file.id]);
|
|
12937
13025
|
const download = () => {
|
|
@@ -12998,7 +13086,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
12998
13086
|
}
|
|
12999
13087
|
|
|
13000
13088
|
// src/components/files/FileBrowser.tsx
|
|
13001
|
-
var
|
|
13089
|
+
var React65 = __toESM(require("react"), 1);
|
|
13002
13090
|
var import_jsx_runtime94 = require("react/jsx-runtime");
|
|
13003
13091
|
function childrenOf(folders, parentId) {
|
|
13004
13092
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -13069,10 +13157,10 @@ function FolderPickerMenu({
|
|
|
13069
13157
|
destinations,
|
|
13070
13158
|
onPick
|
|
13071
13159
|
}) {
|
|
13072
|
-
const [open, setOpen] =
|
|
13160
|
+
const [open, setOpen] = React65.useState(false);
|
|
13073
13161
|
const zIndex = useOverlayLayer(open);
|
|
13074
|
-
const ref =
|
|
13075
|
-
|
|
13162
|
+
const ref = React65.useRef(null);
|
|
13163
|
+
React65.useEffect(() => {
|
|
13076
13164
|
if (!open) return;
|
|
13077
13165
|
const away = (e) => {
|
|
13078
13166
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -13124,8 +13212,8 @@ function FolderPickerMenu({
|
|
|
13124
13212
|
] });
|
|
13125
13213
|
}
|
|
13126
13214
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
13127
|
-
const [over, setOver] =
|
|
13128
|
-
const dragCounter =
|
|
13215
|
+
const [over, setOver] = React65.useState(false);
|
|
13216
|
+
const dragCounter = React65.useRef(0);
|
|
13129
13217
|
const dropHandlers = isDropTarget ? {
|
|
13130
13218
|
onDragEnter: (e) => {
|
|
13131
13219
|
if (!hasInternalPayload(e)) return;
|
|
@@ -13173,8 +13261,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
13173
13261
|
}
|
|
13174
13262
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
13175
13263
|
const kids = childrenOf(folders, folder.id);
|
|
13176
|
-
const [expanded, setExpanded] =
|
|
13177
|
-
|
|
13264
|
+
const [expanded, setExpanded] = React65.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
13265
|
+
React65.useEffect(() => {
|
|
13178
13266
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
13179
13267
|
}, [currentFolderId, folder.id, folders]);
|
|
13180
13268
|
const isCurrent = folder.id === currentFolderId;
|
|
@@ -13240,15 +13328,15 @@ function FileBrowser({
|
|
|
13240
13328
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
13241
13329
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
13242
13330
|
const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
|
|
13243
|
-
const [createOpen, setCreateOpen] =
|
|
13244
|
-
const [createName, setCreateName] =
|
|
13245
|
-
const [renameTarget, setRenameTarget] =
|
|
13246
|
-
const [renameValue, setRenameValue] =
|
|
13247
|
-
const [deleteTarget, setDeleteTarget] =
|
|
13248
|
-
const uploadInputRef =
|
|
13249
|
-
const crumbFolders =
|
|
13250
|
-
const subfolders =
|
|
13251
|
-
const currentFiles =
|
|
13331
|
+
const [createOpen, setCreateOpen] = React65.useState(false);
|
|
13332
|
+
const [createName, setCreateName] = React65.useState("");
|
|
13333
|
+
const [renameTarget, setRenameTarget] = React65.useState(null);
|
|
13334
|
+
const [renameValue, setRenameValue] = React65.useState("");
|
|
13335
|
+
const [deleteTarget, setDeleteTarget] = React65.useState(null);
|
|
13336
|
+
const uploadInputRef = React65.useRef(null);
|
|
13337
|
+
const crumbFolders = React65.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
13338
|
+
const subfolders = React65.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
13339
|
+
const currentFiles = React65.useMemo(
|
|
13252
13340
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
13253
13341
|
[files, currentFolderId]
|
|
13254
13342
|
);
|
|
@@ -13480,8 +13568,8 @@ function BreadcrumbCrumb({
|
|
|
13480
13568
|
isDropTarget,
|
|
13481
13569
|
onDropPayload
|
|
13482
13570
|
}) {
|
|
13483
|
-
const [over, setOver] =
|
|
13484
|
-
const dragCounter =
|
|
13571
|
+
const [over, setOver] = React65.useState(false);
|
|
13572
|
+
const dragCounter = React65.useRef(0);
|
|
13485
13573
|
const dropHandlers = isDropTarget ? {
|
|
13486
13574
|
onDragEnter: (e) => {
|
|
13487
13575
|
if (!hasInternalPayload(e)) return;
|
|
@@ -13510,7 +13598,7 @@ function BreadcrumbCrumb({
|
|
|
13510
13598
|
}
|
|
13511
13599
|
|
|
13512
13600
|
// src/kits/query.ts
|
|
13513
|
-
var
|
|
13601
|
+
var React66 = __toESM(require("react"), 1);
|
|
13514
13602
|
var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
|
|
13515
13603
|
var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
|
|
13516
13604
|
var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
|
|
@@ -13565,22 +13653,22 @@ function compare(a, b, dir) {
|
|
|
13565
13653
|
var API = null;
|
|
13566
13654
|
var PREFS = null;
|
|
13567
13655
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
13568
|
-
const [query, setQuery] =
|
|
13656
|
+
const [query, setQuery] = React66.useState(() => {
|
|
13569
13657
|
const store = PREFS || window.PlannerPrefs;
|
|
13570
13658
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
13571
13659
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
13572
13660
|
});
|
|
13573
|
-
const savePref =
|
|
13661
|
+
const savePref = React66.useCallback((patch2) => {
|
|
13574
13662
|
const store = PREFS || window.PlannerPrefs;
|
|
13575
13663
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
13576
13664
|
}, [prefsKey]);
|
|
13577
|
-
const [res, setRes] =
|
|
13578
|
-
const [loading, setLoading] =
|
|
13579
|
-
const seq2 =
|
|
13665
|
+
const [res, setRes] = React66.useState(null);
|
|
13666
|
+
const [loading, setLoading] = React66.useState(true);
|
|
13667
|
+
const seq2 = React66.useRef(0);
|
|
13580
13668
|
const depKey = (deps || []).join("|");
|
|
13581
13669
|
const paramKey = JSON.stringify(params || {});
|
|
13582
13670
|
const queryKey = JSON.stringify(query);
|
|
13583
|
-
|
|
13671
|
+
React66.useEffect(() => {
|
|
13584
13672
|
const id = ++seq2.current;
|
|
13585
13673
|
setLoading(true);
|
|
13586
13674
|
const t = setTimeout(() => {
|
|
@@ -13899,12 +13987,12 @@ function createVersionStore(initialState, options) {
|
|
|
13899
13987
|
}
|
|
13900
13988
|
|
|
13901
13989
|
// src/kits/documentTitle.ts
|
|
13902
|
-
var
|
|
13990
|
+
var React67 = __toESM(require("react"), 1);
|
|
13903
13991
|
function formatDocumentTitle(routeTitle, appName) {
|
|
13904
13992
|
return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
|
|
13905
13993
|
}
|
|
13906
13994
|
function useDocumentTitle(routeTitle, appName) {
|
|
13907
|
-
|
|
13995
|
+
React67.useEffect(() => {
|
|
13908
13996
|
if (typeof document === "undefined") return;
|
|
13909
13997
|
document.title = formatDocumentTitle(routeTitle, appName);
|
|
13910
13998
|
}, [routeTitle, appName]);
|