@flytedan/flytebot-design-system 0.32.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -6
- package/dist/index.cjs +502 -390
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -5
- package/dist/index.d.ts +23 -5
- package/dist/index.js +502 -390
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -2731,10 +2731,10 @@ function DataTable({
|
|
|
2731
2731
|
}
|
|
2732
2732
|
|
|
2733
2733
|
// src/components/data/FilterBar.tsx
|
|
2734
|
-
import * as
|
|
2734
|
+
import * as React25 from "react";
|
|
2735
2735
|
|
|
2736
2736
|
// src/components/forms/NumberInput.tsx
|
|
2737
|
-
import * as
|
|
2737
|
+
import * as React22 from "react";
|
|
2738
2738
|
|
|
2739
2739
|
// src/components/forms/field.tsx
|
|
2740
2740
|
import * as React20 from "react";
|
|
@@ -2755,6 +2755,16 @@ function useTriggerLabelling(label, id) {
|
|
|
2755
2755
|
return { fieldId, labelId, ariaLabelledBy: label ? labelId + " " + fieldId : void 0 };
|
|
2756
2756
|
}
|
|
2757
2757
|
|
|
2758
|
+
// src/components/useLatest.ts
|
|
2759
|
+
import * as React21 from "react";
|
|
2760
|
+
function useLatest(value) {
|
|
2761
|
+
const ref = React21.useRef(value);
|
|
2762
|
+
React21.useInsertionEffect(() => {
|
|
2763
|
+
ref.current = value;
|
|
2764
|
+
});
|
|
2765
|
+
return ref;
|
|
2766
|
+
}
|
|
2767
|
+
|
|
2758
2768
|
// src/components/forms/NumberInput.tsx
|
|
2759
2769
|
import { jsx as jsx42, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
2760
2770
|
var HOLD_DELAY_MS = 400;
|
|
@@ -2832,24 +2842,22 @@ function NumberInput({
|
|
|
2832
2842
|
const n = typeof v === "number" ? v : parseNumberText(v);
|
|
2833
2843
|
return n == null || Number.isNaN(n) ? null : n;
|
|
2834
2844
|
};
|
|
2835
|
-
const [text, setText] =
|
|
2836
|
-
const [editing, setEditing] =
|
|
2845
|
+
const [text, setText] = React22.useState(() => toText(value));
|
|
2846
|
+
const [editing, setEditing] = React22.useState(false);
|
|
2837
2847
|
const parsed = parseNumberText(text);
|
|
2838
2848
|
const invalidMessage = parsed == null ? null : Number.isNaN(parsed) ? "Enter a number" : integer && !Number.isInteger(parsed) ? "Enter a whole number" : parsed < lo ? "Must be \u2265 " + lo : parsed > hi ? "Must be \u2264 " + hi : null;
|
|
2839
2849
|
const valid = invalidMessage == null;
|
|
2840
|
-
const committedRef =
|
|
2841
|
-
const onChangeRef =
|
|
2842
|
-
|
|
2843
|
-
const
|
|
2844
|
-
|
|
2845
|
-
const focusedRef = React21.useRef(false);
|
|
2846
|
-
React21.useEffect(() => {
|
|
2850
|
+
const committedRef = React22.useRef(toNumber(value));
|
|
2851
|
+
const onChangeRef = useLatest(onChange);
|
|
2852
|
+
const onValidityChangeRef = useLatest(onValidityChange);
|
|
2853
|
+
const focusedRef = React22.useRef(false);
|
|
2854
|
+
React22.useEffect(() => {
|
|
2847
2855
|
committedRef.current = toNumber(value);
|
|
2848
2856
|
if (!focusedRef.current) setText(toText(value));
|
|
2849
2857
|
}, [value]);
|
|
2850
|
-
|
|
2858
|
+
React22.useLayoutEffect(() => {
|
|
2851
2859
|
onValidityChangeRef.current?.(valid);
|
|
2852
|
-
}, [valid]);
|
|
2860
|
+
}, [valid, onValidityChangeRef]);
|
|
2853
2861
|
const fire = (n) => {
|
|
2854
2862
|
committedRef.current = n ?? null;
|
|
2855
2863
|
onChangeRef.current?.({ target: { value: n } });
|
|
@@ -2862,9 +2870,8 @@ function NumberInput({
|
|
|
2862
2870
|
fire(next);
|
|
2863
2871
|
return true;
|
|
2864
2872
|
};
|
|
2865
|
-
const bumpRef =
|
|
2866
|
-
|
|
2867
|
-
const holdTimer = React21.useRef(null);
|
|
2873
|
+
const bumpRef = useLatest(bump);
|
|
2874
|
+
const holdTimer = React22.useRef(null);
|
|
2868
2875
|
const release = () => {
|
|
2869
2876
|
if (holdTimer.current) clearTimeout(holdTimer.current);
|
|
2870
2877
|
holdTimer.current = null;
|
|
@@ -2883,7 +2890,7 @@ function NumberInput({
|
|
|
2883
2890
|
};
|
|
2884
2891
|
holdTimer.current = setTimeout(tick, HOLD_DELAY_MS);
|
|
2885
2892
|
};
|
|
2886
|
-
|
|
2893
|
+
React22.useEffect(() => () => {
|
|
2887
2894
|
if (holdTimer.current) clearTimeout(holdTimer.current);
|
|
2888
2895
|
}, []);
|
|
2889
2896
|
const current2 = committedRef.current;
|
|
@@ -2977,7 +2984,8 @@ function NumberInput({
|
|
|
2977
2984
|
)
|
|
2978
2985
|
] })
|
|
2979
2986
|
] }),
|
|
2980
|
-
|
|
2987
|
+
/* @__PURE__ */ jsx42("span", { id: errorId, className: "fd-sr", role: "status", children: shownError ?? "" }),
|
|
2988
|
+
shownError ? /* @__PURE__ */ jsxs36("span", { className: "fd-field-error", "aria-hidden": "true", children: [
|
|
2981
2989
|
/* @__PURE__ */ jsx42("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
2982
2990
|
shownError
|
|
2983
2991
|
] }) : help ? /* @__PURE__ */ jsx42("span", { className: "fd-field-help", children: help }) : null
|
|
@@ -2985,7 +2993,7 @@ function NumberInput({
|
|
|
2985
2993
|
}
|
|
2986
2994
|
|
|
2987
2995
|
// src/components/forms/DatePicker.tsx
|
|
2988
|
-
import * as
|
|
2996
|
+
import * as React23 from "react";
|
|
2989
2997
|
import { jsx as jsx43, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
2990
2998
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
2991
2999
|
var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
@@ -3003,10 +3011,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3003
3011
|
const today = /* @__PURE__ */ new Date();
|
|
3004
3012
|
const sel = range ? value || {} : { start: value, end: value };
|
|
3005
3013
|
const anchor = parse(sel.start) || parse(initialMonth) || today;
|
|
3006
|
-
const [vy, setVy] =
|
|
3007
|
-
const [vm, setVm] =
|
|
3008
|
-
const [mode2, setMode] =
|
|
3009
|
-
const [hover, setHover] =
|
|
3014
|
+
const [vy, setVy] = React23.useState(anchor.getFullYear());
|
|
3015
|
+
const [vm, setVm] = React23.useState(anchor.getMonth());
|
|
3016
|
+
const [mode2, setMode] = React23.useState("days");
|
|
3017
|
+
const [hover, setHover] = React23.useState(null);
|
|
3010
3018
|
const s = parse(sel.start), e = parse(sel.end);
|
|
3011
3019
|
const hoverEnd = range && s && !e && hover ? parse(hover) : null;
|
|
3012
3020
|
const inRange = (d) => {
|
|
@@ -3122,9 +3130,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3122
3130
|
}
|
|
3123
3131
|
function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, ...rest }) {
|
|
3124
3132
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
3125
|
-
const [open, setOpen] =
|
|
3126
|
-
const rootRef =
|
|
3127
|
-
const boxRef =
|
|
3133
|
+
const [open, setOpen] = React23.useState(false);
|
|
3134
|
+
const rootRef = React23.useRef(null);
|
|
3135
|
+
const boxRef = React23.useRef(null);
|
|
3128
3136
|
const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
|
|
3129
3137
|
const toggle = () => {
|
|
3130
3138
|
if (!disabled) setOpen(!open);
|
|
@@ -3202,9 +3210,9 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
|
|
|
3202
3210
|
}
|
|
3203
3211
|
|
|
3204
3212
|
// src/components/forms/listbox.ts
|
|
3205
|
-
import * as
|
|
3213
|
+
import * as React24 from "react";
|
|
3206
3214
|
function useListboxNav({ count, onSelect }) {
|
|
3207
|
-
const [active, setActive] =
|
|
3215
|
+
const [active, setActive] = React24.useState(-1);
|
|
3208
3216
|
return {
|
|
3209
3217
|
active,
|
|
3210
3218
|
setActive,
|
|
@@ -3217,7 +3225,7 @@ function useListboxNav({ count, onSelect }) {
|
|
|
3217
3225
|
};
|
|
3218
3226
|
}
|
|
3219
3227
|
function useListboxScrollIntoView(active, listRef, enabled) {
|
|
3220
|
-
|
|
3228
|
+
React24.useEffect(() => {
|
|
3221
3229
|
if (!enabled || active < 0 || !listRef.current) return;
|
|
3222
3230
|
const list = listRef.current;
|
|
3223
3231
|
const el = list.querySelector('[data-i="' + active + '"]');
|
|
@@ -3404,42 +3412,40 @@ function MultiSelectPanel({
|
|
|
3404
3412
|
onClose
|
|
3405
3413
|
}) {
|
|
3406
3414
|
const allowedOps = operatorsFor(field);
|
|
3407
|
-
const [draftOperator, setDraftOperator] =
|
|
3415
|
+
const [draftOperator, setDraftOperator] = React25.useState(value?.operator ?? allowedOps[0]);
|
|
3408
3416
|
const operator = allowedOps.length === 1 ? allowedOps[0] : value?.operator ?? draftOperator;
|
|
3409
3417
|
const selected = value?.values ?? [];
|
|
3410
|
-
const selectedRef =
|
|
3411
|
-
|
|
3412
|
-
const
|
|
3413
|
-
|
|
3414
|
-
const mountedRef = React24.useRef(true);
|
|
3415
|
-
React24.useEffect(() => {
|
|
3418
|
+
const selectedRef = useLatest(selected);
|
|
3419
|
+
const operatorRef = useLatest(operator);
|
|
3420
|
+
const mountedRef = React25.useRef(true);
|
|
3421
|
+
React25.useEffect(() => {
|
|
3416
3422
|
mountedRef.current = true;
|
|
3417
3423
|
return () => {
|
|
3418
3424
|
mountedRef.current = false;
|
|
3419
3425
|
};
|
|
3420
3426
|
}, []);
|
|
3421
|
-
const commit = (nextValues, nextOperator =
|
|
3422
|
-
|
|
3427
|
+
const commit = (nextValues, nextOperator = operatorRef.current) => {
|
|
3428
|
+
setDraftOperator(nextOperator);
|
|
3429
|
+
return onCommit({ operator: nextOperator, values: nextValues });
|
|
3423
3430
|
};
|
|
3424
3431
|
const setOperator = (op) => {
|
|
3425
|
-
setDraftOperator(op);
|
|
3426
3432
|
if (selectedRef.current.length > 0) commit(selectedRef.current, op);
|
|
3433
|
+
else setDraftOperator(op);
|
|
3427
3434
|
};
|
|
3428
|
-
const [mode2, setMode] =
|
|
3429
|
-
const [query, setQuery] =
|
|
3430
|
-
const [asyncState, setAsyncState] =
|
|
3435
|
+
const [mode2, setMode] = React25.useState("search");
|
|
3436
|
+
const [query, setQuery] = React25.useState("");
|
|
3437
|
+
const [asyncState, setAsyncState] = React25.useState(
|
|
3431
3438
|
{ options: null, loading: !!field.loadOptions, error: false }
|
|
3432
3439
|
);
|
|
3433
|
-
const [retryTick, setRetryTick] =
|
|
3434
|
-
const inputRef =
|
|
3435
|
-
const listRef =
|
|
3436
|
-
const listId =
|
|
3437
|
-
const loadOptionsRef =
|
|
3438
|
-
|
|
3439
|
-
React24.useEffect(() => {
|
|
3440
|
+
const [retryTick, setRetryTick] = React25.useState(0);
|
|
3441
|
+
const inputRef = React25.useRef(null);
|
|
3442
|
+
const listRef = React25.useRef(null);
|
|
3443
|
+
const listId = React25.useId();
|
|
3444
|
+
const loadOptionsRef = useLatest(field.loadOptions);
|
|
3445
|
+
React25.useEffect(() => {
|
|
3440
3446
|
inputRef.current?.focus();
|
|
3441
3447
|
}, []);
|
|
3442
|
-
|
|
3448
|
+
React25.useEffect(() => {
|
|
3443
3449
|
const load = loadOptionsRef.current;
|
|
3444
3450
|
if (!load) return;
|
|
3445
3451
|
const controller = new AbortController();
|
|
@@ -3457,7 +3463,7 @@ function MultiSelectPanel({
|
|
|
3457
3463
|
clearTimeout(t);
|
|
3458
3464
|
controller.abort();
|
|
3459
3465
|
};
|
|
3460
|
-
}, [query, retryTick]);
|
|
3466
|
+
}, [query, retryTick, loadOptionsRef]);
|
|
3461
3467
|
const options = field.loadOptions ? asyncState.options ?? [] : (field.options ?? []).filter((o) => o.label.toLowerCase().includes(query.toLowerCase()));
|
|
3462
3468
|
const showLoading = !!field.loadOptions && asyncState.loading;
|
|
3463
3469
|
const showError = !!field.loadOptions && asyncState.error;
|
|
@@ -3472,17 +3478,17 @@ function MultiSelectPanel({
|
|
|
3472
3478
|
};
|
|
3473
3479
|
const nav = useListboxNav({ count: options.length, onSelect: (i) => toggle(options[i]) });
|
|
3474
3480
|
useListboxScrollIntoView(nav.active, listRef, hasListbox);
|
|
3475
|
-
|
|
3481
|
+
React25.useEffect(() => {
|
|
3476
3482
|
nav.setActive(0);
|
|
3477
3483
|
}, [query, options.length]);
|
|
3478
3484
|
const activeId = hasListbox && options[nav.active] ? listId + "-opt-" + nav.active : void 0;
|
|
3479
3485
|
const liveMessage = showLoading ? "Loading\u2026" : showError ? "Couldn't load options." : options.length === 0 ? "No matches" : atLimit ? "Limit reached: at most " + field.maxValues + " values" : "";
|
|
3480
|
-
const [pasteText, setPasteText] =
|
|
3481
|
-
const [pasteLoading, setPasteLoading] =
|
|
3482
|
-
const [unmatchedTokens, setUnmatchedTokens] =
|
|
3483
|
-
const [pasteError, setPasteError] =
|
|
3484
|
-
const pasteWrapRef =
|
|
3485
|
-
|
|
3486
|
+
const [pasteText, setPasteText] = React25.useState("");
|
|
3487
|
+
const [pasteLoading, setPasteLoading] = React25.useState(false);
|
|
3488
|
+
const [unmatchedTokens, setUnmatchedTokens] = React25.useState([]);
|
|
3489
|
+
const [pasteError, setPasteError] = React25.useState(null);
|
|
3490
|
+
const pasteWrapRef = React25.useRef(null);
|
|
3491
|
+
React25.useEffect(() => {
|
|
3486
3492
|
if (mode2 === "paste") pasteWrapRef.current?.querySelector("textarea")?.focus();
|
|
3487
3493
|
}, [mode2]);
|
|
3488
3494
|
const doResolve = () => {
|
|
@@ -3501,7 +3507,11 @@ function MultiSelectPanel({
|
|
|
3501
3507
|
setPasteError("This filter allows at most " + field.maxValues + " values; adding this list would make " + merged.size + ".");
|
|
3502
3508
|
return;
|
|
3503
3509
|
}
|
|
3504
|
-
commit(Array.from(merged.values())
|
|
3510
|
+
const applied = commit(Array.from(merged.values()));
|
|
3511
|
+
if (!applied.ok) {
|
|
3512
|
+
setPasteError(applied.reason);
|
|
3513
|
+
return;
|
|
3514
|
+
}
|
|
3505
3515
|
setPasteText("");
|
|
3506
3516
|
}, (err) => {
|
|
3507
3517
|
if (!mountedRef.current) return;
|
|
@@ -3638,6 +3648,59 @@ function MultiSelectPanel({
|
|
|
3638
3648
|
}
|
|
3639
3649
|
);
|
|
3640
3650
|
}
|
|
3651
|
+
function useTextValidity(onFlip) {
|
|
3652
|
+
const invalidRef = React25.useRef(/* @__PURE__ */ new Set());
|
|
3653
|
+
const [, rerender] = React25.useReducer((n) => n + 1, 0);
|
|
3654
|
+
const onFlipRef = useLatest(onFlip);
|
|
3655
|
+
const record = (name, valid) => {
|
|
3656
|
+
const invalid = invalidRef.current;
|
|
3657
|
+
if (valid !== invalid.has(name)) return false;
|
|
3658
|
+
if (valid) invalid.delete(name);
|
|
3659
|
+
else invalid.add(name);
|
|
3660
|
+
rerender();
|
|
3661
|
+
return true;
|
|
3662
|
+
};
|
|
3663
|
+
return {
|
|
3664
|
+
allValid: () => invalidRef.current.size === 0,
|
|
3665
|
+
report: (name) => (valid) => {
|
|
3666
|
+
if (record(name, valid)) onFlipRef.current();
|
|
3667
|
+
},
|
|
3668
|
+
/** For an input that is about to unmount: it has nothing left to show. */
|
|
3669
|
+
forget: (name) => {
|
|
3670
|
+
record(name, true);
|
|
3671
|
+
},
|
|
3672
|
+
/** For a panel that is about to remount every input: each reports afresh on mount. */
|
|
3673
|
+
reset: () => {
|
|
3674
|
+
if (invalidRef.current.size === 0) return;
|
|
3675
|
+
invalidRef.current.clear();
|
|
3676
|
+
rerender();
|
|
3677
|
+
}
|
|
3678
|
+
};
|
|
3679
|
+
}
|
|
3680
|
+
function applicable(field, candidate, textValid) {
|
|
3681
|
+
if (!textValid || candidate === void 0) return void 0;
|
|
3682
|
+
return validateFilterValue(field, candidate).ok ? candidate : void 0;
|
|
3683
|
+
}
|
|
3684
|
+
function sameValue(a, b) {
|
|
3685
|
+
if (a === b) return true;
|
|
3686
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
|
|
3687
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
3688
|
+
const left = a;
|
|
3689
|
+
const right = b;
|
|
3690
|
+
for (const key of /* @__PURE__ */ new Set([...Object.keys(left), ...Object.keys(right)])) {
|
|
3691
|
+
if (!sameValue(left[key], right[key])) return false;
|
|
3692
|
+
}
|
|
3693
|
+
return true;
|
|
3694
|
+
}
|
|
3695
|
+
function useReseedFromProps(value, applies, reseed) {
|
|
3696
|
+
const seen = React25.useRef(value);
|
|
3697
|
+
React25.useLayoutEffect(() => {
|
|
3698
|
+
if (seen.current === value) return;
|
|
3699
|
+
seen.current = value;
|
|
3700
|
+
if (!sameValue(value, applies())) reseed(value);
|
|
3701
|
+
}, [value, applies, reseed]);
|
|
3702
|
+
}
|
|
3703
|
+
var rangeDraft = (value) => ({ min: value?.min, max: value?.max });
|
|
3641
3704
|
function RangePanel({
|
|
3642
3705
|
field,
|
|
3643
3706
|
value,
|
|
@@ -3645,21 +3708,34 @@ function RangePanel({
|
|
|
3645
3708
|
onCommit,
|
|
3646
3709
|
onClose
|
|
3647
3710
|
}) {
|
|
3648
|
-
const [draft, setDraft] =
|
|
3649
|
-
const
|
|
3650
|
-
const
|
|
3651
|
-
const
|
|
3711
|
+
const [draft, setDraft] = React25.useState(() => rangeDraft(value));
|
|
3712
|
+
const [seed, setSeed] = React25.useState(0);
|
|
3713
|
+
const draftRef = React25.useRef(draft);
|
|
3714
|
+
const shown = () => {
|
|
3715
|
+
const { min, max } = draftRef.current;
|
|
3716
|
+
return applicable(field, min == null && max == null ? void 0 : { min, max }, validity.allValid());
|
|
3717
|
+
};
|
|
3718
|
+
const publish = () => {
|
|
3719
|
+
onCommit(shown());
|
|
3720
|
+
};
|
|
3721
|
+
const validity = useTextValidity(publish);
|
|
3722
|
+
useReseedFromProps(value, shown, (next) => {
|
|
3723
|
+
draftRef.current = rangeDraft(next);
|
|
3724
|
+
setDraft(draftRef.current);
|
|
3725
|
+
validity.reset();
|
|
3726
|
+
setSeed((n) => n + 1);
|
|
3727
|
+
});
|
|
3652
3728
|
const draftMin = draft.min;
|
|
3653
3729
|
const draftMax = draft.max;
|
|
3654
3730
|
const isEmpty = draftMin == null && draftMax == null;
|
|
3655
3731
|
const validation = isEmpty ? { ok: true } : validateFilterValue(field, { min: draftMin, max: draftMax });
|
|
3656
3732
|
const comboError = !isEmpty && !validation.ok ? validation.reason : void 0;
|
|
3657
|
-
const doneDisabled = !
|
|
3733
|
+
const doneDisabled = !validity.allValid() || !!comboError;
|
|
3658
3734
|
const apply = (patch) => {
|
|
3659
3735
|
const next = { ...draftRef.current, ...patch };
|
|
3660
3736
|
draftRef.current = next;
|
|
3661
3737
|
setDraft(next);
|
|
3662
|
-
|
|
3738
|
+
publish();
|
|
3663
3739
|
};
|
|
3664
3740
|
return /* @__PURE__ */ jsx45(
|
|
3665
3741
|
Popover,
|
|
@@ -3684,8 +3760,9 @@ function RangePanel({
|
|
|
3684
3760
|
integer: field.integer,
|
|
3685
3761
|
placeholder: field.minPlaceholder,
|
|
3686
3762
|
onChange: (e) => apply({ min: e.target.value }),
|
|
3687
|
-
onValidityChange:
|
|
3688
|
-
}
|
|
3763
|
+
onValidityChange: validity.report("min")
|
|
3764
|
+
},
|
|
3765
|
+
"min-" + seed
|
|
3689
3766
|
),
|
|
3690
3767
|
/* @__PURE__ */ jsx45(
|
|
3691
3768
|
NumberInput,
|
|
@@ -3699,13 +3776,21 @@ function RangePanel({
|
|
|
3699
3776
|
error: comboError,
|
|
3700
3777
|
placeholder: field.maxPlaceholder,
|
|
3701
3778
|
onChange: (e) => apply({ max: e.target.value }),
|
|
3702
|
-
onValidityChange:
|
|
3703
|
-
}
|
|
3779
|
+
onValidityChange: validity.report("max")
|
|
3780
|
+
},
|
|
3781
|
+
"max-" + seed
|
|
3704
3782
|
)
|
|
3705
3783
|
] })
|
|
3706
3784
|
}
|
|
3707
3785
|
);
|
|
3708
3786
|
}
|
|
3787
|
+
function dateDraft(field, value) {
|
|
3788
|
+
return {
|
|
3789
|
+
kind: value?.kind ?? "withinDays",
|
|
3790
|
+
days: value?.kind === "withinDays" ? value.days : field.defaultDays ?? 30,
|
|
3791
|
+
between: value?.kind === "between" ? { from: value.from, to: value.to } : { from: "", to: "" }
|
|
3792
|
+
};
|
|
3793
|
+
}
|
|
3709
3794
|
function DatePanel({
|
|
3710
3795
|
field,
|
|
3711
3796
|
value,
|
|
@@ -3713,36 +3798,69 @@ function DatePanel({
|
|
|
3713
3798
|
onCommit,
|
|
3714
3799
|
onClose
|
|
3715
3800
|
}) {
|
|
3716
|
-
const defaultDays = field.defaultDays ?? 30;
|
|
3717
3801
|
const maxDays = effectiveMaxDays(field);
|
|
3718
|
-
const [
|
|
3719
|
-
const [kind, setKind] =
|
|
3720
|
-
const [daysDraft, setDaysDraft] =
|
|
3721
|
-
|
|
3722
|
-
);
|
|
3723
|
-
const [between, setBetween] =
|
|
3724
|
-
|
|
3725
|
-
)
|
|
3802
|
+
const [initial] = React25.useState(() => dateDraft(field, value));
|
|
3803
|
+
const [kind, setKind] = React25.useState(initial.kind);
|
|
3804
|
+
const [daysDraft, setDaysDraft] = React25.useState(initial.days);
|
|
3805
|
+
const daysRef = React25.useRef(daysDraft);
|
|
3806
|
+
const daysConfirmed = React25.useRef(value?.kind === "withinDays");
|
|
3807
|
+
const [between, setBetween] = React25.useState(initial.between);
|
|
3808
|
+
const [seed, setSeed] = React25.useState(0);
|
|
3809
|
+
const shownWithinDays = () => {
|
|
3810
|
+
const days = daysRef.current;
|
|
3811
|
+
return applicable(field, days == null ? void 0 : { kind: "withinDays", days }, validity.allValid());
|
|
3812
|
+
};
|
|
3813
|
+
const validity = useTextValidity(() => {
|
|
3814
|
+
daysConfirmed.current = true;
|
|
3815
|
+
onCommit(shownWithinDays());
|
|
3816
|
+
});
|
|
3817
|
+
const applies = () => {
|
|
3818
|
+
if (kind === "between") {
|
|
3819
|
+
return applicable(field, between.from && between.to ? { kind: "between", ...between } : void 0, true);
|
|
3820
|
+
}
|
|
3821
|
+
return daysConfirmed.current ? shownWithinDays() : void 0;
|
|
3822
|
+
};
|
|
3823
|
+
useReseedFromProps(value, applies, (next) => {
|
|
3824
|
+
const d = dateDraft(field, next);
|
|
3825
|
+
setKind(d.kind);
|
|
3826
|
+
daysRef.current = d.days;
|
|
3827
|
+
daysConfirmed.current = next?.kind === "withinDays";
|
|
3828
|
+
setDaysDraft(d.days);
|
|
3829
|
+
setBetween(d.between);
|
|
3830
|
+
validity.reset();
|
|
3831
|
+
setSeed((n) => n + 1);
|
|
3832
|
+
});
|
|
3726
3833
|
const applyWithinDays = (days) => {
|
|
3834
|
+
daysRef.current = days;
|
|
3835
|
+
daysConfirmed.current = true;
|
|
3727
3836
|
setDaysDraft(days);
|
|
3728
|
-
onCommit(
|
|
3837
|
+
onCommit(shownWithinDays());
|
|
3729
3838
|
};
|
|
3730
3839
|
const applyBetween = (from, to) => {
|
|
3731
3840
|
setBetween({ from, to });
|
|
3732
|
-
onCommit(from && to ? { kind: "between", from, to } : void 0);
|
|
3841
|
+
onCommit(applicable(field, from && to ? { kind: "between", from, to } : void 0, true));
|
|
3733
3842
|
};
|
|
3734
3843
|
const switchKind = (next) => {
|
|
3735
3844
|
if (next === kind) return;
|
|
3736
3845
|
setKind(next);
|
|
3737
|
-
if (next === "between")
|
|
3738
|
-
|
|
3739
|
-
|
|
3846
|
+
if (next === "between") {
|
|
3847
|
+
setBetween({ from: "", to: "" });
|
|
3848
|
+
validity.forget("days");
|
|
3849
|
+
} else {
|
|
3850
|
+
const { days } = dateDraft(field, void 0);
|
|
3851
|
+
daysRef.current = days;
|
|
3852
|
+
daysConfirmed.current = false;
|
|
3853
|
+
setDaysDraft(days);
|
|
3854
|
+
}
|
|
3740
3855
|
onCommit(void 0);
|
|
3741
3856
|
};
|
|
3742
|
-
const doneDisabled = kind === "withinDays" && !
|
|
3857
|
+
const doneDisabled = kind === "withinDays" && !validity.allValid();
|
|
3743
3858
|
const confirm = () => {
|
|
3744
3859
|
if (doneDisabled) return;
|
|
3745
|
-
if (kind === "withinDays"
|
|
3860
|
+
if (kind === "withinDays") {
|
|
3861
|
+
const shown = shownWithinDays();
|
|
3862
|
+
if (shown) onCommit(shown);
|
|
3863
|
+
}
|
|
3746
3864
|
onClose();
|
|
3747
3865
|
};
|
|
3748
3866
|
return /* @__PURE__ */ jsx45(
|
|
@@ -3779,8 +3897,9 @@ function DatePanel({
|
|
|
3779
3897
|
integer: true,
|
|
3780
3898
|
value: daysDraft ?? "",
|
|
3781
3899
|
onChange: (e) => applyWithinDays(e.target.value),
|
|
3782
|
-
onValidityChange:
|
|
3783
|
-
}
|
|
3900
|
+
onValidityChange: validity.report("days")
|
|
3901
|
+
},
|
|
3902
|
+
"days-" + seed
|
|
3784
3903
|
) : /* @__PURE__ */ jsx45(
|
|
3785
3904
|
DatePicker,
|
|
3786
3905
|
{
|
|
@@ -3788,23 +3907,23 @@ function DatePanel({
|
|
|
3788
3907
|
label: "Date range",
|
|
3789
3908
|
value: { start: between.from, end: between.to },
|
|
3790
3909
|
onChange: (e) => applyBetween(e.target.value.start || "", e.target.value.end || "")
|
|
3791
|
-
}
|
|
3910
|
+
},
|
|
3911
|
+
"between-" + seed
|
|
3792
3912
|
)
|
|
3793
3913
|
] })
|
|
3794
3914
|
}
|
|
3795
3915
|
);
|
|
3796
3916
|
}
|
|
3797
3917
|
function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align = "left", className = "", ...rest }) {
|
|
3798
|
-
const [panel, setPanel] =
|
|
3799
|
-
const editAnchorRef =
|
|
3800
|
-
const addAnchorRef =
|
|
3801
|
-
const textInputRef =
|
|
3802
|
-
const optionsRef =
|
|
3918
|
+
const [panel, setPanel] = React25.useState(null);
|
|
3919
|
+
const editAnchorRef = React25.useRef(null);
|
|
3920
|
+
const addAnchorRef = React25.useRef(null);
|
|
3921
|
+
const textInputRef = React25.useRef(null);
|
|
3922
|
+
const optionsRef = React25.useRef(null);
|
|
3803
3923
|
if (process.env.NODE_ENV !== "production") {
|
|
3804
3924
|
for (const f of fields) assertValidFieldDefinition(f);
|
|
3805
3925
|
}
|
|
3806
|
-
const latest =
|
|
3807
|
-
latest.current = { fields, filters, onFilterChange, onFilterRemove };
|
|
3926
|
+
const latest = useLatest({ fields, filters, onFilterChange, onFilterRemove });
|
|
3808
3927
|
const commit = (field, candidate) => {
|
|
3809
3928
|
const current2 = latest.current.fields.find((f) => f.key === field.key);
|
|
3810
3929
|
if (!current2) return { ok: false, reason: "This filter is no longer available" };
|
|
@@ -3813,24 +3932,17 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
3813
3932
|
return { ok: true };
|
|
3814
3933
|
}
|
|
3815
3934
|
const result = validateFilterValue(current2, candidate);
|
|
3816
|
-
if (result.ok)
|
|
3817
|
-
latest.current.filters = { ...latest.current.filters, [current2.key]: candidate };
|
|
3818
|
-
latest.current.onFilterChange(current2.key, candidate);
|
|
3819
|
-
}
|
|
3935
|
+
if (result.ok) latest.current.onFilterChange(current2.key, candidate);
|
|
3820
3936
|
return result;
|
|
3821
3937
|
};
|
|
3822
3938
|
const removeField = (field) => {
|
|
3823
3939
|
const { filters: now, onFilterRemove: remove } = latest.current;
|
|
3824
|
-
if (
|
|
3825
|
-
const next = { ...now };
|
|
3826
|
-
delete next[field.key];
|
|
3827
|
-
latest.current.filters = next;
|
|
3828
|
-
remove(field.key);
|
|
3940
|
+
if (isFieldSet(field, now[field.key])) remove(field.key);
|
|
3829
3941
|
};
|
|
3830
3942
|
const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
|
|
3831
3943
|
const startEditing = (key) => setPanel({ kind: "edit", key });
|
|
3832
3944
|
const closeEditing = () => setPanel(null);
|
|
3833
|
-
|
|
3945
|
+
React25.useEffect(() => {
|
|
3834
3946
|
if (!panel || panel.kind !== "edit") return;
|
|
3835
3947
|
if (editingField?.type === "text") {
|
|
3836
3948
|
textInputRef.current?.focus();
|
|
@@ -4036,7 +4148,7 @@ function StatTile({ label, value, sub, delta, invert = false, loading = false, c
|
|
|
4036
4148
|
}
|
|
4037
4149
|
|
|
4038
4150
|
// src/components/data/CodeBlock.tsx
|
|
4039
|
-
import * as
|
|
4151
|
+
import * as React26 from "react";
|
|
4040
4152
|
import { Fragment as Fragment6, jsx as jsx47, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
4041
4153
|
var JS_KW = /^(?:const|let|var|function|return|if|else|for|while|do|new|class|extends|import|from|export|default|await|async|try|catch|finally|throw|typeof|instanceof|of|in|switch|case|break|continue|delete|void|yield|static|get|set|this|super|interface|type|enum|implements|public|private|protected|readonly|abstract|as|satisfies|declare|namespace)$/;
|
|
4042
4154
|
var RULES = {
|
|
@@ -4192,13 +4304,13 @@ function tokenize(src, lang) {
|
|
|
4192
4304
|
return out;
|
|
4193
4305
|
}
|
|
4194
4306
|
function Highlighted({ code, lang }) {
|
|
4195
|
-
const toks =
|
|
4307
|
+
const toks = React26.useMemo(() => tokenize(code, lang), [code, lang]);
|
|
4196
4308
|
return /* @__PURE__ */ jsx47(Fragment6, { children: toks.map((tk, i) => tk.c ? /* @__PURE__ */ jsx47("span", { className: "tok-" + tk.c, children: tk.t }, i) : tk.t) });
|
|
4197
4309
|
}
|
|
4198
4310
|
function useCopy() {
|
|
4199
|
-
const [done, setDone] =
|
|
4200
|
-
const timer =
|
|
4201
|
-
|
|
4311
|
+
const [done, setDone] = React26.useState(false);
|
|
4312
|
+
const timer = React26.useRef(null);
|
|
4313
|
+
React26.useEffect(() => () => {
|
|
4202
4314
|
if (timer.current) clearTimeout(timer.current);
|
|
4203
4315
|
}, []);
|
|
4204
4316
|
const copy = (text) => {
|
|
@@ -4234,8 +4346,8 @@ function CodeBlock({
|
|
|
4234
4346
|
actions,
|
|
4235
4347
|
className = ""
|
|
4236
4348
|
}) {
|
|
4237
|
-
const [wrap, setWrap] =
|
|
4238
|
-
const [open, setOpen] =
|
|
4349
|
+
const [wrap, setWrap] = React26.useState(!!wrapDefault);
|
|
4350
|
+
const [open, setOpen] = React26.useState(false);
|
|
4239
4351
|
const [copied, copy] = useCopy();
|
|
4240
4352
|
const body = String(code).replace(/\n$/, "");
|
|
4241
4353
|
const lines = body.split("\n");
|
|
@@ -4264,7 +4376,7 @@ function CodeBlock({
|
|
|
4264
4376
|
] });
|
|
4265
4377
|
}
|
|
4266
4378
|
function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
|
|
4267
|
-
const [open, setOpen] =
|
|
4379
|
+
const [open, setOpen] = React26.useState(false);
|
|
4268
4380
|
const [copied, copy] = useCopy();
|
|
4269
4381
|
const raw = String(diff).replace(/\n$/, "");
|
|
4270
4382
|
const all = raw.split("\n").map((line) => {
|
|
@@ -4310,7 +4422,7 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
|
|
|
4310
4422
|
}
|
|
4311
4423
|
|
|
4312
4424
|
// src/components/data/Markdown.tsx
|
|
4313
|
-
import * as
|
|
4425
|
+
import * as React27 from "react";
|
|
4314
4426
|
import { jsx as jsx48, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
4315
4427
|
var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
|
|
4316
4428
|
var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
|
|
@@ -4349,7 +4461,7 @@ function inlineNodes(src, ctx, keyBase) {
|
|
|
4349
4461
|
const href = safeHref(g(2));
|
|
4350
4462
|
out.push(href ? /* @__PURE__ */ jsx48("a", { href, title: g(3) || void 0, target: /^https?:/i.test(href) ? "_blank" : void 0, rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: inlineNodes(g(1), ctx, key()) }, key()) : /* @__PURE__ */ jsx48("span", { children: g(1) }, key()));
|
|
4351
4463
|
} else if (kind === "cite") {
|
|
4352
|
-
out.push(ctx.renderCitation ? /* @__PURE__ */ jsx48(
|
|
4464
|
+
out.push(ctx.renderCitation ? /* @__PURE__ */ jsx48(React27.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ jsx48("sup", { className: "fd-md-cite", children: g(1) }, key()));
|
|
4353
4465
|
} else if (kind === "strongem") out.push(/* @__PURE__ */ jsx48("strong", { children: /* @__PURE__ */ jsx48("em", { children: inlineNodes(g(1), ctx, key()) }) }, key()));
|
|
4354
4466
|
else if (kind === "strong") out.push(/* @__PURE__ */ jsx48("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
4355
4467
|
else if (kind === "em") out.push(/* @__PURE__ */ jsx48("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
@@ -4514,7 +4626,7 @@ function Markdown({
|
|
|
4514
4626
|
onLinkClick
|
|
4515
4627
|
}) {
|
|
4516
4628
|
const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
|
|
4517
|
-
const blocks =
|
|
4629
|
+
const blocks = React27.useMemo(() => parseBlocks(source), [source]);
|
|
4518
4630
|
return /* @__PURE__ */ jsx48("div", { className: ["fd-md", className].filter(Boolean).join(" "), children: renderBlocks(blocks, ctx, "b") });
|
|
4519
4631
|
}
|
|
4520
4632
|
function MarkdownInline({ source = "", className = "", onLinkClick }) {
|
|
@@ -4628,7 +4740,7 @@ function Pagination({
|
|
|
4628
4740
|
}
|
|
4629
4741
|
|
|
4630
4742
|
// src/components/data/RelativeTime.tsx
|
|
4631
|
-
import * as
|
|
4743
|
+
import * as React28 from "react";
|
|
4632
4744
|
import { jsxs as jsxs45 } from "react/jsx-runtime";
|
|
4633
4745
|
var MIN = 6e4;
|
|
4634
4746
|
var HOUR = 36e5;
|
|
@@ -4680,9 +4792,9 @@ function formatDuration(ms) {
|
|
|
4680
4792
|
return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
|
|
4681
4793
|
}
|
|
4682
4794
|
function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
|
|
4683
|
-
const [, force] =
|
|
4795
|
+
const [, force] = React28.useState(0);
|
|
4684
4796
|
const t = value instanceof Date ? value.getTime() : Date.parse(value);
|
|
4685
|
-
|
|
4797
|
+
React28.useEffect(() => {
|
|
4686
4798
|
if (!refresh2 || !t || isNaN(t)) return;
|
|
4687
4799
|
const abs = Math.abs(t - Date.now());
|
|
4688
4800
|
if (abs > DAY) return;
|
|
@@ -4698,7 +4810,7 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
|
|
|
4698
4810
|
}
|
|
4699
4811
|
|
|
4700
4812
|
// src/components/data/ScoreMeter.tsx
|
|
4701
|
-
import * as
|
|
4813
|
+
import * as React29 from "react";
|
|
4702
4814
|
import { jsx as jsx51, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
4703
4815
|
function ScoreMeter({
|
|
4704
4816
|
score,
|
|
@@ -4713,10 +4825,10 @@ function ScoreMeter({
|
|
|
4713
4825
|
breakdownWidth = 280,
|
|
4714
4826
|
className = ""
|
|
4715
4827
|
}) {
|
|
4716
|
-
const [open, setOpen] =
|
|
4717
|
-
const ref =
|
|
4828
|
+
const [open, setOpen] = React29.useState(false);
|
|
4829
|
+
const ref = React29.useRef(null);
|
|
4718
4830
|
const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
|
|
4719
|
-
const body = /* @__PURE__ */ jsxs46(
|
|
4831
|
+
const body = /* @__PURE__ */ jsxs46(React29.Fragment, { children: [
|
|
4720
4832
|
/* @__PURE__ */ jsx51("span", { className: "fd-scoremeter-rail", style: { width }, "aria-hidden": "true", children: /* @__PURE__ */ jsx51(SegmentedMeter, { total: 100, segments, height, showTotal: false, showPercent: false, legend: false }) }),
|
|
4721
4833
|
showScore ? /* @__PURE__ */ jsx51("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
|
|
4722
4834
|
] });
|
|
@@ -4735,7 +4847,7 @@ function ScoreMeter({
|
|
|
4735
4847
|
}
|
|
4736
4848
|
);
|
|
4737
4849
|
}
|
|
4738
|
-
return /* @__PURE__ */ jsxs46(
|
|
4850
|
+
return /* @__PURE__ */ jsxs46(React29.Fragment, { children: [
|
|
4739
4851
|
/* @__PURE__ */ jsx51(
|
|
4740
4852
|
"button",
|
|
4741
4853
|
{
|
|
@@ -4766,13 +4878,13 @@ function ScoreMeter({
|
|
|
4766
4878
|
}
|
|
4767
4879
|
|
|
4768
4880
|
// src/components/data/SortMenu.tsx
|
|
4769
|
-
import * as
|
|
4881
|
+
import * as React30 from "react";
|
|
4770
4882
|
import { jsx as jsx52, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
4771
4883
|
function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", className = "", ...rest }) {
|
|
4772
|
-
const [open, setOpen] =
|
|
4884
|
+
const [open, setOpen] = React30.useState(false);
|
|
4773
4885
|
const zIndex = useOverlayLayer(open);
|
|
4774
|
-
const ref =
|
|
4775
|
-
|
|
4886
|
+
const ref = React30.useRef(null);
|
|
4887
|
+
React30.useEffect(() => {
|
|
4776
4888
|
if (!open) return;
|
|
4777
4889
|
const away = (e) => {
|
|
4778
4890
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -4834,7 +4946,7 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
|
|
|
4834
4946
|
}
|
|
4835
4947
|
|
|
4836
4948
|
// src/components/data/StepList.tsx
|
|
4837
|
-
import * as
|
|
4949
|
+
import * as React31 from "react";
|
|
4838
4950
|
import { jsx as jsx53, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
4839
4951
|
var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
|
|
4840
4952
|
function StepList({
|
|
@@ -4847,9 +4959,9 @@ function StepList({
|
|
|
4847
4959
|
dense = false,
|
|
4848
4960
|
className = ""
|
|
4849
4961
|
}) {
|
|
4850
|
-
const [openState, setOpenState] =
|
|
4962
|
+
const [openState, setOpenState] = React31.useState(defaultOpen);
|
|
4851
4963
|
const open = openProp == null ? openState : openProp;
|
|
4852
|
-
const [expanded, setExpanded] =
|
|
4964
|
+
const [expanded, setExpanded] = React31.useState({});
|
|
4853
4965
|
if (!steps.length) return null;
|
|
4854
4966
|
const running = steps.some((s) => s.status === "running");
|
|
4855
4967
|
const failed = steps.filter((s) => s.status === "error").length;
|
|
@@ -4907,7 +5019,7 @@ function StepList({
|
|
|
4907
5019
|
}
|
|
4908
5020
|
|
|
4909
5021
|
// src/components/data/VirtualList.tsx
|
|
4910
|
-
import * as
|
|
5022
|
+
import * as React32 from "react";
|
|
4911
5023
|
import { jsx as jsx54, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
4912
5024
|
var VIRTUAL_LIST_BUFFER_ROWS = 20;
|
|
4913
5025
|
var VIRTUAL_LIST_ROW_GAP = 6;
|
|
@@ -4959,35 +5071,35 @@ function VirtualList({
|
|
|
4959
5071
|
className = "",
|
|
4960
5072
|
style
|
|
4961
5073
|
}) {
|
|
4962
|
-
const [scrollTop, setScrollTop] =
|
|
4963
|
-
const loaded =
|
|
5074
|
+
const [scrollTop, setScrollTop] = React32.useState(0);
|
|
5075
|
+
const loaded = React32.useMemo(
|
|
4964
5076
|
() => ({ firstItemIndex, count: items.length }),
|
|
4965
5077
|
[firstItemIndex, items.length]
|
|
4966
5078
|
);
|
|
4967
5079
|
const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
|
|
4968
5080
|
const bandKey = firstItemIndex + ":" + items.length;
|
|
4969
|
-
const win =
|
|
5081
|
+
const win = React32.useMemo(
|
|
4970
5082
|
() => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
|
|
4971
5083
|
[scrollTop, height, itemHeight, total, loaded]
|
|
4972
5084
|
);
|
|
4973
|
-
const need =
|
|
5085
|
+
const need = React32.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
|
|
4974
5086
|
const wantStart = need.start && hasMore?.start !== false;
|
|
4975
5087
|
const wantEnd = need.end && hasMore?.end !== false;
|
|
4976
5088
|
const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
|
|
4977
5089
|
const askKey = bandKey + "@" + bucket2;
|
|
4978
|
-
const asked =
|
|
4979
|
-
|
|
5090
|
+
const asked = React32.useRef({ start: null, end: null });
|
|
5091
|
+
React32.useEffect(() => {
|
|
4980
5092
|
if (loading || !wantStart || asked.current.start === askKey) return;
|
|
4981
5093
|
asked.current.start = askKey;
|
|
4982
5094
|
onNeedMore("start", win);
|
|
4983
5095
|
}, [wantStart, loading, askKey, onNeedMore, win]);
|
|
4984
|
-
|
|
5096
|
+
React32.useEffect(() => {
|
|
4985
5097
|
if (loading || !wantEnd || asked.current.end === askKey) return;
|
|
4986
5098
|
asked.current.end = askKey;
|
|
4987
5099
|
onNeedMore("end", win);
|
|
4988
5100
|
}, [wantEnd, loading, askKey, onNeedMore, win]);
|
|
4989
|
-
const lastKeysRef =
|
|
4990
|
-
const newKeys =
|
|
5101
|
+
const lastKeysRef = React32.useRef(null);
|
|
5102
|
+
const newKeys = React32.useMemo(() => {
|
|
4991
5103
|
const prev = lastKeysRef.current;
|
|
4992
5104
|
if (!prev) return /* @__PURE__ */ new Set();
|
|
4993
5105
|
const fresh = /* @__PURE__ */ new Set();
|
|
@@ -4997,7 +5109,7 @@ function VirtualList({
|
|
|
4997
5109
|
}
|
|
4998
5110
|
return fresh;
|
|
4999
5111
|
}, [items]);
|
|
5000
|
-
|
|
5112
|
+
React32.useEffect(() => {
|
|
5001
5113
|
lastKeysRef.current = new Set(items.map(keyOf));
|
|
5002
5114
|
}, [items]);
|
|
5003
5115
|
const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
|
|
@@ -5042,7 +5154,7 @@ function VirtualList({
|
|
|
5042
5154
|
}
|
|
5043
5155
|
|
|
5044
5156
|
// src/components/data/EntityRow.tsx
|
|
5045
|
-
import * as
|
|
5157
|
+
import * as React33 from "react";
|
|
5046
5158
|
import { jsx as jsx55, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
5047
5159
|
var ENTITY_ROW_METRIC_WIDTH = 74;
|
|
5048
5160
|
var METRIC_TONE_COLOR = {
|
|
@@ -5055,7 +5167,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
|
|
|
5055
5167
|
const key = m.id || m.label || i;
|
|
5056
5168
|
const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
|
|
5057
5169
|
const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
|
|
5058
|
-
const content = /* @__PURE__ */ jsxs50(
|
|
5170
|
+
const content = /* @__PURE__ */ jsxs50(React33.Fragment, { children: [
|
|
5059
5171
|
m.icon ? /* @__PURE__ */ jsx55("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
|
|
5060
5172
|
/* @__PURE__ */ jsx55("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
|
|
5061
5173
|
/* @__PURE__ */ jsx55("span", { className: "fd-sr", children: " " + m.label })
|
|
@@ -5147,7 +5259,7 @@ function EntityRow({
|
|
|
5147
5259
|
}
|
|
5148
5260
|
|
|
5149
5261
|
// src/components/data/TransferList.tsx
|
|
5150
|
-
import * as
|
|
5262
|
+
import * as React34 from "react";
|
|
5151
5263
|
import { createPortal as createPortal4 } from "react-dom";
|
|
5152
5264
|
|
|
5153
5265
|
// src/components/forms/Input.tsx
|
|
@@ -5253,12 +5365,12 @@ function TransferList({
|
|
|
5253
5365
|
listHeight = 440,
|
|
5254
5366
|
className = ""
|
|
5255
5367
|
}) {
|
|
5256
|
-
const [drag, setDrag] =
|
|
5257
|
-
const [dragOverSide, setDragOverSide] =
|
|
5258
|
-
const dragRef =
|
|
5259
|
-
const armedRef =
|
|
5260
|
-
const sideRefs =
|
|
5261
|
-
const hitTestSide =
|
|
5368
|
+
const [drag, setDrag] = React34.useState(null);
|
|
5369
|
+
const [dragOverSide, setDragOverSide] = React34.useState(null);
|
|
5370
|
+
const dragRef = React34.useRef(null);
|
|
5371
|
+
const armedRef = React34.useRef(null);
|
|
5372
|
+
const sideRefs = React34.useRef({ left: null, right: null });
|
|
5373
|
+
const hitTestSide = React34.useCallback((x, y) => {
|
|
5262
5374
|
for (const side of ["left", "right"]) {
|
|
5263
5375
|
const el = sideRefs.current[side];
|
|
5264
5376
|
if (!el) continue;
|
|
@@ -5267,7 +5379,7 @@ function TransferList({
|
|
|
5267
5379
|
}
|
|
5268
5380
|
return null;
|
|
5269
5381
|
}, []);
|
|
5270
|
-
const findItem =
|
|
5382
|
+
const findItem = React34.useCallback(
|
|
5271
5383
|
(side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
|
|
5272
5384
|
[left.items, right.items, keyOf]
|
|
5273
5385
|
);
|
|
@@ -5289,7 +5401,7 @@ function TransferList({
|
|
|
5289
5401
|
height: rect.height
|
|
5290
5402
|
};
|
|
5291
5403
|
};
|
|
5292
|
-
|
|
5404
|
+
React34.useEffect(() => {
|
|
5293
5405
|
const onMovePointer = (e) => {
|
|
5294
5406
|
const armed = armedRef.current;
|
|
5295
5407
|
if (!armed || e.pointerId !== armed.pointerId) return;
|
|
@@ -5342,7 +5454,7 @@ function TransferList({
|
|
|
5342
5454
|
window.removeEventListener("pointercancel", endDrag);
|
|
5343
5455
|
};
|
|
5344
5456
|
}, [hitTestSide, findItem, onMove]);
|
|
5345
|
-
|
|
5457
|
+
React34.useEffect(() => {
|
|
5346
5458
|
if (!drag || typeof document === "undefined") return;
|
|
5347
5459
|
const prev = document.body.style.userSelect;
|
|
5348
5460
|
document.body.style.userSelect = "none";
|
|
@@ -5450,11 +5562,11 @@ function TransferList({
|
|
|
5450
5562
|
}
|
|
5451
5563
|
|
|
5452
5564
|
// src/components/forms/Checkbox.tsx
|
|
5453
|
-
import * as
|
|
5565
|
+
import * as React35 from "react";
|
|
5454
5566
|
import { jsx as jsx59, jsxs as jsxs53 } from "react/jsx-runtime";
|
|
5455
5567
|
function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
|
|
5456
|
-
const ref =
|
|
5457
|
-
|
|
5568
|
+
const ref = React35.useRef(null);
|
|
5569
|
+
React35.useEffect(() => {
|
|
5458
5570
|
if (ref.current) ref.current.indeterminate = indeterminate;
|
|
5459
5571
|
}, [indeterminate]);
|
|
5460
5572
|
return /* @__PURE__ */ jsxs53("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
@@ -5498,7 +5610,7 @@ function Switch({ label, description, className = "", ...rest }) {
|
|
|
5498
5610
|
}
|
|
5499
5611
|
|
|
5500
5612
|
// src/components/forms/Select.tsx
|
|
5501
|
-
import * as
|
|
5613
|
+
import * as React36 from "react";
|
|
5502
5614
|
import { jsx as jsx62, jsxs as jsxs56 } from "react/jsx-runtime";
|
|
5503
5615
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
5504
5616
|
function Select({
|
|
@@ -5525,12 +5637,12 @@ function Select({
|
|
|
5525
5637
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
5526
5638
|
const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
|
|
5527
5639
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
5528
|
-
const [open, setOpen] =
|
|
5529
|
-
const [q, setQ] =
|
|
5530
|
-
const rootRef =
|
|
5531
|
-
const boxRef =
|
|
5532
|
-
const listRef =
|
|
5533
|
-
const typeBuf =
|
|
5640
|
+
const [open, setOpen] = React36.useState(false);
|
|
5641
|
+
const [q, setQ] = React36.useState("");
|
|
5642
|
+
const rootRef = React36.useRef(null);
|
|
5643
|
+
const boxRef = React36.useRef(null);
|
|
5644
|
+
const listRef = React36.useRef(null);
|
|
5645
|
+
const typeBuf = React36.useRef({ s: "", t: 0 });
|
|
5534
5646
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
5535
5647
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
5536
5648
|
const boxText = multiple ? chosen.length === 0 ? placeholder : chosen.length === 1 ? chosen[0].label : summary ? summary(chosen.map((o) => o.value)) : chosen.length + " selected" : selected ? selected.label : placeholder;
|
|
@@ -5669,7 +5781,7 @@ function Select({
|
|
|
5669
5781
|
),
|
|
5670
5782
|
q ? /* @__PURE__ */ jsx62("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
5671
5783
|
] }) : void 0,
|
|
5672
|
-
footer: multiple ? /* @__PURE__ */ jsxs56(
|
|
5784
|
+
footer: multiple ? /* @__PURE__ */ jsxs56(React36.Fragment, { children: [
|
|
5673
5785
|
/* @__PURE__ */ jsx62(
|
|
5674
5786
|
"button",
|
|
5675
5787
|
{
|
|
@@ -5700,7 +5812,7 @@ function Select({
|
|
|
5700
5812
|
'Nothing matches "',
|
|
5701
5813
|
q,
|
|
5702
5814
|
'".'
|
|
5703
|
-
] }) : groups.map((grp) => /* @__PURE__ */ jsxs56(
|
|
5815
|
+
] }) : groups.map((grp) => /* @__PURE__ */ jsxs56(React36.Fragment, { children: [
|
|
5704
5816
|
grp.g ? /* @__PURE__ */ jsx62("div", { className: "fd-pop-group", children: grp.g }) : null,
|
|
5705
5817
|
grp.items.map(({ o, i }) => /* @__PURE__ */ jsxs56(
|
|
5706
5818
|
"button",
|
|
@@ -5737,7 +5849,7 @@ function Select({
|
|
|
5737
5849
|
}
|
|
5738
5850
|
|
|
5739
5851
|
// src/components/forms/TimePicker.tsx
|
|
5740
|
-
import * as
|
|
5852
|
+
import * as React37 from "react";
|
|
5741
5853
|
import { jsx as jsx63, jsxs as jsxs57 } from "react/jsx-runtime";
|
|
5742
5854
|
var pad = (n) => String(n).padStart(2, "0");
|
|
5743
5855
|
function ClockFace({ value = "09:00", onChange }) {
|
|
@@ -5746,9 +5858,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
5746
5858
|
if (isNaN(m)) m = 0;
|
|
5747
5859
|
const pm = h24 >= 12;
|
|
5748
5860
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
5749
|
-
const [mode2, setMode] =
|
|
5750
|
-
const faceRef =
|
|
5751
|
-
const dragging =
|
|
5861
|
+
const [mode2, setMode] = React37.useState("h");
|
|
5862
|
+
const faceRef = React37.useRef(null);
|
|
5863
|
+
const dragging = React37.useRef(false);
|
|
5752
5864
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
5753
5865
|
const R = 108, NR = 80;
|
|
5754
5866
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -5821,9 +5933,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
5821
5933
|
}
|
|
5822
5934
|
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
|
|
5823
5935
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
5824
|
-
const [open, setOpen] =
|
|
5825
|
-
const rootRef =
|
|
5826
|
-
const boxRef =
|
|
5936
|
+
const [open, setOpen] = React37.useState(false);
|
|
5937
|
+
const rootRef = React37.useRef(null);
|
|
5938
|
+
const boxRef = React37.useRef(null);
|
|
5827
5939
|
const disp = () => {
|
|
5828
5940
|
if (!value) return "";
|
|
5829
5941
|
const [h, m] = value.split(":").map(Number);
|
|
@@ -5866,7 +5978,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
5866
5978
|
offset: 6,
|
|
5867
5979
|
width: 262,
|
|
5868
5980
|
role: "presentation",
|
|
5869
|
-
footer: /* @__PURE__ */ jsxs57(
|
|
5981
|
+
footer: /* @__PURE__ */ jsxs57(React37.Fragment, { children: [
|
|
5870
5982
|
/* @__PURE__ */ jsx63(
|
|
5871
5983
|
"button",
|
|
5872
5984
|
{
|
|
@@ -5894,7 +6006,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
5894
6006
|
}
|
|
5895
6007
|
|
|
5896
6008
|
// src/components/forms/Slider.tsx
|
|
5897
|
-
import * as
|
|
6009
|
+
import * as React38 from "react";
|
|
5898
6010
|
import { jsx as jsx64, jsxs as jsxs58 } from "react/jsx-runtime";
|
|
5899
6011
|
function Slider({
|
|
5900
6012
|
label,
|
|
@@ -5912,7 +6024,7 @@ function Slider({
|
|
|
5912
6024
|
...rest
|
|
5913
6025
|
}) {
|
|
5914
6026
|
const fieldId = useFieldId(id);
|
|
5915
|
-
const [dragging, setDragging] =
|
|
6027
|
+
const [dragging, setDragging] = React38.useState(false);
|
|
5916
6028
|
const v = value === void 0 ? min : Number(value);
|
|
5917
6029
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
5918
6030
|
return /* @__PURE__ */ jsxs58("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
|
|
@@ -5946,7 +6058,7 @@ function Slider({
|
|
|
5946
6058
|
}
|
|
5947
6059
|
|
|
5948
6060
|
// src/components/forms/RangeSlider.tsx
|
|
5949
|
-
import * as
|
|
6061
|
+
import * as React39 from "react";
|
|
5950
6062
|
import { jsx as jsx65, jsxs as jsxs59 } from "react/jsx-runtime";
|
|
5951
6063
|
function RangeSlider({
|
|
5952
6064
|
label,
|
|
@@ -5966,9 +6078,9 @@ function RangeSlider({
|
|
|
5966
6078
|
}) {
|
|
5967
6079
|
const fmt2 = format || ((v) => String(v));
|
|
5968
6080
|
const [a, b] = value || [min, max];
|
|
5969
|
-
const [drag, setDrag] =
|
|
5970
|
-
const [focus, setFocus] =
|
|
5971
|
-
const railRef =
|
|
6081
|
+
const [drag, setDrag] = React39.useState(null);
|
|
6082
|
+
const [focus, setFocus] = React39.useState(null);
|
|
6083
|
+
const railRef = React39.useRef(null);
|
|
5972
6084
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
5973
6085
|
const clampPair = (i, v) => {
|
|
5974
6086
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -5983,7 +6095,7 @@ function RangeSlider({
|
|
|
5983
6095
|
const r = railRef.current.getBoundingClientRect();
|
|
5984
6096
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
5985
6097
|
};
|
|
5986
|
-
|
|
6098
|
+
React39.useEffect(() => {
|
|
5987
6099
|
if (drag === null) return;
|
|
5988
6100
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
5989
6101
|
const upH = () => setDrag(null);
|
|
@@ -6064,7 +6176,7 @@ function RangeSlider({
|
|
|
6064
6176
|
/* @__PURE__ */ jsxs59("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
|
|
6065
6177
|
/* @__PURE__ */ jsx65("span", { className: "fd-range-rail", ref: railRef }),
|
|
6066
6178
|
/* @__PURE__ */ jsx65("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
|
|
6067
|
-
marks.map((m) => /* @__PURE__ */ jsxs59(
|
|
6179
|
+
marks.map((m) => /* @__PURE__ */ jsxs59(React39.Fragment, { children: [
|
|
6068
6180
|
/* @__PURE__ */ jsx65("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
|
|
6069
6181
|
m.label ? /* @__PURE__ */ jsx65("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
|
|
6070
6182
|
] }, m.value)),
|
|
@@ -6093,7 +6205,7 @@ function RangeSlider({
|
|
|
6093
6205
|
}
|
|
6094
6206
|
|
|
6095
6207
|
// src/components/forms/Dropzone.tsx
|
|
6096
|
-
import * as
|
|
6208
|
+
import * as React40 from "react";
|
|
6097
6209
|
import { jsx as jsx66, jsxs as jsxs60 } from "react/jsx-runtime";
|
|
6098
6210
|
function Dropzone({
|
|
6099
6211
|
onFiles,
|
|
@@ -6108,8 +6220,8 @@ function Dropzone({
|
|
|
6108
6220
|
className = "",
|
|
6109
6221
|
style
|
|
6110
6222
|
}) {
|
|
6111
|
-
const [over, setOver] =
|
|
6112
|
-
const depth =
|
|
6223
|
+
const [over, setOver] = React40.useState(false);
|
|
6224
|
+
const depth = React40.useRef(0);
|
|
6113
6225
|
const has = (e) => {
|
|
6114
6226
|
const dt = e.dataTransfer;
|
|
6115
6227
|
if (!dt) return false;
|
|
@@ -6171,8 +6283,8 @@ function FilePickButton({
|
|
|
6171
6283
|
className = "",
|
|
6172
6284
|
children
|
|
6173
6285
|
}) {
|
|
6174
|
-
const ref =
|
|
6175
|
-
return /* @__PURE__ */ jsxs60(
|
|
6286
|
+
const ref = React40.useRef(null);
|
|
6287
|
+
return /* @__PURE__ */ jsxs60(React40.Fragment, { children: [
|
|
6176
6288
|
/* @__PURE__ */ jsx66(
|
|
6177
6289
|
"button",
|
|
6178
6290
|
{
|
|
@@ -6205,10 +6317,10 @@ function FilePickButton({
|
|
|
6205
6317
|
}
|
|
6206
6318
|
function useStagedFiles(upload, opts) {
|
|
6207
6319
|
const o = opts || {};
|
|
6208
|
-
const [items, setItems] =
|
|
6209
|
-
const controllers =
|
|
6320
|
+
const [items, setItems] = React40.useState([]);
|
|
6321
|
+
const controllers = React40.useRef({});
|
|
6210
6322
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
6211
|
-
const run =
|
|
6323
|
+
const run = React40.useCallback((att) => {
|
|
6212
6324
|
if (!upload) return;
|
|
6213
6325
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
6214
6326
|
controllers.current[att.id] = ac;
|
|
@@ -6225,14 +6337,14 @@ function useStagedFiles(upload, opts) {
|
|
|
6225
6337
|
delete controllers.current[att.id];
|
|
6226
6338
|
});
|
|
6227
6339
|
}, [upload]);
|
|
6228
|
-
const add =
|
|
6340
|
+
const add = React40.useCallback((files) => {
|
|
6229
6341
|
if (!upload) return [];
|
|
6230
6342
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
6231
6343
|
setItems((list) => list.concat(atts));
|
|
6232
6344
|
atts.forEach(run);
|
|
6233
6345
|
return atts;
|
|
6234
6346
|
}, [upload, run]);
|
|
6235
|
-
const remove =
|
|
6347
|
+
const remove = React40.useCallback((att) => {
|
|
6236
6348
|
const ac = controllers.current[att.id];
|
|
6237
6349
|
if (ac) {
|
|
6238
6350
|
try {
|
|
@@ -6243,10 +6355,10 @@ function useStagedFiles(upload, opts) {
|
|
|
6243
6355
|
}
|
|
6244
6356
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
6245
6357
|
}, []);
|
|
6246
|
-
const retry =
|
|
6358
|
+
const retry = React40.useCallback((att) => {
|
|
6247
6359
|
run(att);
|
|
6248
6360
|
}, [run]);
|
|
6249
|
-
const clear =
|
|
6361
|
+
const clear = React40.useCallback(() => {
|
|
6250
6362
|
Object.values(controllers.current).forEach((ac) => {
|
|
6251
6363
|
try {
|
|
6252
6364
|
ac && ac.abort();
|
|
@@ -6370,7 +6482,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
6370
6482
|
}
|
|
6371
6483
|
|
|
6372
6484
|
// src/components/forms/MarkdownEditor.tsx
|
|
6373
|
-
import * as
|
|
6485
|
+
import * as React41 from "react";
|
|
6374
6486
|
import { jsx as jsx68, jsxs as jsxs62 } from "react/jsx-runtime";
|
|
6375
6487
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
6376
6488
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
@@ -6584,7 +6696,7 @@ function syncDom(root, value) {
|
|
|
6584
6696
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
6585
6697
|
}
|
|
6586
6698
|
var LIST_CONT = RE_LI;
|
|
6587
|
-
var MarkdownEditor =
|
|
6699
|
+
var MarkdownEditor = React41.forwardRef(function MarkdownEditor2({
|
|
6588
6700
|
value = "",
|
|
6589
6701
|
onChange,
|
|
6590
6702
|
onSubmit,
|
|
@@ -6603,10 +6715,10 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6603
6715
|
className = "",
|
|
6604
6716
|
id
|
|
6605
6717
|
}, ref) {
|
|
6606
|
-
const boxRef =
|
|
6607
|
-
const composing =
|
|
6608
|
-
const pendingCaret =
|
|
6609
|
-
|
|
6718
|
+
const boxRef = React41.useRef(null);
|
|
6719
|
+
const composing = React41.useRef(false);
|
|
6720
|
+
const pendingCaret = React41.useRef(null);
|
|
6721
|
+
React41.useLayoutEffect(() => {
|
|
6610
6722
|
const root = boxRef.current;
|
|
6611
6723
|
if (!root || composing.current) return;
|
|
6612
6724
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -6615,7 +6727,7 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6615
6727
|
pendingCaret.current = null;
|
|
6616
6728
|
if (active && caret != null) placeCaret(root, caret);
|
|
6617
6729
|
}, [value]);
|
|
6618
|
-
|
|
6730
|
+
React41.useEffect(() => {
|
|
6619
6731
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
6620
6732
|
}, [autoFocus]);
|
|
6621
6733
|
const caretNow = () => {
|
|
@@ -6682,7 +6794,7 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6682
6794
|
api.replaceRange(from, to, next, from + next.length);
|
|
6683
6795
|
}
|
|
6684
6796
|
};
|
|
6685
|
-
|
|
6797
|
+
React41.useImperativeHandle(ref, () => api);
|
|
6686
6798
|
function detect(text, caret) {
|
|
6687
6799
|
if (!onTrigger) return;
|
|
6688
6800
|
const upto = text.slice(0, caret);
|
|
@@ -6834,16 +6946,16 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6834
6946
|
});
|
|
6835
6947
|
|
|
6836
6948
|
// src/components/platform/AccountMenu.tsx
|
|
6837
|
-
import * as
|
|
6949
|
+
import * as React43 from "react";
|
|
6838
6950
|
|
|
6839
6951
|
// src/kits/sessionContext.tsx
|
|
6840
|
-
import * as
|
|
6841
|
-
var SessionContext =
|
|
6952
|
+
import * as React42 from "react";
|
|
6953
|
+
var SessionContext = React42.createContext(null);
|
|
6842
6954
|
function SessionProvider({ value, children }) {
|
|
6843
|
-
return
|
|
6955
|
+
return React42.createElement(SessionContext.Provider, { value }, children);
|
|
6844
6956
|
}
|
|
6845
6957
|
function useSessionContext() {
|
|
6846
|
-
const ctx =
|
|
6958
|
+
const ctx = React42.useContext(SessionContext);
|
|
6847
6959
|
if (!ctx) {
|
|
6848
6960
|
throw new Error(
|
|
6849
6961
|
"useSessionContext() was called outside a <SessionProvider>. Wrap your app root in <SessionProvider value={...}> with your real session, or \u2014 in the docs site or a demo \u2014 in <DemoSessionProvider>, before rendering AccountMenu, Gate, ProfilePage or AppSwitcher."
|
|
@@ -6883,11 +6995,11 @@ function AccountMenu({
|
|
|
6883
6995
|
...rest
|
|
6884
6996
|
}) {
|
|
6885
6997
|
const { user, roles, can: can2, signOut: ctxSignOut, demo } = useSessionContext();
|
|
6886
|
-
const [open, setOpen] =
|
|
6887
|
-
const [switching, setSwitching] =
|
|
6888
|
-
const [signingOut, setSigningOut] =
|
|
6889
|
-
const [signOutError, setSignOutError] =
|
|
6890
|
-
const ref =
|
|
6998
|
+
const [open, setOpen] = React43.useState(false);
|
|
6999
|
+
const [switching, setSwitching] = React43.useState(false);
|
|
7000
|
+
const [signingOut, setSigningOut] = React43.useState(false);
|
|
7001
|
+
const [signOutError, setSignOutError] = React43.useState(null);
|
|
7002
|
+
const ref = React43.useRef(null);
|
|
6891
7003
|
const visibleLinks = links.filter((l) => !l.perm || can2(l.perm));
|
|
6892
7004
|
const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || can2(l.perm)) })).filter((g) => g.links.length);
|
|
6893
7005
|
const closeMenu = () => {
|
|
@@ -7012,13 +7124,13 @@ function AccountMenu({
|
|
|
7012
7124
|
}
|
|
7013
7125
|
|
|
7014
7126
|
// src/components/platform/AppSwitcher.tsx
|
|
7015
|
-
import * as
|
|
7127
|
+
import * as React44 from "react";
|
|
7016
7128
|
import { jsx as jsx70, jsxs as jsxs64 } from "react/jsx-runtime";
|
|
7017
7129
|
function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
7018
7130
|
const { apps: contextApps } = useSessionContext();
|
|
7019
7131
|
const apps = appsProp ?? contextApps ?? [];
|
|
7020
|
-
const [open, setOpen] =
|
|
7021
|
-
const anchorRef =
|
|
7132
|
+
const [open, setOpen] = React44.useState(false);
|
|
7133
|
+
const anchorRef = React44.useRef(null);
|
|
7022
7134
|
if (!apps.length) return null;
|
|
7023
7135
|
const items = apps.map((app) => ({
|
|
7024
7136
|
id: app.key,
|
|
@@ -7032,7 +7144,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7032
7144
|
window.location.href = app.url;
|
|
7033
7145
|
}
|
|
7034
7146
|
}));
|
|
7035
|
-
return /* @__PURE__ */ jsxs64(
|
|
7147
|
+
return /* @__PURE__ */ jsxs64(React44.Fragment, { children: [
|
|
7036
7148
|
/* @__PURE__ */ jsx70("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx70(
|
|
7037
7149
|
IconButton,
|
|
7038
7150
|
{
|
|
@@ -7061,10 +7173,10 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7061
7173
|
}
|
|
7062
7174
|
|
|
7063
7175
|
// src/components/platform/AppearanceMenu.tsx
|
|
7064
|
-
import * as
|
|
7176
|
+
import * as React46 from "react";
|
|
7065
7177
|
|
|
7066
7178
|
// src/kits/appearance.ts
|
|
7067
|
-
import * as
|
|
7179
|
+
import * as React45 from "react";
|
|
7068
7180
|
var DEFAULT_STORAGE_KEY = "fd-appearance";
|
|
7069
7181
|
var DEFAULT_PREFS = {
|
|
7070
7182
|
theme: "system",
|
|
@@ -7159,11 +7271,11 @@ function applyPrefs(prefs, root = document.documentElement) {
|
|
|
7159
7271
|
else root.removeAttribute("data-motion");
|
|
7160
7272
|
}
|
|
7161
7273
|
function useAppearancePrefs(store) {
|
|
7162
|
-
const prefs =
|
|
7163
|
-
|
|
7274
|
+
const prefs = React45.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
7275
|
+
React45.useEffect(() => {
|
|
7164
7276
|
applyPrefs(prefs);
|
|
7165
7277
|
}, [prefs]);
|
|
7166
|
-
|
|
7278
|
+
React45.useEffect(() => {
|
|
7167
7279
|
if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
7168
7280
|
return;
|
|
7169
7281
|
}
|
|
@@ -7172,7 +7284,7 @@ function useAppearancePrefs(store) {
|
|
|
7172
7284
|
mq.addEventListener("change", onChange);
|
|
7173
7285
|
return () => mq.removeEventListener("change", onChange);
|
|
7174
7286
|
}, [prefs]);
|
|
7175
|
-
const update =
|
|
7287
|
+
const update = React45.useCallback(
|
|
7176
7288
|
(patch) => {
|
|
7177
7289
|
store.write({ ...store.getSnapshot(), ...patch });
|
|
7178
7290
|
},
|
|
@@ -7195,15 +7307,15 @@ var TEXT_SCALE_OPTIONS = [
|
|
|
7195
7307
|
{ value: "xl", label: "XL" }
|
|
7196
7308
|
];
|
|
7197
7309
|
function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
|
|
7198
|
-
const store =
|
|
7310
|
+
const store = React46.useMemo(
|
|
7199
7311
|
() => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
|
|
7200
7312
|
[storeProp, storageKey, storage, defaults]
|
|
7201
7313
|
);
|
|
7202
7314
|
const [prefs, update] = useAppearancePrefs(store);
|
|
7203
|
-
const [open, setOpen] =
|
|
7204
|
-
const anchorRef =
|
|
7315
|
+
const [open, setOpen] = React46.useState(false);
|
|
7316
|
+
const anchorRef = React46.useRef(null);
|
|
7205
7317
|
const patch = (p) => update(p);
|
|
7206
|
-
return /* @__PURE__ */ jsxs65(
|
|
7318
|
+
return /* @__PURE__ */ jsxs65(React46.Fragment, { children: [
|
|
7207
7319
|
/* @__PURE__ */ jsx71("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx71(
|
|
7208
7320
|
IconButton,
|
|
7209
7321
|
{
|
|
@@ -7272,14 +7384,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7272
7384
|
}
|
|
7273
7385
|
|
|
7274
7386
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
7275
|
-
import * as
|
|
7387
|
+
import * as React47 from "react";
|
|
7276
7388
|
import { jsx as jsx72, jsxs as jsxs66 } from "react/jsx-runtime";
|
|
7277
7389
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
7278
7390
|
function Json({ obj }) {
|
|
7279
7391
|
return /* @__PURE__ */ jsx72("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
7280
7392
|
}
|
|
7281
7393
|
function Endpoint({ s, onRequest }) {
|
|
7282
|
-
const [tried, setTried] =
|
|
7394
|
+
const [tried, setTried] = React47.useState(null);
|
|
7283
7395
|
const run = async () => {
|
|
7284
7396
|
setTried("busy");
|
|
7285
7397
|
const t0 = (window.performance || Date).now();
|
|
@@ -7352,10 +7464,10 @@ function ApiSpecBrowser({
|
|
|
7352
7464
|
className = "",
|
|
7353
7465
|
...rest
|
|
7354
7466
|
}) {
|
|
7355
|
-
const [q, setQ] =
|
|
7356
|
-
const [method, setMethod] =
|
|
7357
|
-
const [mod, setMod] =
|
|
7358
|
-
const [listOnly, setListOnly] =
|
|
7467
|
+
const [q, setQ] = React47.useState("");
|
|
7468
|
+
const [method, setMethod] = React47.useState(null);
|
|
7469
|
+
const [mod, setMod] = React47.useState(null);
|
|
7470
|
+
const [listOnly, setListOnly] = React47.useState(false);
|
|
7359
7471
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
7360
7472
|
const hits = spec.filter((s) => (!method || s.method === method) && (!listOnly || s.isList) && (!activeModule || activeModule.endpoints.indexOf(s.id) >= 0) && (!q || (s.path + " " + s.title + " " + s.purpose + " " + (s.usedBy || []).join(" ")).toLowerCase().includes(q.toLowerCase())));
|
|
7361
7473
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
@@ -7434,7 +7546,7 @@ function ApiSpecBrowser({
|
|
|
7434
7546
|
}
|
|
7435
7547
|
|
|
7436
7548
|
// src/components/platform/ProfilePage.tsx
|
|
7437
|
-
import * as
|
|
7549
|
+
import * as React48 from "react";
|
|
7438
7550
|
import { jsx as jsx73, jsxs as jsxs67 } from "react/jsx-runtime";
|
|
7439
7551
|
function fieldInitialValue(field, user) {
|
|
7440
7552
|
if (field.value) return field.value(user);
|
|
@@ -7470,21 +7582,21 @@ function ProfilePage({
|
|
|
7470
7582
|
}) {
|
|
7471
7583
|
const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
|
|
7472
7584
|
const user = userProp || sessionUser;
|
|
7473
|
-
const initialFieldValues =
|
|
7585
|
+
const initialFieldValues = React48.useMemo(() => {
|
|
7474
7586
|
const values2 = {};
|
|
7475
7587
|
for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
|
|
7476
7588
|
return values2;
|
|
7477
7589
|
}, [user.id, fields]);
|
|
7478
|
-
const initialNotify =
|
|
7590
|
+
const initialNotify = React48.useMemo(() => {
|
|
7479
7591
|
const values2 = {};
|
|
7480
7592
|
for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
|
|
7481
7593
|
return values2;
|
|
7482
7594
|
}, [user.id, notifications]);
|
|
7483
|
-
const [values, setValues] =
|
|
7484
|
-
const [notify, setNotify] =
|
|
7485
|
-
const [saving, setSaving] =
|
|
7486
|
-
const [saved, setSaved] =
|
|
7487
|
-
const [prevUserId, setPrevUserId] =
|
|
7595
|
+
const [values, setValues] = React48.useState(initialFieldValues);
|
|
7596
|
+
const [notify, setNotify] = React48.useState(initialNotify);
|
|
7597
|
+
const [saving, setSaving] = React48.useState(false);
|
|
7598
|
+
const [saved, setSaved] = React48.useState(false);
|
|
7599
|
+
const [prevUserId, setPrevUserId] = React48.useState(user.id);
|
|
7488
7600
|
if (user.id !== prevUserId) {
|
|
7489
7601
|
setPrevUserId(user.id);
|
|
7490
7602
|
setValues(initialFieldValues);
|
|
@@ -7672,11 +7784,11 @@ function ProfilePage({
|
|
|
7672
7784
|
}
|
|
7673
7785
|
|
|
7674
7786
|
// src/components/platform/SignInPage.tsx
|
|
7675
|
-
import * as
|
|
7787
|
+
import * as React49 from "react";
|
|
7676
7788
|
import { Fragment as Fragment18, jsx as jsx74, jsxs as jsxs68 } from "react/jsx-runtime";
|
|
7677
7789
|
function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
7678
|
-
const [signingIn, setSigningIn] =
|
|
7679
|
-
const [resuming, setResuming] =
|
|
7790
|
+
const [signingIn, setSigningIn] = React49.useState(false);
|
|
7791
|
+
const [resuming, setResuming] = React49.useState(false);
|
|
7680
7792
|
function handleSignIn() {
|
|
7681
7793
|
setSigningIn(true);
|
|
7682
7794
|
onSignIn();
|
|
@@ -7865,10 +7977,10 @@ function GoogleGlyph() {
|
|
|
7865
7977
|
}
|
|
7866
7978
|
|
|
7867
7979
|
// src/components/platform/RoadmapTimeline.tsx
|
|
7868
|
-
import * as
|
|
7980
|
+
import * as React52 from "react";
|
|
7869
7981
|
|
|
7870
7982
|
// src/kits/session.ts
|
|
7871
|
-
import * as
|
|
7983
|
+
import * as React50 from "react";
|
|
7872
7984
|
var PERMISSION_CATALOG = [
|
|
7873
7985
|
{ group: "Plans", items: [
|
|
7874
7986
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -9435,8 +9547,8 @@ function roadmap(overrides) {
|
|
|
9435
9547
|
};
|
|
9436
9548
|
}
|
|
9437
9549
|
function useSession() {
|
|
9438
|
-
const [s, setS] =
|
|
9439
|
-
|
|
9550
|
+
const [s, setS] = React50.useState(getSession);
|
|
9551
|
+
React50.useEffect(() => subscribe(setS), []);
|
|
9440
9552
|
return s;
|
|
9441
9553
|
}
|
|
9442
9554
|
var SessionKit = {
|
|
@@ -9469,7 +9581,7 @@ var SessionKit = {
|
|
|
9469
9581
|
};
|
|
9470
9582
|
function DemoSessionProvider({ children }) {
|
|
9471
9583
|
const session = useSession();
|
|
9472
|
-
const value =
|
|
9584
|
+
const value = React50.useMemo(
|
|
9473
9585
|
() => ({
|
|
9474
9586
|
user: session.user,
|
|
9475
9587
|
roles: session.roles,
|
|
@@ -9485,11 +9597,11 @@ function DemoSessionProvider({ children }) {
|
|
|
9485
9597
|
}),
|
|
9486
9598
|
[session]
|
|
9487
9599
|
);
|
|
9488
|
-
return
|
|
9600
|
+
return React50.createElement(SessionProvider, { value }, children);
|
|
9489
9601
|
}
|
|
9490
9602
|
|
|
9491
9603
|
// src/kits/runtime.ts
|
|
9492
|
-
import * as
|
|
9604
|
+
import * as React51 from "react";
|
|
9493
9605
|
var WIRED_ENDPOINTS = [
|
|
9494
9606
|
// Nothing yet. Every id below would come from a real service:
|
|
9495
9607
|
// "plan.get", "placements.list", …
|
|
@@ -9660,8 +9772,8 @@ var RuntimeKit = {
|
|
|
9660
9772
|
};
|
|
9661
9773
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
9662
9774
|
function useRuntimeMode() {
|
|
9663
|
-
const [m, setM] =
|
|
9664
|
-
|
|
9775
|
+
const [m, setM] = React51.useState(RuntimeKit.getMode());
|
|
9776
|
+
React51.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
9665
9777
|
return m;
|
|
9666
9778
|
}
|
|
9667
9779
|
function useFeatureStatus(key) {
|
|
@@ -9744,12 +9856,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
9744
9856
|
}
|
|
9745
9857
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
9746
9858
|
const session = SessionKit.useSession();
|
|
9747
|
-
const [project, setProject] =
|
|
9748
|
-
const [q, setQ] =
|
|
9749
|
-
const scrollRef =
|
|
9750
|
-
const nowRef =
|
|
9751
|
-
const rm =
|
|
9752
|
-
const byKey =
|
|
9859
|
+
const [project, setProject] = React52.useState("");
|
|
9860
|
+
const [q, setQ] = React52.useState("");
|
|
9861
|
+
const scrollRef = React52.useRef(null);
|
|
9862
|
+
const nowRef = React52.useRef(null);
|
|
9863
|
+
const rm = React52.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
9864
|
+
const byKey = React52.useMemo(() => {
|
|
9753
9865
|
const m = {};
|
|
9754
9866
|
rm.items.forEach((i) => {
|
|
9755
9867
|
m[i.key] = i;
|
|
@@ -9758,7 +9870,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
9758
9870
|
}, [rm]);
|
|
9759
9871
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
9760
9872
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
9761
|
-
|
|
9873
|
+
React52.useEffect(() => {
|
|
9762
9874
|
let raf1 = 0, raf2 = 0;
|
|
9763
9875
|
const place = () => {
|
|
9764
9876
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -9832,7 +9944,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
9832
9944
|
lastPhase = item.phase;
|
|
9833
9945
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
9834
9946
|
const isBoundary = n === firstPending;
|
|
9835
|
-
return /* @__PURE__ */ jsxs69(
|
|
9947
|
+
return /* @__PURE__ */ jsxs69(React52.Fragment, { children: [
|
|
9836
9948
|
showPhase ? /* @__PURE__ */ jsxs69("div", { className: "fd-rm-era", children: [
|
|
9837
9949
|
/* @__PURE__ */ jsxs69("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
9838
9950
|
/* @__PURE__ */ jsx75("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
@@ -9876,7 +9988,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
9876
9988
|
}
|
|
9877
9989
|
|
|
9878
9990
|
// src/components/platform/ComingSoon.tsx
|
|
9879
|
-
import * as
|
|
9991
|
+
import * as React53 from "react";
|
|
9880
9992
|
import { createPortal as createPortal5 } from "react-dom";
|
|
9881
9993
|
import { Fragment as Fragment20, jsx as jsx76, jsxs as jsxs70 } from "react/jsx-runtime";
|
|
9882
9994
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
@@ -9894,8 +10006,8 @@ function writeBypassed(list) {
|
|
|
9894
10006
|
}
|
|
9895
10007
|
}
|
|
9896
10008
|
function useBypass(key) {
|
|
9897
|
-
const [on, setOn] =
|
|
9898
|
-
|
|
10009
|
+
const [on, setOn] = React53.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
10010
|
+
React53.useEffect(() => {
|
|
9899
10011
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
9900
10012
|
}, [key]);
|
|
9901
10013
|
const set = (next) => {
|
|
@@ -9942,9 +10054,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
|
|
|
9942
10054
|
] });
|
|
9943
10055
|
}
|
|
9944
10056
|
function useHoverCard(open) {
|
|
9945
|
-
const anchor =
|
|
9946
|
-
const [pos, setPos] =
|
|
9947
|
-
|
|
10057
|
+
const anchor = React53.useRef(null);
|
|
10058
|
+
const [pos, setPos] = React53.useState(null);
|
|
10059
|
+
React53.useLayoutEffect(() => {
|
|
9948
10060
|
if (!open || !anchor.current) {
|
|
9949
10061
|
setPos(null);
|
|
9950
10062
|
return;
|
|
@@ -10071,10 +10183,10 @@ function ComingSoon({
|
|
|
10071
10183
|
] });
|
|
10072
10184
|
}
|
|
10073
10185
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
10074
|
-
const [open, setOpen] =
|
|
10186
|
+
const [open, setOpen] = React53.useState(false);
|
|
10075
10187
|
const [anchor, pos] = useHoverCard(open);
|
|
10076
10188
|
const zIndex = useOverlayLayer(open);
|
|
10077
|
-
const close =
|
|
10189
|
+
const close = React53.useRef(null);
|
|
10078
10190
|
const show = () => {
|
|
10079
10191
|
if (close.current) {
|
|
10080
10192
|
clearTimeout(close.current);
|
|
@@ -10090,7 +10202,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10090
10202
|
setOpen(false);
|
|
10091
10203
|
}, 140);
|
|
10092
10204
|
};
|
|
10093
|
-
|
|
10205
|
+
React53.useEffect(() => () => {
|
|
10094
10206
|
if (close.current) clearTimeout(close.current);
|
|
10095
10207
|
}, []);
|
|
10096
10208
|
return /* @__PURE__ */ jsxs70(
|
|
@@ -10261,14 +10373,14 @@ function PermissionHint({ perm, children }) {
|
|
|
10261
10373
|
}
|
|
10262
10374
|
|
|
10263
10375
|
// src/components/platform/ModeSwitch.tsx
|
|
10264
|
-
import * as
|
|
10376
|
+
import * as React54 from "react";
|
|
10265
10377
|
import { Fragment as Fragment21, jsx as jsx78, jsxs as jsxs72 } from "react/jsx-runtime";
|
|
10266
10378
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
10267
10379
|
const mode2 = useRuntimeMode();
|
|
10268
|
-
const [open, setOpen] =
|
|
10380
|
+
const [open, setOpen] = React54.useState(false);
|
|
10269
10381
|
const zIndex = useOverlayLayer(open);
|
|
10270
|
-
const ref =
|
|
10271
|
-
|
|
10382
|
+
const ref = React54.useRef(null);
|
|
10383
|
+
React54.useEffect(() => {
|
|
10272
10384
|
if (!open) return;
|
|
10273
10385
|
const away = (e) => {
|
|
10274
10386
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -10524,7 +10636,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
10524
10636
|
}
|
|
10525
10637
|
|
|
10526
10638
|
// src/components/planner/MixGap.tsx
|
|
10527
|
-
import * as
|
|
10639
|
+
import * as React55 from "react";
|
|
10528
10640
|
import { Fragment as Fragment22, jsx as jsx81, jsxs as jsxs75 } from "react/jsx-runtime";
|
|
10529
10641
|
var MIX_GAP_LAYOUT = {
|
|
10530
10642
|
trackHeight: 30,
|
|
@@ -10539,7 +10651,7 @@ function mixGapOffset(value, max) {
|
|
|
10539
10651
|
}
|
|
10540
10652
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
10541
10653
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
10542
|
-
const [hover, setHover] =
|
|
10654
|
+
const [hover, setHover] = React55.useState(null);
|
|
10543
10655
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
10544
10656
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
10545
10657
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
@@ -10682,7 +10794,7 @@ function ChannelContribution({
|
|
|
10682
10794
|
}
|
|
10683
10795
|
|
|
10684
10796
|
// src/components/planner/BudgetReallocator.tsx
|
|
10685
|
-
import * as
|
|
10797
|
+
import * as React56 from "react";
|
|
10686
10798
|
import { Fragment as Fragment23, jsx as jsx83, jsxs as jsxs77 } from "react/jsx-runtime";
|
|
10687
10799
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
10688
10800
|
function BudgetReallocator({
|
|
@@ -10698,8 +10810,8 @@ function BudgetReallocator({
|
|
|
10698
10810
|
onCancel,
|
|
10699
10811
|
className = ""
|
|
10700
10812
|
}) {
|
|
10701
|
-
const [draft, setDraft] =
|
|
10702
|
-
|
|
10813
|
+
const [draft, setDraft] = React56.useState(spend);
|
|
10814
|
+
React56.useEffect(() => setDraft(spend), [spend]);
|
|
10703
10815
|
const dirty = draft !== spend;
|
|
10704
10816
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
10705
10817
|
const nextBand = bandFor(nextCrp);
|
|
@@ -10714,10 +10826,10 @@ function BudgetReallocator({
|
|
|
10714
10826
|
setDraft(spend);
|
|
10715
10827
|
if (onCancel) onCancel();
|
|
10716
10828
|
};
|
|
10717
|
-
const trackRef =
|
|
10718
|
-
const chipRef =
|
|
10719
|
-
const [chipLeft, setChipLeft] =
|
|
10720
|
-
|
|
10829
|
+
const trackRef = React56.useRef(null);
|
|
10830
|
+
const chipRef = React56.useRef(null);
|
|
10831
|
+
const [chipLeft, setChipLeft] = React56.useState(null);
|
|
10832
|
+
React56.useLayoutEffect(() => {
|
|
10721
10833
|
const track = trackRef.current;
|
|
10722
10834
|
if (!dirty || !track) {
|
|
10723
10835
|
setChipLeft(null);
|
|
@@ -10904,7 +11016,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "" })
|
|
|
10904
11016
|
}
|
|
10905
11017
|
|
|
10906
11018
|
// src/components/planner/PreferenceMeter.tsx
|
|
10907
|
-
import * as
|
|
11019
|
+
import * as React57 from "react";
|
|
10908
11020
|
import { jsx as jsx86, jsxs as jsxs80 } from "react/jsx-runtime";
|
|
10909
11021
|
function preferenceScore(criteria) {
|
|
10910
11022
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
@@ -10934,7 +11046,7 @@ function PreferenceMeter({
|
|
|
10934
11046
|
className = ""
|
|
10935
11047
|
}) {
|
|
10936
11048
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
10937
|
-
const segments =
|
|
11049
|
+
const segments = React57.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
10938
11050
|
return /* @__PURE__ */ jsx86(
|
|
10939
11051
|
ScoreMeter,
|
|
10940
11052
|
{
|
|
@@ -10973,10 +11085,10 @@ function PreferenceMeter({
|
|
|
10973
11085
|
}
|
|
10974
11086
|
|
|
10975
11087
|
// src/components/chat/AgentChatPanel.tsx
|
|
10976
|
-
import * as
|
|
11088
|
+
import * as React63 from "react";
|
|
10977
11089
|
|
|
10978
11090
|
// src/components/chat/chatEngine.ts
|
|
10979
|
-
import * as
|
|
11091
|
+
import * as React58 from "react";
|
|
10980
11092
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
10981
11093
|
var JOB_PENDING = ["queued", "running"];
|
|
10982
11094
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -11030,22 +11142,22 @@ function useChatEngine(opts) {
|
|
|
11030
11142
|
onClear,
|
|
11031
11143
|
onFeedback
|
|
11032
11144
|
} = opts || {};
|
|
11033
|
-
const [status, setStatus] =
|
|
11034
|
-
const [threadId, setThreadId] =
|
|
11035
|
-
const [messages, setMessages] =
|
|
11036
|
-
const [queue, setQueue] =
|
|
11037
|
-
const [fatal, setFatal] =
|
|
11038
|
-
const [busy, setBusy] =
|
|
11039
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
11040
|
-
const listRef =
|
|
11041
|
-
const queueRef =
|
|
11042
|
-
const busyRef =
|
|
11043
|
-
const stoppedRef =
|
|
11044
|
-
const abortRef =
|
|
11045
|
-
const serverCount =
|
|
11046
|
-
const threadRef =
|
|
11047
|
-
const mounted =
|
|
11048
|
-
|
|
11145
|
+
const [status, setStatus] = React58.useState("idle");
|
|
11146
|
+
const [threadId, setThreadId] = React58.useState(null);
|
|
11147
|
+
const [messages, setMessages] = React58.useState([]);
|
|
11148
|
+
const [queue, setQueue] = React58.useState([]);
|
|
11149
|
+
const [fatal, setFatal] = React58.useState(null);
|
|
11150
|
+
const [busy, setBusy] = React58.useState(false);
|
|
11151
|
+
const [turnStartedAt, setTurnStartedAt] = React58.useState(null);
|
|
11152
|
+
const listRef = React58.useRef([]);
|
|
11153
|
+
const queueRef = React58.useRef([]);
|
|
11154
|
+
const busyRef = React58.useRef(false);
|
|
11155
|
+
const stoppedRef = React58.useRef(false);
|
|
11156
|
+
const abortRef = React58.useRef(null);
|
|
11157
|
+
const serverCount = React58.useRef(0);
|
|
11158
|
+
const threadRef = React58.useRef(null);
|
|
11159
|
+
const mounted = React58.useRef(true);
|
|
11160
|
+
React58.useEffect(() => {
|
|
11049
11161
|
mounted.current = true;
|
|
11050
11162
|
return () => {
|
|
11051
11163
|
mounted.current = false;
|
|
@@ -11067,14 +11179,14 @@ function useChatEngine(opts) {
|
|
|
11067
11179
|
}
|
|
11068
11180
|
return false;
|
|
11069
11181
|
};
|
|
11070
|
-
const loadThread =
|
|
11182
|
+
const loadThread = React58.useCallback(async (id) => {
|
|
11071
11183
|
const data = await apiAdapter.getThread(id);
|
|
11072
11184
|
const list = [...data && data.messages || []];
|
|
11073
11185
|
serverCount.current = list.length;
|
|
11074
11186
|
commit(list);
|
|
11075
11187
|
return list;
|
|
11076
11188
|
}, [apiAdapter]);
|
|
11077
|
-
|
|
11189
|
+
React58.useEffect(() => {
|
|
11078
11190
|
if (!apiAdapter) {
|
|
11079
11191
|
setStatus("idle");
|
|
11080
11192
|
setFatal(null);
|
|
@@ -11287,7 +11399,7 @@ function useChatEngine(opts) {
|
|
|
11287
11399
|
await dispatchTurn(turn);
|
|
11288
11400
|
}
|
|
11289
11401
|
}
|
|
11290
|
-
const send =
|
|
11402
|
+
const send = React58.useCallback((text, attachments) => {
|
|
11291
11403
|
const body = (text || "").trim();
|
|
11292
11404
|
if (!body && !(attachments && attachments.length)) return;
|
|
11293
11405
|
if (status === "disconnected") return;
|
|
@@ -11297,7 +11409,7 @@ function useChatEngine(opts) {
|
|
|
11297
11409
|
stoppedRef.current = false;
|
|
11298
11410
|
drain();
|
|
11299
11411
|
}, [status]);
|
|
11300
|
-
const stop =
|
|
11412
|
+
const stop = React58.useCallback(() => {
|
|
11301
11413
|
stoppedRef.current = true;
|
|
11302
11414
|
const ac = abortRef.current;
|
|
11303
11415
|
if (ac) {
|
|
@@ -11316,11 +11428,11 @@ function useChatEngine(opts) {
|
|
|
11316
11428
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
11317
11429
|
}
|
|
11318
11430
|
}, [apiAdapter]);
|
|
11319
|
-
const removeQueued =
|
|
11431
|
+
const removeQueued = React58.useCallback((id) => {
|
|
11320
11432
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
11321
11433
|
setQueue(queueRef.current.slice());
|
|
11322
11434
|
}, []);
|
|
11323
|
-
const retry =
|
|
11435
|
+
const retry = React58.useCallback(() => {
|
|
11324
11436
|
const list = listRef.current;
|
|
11325
11437
|
let at = -1;
|
|
11326
11438
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -11336,19 +11448,19 @@ function useChatEngine(opts) {
|
|
|
11336
11448
|
setQueue(queueRef.current.slice());
|
|
11337
11449
|
drain();
|
|
11338
11450
|
}, []);
|
|
11339
|
-
const clear =
|
|
11451
|
+
const clear = React58.useCallback(() => {
|
|
11340
11452
|
commit([]);
|
|
11341
11453
|
serverCount.current = 0;
|
|
11342
11454
|
queueRef.current = [];
|
|
11343
11455
|
setQueue([]);
|
|
11344
11456
|
onClear && onClear();
|
|
11345
11457
|
}, [onClear]);
|
|
11346
|
-
const setFeedback =
|
|
11458
|
+
const setFeedback = React58.useCallback((id, value) => {
|
|
11347
11459
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
11348
11460
|
const msg = listRef.current.find((m) => m.id === id);
|
|
11349
11461
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
11350
11462
|
}, [onFeedback]);
|
|
11351
|
-
const reload =
|
|
11463
|
+
const reload = React58.useCallback(async () => {
|
|
11352
11464
|
if (!threadRef.current) return;
|
|
11353
11465
|
setStatus("loading");
|
|
11354
11466
|
try {
|
|
@@ -11386,10 +11498,10 @@ var ChatKit = {
|
|
|
11386
11498
|
};
|
|
11387
11499
|
|
|
11388
11500
|
// src/components/chat/ChatTranscript.tsx
|
|
11389
|
-
import * as
|
|
11501
|
+
import * as React60 from "react";
|
|
11390
11502
|
|
|
11391
11503
|
// src/components/chat/ChatTurn.tsx
|
|
11392
|
-
import * as
|
|
11504
|
+
import * as React59 from "react";
|
|
11393
11505
|
import { jsx as jsx87, jsxs as jsxs81 } from "react/jsx-runtime";
|
|
11394
11506
|
function JsonView({ value }) {
|
|
11395
11507
|
let text;
|
|
@@ -11426,7 +11538,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
|
11426
11538
|
] });
|
|
11427
11539
|
}
|
|
11428
11540
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
11429
|
-
const [open, setOpen] =
|
|
11541
|
+
const [open, setOpen] = React59.useState(defaultOpen);
|
|
11430
11542
|
if (!text) return null;
|
|
11431
11543
|
return /* @__PURE__ */ jsxs81("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
|
|
11432
11544
|
/* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -11443,7 +11555,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
|
11443
11555
|
] });
|
|
11444
11556
|
}
|
|
11445
11557
|
function Citations({ items = [], onOpen }) {
|
|
11446
|
-
const [open, setOpen] =
|
|
11558
|
+
const [open, setOpen] = React59.useState(false);
|
|
11447
11559
|
if (!items.length) return null;
|
|
11448
11560
|
return /* @__PURE__ */ jsxs81("div", { className: "fdc-cites", children: [
|
|
11449
11561
|
/* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -11469,7 +11581,7 @@ function clampText(text, max) {
|
|
|
11469
11581
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
11470
11582
|
}
|
|
11471
11583
|
function MessageBody({ message: m, ctx }) {
|
|
11472
|
-
const [expanded, setExpanded] =
|
|
11584
|
+
const [expanded, setExpanded] = React59.useState(false);
|
|
11473
11585
|
const isUser = m.role === "user";
|
|
11474
11586
|
const raw = m.text || "";
|
|
11475
11587
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
@@ -11536,9 +11648,9 @@ function MessageBody({ message: m, ctx }) {
|
|
|
11536
11648
|
] });
|
|
11537
11649
|
}
|
|
11538
11650
|
function useCopyRun() {
|
|
11539
|
-
const [done, setDone] =
|
|
11540
|
-
const t =
|
|
11541
|
-
|
|
11651
|
+
const [done, setDone] = React59.useState(false);
|
|
11652
|
+
const t = React59.useRef(null);
|
|
11653
|
+
React59.useEffect(() => () => {
|
|
11542
11654
|
if (t.current) clearTimeout(t.current);
|
|
11543
11655
|
}, []);
|
|
11544
11656
|
return [done, (text) => {
|
|
@@ -11565,7 +11677,7 @@ function RunActions({ group, ctx }) {
|
|
|
11565
11677
|
] }),
|
|
11566
11678
|
isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx87("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx87("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
11567
11679
|
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx87("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx87("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
11568
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs81(
|
|
11680
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs81(React59.Fragment, { children: [
|
|
11569
11681
|
/* @__PURE__ */ jsx87("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ jsx87("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
11570
11682
|
/* @__PURE__ */ jsx87("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ jsx87("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
11571
11683
|
] }) : null,
|
|
@@ -11660,10 +11772,10 @@ function ChatTranscript({
|
|
|
11660
11772
|
renderEmpty,
|
|
11661
11773
|
className = ""
|
|
11662
11774
|
}) {
|
|
11663
|
-
const scroller =
|
|
11664
|
-
const stick =
|
|
11665
|
-
const [pill, setPill] =
|
|
11666
|
-
const seen =
|
|
11775
|
+
const scroller = React60.useRef(null);
|
|
11776
|
+
const stick = React60.useRef(true);
|
|
11777
|
+
const [pill, setPill] = React60.useState(0);
|
|
11778
|
+
const seen = React60.useRef(0);
|
|
11667
11779
|
const toBottom = (smooth) => {
|
|
11668
11780
|
const el = scroller.current;
|
|
11669
11781
|
if (!el) return;
|
|
@@ -11682,7 +11794,7 @@ function ChatTranscript({
|
|
|
11682
11794
|
seen.current = messages.length;
|
|
11683
11795
|
}
|
|
11684
11796
|
};
|
|
11685
|
-
|
|
11797
|
+
React60.useLayoutEffect(() => {
|
|
11686
11798
|
const el = scroller.current;
|
|
11687
11799
|
if (!el) return;
|
|
11688
11800
|
if (stick.current) {
|
|
@@ -11690,7 +11802,7 @@ function ChatTranscript({
|
|
|
11690
11802
|
seen.current = messages.length;
|
|
11691
11803
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
11692
11804
|
}, [messages]);
|
|
11693
|
-
|
|
11805
|
+
React60.useEffect(() => {
|
|
11694
11806
|
const el = scroller.current;
|
|
11695
11807
|
const inner = el && el.firstChild;
|
|
11696
11808
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -11700,7 +11812,7 @@ function ChatTranscript({
|
|
|
11700
11812
|
ro.observe(inner);
|
|
11701
11813
|
return () => ro.disconnect();
|
|
11702
11814
|
}, []);
|
|
11703
|
-
const groups =
|
|
11815
|
+
const groups = React60.useMemo(() => groupMessages(messages), [messages]);
|
|
11704
11816
|
const empty = !messages.length && status === "ready";
|
|
11705
11817
|
return /* @__PURE__ */ jsxs82("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
11706
11818
|
/* @__PURE__ */ jsxs82("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
@@ -11724,7 +11836,7 @@ function ChatTranscript({
|
|
|
11724
11836
|
const prev = groups[i - 1];
|
|
11725
11837
|
const k = dayKey(g.messages[0].timestamp);
|
|
11726
11838
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
11727
|
-
return /* @__PURE__ */ jsxs82(
|
|
11839
|
+
return /* @__PURE__ */ jsxs82(React60.Fragment, { children: [
|
|
11728
11840
|
showDay ? /* @__PURE__ */ jsx88("div", { className: "fdc-day", children: /* @__PURE__ */ jsx88("span", { children: dayLabel(k) }) }) : null,
|
|
11729
11841
|
/* @__PURE__ */ jsx88(ChatTurn, { group: g, ctx })
|
|
11730
11842
|
] }, g.key || i);
|
|
@@ -11741,7 +11853,7 @@ function ChatTranscript({
|
|
|
11741
11853
|
var TranscriptKit = { groupMessages };
|
|
11742
11854
|
|
|
11743
11855
|
// src/components/chat/ChatComposer.tsx
|
|
11744
|
-
import * as
|
|
11856
|
+
import * as React61 from "react";
|
|
11745
11857
|
import { jsx as jsx89, jsxs as jsxs83 } from "react/jsx-runtime";
|
|
11746
11858
|
function ChatComposer({
|
|
11747
11859
|
onSubmit,
|
|
@@ -11769,17 +11881,17 @@ function ChatComposer({
|
|
|
11769
11881
|
onReject,
|
|
11770
11882
|
onOpenAttachment
|
|
11771
11883
|
}) {
|
|
11772
|
-
const [text, setText] =
|
|
11773
|
-
const [trigger, setTrigger] =
|
|
11774
|
-
const [mentionItems, setMentionItems] =
|
|
11775
|
-
const [listening, setListening] =
|
|
11776
|
-
const [notice, setNotice] =
|
|
11777
|
-
const editor =
|
|
11778
|
-
const wrap =
|
|
11779
|
-
const stopVoice =
|
|
11884
|
+
const [text, setText] = React61.useState(draft || "");
|
|
11885
|
+
const [trigger, setTrigger] = React61.useState(null);
|
|
11886
|
+
const [mentionItems, setMentionItems] = React61.useState([]);
|
|
11887
|
+
const [listening, setListening] = React61.useState(false);
|
|
11888
|
+
const [notice, setNotice] = React61.useState(null);
|
|
11889
|
+
const editor = React61.useRef(null);
|
|
11890
|
+
const wrap = React61.useRef(null);
|
|
11891
|
+
const stopVoice = React61.useRef(null);
|
|
11780
11892
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
11781
11893
|
} });
|
|
11782
|
-
|
|
11894
|
+
React61.useEffect(() => {
|
|
11783
11895
|
if (draft != null && draft !== text) setText(draft);
|
|
11784
11896
|
}, [draft]);
|
|
11785
11897
|
const change = (v) => {
|
|
@@ -11815,7 +11927,7 @@ function ChatComposer({
|
|
|
11815
11927
|
e.preventDefault();
|
|
11816
11928
|
staged.add(found.files);
|
|
11817
11929
|
};
|
|
11818
|
-
|
|
11930
|
+
React61.useEffect(() => {
|
|
11819
11931
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
11820
11932
|
setMentionItems([]);
|
|
11821
11933
|
return;
|
|
@@ -11833,7 +11945,7 @@ function ChatComposer({
|
|
|
11833
11945
|
const q = (trigger.query || "").toLowerCase();
|
|
11834
11946
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
11835
11947
|
}, [trigger, mentionSources]);
|
|
11836
|
-
const slashItems =
|
|
11948
|
+
const slashItems = React61.useMemo(() => {
|
|
11837
11949
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
11838
11950
|
const q = (trigger.query || "").toLowerCase();
|
|
11839
11951
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -12007,12 +12119,12 @@ function ChatComposer({
|
|
|
12007
12119
|
}
|
|
12008
12120
|
|
|
12009
12121
|
// src/components/chat/ChatSessionBar.tsx
|
|
12010
|
-
import * as
|
|
12122
|
+
import * as React62 from "react";
|
|
12011
12123
|
import { jsx as jsx90, jsxs as jsxs84 } from "react/jsx-runtime";
|
|
12012
12124
|
var compact2 = meterFormats.compact;
|
|
12013
12125
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
12014
|
-
const [open, setOpen] =
|
|
12015
|
-
const anchor =
|
|
12126
|
+
const [open, setOpen] = React62.useState(false);
|
|
12127
|
+
const anchor = React62.useRef(null);
|
|
12016
12128
|
const stats = sessionStats || null;
|
|
12017
12129
|
const cu = contextUsage || null;
|
|
12018
12130
|
const limits = usageLimits || null;
|
|
@@ -12027,7 +12139,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12027
12139
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
12028
12140
|
if (cu) bits.push(pct + "% context");
|
|
12029
12141
|
const expandable = !!(cu || limits);
|
|
12030
|
-
return /* @__PURE__ */ jsxs84(
|
|
12142
|
+
return /* @__PURE__ */ jsxs84(React62.Fragment, { children: [
|
|
12031
12143
|
/* @__PURE__ */ jsxs84("div", { className: "fdc-bar", children: [
|
|
12032
12144
|
/* @__PURE__ */ jsxs84(
|
|
12033
12145
|
"button",
|
|
@@ -12168,7 +12280,7 @@ function ModelControls({
|
|
|
12168
12280
|
] })
|
|
12169
12281
|
});
|
|
12170
12282
|
}
|
|
12171
|
-
return /* @__PURE__ */ jsxs84(
|
|
12283
|
+
return /* @__PURE__ */ jsxs84(React62.Fragment, { children: [
|
|
12172
12284
|
/* @__PURE__ */ jsx90(
|
|
12173
12285
|
MenuButton,
|
|
12174
12286
|
{
|
|
@@ -12285,11 +12397,11 @@ function AgentChatPanel({
|
|
|
12285
12397
|
onFeedback,
|
|
12286
12398
|
onEditMessage
|
|
12287
12399
|
}) {
|
|
12288
|
-
const [panelWidth, setPanelWidth] =
|
|
12289
|
-
const [applied, setApplied] =
|
|
12290
|
-
const [draft, setDraft] =
|
|
12291
|
-
const dragging =
|
|
12292
|
-
|
|
12400
|
+
const [panelWidth, setPanelWidth] = React63.useState(width);
|
|
12401
|
+
const [applied, setApplied] = React63.useState({});
|
|
12402
|
+
const [draft, setDraft] = React63.useState("");
|
|
12403
|
+
const dragging = React63.useRef(null);
|
|
12404
|
+
React63.useEffect(() => setPanelWidth(width), [width]);
|
|
12293
12405
|
const engine = useChatEngine({
|
|
12294
12406
|
contextType,
|
|
12295
12407
|
contextId,
|
|
@@ -12493,7 +12605,7 @@ function AgentChatPanel({
|
|
|
12493
12605
|
}
|
|
12494
12606
|
|
|
12495
12607
|
// src/components/files/FileViewer.tsx
|
|
12496
|
-
import * as
|
|
12608
|
+
import * as React64 from "react";
|
|
12497
12609
|
import { jsx as jsx92, jsxs as jsxs86 } from "react/jsx-runtime";
|
|
12498
12610
|
function previewKindOf(file) {
|
|
12499
12611
|
const mime = (file.mime || "").toLowerCase();
|
|
@@ -12550,13 +12662,13 @@ function parseDelimited(text, delimiter) {
|
|
|
12550
12662
|
return rows;
|
|
12551
12663
|
}
|
|
12552
12664
|
function usePreview(file, kind, resolveUrl) {
|
|
12553
|
-
const [state, setState] =
|
|
12554
|
-
const [attempt, setAttempt] =
|
|
12555
|
-
const resolveRef =
|
|
12556
|
-
|
|
12665
|
+
const [state, setState] = React64.useState({ status: "loading" });
|
|
12666
|
+
const [attempt, setAttempt] = React64.useState(0);
|
|
12667
|
+
const resolveRef = React64.useRef(resolveUrl);
|
|
12668
|
+
React64.useEffect(() => {
|
|
12557
12669
|
resolveRef.current = resolveUrl;
|
|
12558
12670
|
}, [resolveUrl]);
|
|
12559
|
-
|
|
12671
|
+
React64.useEffect(() => {
|
|
12560
12672
|
if (kind === "none") {
|
|
12561
12673
|
setState({ status: "ready" });
|
|
12562
12674
|
return;
|
|
@@ -12586,7 +12698,7 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
12586
12698
|
if (ac) ac.abort();
|
|
12587
12699
|
};
|
|
12588
12700
|
}, [file.id, kind, attempt]);
|
|
12589
|
-
return { ...state, retry:
|
|
12701
|
+
return { ...state, retry: React64.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
12590
12702
|
}
|
|
12591
12703
|
function PreviewBody({ file, kind, state }) {
|
|
12592
12704
|
if (kind === "image") return /* @__PURE__ */ jsx92("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
@@ -12631,13 +12743,13 @@ function PreviewBody({ file, kind, state }) {
|
|
|
12631
12743
|
] });
|
|
12632
12744
|
}
|
|
12633
12745
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
12634
|
-
const kind =
|
|
12746
|
+
const kind = React64.useMemo(() => previewKindOf(file), [file]);
|
|
12635
12747
|
const preview = usePreview(file, kind, resolveUrl);
|
|
12636
|
-
const [tab, setTab] =
|
|
12637
|
-
const [downloading, setDownloading] =
|
|
12638
|
-
const [downloadError, setDownloadError] =
|
|
12748
|
+
const [tab, setTab] = React64.useState("preview");
|
|
12749
|
+
const [downloading, setDownloading] = React64.useState(false);
|
|
12750
|
+
const [downloadError, setDownloadError] = React64.useState(null);
|
|
12639
12751
|
const hasSide = sidePanel != null;
|
|
12640
|
-
|
|
12752
|
+
React64.useEffect(() => {
|
|
12641
12753
|
setTab("preview");
|
|
12642
12754
|
}, [file.id]);
|
|
12643
12755
|
const download = () => {
|
|
@@ -12704,7 +12816,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
12704
12816
|
}
|
|
12705
12817
|
|
|
12706
12818
|
// src/components/files/FileBrowser.tsx
|
|
12707
|
-
import * as
|
|
12819
|
+
import * as React65 from "react";
|
|
12708
12820
|
import { Fragment as Fragment27, jsx as jsx93, jsxs as jsxs87 } from "react/jsx-runtime";
|
|
12709
12821
|
function childrenOf(folders, parentId) {
|
|
12710
12822
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -12775,10 +12887,10 @@ function FolderPickerMenu({
|
|
|
12775
12887
|
destinations,
|
|
12776
12888
|
onPick
|
|
12777
12889
|
}) {
|
|
12778
|
-
const [open, setOpen] =
|
|
12890
|
+
const [open, setOpen] = React65.useState(false);
|
|
12779
12891
|
const zIndex = useOverlayLayer(open);
|
|
12780
|
-
const ref =
|
|
12781
|
-
|
|
12892
|
+
const ref = React65.useRef(null);
|
|
12893
|
+
React65.useEffect(() => {
|
|
12782
12894
|
if (!open) return;
|
|
12783
12895
|
const away = (e) => {
|
|
12784
12896
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -12830,8 +12942,8 @@ function FolderPickerMenu({
|
|
|
12830
12942
|
] });
|
|
12831
12943
|
}
|
|
12832
12944
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
12833
|
-
const [over, setOver] =
|
|
12834
|
-
const dragCounter =
|
|
12945
|
+
const [over, setOver] = React65.useState(false);
|
|
12946
|
+
const dragCounter = React65.useRef(0);
|
|
12835
12947
|
const dropHandlers = isDropTarget ? {
|
|
12836
12948
|
onDragEnter: (e) => {
|
|
12837
12949
|
if (!hasInternalPayload(e)) return;
|
|
@@ -12879,8 +12991,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
12879
12991
|
}
|
|
12880
12992
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
12881
12993
|
const kids = childrenOf(folders, folder.id);
|
|
12882
|
-
const [expanded, setExpanded] =
|
|
12883
|
-
|
|
12994
|
+
const [expanded, setExpanded] = React65.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
12995
|
+
React65.useEffect(() => {
|
|
12884
12996
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
12885
12997
|
}, [currentFolderId, folder.id, folders]);
|
|
12886
12998
|
const isCurrent = folder.id === currentFolderId;
|
|
@@ -12946,15 +13058,15 @@ function FileBrowser({
|
|
|
12946
13058
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
12947
13059
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
12948
13060
|
const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
|
|
12949
|
-
const [createOpen, setCreateOpen] =
|
|
12950
|
-
const [createName, setCreateName] =
|
|
12951
|
-
const [renameTarget, setRenameTarget] =
|
|
12952
|
-
const [renameValue, setRenameValue] =
|
|
12953
|
-
const [deleteTarget, setDeleteTarget] =
|
|
12954
|
-
const uploadInputRef =
|
|
12955
|
-
const crumbFolders =
|
|
12956
|
-
const subfolders =
|
|
12957
|
-
const currentFiles =
|
|
13061
|
+
const [createOpen, setCreateOpen] = React65.useState(false);
|
|
13062
|
+
const [createName, setCreateName] = React65.useState("");
|
|
13063
|
+
const [renameTarget, setRenameTarget] = React65.useState(null);
|
|
13064
|
+
const [renameValue, setRenameValue] = React65.useState("");
|
|
13065
|
+
const [deleteTarget, setDeleteTarget] = React65.useState(null);
|
|
13066
|
+
const uploadInputRef = React65.useRef(null);
|
|
13067
|
+
const crumbFolders = React65.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
13068
|
+
const subfolders = React65.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
13069
|
+
const currentFiles = React65.useMemo(
|
|
12958
13070
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
12959
13071
|
[files, currentFolderId]
|
|
12960
13072
|
);
|
|
@@ -13186,8 +13298,8 @@ function BreadcrumbCrumb({
|
|
|
13186
13298
|
isDropTarget,
|
|
13187
13299
|
onDropPayload
|
|
13188
13300
|
}) {
|
|
13189
|
-
const [over, setOver] =
|
|
13190
|
-
const dragCounter =
|
|
13301
|
+
const [over, setOver] = React65.useState(false);
|
|
13302
|
+
const dragCounter = React65.useRef(0);
|
|
13191
13303
|
const dropHandlers = isDropTarget ? {
|
|
13192
13304
|
onDragEnter: (e) => {
|
|
13193
13305
|
if (!hasInternalPayload(e)) return;
|
|
@@ -13216,7 +13328,7 @@ function BreadcrumbCrumb({
|
|
|
13216
13328
|
}
|
|
13217
13329
|
|
|
13218
13330
|
// src/kits/query.ts
|
|
13219
|
-
import * as
|
|
13331
|
+
import * as React66 from "react";
|
|
13220
13332
|
var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
|
|
13221
13333
|
var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
|
|
13222
13334
|
var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
|
|
@@ -13271,22 +13383,22 @@ function compare(a, b, dir) {
|
|
|
13271
13383
|
var API = null;
|
|
13272
13384
|
var PREFS = null;
|
|
13273
13385
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
13274
|
-
const [query, setQuery] =
|
|
13386
|
+
const [query, setQuery] = React66.useState(() => {
|
|
13275
13387
|
const store = PREFS || window.PlannerPrefs;
|
|
13276
13388
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
13277
13389
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
13278
13390
|
});
|
|
13279
|
-
const savePref =
|
|
13391
|
+
const savePref = React66.useCallback((patch2) => {
|
|
13280
13392
|
const store = PREFS || window.PlannerPrefs;
|
|
13281
13393
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
13282
13394
|
}, [prefsKey]);
|
|
13283
|
-
const [res, setRes] =
|
|
13284
|
-
const [loading, setLoading] =
|
|
13285
|
-
const seq2 =
|
|
13395
|
+
const [res, setRes] = React66.useState(null);
|
|
13396
|
+
const [loading, setLoading] = React66.useState(true);
|
|
13397
|
+
const seq2 = React66.useRef(0);
|
|
13286
13398
|
const depKey = (deps || []).join("|");
|
|
13287
13399
|
const paramKey = JSON.stringify(params || {});
|
|
13288
13400
|
const queryKey = JSON.stringify(query);
|
|
13289
|
-
|
|
13401
|
+
React66.useEffect(() => {
|
|
13290
13402
|
const id = ++seq2.current;
|
|
13291
13403
|
setLoading(true);
|
|
13292
13404
|
const t = setTimeout(() => {
|
|
@@ -13605,12 +13717,12 @@ function createVersionStore(initialState, options) {
|
|
|
13605
13717
|
}
|
|
13606
13718
|
|
|
13607
13719
|
// src/kits/documentTitle.ts
|
|
13608
|
-
import * as
|
|
13720
|
+
import * as React67 from "react";
|
|
13609
13721
|
function formatDocumentTitle(routeTitle, appName) {
|
|
13610
13722
|
return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
|
|
13611
13723
|
}
|
|
13612
13724
|
function useDocumentTitle(routeTitle, appName) {
|
|
13613
|
-
|
|
13725
|
+
React67.useEffect(() => {
|
|
13614
13726
|
if (typeof document === "undefined") return;
|
|
13615
13727
|
document.title = formatDocumentTitle(routeTitle, appName);
|
|
13616
13728
|
}, [routeTitle, appName]);
|