@flytedan/flytebot-design-system 0.32.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -6
- package/dist/index.cjs +502 -390
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -5
- package/dist/index.d.ts +23 -5
- package/dist/index.js +502 -390
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.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;
|
|
@@ -3217,7 +3224,8 @@ function NumberInput({
|
|
|
3217
3224
|
)
|
|
3218
3225
|
] })
|
|
3219
3226
|
] }),
|
|
3220
|
-
|
|
3227
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { id: errorId, className: "fd-sr", role: "status", children: shownError ?? "" }),
|
|
3228
|
+
shownError ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "fd-field-error", "aria-hidden": "true", children: [
|
|
3221
3229
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3222
3230
|
shownError
|
|
3223
3231
|
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
@@ -3225,7 +3233,7 @@ function NumberInput({
|
|
|
3225
3233
|
}
|
|
3226
3234
|
|
|
3227
3235
|
// src/components/forms/DatePicker.tsx
|
|
3228
|
-
var
|
|
3236
|
+
var React23 = __toESM(require("react"), 1);
|
|
3229
3237
|
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
3230
3238
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
3231
3239
|
var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
@@ -3243,10 +3251,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3243
3251
|
const today = /* @__PURE__ */ new Date();
|
|
3244
3252
|
const sel = range ? value || {} : { start: value, end: value };
|
|
3245
3253
|
const anchor = parse(sel.start) || parse(initialMonth) || today;
|
|
3246
|
-
const [vy, setVy] =
|
|
3247
|
-
const [vm, setVm] =
|
|
3248
|
-
const [mode2, setMode] =
|
|
3249
|
-
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);
|
|
3250
3258
|
const s = parse(sel.start), e = parse(sel.end);
|
|
3251
3259
|
const hoverEnd = range && s && !e && hover ? parse(hover) : null;
|
|
3252
3260
|
const inRange = (d) => {
|
|
@@ -3362,9 +3370,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3362
3370
|
}
|
|
3363
3371
|
function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, ...rest }) {
|
|
3364
3372
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
3365
|
-
const [open, setOpen] =
|
|
3366
|
-
const rootRef =
|
|
3367
|
-
const boxRef =
|
|
3373
|
+
const [open, setOpen] = React23.useState(false);
|
|
3374
|
+
const rootRef = React23.useRef(null);
|
|
3375
|
+
const boxRef = React23.useRef(null);
|
|
3368
3376
|
const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
|
|
3369
3377
|
const toggle = () => {
|
|
3370
3378
|
if (!disabled) setOpen(!open);
|
|
@@ -3442,9 +3450,9 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
|
|
|
3442
3450
|
}
|
|
3443
3451
|
|
|
3444
3452
|
// src/components/forms/listbox.ts
|
|
3445
|
-
var
|
|
3453
|
+
var React24 = __toESM(require("react"), 1);
|
|
3446
3454
|
function useListboxNav({ count, onSelect }) {
|
|
3447
|
-
const [active, setActive] =
|
|
3455
|
+
const [active, setActive] = React24.useState(-1);
|
|
3448
3456
|
return {
|
|
3449
3457
|
active,
|
|
3450
3458
|
setActive,
|
|
@@ -3457,7 +3465,7 @@ function useListboxNav({ count, onSelect }) {
|
|
|
3457
3465
|
};
|
|
3458
3466
|
}
|
|
3459
3467
|
function useListboxScrollIntoView(active, listRef, enabled) {
|
|
3460
|
-
|
|
3468
|
+
React24.useEffect(() => {
|
|
3461
3469
|
if (!enabled || active < 0 || !listRef.current) return;
|
|
3462
3470
|
const list = listRef.current;
|
|
3463
3471
|
const el = list.querySelector('[data-i="' + active + '"]');
|
|
@@ -3644,42 +3652,40 @@ function MultiSelectPanel({
|
|
|
3644
3652
|
onClose
|
|
3645
3653
|
}) {
|
|
3646
3654
|
const allowedOps = operatorsFor(field);
|
|
3647
|
-
const [draftOperator, setDraftOperator] =
|
|
3655
|
+
const [draftOperator, setDraftOperator] = React25.useState(value?.operator ?? allowedOps[0]);
|
|
3648
3656
|
const operator = allowedOps.length === 1 ? allowedOps[0] : value?.operator ?? draftOperator;
|
|
3649
3657
|
const selected = value?.values ?? [];
|
|
3650
|
-
const selectedRef =
|
|
3651
|
-
|
|
3652
|
-
const
|
|
3653
|
-
|
|
3654
|
-
const mountedRef = React24.useRef(true);
|
|
3655
|
-
React24.useEffect(() => {
|
|
3658
|
+
const selectedRef = useLatest(selected);
|
|
3659
|
+
const operatorRef = useLatest(operator);
|
|
3660
|
+
const mountedRef = React25.useRef(true);
|
|
3661
|
+
React25.useEffect(() => {
|
|
3656
3662
|
mountedRef.current = true;
|
|
3657
3663
|
return () => {
|
|
3658
3664
|
mountedRef.current = false;
|
|
3659
3665
|
};
|
|
3660
3666
|
}, []);
|
|
3661
|
-
const commit = (nextValues, nextOperator =
|
|
3662
|
-
|
|
3667
|
+
const commit = (nextValues, nextOperator = operatorRef.current) => {
|
|
3668
|
+
setDraftOperator(nextOperator);
|
|
3669
|
+
return onCommit({ operator: nextOperator, values: nextValues });
|
|
3663
3670
|
};
|
|
3664
3671
|
const setOperator = (op) => {
|
|
3665
|
-
setDraftOperator(op);
|
|
3666
3672
|
if (selectedRef.current.length > 0) commit(selectedRef.current, op);
|
|
3673
|
+
else setDraftOperator(op);
|
|
3667
3674
|
};
|
|
3668
|
-
const [mode2, setMode] =
|
|
3669
|
-
const [query, setQuery] =
|
|
3670
|
-
const [asyncState, setAsyncState] =
|
|
3675
|
+
const [mode2, setMode] = React25.useState("search");
|
|
3676
|
+
const [query, setQuery] = React25.useState("");
|
|
3677
|
+
const [asyncState, setAsyncState] = React25.useState(
|
|
3671
3678
|
{ options: null, loading: !!field.loadOptions, error: false }
|
|
3672
3679
|
);
|
|
3673
|
-
const [retryTick, setRetryTick] =
|
|
3674
|
-
const inputRef =
|
|
3675
|
-
const listRef =
|
|
3676
|
-
const listId =
|
|
3677
|
-
const loadOptionsRef =
|
|
3678
|
-
|
|
3679
|
-
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(() => {
|
|
3680
3686
|
inputRef.current?.focus();
|
|
3681
3687
|
}, []);
|
|
3682
|
-
|
|
3688
|
+
React25.useEffect(() => {
|
|
3683
3689
|
const load = loadOptionsRef.current;
|
|
3684
3690
|
if (!load) return;
|
|
3685
3691
|
const controller = new AbortController();
|
|
@@ -3697,7 +3703,7 @@ function MultiSelectPanel({
|
|
|
3697
3703
|
clearTimeout(t);
|
|
3698
3704
|
controller.abort();
|
|
3699
3705
|
};
|
|
3700
|
-
}, [query, retryTick]);
|
|
3706
|
+
}, [query, retryTick, loadOptionsRef]);
|
|
3701
3707
|
const options = field.loadOptions ? asyncState.options ?? [] : (field.options ?? []).filter((o) => o.label.toLowerCase().includes(query.toLowerCase()));
|
|
3702
3708
|
const showLoading = !!field.loadOptions && asyncState.loading;
|
|
3703
3709
|
const showError = !!field.loadOptions && asyncState.error;
|
|
@@ -3712,17 +3718,17 @@ function MultiSelectPanel({
|
|
|
3712
3718
|
};
|
|
3713
3719
|
const nav = useListboxNav({ count: options.length, onSelect: (i) => toggle(options[i]) });
|
|
3714
3720
|
useListboxScrollIntoView(nav.active, listRef, hasListbox);
|
|
3715
|
-
|
|
3721
|
+
React25.useEffect(() => {
|
|
3716
3722
|
nav.setActive(0);
|
|
3717
3723
|
}, [query, options.length]);
|
|
3718
3724
|
const activeId = hasListbox && options[nav.active] ? listId + "-opt-" + nav.active : void 0;
|
|
3719
3725
|
const liveMessage = showLoading ? "Loading\u2026" : showError ? "Couldn't load options." : options.length === 0 ? "No matches" : atLimit ? "Limit reached: at most " + field.maxValues + " values" : "";
|
|
3720
|
-
const [pasteText, setPasteText] =
|
|
3721
|
-
const [pasteLoading, setPasteLoading] =
|
|
3722
|
-
const [unmatchedTokens, setUnmatchedTokens] =
|
|
3723
|
-
const [pasteError, setPasteError] =
|
|
3724
|
-
const pasteWrapRef =
|
|
3725
|
-
|
|
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(() => {
|
|
3726
3732
|
if (mode2 === "paste") pasteWrapRef.current?.querySelector("textarea")?.focus();
|
|
3727
3733
|
}, [mode2]);
|
|
3728
3734
|
const doResolve = () => {
|
|
@@ -3741,7 +3747,11 @@ function MultiSelectPanel({
|
|
|
3741
3747
|
setPasteError("This filter allows at most " + field.maxValues + " values; adding this list would make " + merged.size + ".");
|
|
3742
3748
|
return;
|
|
3743
3749
|
}
|
|
3744
|
-
commit(Array.from(merged.values())
|
|
3750
|
+
const applied = commit(Array.from(merged.values()));
|
|
3751
|
+
if (!applied.ok) {
|
|
3752
|
+
setPasteError(applied.reason);
|
|
3753
|
+
return;
|
|
3754
|
+
}
|
|
3745
3755
|
setPasteText("");
|
|
3746
3756
|
}, (err) => {
|
|
3747
3757
|
if (!mountedRef.current) return;
|
|
@@ -3878,6 +3888,59 @@ function MultiSelectPanel({
|
|
|
3878
3888
|
}
|
|
3879
3889
|
);
|
|
3880
3890
|
}
|
|
3891
|
+
function useTextValidity(onFlip) {
|
|
3892
|
+
const invalidRef = React25.useRef(/* @__PURE__ */ new Set());
|
|
3893
|
+
const [, rerender] = React25.useReducer((n) => n + 1, 0);
|
|
3894
|
+
const onFlipRef = useLatest(onFlip);
|
|
3895
|
+
const record = (name, valid) => {
|
|
3896
|
+
const invalid = invalidRef.current;
|
|
3897
|
+
if (valid !== invalid.has(name)) return false;
|
|
3898
|
+
if (valid) invalid.delete(name);
|
|
3899
|
+
else invalid.add(name);
|
|
3900
|
+
rerender();
|
|
3901
|
+
return true;
|
|
3902
|
+
};
|
|
3903
|
+
return {
|
|
3904
|
+
allValid: () => invalidRef.current.size === 0,
|
|
3905
|
+
report: (name) => (valid) => {
|
|
3906
|
+
if (record(name, valid)) onFlipRef.current();
|
|
3907
|
+
},
|
|
3908
|
+
/** For an input that is about to unmount: it has nothing left to show. */
|
|
3909
|
+
forget: (name) => {
|
|
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();
|
|
3917
|
+
}
|
|
3918
|
+
};
|
|
3919
|
+
}
|
|
3920
|
+
function applicable(field, candidate, textValid) {
|
|
3921
|
+
if (!textValid || candidate === void 0) return void 0;
|
|
3922
|
+
return validateFilterValue(field, candidate).ok ? candidate : void 0;
|
|
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 });
|
|
3881
3944
|
function RangePanel({
|
|
3882
3945
|
field,
|
|
3883
3946
|
value,
|
|
@@ -3885,21 +3948,34 @@ function RangePanel({
|
|
|
3885
3948
|
onCommit,
|
|
3886
3949
|
onClose
|
|
3887
3950
|
}) {
|
|
3888
|
-
const [draft, setDraft] =
|
|
3889
|
-
const
|
|
3890
|
-
const
|
|
3891
|
-
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 = () => {
|
|
3955
|
+
const { min, max } = draftRef.current;
|
|
3956
|
+
return applicable(field, min == null && max == null ? void 0 : { min, max }, validity.allValid());
|
|
3957
|
+
};
|
|
3958
|
+
const publish = () => {
|
|
3959
|
+
onCommit(shown());
|
|
3960
|
+
};
|
|
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
|
+
});
|
|
3892
3968
|
const draftMin = draft.min;
|
|
3893
3969
|
const draftMax = draft.max;
|
|
3894
3970
|
const isEmpty = draftMin == null && draftMax == null;
|
|
3895
3971
|
const validation = isEmpty ? { ok: true } : validateFilterValue(field, { min: draftMin, max: draftMax });
|
|
3896
3972
|
const comboError = !isEmpty && !validation.ok ? validation.reason : void 0;
|
|
3897
|
-
const doneDisabled = !
|
|
3973
|
+
const doneDisabled = !validity.allValid() || !!comboError;
|
|
3898
3974
|
const apply = (patch) => {
|
|
3899
3975
|
const next = { ...draftRef.current, ...patch };
|
|
3900
3976
|
draftRef.current = next;
|
|
3901
3977
|
setDraft(next);
|
|
3902
|
-
|
|
3978
|
+
publish();
|
|
3903
3979
|
};
|
|
3904
3980
|
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3905
3981
|
Popover,
|
|
@@ -3924,8 +4000,9 @@ function RangePanel({
|
|
|
3924
4000
|
integer: field.integer,
|
|
3925
4001
|
placeholder: field.minPlaceholder,
|
|
3926
4002
|
onChange: (e) => apply({ min: e.target.value }),
|
|
3927
|
-
onValidityChange:
|
|
3928
|
-
}
|
|
4003
|
+
onValidityChange: validity.report("min")
|
|
4004
|
+
},
|
|
4005
|
+
"min-" + seed
|
|
3929
4006
|
),
|
|
3930
4007
|
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3931
4008
|
NumberInput,
|
|
@@ -3939,13 +4016,21 @@ function RangePanel({
|
|
|
3939
4016
|
error: comboError,
|
|
3940
4017
|
placeholder: field.maxPlaceholder,
|
|
3941
4018
|
onChange: (e) => apply({ max: e.target.value }),
|
|
3942
|
-
onValidityChange:
|
|
3943
|
-
}
|
|
4019
|
+
onValidityChange: validity.report("max")
|
|
4020
|
+
},
|
|
4021
|
+
"max-" + seed
|
|
3944
4022
|
)
|
|
3945
4023
|
] })
|
|
3946
4024
|
}
|
|
3947
4025
|
);
|
|
3948
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
|
+
}
|
|
3949
4034
|
function DatePanel({
|
|
3950
4035
|
field,
|
|
3951
4036
|
value,
|
|
@@ -3953,36 +4038,69 @@ function DatePanel({
|
|
|
3953
4038
|
onCommit,
|
|
3954
4039
|
onClose
|
|
3955
4040
|
}) {
|
|
3956
|
-
const defaultDays = field.defaultDays ?? 30;
|
|
3957
4041
|
const maxDays = effectiveMaxDays(field);
|
|
3958
|
-
const [
|
|
3959
|
-
const [kind, setKind] =
|
|
3960
|
-
const [daysDraft, setDaysDraft] =
|
|
3961
|
-
|
|
3962
|
-
);
|
|
3963
|
-
const [between, setBetween] =
|
|
3964
|
-
|
|
3965
|
-
)
|
|
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);
|
|
4049
|
+
const shownWithinDays = () => {
|
|
4050
|
+
const days = daysRef.current;
|
|
4051
|
+
return applicable(field, days == null ? void 0 : { kind: "withinDays", days }, validity.allValid());
|
|
4052
|
+
};
|
|
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
|
+
});
|
|
3966
4073
|
const applyWithinDays = (days) => {
|
|
4074
|
+
daysRef.current = days;
|
|
4075
|
+
daysConfirmed.current = true;
|
|
3967
4076
|
setDaysDraft(days);
|
|
3968
|
-
onCommit(
|
|
4077
|
+
onCommit(shownWithinDays());
|
|
3969
4078
|
};
|
|
3970
4079
|
const applyBetween = (from, to) => {
|
|
3971
4080
|
setBetween({ from, to });
|
|
3972
|
-
onCommit(from && to ? { kind: "between", from, to } : void 0);
|
|
4081
|
+
onCommit(applicable(field, from && to ? { kind: "between", from, to } : void 0, true));
|
|
3973
4082
|
};
|
|
3974
4083
|
const switchKind = (next) => {
|
|
3975
4084
|
if (next === kind) return;
|
|
3976
4085
|
setKind(next);
|
|
3977
|
-
if (next === "between")
|
|
3978
|
-
|
|
3979
|
-
|
|
4086
|
+
if (next === "between") {
|
|
4087
|
+
setBetween({ from: "", to: "" });
|
|
4088
|
+
validity.forget("days");
|
|
4089
|
+
} else {
|
|
4090
|
+
const { days } = dateDraft(field, void 0);
|
|
4091
|
+
daysRef.current = days;
|
|
4092
|
+
daysConfirmed.current = false;
|
|
4093
|
+
setDaysDraft(days);
|
|
4094
|
+
}
|
|
3980
4095
|
onCommit(void 0);
|
|
3981
4096
|
};
|
|
3982
|
-
const doneDisabled = kind === "withinDays" && !
|
|
4097
|
+
const doneDisabled = kind === "withinDays" && !validity.allValid();
|
|
3983
4098
|
const confirm = () => {
|
|
3984
4099
|
if (doneDisabled) return;
|
|
3985
|
-
if (kind === "withinDays"
|
|
4100
|
+
if (kind === "withinDays") {
|
|
4101
|
+
const shown = shownWithinDays();
|
|
4102
|
+
if (shown) onCommit(shown);
|
|
4103
|
+
}
|
|
3986
4104
|
onClose();
|
|
3987
4105
|
};
|
|
3988
4106
|
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
@@ -4019,8 +4137,9 @@ function DatePanel({
|
|
|
4019
4137
|
integer: true,
|
|
4020
4138
|
value: daysDraft ?? "",
|
|
4021
4139
|
onChange: (e) => applyWithinDays(e.target.value),
|
|
4022
|
-
onValidityChange:
|
|
4023
|
-
}
|
|
4140
|
+
onValidityChange: validity.report("days")
|
|
4141
|
+
},
|
|
4142
|
+
"days-" + seed
|
|
4024
4143
|
) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
4025
4144
|
DatePicker,
|
|
4026
4145
|
{
|
|
@@ -4028,23 +4147,23 @@ function DatePanel({
|
|
|
4028
4147
|
label: "Date range",
|
|
4029
4148
|
value: { start: between.from, end: between.to },
|
|
4030
4149
|
onChange: (e) => applyBetween(e.target.value.start || "", e.target.value.end || "")
|
|
4031
|
-
}
|
|
4150
|
+
},
|
|
4151
|
+
"between-" + seed
|
|
4032
4152
|
)
|
|
4033
4153
|
] })
|
|
4034
4154
|
}
|
|
4035
4155
|
);
|
|
4036
4156
|
}
|
|
4037
4157
|
function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align = "left", className = "", ...rest }) {
|
|
4038
|
-
const [panel, setPanel] =
|
|
4039
|
-
const editAnchorRef =
|
|
4040
|
-
const addAnchorRef =
|
|
4041
|
-
const textInputRef =
|
|
4042
|
-
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);
|
|
4043
4163
|
if (process.env.NODE_ENV !== "production") {
|
|
4044
4164
|
for (const f of fields) assertValidFieldDefinition(f);
|
|
4045
4165
|
}
|
|
4046
|
-
const latest =
|
|
4047
|
-
latest.current = { fields, filters, onFilterChange, onFilterRemove };
|
|
4166
|
+
const latest = useLatest({ fields, filters, onFilterChange, onFilterRemove });
|
|
4048
4167
|
const commit = (field, candidate) => {
|
|
4049
4168
|
const current2 = latest.current.fields.find((f) => f.key === field.key);
|
|
4050
4169
|
if (!current2) return { ok: false, reason: "This filter is no longer available" };
|
|
@@ -4053,24 +4172,17 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
|
|
|
4053
4172
|
return { ok: true };
|
|
4054
4173
|
}
|
|
4055
4174
|
const result = validateFilterValue(current2, candidate);
|
|
4056
|
-
if (result.ok)
|
|
4057
|
-
latest.current.filters = { ...latest.current.filters, [current2.key]: candidate };
|
|
4058
|
-
latest.current.onFilterChange(current2.key, candidate);
|
|
4059
|
-
}
|
|
4175
|
+
if (result.ok) latest.current.onFilterChange(current2.key, candidate);
|
|
4060
4176
|
return result;
|
|
4061
4177
|
};
|
|
4062
4178
|
const removeField = (field) => {
|
|
4063
4179
|
const { filters: now, onFilterRemove: remove } = latest.current;
|
|
4064
|
-
if (
|
|
4065
|
-
const next = { ...now };
|
|
4066
|
-
delete next[field.key];
|
|
4067
|
-
latest.current.filters = next;
|
|
4068
|
-
remove(field.key);
|
|
4180
|
+
if (isFieldSet(field, now[field.key])) remove(field.key);
|
|
4069
4181
|
};
|
|
4070
4182
|
const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
|
|
4071
4183
|
const startEditing = (key) => setPanel({ kind: "edit", key });
|
|
4072
4184
|
const closeEditing = () => setPanel(null);
|
|
4073
|
-
|
|
4185
|
+
React25.useEffect(() => {
|
|
4074
4186
|
if (!panel || panel.kind !== "edit") return;
|
|
4075
4187
|
if (editingField?.type === "text") {
|
|
4076
4188
|
textInputRef.current?.focus();
|
|
@@ -4276,7 +4388,7 @@ function StatTile({ label, value, sub, delta, invert = false, loading = false, c
|
|
|
4276
4388
|
}
|
|
4277
4389
|
|
|
4278
4390
|
// src/components/data/CodeBlock.tsx
|
|
4279
|
-
var
|
|
4391
|
+
var React26 = __toESM(require("react"), 1);
|
|
4280
4392
|
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
4281
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)$/;
|
|
4282
4394
|
var RULES = {
|
|
@@ -4432,13 +4544,13 @@ function tokenize(src, lang) {
|
|
|
4432
4544
|
return out;
|
|
4433
4545
|
}
|
|
4434
4546
|
function Highlighted({ code, lang }) {
|
|
4435
|
-
const toks =
|
|
4547
|
+
const toks = React26.useMemo(() => tokenize(code, lang), [code, lang]);
|
|
4436
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) });
|
|
4437
4549
|
}
|
|
4438
4550
|
function useCopy() {
|
|
4439
|
-
const [done, setDone] =
|
|
4440
|
-
const timer =
|
|
4441
|
-
|
|
4551
|
+
const [done, setDone] = React26.useState(false);
|
|
4552
|
+
const timer = React26.useRef(null);
|
|
4553
|
+
React26.useEffect(() => () => {
|
|
4442
4554
|
if (timer.current) clearTimeout(timer.current);
|
|
4443
4555
|
}, []);
|
|
4444
4556
|
const copy = (text) => {
|
|
@@ -4474,8 +4586,8 @@ function CodeBlock({
|
|
|
4474
4586
|
actions,
|
|
4475
4587
|
className = ""
|
|
4476
4588
|
}) {
|
|
4477
|
-
const [wrap, setWrap] =
|
|
4478
|
-
const [open, setOpen] =
|
|
4589
|
+
const [wrap, setWrap] = React26.useState(!!wrapDefault);
|
|
4590
|
+
const [open, setOpen] = React26.useState(false);
|
|
4479
4591
|
const [copied, copy] = useCopy();
|
|
4480
4592
|
const body = String(code).replace(/\n$/, "");
|
|
4481
4593
|
const lines = body.split("\n");
|
|
@@ -4504,7 +4616,7 @@ function CodeBlock({
|
|
|
4504
4616
|
] });
|
|
4505
4617
|
}
|
|
4506
4618
|
function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
|
|
4507
|
-
const [open, setOpen] =
|
|
4619
|
+
const [open, setOpen] = React26.useState(false);
|
|
4508
4620
|
const [copied, copy] = useCopy();
|
|
4509
4621
|
const raw = String(diff).replace(/\n$/, "");
|
|
4510
4622
|
const all = raw.split("\n").map((line) => {
|
|
@@ -4550,7 +4662,7 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
|
|
|
4550
4662
|
}
|
|
4551
4663
|
|
|
4552
4664
|
// src/components/data/Markdown.tsx
|
|
4553
|
-
var
|
|
4665
|
+
var React27 = __toESM(require("react"), 1);
|
|
4554
4666
|
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
4555
4667
|
var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
|
|
4556
4668
|
var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
|
|
@@ -4589,7 +4701,7 @@ function inlineNodes(src, ctx, keyBase) {
|
|
|
4589
4701
|
const href = safeHref(g(2));
|
|
4590
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()));
|
|
4591
4703
|
} else if (kind === "cite") {
|
|
4592
|
-
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()));
|
|
4593
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()));
|
|
4594
4706
|
else if (kind === "strong") out.push(/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
4595
4707
|
else if (kind === "em") out.push(/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
|
|
@@ -4754,7 +4866,7 @@ function Markdown({
|
|
|
4754
4866
|
onLinkClick
|
|
4755
4867
|
}) {
|
|
4756
4868
|
const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
|
|
4757
|
-
const blocks =
|
|
4869
|
+
const blocks = React27.useMemo(() => parseBlocks(source), [source]);
|
|
4758
4870
|
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: ["fd-md", className].filter(Boolean).join(" "), children: renderBlocks(blocks, ctx, "b") });
|
|
4759
4871
|
}
|
|
4760
4872
|
function MarkdownInline({ source = "", className = "", onLinkClick }) {
|
|
@@ -4868,7 +4980,7 @@ function Pagination({
|
|
|
4868
4980
|
}
|
|
4869
4981
|
|
|
4870
4982
|
// src/components/data/RelativeTime.tsx
|
|
4871
|
-
var
|
|
4983
|
+
var React28 = __toESM(require("react"), 1);
|
|
4872
4984
|
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
4873
4985
|
var MIN = 6e4;
|
|
4874
4986
|
var HOUR = 36e5;
|
|
@@ -4920,9 +5032,9 @@ function formatDuration(ms) {
|
|
|
4920
5032
|
return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
|
|
4921
5033
|
}
|
|
4922
5034
|
function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
|
|
4923
|
-
const [, force] =
|
|
5035
|
+
const [, force] = React28.useState(0);
|
|
4924
5036
|
const t = value instanceof Date ? value.getTime() : Date.parse(value);
|
|
4925
|
-
|
|
5037
|
+
React28.useEffect(() => {
|
|
4926
5038
|
if (!refresh2 || !t || isNaN(t)) return;
|
|
4927
5039
|
const abs = Math.abs(t - Date.now());
|
|
4928
5040
|
if (abs > DAY) return;
|
|
@@ -4938,7 +5050,7 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
|
|
|
4938
5050
|
}
|
|
4939
5051
|
|
|
4940
5052
|
// src/components/data/ScoreMeter.tsx
|
|
4941
|
-
var
|
|
5053
|
+
var React29 = __toESM(require("react"), 1);
|
|
4942
5054
|
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
4943
5055
|
function ScoreMeter({
|
|
4944
5056
|
score,
|
|
@@ -4953,10 +5065,10 @@ function ScoreMeter({
|
|
|
4953
5065
|
breakdownWidth = 280,
|
|
4954
5066
|
className = ""
|
|
4955
5067
|
}) {
|
|
4956
|
-
const [open, setOpen] =
|
|
4957
|
-
const ref =
|
|
5068
|
+
const [open, setOpen] = React29.useState(false);
|
|
5069
|
+
const ref = React29.useRef(null);
|
|
4958
5070
|
const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
|
|
4959
|
-
const body = /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
5071
|
+
const body = /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React29.Fragment, { children: [
|
|
4960
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 }) }),
|
|
4961
5073
|
showScore ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
|
|
4962
5074
|
] });
|
|
@@ -4975,7 +5087,7 @@ function ScoreMeter({
|
|
|
4975
5087
|
}
|
|
4976
5088
|
);
|
|
4977
5089
|
}
|
|
4978
|
-
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
5090
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React29.Fragment, { children: [
|
|
4979
5091
|
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
4980
5092
|
"button",
|
|
4981
5093
|
{
|
|
@@ -5006,13 +5118,13 @@ function ScoreMeter({
|
|
|
5006
5118
|
}
|
|
5007
5119
|
|
|
5008
5120
|
// src/components/data/SortMenu.tsx
|
|
5009
|
-
var
|
|
5121
|
+
var React30 = __toESM(require("react"), 1);
|
|
5010
5122
|
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
5011
5123
|
function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", className = "", ...rest }) {
|
|
5012
|
-
const [open, setOpen] =
|
|
5124
|
+
const [open, setOpen] = React30.useState(false);
|
|
5013
5125
|
const zIndex = useOverlayLayer(open);
|
|
5014
|
-
const ref =
|
|
5015
|
-
|
|
5126
|
+
const ref = React30.useRef(null);
|
|
5127
|
+
React30.useEffect(() => {
|
|
5016
5128
|
if (!open) return;
|
|
5017
5129
|
const away = (e) => {
|
|
5018
5130
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -5074,7 +5186,7 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
|
|
|
5074
5186
|
}
|
|
5075
5187
|
|
|
5076
5188
|
// src/components/data/StepList.tsx
|
|
5077
|
-
var
|
|
5189
|
+
var React31 = __toESM(require("react"), 1);
|
|
5078
5190
|
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
5079
5191
|
var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
|
|
5080
5192
|
function StepList({
|
|
@@ -5087,9 +5199,9 @@ function StepList({
|
|
|
5087
5199
|
dense = false,
|
|
5088
5200
|
className = ""
|
|
5089
5201
|
}) {
|
|
5090
|
-
const [openState, setOpenState] =
|
|
5202
|
+
const [openState, setOpenState] = React31.useState(defaultOpen);
|
|
5091
5203
|
const open = openProp == null ? openState : openProp;
|
|
5092
|
-
const [expanded, setExpanded] =
|
|
5204
|
+
const [expanded, setExpanded] = React31.useState({});
|
|
5093
5205
|
if (!steps.length) return null;
|
|
5094
5206
|
const running = steps.some((s) => s.status === "running");
|
|
5095
5207
|
const failed = steps.filter((s) => s.status === "error").length;
|
|
@@ -5147,7 +5259,7 @@ function StepList({
|
|
|
5147
5259
|
}
|
|
5148
5260
|
|
|
5149
5261
|
// src/components/data/VirtualList.tsx
|
|
5150
|
-
var
|
|
5262
|
+
var React32 = __toESM(require("react"), 1);
|
|
5151
5263
|
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
5152
5264
|
var VIRTUAL_LIST_BUFFER_ROWS = 20;
|
|
5153
5265
|
var VIRTUAL_LIST_ROW_GAP = 6;
|
|
@@ -5199,35 +5311,35 @@ function VirtualList({
|
|
|
5199
5311
|
className = "",
|
|
5200
5312
|
style
|
|
5201
5313
|
}) {
|
|
5202
|
-
const [scrollTop, setScrollTop] =
|
|
5203
|
-
const loaded =
|
|
5314
|
+
const [scrollTop, setScrollTop] = React32.useState(0);
|
|
5315
|
+
const loaded = React32.useMemo(
|
|
5204
5316
|
() => ({ firstItemIndex, count: items.length }),
|
|
5205
5317
|
[firstItemIndex, items.length]
|
|
5206
5318
|
);
|
|
5207
5319
|
const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
|
|
5208
5320
|
const bandKey = firstItemIndex + ":" + items.length;
|
|
5209
|
-
const win =
|
|
5321
|
+
const win = React32.useMemo(
|
|
5210
5322
|
() => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
|
|
5211
5323
|
[scrollTop, height, itemHeight, total, loaded]
|
|
5212
5324
|
);
|
|
5213
|
-
const need =
|
|
5325
|
+
const need = React32.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
|
|
5214
5326
|
const wantStart = need.start && hasMore?.start !== false;
|
|
5215
5327
|
const wantEnd = need.end && hasMore?.end !== false;
|
|
5216
5328
|
const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
|
|
5217
5329
|
const askKey = bandKey + "@" + bucket2;
|
|
5218
|
-
const asked =
|
|
5219
|
-
|
|
5330
|
+
const asked = React32.useRef({ start: null, end: null });
|
|
5331
|
+
React32.useEffect(() => {
|
|
5220
5332
|
if (loading || !wantStart || asked.current.start === askKey) return;
|
|
5221
5333
|
asked.current.start = askKey;
|
|
5222
5334
|
onNeedMore("start", win);
|
|
5223
5335
|
}, [wantStart, loading, askKey, onNeedMore, win]);
|
|
5224
|
-
|
|
5336
|
+
React32.useEffect(() => {
|
|
5225
5337
|
if (loading || !wantEnd || asked.current.end === askKey) return;
|
|
5226
5338
|
asked.current.end = askKey;
|
|
5227
5339
|
onNeedMore("end", win);
|
|
5228
5340
|
}, [wantEnd, loading, askKey, onNeedMore, win]);
|
|
5229
|
-
const lastKeysRef =
|
|
5230
|
-
const newKeys =
|
|
5341
|
+
const lastKeysRef = React32.useRef(null);
|
|
5342
|
+
const newKeys = React32.useMemo(() => {
|
|
5231
5343
|
const prev = lastKeysRef.current;
|
|
5232
5344
|
if (!prev) return /* @__PURE__ */ new Set();
|
|
5233
5345
|
const fresh = /* @__PURE__ */ new Set();
|
|
@@ -5237,7 +5349,7 @@ function VirtualList({
|
|
|
5237
5349
|
}
|
|
5238
5350
|
return fresh;
|
|
5239
5351
|
}, [items]);
|
|
5240
|
-
|
|
5352
|
+
React32.useEffect(() => {
|
|
5241
5353
|
lastKeysRef.current = new Set(items.map(keyOf));
|
|
5242
5354
|
}, [items]);
|
|
5243
5355
|
const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
|
|
@@ -5282,7 +5394,7 @@ function VirtualList({
|
|
|
5282
5394
|
}
|
|
5283
5395
|
|
|
5284
5396
|
// src/components/data/EntityRow.tsx
|
|
5285
|
-
var
|
|
5397
|
+
var React33 = __toESM(require("react"), 1);
|
|
5286
5398
|
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
5287
5399
|
var ENTITY_ROW_METRIC_WIDTH = 74;
|
|
5288
5400
|
var METRIC_TONE_COLOR = {
|
|
@@ -5295,7 +5407,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
|
|
|
5295
5407
|
const key = m.id || m.label || i;
|
|
5296
5408
|
const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
|
|
5297
5409
|
const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
|
|
5298
|
-
const content = /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
|
|
5410
|
+
const content = /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(React33.Fragment, { children: [
|
|
5299
5411
|
m.icon ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
|
|
5300
5412
|
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
|
|
5301
5413
|
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-sr", children: " " + m.label })
|
|
@@ -5387,7 +5499,7 @@ function EntityRow({
|
|
|
5387
5499
|
}
|
|
5388
5500
|
|
|
5389
5501
|
// src/components/data/TransferList.tsx
|
|
5390
|
-
var
|
|
5502
|
+
var React34 = __toESM(require("react"), 1);
|
|
5391
5503
|
var import_react_dom5 = require("react-dom");
|
|
5392
5504
|
|
|
5393
5505
|
// src/components/forms/Input.tsx
|
|
@@ -5493,12 +5605,12 @@ function TransferList({
|
|
|
5493
5605
|
listHeight = 440,
|
|
5494
5606
|
className = ""
|
|
5495
5607
|
}) {
|
|
5496
|
-
const [drag, setDrag] =
|
|
5497
|
-
const [dragOverSide, setDragOverSide] =
|
|
5498
|
-
const dragRef =
|
|
5499
|
-
const armedRef =
|
|
5500
|
-
const sideRefs =
|
|
5501
|
-
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) => {
|
|
5502
5614
|
for (const side of ["left", "right"]) {
|
|
5503
5615
|
const el = sideRefs.current[side];
|
|
5504
5616
|
if (!el) continue;
|
|
@@ -5507,7 +5619,7 @@ function TransferList({
|
|
|
5507
5619
|
}
|
|
5508
5620
|
return null;
|
|
5509
5621
|
}, []);
|
|
5510
|
-
const findItem =
|
|
5622
|
+
const findItem = React34.useCallback(
|
|
5511
5623
|
(side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
|
|
5512
5624
|
[left.items, right.items, keyOf]
|
|
5513
5625
|
);
|
|
@@ -5529,7 +5641,7 @@ function TransferList({
|
|
|
5529
5641
|
height: rect.height
|
|
5530
5642
|
};
|
|
5531
5643
|
};
|
|
5532
|
-
|
|
5644
|
+
React34.useEffect(() => {
|
|
5533
5645
|
const onMovePointer = (e) => {
|
|
5534
5646
|
const armed = armedRef.current;
|
|
5535
5647
|
if (!armed || e.pointerId !== armed.pointerId) return;
|
|
@@ -5582,7 +5694,7 @@ function TransferList({
|
|
|
5582
5694
|
window.removeEventListener("pointercancel", endDrag);
|
|
5583
5695
|
};
|
|
5584
5696
|
}, [hitTestSide, findItem, onMove]);
|
|
5585
|
-
|
|
5697
|
+
React34.useEffect(() => {
|
|
5586
5698
|
if (!drag || typeof document === "undefined") return;
|
|
5587
5699
|
const prev = document.body.style.userSelect;
|
|
5588
5700
|
document.body.style.userSelect = "none";
|
|
@@ -5690,11 +5802,11 @@ function TransferList({
|
|
|
5690
5802
|
}
|
|
5691
5803
|
|
|
5692
5804
|
// src/components/forms/Checkbox.tsx
|
|
5693
|
-
var
|
|
5805
|
+
var React35 = __toESM(require("react"), 1);
|
|
5694
5806
|
var import_jsx_runtime60 = require("react/jsx-runtime");
|
|
5695
5807
|
function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
|
|
5696
|
-
const ref =
|
|
5697
|
-
|
|
5808
|
+
const ref = React35.useRef(null);
|
|
5809
|
+
React35.useEffect(() => {
|
|
5698
5810
|
if (ref.current) ref.current.indeterminate = indeterminate;
|
|
5699
5811
|
}, [indeterminate]);
|
|
5700
5812
|
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
@@ -5738,7 +5850,7 @@ function Switch({ label, description, className = "", ...rest }) {
|
|
|
5738
5850
|
}
|
|
5739
5851
|
|
|
5740
5852
|
// src/components/forms/Select.tsx
|
|
5741
|
-
var
|
|
5853
|
+
var React36 = __toESM(require("react"), 1);
|
|
5742
5854
|
var import_jsx_runtime63 = require("react/jsx-runtime");
|
|
5743
5855
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
5744
5856
|
function Select({
|
|
@@ -5765,12 +5877,12 @@ function Select({
|
|
|
5765
5877
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
5766
5878
|
const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
|
|
5767
5879
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
5768
|
-
const [open, setOpen] =
|
|
5769
|
-
const [q, setQ] =
|
|
5770
|
-
const rootRef =
|
|
5771
|
-
const boxRef =
|
|
5772
|
-
const listRef =
|
|
5773
|
-
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 });
|
|
5774
5886
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
5775
5887
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
5776
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;
|
|
@@ -5909,7 +6021,7 @@ function Select({
|
|
|
5909
6021
|
),
|
|
5910
6022
|
q ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
5911
6023
|
] }) : void 0,
|
|
5912
|
-
footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
|
|
6024
|
+
footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(React36.Fragment, { children: [
|
|
5913
6025
|
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
|
|
5914
6026
|
"button",
|
|
5915
6027
|
{
|
|
@@ -5940,7 +6052,7 @@ function Select({
|
|
|
5940
6052
|
'Nothing matches "',
|
|
5941
6053
|
q,
|
|
5942
6054
|
'".'
|
|
5943
|
-
] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
|
|
6055
|
+
] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(React36.Fragment, { children: [
|
|
5944
6056
|
grp.g ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
|
|
5945
6057
|
grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
|
|
5946
6058
|
"button",
|
|
@@ -5977,7 +6089,7 @@ function Select({
|
|
|
5977
6089
|
}
|
|
5978
6090
|
|
|
5979
6091
|
// src/components/forms/TimePicker.tsx
|
|
5980
|
-
var
|
|
6092
|
+
var React37 = __toESM(require("react"), 1);
|
|
5981
6093
|
var import_jsx_runtime64 = require("react/jsx-runtime");
|
|
5982
6094
|
var pad = (n) => String(n).padStart(2, "0");
|
|
5983
6095
|
function ClockFace({ value = "09:00", onChange }) {
|
|
@@ -5986,9 +6098,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
5986
6098
|
if (isNaN(m)) m = 0;
|
|
5987
6099
|
const pm = h24 >= 12;
|
|
5988
6100
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
5989
|
-
const [mode2, setMode] =
|
|
5990
|
-
const faceRef =
|
|
5991
|
-
const dragging =
|
|
6101
|
+
const [mode2, setMode] = React37.useState("h");
|
|
6102
|
+
const faceRef = React37.useRef(null);
|
|
6103
|
+
const dragging = React37.useRef(false);
|
|
5992
6104
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
5993
6105
|
const R = 108, NR = 80;
|
|
5994
6106
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -6061,9 +6173,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
6061
6173
|
}
|
|
6062
6174
|
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
|
|
6063
6175
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
6064
|
-
const [open, setOpen] =
|
|
6065
|
-
const rootRef =
|
|
6066
|
-
const boxRef =
|
|
6176
|
+
const [open, setOpen] = React37.useState(false);
|
|
6177
|
+
const rootRef = React37.useRef(null);
|
|
6178
|
+
const boxRef = React37.useRef(null);
|
|
6067
6179
|
const disp = () => {
|
|
6068
6180
|
if (!value) return "";
|
|
6069
6181
|
const [h, m] = value.split(":").map(Number);
|
|
@@ -6106,7 +6218,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
6106
6218
|
offset: 6,
|
|
6107
6219
|
width: 262,
|
|
6108
6220
|
role: "presentation",
|
|
6109
|
-
footer: /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
|
|
6221
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(React37.Fragment, { children: [
|
|
6110
6222
|
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
|
|
6111
6223
|
"button",
|
|
6112
6224
|
{
|
|
@@ -6134,7 +6246,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
6134
6246
|
}
|
|
6135
6247
|
|
|
6136
6248
|
// src/components/forms/Slider.tsx
|
|
6137
|
-
var
|
|
6249
|
+
var React38 = __toESM(require("react"), 1);
|
|
6138
6250
|
var import_jsx_runtime65 = require("react/jsx-runtime");
|
|
6139
6251
|
function Slider({
|
|
6140
6252
|
label,
|
|
@@ -6152,7 +6264,7 @@ function Slider({
|
|
|
6152
6264
|
...rest
|
|
6153
6265
|
}) {
|
|
6154
6266
|
const fieldId = useFieldId(id);
|
|
6155
|
-
const [dragging, setDragging] =
|
|
6267
|
+
const [dragging, setDragging] = React38.useState(false);
|
|
6156
6268
|
const v = value === void 0 ? min : Number(value);
|
|
6157
6269
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
6158
6270
|
return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
|
|
@@ -6186,7 +6298,7 @@ function Slider({
|
|
|
6186
6298
|
}
|
|
6187
6299
|
|
|
6188
6300
|
// src/components/forms/RangeSlider.tsx
|
|
6189
|
-
var
|
|
6301
|
+
var React39 = __toESM(require("react"), 1);
|
|
6190
6302
|
var import_jsx_runtime66 = require("react/jsx-runtime");
|
|
6191
6303
|
function RangeSlider({
|
|
6192
6304
|
label,
|
|
@@ -6206,9 +6318,9 @@ function RangeSlider({
|
|
|
6206
6318
|
}) {
|
|
6207
6319
|
const fmt2 = format || ((v) => String(v));
|
|
6208
6320
|
const [a, b] = value || [min, max];
|
|
6209
|
-
const [drag, setDrag] =
|
|
6210
|
-
const [focus, setFocus] =
|
|
6211
|
-
const railRef =
|
|
6321
|
+
const [drag, setDrag] = React39.useState(null);
|
|
6322
|
+
const [focus, setFocus] = React39.useState(null);
|
|
6323
|
+
const railRef = React39.useRef(null);
|
|
6212
6324
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
6213
6325
|
const clampPair = (i, v) => {
|
|
6214
6326
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -6223,7 +6335,7 @@ function RangeSlider({
|
|
|
6223
6335
|
const r = railRef.current.getBoundingClientRect();
|
|
6224
6336
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
6225
6337
|
};
|
|
6226
|
-
|
|
6338
|
+
React39.useEffect(() => {
|
|
6227
6339
|
if (drag === null) return;
|
|
6228
6340
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
6229
6341
|
const upH = () => setDrag(null);
|
|
@@ -6304,7 +6416,7 @@ function RangeSlider({
|
|
|
6304
6416
|
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
|
|
6305
6417
|
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-range-rail", ref: railRef }),
|
|
6306
6418
|
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
|
|
6307
|
-
marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
|
|
6419
|
+
marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(React39.Fragment, { children: [
|
|
6308
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) + "%" } }),
|
|
6309
6421
|
m.label ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
|
|
6310
6422
|
] }, m.value)),
|
|
@@ -6333,7 +6445,7 @@ function RangeSlider({
|
|
|
6333
6445
|
}
|
|
6334
6446
|
|
|
6335
6447
|
// src/components/forms/Dropzone.tsx
|
|
6336
|
-
var
|
|
6448
|
+
var React40 = __toESM(require("react"), 1);
|
|
6337
6449
|
var import_jsx_runtime67 = require("react/jsx-runtime");
|
|
6338
6450
|
function Dropzone({
|
|
6339
6451
|
onFiles,
|
|
@@ -6348,8 +6460,8 @@ function Dropzone({
|
|
|
6348
6460
|
className = "",
|
|
6349
6461
|
style
|
|
6350
6462
|
}) {
|
|
6351
|
-
const [over, setOver] =
|
|
6352
|
-
const depth =
|
|
6463
|
+
const [over, setOver] = React40.useState(false);
|
|
6464
|
+
const depth = React40.useRef(0);
|
|
6353
6465
|
const has = (e) => {
|
|
6354
6466
|
const dt = e.dataTransfer;
|
|
6355
6467
|
if (!dt) return false;
|
|
@@ -6411,8 +6523,8 @@ function FilePickButton({
|
|
|
6411
6523
|
className = "",
|
|
6412
6524
|
children
|
|
6413
6525
|
}) {
|
|
6414
|
-
const ref =
|
|
6415
|
-
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
|
|
6526
|
+
const ref = React40.useRef(null);
|
|
6527
|
+
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(React40.Fragment, { children: [
|
|
6416
6528
|
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
|
|
6417
6529
|
"button",
|
|
6418
6530
|
{
|
|
@@ -6445,10 +6557,10 @@ function FilePickButton({
|
|
|
6445
6557
|
}
|
|
6446
6558
|
function useStagedFiles(upload, opts) {
|
|
6447
6559
|
const o = opts || {};
|
|
6448
|
-
const [items, setItems] =
|
|
6449
|
-
const controllers =
|
|
6560
|
+
const [items, setItems] = React40.useState([]);
|
|
6561
|
+
const controllers = React40.useRef({});
|
|
6450
6562
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
6451
|
-
const run =
|
|
6563
|
+
const run = React40.useCallback((att) => {
|
|
6452
6564
|
if (!upload) return;
|
|
6453
6565
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
6454
6566
|
controllers.current[att.id] = ac;
|
|
@@ -6465,14 +6577,14 @@ function useStagedFiles(upload, opts) {
|
|
|
6465
6577
|
delete controllers.current[att.id];
|
|
6466
6578
|
});
|
|
6467
6579
|
}, [upload]);
|
|
6468
|
-
const add =
|
|
6580
|
+
const add = React40.useCallback((files) => {
|
|
6469
6581
|
if (!upload) return [];
|
|
6470
6582
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
6471
6583
|
setItems((list) => list.concat(atts));
|
|
6472
6584
|
atts.forEach(run);
|
|
6473
6585
|
return atts;
|
|
6474
6586
|
}, [upload, run]);
|
|
6475
|
-
const remove =
|
|
6587
|
+
const remove = React40.useCallback((att) => {
|
|
6476
6588
|
const ac = controllers.current[att.id];
|
|
6477
6589
|
if (ac) {
|
|
6478
6590
|
try {
|
|
@@ -6483,10 +6595,10 @@ function useStagedFiles(upload, opts) {
|
|
|
6483
6595
|
}
|
|
6484
6596
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
6485
6597
|
}, []);
|
|
6486
|
-
const retry =
|
|
6598
|
+
const retry = React40.useCallback((att) => {
|
|
6487
6599
|
run(att);
|
|
6488
6600
|
}, [run]);
|
|
6489
|
-
const clear =
|
|
6601
|
+
const clear = React40.useCallback(() => {
|
|
6490
6602
|
Object.values(controllers.current).forEach((ac) => {
|
|
6491
6603
|
try {
|
|
6492
6604
|
ac && ac.abort();
|
|
@@ -6610,7 +6722,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
6610
6722
|
}
|
|
6611
6723
|
|
|
6612
6724
|
// src/components/forms/MarkdownEditor.tsx
|
|
6613
|
-
var
|
|
6725
|
+
var React41 = __toESM(require("react"), 1);
|
|
6614
6726
|
var import_jsx_runtime69 = require("react/jsx-runtime");
|
|
6615
6727
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
6616
6728
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
@@ -6824,7 +6936,7 @@ function syncDom(root, value) {
|
|
|
6824
6936
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
6825
6937
|
}
|
|
6826
6938
|
var LIST_CONT = RE_LI;
|
|
6827
|
-
var MarkdownEditor =
|
|
6939
|
+
var MarkdownEditor = React41.forwardRef(function MarkdownEditor2({
|
|
6828
6940
|
value = "",
|
|
6829
6941
|
onChange,
|
|
6830
6942
|
onSubmit,
|
|
@@ -6843,10 +6955,10 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6843
6955
|
className = "",
|
|
6844
6956
|
id
|
|
6845
6957
|
}, ref) {
|
|
6846
|
-
const boxRef =
|
|
6847
|
-
const composing =
|
|
6848
|
-
const pendingCaret =
|
|
6849
|
-
|
|
6958
|
+
const boxRef = React41.useRef(null);
|
|
6959
|
+
const composing = React41.useRef(false);
|
|
6960
|
+
const pendingCaret = React41.useRef(null);
|
|
6961
|
+
React41.useLayoutEffect(() => {
|
|
6850
6962
|
const root = boxRef.current;
|
|
6851
6963
|
if (!root || composing.current) return;
|
|
6852
6964
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -6855,7 +6967,7 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6855
6967
|
pendingCaret.current = null;
|
|
6856
6968
|
if (active && caret != null) placeCaret(root, caret);
|
|
6857
6969
|
}, [value]);
|
|
6858
|
-
|
|
6970
|
+
React41.useEffect(() => {
|
|
6859
6971
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
6860
6972
|
}, [autoFocus]);
|
|
6861
6973
|
const caretNow = () => {
|
|
@@ -6922,7 +7034,7 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
6922
7034
|
api.replaceRange(from, to, next, from + next.length);
|
|
6923
7035
|
}
|
|
6924
7036
|
};
|
|
6925
|
-
|
|
7037
|
+
React41.useImperativeHandle(ref, () => api);
|
|
6926
7038
|
function detect(text, caret) {
|
|
6927
7039
|
if (!onTrigger) return;
|
|
6928
7040
|
const upto = text.slice(0, caret);
|
|
@@ -7074,16 +7186,16 @@ var MarkdownEditor = React40.forwardRef(function MarkdownEditor2({
|
|
|
7074
7186
|
});
|
|
7075
7187
|
|
|
7076
7188
|
// src/components/platform/AccountMenu.tsx
|
|
7077
|
-
var
|
|
7189
|
+
var React43 = __toESM(require("react"), 1);
|
|
7078
7190
|
|
|
7079
7191
|
// src/kits/sessionContext.tsx
|
|
7080
|
-
var
|
|
7081
|
-
var SessionContext =
|
|
7192
|
+
var React42 = __toESM(require("react"), 1);
|
|
7193
|
+
var SessionContext = React42.createContext(null);
|
|
7082
7194
|
function SessionProvider({ value, children }) {
|
|
7083
|
-
return
|
|
7195
|
+
return React42.createElement(SessionContext.Provider, { value }, children);
|
|
7084
7196
|
}
|
|
7085
7197
|
function useSessionContext() {
|
|
7086
|
-
const ctx =
|
|
7198
|
+
const ctx = React42.useContext(SessionContext);
|
|
7087
7199
|
if (!ctx) {
|
|
7088
7200
|
throw new Error(
|
|
7089
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."
|
|
@@ -7123,11 +7235,11 @@ function AccountMenu({
|
|
|
7123
7235
|
...rest
|
|
7124
7236
|
}) {
|
|
7125
7237
|
const { user, roles, can: can2, signOut: ctxSignOut, demo } = useSessionContext();
|
|
7126
|
-
const [open, setOpen] =
|
|
7127
|
-
const [switching, setSwitching] =
|
|
7128
|
-
const [signingOut, setSigningOut] =
|
|
7129
|
-
const [signOutError, setSignOutError] =
|
|
7130
|
-
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);
|
|
7131
7243
|
const visibleLinks = links.filter((l) => !l.perm || can2(l.perm));
|
|
7132
7244
|
const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || can2(l.perm)) })).filter((g) => g.links.length);
|
|
7133
7245
|
const closeMenu = () => {
|
|
@@ -7252,13 +7364,13 @@ function AccountMenu({
|
|
|
7252
7364
|
}
|
|
7253
7365
|
|
|
7254
7366
|
// src/components/platform/AppSwitcher.tsx
|
|
7255
|
-
var
|
|
7367
|
+
var React44 = __toESM(require("react"), 1);
|
|
7256
7368
|
var import_jsx_runtime71 = require("react/jsx-runtime");
|
|
7257
7369
|
function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
7258
7370
|
const { apps: contextApps } = useSessionContext();
|
|
7259
7371
|
const apps = appsProp ?? contextApps ?? [];
|
|
7260
|
-
const [open, setOpen] =
|
|
7261
|
-
const anchorRef =
|
|
7372
|
+
const [open, setOpen] = React44.useState(false);
|
|
7373
|
+
const anchorRef = React44.useRef(null);
|
|
7262
7374
|
if (!apps.length) return null;
|
|
7263
7375
|
const items = apps.map((app) => ({
|
|
7264
7376
|
id: app.key,
|
|
@@ -7272,7 +7384,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7272
7384
|
window.location.href = app.url;
|
|
7273
7385
|
}
|
|
7274
7386
|
}));
|
|
7275
|
-
return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
|
|
7387
|
+
return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(React44.Fragment, { children: [
|
|
7276
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)(
|
|
7277
7389
|
IconButton,
|
|
7278
7390
|
{
|
|
@@ -7301,10 +7413,10 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
|
|
|
7301
7413
|
}
|
|
7302
7414
|
|
|
7303
7415
|
// src/components/platform/AppearanceMenu.tsx
|
|
7304
|
-
var
|
|
7416
|
+
var React46 = __toESM(require("react"), 1);
|
|
7305
7417
|
|
|
7306
7418
|
// src/kits/appearance.ts
|
|
7307
|
-
var
|
|
7419
|
+
var React45 = __toESM(require("react"), 1);
|
|
7308
7420
|
var DEFAULT_STORAGE_KEY = "fd-appearance";
|
|
7309
7421
|
var DEFAULT_PREFS = {
|
|
7310
7422
|
theme: "system",
|
|
@@ -7399,11 +7511,11 @@ function applyPrefs(prefs, root = document.documentElement) {
|
|
|
7399
7511
|
else root.removeAttribute("data-motion");
|
|
7400
7512
|
}
|
|
7401
7513
|
function useAppearancePrefs(store) {
|
|
7402
|
-
const prefs =
|
|
7403
|
-
|
|
7514
|
+
const prefs = React45.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
7515
|
+
React45.useEffect(() => {
|
|
7404
7516
|
applyPrefs(prefs);
|
|
7405
7517
|
}, [prefs]);
|
|
7406
|
-
|
|
7518
|
+
React45.useEffect(() => {
|
|
7407
7519
|
if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
7408
7520
|
return;
|
|
7409
7521
|
}
|
|
@@ -7412,7 +7524,7 @@ function useAppearancePrefs(store) {
|
|
|
7412
7524
|
mq.addEventListener("change", onChange);
|
|
7413
7525
|
return () => mq.removeEventListener("change", onChange);
|
|
7414
7526
|
}, [prefs]);
|
|
7415
|
-
const update =
|
|
7527
|
+
const update = React45.useCallback(
|
|
7416
7528
|
(patch) => {
|
|
7417
7529
|
store.write({ ...store.getSnapshot(), ...patch });
|
|
7418
7530
|
},
|
|
@@ -7435,15 +7547,15 @@ var TEXT_SCALE_OPTIONS = [
|
|
|
7435
7547
|
{ value: "xl", label: "XL" }
|
|
7436
7548
|
];
|
|
7437
7549
|
function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
|
|
7438
|
-
const store =
|
|
7550
|
+
const store = React46.useMemo(
|
|
7439
7551
|
() => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
|
|
7440
7552
|
[storeProp, storageKey, storage, defaults]
|
|
7441
7553
|
);
|
|
7442
7554
|
const [prefs, update] = useAppearancePrefs(store);
|
|
7443
|
-
const [open, setOpen] =
|
|
7444
|
-
const anchorRef =
|
|
7555
|
+
const [open, setOpen] = React46.useState(false);
|
|
7556
|
+
const anchorRef = React46.useRef(null);
|
|
7445
7557
|
const patch = (p) => update(p);
|
|
7446
|
-
return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
|
|
7558
|
+
return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(React46.Fragment, { children: [
|
|
7447
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)(
|
|
7448
7560
|
IconButton,
|
|
7449
7561
|
{
|
|
@@ -7512,14 +7624,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
|
|
|
7512
7624
|
}
|
|
7513
7625
|
|
|
7514
7626
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
7515
|
-
var
|
|
7627
|
+
var React47 = __toESM(require("react"), 1);
|
|
7516
7628
|
var import_jsx_runtime73 = require("react/jsx-runtime");
|
|
7517
7629
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
7518
7630
|
function Json({ obj }) {
|
|
7519
7631
|
return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
7520
7632
|
}
|
|
7521
7633
|
function Endpoint({ s, onRequest }) {
|
|
7522
|
-
const [tried, setTried] =
|
|
7634
|
+
const [tried, setTried] = React47.useState(null);
|
|
7523
7635
|
const run = async () => {
|
|
7524
7636
|
setTried("busy");
|
|
7525
7637
|
const t0 = (window.performance || Date).now();
|
|
@@ -7592,10 +7704,10 @@ function ApiSpecBrowser({
|
|
|
7592
7704
|
className = "",
|
|
7593
7705
|
...rest
|
|
7594
7706
|
}) {
|
|
7595
|
-
const [q, setQ] =
|
|
7596
|
-
const [method, setMethod] =
|
|
7597
|
-
const [mod, setMod] =
|
|
7598
|
-
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);
|
|
7599
7711
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
7600
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())));
|
|
7601
7713
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
@@ -7674,7 +7786,7 @@ function ApiSpecBrowser({
|
|
|
7674
7786
|
}
|
|
7675
7787
|
|
|
7676
7788
|
// src/components/platform/ProfilePage.tsx
|
|
7677
|
-
var
|
|
7789
|
+
var React48 = __toESM(require("react"), 1);
|
|
7678
7790
|
var import_jsx_runtime74 = require("react/jsx-runtime");
|
|
7679
7791
|
function fieldInitialValue(field, user) {
|
|
7680
7792
|
if (field.value) return field.value(user);
|
|
@@ -7710,21 +7822,21 @@ function ProfilePage({
|
|
|
7710
7822
|
}) {
|
|
7711
7823
|
const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
|
|
7712
7824
|
const user = userProp || sessionUser;
|
|
7713
|
-
const initialFieldValues =
|
|
7825
|
+
const initialFieldValues = React48.useMemo(() => {
|
|
7714
7826
|
const values2 = {};
|
|
7715
7827
|
for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
|
|
7716
7828
|
return values2;
|
|
7717
7829
|
}, [user.id, fields]);
|
|
7718
|
-
const initialNotify =
|
|
7830
|
+
const initialNotify = React48.useMemo(() => {
|
|
7719
7831
|
const values2 = {};
|
|
7720
7832
|
for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
|
|
7721
7833
|
return values2;
|
|
7722
7834
|
}, [user.id, notifications]);
|
|
7723
|
-
const [values, setValues] =
|
|
7724
|
-
const [notify, setNotify] =
|
|
7725
|
-
const [saving, setSaving] =
|
|
7726
|
-
const [saved, setSaved] =
|
|
7727
|
-
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);
|
|
7728
7840
|
if (user.id !== prevUserId) {
|
|
7729
7841
|
setPrevUserId(user.id);
|
|
7730
7842
|
setValues(initialFieldValues);
|
|
@@ -7912,11 +8024,11 @@ function ProfilePage({
|
|
|
7912
8024
|
}
|
|
7913
8025
|
|
|
7914
8026
|
// src/components/platform/SignInPage.tsx
|
|
7915
|
-
var
|
|
8027
|
+
var React49 = __toESM(require("react"), 1);
|
|
7916
8028
|
var import_jsx_runtime75 = require("react/jsx-runtime");
|
|
7917
8029
|
function SignInPage({ productName, onSignIn, continueAs, error }) {
|
|
7918
|
-
const [signingIn, setSigningIn] =
|
|
7919
|
-
const [resuming, setResuming] =
|
|
8030
|
+
const [signingIn, setSigningIn] = React49.useState(false);
|
|
8031
|
+
const [resuming, setResuming] = React49.useState(false);
|
|
7920
8032
|
function handleSignIn() {
|
|
7921
8033
|
setSigningIn(true);
|
|
7922
8034
|
onSignIn();
|
|
@@ -8105,10 +8217,10 @@ function GoogleGlyph() {
|
|
|
8105
8217
|
}
|
|
8106
8218
|
|
|
8107
8219
|
// src/components/platform/RoadmapTimeline.tsx
|
|
8108
|
-
var
|
|
8220
|
+
var React52 = __toESM(require("react"), 1);
|
|
8109
8221
|
|
|
8110
8222
|
// src/kits/session.ts
|
|
8111
|
-
var
|
|
8223
|
+
var React50 = __toESM(require("react"), 1);
|
|
8112
8224
|
var PERMISSION_CATALOG = [
|
|
8113
8225
|
{ group: "Plans", items: [
|
|
8114
8226
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -9675,8 +9787,8 @@ function roadmap(overrides) {
|
|
|
9675
9787
|
};
|
|
9676
9788
|
}
|
|
9677
9789
|
function useSession() {
|
|
9678
|
-
const [s, setS] =
|
|
9679
|
-
|
|
9790
|
+
const [s, setS] = React50.useState(getSession);
|
|
9791
|
+
React50.useEffect(() => subscribe(setS), []);
|
|
9680
9792
|
return s;
|
|
9681
9793
|
}
|
|
9682
9794
|
var SessionKit = {
|
|
@@ -9709,7 +9821,7 @@ var SessionKit = {
|
|
|
9709
9821
|
};
|
|
9710
9822
|
function DemoSessionProvider({ children }) {
|
|
9711
9823
|
const session = useSession();
|
|
9712
|
-
const value =
|
|
9824
|
+
const value = React50.useMemo(
|
|
9713
9825
|
() => ({
|
|
9714
9826
|
user: session.user,
|
|
9715
9827
|
roles: session.roles,
|
|
@@ -9725,11 +9837,11 @@ function DemoSessionProvider({ children }) {
|
|
|
9725
9837
|
}),
|
|
9726
9838
|
[session]
|
|
9727
9839
|
);
|
|
9728
|
-
return
|
|
9840
|
+
return React50.createElement(SessionProvider, { value }, children);
|
|
9729
9841
|
}
|
|
9730
9842
|
|
|
9731
9843
|
// src/kits/runtime.ts
|
|
9732
|
-
var
|
|
9844
|
+
var React51 = __toESM(require("react"), 1);
|
|
9733
9845
|
var WIRED_ENDPOINTS = [
|
|
9734
9846
|
// Nothing yet. Every id below would come from a real service:
|
|
9735
9847
|
// "plan.get", "placements.list", …
|
|
@@ -9900,8 +10012,8 @@ var RuntimeKit = {
|
|
|
9900
10012
|
};
|
|
9901
10013
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
9902
10014
|
function useRuntimeMode() {
|
|
9903
|
-
const [m, setM] =
|
|
9904
|
-
|
|
10015
|
+
const [m, setM] = React51.useState(RuntimeKit.getMode());
|
|
10016
|
+
React51.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
9905
10017
|
return m;
|
|
9906
10018
|
}
|
|
9907
10019
|
function useFeatureStatus(key) {
|
|
@@ -9984,12 +10096,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
9984
10096
|
}
|
|
9985
10097
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
9986
10098
|
const session = SessionKit.useSession();
|
|
9987
|
-
const [project, setProject] =
|
|
9988
|
-
const [q, setQ] =
|
|
9989
|
-
const scrollRef =
|
|
9990
|
-
const nowRef =
|
|
9991
|
-
const rm =
|
|
9992
|
-
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(() => {
|
|
9993
10105
|
const m = {};
|
|
9994
10106
|
rm.items.forEach((i) => {
|
|
9995
10107
|
m[i.key] = i;
|
|
@@ -9998,7 +10110,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
9998
10110
|
}, [rm]);
|
|
9999
10111
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
10000
10112
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
10001
|
-
|
|
10113
|
+
React52.useEffect(() => {
|
|
10002
10114
|
let raf1 = 0, raf2 = 0;
|
|
10003
10115
|
const place = () => {
|
|
10004
10116
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -10072,7 +10184,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10072
10184
|
lastPhase = item.phase;
|
|
10073
10185
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
10074
10186
|
const isBoundary = n === firstPending;
|
|
10075
|
-
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
|
|
10187
|
+
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React52.Fragment, { children: [
|
|
10076
10188
|
showPhase ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-rm-era", children: [
|
|
10077
10189
|
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
10078
10190
|
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
@@ -10116,7 +10228,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
10116
10228
|
}
|
|
10117
10229
|
|
|
10118
10230
|
// src/components/platform/ComingSoon.tsx
|
|
10119
|
-
var
|
|
10231
|
+
var React53 = __toESM(require("react"), 1);
|
|
10120
10232
|
var import_react_dom6 = require("react-dom");
|
|
10121
10233
|
var import_jsx_runtime77 = require("react/jsx-runtime");
|
|
10122
10234
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
@@ -10134,8 +10246,8 @@ function writeBypassed(list) {
|
|
|
10134
10246
|
}
|
|
10135
10247
|
}
|
|
10136
10248
|
function useBypass(key) {
|
|
10137
|
-
const [on, setOn] =
|
|
10138
|
-
|
|
10249
|
+
const [on, setOn] = React53.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
10250
|
+
React53.useEffect(() => {
|
|
10139
10251
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
10140
10252
|
}, [key]);
|
|
10141
10253
|
const set = (next) => {
|
|
@@ -10182,9 +10294,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
|
|
|
10182
10294
|
] });
|
|
10183
10295
|
}
|
|
10184
10296
|
function useHoverCard(open) {
|
|
10185
|
-
const anchor =
|
|
10186
|
-
const [pos, setPos] =
|
|
10187
|
-
|
|
10297
|
+
const anchor = React53.useRef(null);
|
|
10298
|
+
const [pos, setPos] = React53.useState(null);
|
|
10299
|
+
React53.useLayoutEffect(() => {
|
|
10188
10300
|
if (!open || !anchor.current) {
|
|
10189
10301
|
setPos(null);
|
|
10190
10302
|
return;
|
|
@@ -10311,10 +10423,10 @@ function ComingSoon({
|
|
|
10311
10423
|
] });
|
|
10312
10424
|
}
|
|
10313
10425
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
10314
|
-
const [open, setOpen] =
|
|
10426
|
+
const [open, setOpen] = React53.useState(false);
|
|
10315
10427
|
const [anchor, pos] = useHoverCard(open);
|
|
10316
10428
|
const zIndex = useOverlayLayer(open);
|
|
10317
|
-
const close =
|
|
10429
|
+
const close = React53.useRef(null);
|
|
10318
10430
|
const show = () => {
|
|
10319
10431
|
if (close.current) {
|
|
10320
10432
|
clearTimeout(close.current);
|
|
@@ -10330,7 +10442,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
10330
10442
|
setOpen(false);
|
|
10331
10443
|
}, 140);
|
|
10332
10444
|
};
|
|
10333
|
-
|
|
10445
|
+
React53.useEffect(() => () => {
|
|
10334
10446
|
if (close.current) clearTimeout(close.current);
|
|
10335
10447
|
}, []);
|
|
10336
10448
|
return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(
|
|
@@ -10501,14 +10613,14 @@ function PermissionHint({ perm, children }) {
|
|
|
10501
10613
|
}
|
|
10502
10614
|
|
|
10503
10615
|
// src/components/platform/ModeSwitch.tsx
|
|
10504
|
-
var
|
|
10616
|
+
var React54 = __toESM(require("react"), 1);
|
|
10505
10617
|
var import_jsx_runtime79 = require("react/jsx-runtime");
|
|
10506
10618
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
10507
10619
|
const mode2 = useRuntimeMode();
|
|
10508
|
-
const [open, setOpen] =
|
|
10620
|
+
const [open, setOpen] = React54.useState(false);
|
|
10509
10621
|
const zIndex = useOverlayLayer(open);
|
|
10510
|
-
const ref =
|
|
10511
|
-
|
|
10622
|
+
const ref = React54.useRef(null);
|
|
10623
|
+
React54.useEffect(() => {
|
|
10512
10624
|
if (!open) return;
|
|
10513
10625
|
const away = (e) => {
|
|
10514
10626
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -10764,7 +10876,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
10764
10876
|
}
|
|
10765
10877
|
|
|
10766
10878
|
// src/components/planner/MixGap.tsx
|
|
10767
|
-
var
|
|
10879
|
+
var React55 = __toESM(require("react"), 1);
|
|
10768
10880
|
var import_jsx_runtime82 = require("react/jsx-runtime");
|
|
10769
10881
|
var MIX_GAP_LAYOUT = {
|
|
10770
10882
|
trackHeight: 30,
|
|
@@ -10779,7 +10891,7 @@ function mixGapOffset(value, max) {
|
|
|
10779
10891
|
}
|
|
10780
10892
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
10781
10893
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
10782
|
-
const [hover, setHover] =
|
|
10894
|
+
const [hover, setHover] = React55.useState(null);
|
|
10783
10895
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
10784
10896
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
10785
10897
|
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
@@ -10922,7 +11034,7 @@ function ChannelContribution({
|
|
|
10922
11034
|
}
|
|
10923
11035
|
|
|
10924
11036
|
// src/components/planner/BudgetReallocator.tsx
|
|
10925
|
-
var
|
|
11037
|
+
var React56 = __toESM(require("react"), 1);
|
|
10926
11038
|
var import_jsx_runtime84 = require("react/jsx-runtime");
|
|
10927
11039
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
10928
11040
|
function BudgetReallocator({
|
|
@@ -10938,8 +11050,8 @@ function BudgetReallocator({
|
|
|
10938
11050
|
onCancel,
|
|
10939
11051
|
className = ""
|
|
10940
11052
|
}) {
|
|
10941
|
-
const [draft, setDraft] =
|
|
10942
|
-
|
|
11053
|
+
const [draft, setDraft] = React56.useState(spend);
|
|
11054
|
+
React56.useEffect(() => setDraft(spend), [spend]);
|
|
10943
11055
|
const dirty = draft !== spend;
|
|
10944
11056
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
10945
11057
|
const nextBand = bandFor(nextCrp);
|
|
@@ -10954,10 +11066,10 @@ function BudgetReallocator({
|
|
|
10954
11066
|
setDraft(spend);
|
|
10955
11067
|
if (onCancel) onCancel();
|
|
10956
11068
|
};
|
|
10957
|
-
const trackRef =
|
|
10958
|
-
const chipRef =
|
|
10959
|
-
const [chipLeft, setChipLeft] =
|
|
10960
|
-
|
|
11069
|
+
const trackRef = React56.useRef(null);
|
|
11070
|
+
const chipRef = React56.useRef(null);
|
|
11071
|
+
const [chipLeft, setChipLeft] = React56.useState(null);
|
|
11072
|
+
React56.useLayoutEffect(() => {
|
|
10961
11073
|
const track = trackRef.current;
|
|
10962
11074
|
if (!dirty || !track) {
|
|
10963
11075
|
setChipLeft(null);
|
|
@@ -11144,7 +11256,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "" })
|
|
|
11144
11256
|
}
|
|
11145
11257
|
|
|
11146
11258
|
// src/components/planner/PreferenceMeter.tsx
|
|
11147
|
-
var
|
|
11259
|
+
var React57 = __toESM(require("react"), 1);
|
|
11148
11260
|
var import_jsx_runtime87 = require("react/jsx-runtime");
|
|
11149
11261
|
function preferenceScore(criteria) {
|
|
11150
11262
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
@@ -11174,7 +11286,7 @@ function PreferenceMeter({
|
|
|
11174
11286
|
className = ""
|
|
11175
11287
|
}) {
|
|
11176
11288
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
11177
|
-
const segments =
|
|
11289
|
+
const segments = React57.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
11178
11290
|
return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
|
|
11179
11291
|
ScoreMeter,
|
|
11180
11292
|
{
|
|
@@ -11213,10 +11325,10 @@ function PreferenceMeter({
|
|
|
11213
11325
|
}
|
|
11214
11326
|
|
|
11215
11327
|
// src/components/chat/AgentChatPanel.tsx
|
|
11216
|
-
var
|
|
11328
|
+
var React63 = __toESM(require("react"), 1);
|
|
11217
11329
|
|
|
11218
11330
|
// src/components/chat/chatEngine.ts
|
|
11219
|
-
var
|
|
11331
|
+
var React58 = __toESM(require("react"), 1);
|
|
11220
11332
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
11221
11333
|
var JOB_PENDING = ["queued", "running"];
|
|
11222
11334
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -11270,22 +11382,22 @@ function useChatEngine(opts) {
|
|
|
11270
11382
|
onClear,
|
|
11271
11383
|
onFeedback
|
|
11272
11384
|
} = opts || {};
|
|
11273
|
-
const [status, setStatus] =
|
|
11274
|
-
const [threadId, setThreadId] =
|
|
11275
|
-
const [messages, setMessages] =
|
|
11276
|
-
const [queue, setQueue] =
|
|
11277
|
-
const [fatal, setFatal] =
|
|
11278
|
-
const [busy, setBusy] =
|
|
11279
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
11280
|
-
const listRef =
|
|
11281
|
-
const queueRef =
|
|
11282
|
-
const busyRef =
|
|
11283
|
-
const stoppedRef =
|
|
11284
|
-
const abortRef =
|
|
11285
|
-
const serverCount =
|
|
11286
|
-
const threadRef =
|
|
11287
|
-
const mounted =
|
|
11288
|
-
|
|
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(() => {
|
|
11289
11401
|
mounted.current = true;
|
|
11290
11402
|
return () => {
|
|
11291
11403
|
mounted.current = false;
|
|
@@ -11307,14 +11419,14 @@ function useChatEngine(opts) {
|
|
|
11307
11419
|
}
|
|
11308
11420
|
return false;
|
|
11309
11421
|
};
|
|
11310
|
-
const loadThread =
|
|
11422
|
+
const loadThread = React58.useCallback(async (id) => {
|
|
11311
11423
|
const data = await apiAdapter.getThread(id);
|
|
11312
11424
|
const list = [...data && data.messages || []];
|
|
11313
11425
|
serverCount.current = list.length;
|
|
11314
11426
|
commit(list);
|
|
11315
11427
|
return list;
|
|
11316
11428
|
}, [apiAdapter]);
|
|
11317
|
-
|
|
11429
|
+
React58.useEffect(() => {
|
|
11318
11430
|
if (!apiAdapter) {
|
|
11319
11431
|
setStatus("idle");
|
|
11320
11432
|
setFatal(null);
|
|
@@ -11527,7 +11639,7 @@ function useChatEngine(opts) {
|
|
|
11527
11639
|
await dispatchTurn(turn);
|
|
11528
11640
|
}
|
|
11529
11641
|
}
|
|
11530
|
-
const send =
|
|
11642
|
+
const send = React58.useCallback((text, attachments) => {
|
|
11531
11643
|
const body = (text || "").trim();
|
|
11532
11644
|
if (!body && !(attachments && attachments.length)) return;
|
|
11533
11645
|
if (status === "disconnected") return;
|
|
@@ -11537,7 +11649,7 @@ function useChatEngine(opts) {
|
|
|
11537
11649
|
stoppedRef.current = false;
|
|
11538
11650
|
drain();
|
|
11539
11651
|
}, [status]);
|
|
11540
|
-
const stop =
|
|
11652
|
+
const stop = React58.useCallback(() => {
|
|
11541
11653
|
stoppedRef.current = true;
|
|
11542
11654
|
const ac = abortRef.current;
|
|
11543
11655
|
if (ac) {
|
|
@@ -11556,11 +11668,11 @@ function useChatEngine(opts) {
|
|
|
11556
11668
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
11557
11669
|
}
|
|
11558
11670
|
}, [apiAdapter]);
|
|
11559
|
-
const removeQueued =
|
|
11671
|
+
const removeQueued = React58.useCallback((id) => {
|
|
11560
11672
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
11561
11673
|
setQueue(queueRef.current.slice());
|
|
11562
11674
|
}, []);
|
|
11563
|
-
const retry =
|
|
11675
|
+
const retry = React58.useCallback(() => {
|
|
11564
11676
|
const list = listRef.current;
|
|
11565
11677
|
let at = -1;
|
|
11566
11678
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -11576,19 +11688,19 @@ function useChatEngine(opts) {
|
|
|
11576
11688
|
setQueue(queueRef.current.slice());
|
|
11577
11689
|
drain();
|
|
11578
11690
|
}, []);
|
|
11579
|
-
const clear =
|
|
11691
|
+
const clear = React58.useCallback(() => {
|
|
11580
11692
|
commit([]);
|
|
11581
11693
|
serverCount.current = 0;
|
|
11582
11694
|
queueRef.current = [];
|
|
11583
11695
|
setQueue([]);
|
|
11584
11696
|
onClear && onClear();
|
|
11585
11697
|
}, [onClear]);
|
|
11586
|
-
const setFeedback =
|
|
11698
|
+
const setFeedback = React58.useCallback((id, value) => {
|
|
11587
11699
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
11588
11700
|
const msg = listRef.current.find((m) => m.id === id);
|
|
11589
11701
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
11590
11702
|
}, [onFeedback]);
|
|
11591
|
-
const reload =
|
|
11703
|
+
const reload = React58.useCallback(async () => {
|
|
11592
11704
|
if (!threadRef.current) return;
|
|
11593
11705
|
setStatus("loading");
|
|
11594
11706
|
try {
|
|
@@ -11626,10 +11738,10 @@ var ChatKit = {
|
|
|
11626
11738
|
};
|
|
11627
11739
|
|
|
11628
11740
|
// src/components/chat/ChatTranscript.tsx
|
|
11629
|
-
var
|
|
11741
|
+
var React60 = __toESM(require("react"), 1);
|
|
11630
11742
|
|
|
11631
11743
|
// src/components/chat/ChatTurn.tsx
|
|
11632
|
-
var
|
|
11744
|
+
var React59 = __toESM(require("react"), 1);
|
|
11633
11745
|
var import_jsx_runtime88 = require("react/jsx-runtime");
|
|
11634
11746
|
function JsonView({ value }) {
|
|
11635
11747
|
let text;
|
|
@@ -11666,7 +11778,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
|
11666
11778
|
] });
|
|
11667
11779
|
}
|
|
11668
11780
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
11669
|
-
const [open, setOpen] =
|
|
11781
|
+
const [open, setOpen] = React59.useState(defaultOpen);
|
|
11670
11782
|
if (!text) return null;
|
|
11671
11783
|
return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
|
|
11672
11784
|
/* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -11683,7 +11795,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
|
11683
11795
|
] });
|
|
11684
11796
|
}
|
|
11685
11797
|
function Citations({ items = [], onOpen }) {
|
|
11686
|
-
const [open, setOpen] =
|
|
11798
|
+
const [open, setOpen] = React59.useState(false);
|
|
11687
11799
|
if (!items.length) return null;
|
|
11688
11800
|
return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fdc-cites", children: [
|
|
11689
11801
|
/* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -11709,7 +11821,7 @@ function clampText(text, max) {
|
|
|
11709
11821
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
11710
11822
|
}
|
|
11711
11823
|
function MessageBody({ message: m, ctx }) {
|
|
11712
|
-
const [expanded, setExpanded] =
|
|
11824
|
+
const [expanded, setExpanded] = React59.useState(false);
|
|
11713
11825
|
const isUser = m.role === "user";
|
|
11714
11826
|
const raw = m.text || "";
|
|
11715
11827
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
@@ -11776,9 +11888,9 @@ function MessageBody({ message: m, ctx }) {
|
|
|
11776
11888
|
] });
|
|
11777
11889
|
}
|
|
11778
11890
|
function useCopyRun() {
|
|
11779
|
-
const [done, setDone] =
|
|
11780
|
-
const t =
|
|
11781
|
-
|
|
11891
|
+
const [done, setDone] = React59.useState(false);
|
|
11892
|
+
const t = React59.useRef(null);
|
|
11893
|
+
React59.useEffect(() => () => {
|
|
11782
11894
|
if (t.current) clearTimeout(t.current);
|
|
11783
11895
|
}, []);
|
|
11784
11896
|
return [done, (text) => {
|
|
@@ -11805,7 +11917,7 @@ function RunActions({ group, ctx }) {
|
|
|
11805
11917
|
] }),
|
|
11806
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,
|
|
11807
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,
|
|
11808
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(
|
|
11920
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(React59.Fragment, { children: [
|
|
11809
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" }) }),
|
|
11810
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" }) })
|
|
11811
11923
|
] }) : null,
|
|
@@ -11900,10 +12012,10 @@ function ChatTranscript({
|
|
|
11900
12012
|
renderEmpty,
|
|
11901
12013
|
className = ""
|
|
11902
12014
|
}) {
|
|
11903
|
-
const scroller =
|
|
11904
|
-
const stick =
|
|
11905
|
-
const [pill, setPill] =
|
|
11906
|
-
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);
|
|
11907
12019
|
const toBottom = (smooth) => {
|
|
11908
12020
|
const el = scroller.current;
|
|
11909
12021
|
if (!el) return;
|
|
@@ -11922,7 +12034,7 @@ function ChatTranscript({
|
|
|
11922
12034
|
seen.current = messages.length;
|
|
11923
12035
|
}
|
|
11924
12036
|
};
|
|
11925
|
-
|
|
12037
|
+
React60.useLayoutEffect(() => {
|
|
11926
12038
|
const el = scroller.current;
|
|
11927
12039
|
if (!el) return;
|
|
11928
12040
|
if (stick.current) {
|
|
@@ -11930,7 +12042,7 @@ function ChatTranscript({
|
|
|
11930
12042
|
seen.current = messages.length;
|
|
11931
12043
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
11932
12044
|
}, [messages]);
|
|
11933
|
-
|
|
12045
|
+
React60.useEffect(() => {
|
|
11934
12046
|
const el = scroller.current;
|
|
11935
12047
|
const inner = el && el.firstChild;
|
|
11936
12048
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -11940,7 +12052,7 @@ function ChatTranscript({
|
|
|
11940
12052
|
ro.observe(inner);
|
|
11941
12053
|
return () => ro.disconnect();
|
|
11942
12054
|
}, []);
|
|
11943
|
-
const groups =
|
|
12055
|
+
const groups = React60.useMemo(() => groupMessages(messages), [messages]);
|
|
11944
12056
|
const empty = !messages.length && status === "ready";
|
|
11945
12057
|
return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
11946
12058
|
/* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
@@ -11964,7 +12076,7 @@ function ChatTranscript({
|
|
|
11964
12076
|
const prev = groups[i - 1];
|
|
11965
12077
|
const k = dayKey(g.messages[0].timestamp);
|
|
11966
12078
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
11967
|
-
return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
|
|
12079
|
+
return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(React60.Fragment, { children: [
|
|
11968
12080
|
showDay ? /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { children: dayLabel(k) }) }) : null,
|
|
11969
12081
|
/* @__PURE__ */ (0, import_jsx_runtime89.jsx)(ChatTurn, { group: g, ctx })
|
|
11970
12082
|
] }, g.key || i);
|
|
@@ -11981,7 +12093,7 @@ function ChatTranscript({
|
|
|
11981
12093
|
var TranscriptKit = { groupMessages };
|
|
11982
12094
|
|
|
11983
12095
|
// src/components/chat/ChatComposer.tsx
|
|
11984
|
-
var
|
|
12096
|
+
var React61 = __toESM(require("react"), 1);
|
|
11985
12097
|
var import_jsx_runtime90 = require("react/jsx-runtime");
|
|
11986
12098
|
function ChatComposer({
|
|
11987
12099
|
onSubmit,
|
|
@@ -12009,17 +12121,17 @@ function ChatComposer({
|
|
|
12009
12121
|
onReject,
|
|
12010
12122
|
onOpenAttachment
|
|
12011
12123
|
}) {
|
|
12012
|
-
const [text, setText] =
|
|
12013
|
-
const [trigger, setTrigger] =
|
|
12014
|
-
const [mentionItems, setMentionItems] =
|
|
12015
|
-
const [listening, setListening] =
|
|
12016
|
-
const [notice, setNotice] =
|
|
12017
|
-
const editor =
|
|
12018
|
-
const wrap =
|
|
12019
|
-
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);
|
|
12020
12132
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
12021
12133
|
} });
|
|
12022
|
-
|
|
12134
|
+
React61.useEffect(() => {
|
|
12023
12135
|
if (draft != null && draft !== text) setText(draft);
|
|
12024
12136
|
}, [draft]);
|
|
12025
12137
|
const change = (v) => {
|
|
@@ -12055,7 +12167,7 @@ function ChatComposer({
|
|
|
12055
12167
|
e.preventDefault();
|
|
12056
12168
|
staged.add(found.files);
|
|
12057
12169
|
};
|
|
12058
|
-
|
|
12170
|
+
React61.useEffect(() => {
|
|
12059
12171
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
12060
12172
|
setMentionItems([]);
|
|
12061
12173
|
return;
|
|
@@ -12073,7 +12185,7 @@ function ChatComposer({
|
|
|
12073
12185
|
const q = (trigger.query || "").toLowerCase();
|
|
12074
12186
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
12075
12187
|
}, [trigger, mentionSources]);
|
|
12076
|
-
const slashItems =
|
|
12188
|
+
const slashItems = React61.useMemo(() => {
|
|
12077
12189
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
12078
12190
|
const q = (trigger.query || "").toLowerCase();
|
|
12079
12191
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -12247,12 +12359,12 @@ function ChatComposer({
|
|
|
12247
12359
|
}
|
|
12248
12360
|
|
|
12249
12361
|
// src/components/chat/ChatSessionBar.tsx
|
|
12250
|
-
var
|
|
12362
|
+
var React62 = __toESM(require("react"), 1);
|
|
12251
12363
|
var import_jsx_runtime91 = require("react/jsx-runtime");
|
|
12252
12364
|
var compact2 = meterFormats.compact;
|
|
12253
12365
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
12254
|
-
const [open, setOpen] =
|
|
12255
|
-
const anchor =
|
|
12366
|
+
const [open, setOpen] = React62.useState(false);
|
|
12367
|
+
const anchor = React62.useRef(null);
|
|
12256
12368
|
const stats = sessionStats || null;
|
|
12257
12369
|
const cu = contextUsage || null;
|
|
12258
12370
|
const limits = usageLimits || null;
|
|
@@ -12267,7 +12379,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
12267
12379
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
12268
12380
|
if (cu) bits.push(pct + "% context");
|
|
12269
12381
|
const expandable = !!(cu || limits);
|
|
12270
|
-
return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
|
|
12382
|
+
return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(React62.Fragment, { children: [
|
|
12271
12383
|
/* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-bar", children: [
|
|
12272
12384
|
/* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
|
|
12273
12385
|
"button",
|
|
@@ -12408,7 +12520,7 @@ function ModelControls({
|
|
|
12408
12520
|
] })
|
|
12409
12521
|
});
|
|
12410
12522
|
}
|
|
12411
|
-
return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
|
|
12523
|
+
return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(React62.Fragment, { children: [
|
|
12412
12524
|
/* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
|
|
12413
12525
|
MenuButton,
|
|
12414
12526
|
{
|
|
@@ -12525,11 +12637,11 @@ function AgentChatPanel({
|
|
|
12525
12637
|
onFeedback,
|
|
12526
12638
|
onEditMessage
|
|
12527
12639
|
}) {
|
|
12528
|
-
const [panelWidth, setPanelWidth] =
|
|
12529
|
-
const [applied, setApplied] =
|
|
12530
|
-
const [draft, setDraft] =
|
|
12531
|
-
const dragging =
|
|
12532
|
-
|
|
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]);
|
|
12533
12645
|
const engine = useChatEngine({
|
|
12534
12646
|
contextType,
|
|
12535
12647
|
contextId,
|
|
@@ -12733,7 +12845,7 @@ function AgentChatPanel({
|
|
|
12733
12845
|
}
|
|
12734
12846
|
|
|
12735
12847
|
// src/components/files/FileViewer.tsx
|
|
12736
|
-
var
|
|
12848
|
+
var React64 = __toESM(require("react"), 1);
|
|
12737
12849
|
var import_jsx_runtime93 = require("react/jsx-runtime");
|
|
12738
12850
|
function previewKindOf(file) {
|
|
12739
12851
|
const mime = (file.mime || "").toLowerCase();
|
|
@@ -12790,13 +12902,13 @@ function parseDelimited(text, delimiter) {
|
|
|
12790
12902
|
return rows;
|
|
12791
12903
|
}
|
|
12792
12904
|
function usePreview(file, kind, resolveUrl) {
|
|
12793
|
-
const [state, setState] =
|
|
12794
|
-
const [attempt, setAttempt] =
|
|
12795
|
-
const resolveRef =
|
|
12796
|
-
|
|
12905
|
+
const [state, setState] = React64.useState({ status: "loading" });
|
|
12906
|
+
const [attempt, setAttempt] = React64.useState(0);
|
|
12907
|
+
const resolveRef = React64.useRef(resolveUrl);
|
|
12908
|
+
React64.useEffect(() => {
|
|
12797
12909
|
resolveRef.current = resolveUrl;
|
|
12798
12910
|
}, [resolveUrl]);
|
|
12799
|
-
|
|
12911
|
+
React64.useEffect(() => {
|
|
12800
12912
|
if (kind === "none") {
|
|
12801
12913
|
setState({ status: "ready" });
|
|
12802
12914
|
return;
|
|
@@ -12826,7 +12938,7 @@ function usePreview(file, kind, resolveUrl) {
|
|
|
12826
12938
|
if (ac) ac.abort();
|
|
12827
12939
|
};
|
|
12828
12940
|
}, [file.id, kind, attempt]);
|
|
12829
|
-
return { ...state, retry:
|
|
12941
|
+
return { ...state, retry: React64.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
12830
12942
|
}
|
|
12831
12943
|
function PreviewBody({ file, kind, state }) {
|
|
12832
12944
|
if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
@@ -12871,13 +12983,13 @@ function PreviewBody({ file, kind, state }) {
|
|
|
12871
12983
|
] });
|
|
12872
12984
|
}
|
|
12873
12985
|
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
12874
|
-
const kind =
|
|
12986
|
+
const kind = React64.useMemo(() => previewKindOf(file), [file]);
|
|
12875
12987
|
const preview = usePreview(file, kind, resolveUrl);
|
|
12876
|
-
const [tab, setTab] =
|
|
12877
|
-
const [downloading, setDownloading] =
|
|
12878
|
-
const [downloadError, setDownloadError] =
|
|
12988
|
+
const [tab, setTab] = React64.useState("preview");
|
|
12989
|
+
const [downloading, setDownloading] = React64.useState(false);
|
|
12990
|
+
const [downloadError, setDownloadError] = React64.useState(null);
|
|
12879
12991
|
const hasSide = sidePanel != null;
|
|
12880
|
-
|
|
12992
|
+
React64.useEffect(() => {
|
|
12881
12993
|
setTab("preview");
|
|
12882
12994
|
}, [file.id]);
|
|
12883
12995
|
const download = () => {
|
|
@@ -12944,7 +13056,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
|
|
|
12944
13056
|
}
|
|
12945
13057
|
|
|
12946
13058
|
// src/components/files/FileBrowser.tsx
|
|
12947
|
-
var
|
|
13059
|
+
var React65 = __toESM(require("react"), 1);
|
|
12948
13060
|
var import_jsx_runtime94 = require("react/jsx-runtime");
|
|
12949
13061
|
function childrenOf(folders, parentId) {
|
|
12950
13062
|
return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -13015,10 +13127,10 @@ function FolderPickerMenu({
|
|
|
13015
13127
|
destinations,
|
|
13016
13128
|
onPick
|
|
13017
13129
|
}) {
|
|
13018
|
-
const [open, setOpen] =
|
|
13130
|
+
const [open, setOpen] = React65.useState(false);
|
|
13019
13131
|
const zIndex = useOverlayLayer(open);
|
|
13020
|
-
const ref =
|
|
13021
|
-
|
|
13132
|
+
const ref = React65.useRef(null);
|
|
13133
|
+
React65.useEffect(() => {
|
|
13022
13134
|
if (!open) return;
|
|
13023
13135
|
const away = (e) => {
|
|
13024
13136
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -13070,8 +13182,8 @@ function FolderPickerMenu({
|
|
|
13070
13182
|
] });
|
|
13071
13183
|
}
|
|
13072
13184
|
function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
|
|
13073
|
-
const [over, setOver] =
|
|
13074
|
-
const dragCounter =
|
|
13185
|
+
const [over, setOver] = React65.useState(false);
|
|
13186
|
+
const dragCounter = React65.useRef(0);
|
|
13075
13187
|
const dropHandlers = isDropTarget ? {
|
|
13076
13188
|
onDragEnter: (e) => {
|
|
13077
13189
|
if (!hasInternalPayload(e)) return;
|
|
@@ -13119,8 +13231,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
|
|
|
13119
13231
|
}
|
|
13120
13232
|
function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
|
|
13121
13233
|
const kids = childrenOf(folders, folder.id);
|
|
13122
|
-
const [expanded, setExpanded] =
|
|
13123
|
-
|
|
13234
|
+
const [expanded, setExpanded] = React65.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
|
|
13235
|
+
React65.useEffect(() => {
|
|
13124
13236
|
if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
|
|
13125
13237
|
}, [currentFolderId, folder.id, folders]);
|
|
13126
13238
|
const isCurrent = folder.id === currentFolderId;
|
|
@@ -13186,15 +13298,15 @@ function FileBrowser({
|
|
|
13186
13298
|
const canUpload = perm.canUpload !== false && !!onUpload;
|
|
13187
13299
|
const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
|
|
13188
13300
|
const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
|
|
13189
|
-
const [createOpen, setCreateOpen] =
|
|
13190
|
-
const [createName, setCreateName] =
|
|
13191
|
-
const [renameTarget, setRenameTarget] =
|
|
13192
|
-
const [renameValue, setRenameValue] =
|
|
13193
|
-
const [deleteTarget, setDeleteTarget] =
|
|
13194
|
-
const uploadInputRef =
|
|
13195
|
-
const crumbFolders =
|
|
13196
|
-
const subfolders =
|
|
13197
|
-
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(
|
|
13198
13310
|
() => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
|
|
13199
13311
|
[files, currentFolderId]
|
|
13200
13312
|
);
|
|
@@ -13426,8 +13538,8 @@ function BreadcrumbCrumb({
|
|
|
13426
13538
|
isDropTarget,
|
|
13427
13539
|
onDropPayload
|
|
13428
13540
|
}) {
|
|
13429
|
-
const [over, setOver] =
|
|
13430
|
-
const dragCounter =
|
|
13541
|
+
const [over, setOver] = React65.useState(false);
|
|
13542
|
+
const dragCounter = React65.useRef(0);
|
|
13431
13543
|
const dropHandlers = isDropTarget ? {
|
|
13432
13544
|
onDragEnter: (e) => {
|
|
13433
13545
|
if (!hasInternalPayload(e)) return;
|
|
@@ -13456,7 +13568,7 @@ function BreadcrumbCrumb({
|
|
|
13456
13568
|
}
|
|
13457
13569
|
|
|
13458
13570
|
// src/kits/query.ts
|
|
13459
|
-
var
|
|
13571
|
+
var React66 = __toESM(require("react"), 1);
|
|
13460
13572
|
var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
|
|
13461
13573
|
var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
|
|
13462
13574
|
var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
|
|
@@ -13511,22 +13623,22 @@ function compare(a, b, dir) {
|
|
|
13511
13623
|
var API = null;
|
|
13512
13624
|
var PREFS = null;
|
|
13513
13625
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
13514
|
-
const [query, setQuery] =
|
|
13626
|
+
const [query, setQuery] = React66.useState(() => {
|
|
13515
13627
|
const store = PREFS || window.PlannerPrefs;
|
|
13516
13628
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
13517
13629
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
13518
13630
|
});
|
|
13519
|
-
const savePref =
|
|
13631
|
+
const savePref = React66.useCallback((patch2) => {
|
|
13520
13632
|
const store = PREFS || window.PlannerPrefs;
|
|
13521
13633
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
13522
13634
|
}, [prefsKey]);
|
|
13523
|
-
const [res, setRes] =
|
|
13524
|
-
const [loading, setLoading] =
|
|
13525
|
-
const seq2 =
|
|
13635
|
+
const [res, setRes] = React66.useState(null);
|
|
13636
|
+
const [loading, setLoading] = React66.useState(true);
|
|
13637
|
+
const seq2 = React66.useRef(0);
|
|
13526
13638
|
const depKey = (deps || []).join("|");
|
|
13527
13639
|
const paramKey = JSON.stringify(params || {});
|
|
13528
13640
|
const queryKey = JSON.stringify(query);
|
|
13529
|
-
|
|
13641
|
+
React66.useEffect(() => {
|
|
13530
13642
|
const id = ++seq2.current;
|
|
13531
13643
|
setLoading(true);
|
|
13532
13644
|
const t = setTimeout(() => {
|
|
@@ -13845,12 +13957,12 @@ function createVersionStore(initialState, options) {
|
|
|
13845
13957
|
}
|
|
13846
13958
|
|
|
13847
13959
|
// src/kits/documentTitle.ts
|
|
13848
|
-
var
|
|
13960
|
+
var React67 = __toESM(require("react"), 1);
|
|
13849
13961
|
function formatDocumentTitle(routeTitle, appName) {
|
|
13850
13962
|
return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
|
|
13851
13963
|
}
|
|
13852
13964
|
function useDocumentTitle(routeTitle, appName) {
|
|
13853
|
-
|
|
13965
|
+
React67.useEffect(() => {
|
|
13854
13966
|
if (typeof document === "undefined") return;
|
|
13855
13967
|
document.title = formatDocumentTitle(routeTitle, appName);
|
|
13856
13968
|
}, [routeTitle, appName]);
|