@flytedan/flytebot-design-system 0.33.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -2
- package/dist/index.cjs +448 -390
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -8
- package/dist/index.d.ts +21 -8
- package/dist/index.js +448 -390
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2971,10 +2971,10 @@ function DataTable({
|
|
|
2971
2971
|
}
|
|
2972
2972
|
|
|
2973
2973
|
// src/components/data/FilterBar.tsx
|
|
2974
|
-
var
|
|
2974
|
+
var React25 = __toESM(require("react"), 1);
|
|
2975
2975
|
|
|
2976
2976
|
// src/components/forms/NumberInput.tsx
|
|
2977
|
-
var
|
|
2977
|
+
var React22 = __toESM(require("react"), 1);
|
|
2978
2978
|
|
|
2979
2979
|
// src/components/forms/field.tsx
|
|
2980
2980
|
var React20 = __toESM(require("react"), 1);
|
|
@@ -2995,6 +2995,16 @@ function useTriggerLabelling(label, id) {
|
|
|
2995
2995
|
return { fieldId, labelId, ariaLabelledBy: label ? labelId + " " + fieldId : void 0 };
|
|
2996
2996
|
}
|
|
2997
2997
|
|
|
2998
|
+
// src/components/useLatest.ts
|
|
2999
|
+
var React21 = __toESM(require("react"), 1);
|
|
3000
|
+
function useLatest(value) {
|
|
3001
|
+
const ref = React21.useRef(value);
|
|
3002
|
+
React21.useInsertionEffect(() => {
|
|
3003
|
+
ref.current = value;
|
|
3004
|
+
});
|
|
3005
|
+
return ref;
|
|
3006
|
+
}
|
|
3007
|
+
|
|
2998
3008
|
// src/components/forms/NumberInput.tsx
|
|
2999
3009
|
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
3000
3010
|
var HOLD_DELAY_MS = 400;
|
|
@@ -3072,24 +3082,22 @@ function NumberInput({
|
|
|
3072
3082
|
const n = typeof v === "number" ? v : parseNumberText(v);
|
|
3073
3083
|
return n == null || Number.isNaN(n) ? null : n;
|
|
3074
3084
|
};
|
|
3075
|
-
const [text, setText] =
|
|
3076
|
-
const [editing, setEditing] =
|
|
3085
|
+
const [text, setText] = React22.useState(() => toText(value));
|
|
3086
|
+
const [editing, setEditing] = React22.useState(false);
|
|
3077
3087
|
const parsed = parseNumberText(text);
|
|
3078
3088
|
const invalidMessage = parsed == null ? null : Number.isNaN(parsed) ? "Enter a number" : integer && !Number.isInteger(parsed) ? "Enter a whole number" : parsed < lo ? "Must be \u2265 " + lo : parsed > hi ? "Must be \u2264 " + hi : null;
|
|
3079
3089
|
const valid = invalidMessage == null;
|
|
3080
|
-
const committedRef =
|
|
3081
|
-
const onChangeRef =
|
|
3082
|
-
|
|
3083
|
-
const
|
|
3084
|
-
|
|
3085
|
-
const focusedRef = React21.useRef(false);
|
|
3086
|
-
React21.useEffect(() => {
|
|
3090
|
+
const committedRef = React22.useRef(toNumber(value));
|
|
3091
|
+
const onChangeRef = useLatest(onChange);
|
|
3092
|
+
const onValidityChangeRef = useLatest(onValidityChange);
|
|
3093
|
+
const focusedRef = React22.useRef(false);
|
|
3094
|
+
React22.useEffect(() => {
|
|
3087
3095
|
committedRef.current = toNumber(value);
|
|
3088
3096
|
if (!focusedRef.current) setText(toText(value));
|
|
3089
3097
|
}, [value]);
|
|
3090
|
-
|
|
3098
|
+
React22.useLayoutEffect(() => {
|
|
3091
3099
|
onValidityChangeRef.current?.(valid);
|
|
3092
|
-
}, [valid]);
|
|
3100
|
+
}, [valid, onValidityChangeRef]);
|
|
3093
3101
|
const fire = (n) => {
|
|
3094
3102
|
committedRef.current = n ?? null;
|
|
3095
3103
|
onChangeRef.current?.({ target: { value: n } });
|
|
@@ -3102,9 +3110,8 @@ function NumberInput({
|
|
|
3102
3110
|
fire(next);
|
|
3103
3111
|
return true;
|
|
3104
3112
|
};
|
|
3105
|
-
const bumpRef =
|
|
3106
|
-
|
|
3107
|
-
const holdTimer = React21.useRef(null);
|
|
3113
|
+
const bumpRef = useLatest(bump);
|
|
3114
|
+
const holdTimer = React22.useRef(null);
|
|
3108
3115
|
const release = () => {
|
|
3109
3116
|
if (holdTimer.current) clearTimeout(holdTimer.current);
|
|
3110
3117
|
holdTimer.current = null;
|
|
@@ -3123,7 +3130,7 @@ function NumberInput({
|
|
|
3123
3130
|
};
|
|
3124
3131
|
holdTimer.current = setTimeout(tick, HOLD_DELAY_MS);
|
|
3125
3132
|
};
|
|
3126
|
-
|
|
3133
|
+
React22.useEffect(() => () => {
|
|
3127
3134
|
if (holdTimer.current) clearTimeout(holdTimer.current);
|
|
3128
3135
|
}, []);
|
|
3129
3136
|
const current2 = committedRef.current;
|
|
@@ -3226,7 +3233,7 @@ function NumberInput({
|
|
|
3226
3233
|
}
|
|
3227
3234
|
|
|
3228
3235
|
// src/components/forms/DatePicker.tsx
|
|
3229
|
-
var
|
|
3236
|
+
var React23 = __toESM(require("react"), 1);
|
|
3230
3237
|
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
3231
3238
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
3232
3239
|
var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
@@ -3244,10 +3251,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3244
3251
|
const today = /* @__PURE__ */ new Date();
|
|
3245
3252
|
const sel = range ? value || {} : { start: value, end: value };
|
|
3246
3253
|
const anchor = parse(sel.start) || parse(initialMonth) || today;
|
|
3247
|
-
const [vy, setVy] =
|
|
3248
|
-
const [vm, setVm] =
|
|
3249
|
-
const [mode2, setMode] =
|
|
3250
|
-
const [hover, setHover] =
|
|
3254
|
+
const [vy, setVy] = React23.useState(anchor.getFullYear());
|
|
3255
|
+
const [vm, setVm] = React23.useState(anchor.getMonth());
|
|
3256
|
+
const [mode2, setMode] = React23.useState("days");
|
|
3257
|
+
const [hover, setHover] = React23.useState(null);
|
|
3251
3258
|
const s = parse(sel.start), e = parse(sel.end);
|
|
3252
3259
|
const hoverEnd = range && s && !e && hover ? parse(hover) : null;
|
|
3253
3260
|
const inRange = (d) => {
|
|
@@ -3363,9 +3370,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3363
3370
|
}
|
|
3364
3371
|
function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, ...rest }) {
|
|
3365
3372
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
3366
|
-
const [open, setOpen] =
|
|
3367
|
-
const rootRef =
|
|
3368
|
-
const boxRef =
|
|
3373
|
+
const [open, setOpen] = React23.useState(false);
|
|
3374
|
+
const rootRef = React23.useRef(null);
|
|
3375
|
+
const boxRef = React23.useRef(null);
|
|
3369
3376
|
const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
|
|
3370
3377
|
const toggle = () => {
|
|
3371
3378
|
if (!disabled) setOpen(!open);
|
|
@@ -3443,9 +3450,9 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
|
|
|
3443
3450
|
}
|
|
3444
3451
|
|
|
3445
3452
|
// src/components/forms/listbox.ts
|
|
3446
|
-
var
|
|
3453
|
+
var React24 = __toESM(require("react"), 1);
|
|
3447
3454
|
function useListboxNav({ count, onSelect }) {
|
|
3448
|
-
const [active, setActive] =
|
|
3455
|
+
const [active, setActive] = React24.useState(-1);
|
|
3449
3456
|
return {
|
|
3450
3457
|
active,
|
|
3451
3458
|
setActive,
|
|
@@ -3458,7 +3465,7 @@ function useListboxNav({ count, onSelect }) {
|
|
|
3458
3465
|
};
|
|
3459
3466
|
}
|
|
3460
3467
|
function useListboxScrollIntoView(active, listRef, enabled) {
|
|
3461
|
-
|
|
3468
|
+
React24.useEffect(() => {
|
|
3462
3469
|
if (!enabled || active < 0 || !listRef.current) return;
|
|
3463
3470
|
const list = listRef.current;
|
|
3464
3471
|
const el = list.querySelector('[data-i="' + active + '"]');
|
|
@@ -3645,40 +3652,40 @@ function MultiSelectPanel({
|
|
|
3645
3652
|
onClose
|
|
3646
3653
|
}) {
|
|
3647
3654
|
const allowedOps = operatorsFor(field);
|
|
3648
|
-
const [draftOperator, setDraftOperator] =
|
|
3655
|
+
const [draftOperator, setDraftOperator] = React25.useState(value?.operator ?? allowedOps[0]);
|
|
3649
3656
|
const operator = allowedOps.length === 1 ? allowedOps[0] : value?.operator ?? draftOperator;
|
|
3650
3657
|
const selected = value?.values ?? [];
|
|
3651
|
-
const selectedRef =
|
|
3652
|
-
|
|
3653
|
-
const
|
|
3654
|
-
|
|
3655
|
-
const mountedRef = React24.useRef(true);
|
|
3656
|
-
React24.useEffect(() => {
|
|
3658
|
+
const selectedRef = useLatest(selected);
|
|
3659
|
+
const operatorRef = useLatest(operator);
|
|
3660
|
+
const mountedRef = React25.useRef(true);
|
|
3661
|
+
React25.useEffect(() => {
|
|
3657
3662
|
mountedRef.current = true;
|
|
3658
3663
|
return () => {
|
|
3659
3664
|
mountedRef.current = false;
|
|
3660
3665
|
};
|
|
3661
3666
|
}, []);
|
|
3662
|
-
const commit = (nextValues, nextOperator =
|
|
3667
|
+
const commit = (nextValues, nextOperator = operatorRef.current) => {
|
|
3668
|
+
setDraftOperator(nextOperator);
|
|
3669
|
+
return onCommit({ operator: nextOperator, values: nextValues });
|
|
3670
|
+
};
|
|
3663
3671
|
const setOperator = (op) => {
|
|
3664
|
-
setDraftOperator(op);
|
|
3665
3672
|
if (selectedRef.current.length > 0) commit(selectedRef.current, op);
|
|
3673
|
+
else setDraftOperator(op);
|
|
3666
3674
|
};
|
|
3667
|
-
const [mode2, setMode] =
|
|
3668
|
-
const [query, setQuery] =
|
|
3669
|
-
const [asyncState, setAsyncState] =
|
|
3675
|
+
const [mode2, setMode] = React25.useState("search");
|
|
3676
|
+
const [query, setQuery] = React25.useState("");
|
|
3677
|
+
const [asyncState, setAsyncState] = React25.useState(
|
|
3670
3678
|
{ options: null, loading: !!field.loadOptions, error: false }
|
|
3671
3679
|
);
|
|
3672
|
-
const [retryTick, setRetryTick] =
|
|
3673
|
-
const inputRef =
|
|
3674
|
-
const listRef =
|
|
3675
|
-
const listId =
|
|
3676
|
-
const loadOptionsRef =
|
|
3677
|
-
|
|
3678
|
-
React24.useEffect(() => {
|
|
3680
|
+
const [retryTick, setRetryTick] = React25.useState(0);
|
|
3681
|
+
const inputRef = React25.useRef(null);
|
|
3682
|
+
const listRef = React25.useRef(null);
|
|
3683
|
+
const listId = React25.useId();
|
|
3684
|
+
const loadOptionsRef = useLatest(field.loadOptions);
|
|
3685
|
+
React25.useEffect(() => {
|
|
3679
3686
|
inputRef.current?.focus();
|
|
3680
3687
|
}, []);
|
|
3681
|
-
|
|
3688
|
+
React25.useEffect(() => {
|
|
3682
3689
|
const load = loadOptionsRef.current;
|
|
3683
3690
|
if (!load) return;
|
|
3684
3691
|
const controller = new AbortController();
|
|
@@ -3696,7 +3703,7 @@ function MultiSelectPanel({
|
|
|
3696
3703
|
clearTimeout(t);
|
|
3697
3704
|
controller.abort();
|
|
3698
3705
|
};
|
|
3699
|
-
}, [query, retryTick]);
|
|
3706
|
+
}, [query, retryTick, loadOptionsRef]);
|
|
3700
3707
|
const options = field.loadOptions ? asyncState.options ?? [] : (field.options ?? []).filter((o) => o.label.toLowerCase().includes(query.toLowerCase()));
|
|
3701
3708
|
const showLoading = !!field.loadOptions && asyncState.loading;
|
|
3702
3709
|
const showError = !!field.loadOptions && asyncState.error;
|
|
@@ -3711,17 +3718,17 @@ function MultiSelectPanel({
|
|
|
3711
3718
|
};
|
|
3712
3719
|
const nav = useListboxNav({ count: options.length, onSelect: (i) => toggle(options[i]) });
|
|
3713
3720
|
useListboxScrollIntoView(nav.active, listRef, hasListbox);
|
|
3714
|
-
|
|
3721
|
+
React25.useEffect(() => {
|
|
3715
3722
|
nav.setActive(0);
|
|
3716
3723
|
}, [query, options.length]);
|
|
3717
3724
|
const activeId = hasListbox && options[nav.active] ? listId + "-opt-" + nav.active : void 0;
|
|
3718
3725
|
const liveMessage = showLoading ? "Loading\u2026" : showError ? "Couldn't load options." : options.length === 0 ? "No matches" : atLimit ? "Limit reached: at most " + field.maxValues + " values" : "";
|
|
3719
|
-
const [pasteText, setPasteText] =
|
|
3720
|
-
const [pasteLoading, setPasteLoading] =
|
|
3721
|
-
const [unmatchedTokens, setUnmatchedTokens] =
|
|
3722
|
-
const [pasteError, setPasteError] =
|
|
3723
|
-
const pasteWrapRef =
|
|
3724
|
-
|
|
3726
|
+
const [pasteText, setPasteText] = React25.useState("");
|
|
3727
|
+
const [pasteLoading, setPasteLoading] = React25.useState(false);
|
|
3728
|
+
const [unmatchedTokens, setUnmatchedTokens] = React25.useState([]);
|
|
3729
|
+
const [pasteError, setPasteError] = React25.useState(null);
|
|
3730
|
+
const pasteWrapRef = React25.useRef(null);
|
|
3731
|
+
React25.useEffect(() => {
|
|
3725
3732
|
if (mode2 === "paste") pasteWrapRef.current?.querySelector("textarea")?.focus();
|
|
3726
3733
|
}, [mode2]);
|
|
3727
3734
|
const doResolve = () => {
|
|
@@ -3740,7 +3747,7 @@ function MultiSelectPanel({
|
|
|
3740
3747
|
setPasteError("This filter allows at most " + field.maxValues + " values; adding this list would make " + merged.size + ".");
|
|
3741
3748
|
return;
|
|
3742
3749
|
}
|
|
3743
|
-
const applied = commit(Array.from(merged.values())
|
|
3750
|
+
const applied = commit(Array.from(merged.values()));
|
|
3744
3751
|
if (!applied.ok) {
|
|
3745
3752
|
setPasteError(applied.reason);
|
|
3746
3753
|
return;
|
|
@@ -3882,10 +3889,9 @@ function MultiSelectPanel({
|
|
|
3882
3889
|
);
|
|
3883
3890
|
}
|
|
3884
3891
|
function useTextValidity(onFlip) {
|
|
3885
|
-
const invalidRef =
|
|
3886
|
-
const [, rerender] =
|
|
3887
|
-
const onFlipRef =
|
|
3888
|
-
onFlipRef.current = onFlip;
|
|
3892
|
+
const invalidRef = React25.useRef(/* @__PURE__ */ new Set());
|
|
3893
|
+
const [, rerender] = React25.useReducer((n) => n + 1, 0);
|
|
3894
|
+
const onFlipRef = useLatest(onFlip);
|
|
3889
3895
|
const record = (name, valid) => {
|
|
3890
3896
|
const invalid = invalidRef.current;
|
|
3891
3897
|
if (valid !== invalid.has(name)) return false;
|
|
@@ -3902,6 +3908,12 @@ function useTextValidity(onFlip) {
|
|
|
3902
3908
|
/** For an input that is about to unmount: it has nothing left to show. */
|
|
3903
3909
|
forget: (name) => {
|
|
3904
3910
|
record(name, true);
|
|
3911
|
+
},
|
|
3912
|
+
/** For a panel that is about to remount every input: each reports afresh on mount. */
|
|
3913
|
+
reset: () => {
|
|
3914
|
+
if (invalidRef.current.size === 0) return;
|
|
3915
|
+
invalidRef.current.clear();
|
|
3916
|
+
rerender();
|
|
3905
3917
|
}
|
|
3906
3918
|
};
|
|
3907
3919
|
}
|
|
@@ -3909,6 +3921,26 @@ function applicable(field, candidate, textValid) {
|
|
|
3909
3921
|
if (!textValid || candidate === void 0) return void 0;
|
|
3910
3922
|
return validateFilterValue(field, candidate).ok ? candidate : void 0;
|
|
3911
3923
|
}
|
|
3924
|
+
function sameValue(a, b) {
|
|
3925
|
+
if (a === b) return true;
|
|
3926
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
|
|
3927
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
3928
|
+
const left = a;
|
|
3929
|
+
const right = b;
|
|
3930
|
+
for (const key of /* @__PURE__ */ new Set([...Object.keys(left), ...Object.keys(right)])) {
|
|
3931
|
+
if (!sameValue(left[key], right[key])) return false;
|
|
3932
|
+
}
|
|
3933
|
+
return true;
|
|
3934
|
+
}
|
|
3935
|
+
function useReseedFromProps(value, applies, reseed) {
|
|
3936
|
+
const seen = React25.useRef(value);
|
|
3937
|
+
React25.useLayoutEffect(() => {
|
|
3938
|
+
if (seen.current === value) return;
|
|
3939
|
+
seen.current = value;
|
|
3940
|
+
if (!sameValue(value, applies())) reseed(value);
|
|
3941
|
+
}, [value, applies, reseed]);
|
|
3942
|
+
}
|
|
3943
|
+
var rangeDraft = (value) => ({ min: value?.min, max: value?.max });
|
|
3912
3944
|
function RangePanel({
|
|
3913
3945
|
field,
|
|
3914
3946
|
value,
|
|
@@ -3916,13 +3948,23 @@ function RangePanel({
|
|
|
3916
3948
|
onCommit,
|
|
3917
3949
|
onClose
|
|
3918
3950
|
}) {
|
|
3919
|
-
const [draft, setDraft] =
|
|
3920
|
-
const
|
|
3921
|
-
const
|
|
3951
|
+
const [draft, setDraft] = React25.useState(() => rangeDraft(value));
|
|
3952
|
+
const [seed, setSeed] = React25.useState(0);
|
|
3953
|
+
const draftRef = React25.useRef(draft);
|
|
3954
|
+
const shown = () => {
|
|
3922
3955
|
const { min, max } = draftRef.current;
|
|
3923
|
-
|
|
3956
|
+
return applicable(field, min == null && max == null ? void 0 : { min, max }, validity.allValid());
|
|
3957
|
+
};
|
|
3958
|
+
const publish = () => {
|
|
3959
|
+
onCommit(shown());
|
|
3924
3960
|
};
|
|
3925
3961
|
const validity = useTextValidity(publish);
|
|
3962
|
+
useReseedFromProps(value, shown, (next) => {
|
|
3963
|
+
draftRef.current = rangeDraft(next);
|
|
3964
|
+
setDraft(draftRef.current);
|
|
3965
|
+
validity.reset();
|
|
3966
|
+
setSeed((n) => n + 1);
|
|
3967
|
+
});
|
|
3926
3968
|
const draftMin = draft.min;
|
|
3927
3969
|
const draftMax = draft.max;
|
|
3928
3970
|
const isEmpty = draftMin == null && draftMax == null;
|
|
@@ -3959,7 +4001,8 @@ function RangePanel({
|
|
|
3959
4001
|
placeholder: field.minPlaceholder,
|
|
3960
4002
|
onChange: (e) => apply({ min: e.target.value }),
|
|
3961
4003
|
onValidityChange: validity.report("min")
|
|
3962
|
-
}
|
|
4004
|
+
},
|
|
4005
|
+
"min-" + seed
|
|
3963
4006
|
),
|
|
3964
4007
|
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3965
4008
|
NumberInput,
|
|
@@ -3974,12 +4017,20 @@ function RangePanel({
|
|
|
3974
4017
|
placeholder: field.maxPlaceholder,
|
|
3975
4018
|
onChange: (e) => apply({ max: e.target.value }),
|
|
3976
4019
|
onValidityChange: validity.report("max")
|
|
3977
|
-
}
|
|
4020
|
+
},
|
|
4021
|
+
"max-" + seed
|
|
3978
4022
|
)
|
|
3979
4023
|
] })
|
|
3980
4024
|
}
|
|
3981
4025
|
);
|
|
3982
4026
|
}
|
|
4027
|
+
function dateDraft(field, value) {
|
|
4028
|
+
return {
|
|
4029
|
+
kind: value?.kind ?? "withinDays",
|
|
4030
|
+
days: value?.kind === "withinDays" ? value.days : field.defaultDays ?? 30,
|
|
4031
|
+
between: value?.kind === "between" ? { from: value.from, to: value.to } : { from: "", to: "" }
|
|
4032
|
+
};
|
|
4033
|
+
}
|
|
3983
4034
|
function DatePanel({
|
|
3984
4035
|
field,
|
|
3985
4036
|
value,
|
|
@@ -3987,23 +4038,41 @@ function DatePanel({
|
|
|
3987
4038
|
onCommit,
|
|
3988
4039
|
onClose
|
|
3989
4040
|
}) {
|
|
3990
|
-
const defaultDays = field.defaultDays ?? 30;
|
|
3991
4041
|
const maxDays = effectiveMaxDays(field);
|
|
3992
|
-
const [
|
|
3993
|
-
const [
|
|
3994
|
-
|
|
3995
|
-
);
|
|
3996
|
-
const
|
|
3997
|
-
const [between, setBetween] =
|
|
3998
|
-
|
|
3999
|
-
);
|
|
4042
|
+
const [initial] = React25.useState(() => dateDraft(field, value));
|
|
4043
|
+
const [kind, setKind] = React25.useState(initial.kind);
|
|
4044
|
+
const [daysDraft, setDaysDraft] = React25.useState(initial.days);
|
|
4045
|
+
const daysRef = React25.useRef(daysDraft);
|
|
4046
|
+
const daysConfirmed = React25.useRef(value?.kind === "withinDays");
|
|
4047
|
+
const [between, setBetween] = React25.useState(initial.between);
|
|
4048
|
+
const [seed, setSeed] = React25.useState(0);
|
|
4000
4049
|
const shownWithinDays = () => {
|
|
4001
4050
|
const days = daysRef.current;
|
|
4002
4051
|
return applicable(field, days == null ? void 0 : { kind: "withinDays", days }, validity.allValid());
|
|
4003
4052
|
};
|
|
4004
|
-
const validity = useTextValidity(() =>
|
|
4053
|
+
const validity = useTextValidity(() => {
|
|
4054
|
+
daysConfirmed.current = true;
|
|
4055
|
+
onCommit(shownWithinDays());
|
|
4056
|
+
});
|
|
4057
|
+
const applies = () => {
|
|
4058
|
+
if (kind === "between") {
|
|
4059
|
+
return applicable(field, between.from && between.to ? { kind: "between", ...between } : void 0, true);
|
|
4060
|
+
}
|
|
4061
|
+
return daysConfirmed.current ? shownWithinDays() : void 0;
|
|
4062
|
+
};
|
|
4063
|
+
useReseedFromProps(value, applies, (next) => {
|
|
4064
|
+
const d = dateDraft(field, next);
|
|
4065
|
+
setKind(d.kind);
|
|
4066
|
+
daysRef.current = d.days;
|
|
4067
|
+
daysConfirmed.current = next?.kind === "withinDays";
|
|
4068
|
+
setDaysDraft(d.days);
|
|
4069
|
+
setBetween(d.between);
|
|
4070
|
+
validity.reset();
|
|
4071
|
+
setSeed((n) => n + 1);
|
|
4072
|
+
});
|
|
4005
4073
|
const applyWithinDays = (days) => {
|
|
4006
4074
|
daysRef.current = days;
|
|
4075
|
+
daysConfirmed.current = true;
|
|
4007
4076
|
setDaysDraft(days);
|
|
4008
4077
|
onCommit(shownWithinDays());
|
|
4009
4078
|
};
|
|
@@ -4018,8 +4087,10 @@ function DatePanel({
|
|
|
4018
4087
|
setBetween({ from: "", to: "" });
|
|
4019
4088
|
validity.forget("days");
|
|
4020
4089
|
} else {
|
|
4021
|
-
|
|
4022
|
-
|
|
4090
|
+
const { days } = dateDraft(field, void 0);
|
|
4091
|
+
daysRef.current = days;
|
|
4092
|
+
daysConfirmed.current = false;
|
|
4093
|
+
setDaysDraft(days);
|
|
4023
4094
|
}
|
|
4024
4095
|
onCommit(void 0);
|
|
4025
4096
|
};
|
|
@@ -4067,7 +4138,8 @@ function DatePanel({
|
|
|
4067
4138
|
value: daysDraft ?? "",
|
|
4068
4139
|
onChange: (e) => applyWithinDays(e.target.value),
|
|
4069
4140
|
onValidityChange: validity.report("days")
|
|
4070
|
-
}
|
|
4141
|
+
},
|
|
4142
|
+
"days-" + seed
|
|
4071
4143
|
) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
4072
4144
|
DatePicker,
|
|
4073
4145
|
{
|
|
@@ -4075,30 +4147,23 @@ function DatePanel({
|
|
|
4075
4147
|
label: "Date range",
|
|
4076
4148
|
value: { start: between.from, end: between.to },
|
|
4077
4149
|
onChange: (e) => applyBetween(e.target.value.start || "", e.target.value.end || "")
|
|
4078
|
-
}
|
|
4150
|
+
},
|
|
4151
|
+
"between-" + seed
|
|
4079
4152
|
)
|
|
4080
4153
|
] })
|
|
4081
4154
|
}
|
|
4082
4155
|
);
|
|
4083
4156
|
}
|
|
4084
4157
|
function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align = "left", className = "", ...rest }) {
|
|
4085
|
-
const [panel, setPanel] =
|
|
4086
|
-
const editAnchorRef =
|
|
4087
|
-
const addAnchorRef =
|
|
4088
|
-
const textInputRef =
|
|
4089
|
-
const optionsRef =
|
|
4158
|
+
const [panel, setPanel] = React25.useState(null);
|
|
4159
|
+
const editAnchorRef = React25.useRef(null);
|
|
4160
|
+
const addAnchorRef = React25.useRef(null);
|
|
4161
|
+
const textInputRef = React25.useRef(null);
|
|
4162
|
+
const optionsRef = React25.useRef(null);
|
|
4090
4163
|
if (process.env.NODE_ENV !== "production") {
|
|
4091
4164
|
for (const f of fields) assertValidFieldDefinition(f);
|
|
4092
4165
|
}
|
|
4093
|
-
const latest =
|
|
4094
|
-
const filtersProp = React24.useRef(filters);
|
|
4095
|
-
if (filters !== filtersProp.current) {
|
|
4096
|
-
filtersProp.current = filters;
|
|
4097
|
-
latest.current.filters = filters;
|
|
4098
|
-
}
|
|
4099
|
-
latest.current.fields = fields;
|
|
4100
|
-
latest.current.onFilterChange = onFilterChange;
|
|
4101
|
-
latest.current.onFilterRemove = onFilterRemove;
|
|
4166
|
+
const latest = useLatest({ fields, filters, onFilterChange, onFilterRemove });
|
|
4102
4167
|
const commit = (field, candidate) => {
|
|
4103
4168
|
const current2 = latest.current.fields.find((f) => f.key === field.key);
|
|
4104
4169
|
if (!current2) return { ok: false, reason: "This filter is no longer available" };
|
|
@@ -4107,24 +4172,17 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
4107
4172
|
return { ok: true };
|
|
4108
4173
|
}
|
|
4109
4174
|
const result = validateFilterValue(current2, candidate);
|
|
4110
|
-
if (result.ok)
|
|
4111
|
-
latest.current.filters = { ...latest.current.filters, [current2.key]: candidate };
|
|
4112
|
-
latest.current.onFilterChange(current2.key, candidate);
|
|
4113
|
-
}
|
|
4175
|
+
if (result.ok) latest.current.onFilterChange(current2.key, candidate);
|
|
4114
4176
|
return result;
|
|
4115
4177
|
};
|
|
4116
4178
|
const removeField = (field) => {
|
|
4117
4179
|
const { filters: now, onFilterRemove: remove } = latest.current;
|
|
4118
|
-
if (
|
|
4119
|
-
const next = { ...now };
|
|
4120
|
-
delete next[field.key];
|
|
4121
|
-
latest.current.filters = next;
|
|
4122
|
-
remove(field.key);
|
|
4180
|
+
if (isFieldSet(field, now[field.key])) remove(field.key);
|
|
4123
4181
|
};
|
|
4124
4182
|
const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
|
|
4125
4183
|
const startEditing = (key) => setPanel({ kind: "edit", key });
|
|
4126
4184
|
const closeEditing = () => setPanel(null);
|
|
4127
|
-
|
|
4185
|
+
React25.useEffect(() => {
|
|
4128
4186
|
if (!panel || panel.kind !== "edit") return;
|
|
4129
4187
|
if (editingField?.type === "text") {
|
|
4130
4188
|
textInputRef.current?.focus();
|
|
@@ -4330,7 +4388,7 @@ function StatTile({ label, value, sub, delta, invert = false, loading = false, c
|
|
|
4330
4388
|
}
|
|
4331
4389
|
|
|
4332
4390
|
// src/components/data/CodeBlock.tsx
|
|
4333
|
-
var
|
|
4391
|
+
var React26 = __toESM(require("react"), 1);
|
|
4334
4392
|
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
4335
4393
|
var JS_KW = /^(?:const|let|var|function|return|if|else|for|while|do|new|class|extends|import|from|export|default|await|async|try|catch|finally|throw|typeof|instanceof|of|in|switch|case|break|continue|delete|void|yield|static|get|set|this|super|interface|type|enum|implements|public|private|protected|readonly|abstract|as|satisfies|declare|namespace)$/;
|
|
4336
4394
|
var RULES = {
|
|
@@ -4486,13 +4544,13 @@ function tokenize(src, lang) {
|
|
|
4486
4544
|
return out;
|
|
4487
4545
|
}
|
|
4488
4546
|
function Highlighted({ code, lang }) {
|
|
4489
|
-
const toks =
|
|
4547
|
+
const toks = React26.useMemo(() => tokenize(code, lang), [code, lang]);
|
|
4490
4548
|
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_jsx_runtime47.Fragment, { children: toks.map((tk, i) => tk.c ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "tok-" + tk.c, children: tk.t }, i) : tk.t) });
|
|
4491
4549
|
}
|
|
4492
4550
|
function useCopy() {
|
|
4493
|
-
const [done, setDone] =
|
|
4494
|
-
const timer =
|
|
4495
|
-
|
|
4551
|
+
const [done, setDone] = React26.useState(false);
|
|
4552
|
+
const timer = React26.useRef(null);
|
|
4553
|
+
React26.useEffect(() => () => {
|
|
4496
4554
|
if (timer.current) clearTimeout(timer.current);
|
|
4497
4555
|
}, []);
|
|
4498
4556
|
const copy = (text) => {
|
|
@@ -4528,8 +4586,8 @@ function CodeBlock({
|
|
|
4528
4586
|
actions,
|
|
4529
4587
|
className = ""
|
|
4530
4588
|
}) {
|
|
4531
|
-
const [wrap, setWrap] =
|
|
4532
|
-
const [open, setOpen] =
|
|
4589
|
+
const [wrap, setWrap] = React26.useState(!!wrapDefault);
|
|
4590
|
+
const [open, setOpen] = React26.useState(false);
|
|
4533
4591
|
const [copied, copy] = useCopy();
|
|
4534
4592
|
const body = String(code).replace(/\n$/, "");
|
|
4535
4593
|
const lines = body.split("\n");
|
|
@@ -4558,7 +4616,7 @@ function CodeBlock({
|
|
|
4558
4616
|
] });
|
|
4559
4617
|
}
|
|
4560
4618
|
function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
|
|
4561
|
-
const [open, setOpen] =
|
|
4619
|
+
const [open, setOpen] = React26.useState(false);
|
|
4562
4620
|
const [copied, copy] = useCopy();
|
|
4563
4621
|
const raw = String(diff).replace(/\n$/, "");
|
|
4564
4622
|
const all = raw.split("\n").map((line) => {
|
|
@@ -4604,7 +4662,7 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
|
|
|
4604
4662
|
}
|
|
4605
4663
|
|
|
4606
4664
|
// src/components/data/Markdown.tsx
|
|
4607
|
-
var
|
|
4665
|
+
var React27 = __toESM(require("react"), 1);
|
|
4608
4666
|
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
4609
4667
|
var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
|
|
4610
4668
|
var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
|
|
@@ -4643,7 +4701,7 @@ function inlineNodes(src, ctx, keyBase) {
|
|
|
4643
4701
|
const href = safeHref(g(2));
|
|
4644
4702
|
out.push(href ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("a", { href, title: g(3) || void 0, target: /^https?:/i.test(href) ? "_blank" : void 0, rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: inlineNodes(g(1), ctx, key()) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { children: g(1) }, key()));
|
|
4645
4703
|
} else if (kind === "cite") {
|
|
4646
|
-
out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
4704
|
+
out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(React27.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("sup", { className: "fd-md-cite", children: g(1) }, key()));
|
|
4647
4705
|
} else if (kind === "strongem") out.push(/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("strong", { children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("em", { children: inlineNodes(g(1), ctx, key()) }) }, key()));
|
|
4648
4706
|
else if (kind === "strong") out.push(/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
4649
4707
|
else if (kind === "em") out.push(/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
@@ -4808,7 +4866,7 @@ function Markdown({
|
|
|
4808
4866
|
onLinkClick
|
|
4809
4867
|
}) {
|
|
4810
4868
|
const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
|
|
4811
|
-
const blocks =
|
|
4869
|
+
const blocks = React27.useMemo(() => parseBlocks(source), [source]);
|
|
4812
4870
|
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: ["fd-md", className].filter(Boolean).join(" "), children: renderBlocks(blocks, ctx, "b") });
|
|
4813
4871
|
}
|
|
4814
4872
|
function MarkdownInline({ source = "", className = "", onLinkClick }) {
|
|
@@ -4922,7 +4980,7 @@ function Pagination({
|
|
|
4922
4980
|
}
|
|
4923
4981
|
|
|
4924
4982
|
// src/components/data/RelativeTime.tsx
|
|
4925
|
-
var
|
|
4983
|
+
var React28 = __toESM(require("react"), 1);
|
|
4926
4984
|
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
4927
4985
|
var MIN = 6e4;
|
|
4928
4986
|
var HOUR = 36e5;
|
|
@@ -4974,9 +5032,9 @@ function formatDuration(ms) {
|
|
|
4974
5032
|
return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
|
|
4975
5033
|
}
|
|
4976
5034
|
function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
|
|
4977
|
-
const [, force] =
|
|
5035
|
+
const [, force] = React28.useState(0);
|
|
4978
5036
|
const t = value instanceof Date ? value.getTime() : Date.parse(value);
|
|
4979
|
-
|
|
5037
|
+
React28.useEffect(() => {
|
|
4980
5038
|
if (!refresh2 || !t || isNaN(t)) return;
|
|
4981
5039
|
const abs = Math.abs(t - Date.now());
|
|
4982
5040
|
if (abs > DAY) return;
|
|
@@ -4992,7 +5050,7 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
|
|
|
4992
5050
|
}
|
|
4993
5051
|
|
|
4994
5052
|
// src/components/data/ScoreMeter.tsx
|
|
4995
|
-
var
|
|
5053
|
+
var React29 = __toESM(require("react"), 1);
|
|
4996
5054
|
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
4997
5055
|
function ScoreMeter({
|
|
4998
5056
|
score,
|
|
@@ -5007,10 +5065,10 @@ function ScoreMeter({
|
|
|
5007
5065
|
breakdownWidth = 280,
|
|
5008
5066
|
className = ""
|
|
5009
5067
|
}) {
|
|
5010
|
-
const [open, setOpen] =
|
|
5011
|
-
const ref =
|
|
5068
|
+
const [open, setOpen] = React29.useState(false);
|
|
5069
|
+
const ref = React29.useRef(null);
|
|
5012
5070
|
const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
|
|
5013
|
-
const body = /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
5071
|
+
const body = /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React29.Fragment, { children: [
|
|
5014
5072
|
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-scoremeter-rail", style: { width }, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(SegmentedMeter, { total: 100, segments, height, showTotal: false, showPercent: false, legend: false }) }),
|
|
5015
5073
|
showScore ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
|
|
5016
5074
|
] });
|
|
@@ -5029,7 +5087,7 @@ function ScoreMeter({
|
|
|
5029
5087
|
}
|
|
5030
5088
|
);
|
|
5031
5089
|
}
|
|
5032
|
-
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
5090
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React29.Fragment, { children: [
|
|
5033
5091
|
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
5034
5092
|
"button",
|
|
5035
5093
|
{
|
|
@@ -5060,13 +5118,13 @@ function ScoreMeter({
|
|
|
5060
5118
|
}
|
|
5061
5119
|
|
|
5062
5120
|
// src/components/data/SortMenu.tsx
|
|
5063
|
-
var
|
|
5121
|
+
var React30 = __toESM(require("react"), 1);
|
|
5064
5122
|
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
5065
5123
|
function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", className = "", ...rest }) {
|
|
5066
|
-
const [open, setOpen] =
|
|
5124
|
+
const [open, setOpen] = React30.useState(false);
|
|
5067
5125
|
const zIndex = useOverlayLayer(open);
|
|
5068
|
-
const ref =
|
|
5069
|
-
|
|
5126
|
+
const ref = React30.useRef(null);
|
|
5127
|
+
React30.useEffect(() => {
|
|
5070
5128
|
if (!open) return;
|
|
5071
5129
|
const away = (e) => {
|
|
5072
5130
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -5128,7 +5186,7 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
|
|
|
5128
5186
|
}
|
|
5129
5187
|
|
|
5130
5188
|
// src/components/data/StepList.tsx
|
|
5131
|
-
var
|
|
5189
|
+
var React31 = __toESM(require("react"), 1);
|
|
5132
5190
|
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
5133
5191
|
var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
|
|
5134
5192
|
function StepList({
|
|
@@ -5141,9 +5199,9 @@ function StepList({
|
|
|
5141
5199
|
dense = false,
|
|
5142
5200
|
className = ""
|
|
5143
5201
|
}) {
|
|
5144
|
-
const [openState, setOpenState] =
|
|
5202
|
+
const [openState, setOpenState] = React31.useState(defaultOpen);
|
|
5145
5203
|
const open = openProp == null ? openState : openProp;
|
|
5146
|
-
const [expanded, setExpanded] =
|
|
5204
|
+
const [expanded, setExpanded] = React31.useState({});
|
|
5147
5205
|
if (!steps.length) return null;
|
|
5148
5206
|
const running = steps.some((s) => s.status === "running");
|
|
5149
5207
|
const failed = steps.filter((s) => s.status === "error").length;
|
|
@@ -5201,7 +5259,7 @@ function StepList({
|
|
|
5201
5259
|
}
|
|
5202
5260
|
|
|
5203
5261
|
// src/components/data/VirtualList.tsx
|
|
5204
|
-
var
|
|
5262
|
+
var React32 = __toESM(require("react"), 1);
|
|
5205
5263
|
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
5206
5264
|
var VIRTUAL_LIST_BUFFER_ROWS = 20;
|
|
5207
5265
|
var VIRTUAL_LIST_ROW_GAP = 6;
|
|
@@ -5253,35 +5311,35 @@ function VirtualList({
|
|
|
5253
5311
|
className = "",
|
|
5254
5312
|
style
|
|
5255
5313
|
}) {
|
|
5256
|
-
const [scrollTop, setScrollTop] =
|
|
5257
|
-
const loaded =
|
|
5314
|
+
const [scrollTop, setScrollTop] = React32.useState(0);
|
|
5315
|
+
const loaded = React32.useMemo(
|
|
5258
5316
|
() => ({ firstItemIndex, count: items.length }),
|
|
5259
5317
|
[firstItemIndex, items.length]
|
|
5260
5318
|
);
|
|
5261
5319
|
const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
|
|
5262
5320
|
const bandKey = firstItemIndex + ":" + items.length;
|
|
5263
|
-
const win =
|
|
5321
|
+
const win = React32.useMemo(
|
|
5264
5322
|
() => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
|
|
5265
5323
|
[scrollTop, height, itemHeight, total, loaded]
|
|
5266
5324
|
);
|
|
5267
|
-
const need =
|
|
5325
|
+
const need = React32.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
|
|
5268
5326
|
const wantStart = need.start && hasMore?.start !== false;
|
|
5269
5327
|
const wantEnd = need.end && hasMore?.end !== false;
|
|
5270
5328
|
const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
|
|
5271
5329
|
const askKey = bandKey + "@" + bucket2;
|
|
5272
|
-
const asked =
|
|
5273
|
-
|
|
5330
|
+
const asked = React32.useRef({ start: null, end: null });
|
|
5331
|
+
React32.useEffect(() => {
|
|
5274
5332
|
if (loading || !wantStart || asked.current.start === askKey) return;
|
|
5275
5333
|
asked.current.start = askKey;
|
|
5276
5334
|
onNeedMore("start", win);
|
|
5277
5335
|
}, [wantStart, loading, askKey, onNeedMore, win]);
|
|
5278
|
-
|
|
5336
|
+
React32.useEffect(() => {
|
|
5279
5337
|
if (loading || !wantEnd || asked.current.end === askKey) return;
|
|
5280
5338
|
asked.current.end = askKey;
|
|
5281
5339
|
onNeedMore("end", win);
|
|
5282
5340
|
}, [wantEnd, loading, askKey, onNeedMore, win]);
|
|
5283
|
-
const lastKeysRef =
|
|
5284
|
-
const newKeys =
|
|
5341
|
+
const lastKeysRef = React32.useRef(null);
|
|
5342
|
+
const newKeys = React32.useMemo(() => {
|
|
5285
5343
|
const prev = lastKeysRef.current;
|
|
5286
5344
|
if (!prev) return /* @__PURE__ */ new Set();
|
|
5287
5345
|
const fresh = /* @__PURE__ */ new Set();
|
|
@@ -5291,7 +5349,7 @@ function VirtualList({
|
|
|
5291
5349
|
}
|
|
5292
5350
|
return fresh;
|
|
5293
5351
|
}, [items]);
|
|
5294
|
-
|
|
5352
|
+
React32.useEffect(() => {
|
|
5295
5353
|
lastKeysRef.current = new Set(items.map(keyOf));
|
|
5296
5354
|
}, [items]);
|
|
5297
5355
|
const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
|
|
@@ -5336,7 +5394,7 @@ function VirtualList({
|
|
|
5336
5394
|
}
|
|
5337
5395
|
|
|
5338
5396
|
// src/components/data/EntityRow.tsx
|
|
5339
|
-
var
|
|
5397
|
+
var React33 = __toESM(require("react"), 1);
|
|
5340
5398
|
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
5341
5399
|
var ENTITY_ROW_METRIC_WIDTH = 74;
|
|
5342
5400
|
var METRIC_TONE_COLOR = {
|
|
@@ -5349,7 +5407,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
|
|
|
5349
5407
|
const key = m.id || m.label || i;
|
|
5350
5408
|
const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
|
|
5351
5409
|
const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
|
|
5352
|
-
const content = /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
|
|
5410
|
+
const content = /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(React33.Fragment, { children: [
|
|
5353
5411
|
m.icon ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
|
|
5354
5412
|
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
|
|
5355
5413
|
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-sr", children: " " + m.label })
|
|
@@ -5441,7 +5499,7 @@ function EntityRow({
|
|
|
5441
5499
|
}
|
|
5442
5500
|
|
|
5443
5501
|
// src/components/data/TransferList.tsx
|
|
5444
|
-
var
|
|
5502
|
+
var React34 = __toESM(require("react"), 1);
|
|
5445
5503
|
var import_react_dom5 = require("react-dom");
|
|
5446
5504
|
|
|
5447
5505
|
// src/components/forms/Input.tsx
|
|
@@ -5547,12 +5605,12 @@ function TransferList({
|
|
|
5547
5605
|
listHeight = 440,
|
|
5548
5606
|
className = ""
|
|
5549
5607
|
}) {
|
|
5550
|
-
const [drag, setDrag] =
|
|
5551
|
-
const [dragOverSide, setDragOverSide] =
|
|
5552
|
-
const dragRef =
|
|
5553
|
-
const armedRef =
|
|
5554
|
-
const sideRefs =
|
|
5555
|
-
const hitTestSide =
|
|
5608
|
+
const [drag, setDrag] = React34.useState(null);
|
|
5609
|
+
const [dragOverSide, setDragOverSide] = React34.useState(null);
|
|
5610
|
+
const dragRef = React34.useRef(null);
|
|
5611
|
+
const armedRef = React34.useRef(null);
|
|
5612
|
+
const sideRefs = React34.useRef({ left: null, right: null });
|
|
5613
|
+
const hitTestSide = React34.useCallback((x, y) => {
|
|
5556
5614
|
for (const side of ["left", "right"]) {
|
|
5557
5615
|
const el = sideRefs.current[side];
|
|
5558
5616
|
if (!el) continue;
|
|
@@ -5561,7 +5619,7 @@ function TransferList({
|
|
|
5561
5619
|
}
|
|
5562
5620
|
return null;
|
|
5563
5621
|
}, []);
|
|
5564
|
-
const findItem =
|
|
5622
|
+
const findItem = React34.useCallback(
|
|
5565
5623
|
(side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
|
|
5566
5624
|
[left.items, right.items, keyOf]
|
|
5567
5625
|
);
|
|
@@ -5583,7 +5641,7 @@ function TransferList({
|
|
|
5583
5641
|
height: rect.height
|
|
5584
5642
|
};
|
|
5585
5643
|
};
|
|
5586
|
-
|
|
5644
|
+
React34.useEffect(() => {
|
|
5587
5645
|
const onMovePointer = (e) => {
|
|
5588
5646
|
const armed = armedRef.current;
|
|
5589
5647
|
if (!armed || e.pointerId !== armed.pointerId) return;
|
|
@@ -5636,7 +5694,7 @@ function TransferList({
|
|
|
5636
5694
|
window.removeEventListener("pointercancel", endDrag);
|
|
5637
5695
|
};
|
|
5638
5696
|
}, [hitTestSide, findItem, onMove]);
|
|
5639
|
-
|
|
5697
|
+
React34.useEffect(() => {
|
|
5640
5698
|
if (!drag || typeof document === "undefined") return;
|
|
5641
5699
|
const prev = document.body.style.userSelect;
|
|
5642
5700
|
document.body.style.userSelect = "none";
|
|
@@ -5744,11 +5802,11 @@ function TransferList({
|
|
|
5744
5802
|
}
|
|
5745
5803
|
|
|
5746
5804
|
// src/components/forms/Checkbox.tsx
|
|
5747
|
-
var
|
|
5805
|
+
var React35 = __toESM(require("react"), 1);
|
|
5748
5806
|
var import_jsx_runtime60 = require("react/jsx-runtime");
|
|
5749
5807
|
function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
|
|
5750
|
-
const ref =
|
|
5751
|
-
|
|
5808
|
+
const ref = React35.useRef(null);
|
|
5809
|
+
React35.useEffect(() => {
|
|
5752
5810
|
if (ref.current) ref.current.indeterminate = indeterminate;
|
|
5753
5811
|
}, [indeterminate]);
|
|
5754
5812
|
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
@@ -5792,7 +5850,7 @@ function Switch({ label, description, className = "", ...rest }) {
|
|
|
5792
5850
|
}
|
|
5793
5851
|
|
|
5794
5852
|
// src/components/forms/Select.tsx
|
|
5795
|
-
var
|
|
5853
|
+
var React36 = __toESM(require("react"), 1);
|
|
5796
5854
|
var import_jsx_runtime63 = require("react/jsx-runtime");
|
|
5797
5855
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
5798
5856
|
function Select({
|
|
@@ -5819,12 +5877,12 @@ function Select({
|
|
|
5819
5877
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
5820
5878
|
const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
|
|
5821
5879
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
5822
|
-
const [open, setOpen] =
|
|
5823
|
-
const [q, setQ] =
|
|
5824
|
-
const rootRef =
|
|
5825
|
-
const boxRef =
|
|
5826
|
-
const listRef =
|
|
5827
|
-
const typeBuf =
|
|
5880
|
+
const [open, setOpen] = React36.useState(false);
|
|
5881
|
+
const [q, setQ] = React36.useState("");
|
|
5882
|
+
const rootRef = React36.useRef(null);
|
|
5883
|
+
const boxRef = React36.useRef(null);
|
|
5884
|
+
const listRef = React36.useRef(null);
|
|
5885
|
+
const typeBuf = React36.useRef({ s: "", t: 0 });
|
|
5828
5886
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
5829
5887
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
5830
5888
|
const boxText = multiple ? chosen.length === 0 ? placeholder : chosen.length === 1 ? chosen[0].label : summary ? summary(chosen.map((o) => o.value)) : chosen.length + " selected" : selected ? selected.label : placeholder;
|
|
@@ -5963,7 +6021,7 @@ function Select({
|
|
|
5963
6021
|
),
|
|
5964
6022
|
q ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
5965
6023
|
] }) : void 0,
|
|
5966
|
-
footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
|
|
6024
|
+
footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(React36.Fragment, { children: [
|
|
5967
6025
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
|
|
5968
6026
|
"button",
|
|
5969
6027
|
{
|
|
@@ -5994,7 +6052,7 @@ function Select({
|
|
|
5994
6052
|
'Nothing matches "',
|
|
5995
6053
|
q,
|
|
5996
6054
|
'".'
|
|
5997
|
-
] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
|
|
6055
|
+
] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(React36.Fragment, { children: [
|
|
5998
6056
|
grp.g ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
|
|
5999
6057
|
grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
|
|
6000
6058
|
"button",
|
|
@@ -6031,7 +6089,7 @@ function Select({
|
|
|
6031
6089
|
}
|
|
6032
6090
|
|
|
6033
6091
|
// src/components/forms/TimePicker.tsx
|
|
6034
|
-
var
|
|
6092
|
+
var React37 = __toESM(require("react"), 1);
|
|
6035
6093
|
var import_jsx_runtime64 = require("react/jsx-runtime");
|
|
6036
6094
|
var pad = (n) => String(n).padStart(2, "0");
|
|
6037
6095
|
function ClockFace({ value = "09:00", onChange }) {
|
|
@@ -6040,9 +6098,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
6040
6098
|
if (isNaN(m)) m = 0;
|
|
6041
6099
|
const pm = h24 >= 12;
|
|
6042
6100
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
6043
|
-
const [mode2, setMode] =
|
|
6044
|
-
const faceRef =
|
|
6045
|
-
const dragging =
|
|
6101
|
+
const [mode2, setMode] = React37.useState("h");
|
|
6102
|
+
const faceRef = React37.useRef(null);
|
|
6103
|
+
const dragging = React37.useRef(false);
|
|
6046
6104
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
6047
6105
|
const R = 108, NR = 80;
|
|
6048
6106
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -6115,9 +6173,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
6115
6173
|
}
|
|
6116
6174
|
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
|
|
6117
6175
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
6118
|
-
const [open, setOpen] =
|
|
6119
|
-
const rootRef =
|
|
6120
|
-
const boxRef =
|
|
6176
|
+
const [open, setOpen] = React37.useState(false);
|
|
6177
|
+
const rootRef = React37.useRef(null);
|
|
6178
|
+
const boxRef = React37.useRef(null);
|
|
6121
6179
|
const disp = () => {
|
|
6122
6180
|
if (!value) return "";
|
|
6123
6181
|
const [h, m] = value.split(":").map(Number);
|
|
@@ -6160,7 +6218,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
6160
6218
|
offset: 6,
|
|
6161
6219
|
width: 262,
|
|
6162
6220
|
role: "presentation",
|
|
6163
|
-
footer: /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
|
|
6221
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(React37.Fragment, { children: [
|
|
6164
6222
|
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
|
|
6165
6223
|
"button",
|
|
6166
6224
|
{
|
|
@@ -6188,7 +6246,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
6188
6246
|
}
|
|
6189
6247
|
|
|
6190
6248
|
// src/components/forms/Slider.tsx
|
|
6191
|
-
var
|
|
6249
|
+
var React38 = __toESM(require("react"), 1);
|
|
6192
6250
|
var import_jsx_runtime65 = require("react/jsx-runtime");
|
|
6193
6251
|
function Slider({
|
|
6194
6252
|
label,
|
|
@@ -6206,7 +6264,7 @@ function Slider({
|
|
|
6206
6264
|
...rest
|
|
6207
6265
|
}) {
|
|
6208
6266
|
const fieldId = useFieldId(id);
|
|
6209
|
-
const [dragging, setDragging] =
|
|
6267
|
+
const [dragging, setDragging] = React38.useState(false);
|
|
6210
6268
|
const v = value === void 0 ? min : Number(value);
|
|
6211
6269
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
6212
6270
|
return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
|
|
@@ -6240,7 +6298,7 @@ function Slider({
|
|
|
6240
6298
|
}
|
|
6241
6299
|
|
|
6242
6300
|
// src/components/forms/RangeSlider.tsx
|
|
6243
|
-
var
|
|
6301
|
+
var React39 = __toESM(require("react"), 1);
|
|
6244
6302
|
var import_jsx_runtime66 = require("react/jsx-runtime");
|
|
6245
6303
|
function RangeSlider({
|
|
6246
6304
|
label,
|
|
@@ -6260,9 +6318,9 @@ function RangeSlider({
|
|
|
6260
6318
|
}) {
|
|
6261
6319
|
const fmt2 = format || ((v) => String(v));
|
|
6262
6320
|
const [a, b] = value || [min, max];
|
|
6263
|
-
const [drag, setDrag] =
|
|
6264
|
-
const [focus, setFocus] =
|
|
6265
|
-
const railRef =
|
|
6321
|
+
const [drag, setDrag] = React39.useState(null);
|
|
6322
|
+
const [focus, setFocus] = React39.useState(null);
|
|
6323
|
+
const railRef = React39.useRef(null);
|
|
6266
6324
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
6267
6325
|
const clampPair = (i, v) => {
|
|
6268
6326
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -6277,7 +6335,7 @@ function RangeSlider({
|
|
|
6277
6335
|
const r = railRef.current.getBoundingClientRect();
|
|
6278
6336
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
6279
6337
|
};
|
|
6280
|
-
|
|
6338
|
+
React39.useEffect(() => {
|
|
6281
6339
|
if (drag === null) return;
|
|
6282
6340
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
6283
6341
|
const upH = () => setDrag(null);
|
|
@@ -6358,7 +6416,7 @@ function RangeSlider({
|
|
|
6358
6416
|
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
|
|
6359
6417
|
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-range-rail", ref: railRef }),
|
|
6360
6418
|
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
|
|
6361
|
-
marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
|
|
6419
|
+
marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(React39.Fragment, { children: [
|
|
6362
6420
|
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
|
|
6363
6421
|
m.label ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
|
|
6364
6422
|
] }, m.value)),
|
|
@@ -6387,7 +6445,7 @@ function RangeSlider({
|
|
|
6387
6445
|
}
|
|
6388
6446
|
|
|
6389
6447
|
// src/components/forms/Dropzone.tsx
|
|
6390
|
-
var
|
|
6448
|
+
var React40 = __toESM(require("react"), 1);
|
|
6391
6449
|
var import_jsx_runtime67 = require("react/jsx-runtime");
|
|
6392
6450
|
function Dropzone({
|
|
6393
6451
|
onFiles,
|
|
@@ -6402,8 +6460,8 @@ function Dropzone({
|
|
|
6402
6460
|
className = "",
|
|
6403
6461
|
style
|
|
6404
6462
|
}) {
|
|
6405
|
-
const [over, setOver] =
|
|
6406
|
-
const depth =
|
|
6463
|
+
const [over, setOver] = React40.useState(false);
|
|
6464
|
+
const depth = React40.useRef(0);
|
|
6407
6465
|
const has = (e) => {
|
|
6408
6466
|
const dt = e.dataTransfer;
|
|
6409
6467
|
if (!dt) return false;
|
|
@@ -6465,8 +6523,8 @@ function FilePickButton({
|
|
|
6465
6523
|
className = "",
|
|
6466
6524
|
children
|
|
6467
6525
|
}) {
|
|
6468
|
-
const ref =
|
|
6469
|
-
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
|
|
6526
|
+
const ref = React40.useRef(null);
|
|
6527
|
+
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(React40.Fragment, { children: [
|
|
6470
6528
|
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
|
|
6471
6529
|
"button",
|
|
6472
6530
|
{
|
|
@@ -6499,10 +6557,10 @@ function FilePickButton({
|
|
|
6499
6557
|
}
|
|
6500
6558
|
function useStagedFiles(upload, opts) {
|
|
6501
6559
|
const o = opts || {};
|
|
6502
|
-
const [items, setItems] =
|
|
6503
|
-
const controllers =
|
|
6560
|
+
const [items, setItems] = React40.useState([]);
|
|
6561
|
+
const controllers = React40.useRef({});
|
|
6504
6562
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
6505
|
-
const run =
|
|
6563
|
+
const run = React40.useCallback((att) => {
|
|
6506
6564
|
if (!upload) return;
|
|
6507
6565
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
6508
6566
|
controllers.current[att.id] = ac;
|
|
@@ -6519,14 +6577,14 @@ function useStagedFiles(upload, opts) {
|
|
|
6519
6577
|
delete controllers.current[att.id];
|
|
6520
6578
|
});
|
|
6521
6579
|
}, [upload]);
|
|
6522
|
-
const add =
|
|
6580
|
+
const add = React40.useCallback((files) => {
|
|
6523
6581
|
if (!upload) return [];
|
|
6524
6582
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
6525
6583
|
setItems((list) => list.concat(atts));
|
|
6526
6584
|
atts.forEach(run);
|
|
6527
6585
|
return atts;
|
|
6528
6586
|
}, [upload, run]);
|
|
6529
|
-
const remove =
|
|
6587
|
+
const remove = React40.useCallback((att) => {
|
|
6530
6588
|
const ac = controllers.current[att.id];
|
|
6531
6589
|
if (ac) {
|
|
6532
6590
|
try {
|
|
@@ -6537,10 +6595,10 @@ function useStagedFiles(upload, opts) {
|
|
|
6537
6595
|
}
|
|
6538
6596
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
6539
6597
|
}, []);
|
|
6540
|
-
const retry =
|
|
6598
|
+
const retry = React40.useCallback((att) => {
|
|
6541
6599
|
run(att);
|
|
6542
6600
|
}, [run]);
|
|
6543
|
-
const clear =
|
|
6601
|
+
const clear = React40.useCallback(() => {
|
|
6544
6602
|
Object.values(controllers.current).forEach((ac) => {
|
|
6545
6603
|
try {
|
|
6546
6604
|
ac && ac.abort();
|
|
@@ -6664,7 +6722,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
6664
6722
|
}
|
|
6665
6723
|
|
|
6666
6724
|
// src/components/forms/MarkdownEditor.tsx
|
|
6667
|
-
var
|
|
6725
|
+
var React41 = __toESM(require("react"), 1);
|
|
6668
6726
|
var import_jsx_runtime69 = require("react/jsx-runtime");
|
|
6669
6727
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
6670
6728
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
@@ -6878,7 +6936,7 @@ function syncDom(root, value) {
|
|
|
6878
6936
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
6879
6937
|
}
|
|
6880
6938
|
var LIST_CONT = RE_LI;
|
|
6881
|
-
var MarkdownEditor =
|
|
6939
|
+
var MarkdownEditor = React41.forwardRef(function MarkdownEditor2({
|
|
6882
6940
|
value = "",
|
|
6883
6941
|
onChange,
|
|
6884
6942
|
onSubmit,
|
|
@@ -6897,10 +6955,10 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6897
6955
|
className = "",
|
|
6898
6956
|
id
|
|
6899
6957
|
}, ref) {
|
|
6900
|
-
const boxRef =
|
|
6901
|
-
const composing =
|
|
6902
|
-
const pendingCaret =
|
|
6903
|
-
|
|
6958
|
+
const boxRef = React41.useRef(null);
|
|
6959
|
+
const composing = React41.useRef(false);
|
|
6960
|
+
const pendingCaret = React41.useRef(null);
|
|
6961
|
+
React41.useLayoutEffect(() => {
|
|
6904
6962
|
const root = boxRef.current;
|
|
6905
6963
|
if (!root || composing.current) return;
|
|
6906
6964
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -6909,7 +6967,7 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6909
6967
|
pendingCaret.current = null;
|
|
6910
6968
|
if (active && caret != null) placeCaret(root, caret);
|
|
6911
6969
|
}, [value]);
|
|
6912
|
-
|
|
6970
|
+
React41.useEffect(() => {
|
|
6913
6971
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
6914
6972
|
}, [autoFocus]);
|
|
6915
6973
|
const caretNow = () => {
|
|
@@ -6976,7 +7034,7 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6976
7034
|
api.replaceRange(from, to, next, from + next.length);
|
|
6977
7035
|
}
|
|
6978
7036
|
};
|
|
6979
|
-
|
|
7037
|
+
React41.useImperativeHandle(ref, () => api);
|
|
6980
7038
|
function detect(text, caret) {
|
|
6981
7039
|
if (!onTrigger) return;
|
|
6982
7040
|
const upto = text.slice(0, caret);
|
|
@@ -7128,16 +7186,16 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
7128
7186
|
});
|
|
7129
7187
|
|
|
7130
7188
|
// src/components/platform/AccountMenu.tsx
|
|
7131
|
-
var
|
|
7189
|
+
var React43 = __toESM(require("react"), 1);
|
|
7132
7190
|
|
|
7133
7191
|
// src/kits/sessionContext.tsx
|
|
7134
|
-
var
|
|
7135
|
-
var SessionContext =
|
|
7192
|
+
var React42 = __toESM(require("react"), 1);
|
|
7193
|
+
var SessionContext = React42.createContext(null);
|
|
7136
7194
|
function SessionProvider({ value, children }) {
|
|
7137
|
-
return
|
|
7195
|
+
return React42.createElement(SessionContext.Provider, { value }, children);
|
|
7138
7196
|
}
|
|
7139
7197
|
function useSessionContext() {
|
|
7140
|
-
const ctx =
|
|
7198
|
+
const ctx = React42.useContext(SessionContext);
|
|
7141
7199
|
if (!ctx) {
|
|
7142
7200
|
throw new Error(
|
|
7143
7201
|
"useSessionContext() was called outside a <SessionProvider>. Wrap your app root in <SessionProvider value={...}> with your real session, or \u2014 in the docs site or a demo \u2014 in <DemoSessionProvider>, before rendering AccountMenu, Gate, ProfilePage or AppSwitcher."
|
|
@@ -7177,11 +7235,11 @@ function AccountMenu({
|
|
|
7177
7235
|
...rest
|
|
7178
7236
|
}) {
|
|
7179
7237
|
const { user, roles, can: can2, signOut: ctxSignOut, demo } = useSessionContext();
|
|
7180
|
-
const [open, setOpen] =
|
|
7181
|
-
const [switching, setSwitching] =
|
|
7182
|
-
const [signingOut, setSigningOut] =
|
|
7183
|
-
const [signOutError, setSignOutError] =
|
|
7184
|
-
const ref =
|
|
7238
|
+
const [open, setOpen] = React43.useState(false);
|
|
7239
|
+
const [switching, setSwitching] = React43.useState(false);
|
|
7240
|
+
const [signingOut, setSigningOut] = React43.useState(false);
|
|
7241
|
+
const [signOutError, setSignOutError] = React43.useState(null);
|
|
7242
|
+
const ref = React43.useRef(null);
|
|
7185
7243
|
const visibleLinks = links.filter((l) => !l.perm || can2(l.perm));
|
|
7186
7244
|
const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || can2(l.perm)) })).filter((g) => g.links.length);
|
|
7187
7245
|
const closeMenu = () => {
|
|
@@ -7306,13 +7364,13 @@ function AccountMenu({
|
|
|
7306
7364
|
}
|
|
7307
7365
|
|
|
7308
7366
|
// src/components/platform/AppSwitcher.tsx
|
|
7309
|
-
var
|
|
7367
|
+
var React44 = __toESM(require("react"), 1);
|
|
7310
7368
|
var import_jsx_runtime71 = require("react/jsx-runtime");
|
|
7311
7369
|
function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
7312
7370
|
const { apps: contextApps } = useSessionContext();
|
|
7313
7371
|
const apps = appsProp ?? contextApps ?? [];
|
|
7314
|
-
const [open, setOpen] =
|
|
7315
|
-
const anchorRef =
|
|
7372
|
+
const [open, setOpen] = React44.useState(false);
|
|
7373
|
+
const anchorRef = React44.useRef(null);
|
|
7316
7374
|
if (!apps.length) return null;
|
|
7317
7375
|
const items = apps.map((app) => ({
|
|
7318
7376
|
id: app.key,
|
|
@@ -7326,7 +7384,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7326
7384
|
window.location.href = app.url;
|
|
7327
7385
|
}
|
|
7328
7386
|
}));
|
|
7329
|
-
return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
|
|
7387
|
+
return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(React44.Fragment, { children: [
|
|
7330
7388
|
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
|
|
7331
7389
|
IconButton,
|
|
7332
7390
|
{
|
|
@@ -7355,10 +7413,10 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7355
7413
|
}
|
|
7356
7414
|
|
|
7357
7415
|
// src/components/platform/AppearanceMenu.tsx
|
|
7358
|
-
var
|
|
7416
|
+
var React46 = __toESM(require("react"), 1);
|
|
7359
7417
|
|
|
7360
7418
|
// src/kits/appearance.ts
|
|
7361
|
-
var
|
|
7419
|
+
var React45 = __toESM(require("react"), 1);
|
|
7362
7420
|
var DEFAULT_STORAGE_KEY = "fd-appearance";
|
|
7363
7421
|
var DEFAULT_PREFS = {
|
|
7364
7422
|
theme: "system",
|
|
@@ -7453,11 +7511,11 @@ function applyPrefs(prefs, root = document.documentElement) {
|
|
|
7453
7511
|
else root.removeAttribute("data-motion");
|
|
7454
7512
|
}
|
|
7455
7513
|
function useAppearancePrefs(store) {
|
|
7456
|
-
const prefs =
|
|
7457
|
-
|
|
7514
|
+
const prefs = React45.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
7515
|
+
React45.useEffect(() => {
|
|
7458
7516
|
applyPrefs(prefs);
|
|
7459
7517
|
}, [prefs]);
|
|
7460
|
-
|
|
7518
|
+
React45.useEffect(() => {
|
|
7461
7519
|
if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
7462
7520
|
return;
|
|
7463
7521
|
}
|
|
@@ -7466,7 +7524,7 @@ function useAppearancePrefs(store) {
|
|
|
7466
7524
|
mq.addEventListener("change", onChange);
|
|
7467
7525
|
return () => mq.removeEventListener("change", onChange);
|
|
7468
7526
|
}, [prefs]);
|
|
7469
|
-
const update =
|
|
7527
|
+
const update = React45.useCallback(
|
|
7470
7528
|
(patch) => {
|
|
7471
7529
|
store.write({ ...store.getSnapshot(), ...patch });
|
|
7472
7530
|
},
|
|
@@ -7489,15 +7547,15 @@ var TEXT_SCALE_OPTIONS = [
|
|
|
7489
7547
|
{ value: "xl", label: "XL" }
|
|
7490
7548
|
];
|
|
7491
7549
|
function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
|
|
7492
|
-
const store =
|
|
7550
|
+
const store = React46.useMemo(
|
|
7493
7551
|
() => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
|
|
7494
7552
|
[storeProp, storageKey, storage, defaults]
|
|
7495
7553
|
);
|
|
7496
7554
|
const [prefs, update] = useAppearancePrefs(store);
|
|
7497
|
-
const [open, setOpen] =
|
|
7498
|
-
const anchorRef =
|
|
7555
|
+
const [open, setOpen] = React46.useState(false);
|
|
7556
|
+
const anchorRef = React46.useRef(null);
|
|
7499
7557
|
const patch = (p) => update(p);
|
|
7500
|
-
return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
|
|
7558
|
+
return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(React46.Fragment, { children: [
|
|
7501
7559
|
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
|
|
7502
7560
|
IconButton,
|
|
7503
7561
|
{
|
|
@@ -7566,14 +7624,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7566
7624
|
}
|
|
7567
7625
|
|
|
7568
7626
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
7569
|
-
var
|
|
7627
|
+
var React47 = __toESM(require("react"), 1);
|
|
7570
7628
|
var import_jsx_runtime73 = require("react/jsx-runtime");
|
|
7571
7629
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
7572
7630
|
function Json({ obj }) {
|
|
7573
7631
|
return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
7574
7632
|
}
|
|
7575
7633
|
function Endpoint({ s, onRequest }) {
|
|
7576
|
-
const [tried, setTried] =
|
|
7634
|
+
const [tried, setTried] = React47.useState(null);
|
|
7577
7635
|
const run = async () => {
|
|
7578
7636
|
setTried("busy");
|
|
7579
7637
|
const t0 = (window.performance || Date).now();
|
|
@@ -7646,10 +7704,10 @@ function ApiSpecBrowser({
|
|
|
7646
7704
|
className = "",
|
|
7647
7705
|
...rest
|
|
7648
7706
|
}) {
|
|
7649
|
-
const [q, setQ] =
|
|
7650
|
-
const [method, setMethod] =
|
|
7651
|
-
const [mod, setMod] =
|
|
7652
|
-
const [listOnly, setListOnly] =
|
|
7707
|
+
const [q, setQ] = React47.useState("");
|
|
7708
|
+
const [method, setMethod] = React47.useState(null);
|
|
7709
|
+
const [mod, setMod] = React47.useState(null);
|
|
7710
|
+
const [listOnly, setListOnly] = React47.useState(false);
|
|
7653
7711
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
7654
7712
|
const hits = spec.filter((s) => (!method || s.method === method) && (!listOnly || s.isList) && (!activeModule || activeModule.endpoints.indexOf(s.id) >= 0) && (!q || (s.path + " " + s.title + " " + s.purpose + " " + (s.usedBy || []).join(" ")).toLowerCase().includes(q.toLowerCase())));
|
|
7655
7713
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
@@ -7728,7 +7786,7 @@ function ApiSpecBrowser({
|
|
|
7728
7786
|
}
|
|
7729
7787
|
|
|
7730
7788
|
// src/components/platform/ProfilePage.tsx
|
|
7731
|
-
var
|
|
7789
|
+
var React48 = __toESM(require("react"), 1);
|
|
7732
7790
|
var import_jsx_runtime74 = require("react/jsx-runtime");
|
|
7733
7791
|
function fieldInitialValue(field, user) {
|
|
7734
7792
|
if (field.value) return field.value(user);
|
|
@@ -7764,21 +7822,21 @@ function ProfilePage({
|
|
|
7764
7822
|
}) {
|
|
7765
7823
|
const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
|
|
7766
7824
|
const user = userProp || sessionUser;
|
|
7767
|
-
const initialFieldValues =
|
|
7825
|
+
const initialFieldValues = React48.useMemo(() => {
|
|
7768
7826
|
const values2 = {};
|
|
7769
7827
|
for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
|
|
7770
7828
|
return values2;
|
|
7771
7829
|
}, [user.id, fields]);
|
|
7772
|
-
const initialNotify =
|
|
7830
|
+
const initialNotify = React48.useMemo(() => {
|
|
7773
7831
|
const values2 = {};
|
|
7774
7832
|
for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
|
|
7775
7833
|
return values2;
|
|
7776
7834
|
}, [user.id, notifications]);
|
|
7777
|
-
const [values, setValues] =
|
|
7778
|
-
const [notify, setNotify] =
|
|
7779
|
-
const [saving, setSaving] =
|
|
7780
|
-
const [saved, setSaved] =
|
|
7781
|
-
const [prevUserId, setPrevUserId] =
|
|
7835
|
+
const [values, setValues] = React48.useState(initialFieldValues);
|
|
7836
|
+
const [notify, setNotify] = React48.useState(initialNotify);
|
|
7837
|
+
const [saving, setSaving] = React48.useState(false);
|
|
7838
|
+
const [saved, setSaved] = React48.useState(false);
|
|
7839
|
+
const [prevUserId, setPrevUserId] = React48.useState(user.id);
|
|
7782
7840
|
if (user.id !== prevUserId) {
|
|
7783
7841
|
setPrevUserId(user.id);
|
|
7784
7842
|
setValues(initialFieldValues);
|
|
@@ -7966,11 +8024,11 @@ function ProfilePage({
|
|
|
7966
8024
|
}
|
|
7967
8025
|
|
|
7968
8026
|
// src/components/platform/SignInPage.tsx
|
|
7969
|
-
var
|
|
8027
|
+
var React49 = __toESM(require("react"), 1);
|
|
7970
8028
|
var import_jsx_runtime75 = require("react/jsx-runtime");
|
|
7971
8029
|
function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
7972
|
-
const [signingIn, setSigningIn] =
|
|
7973
|
-
const [resuming, setResuming] =
|
|
8030
|
+
const [signingIn, setSigningIn] = React49.useState(false);
|
|
8031
|
+
const [resuming, setResuming] = React49.useState(false);
|
|
7974
8032
|
function handleSignIn() {
|
|
7975
8033
|
setSigningIn(true);
|
|
7976
8034
|
onSignIn();
|
|
@@ -8159,10 +8217,10 @@ function GoogleGlyph() {
|
|
|
8159
8217
|
}
|
|
8160
8218
|
|
|
8161
8219
|
// src/components/platform/RoadmapTimeline.tsx
|
|
8162
|
-
var
|
|
8220
|
+
var React52 = __toESM(require("react"), 1);
|
|
8163
8221
|
|
|
8164
8222
|
// src/kits/session.ts
|
|
8165
|
-
var
|
|
8223
|
+
var React50 = __toESM(require("react"), 1);
|
|
8166
8224
|
var PERMISSION_CATALOG = [
|
|
8167
8225
|
{ group: "Plans", items: [
|
|
8168
8226
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -9729,8 +9787,8 @@ function roadmap(overrides) {
|
|
|
9729
9787
|
};
|
|
9730
9788
|
}
|
|
9731
9789
|
function useSession() {
|
|
9732
|
-
const [s, setS] =
|
|
9733
|
-
|
|
9790
|
+
const [s, setS] = React50.useState(getSession);
|
|
9791
|
+
React50.useEffect(() => subscribe(setS), []);
|
|
9734
9792
|
return s;
|
|
9735
9793
|
}
|
|
9736
9794
|
var SessionKit = {
|
|
@@ -9763,7 +9821,7 @@ var SessionKit = {
|
|
|
9763
9821
|
};
|
|
9764
9822
|
function DemoSessionProvider({ children }) {
|
|
9765
9823
|
const session = useSession();
|
|
9766
|
-
const value =
|
|
9824
|
+
const value = React50.useMemo(
|
|
9767
9825
|
() => ({
|
|
9768
9826
|
user: session.user,
|
|
9769
9827
|
roles: session.roles,
|
|
@@ -9779,11 +9837,11 @@ function DemoSessionProvider({ children }) {
|
|
|
9779
9837
|
}),
|
|
9780
9838
|
[session]
|
|
9781
9839
|
);
|
|
9782
|
-
return
|
|
9840
|
+
return React50.createElement(SessionProvider, { value }, children);
|
|
9783
9841
|
}
|
|
9784
9842
|
|
|
9785
9843
|
// src/kits/runtime.ts
|
|
9786
|
-
var
|
|
9844
|
+
var React51 = __toESM(require("react"), 1);
|
|
9787
9845
|
var WIRED_ENDPOINTS = [
|
|
9788
9846
|
// Nothing yet. Every id below would come from a real service:
|
|
9789
9847
|
// "plan.get", "placements.list", …
|
|
@@ -9954,8 +10012,8 @@ var RuntimeKit = {
|
|
|
9954
10012
|
};
|
|
9955
10013
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
9956
10014
|
function useRuntimeMode() {
|
|
9957
|
-
const [m, setM] =
|
|
9958
|
-
|
|
10015
|
+
const [m, setM] = React51.useState(RuntimeKit.getMode());
|
|
10016
|
+
React51.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
9959
10017
|
return m;
|
|
9960
10018
|
}
|
|
9961
10019
|
function useFeatureStatus(key) {
|
|
@@ -10038,12 +10096,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
10038
10096
|
}
|
|
10039
10097
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
10040
10098
|
const session = SessionKit.useSession();
|
|
10041
|
-
const [project, setProject] =
|
|
10042
|
-
const [q, setQ] =
|
|
10043
|
-
const scrollRef =
|
|
10044
|
-
const nowRef =
|
|
10045
|
-
const rm =
|
|
10046
|
-
const byKey =
|
|
10099
|
+
const [project, setProject] = React52.useState("");
|
|
10100
|
+
const [q, setQ] = React52.useState("");
|
|
10101
|
+
const scrollRef = React52.useRef(null);
|
|
10102
|
+
const nowRef = React52.useRef(null);
|
|
10103
|
+
const rm = React52.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
10104
|
+
const byKey = React52.useMemo(() => {
|
|
10047
10105
|
const m = {};
|
|
10048
10106
|
rm.items.forEach((i) => {
|
|
10049
10107
|
m[i.key] = i;
|
|
@@ -10052,7 +10110,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10052
10110
|
}, [rm]);
|
|
10053
10111
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
10054
10112
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
10055
|
-
|
|
10113
|
+
React52.useEffect(() => {
|
|
10056
10114
|
let raf1 = 0, raf2 = 0;
|
|
10057
10115
|
const place = () => {
|
|
10058
10116
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -10126,7 +10184,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10126
10184
|
lastPhase = item.phase;
|
|
10127
10185
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
10128
10186
|
const isBoundary = n === firstPending;
|
|
10129
|
-
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
|
|
10187
|
+
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React52.Fragment, { children: [
|
|
10130
10188
|
showPhase ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-rm-era", children: [
|
|
10131
10189
|
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
10132
10190
|
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
@@ -10170,7 +10228,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10170
10228
|
}
|
|
10171
10229
|
|
|
10172
10230
|
// src/components/platform/ComingSoon.tsx
|
|
10173
|
-
var
|
|
10231
|
+
var React53 = __toESM(require("react"), 1);
|
|
10174
10232
|
var import_react_dom6 = require("react-dom");
|
|
10175
10233
|
var import_jsx_runtime77 = require("react/jsx-runtime");
|
|
10176
10234
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
@@ -10188,8 +10246,8 @@ function writeBypassed(list) {
|
|
|
10188
10246
|
}
|
|
10189
10247
|
}
|
|
10190
10248
|
function useBypass(key) {
|
|
10191
|
-
const [on, setOn] =
|
|
10192
|
-
|
|
10249
|
+
const [on, setOn] = React53.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
10250
|
+
React53.useEffect(() => {
|
|
10193
10251
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
10194
10252
|
}, [key]);
|
|
10195
10253
|
const set = (next) => {
|
|
@@ -10236,9 +10294,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
|
|
|
10236
10294
|
] });
|
|
10237
10295
|
}
|
|
10238
10296
|
function useHoverCard(open) {
|
|
10239
|
-
const anchor =
|
|
10240
|
-
const [pos, setPos] =
|
|
10241
|
-
|
|
10297
|
+
const anchor = React53.useRef(null);
|
|
10298
|
+
const [pos, setPos] = React53.useState(null);
|
|
10299
|
+
React53.useLayoutEffect(() => {
|
|
10242
10300
|
if (!open || !anchor.current) {
|
|
10243
10301
|
setPos(null);
|
|
10244
10302
|
return;
|
|
@@ -10365,10 +10423,10 @@ function ComingSoon({
|
|
|
10365
10423
|
] });
|
|
10366
10424
|
}
|
|
10367
10425
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
10368
|
-
const [open, setOpen] =
|
|
10426
|
+
const [open, setOpen] = React53.useState(false);
|
|
10369
10427
|
const [anchor, pos] = useHoverCard(open);
|
|
10370
10428
|
const zIndex = useOverlayLayer(open);
|
|
10371
|
-
const close =
|
|
10429
|
+
const close = React53.useRef(null);
|
|
10372
10430
|
const show = () => {
|
|
10373
10431
|
if (close.current) {
|
|
10374
10432
|
clearTimeout(close.current);
|
|
@@ -10384,7 +10442,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10384
10442
|
setOpen(false);
|
|
10385
10443
|
}, 140);
|
|
10386
10444
|
};
|
|
10387
|
-
|
|
10445
|
+
React53.useEffect(() => () => {
|
|
10388
10446
|
if (close.current) clearTimeout(close.current);
|
|
10389
10447
|
}, []);
|
|
10390
10448
|
return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(
|
|
@@ -10555,14 +10613,14 @@ function PermissionHint({ perm, children }) {
|
|
|
10555
10613
|
}
|
|
10556
10614
|
|
|
10557
10615
|
// src/components/platform/ModeSwitch.tsx
|
|
10558
|
-
var
|
|
10616
|
+
var React54 = __toESM(require("react"), 1);
|
|
10559
10617
|
var import_jsx_runtime79 = require("react/jsx-runtime");
|
|
10560
10618
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
10561
10619
|
const mode2 = useRuntimeMode();
|
|
10562
|
-
const [open, setOpen] =
|
|
10620
|
+
const [open, setOpen] = React54.useState(false);
|
|
10563
10621
|
const zIndex = useOverlayLayer(open);
|
|
10564
|
-
const ref =
|
|
10565
|
-
|
|
10622
|
+
const ref = React54.useRef(null);
|
|
10623
|
+
React54.useEffect(() => {
|
|
10566
10624
|
if (!open) return;
|
|
10567
10625
|
const away = (e) => {
|
|
10568
10626
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -10818,7 +10876,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
10818
10876
|
}
|
|
10819
10877
|
|
|
10820
10878
|
// src/components/planner/MixGap.tsx
|
|
10821
|
-
var
|
|
10879
|
+
var React55 = __toESM(require("react"), 1);
|
|
10822
10880
|
var import_jsx_runtime82 = require("react/jsx-runtime");
|
|
10823
10881
|
var MIX_GAP_LAYOUT = {
|
|
10824
10882
|
trackHeight: 30,
|
|
@@ -10833,7 +10891,7 @@ function mixGapOffset(value, max) {
|
|
|
10833
10891
|
}
|
|
10834
10892
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
10835
10893
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
10836
|
-
const [hover, setHover] =
|
|
10894
|
+
const [hover, setHover] = React55.useState(null);
|
|
10837
10895
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
10838
10896
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
10839
10897
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
@@ -10976,7 +11034,7 @@ function ChannelContribution({
|
|
|
10976
11034
|
}
|
|
10977
11035
|
|
|
10978
11036
|
// src/components/planner/BudgetReallocator.tsx
|
|
10979
|
-
var
|
|
11037
|
+
var React56 = __toESM(require("react"), 1);
|
|
10980
11038
|
var import_jsx_runtime84 = require("react/jsx-runtime");
|
|
10981
11039
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
10982
11040
|
function BudgetReallocator({
|
|
@@ -10992,8 +11050,8 @@ function BudgetReallocator({
|
|
|
10992
11050
|
onCancel,
|
|
10993
11051
|
className = ""
|
|
10994
11052
|
}) {
|
|
10995
|
-
const [draft, setDraft] =
|
|
10996
|
-
|
|
11053
|
+
const [draft, setDraft] = React56.useState(spend);
|
|
11054
|
+
React56.useEffect(() => setDraft(spend), [spend]);
|
|
10997
11055
|
const dirty = draft !== spend;
|
|
10998
11056
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
10999
11057
|
const nextBand = bandFor(nextCrp);
|
|
@@ -11008,10 +11066,10 @@ function BudgetReallocator({
|
|
|
11008
11066
|
setDraft(spend);
|
|
11009
11067
|
if (onCancel) onCancel();
|
|
11010
11068
|
};
|
|
11011
|
-
const trackRef =
|
|
11012
|
-
const chipRef =
|
|
11013
|
-
const [chipLeft, setChipLeft] =
|
|
11014
|
-
|
|
11069
|
+
const trackRef = React56.useRef(null);
|
|
11070
|
+
const chipRef = React56.useRef(null);
|
|
11071
|
+
const [chipLeft, setChipLeft] = React56.useState(null);
|
|
11072
|
+
React56.useLayoutEffect(() => {
|
|
11015
11073
|
const track = trackRef.current;
|
|
11016
11074
|
if (!dirty || !track) {
|
|
11017
11075
|
setChipLeft(null);
|
|
@@ -11198,7 +11256,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "" })
|
|
|
11198
11256
|
}
|
|
11199
11257
|
|
|
11200
11258
|
// src/components/planner/PreferenceMeter.tsx
|
|
11201
|
-
var
|
|
11259
|
+
var React57 = __toESM(require("react"), 1);
|
|
11202
11260
|
var import_jsx_runtime87 = require("react/jsx-runtime");
|
|
11203
11261
|
function preferenceScore(criteria) {
|
|
11204
11262
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
@@ -11228,7 +11286,7 @@ function PreferenceMeter({
|
|
|
11228
11286
|
className = ""
|
|
11229
11287
|
}) {
|
|
11230
11288
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
11231
|
-
const segments =
|
|
11289
|
+
const segments = React57.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
11232
11290
|
return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
|
|
11233
11291
|
ScoreMeter,
|
|
11234
11292
|
{
|
|
@@ -11267,10 +11325,10 @@ function PreferenceMeter({
|
|
|
11267
11325
|
}
|
|
11268
11326
|
|
|
11269
11327
|
// src/components/chat/AgentChatPanel.tsx
|
|
11270
|
-
var
|
|
11328
|
+
var React63 = __toESM(require("react"), 1);
|
|
11271
11329
|
|
|
11272
11330
|
// src/components/chat/chatEngine.ts
|
|
11273
|
-
var
|
|
11331
|
+
var React58 = __toESM(require("react"), 1);
|
|
11274
11332
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
11275
11333
|
var JOB_PENDING = ["queued", "running"];
|
|
11276
11334
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -11324,22 +11382,22 @@ function useChatEngine(opts) {
|
|
|
11324
11382
|
onClear,
|
|
11325
11383
|
onFeedback
|
|
11326
11384
|
} = opts || {};
|
|
11327
|
-
const [status, setStatus] =
|
|
11328
|
-
const [threadId, setThreadId] =
|
|
11329
|
-
const [messages, setMessages] =
|
|
11330
|
-
const [queue, setQueue] =
|
|
11331
|
-
const [fatal, setFatal] =
|
|
11332
|
-
const [busy, setBusy] =
|
|
11333
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
11334
|
-
const listRef =
|
|
11335
|
-
const queueRef =
|
|
11336
|
-
const busyRef =
|
|
11337
|
-
const stoppedRef =
|
|
11338
|
-
const abortRef =
|
|
11339
|
-
const serverCount =
|
|
11340
|
-
const threadRef =
|
|
11341
|
-
const mounted =
|
|
11342
|
-
|
|
11385
|
+
const [status, setStatus] = React58.useState("idle");
|
|
11386
|
+
const [threadId, setThreadId] = React58.useState(null);
|
|
11387
|
+
const [messages, setMessages] = React58.useState([]);
|
|
11388
|
+
const [queue, setQueue] = React58.useState([]);
|
|
11389
|
+
const [fatal, setFatal] = React58.useState(null);
|
|
11390
|
+
const [busy, setBusy] = React58.useState(false);
|
|
11391
|
+
const [turnStartedAt, setTurnStartedAt] = React58.useState(null);
|
|
11392
|
+
const listRef = React58.useRef([]);
|
|
11393
|
+
const queueRef = React58.useRef([]);
|
|
11394
|
+
const busyRef = React58.useRef(false);
|
|
11395
|
+
const stoppedRef = React58.useRef(false);
|
|
11396
|
+
const abortRef = React58.useRef(null);
|
|
11397
|
+
const serverCount = React58.useRef(0);
|
|
11398
|
+
const threadRef = React58.useRef(null);
|
|
11399
|
+
const mounted = React58.useRef(true);
|
|
11400
|
+
React58.useEffect(() => {
|
|
11343
11401
|
mounted.current = true;
|
|
11344
11402
|
return () => {
|
|
11345
11403
|
mounted.current = false;
|
|
@@ -11361,14 +11419,14 @@ function useChatEngine(opts) {
|
|
|
11361
11419
|
}
|
|
11362
11420
|
return false;
|
|
11363
11421
|
};
|
|
11364
|
-
const loadThread =
|
|
11422
|
+
const loadThread = React58.useCallback(async (id) => {
|
|
11365
11423
|
const data = await apiAdapter.getThread(id);
|
|
11366
11424
|
const list = [...data && data.messages || []];
|
|
11367
11425
|
serverCount.current = list.length;
|
|
11368
11426
|
commit(list);
|
|
11369
11427
|
return list;
|
|
11370
11428
|
}, [apiAdapter]);
|
|
11371
|
-
|
|
11429
|
+
React58.useEffect(() => {
|
|
11372
11430
|
if (!apiAdapter) {
|
|
11373
11431
|
setStatus("idle");
|
|
11374
11432
|
setFatal(null);
|
|
@@ -11581,7 +11639,7 @@ function useChatEngine(opts) {
|
|
|
11581
11639
|
await dispatchTurn(turn);
|
|
11582
11640
|
}
|
|
11583
11641
|
}
|
|
11584
|
-
const send =
|
|
11642
|
+
const send = React58.useCallback((text, attachments) => {
|
|
11585
11643
|
const body = (text || "").trim();
|
|
11586
11644
|
if (!body && !(attachments && attachments.length)) return;
|
|
11587
11645
|
if (status === "disconnected") return;
|
|
@@ -11591,7 +11649,7 @@ function useChatEngine(opts) {
|
|
|
11591
11649
|
stoppedRef.current = false;
|
|
11592
11650
|
drain();
|
|
11593
11651
|
}, [status]);
|
|
11594
|
-
const stop =
|
|
11652
|
+
const stop = React58.useCallback(() => {
|
|
11595
11653
|
stoppedRef.current = true;
|
|
11596
11654
|
const ac = abortRef.current;
|
|
11597
11655
|
if (ac) {
|
|
@@ -11610,11 +11668,11 @@ function useChatEngine(opts) {
|
|
|
11610
11668
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
11611
11669
|
}
|
|
11612
11670
|
}, [apiAdapter]);
|
|
11613
|
-
const removeQueued =
|
|
11671
|
+
const removeQueued = React58.useCallback((id) => {
|
|
11614
11672
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
11615
11673
|
setQueue(queueRef.current.slice());
|
|
11616
11674
|
}, []);
|
|
11617
|
-
const retry =
|
|
11675
|
+
const retry = React58.useCallback(() => {
|
|
11618
11676
|
const list = listRef.current;
|
|
11619
11677
|
let at = -1;
|
|
11620
11678
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -11630,19 +11688,19 @@ function useChatEngine(opts) {
|
|
|
11630
11688
|
setQueue(queueRef.current.slice());
|
|
11631
11689
|
drain();
|
|
11632
11690
|
}, []);
|
|
11633
|
-
const clear =
|
|
11691
|
+
const clear = React58.useCallback(() => {
|
|
11634
11692
|
commit([]);
|
|
11635
11693
|
serverCount.current = 0;
|
|
11636
11694
|
queueRef.current = [];
|
|
11637
11695
|
setQueue([]);
|
|
11638
11696
|
onClear && onClear();
|
|
11639
11697
|
}, [onClear]);
|
|
11640
|
-
const setFeedback =
|
|
11698
|
+
const setFeedback = React58.useCallback((id, value) => {
|
|
11641
11699
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
11642
11700
|
const msg = listRef.current.find((m) => m.id === id);
|
|
11643
11701
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
11644
11702
|
}, [onFeedback]);
|
|
11645
|
-
const reload =
|
|
11703
|
+
const reload = React58.useCallback(async () => {
|
|
11646
11704
|
if (!threadRef.current) return;
|
|
11647
11705
|
setStatus("loading");
|
|
11648
11706
|
try {
|
|
@@ -11680,10 +11738,10 @@ var ChatKit = {
|
|
|
11680
11738
|
};
|
|
11681
11739
|
|
|
11682
11740
|
// src/components/chat/ChatTranscript.tsx
|
|
11683
|
-
var
|
|
11741
|
+
var React60 = __toESM(require("react"), 1);
|
|
11684
11742
|
|
|
11685
11743
|
// src/components/chat/ChatTurn.tsx
|
|
11686
|
-
var
|
|
11744
|
+
var React59 = __toESM(require("react"), 1);
|
|
11687
11745
|
var import_jsx_runtime88 = require("react/jsx-runtime");
|
|
11688
11746
|
function JsonView({ value }) {
|
|
11689
11747
|
let text;
|
|
@@ -11720,7 +11778,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
|
11720
11778
|
] });
|
|
11721
11779
|
}
|
|
11722
11780
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
11723
|
-
const [open, setOpen] =
|
|
11781
|
+
const [open, setOpen] = React59.useState(defaultOpen);
|
|
11724
11782
|
if (!text) return null;
|
|
11725
11783
|
return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
|
|
11726
11784
|
/* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -11737,7 +11795,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
|
11737
11795
|
] });
|
|
11738
11796
|
}
|
|
11739
11797
|
function Citations({ items = [], onOpen }) {
|
|
11740
|
-
const [open, setOpen] =
|
|
11798
|
+
const [open, setOpen] = React59.useState(false);
|
|
11741
11799
|
if (!items.length) return null;
|
|
11742
11800
|
return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fdc-cites", children: [
|
|
11743
11801
|
/* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -11763,7 +11821,7 @@ function clampText(text, max) {
|
|
|
11763
11821
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
11764
11822
|
}
|
|
11765
11823
|
function MessageBody({ message: m, ctx }) {
|
|
11766
|
-
const [expanded, setExpanded] =
|
|
11824
|
+
const [expanded, setExpanded] = React59.useState(false);
|
|
11767
11825
|
const isUser = m.role === "user";
|
|
11768
11826
|
const raw = m.text || "";
|
|
11769
11827
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
@@ -11830,9 +11888,9 @@ function MessageBody({ message: m, ctx }) {
|
|
|
11830
11888
|
] });
|
|
11831
11889
|
}
|
|
11832
11890
|
function useCopyRun() {
|
|
11833
|
-
const [done, setDone] =
|
|
11834
|
-
const t =
|
|
11835
|
-
|
|
11891
|
+
const [done, setDone] = React59.useState(false);
|
|
11892
|
+
const t = React59.useRef(null);
|
|
11893
|
+
React59.useEffect(() => () => {
|
|
11836
11894
|
if (t.current) clearTimeout(t.current);
|
|
11837
11895
|
}, []);
|
|
11838
11896
|
return [done, (text) => {
|
|
@@ -11859,7 +11917,7 @@ function RunActions({ group, ctx }) {
|
|
|
11859
11917
|
] }),
|
|
11860
11918
|
isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
11861
11919
|
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
11862
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(
|
|
11920
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(React59.Fragment, { children: [
|
|
11863
11921
|
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
11864
11922
|
/* @__PURE__ */ (0, import_jsx_runtime88.jsx)("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
11865
11923
|
] }) : null,
|
|
@@ -11954,10 +12012,10 @@ function ChatTranscript({
|
|
|
11954
12012
|
renderEmpty,
|
|
11955
12013
|
className = ""
|
|
11956
12014
|
}) {
|
|
11957
|
-
const scroller =
|
|
11958
|
-
const stick =
|
|
11959
|
-
const [pill, setPill] =
|
|
11960
|
-
const seen =
|
|
12015
|
+
const scroller = React60.useRef(null);
|
|
12016
|
+
const stick = React60.useRef(true);
|
|
12017
|
+
const [pill, setPill] = React60.useState(0);
|
|
12018
|
+
const seen = React60.useRef(0);
|
|
11961
12019
|
const toBottom = (smooth) => {
|
|
11962
12020
|
const el = scroller.current;
|
|
11963
12021
|
if (!el) return;
|
|
@@ -11976,7 +12034,7 @@ function ChatTranscript({
|
|
|
11976
12034
|
seen.current = messages.length;
|
|
11977
12035
|
}
|
|
11978
12036
|
};
|
|
11979
|
-
|
|
12037
|
+
React60.useLayoutEffect(() => {
|
|
11980
12038
|
const el = scroller.current;
|
|
11981
12039
|
if (!el) return;
|
|
11982
12040
|
if (stick.current) {
|
|
@@ -11984,7 +12042,7 @@ function ChatTranscript({
|
|
|
11984
12042
|
seen.current = messages.length;
|
|
11985
12043
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
11986
12044
|
}, [messages]);
|
|
11987
|
-
|
|
12045
|
+
React60.useEffect(() => {
|
|
11988
12046
|
const el = scroller.current;
|
|
11989
12047
|
const inner = el && el.firstChild;
|
|
11990
12048
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -11994,7 +12052,7 @@ function ChatTranscript({
|
|
|
11994
12052
|
ro.observe(inner);
|
|
11995
12053
|
return () => ro.disconnect();
|
|
11996
12054
|
}, []);
|
|
11997
|
-
const groups =
|
|
12055
|
+
const groups = React60.useMemo(() => groupMessages(messages), [messages]);
|
|
11998
12056
|
const empty = !messages.length && status === "ready";
|
|
11999
12057
|
return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
12000
12058
|
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
@@ -12018,7 +12076,7 @@ function ChatTranscript({
|
|
|
12018
12076
|
const prev = groups[i - 1];
|
|
12019
12077
|
const k = dayKey(g.messages[0].timestamp);
|
|
12020
12078
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
12021
|
-
return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
|
|
12079
|
+
return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(React60.Fragment, { children: [
|
|
12022
12080
|
showDay ? /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { children: dayLabel(k) }) }) : null,
|
|
12023
12081
|
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(ChatTurn, { group: g, ctx })
|
|
12024
12082
|
] }, g.key || i);
|
|
@@ -12035,7 +12093,7 @@ function ChatTranscript({
|
|
|
12035
12093
|
var TranscriptKit = { groupMessages };
|
|
12036
12094
|
|
|
12037
12095
|
// src/components/chat/ChatComposer.tsx
|
|
12038
|
-
var
|
|
12096
|
+
var React61 = __toESM(require("react"), 1);
|
|
12039
12097
|
var import_jsx_runtime90 = require("react/jsx-runtime");
|
|
12040
12098
|
function ChatComposer({
|
|
12041
12099
|
onSubmit,
|
|
@@ -12063,17 +12121,17 @@ function ChatComposer({
|
|
|
12063
12121
|
onReject,
|
|
12064
12122
|
onOpenAttachment
|
|
12065
12123
|
}) {
|
|
12066
|
-
const [text, setText] =
|
|
12067
|
-
const [trigger, setTrigger] =
|
|
12068
|
-
const [mentionItems, setMentionItems] =
|
|
12069
|
-
const [listening, setListening] =
|
|
12070
|
-
const [notice, setNotice] =
|
|
12071
|
-
const editor =
|
|
12072
|
-
const wrap =
|
|
12073
|
-
const stopVoice =
|
|
12124
|
+
const [text, setText] = React61.useState(draft || "");
|
|
12125
|
+
const [trigger, setTrigger] = React61.useState(null);
|
|
12126
|
+
const [mentionItems, setMentionItems] = React61.useState([]);
|
|
12127
|
+
const [listening, setListening] = React61.useState(false);
|
|
12128
|
+
const [notice, setNotice] = React61.useState(null);
|
|
12129
|
+
const editor = React61.useRef(null);
|
|
12130
|
+
const wrap = React61.useRef(null);
|
|
12131
|
+
const stopVoice = React61.useRef(null);
|
|
12074
12132
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
12075
12133
|
} });
|
|
12076
|
-
|
|
12134
|
+
React61.useEffect(() => {
|
|
12077
12135
|
if (draft != null && draft !== text) setText(draft);
|
|
12078
12136
|
}, [draft]);
|
|
12079
12137
|
const change = (v) => {
|
|
@@ -12109,7 +12167,7 @@ function ChatComposer({
|
|
|
12109
12167
|
e.preventDefault();
|
|
12110
12168
|
staged.add(found.files);
|
|
12111
12169
|
};
|
|
12112
|
-
|
|
12170
|
+
React61.useEffect(() => {
|
|
12113
12171
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
12114
12172
|
setMentionItems([]);
|
|
12115
12173
|
return;
|
|
@@ -12127,7 +12185,7 @@ function ChatComposer({
|
|
|
12127
12185
|
const q = (trigger.query || "").toLowerCase();
|
|
12128
12186
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
12129
12187
|
}, [trigger, mentionSources]);
|
|
12130
|
-
const slashItems =
|
|
12188
|
+
const slashItems = React61.useMemo(() => {
|
|
12131
12189
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
12132
12190
|
const q = (trigger.query || "").toLowerCase();
|
|
12133
12191
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -12301,12 +12359,12 @@ function ChatComposer({
|
|
|
12301
12359
|
}
|
|
12302
12360
|
|
|
12303
12361
|
// src/components/chat/ChatSessionBar.tsx
|
|
12304
|
-
var
|
|
12362
|
+
var React62 = __toESM(require("react"), 1);
|
|
12305
12363
|
var import_jsx_runtime91 = require("react/jsx-runtime");
|
|
12306
12364
|
var compact2 = meterFormats.compact;
|
|
12307
12365
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
12308
|
-
const [open, setOpen] =
|
|
12309
|
-
const anchor =
|
|
12366
|
+
const [open, setOpen] = React62.useState(false);
|
|
12367
|
+
const anchor = React62.useRef(null);
|
|
12310
12368
|
const stats = sessionStats || null;
|
|
12311
12369
|
const cu = contextUsage || null;
|
|
12312
12370
|
const limits = usageLimits || null;
|
|
@@ -12321,7 +12379,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12321
12379
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
12322
12380
|
if (cu) bits.push(pct + "% context");
|
|
12323
12381
|
const expandable = !!(cu || limits);
|
|
12324
|
-
return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
|
|
12382
|
+
return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(React62.Fragment, { children: [
|
|
12325
12383
|
/* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-bar", children: [
|
|
12326
12384
|
/* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
|
|
12327
12385
|
"button",
|
|
@@ -12462,7 +12520,7 @@ function ModelControls({
|
|
|
12462
12520
|
] })
|
|
12463
12521
|
});
|
|
12464
12522
|
}
|
|
12465
|
-
return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
|
|
12523
|
+
return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(React62.Fragment, { children: [
|
|
12466
12524
|
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
|
|
12467
12525
|
MenuButton,
|
|
12468
12526
|
{
|
|
@@ -12579,11 +12637,11 @@ function AgentChatPanel({
|
|
|
12579
12637
|
onFeedback,
|
|
12580
12638
|
onEditMessage
|
|
12581
12639
|
}) {
|
|
12582
|
-
const [panelWidth, setPanelWidth] =
|
|
12583
|
-
const [applied, setApplied] =
|
|
12584
|
-
const [draft, setDraft] =
|
|
12585
|
-
const dragging =
|
|
12586
|
-
|
|
12640
|
+
const [panelWidth, setPanelWidth] = React63.useState(width);
|
|
12641
|
+
const [applied, setApplied] = React63.useState({});
|
|
12642
|
+
const [draft, setDraft] = React63.useState("");
|
|
12643
|
+
const dragging = React63.useRef(null);
|
|
12644
|
+
React63.useEffect(() => setPanelWidth(width), [width]);
|
|
12587
12645
|
const engine = useChatEngine({
|
|
12588
12646
|
contextType,
|
|
12589
12647
|
contextId,
|
|
@@ -12787,7 +12845,7 @@ function AgentChatPanel({
|
|
|
12787
12845
|
}
|
|
12788
12846
|
|
|
12789
12847
|
// src/components/files/FileViewer.tsx
|
|
12790
|
-
var
|
|
12848
|
+
var React64 = __toESM(require("react"), 1);
|
|
12791
12849
|
var import_jsx_runtime93 = require("react/jsx-runtime");
|
|
12792
12850
|
function previewKindOf(file) {
|
|
12793
12851
|
const mime = (file.mime || "").toLowerCase();
|
|
@@ -12844,13 +12902,13 @@ function parseDelimited(text, delimiter) {
|
|
|
12844
12902
|
return rows;
|
|
12845
12903
|
}
|
|
12846
12904
|
function usePreview(file, kind, resolveUrl) {
|
|
12847
|
-
const [state, setState] =
|
|
12848
|
-
const [attempt, setAttempt] =
|
|
12849
|
-
const resolveRef =
|
|
12850
|
-
|
|
12905
|
+
const [state, setState] = React64.useState({ status: "loading" });
|
|
12906
|
+
const [attempt, setAttempt] = React64.useState(0);
|
|
12907
|
+
const resolveRef = React64.useRef(resolveUrl);
|
|
12908
|
+
React64.useEffect(() => {
|
|
12851
12909
|
resolveRef.current = resolveUrl;
|
|
12852
12910
|
}, [resolveUrl]);
|
|
12853
|
-
|
|
12911
|
+
React64.useEffect(() => {
|
|
12854
12912
|
if (kind === "none") {
|
|
12855
12913
|
setState({ status: "ready" });
|
|
12856
12914
|
return;
|
|
@@ -12880,7 +12938,7 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
12880
12938
|
if (ac) ac.abort();
|
|
12881
12939
|
};
|
|
12882
12940
|
}, [file.id, kind, attempt]);
|
|
12883
|
-
return { ...state, retry:
|
|
12941
|
+
return { ...state, retry: React64.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
12884
12942
|
}
|
|
12885
12943
|
function PreviewBody({ file, kind, state }) {
|
|
12886
12944
|
if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
@@ -12925,13 +12983,13 @@ function PreviewBody({ file, kind, state }) {
|
|
|
12925
12983
|
] });
|
|
12926
12984
|
}
|
|
12927
12985
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
12928
|
-
const kind =
|
|
12986
|
+
const kind = React64.useMemo(() => previewKindOf(file), [file]);
|
|
12929
12987
|
const preview = usePreview(file, kind, resolveUrl);
|
|
12930
|
-
const [tab, setTab] =
|
|
12931
|
-
const [downloading, setDownloading] =
|
|
12932
|
-
const [downloadError, setDownloadError] =
|
|
12988
|
+
const [tab, setTab] = React64.useState("preview");
|
|
12989
|
+
const [downloading, setDownloading] = React64.useState(false);
|
|
12990
|
+
const [downloadError, setDownloadError] = React64.useState(null);
|
|
12933
12991
|
const hasSide = sidePanel != null;
|
|
12934
|
-
|
|
12992
|
+
React64.useEffect(() => {
|
|
12935
12993
|
setTab("preview");
|
|
12936
12994
|
}, [file.id]);
|
|
12937
12995
|
const download = () => {
|
|
@@ -12998,7 +13056,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
12998
13056
|
}
|
|
12999
13057
|
|
|
13000
13058
|
// src/components/files/FileBrowser.tsx
|
|
13001
|
-
var
|
|
13059
|
+
var React65 = __toESM(require("react"), 1);
|
|
13002
13060
|
var import_jsx_runtime94 = require("react/jsx-runtime");
|
|
13003
13061
|
function childrenOf(folders, parentId) {
|
|
13004
13062
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -13069,10 +13127,10 @@ function FolderPickerMenu({
|
|
|
13069
13127
|
destinations,
|
|
13070
13128
|
onPick
|
|
13071
13129
|
}) {
|
|
13072
|
-
const [open, setOpen] =
|
|
13130
|
+
const [open, setOpen] = React65.useState(false);
|
|
13073
13131
|
const zIndex = useOverlayLayer(open);
|
|
13074
|
-
const ref =
|
|
13075
|
-
|
|
13132
|
+
const ref = React65.useRef(null);
|
|
13133
|
+
React65.useEffect(() => {
|
|
13076
13134
|
if (!open) return;
|
|
13077
13135
|
const away = (e) => {
|
|
13078
13136
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -13124,8 +13182,8 @@ function FolderPickerMenu({
|
|
|
13124
13182
|
] });
|
|
13125
13183
|
}
|
|
13126
13184
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
13127
|
-
const [over, setOver] =
|
|
13128
|
-
const dragCounter =
|
|
13185
|
+
const [over, setOver] = React65.useState(false);
|
|
13186
|
+
const dragCounter = React65.useRef(0);
|
|
13129
13187
|
const dropHandlers = isDropTarget ? {
|
|
13130
13188
|
onDragEnter: (e) => {
|
|
13131
13189
|
if (!hasInternalPayload(e)) return;
|
|
@@ -13173,8 +13231,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
13173
13231
|
}
|
|
13174
13232
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
13175
13233
|
const kids = childrenOf(folders, folder.id);
|
|
13176
|
-
const [expanded, setExpanded] =
|
|
13177
|
-
|
|
13234
|
+
const [expanded, setExpanded] = React65.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
13235
|
+
React65.useEffect(() => {
|
|
13178
13236
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
13179
13237
|
}, [currentFolderId, folder.id, folders]);
|
|
13180
13238
|
const isCurrent = folder.id === currentFolderId;
|
|
@@ -13240,15 +13298,15 @@ function FileBrowser({
|
|
|
13240
13298
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
13241
13299
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
13242
13300
|
const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
|
|
13243
|
-
const [createOpen, setCreateOpen] =
|
|
13244
|
-
const [createName, setCreateName] =
|
|
13245
|
-
const [renameTarget, setRenameTarget] =
|
|
13246
|
-
const [renameValue, setRenameValue] =
|
|
13247
|
-
const [deleteTarget, setDeleteTarget] =
|
|
13248
|
-
const uploadInputRef =
|
|
13249
|
-
const crumbFolders =
|
|
13250
|
-
const subfolders =
|
|
13251
|
-
const currentFiles =
|
|
13301
|
+
const [createOpen, setCreateOpen] = React65.useState(false);
|
|
13302
|
+
const [createName, setCreateName] = React65.useState("");
|
|
13303
|
+
const [renameTarget, setRenameTarget] = React65.useState(null);
|
|
13304
|
+
const [renameValue, setRenameValue] = React65.useState("");
|
|
13305
|
+
const [deleteTarget, setDeleteTarget] = React65.useState(null);
|
|
13306
|
+
const uploadInputRef = React65.useRef(null);
|
|
13307
|
+
const crumbFolders = React65.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
13308
|
+
const subfolders = React65.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
|
|
13309
|
+
const currentFiles = React65.useMemo(
|
|
13252
13310
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
13253
13311
|
[files, currentFolderId]
|
|
13254
13312
|
);
|
|
@@ -13480,8 +13538,8 @@ function BreadcrumbCrumb({
|
|
|
13480
13538
|
isDropTarget,
|
|
13481
13539
|
onDropPayload
|
|
13482
13540
|
}) {
|
|
13483
|
-
const [over, setOver] =
|
|
13484
|
-
const dragCounter =
|
|
13541
|
+
const [over, setOver] = React65.useState(false);
|
|
13542
|
+
const dragCounter = React65.useRef(0);
|
|
13485
13543
|
const dropHandlers = isDropTarget ? {
|
|
13486
13544
|
onDragEnter: (e) => {
|
|
13487
13545
|
if (!hasInternalPayload(e)) return;
|
|
@@ -13510,7 +13568,7 @@ function BreadcrumbCrumb({
|
|
|
13510
13568
|
}
|
|
13511
13569
|
|
|
13512
13570
|
// src/kits/query.ts
|
|
13513
|
-
var
|
|
13571
|
+
var React66 = __toESM(require("react"), 1);
|
|
13514
13572
|
var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
|
|
13515
13573
|
var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
|
|
13516
13574
|
var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
|
|
@@ -13565,22 +13623,22 @@ function compare(a, b, dir) {
|
|
|
13565
13623
|
var API = null;
|
|
13566
13624
|
var PREFS = null;
|
|
13567
13625
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
13568
|
-
const [query, setQuery] =
|
|
13626
|
+
const [query, setQuery] = React66.useState(() => {
|
|
13569
13627
|
const store = PREFS || window.PlannerPrefs;
|
|
13570
13628
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
13571
13629
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
13572
13630
|
});
|
|
13573
|
-
const savePref =
|
|
13631
|
+
const savePref = React66.useCallback((patch2) => {
|
|
13574
13632
|
const store = PREFS || window.PlannerPrefs;
|
|
13575
13633
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
13576
13634
|
}, [prefsKey]);
|
|
13577
|
-
const [res, setRes] =
|
|
13578
|
-
const [loading, setLoading] =
|
|
13579
|
-
const seq2 =
|
|
13635
|
+
const [res, setRes] = React66.useState(null);
|
|
13636
|
+
const [loading, setLoading] = React66.useState(true);
|
|
13637
|
+
const seq2 = React66.useRef(0);
|
|
13580
13638
|
const depKey = (deps || []).join("|");
|
|
13581
13639
|
const paramKey = JSON.stringify(params || {});
|
|
13582
13640
|
const queryKey = JSON.stringify(query);
|
|
13583
|
-
|
|
13641
|
+
React66.useEffect(() => {
|
|
13584
13642
|
const id = ++seq2.current;
|
|
13585
13643
|
setLoading(true);
|
|
13586
13644
|
const t = setTimeout(() => {
|
|
@@ -13899,12 +13957,12 @@ function createVersionStore(initialState, options) {
|
|
|
13899
13957
|
}
|
|
13900
13958
|
|
|
13901
13959
|
// src/kits/documentTitle.ts
|
|
13902
|
-
var
|
|
13960
|
+
var React67 = __toESM(require("react"), 1);
|
|
13903
13961
|
function formatDocumentTitle(routeTitle, appName) {
|
|
13904
13962
|
return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
|
|
13905
13963
|
}
|
|
13906
13964
|
function useDocumentTitle(routeTitle, appName) {
|
|
13907
|
-
|
|
13965
|
+
React67.useEffect(() => {
|
|
13908
13966
|
if (typeof document === "undefined") return;
|
|
13909
13967
|
document.title = formatDocumentTitle(routeTitle, appName);
|
|
13910
13968
|
}, [routeTitle, appName]);
|