@flytedan/flytebot-design-system 0.27.1 → 0.28.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/dist/index.cjs CHANGED
@@ -2953,20 +2953,780 @@ function DataTable({
2953
2953
  }
2954
2954
 
2955
2955
  // src/components/data/FilterBar.tsx
2956
+ var React23 = __toESM(require("react"), 1);
2957
+
2958
+ // src/components/forms/NumberInput.tsx
2959
+ var React21 = __toESM(require("react"), 1);
2960
+
2961
+ // src/components/forms/field.tsx
2956
2962
  var React20 = __toESM(require("react"), 1);
2957
2963
  var import_jsx_runtime41 = require("react/jsx-runtime");
2964
+ function useFieldId(id) {
2965
+ const generated = React20.useId();
2966
+ return id || generated;
2967
+ }
2968
+ function FieldLabel({ htmlFor, id, required = false, onClick, children }) {
2969
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { className: "fd-field-label", htmlFor, id, onClick, children: [
2970
+ children,
2971
+ required ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-field-req", "aria-hidden": "true", children: "*" }) : null
2972
+ ] });
2973
+ }
2974
+ function useTriggerLabelling(label, id) {
2975
+ const fieldId = useFieldId(id);
2976
+ const labelId = fieldId + "-label";
2977
+ return { fieldId, labelId, ariaLabelledBy: label ? labelId + " " + fieldId : void 0 };
2978
+ }
2979
+
2980
+ // src/components/forms/NumberInput.tsx
2981
+ var import_jsx_runtime42 = require("react/jsx-runtime");
2982
+ function NumberInput({
2983
+ label,
2984
+ help,
2985
+ error,
2986
+ prefix,
2987
+ suffix,
2988
+ required = false,
2989
+ disabled = false,
2990
+ min = -Infinity,
2991
+ max = Infinity,
2992
+ step = 1,
2993
+ bigStep,
2994
+ value,
2995
+ onChange,
2996
+ format = true,
2997
+ className = "",
2998
+ style,
2999
+ placeholder,
3000
+ id,
3001
+ "aria-label": ariaLabel
3002
+ }) {
3003
+ const fieldId = useFieldId(id);
3004
+ const num = (v) => {
3005
+ const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
3006
+ return isNaN(n) ? null : n;
3007
+ };
3008
+ const [text, setText] = React21.useState(value == null || value === "" ? "" : String(value));
3009
+ const [editing, setEditing] = React21.useState(false);
3010
+ const timer = React21.useRef(null);
3011
+ React21.useEffect(() => {
3012
+ if (!editing) setText(value == null || value === "" ? "" : String(value));
3013
+ }, [value, editing]);
3014
+ const clamp = (n) => Math.min(max, Math.max(min, n));
3015
+ const fire = (n) => onChange && onChange({ target: { value: n } });
3016
+ const bump = (dir, mult = 1) => {
3017
+ const cur = num(text) ?? num(value) ?? (min === -Infinity ? 0 : min);
3018
+ const next = clamp(cur + dir * (bigStep && mult > 1 ? bigStep : step) * (bigStep ? 1 : mult));
3019
+ setText(String(next));
3020
+ fire(next);
3021
+ };
3022
+ const hold = (dir) => {
3023
+ bump(dir);
3024
+ let n = 0;
3025
+ const tick = () => {
3026
+ n++;
3027
+ bump(dir, n > 6 ? 4 : 1);
3028
+ timer.current = setTimeout(tick, n > 12 ? 40 : n > 6 ? 70 : 120);
3029
+ };
3030
+ timer.current = setTimeout(tick, 420);
3031
+ };
3032
+ const release = () => {
3033
+ if (timer.current) clearTimeout(timer.current);
3034
+ };
3035
+ React21.useEffect(() => () => {
3036
+ if (timer.current) clearTimeout(timer.current);
3037
+ }, []);
3038
+ const shown = editing ? text : (() => {
3039
+ const n = num(text);
3040
+ return n == null ? "" : format ? n.toLocaleString() : String(n);
3041
+ })();
3042
+ const box = ["fd-input", "fd-input-num", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
3043
+ const fieldName = label || ariaLabel;
3044
+ const stepperName = (verb) => fieldName ? verb + " " + fieldName : verb;
3045
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
3046
+ label ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
3047
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: box, style: { gap: 8 }, children: [
3048
+ prefix ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
3049
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
3050
+ "input",
3051
+ {
3052
+ id: fieldId,
3053
+ "aria-label": ariaLabel,
3054
+ inputMode: "numeric",
3055
+ disabled,
3056
+ placeholder,
3057
+ value: shown,
3058
+ onFocus: () => setEditing(true),
3059
+ onBlur: () => {
3060
+ setEditing(false);
3061
+ const n = num(text);
3062
+ if (n != null) {
3063
+ const c = clamp(n);
3064
+ setText(String(c));
3065
+ fire(c);
3066
+ }
3067
+ },
3068
+ onChange: (e) => {
3069
+ setText(e.target.value);
3070
+ const n = num(e.target.value);
3071
+ if (n != null) fire(n);
3072
+ },
3073
+ onKeyDown: (e) => {
3074
+ if (e.key === "ArrowUp") {
3075
+ e.preventDefault();
3076
+ bump(1, e.shiftKey ? 2 : 1);
3077
+ } else if (e.key === "ArrowDown") {
3078
+ e.preventDefault();
3079
+ bump(-1, e.shiftKey ? 2 : 1);
3080
+ }
3081
+ }
3082
+ }
3083
+ ),
3084
+ suffix ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "fd-input-affix", children: suffix }) : null,
3085
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "fd-row", style: { gap: 4, flex: "none" }, children: [
3086
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
3087
+ "button",
3088
+ {
3089
+ type: "button",
3090
+ className: "fd-stepbtn",
3091
+ "aria-label": stepperName("Decrease"),
3092
+ disabled: disabled || (num(text) ?? 0) <= min,
3093
+ onPointerDown: () => hold(-1),
3094
+ onPointerUp: release,
3095
+ onPointerLeave: release,
3096
+ children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("i", { className: "ph ph-minus" })
3097
+ }
3098
+ ),
3099
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
3100
+ "button",
3101
+ {
3102
+ type: "button",
3103
+ className: "fd-stepbtn",
3104
+ "aria-label": stepperName("Increase"),
3105
+ disabled: disabled || (num(text) ?? 0) >= max,
3106
+ onPointerDown: () => hold(1),
3107
+ onPointerUp: release,
3108
+ onPointerLeave: release,
3109
+ children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("i", { className: "ph ph-plus" })
3110
+ }
3111
+ )
3112
+ ] })
3113
+ ] }),
3114
+ error ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "fd-field-error", children: [
3115
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3116
+ error
3117
+ ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "fd-field-help", children: help }) : null
3118
+ ] });
3119
+ }
3120
+
3121
+ // src/components/forms/DatePicker.tsx
3122
+ var React22 = __toESM(require("react"), 1);
3123
+ var import_jsx_runtime43 = require("react/jsx-runtime");
3124
+ var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
3125
+ var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
3126
+ var iso = (d) => d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
3127
+ var parse = (s) => {
3128
+ if (!s) return null;
3129
+ const [y, m, d] = s.split("-").map(Number);
3130
+ return new Date(y, m - 1, d);
3131
+ };
3132
+ var fmt = (s) => {
3133
+ const d = parse(s);
3134
+ return d ? MONTHS[d.getMonth()].slice(0, 3) + " " + d.getDate() + ", " + d.getFullYear() : "";
3135
+ };
3136
+ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3137
+ const today = /* @__PURE__ */ new Date();
3138
+ const sel = range ? value || {} : { start: value, end: value };
3139
+ const anchor = parse(sel.start) || parse(initialMonth) || today;
3140
+ const [vy, setVy] = React22.useState(anchor.getFullYear());
3141
+ const [vm, setVm] = React22.useState(anchor.getMonth());
3142
+ const [mode2, setMode] = React22.useState("days");
3143
+ const [hover, setHover] = React22.useState(null);
3144
+ const s = parse(sel.start), e = parse(sel.end);
3145
+ const hoverEnd = range && s && !e && hover ? parse(hover) : null;
3146
+ const inRange = (d) => {
3147
+ const lo = s, hi = e || hoverEnd;
3148
+ return lo && hi && d > (lo < hi ? lo : hi) && d < (lo < hi ? hi : lo);
3149
+ };
3150
+ const isEdge = (d) => s && iso(d) === iso(s) || e && iso(d) === iso(e);
3151
+ const clickDay = (d) => {
3152
+ const v = iso(d);
3153
+ if (!range) {
3154
+ onPick(v);
3155
+ return;
3156
+ }
3157
+ if (!sel.start || sel.start && sel.end) onPick({ start: v, end: "" });
3158
+ else {
3159
+ const a = parse(sel.start);
3160
+ onPick(d < a ? { start: v, end: sel.start } : { start: sel.start, end: v });
3161
+ }
3162
+ };
3163
+ const nav = (d) => {
3164
+ let m = vm + d, y = vy;
3165
+ if (m < 0) {
3166
+ m = 11;
3167
+ y--;
3168
+ }
3169
+ if (m > 11) {
3170
+ m = 0;
3171
+ y++;
3172
+ }
3173
+ setVm(m);
3174
+ setVy(y);
3175
+ };
3176
+ const monthGrid = (y, m) => {
3177
+ const startPad = new Date(y, m, 1).getDay();
3178
+ const cells = [];
3179
+ for (let i = 0; i < 42; i++) cells.push(new Date(y, m, i - startPad + 1));
3180
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "fd-cal-grid", style: { width: months > 1 ? 252 : "auto", flex: "none" }, onMouseLeave: () => setHover(null), children: [
3181
+ DOW.map((d) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-cal-dow", children: d }, d)),
3182
+ cells.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
3183
+ "button",
3184
+ {
3185
+ type: "button",
3186
+ className: ["fd-cal-day", d.getMonth() !== m ? "is-out" : "", iso(d) === iso(today) ? "is-today" : "", inRange(d) ? "in-range" : "", isEdge(d) ? "is-edge" : ""].filter(Boolean).join(" "),
3187
+ onClick: () => clickDay(d),
3188
+ onMouseEnter: () => range && setHover(iso(d)),
3189
+ children: d.getDate()
3190
+ },
3191
+ i
3192
+ ))
3193
+ ] });
3194
+ };
3195
+ const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
3196
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, children: [
3197
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "fd-cal-head", children: [
3198
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Previous", onClick: () => mode2 === "years" ? setVy(vy - 12) : mode2 === "months" ? setVy(vy - 1) : nav(-1), children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("i", { className: "ph ph-caret-left" }) }),
3199
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("button", { type: "button", className: "fd-cal-title", onClick: () => setMode(mode2 === "days" ? "months" : mode2 === "months" ? "years" : "days"), children: [
3200
+ mode2 === "days" ? MONTHS[vm] + " " + vy : mode2 === "months" ? vy : vy - 5 + " \u2013 " + (vy + 6),
3201
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("i", { className: "ph ph-caret-down", style: { fontSize: 10, marginLeft: 6, color: "var(--text-muted)" } })
3202
+ ] }),
3203
+ months > 1 && mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-cal-title", style: { cursor: "default", background: "none" }, children: MONTHS[nextM] + " " + nextY }) : null,
3204
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Next", onClick: () => mode2 === "years" ? setVy(vy + 12) : mode2 === "months" ? setVy(vy + 1) : nav(1), children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("i", { className: "ph ph-caret-right" }) })
3205
+ ] }),
3206
+ mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { style: { display: "flex", gap: 18 }, children: [
3207
+ monthGrid(vy, vm),
3208
+ months > 1 ? monthGrid(nextY, nextM) : null
3209
+ ] }) : mode2 === "months" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "fd-cal-grid-months", children: MONTHS.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
3210
+ "button",
3211
+ {
3212
+ type: "button",
3213
+ className: "fd-cal-cell" + (i === vm && s && s.getFullYear() === vy ? " is-sel" : ""),
3214
+ onClick: () => {
3215
+ setVm(i);
3216
+ setMode("days");
3217
+ },
3218
+ children: m.slice(0, 3)
3219
+ },
3220
+ m
3221
+ )) }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "fd-cal-grid-months", children: Array.from({ length: 12 }, (_, i) => vy - 5 + i).map((y) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
3222
+ "button",
3223
+ {
3224
+ type: "button",
3225
+ className: "fd-cal-cell" + (y === vy ? " is-sel" : ""),
3226
+ onClick: () => {
3227
+ setVy(y);
3228
+ setMode("months");
3229
+ },
3230
+ children: y
3231
+ },
3232
+ y
3233
+ )) }),
3234
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "fd-cal-foot", children: [
3235
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
3236
+ "button",
3237
+ {
3238
+ type: "button",
3239
+ className: "fd-btn fd-btn-link",
3240
+ style: { fontSize: 12.5 },
3241
+ onClick: () => {
3242
+ setVy(today.getFullYear());
3243
+ setVm(today.getMonth());
3244
+ setMode("days");
3245
+ },
3246
+ children: "Today"
3247
+ }
3248
+ ),
3249
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { style: { flex: 1 } }),
3250
+ range && sel.start ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
3251
+ fmt(sel.start),
3252
+ sel.end ? " \u2192 " + fmt(sel.end) : " \u2192 pick an end"
3253
+ ] }) : null
3254
+ ] })
3255
+ ] });
3256
+ }
3257
+ function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, ...rest }) {
3258
+ const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
3259
+ const [open, setOpen] = React22.useState(false);
3260
+ const rootRef = React22.useRef(null);
3261
+ const boxRef = React22.useRef(null);
3262
+ const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
3263
+ const toggle = () => {
3264
+ if (!disabled) setOpen(!open);
3265
+ };
3266
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3267
+ label ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(FieldLabel, { id: labelId, required, onClick: toggle, children: label }) : null,
3268
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: ["fd-input", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" "), style: { cursor: disabled ? "not-allowed" : "pointer" }, onClick: toggle, ref: boxRef, children: [
3269
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }) }),
3270
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
3271
+ "button",
3272
+ {
3273
+ type: "button",
3274
+ id: fieldId,
3275
+ "aria-labelledby": ariaLabelledBy,
3276
+ title: truncationTitle(display),
3277
+ disabled,
3278
+ onKeyDown: (e) => {
3279
+ if (e.key === "Enter" || e.key === " ") {
3280
+ e.preventDefault();
3281
+ toggle();
3282
+ }
3283
+ },
3284
+ style: { all: "unset", flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", cursor: "inherit", color: display ? "var(--text)" : "var(--text-muted)" },
3285
+ ...rest,
3286
+ children: display || placeholder || (range ? "Pick a date range" : "Pick a date")
3287
+ }
3288
+ ),
3289
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-select-caret", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
3290
+ ] }),
3291
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
3292
+ Popover,
3293
+ {
3294
+ open,
3295
+ anchorRef: boxRef,
3296
+ triggerRef: rootRef,
3297
+ onClose: () => setOpen(false),
3298
+ placement: "bottom-start",
3299
+ offset: 6,
3300
+ role: "presentation",
3301
+ style: { width: "max-content" },
3302
+ children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
3303
+ Calendar,
3304
+ {
3305
+ range,
3306
+ months: range ? 2 : 1,
3307
+ value,
3308
+ onPick: (v) => {
3309
+ onChange && onChange({ target: { value: v } });
3310
+ if (!range || v.start && v.end) setOpen(false);
3311
+ }
3312
+ }
3313
+ )
3314
+ }
3315
+ ),
3316
+ error ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "fd-field-error", children: [
3317
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3318
+ error
3319
+ ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-field-help", children: help }) : null
3320
+ ] });
3321
+ }
3322
+
3323
+ // src/components/forms/Textarea.tsx
3324
+ var import_jsx_runtime44 = require("react/jsx-runtime");
3325
+ function Textarea({ label, help, error, required = false, rows = 4, disabled = false, id, className = "", style, ...rest }) {
3326
+ const fieldId = useFieldId(id);
3327
+ const box = ["fd-input", "fd-input-textarea", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
3328
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
3329
+ label ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
3330
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: box, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("textarea", { id: fieldId, rows, disabled, "aria-invalid": error ? "true" : void 0, ...rest }) }),
3331
+ error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "fd-field-error", children: [
3332
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3333
+ error
3334
+ ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-field-help", children: help }) : null
3335
+ ] });
3336
+ }
3337
+
3338
+ // src/components/data/FilterBar.tsx
3339
+ var import_jsx_runtime45 = require("react/jsx-runtime");
2958
3340
  var isSet = (v) => !(v == null || v === "" || v === false);
3341
+ function isFieldSet(field, value) {
3342
+ switch (field.type) {
3343
+ case "text":
3344
+ case "select":
3345
+ return isSet(value);
3346
+ case "multiSelect":
3347
+ case "pasteList": {
3348
+ const v = value;
3349
+ return !!v && Array.isArray(v.values) && v.values.length > 0;
3350
+ }
3351
+ case "range": {
3352
+ const v = value;
3353
+ return !!v && (v.min != null || v.max != null);
3354
+ }
3355
+ case "date": {
3356
+ const v = value;
3357
+ if (!v) return false;
3358
+ return v.kind === "withinDays" ? v.days != null : !!(v.from || v.to);
3359
+ }
3360
+ }
3361
+ }
3362
+ function chipLabel(field, value) {
3363
+ switch (field.type) {
3364
+ case "text":
3365
+ return String(value ?? "");
3366
+ case "select": {
3367
+ const chosen = field.options.find((o) => o.value === value);
3368
+ return chosen ? chosen.label : String(value ?? "");
3369
+ }
3370
+ case "multiSelect":
3371
+ case "pasteList": {
3372
+ const v = value;
3373
+ if (!v || !v.values.length) return "";
3374
+ const prefix = v.operator === "notIn" ? "Not " : "";
3375
+ return v.values.length <= 2 ? prefix + v.values.map((o) => o.label).join(", ") : prefix + v.values.length + " selected";
3376
+ }
3377
+ case "range": {
3378
+ const v = value;
3379
+ if (!v) return "";
3380
+ if (v.min != null && v.max != null) return v.min + "\u2013" + v.max;
3381
+ if (v.min != null) return "\u2265 " + v.min;
3382
+ if (v.max != null) return "\u2264 " + v.max;
3383
+ return "";
3384
+ }
3385
+ case "date": {
3386
+ const v = value;
3387
+ if (!v) return "";
3388
+ if (v.kind === "withinDays") return "Last " + v.days + " day" + (v.days === 1 ? "" : "s");
3389
+ return (v.from || "\u2026") + " \u2192 " + (v.to || "\u2026");
3390
+ }
3391
+ }
3392
+ }
3393
+ function OperatorToggle({
3394
+ operator,
3395
+ onChange,
3396
+ label
3397
+ }) {
3398
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3399
+ SegmentedControl,
3400
+ {
3401
+ "aria-label": label + " \u2014 include or exclude",
3402
+ options: [
3403
+ { value: "in", label: "Is any of" },
3404
+ { value: "notIn", label: "Is none of" }
3405
+ ],
3406
+ value: operator,
3407
+ onChange: (v) => onChange(v)
3408
+ }
3409
+ );
3410
+ }
3411
+ function EditPopover({ zIndex, width, children }) {
3412
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3413
+ "span",
3414
+ {
3415
+ className: "fd-view-enter",
3416
+ style: {
3417
+ position: "absolute",
3418
+ top: "calc(100% + 6px)",
3419
+ left: 0,
3420
+ zIndex,
3421
+ width,
3422
+ maxWidth: "calc(100vw - 32px)",
3423
+ display: "block",
3424
+ background: "var(--surface)",
3425
+ border: "1px solid var(--border)",
3426
+ borderRadius: 10,
3427
+ boxShadow: "0 16px 44px rgba(11,13,17,.18)",
3428
+ padding: "var(--s-8)"
3429
+ },
3430
+ children
3431
+ }
3432
+ ) });
3433
+ }
3434
+ function MultiSelectPanel({
3435
+ field,
3436
+ value,
3437
+ onChange,
3438
+ onClose
3439
+ }) {
3440
+ const operator = value?.operator ?? "in";
3441
+ const selected = value?.values ?? [];
3442
+ const [query, setQuery] = React23.useState("");
3443
+ const [asyncOptions, setAsyncOptions] = React23.useState(null);
3444
+ const [loading, setLoading] = React23.useState(!!field.loadOptions);
3445
+ const [active, setActive] = React23.useState(0);
3446
+ const inputRef = React23.useRef(null);
3447
+ const listId = React23.useId();
3448
+ React23.useEffect(() => {
3449
+ inputRef.current?.focus();
3450
+ }, []);
3451
+ React23.useEffect(() => {
3452
+ if (!field.loadOptions) return;
3453
+ let cancelled = false;
3454
+ setLoading(true);
3455
+ const loadOptions = field.loadOptions;
3456
+ const t = setTimeout(() => {
3457
+ loadOptions(query).then((opts) => {
3458
+ if (!cancelled) {
3459
+ setAsyncOptions(opts);
3460
+ setLoading(false);
3461
+ }
3462
+ }).catch(() => {
3463
+ if (!cancelled) {
3464
+ setAsyncOptions([]);
3465
+ setLoading(false);
3466
+ }
3467
+ });
3468
+ }, 300);
3469
+ return () => {
3470
+ cancelled = true;
3471
+ clearTimeout(t);
3472
+ };
3473
+ }, [query, field.loadOptions]);
3474
+ const options = field.loadOptions ? asyncOptions ?? [] : (field.options ?? []).filter((o) => o.label.toLowerCase().includes(query.toLowerCase()));
3475
+ React23.useEffect(() => {
3476
+ setActive(0);
3477
+ }, [query, options.length]);
3478
+ const isSelected = (o) => selected.some((s) => s.value === o.value);
3479
+ const toggle = (o) => {
3480
+ const next = isSelected(o) ? selected.filter((s) => s.value !== o.value) : [...selected, o];
3481
+ onChange({ operator, values: next });
3482
+ };
3483
+ const activeId = options[active] ? listId + "-opt-" + active : void 0;
3484
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-stack", style: { gap: "var(--s-8)", width: 260 }, children: [
3485
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(OperatorToggle, { operator, onChange: (op) => onChange({ operator: op, values: selected }), label: field.label }),
3486
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3487
+ "input",
3488
+ {
3489
+ ref: inputRef,
3490
+ role: "combobox",
3491
+ "aria-expanded": "true",
3492
+ "aria-controls": listId,
3493
+ "aria-autocomplete": "list",
3494
+ "aria-activedescendant": activeId,
3495
+ "aria-label": field.label,
3496
+ className: "fd-input",
3497
+ style: { width: "100%", padding: "6px 10px" },
3498
+ value: query,
3499
+ placeholder: field.placeholder || "Search\u2026",
3500
+ onChange: (e) => setQuery(e.target.value),
3501
+ onKeyDown: (e) => {
3502
+ if (e.key === "ArrowDown") {
3503
+ e.preventDefault();
3504
+ setActive((a) => Math.min(a + 1, options.length - 1));
3505
+ } else if (e.key === "ArrowUp") {
3506
+ e.preventDefault();
3507
+ setActive((a) => Math.max(a - 1, 0));
3508
+ } else if (e.key === "Enter") {
3509
+ e.preventDefault();
3510
+ if (options[active]) toggle(options[active]);
3511
+ } else if (e.key === "Escape") {
3512
+ e.stopPropagation();
3513
+ onClose();
3514
+ }
3515
+ }
3516
+ }
3517
+ ),
3518
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: "var(--s-4)" }, children: [
3519
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-spinner", "aria-hidden": "true" }),
3520
+ " Loading\u2026"
3521
+ ] }) : options.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-body-sm fd-muted", children: "No matches" }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3522
+ "span",
3523
+ {
3524
+ id: listId,
3525
+ role: "listbox",
3526
+ "aria-label": field.label,
3527
+ "aria-multiselectable": "true",
3528
+ className: "fd-stack",
3529
+ style: { gap: 2, maxHeight: 220, overflowY: "auto" },
3530
+ children: options.map((o, i) => {
3531
+ const on = isSelected(o);
3532
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
3533
+ "button",
3534
+ {
3535
+ type: "button",
3536
+ id: listId + "-opt-" + i,
3537
+ role: "option",
3538
+ "aria-selected": on,
3539
+ className: "fd-row",
3540
+ onMouseEnter: () => setActive(i),
3541
+ onClick: () => toggle(o),
3542
+ style: {
3543
+ gap: "var(--s-8)",
3544
+ padding: "4px 8px",
3545
+ borderRadius: 7,
3546
+ border: 0,
3547
+ width: "100%",
3548
+ textAlign: "left",
3549
+ cursor: "pointer",
3550
+ background: i === active ? "var(--surface-brand)" : "transparent"
3551
+ },
3552
+ children: [
3553
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("i", { className: on ? "ph ph-check-square" : "ph ph-square", "aria-hidden": "true" }),
3554
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-body-sm", style: { flex: 1, color: "var(--text)" }, children: o.label })
3555
+ ]
3556
+ },
3557
+ o.value
3558
+ );
3559
+ })
3560
+ }
3561
+ ),
3562
+ selected.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
3563
+ selected.length,
3564
+ " selected"
3565
+ ] }) : null
3566
+ ] });
3567
+ }
3568
+ function RangePanel({
3569
+ field,
3570
+ value,
3571
+ onChange,
3572
+ onClose
3573
+ }) {
3574
+ const min = value?.min;
3575
+ const max = value?.max;
3576
+ const rangeError = min != null && max != null && min > max ? "Must be \u2265 " + (field.minLabel || "min").toLowerCase() : void 0;
3577
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-stack", style: { gap: "var(--s-8)", width: 240 }, children: [
3578
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3579
+ NumberInput,
3580
+ {
3581
+ label: field.minLabel || "At least",
3582
+ value: min ?? "",
3583
+ min: field.min,
3584
+ max: field.max,
3585
+ step: field.step,
3586
+ placeholder: field.minPlaceholder,
3587
+ onChange: (e) => onChange({ min: e.target.value, max })
3588
+ }
3589
+ ),
3590
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3591
+ NumberInput,
3592
+ {
3593
+ label: field.maxLabel || "At most",
3594
+ value: max ?? "",
3595
+ min: field.min,
3596
+ max: field.max,
3597
+ step: field.step,
3598
+ error: rangeError,
3599
+ placeholder: field.maxPlaceholder,
3600
+ onChange: (e) => onChange({ min, max: e.target.value })
3601
+ }
3602
+ ),
3603
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Button, { size: "sm", variant: "secondary", onClick: onClose, children: "Done" })
3604
+ ] });
3605
+ }
3606
+ function DatePanel({
3607
+ field,
3608
+ value,
3609
+ onChange,
3610
+ onClose
3611
+ }) {
3612
+ const kind = value?.kind ?? "withinDays";
3613
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-stack", style: { gap: "var(--s-8)", width: 300 }, children: [
3614
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3615
+ SegmentedControl,
3616
+ {
3617
+ "aria-label": field.label + " \u2014 relative or between dates",
3618
+ options: [
3619
+ { value: "withinDays", label: "Within last N days" },
3620
+ { value: "between", label: "Between dates" }
3621
+ ],
3622
+ value: kind,
3623
+ onChange: (k) => {
3624
+ if (k === "withinDays") {
3625
+ onChange({ kind: "withinDays", days: value?.kind === "withinDays" ? value.days : field.defaultDays ?? 30 });
3626
+ } else {
3627
+ onChange({ kind: "between", from: value?.kind === "between" ? value.from : "", to: value?.kind === "between" ? value.to : "" });
3628
+ }
3629
+ }
3630
+ }
3631
+ ),
3632
+ kind === "withinDays" ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3633
+ NumberInput,
3634
+ {
3635
+ label: "Days",
3636
+ min: 1,
3637
+ value: value?.kind === "withinDays" ? value.days : field.defaultDays ?? 30,
3638
+ onChange: (e) => onChange({ kind: "withinDays", days: e.target.value })
3639
+ }
3640
+ ) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3641
+ DatePicker,
3642
+ {
3643
+ range: true,
3644
+ label: "Date range",
3645
+ value: value?.kind === "between" ? { start: value.from, end: value.to } : void 0,
3646
+ onChange: (e) => onChange({ kind: "between", from: e.target.value.start || "", to: e.target.value.end || "" })
3647
+ }
3648
+ ),
3649
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Button, { size: "sm", variant: "secondary", onClick: onClose, children: "Done" })
3650
+ ] });
3651
+ }
3652
+ function PasteListPanel({
3653
+ field,
3654
+ value,
3655
+ onChange,
3656
+ onClose
3657
+ }) {
3658
+ const operator = value?.operator ?? "in";
3659
+ const selected = value?.values ?? [];
3660
+ const [text, setText] = React23.useState("");
3661
+ const [loading, setLoading] = React23.useState(false);
3662
+ const [unmatched, setUnmatched] = React23.useState([]);
3663
+ const [error, setError] = React23.useState(null);
3664
+ const wrapRef = React23.useRef(null);
3665
+ React23.useEffect(() => {
3666
+ wrapRef.current?.querySelector("textarea")?.focus();
3667
+ }, []);
3668
+ const doResolve = () => {
3669
+ const tokens = text.split(/[\n,]/).map((t) => t.trim()).filter(Boolean);
3670
+ if (!tokens.length) return;
3671
+ setLoading(true);
3672
+ setError(null);
3673
+ field.resolve(tokens).then((result) => {
3674
+ setLoading(false);
3675
+ setUnmatched(result.unmatched);
3676
+ const merged = new Map(selected.map((s) => [s.value, s]));
3677
+ for (const m of result.matched) merged.set(m.value, { value: m.value, label: m.label });
3678
+ onChange({ operator, values: Array.from(merged.values()) });
3679
+ setText("");
3680
+ }).catch((err) => {
3681
+ setLoading(false);
3682
+ setError(err instanceof Error ? err.message : "Could not resolve the pasted list.");
3683
+ });
3684
+ };
3685
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-stack", style: { gap: "var(--s-8)", width: 320 }, children: [
3686
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(OperatorToggle, { operator, onChange: (op) => onChange({ operator: op, values: selected }), label: field.label }),
3687
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { ref: wrapRef, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3688
+ Textarea,
3689
+ {
3690
+ "aria-label": field.label + " \u2014 paste a list",
3691
+ rows: 4,
3692
+ placeholder: field.placeholder || "Paste names, one per line or comma-separated",
3693
+ value: text,
3694
+ disabled: loading,
3695
+ onChange: (e) => setText(e.target.value),
3696
+ onKeyDown: (e) => {
3697
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
3698
+ e.preventDefault();
3699
+ doResolve();
3700
+ }
3701
+ }
3702
+ }
3703
+ ) }),
3704
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Button, { size: "sm", variant: "secondary", onClick: doResolve, disabled: loading || !text.trim(), children: loading ? "Resolving\u2026" : "Resolve" }),
3705
+ error ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Banner, { tone: "danger", title: "Couldn't resolve the list", detail: error }) : null,
3706
+ unmatched.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Banner, { tone: "warn", title: unmatched.length + " didn't match", detail: unmatched.join(", ") }) : null,
3707
+ selected.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-stack", style: { gap: "var(--s-4)" }, children: [
3708
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
3709
+ selected.length,
3710
+ " matched"
3711
+ ] }),
3712
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-row", style: { flexWrap: "wrap", gap: "var(--s-4)" }, children: selected.map((v) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Tag, { onRemove: () => onChange({ operator, values: selected.filter((s) => s.value !== v.value) }), children: v.label }, v.value)) })
3713
+ ] }) : null,
3714
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Button, { size: "sm", variant: "secondary", onClick: onClose, children: "Done" })
3715
+ ] });
3716
+ }
2959
3717
  function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align = "left", className = "", ...rest }) {
2960
- const [panel, setPanel] = React20.useState(null);
3718
+ const [panel, setPanel] = React23.useState(null);
2961
3719
  const zIndex = useOverlayLayer(!!panel);
2962
- const rootRef = React20.useRef(null);
2963
- const textInputRef = React20.useRef(null);
2964
- const optionsRef = React20.useRef(null);
3720
+ const rootRef = React23.useRef(null);
3721
+ const textInputRef = React23.useRef(null);
3722
+ const optionsRef = React23.useRef(null);
2965
3723
  const editingField = panel && panel.kind === "edit" ? fields.find((f) => f.key === panel.key) : void 0;
2966
- const dismissible = !!panel && (panel.kind === "add" || panel.kind === "edit" && editingField?.type === "select");
2967
- React20.useEffect(() => {
3724
+ const dismissible = !!panel && (panel.kind === "add" || panel.kind === "edit" && editingField?.type !== "text");
3725
+ React23.useEffect(() => {
2968
3726
  if (!dismissible) return;
2969
3727
  const away = (e) => {
3728
+ const target = e.target;
3729
+ if (target.closest && target.closest(".fd-pop")) return;
2970
3730
  if (rootRef.current && !rootRef.current.contains(e.target)) setPanel(null);
2971
3731
  };
2972
3732
  const esc = (e) => {
@@ -2979,7 +3739,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
2979
3739
  document.removeEventListener("keydown", esc);
2980
3740
  };
2981
3741
  }, [dismissible]);
2982
- React20.useEffect(() => {
3742
+ React23.useEffect(() => {
2983
3743
  if (!panel || panel.kind !== "edit") return;
2984
3744
  if (editingField?.type === "text") {
2985
3745
  textInputRef.current?.focus();
@@ -2988,20 +3748,20 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
2988
3748
  target?.focus();
2989
3749
  }
2990
3750
  }, [panel]);
2991
- const addableFields = fields.filter((f) => !isSet(filters[f.key]));
3751
+ const addableFields = fields.filter((f) => !isFieldSet(f, filters[f.key]));
2992
3752
  const startEditing = (key) => setPanel({ kind: "edit", key });
2993
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className, style: { position: "relative", display: "inline-flex", flexWrap: "wrap", alignItems: "center", gap: 8 }, ref: rootRef, ...rest, children: [
3753
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className, style: { position: "relative", display: "inline-flex", flexWrap: "wrap", alignItems: "center", gap: 8 }, ref: rootRef, ...rest, children: [
2994
3754
  fields.map((field) => {
2995
3755
  const value = filters[field.key];
2996
3756
  const editing = panel?.kind === "edit" && panel.key === field.key;
2997
3757
  if (editing && field.type === "text") {
2998
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
3758
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
2999
3759
  "span",
3000
3760
  {
3001
3761
  className: "fd-tag",
3002
3762
  style: { background: "var(--surface-brand)", borderColor: "var(--border-brand)", cursor: "text" },
3003
3763
  children: [
3004
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
3764
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3005
3765
  "input",
3006
3766
  {
3007
3767
  ref: textInputRef,
@@ -3020,7 +3780,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
3020
3780
  style: { all: "unset", minWidth: 90, color: "var(--text-on-surface-brand)" }
3021
3781
  }
3022
3782
  ),
3023
- isSet(value) ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
3783
+ isSet(value) ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3024
3784
  "span",
3025
3785
  {
3026
3786
  className: "fd-tag-remove",
@@ -3031,7 +3791,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
3031
3791
  onFilterRemove(field.key);
3032
3792
  setPanel(null);
3033
3793
  },
3034
- children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" })
3794
+ children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" })
3035
3795
  }
3036
3796
  ) : null
3037
3797
  ]
@@ -3041,22 +3801,22 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
3041
3801
  }
3042
3802
  if (editing && field.type === "select") {
3043
3803
  const chosen = field.options.find((o) => o.value === value);
3044
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, children: [
3045
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(Tag, { selected: true, onClick: () => setPanel(null), onRemove: () => {
3804
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, children: [
3805
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(Tag, { selected: true, onClick: () => setPanel(null), onRemove: () => {
3046
3806
  if (isSet(value)) onFilterRemove(field.key);
3047
3807
  setPanel(null);
3048
3808
  }, children: [
3049
3809
  field.label,
3050
3810
  chosen ? ": " + chosen.label : ""
3051
3811
  ] }),
3052
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
3812
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3053
3813
  "span",
3054
3814
  {
3055
3815
  className: "fd-view-enter",
3056
3816
  style: { position: "absolute", top: "calc(100% + 6px)", left: 0, zIndex, minWidth: 200, maxWidth: "calc(100vw - 32px)", display: "block", background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 10, boxShadow: "0 16px 44px rgba(11,13,17,.18)", padding: 8 },
3057
- children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-stack", role: "listbox", "aria-label": field.label, ref: optionsRef, style: { gap: 2 }, children: field.options.map((o) => {
3817
+ children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-stack", role: "listbox", "aria-label": field.label, ref: optionsRef, style: { gap: 2 }, children: field.options.map((o) => {
3058
3818
  const on = o.value === value;
3059
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
3819
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3060
3820
  "button",
3061
3821
  {
3062
3822
  type: "button",
@@ -3068,7 +3828,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
3068
3828
  setPanel(null);
3069
3829
  },
3070
3830
  style: { gap: 8, padding: "4px 8px", borderRadius: 7, border: 0, width: "100%", textAlign: "left", cursor: "pointer", background: on ? "var(--surface-brand)" : "transparent" },
3071
- children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-body-sm", style: { flex: 1, fontWeight: on ? 700 : 500, color: on ? "var(--text-on-surface-brand)" : "var(--text)" }, children: o.label })
3831
+ children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-body-sm", style: { flex: 1, fontWeight: on ? 700 : 500, color: on ? "var(--text-on-surface-brand)" : "var(--text)" }, children: o.label })
3072
3832
  },
3073
3833
  o.value
3074
3834
  );
@@ -3077,19 +3837,69 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
3077
3837
  ) })
3078
3838
  ] }, field.key);
3079
3839
  }
3080
- if (isSet(value)) {
3081
- const chosen = field.type === "select" ? field.options.find((o) => o.value === value) : void 0;
3082
- const display = chosen ? chosen.label : String(value);
3083
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(Tag, { selected: true, onClick: () => startEditing(field.key), onRemove: () => onFilterRemove(field.key), children: [
3840
+ if (editing && field.type === "multiSelect") {
3841
+ const mv = value;
3842
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, children: [
3843
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(Tag, { selected: true, onClick: () => setPanel(null), onRemove: () => {
3844
+ if (isFieldSet(field, value)) onFilterRemove(field.key);
3845
+ setPanel(null);
3846
+ }, children: [
3847
+ field.label,
3848
+ isFieldSet(field, value) ? ": " + chipLabel(field, value) : ""
3849
+ ] }),
3850
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(EditPopover, { zIndex, width: 260, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(MultiSelectPanel, { field, value: mv, onChange: (v) => onFilterChange(field.key, v), onClose: () => setPanel(null) }) })
3851
+ ] }, field.key);
3852
+ }
3853
+ if (editing && field.type === "range") {
3854
+ const rv = value;
3855
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, children: [
3856
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(Tag, { selected: true, onClick: () => setPanel(null), onRemove: () => {
3857
+ if (isFieldSet(field, value)) onFilterRemove(field.key);
3858
+ setPanel(null);
3859
+ }, children: [
3860
+ field.label,
3861
+ isFieldSet(field, value) ? ": " + chipLabel(field, value) : ""
3862
+ ] }),
3863
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(EditPopover, { zIndex, width: 240, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(RangePanel, { field, value: rv, onChange: (v) => onFilterChange(field.key, v), onClose: () => setPanel(null) }) })
3864
+ ] }, field.key);
3865
+ }
3866
+ if (editing && field.type === "date") {
3867
+ const dv = value;
3868
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, children: [
3869
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(Tag, { selected: true, onClick: () => setPanel(null), onRemove: () => {
3870
+ if (isFieldSet(field, value)) onFilterRemove(field.key);
3871
+ setPanel(null);
3872
+ }, children: [
3873
+ field.label,
3874
+ isFieldSet(field, value) ? ": " + chipLabel(field, value) : ""
3875
+ ] }),
3876
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(EditPopover, { zIndex, width: 300, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(DatePanel, { field, value: dv, onChange: (v) => onFilterChange(field.key, v), onClose: () => setPanel(null) }) })
3877
+ ] }, field.key);
3878
+ }
3879
+ if (editing && field.type === "pasteList") {
3880
+ const pv = value;
3881
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, children: [
3882
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(Tag, { selected: true, onClick: () => setPanel(null), onRemove: () => {
3883
+ if (isFieldSet(field, value)) onFilterRemove(field.key);
3884
+ setPanel(null);
3885
+ }, children: [
3886
+ field.label,
3887
+ isFieldSet(field, value) ? ": " + chipLabel(field, value) : ""
3888
+ ] }),
3889
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(EditPopover, { zIndex, width: 320, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(PasteListPanel, { field, value: pv, onChange: (v) => onFilterChange(field.key, v), onClose: () => setPanel(null) }) })
3890
+ ] }, field.key);
3891
+ }
3892
+ if (isFieldSet(field, value)) {
3893
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(Tag, { selected: true, onClick: () => startEditing(field.key), onRemove: () => onFilterRemove(field.key), children: [
3084
3894
  field.label,
3085
3895
  ": ",
3086
- display
3896
+ chipLabel(field, value)
3087
3897
  ] }, field.key);
3088
3898
  }
3089
3899
  return null;
3090
3900
  }),
3091
- addableFields.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, children: [
3092
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
3901
+ addableFields.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, children: [
3902
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3093
3903
  Button,
3094
3904
  {
3095
3905
  size: "sm",
@@ -3101,14 +3911,14 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
3101
3911
  children: "Filter"
3102
3912
  }
3103
3913
  ),
3104
- panel?.kind === "add" ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
3914
+ panel?.kind === "add" ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3105
3915
  "span",
3106
3916
  {
3107
3917
  className: "fd-view-enter",
3108
3918
  style: { position: "absolute", top: "calc(100% + 6px)", [align]: 0, zIndex, width: 220, maxWidth: "calc(100vw - 32px)", display: "block", background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 10, boxShadow: "0 16px 44px rgba(11,13,17,.18)", padding: 8 },
3109
- children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "fd-stack", role: "menu", "aria-label": "Add filter", style: { gap: 2 }, children: [
3110
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "4px 8px 6px" }, children: "Add filter" }),
3111
- addableFields.map((f) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
3919
+ children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-stack", role: "menu", "aria-label": "Add filter", style: { gap: 2 }, children: [
3920
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "4px 8px 6px" }, children: "Add filter" }),
3921
+ addableFields.map((f) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3112
3922
  "button",
3113
3923
  {
3114
3924
  type: "button",
@@ -3116,7 +3926,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
3116
3926
  className: "fd-row",
3117
3927
  onClick: () => startEditing(f.key),
3118
3928
  style: { gap: 8, padding: "4px 8px", borderRadius: 7, border: 0, width: "100%", textAlign: "left", cursor: "pointer", background: "transparent" },
3119
- children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-body-sm", style: { flex: 1, color: "var(--text)" }, children: f.label })
3929
+ children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-body-sm", style: { flex: 1, color: "var(--text)" }, children: f.label })
3120
3930
  },
3121
3931
  f.key
3122
3932
  ))
@@ -3128,7 +3938,7 @@ function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align
3128
3938
  }
3129
3939
 
3130
3940
  // src/components/data/StatTile.tsx
3131
- var import_jsx_runtime42 = require("react/jsx-runtime");
3941
+ var import_jsx_runtime46 = require("react/jsx-runtime");
3132
3942
  function isZeroDelta(delta) {
3133
3943
  if (!delta) return false;
3134
3944
  const match = delta.match(/[\d.]+/);
@@ -3139,23 +3949,23 @@ function StatTile({ label, value, sub, delta, invert = false, loading = false, c
3139
3949
  const isZero = isZeroDelta(delta);
3140
3950
  const isGood = invert ? isDecrease : !isDecrease;
3141
3951
  const deltaToneClass = isZero ? "fd-stat-delta-neutral" : isGood ? "fd-stat-delta-up" : "fd-stat-delta-down";
3142
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: ["fd-stat", compact3 ? "fd-stat-compact" : "", className].filter(Boolean).join(" "), ...rest, children: [
3143
- loading ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "fd-skel fd-skel-text", style: { display: "block", height: compact3 ? 20 : 28, width: "62%" } }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "fd-stat-top", children: [
3144
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "fd-stat-figure", children: value }),
3145
- delta ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: deltaToneClass, style: { fontWeight: 600, fontSize: "var(--body-sm-size)", flex: "none" }, children: [
3146
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("i", { className: "ph ph-" + (isZero ? "minus" : "arrow-" + (isDecrease ? "down" : "up") + "-right"), "aria-hidden": "true" }),
3952
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: ["fd-stat", compact3 ? "fd-stat-compact" : "", className].filter(Boolean).join(" "), ...rest, children: [
3953
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-skel fd-skel-text", style: { display: "block", height: compact3 ? 20 : 28, width: "62%" } }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "fd-stat-top", children: [
3954
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-stat-figure", children: value }),
3955
+ delta ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: deltaToneClass, style: { fontWeight: 600, fontSize: "var(--body-sm-size)", flex: "none" }, children: [
3956
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { className: "ph ph-" + (isZero ? "minus" : "arrow-" + (isDecrease ? "down" : "up") + "-right"), "aria-hidden": "true" }),
3147
3957
  " ",
3148
3958
  delta
3149
3959
  ] }) : null
3150
3960
  ] }),
3151
- !loading && sub ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "fd-stat-sub", children: sub }) : null,
3152
- loading ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "fd-skel fd-skel-text", style: { display: "block", height: 10, width: "40%", marginTop: 8 } }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "fd-stat-label", style: { display: "block" }, children: label })
3961
+ !loading && sub ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-stat-sub", children: sub }) : null,
3962
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-skel fd-skel-text", style: { display: "block", height: 10, width: "40%", marginTop: 8 } }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-stat-label", style: { display: "block" }, children: label })
3153
3963
  ] });
3154
3964
  }
3155
3965
 
3156
3966
  // src/components/data/CodeBlock.tsx
3157
- var React21 = __toESM(require("react"), 1);
3158
- var import_jsx_runtime43 = require("react/jsx-runtime");
3967
+ var React24 = __toESM(require("react"), 1);
3968
+ var import_jsx_runtime47 = require("react/jsx-runtime");
3159
3969
  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)$/;
3160
3970
  var RULES = {
3161
3971
  js: [
@@ -3310,13 +4120,13 @@ function tokenize(src, lang) {
3310
4120
  return out;
3311
4121
  }
3312
4122
  function Highlighted({ code, lang }) {
3313
- const toks = React21.useMemo(() => tokenize(code, lang), [code, lang]);
3314
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_jsx_runtime43.Fragment, { children: toks.map((tk, i) => tk.c ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "tok-" + tk.c, children: tk.t }, i) : tk.t) });
4123
+ const toks = React24.useMemo(() => tokenize(code, lang), [code, lang]);
4124
+ 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) });
3315
4125
  }
3316
4126
  function useCopy() {
3317
- const [done, setDone] = React21.useState(false);
3318
- const timer = React21.useRef(null);
3319
- React21.useEffect(() => () => {
4127
+ const [done, setDone] = React24.useState(false);
4128
+ const timer = React24.useRef(null);
4129
+ React24.useEffect(() => () => {
3320
4130
  if (timer.current) clearTimeout(timer.current);
3321
4131
  }, []);
3322
4132
  const copy = (text) => {
@@ -3352,37 +4162,37 @@ function CodeBlock({
3352
4162
  actions,
3353
4163
  className = ""
3354
4164
  }) {
3355
- const [wrap, setWrap] = React21.useState(!!wrapDefault);
3356
- const [open, setOpen] = React21.useState(false);
4165
+ const [wrap, setWrap] = React24.useState(!!wrapDefault);
4166
+ const [open, setOpen] = React24.useState(false);
3357
4167
  const [copied, copy] = useCopy();
3358
4168
  const body = String(code).replace(/\n$/, "");
3359
4169
  const lines = body.split("\n");
3360
4170
  const foldable = collapseAfter > 0 && lines.length > collapseAfter + 6;
3361
4171
  const shown = foldable && !open ? lines.slice(0, collapseAfter).join("\n") : body;
3362
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: ["fd-code", wrap ? "is-wrap" : "", className].filter(Boolean).join(" "), children: [
3363
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "fd-code-head", children: [
3364
- filename ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-code-file", children: filename }) : null,
3365
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-code-lang", children: languageLabel(language) }),
3366
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-code-spacer" }),
4172
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: ["fd-code", wrap ? "is-wrap" : "", className].filter(Boolean).join(" "), children: [
4173
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "fd-code-head", children: [
4174
+ filename ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-code-file", children: filename }) : null,
4175
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-code-lang", children: languageLabel(language) }),
4176
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-code-spacer" }),
3367
4177
  actions,
3368
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: "fd-code-act", onClick: () => setWrap((v) => !v), "aria-pressed": wrap, title: wrap ? "No wrap" : "Soft wrap", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("i", { className: "ph ph-text-" + (wrap ? "columns" : "align-left"), "aria-hidden": "true" }) }),
3369
- copyable ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("button", { type: "button", className: "fd-code-act" + (copied ? " is-done" : ""), onClick: () => copy(body), children: [
3370
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
3371
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { children: copied ? "Copied" : "Copy" })
4178
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: "fd-code-act", onClick: () => setWrap((v) => !v), "aria-pressed": wrap, title: wrap ? "No wrap" : "Soft wrap", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-text-" + (wrap ? "columns" : "align-left"), "aria-hidden": "true" }) }),
4179
+ copyable ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("button", { type: "button", className: "fd-code-act" + (copied ? " is-done" : ""), onClick: () => copy(body), children: [
4180
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
4181
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { children: copied ? "Copied" : "Copy" })
3372
4182
  ] }) : null
3373
4183
  ] }),
3374
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "fd-code-body", children: [
3375
- lineNumbers ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("pre", { className: "fd-code-gutter", "aria-hidden": "true", children: shown.split("\n").map((_, i) => i + 1 + "\n").join("") }) : null,
3376
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("pre", { className: "fd-code-pre", tabIndex: 0, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("code", { children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Highlighted, { code: shown, lang: language }) }) })
4184
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "fd-code-body", children: [
4185
+ lineNumbers ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("pre", { className: "fd-code-gutter", "aria-hidden": "true", children: shown.split("\n").map((_, i) => i + 1 + "\n").join("") }) : null,
4186
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("pre", { className: "fd-code-pre", tabIndex: 0, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("code", { children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Highlighted, { code: shown, lang: language }) }) })
3377
4187
  ] }),
3378
- foldable ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("button", { type: "button", className: "fd-code-fold", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
3379
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" }),
4188
+ foldable ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("button", { type: "button", className: "fd-code-fold", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
4189
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" }),
3380
4190
  open ? "Collapse" : "Show all " + lines.length + " lines"
3381
4191
  ] }) : null
3382
4192
  ] });
3383
4193
  }
3384
4194
  function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" }) {
3385
- const [open, setOpen] = React21.useState(false);
4195
+ const [open, setOpen] = React24.useState(false);
3386
4196
  const [copied, copy] = useCopy();
3387
4197
  const raw = String(diff).replace(/\n$/, "");
3388
4198
  const all = raw.split("\n").map((line) => {
@@ -3396,40 +4206,40 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
3396
4206
  const dels = all.filter((l) => l.k === "del").length;
3397
4207
  const foldable = collapseAfter > 0 && all.length > collapseAfter + 6;
3398
4208
  const rows = foldable && !open ? all.slice(0, collapseAfter) : all;
3399
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: ["fd-code", "fd-diff", className].filter(Boolean).join(" "), children: [
3400
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "fd-code-head", children: [
3401
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("i", { className: "ph ph-git-diff fd-code-icon", "aria-hidden": "true" }),
3402
- filename ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-code-file", children: filename }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-code-lang", children: "Diff" }),
3403
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "fd-diff-stat fd-tabular", children: [
3404
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "is-add", children: [
4209
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: ["fd-code", "fd-diff", className].filter(Boolean).join(" "), children: [
4210
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "fd-code-head", children: [
4211
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-git-diff fd-code-icon", "aria-hidden": "true" }),
4212
+ filename ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-code-file", children: filename }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-code-lang", children: "Diff" }),
4213
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "fd-diff-stat fd-tabular", children: [
4214
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "is-add", children: [
3405
4215
  "+",
3406
4216
  adds
3407
4217
  ] }),
3408
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "is-del", children: [
4218
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "is-del", children: [
3409
4219
  "\u2212",
3410
4220
  dels
3411
4221
  ] })
3412
4222
  ] }),
3413
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-code-spacer" }),
3414
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("button", { type: "button", className: "fd-code-act" + (copied ? " is-done" : ""), onClick: () => copy(raw), children: [
3415
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
3416
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { children: copied ? "Copied" : "Copy" })
4223
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-code-spacer" }),
4224
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("button", { type: "button", className: "fd-code-act" + (copied ? " is-done" : ""), onClick: () => copy(raw), children: [
4225
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
4226
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { children: copied ? "Copied" : "Copy" })
3417
4227
  ] })
3418
4228
  ] }),
3419
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "fd-diff-body", children: rows.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "fd-diff-line is-" + r.k, children: [
3420
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-diff-mark", "aria-hidden": "true", children: r.k === "add" ? "+" : r.k === "del" ? "\u2212" : "" }),
3421
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("code", { children: r.k === "add" || r.k === "del" ? r.line.slice(1) : r.line })
4229
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "fd-diff-body", children: rows.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "fd-diff-line is-" + r.k, children: [
4230
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-diff-mark", "aria-hidden": "true", children: r.k === "add" ? "+" : r.k === "del" ? "\u2212" : "" }),
4231
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("code", { children: r.k === "add" || r.k === "del" ? r.line.slice(1) : r.line })
3422
4232
  ] }, i)) }),
3423
- foldable ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("button", { type: "button", className: "fd-code-fold", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
3424
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" }),
4233
+ foldable ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("button", { type: "button", className: "fd-code-fold", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
4234
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" }),
3425
4235
  open ? "Collapse" : "Show all " + all.length + " lines"
3426
4236
  ] }) : null
3427
4237
  ] });
3428
4238
  }
3429
4239
 
3430
4240
  // src/components/data/Markdown.tsx
3431
- var React22 = __toESM(require("react"), 1);
3432
- var import_jsx_runtime44 = require("react/jsx-runtime");
4241
+ var React25 = __toESM(require("react"), 1);
4242
+ var import_jsx_runtime48 = require("react/jsx-runtime");
3433
4243
  var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
3434
4244
  var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
3435
4245
  var INLINE = [
@@ -3459,22 +4269,22 @@ function inlineNodes(src, ctx, keyBase) {
3459
4269
  const { kind, m } = best;
3460
4270
  if (m.index > 0) out.push(rest.slice(0, m.index));
3461
4271
  const g = (i) => m[i];
3462
- if (kind === "code") out.push(/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("code", { className: "fd-md-code", children: g(1) }, key()));
4272
+ if (kind === "code") out.push(/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("code", { className: "fd-md-code", children: g(1) }, key()));
3463
4273
  else if (kind === "image") {
3464
4274
  const src2 = safeHref(g(2));
3465
- out.push(ctx.allowImages && src2 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("img", { className: "fd-md-img", src: src2, alt: g(1) || "", title: g(3) || void 0, loading: "lazy" }, key()) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-md-imgalt", children: g(1) || "image" }, key()));
4275
+ out.push(ctx.allowImages && src2 ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("img", { className: "fd-md-img", src: src2, alt: g(1) || "", title: g(3) || void 0, loading: "lazy" }, key()) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-md-imgalt", children: g(1) || "image" }, key()));
3466
4276
  } else if (kind === "link") {
3467
4277
  const href = safeHref(g(2));
3468
- out.push(href ? /* @__PURE__ */ (0, import_jsx_runtime44.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_runtime44.jsx)("span", { children: g(1) }, key()));
4278
+ 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()));
3469
4279
  } else if (kind === "cite") {
3470
- out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(React22.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("sup", { className: "fd-md-cite", children: g(1) }, key()));
3471
- } else if (kind === "strongem") out.push(/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("strong", { children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("em", { children: inlineNodes(g(1), ctx, key()) }) }, key()));
3472
- else if (kind === "strong") out.push(/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
3473
- else if (kind === "em") out.push(/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
3474
- else if (kind === "del") out.push(/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("del", { children: inlineNodes(g(1), ctx, key()) }, key()));
4280
+ out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(React25.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("sup", { className: "fd-md-cite", children: g(1) }, key()));
4281
+ } 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()));
4282
+ else if (kind === "strong") out.push(/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
4283
+ else if (kind === "em") out.push(/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
4284
+ else if (kind === "del") out.push(/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("del", { children: inlineNodes(g(1), ctx, key()) }, key()));
3475
4285
  else if (kind === "autolink" || kind === "bare") {
3476
4286
  const href = safeHref(g(1));
3477
- out.push(href ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: g(1).replace(/^mailto:/, "") }, key()) : g(1));
4287
+ out.push(href ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: g(1).replace(/^mailto:/, "") }, key()) : g(1));
3478
4288
  }
3479
4289
  rest = rest.slice(m.index + m[0].length);
3480
4290
  }
@@ -3592,33 +4402,33 @@ function renderBlocks(blocks, ctx, path) {
3592
4402
  const k = path + "-" + i;
3593
4403
  switch (b.t) {
3594
4404
  case "code": {
3595
- if ((b.lang || "").toLowerCase() === "diff") return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(DiffBlock, { diff: b.code, filename: b.file || void 0 }, k);
3596
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(CodeBlock, { code: b.code, language: b.lang, filename: b.file || void 0, ...ctx.codeProps || {} }, k);
4405
+ if ((b.lang || "").toLowerCase() === "diff") return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(DiffBlock, { diff: b.code, filename: b.file || void 0 }, k);
4406
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(CodeBlock, { code: b.code, language: b.lang, filename: b.file || void 0, ...ctx.codeProps || {} }, k);
3597
4407
  }
3598
4408
  case "h": {
3599
4409
  const lvl = Math.min(6, Math.max(1, b.level + (ctx.headingOffset || 0)));
3600
4410
  const Tag2 = "h" + lvl;
3601
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Tag2, { className: "fd-md-h fd-md-h" + lvl, children: inlineNodes(b.text, ctx, k) }, k);
4411
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Tag2, { className: "fd-md-h fd-md-h" + lvl, children: inlineNodes(b.text, ctx, k) }, k);
3602
4412
  }
3603
4413
  case "hr":
3604
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("hr", { className: "fd-md-hr" }, k);
4414
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("hr", { className: "fd-md-hr" }, k);
3605
4415
  case "quote":
3606
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("blockquote", { className: "fd-md-quote", children: renderBlocks(b.children, ctx, k) }, k);
4416
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("blockquote", { className: "fd-md-quote", children: renderBlocks(b.children, ctx, k) }, k);
3607
4417
  case "list": {
3608
4418
  const Tag2 = b.ordered ? "ol" : "ul";
3609
4419
  const isTask = b.items.some((it) => it.checked != null);
3610
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Tag2, { className: "fd-md-list" + (isTask ? " is-task" : ""), start: b.ordered && b.start !== 1 ? b.start : void 0, children: b.items.map((it, j) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("li", { className: it.checked != null ? it.checked ? "is-done" : "is-todo" : void 0, children: [
3611
- it.checked != null ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-md-task", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("i", { className: "ph ph-" + (it.checked ? "check-square" : "square") }) }) : null,
3612
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-md-li", children: renderBlocks(it.children, ctx, k + "-" + j) })
4420
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Tag2, { className: "fd-md-list" + (isTask ? " is-task" : ""), start: b.ordered && b.start !== 1 ? b.start : void 0, children: b.items.map((it, j) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("li", { className: it.checked != null ? it.checked ? "is-done" : "is-todo" : void 0, children: [
4421
+ it.checked != null ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-md-task", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-" + (it.checked ? "check-square" : "square") }) }) : null,
4422
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-md-li", children: renderBlocks(it.children, ctx, k + "-" + j) })
3613
4423
  ] }, k + "-" + j)) }, k);
3614
4424
  }
3615
4425
  case "table":
3616
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "fd-md-tablewrap", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("table", { className: "fd-md-table", children: [
3617
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("tr", { children: b.head.map((c, j) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("th", { style: { textAlign: b.align[j] || "left" }, children: inlineNodes(c, ctx, k + "h" + j) }, j)) }) }),
3618
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("tbody", { children: b.rows.map((r, ri) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("tr", { children: b.head.map((_, ci) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { style: { textAlign: b.align[ci] || "left" }, children: inlineNodes(r[ci] || "", ctx, k + ri + "c" + ci) }, ci)) }, ri)) })
4426
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "fd-md-tablewrap", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("table", { className: "fd-md-table", children: [
4427
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("tr", { children: b.head.map((c, j) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("th", { style: { textAlign: b.align[j] || "left" }, children: inlineNodes(c, ctx, k + "h" + j) }, j)) }) }),
4428
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("tbody", { children: b.rows.map((r, ri) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("tr", { children: b.head.map((_, ci) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("td", { style: { textAlign: b.align[ci] || "left" }, children: inlineNodes(r[ci] || "", ctx, k + ri + "c" + ci) }, ci)) }, ri)) })
3619
4429
  ] }) }, k);
3620
4430
  default:
3621
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "fd-md-p", children: inlineNodes(b.text, ctx, k) }, k);
4431
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "fd-md-p", children: inlineNodes(b.text, ctx, k) }, k);
3622
4432
  }
3623
4433
  });
3624
4434
  }
@@ -3632,25 +4442,25 @@ function Markdown({
3632
4442
  onLinkClick
3633
4443
  }) {
3634
4444
  const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
3635
- const blocks = React22.useMemo(() => parseBlocks(source), [source]);
3636
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: ["fd-md", className].filter(Boolean).join(" "), children: renderBlocks(blocks, ctx, "b") });
4445
+ const blocks = React25.useMemo(() => parseBlocks(source), [source]);
4446
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: ["fd-md", className].filter(Boolean).join(" "), children: renderBlocks(blocks, ctx, "b") });
3637
4447
  }
3638
4448
  function MarkdownInline({ source = "", className = "", onLinkClick }) {
3639
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: ["fd-md-inline", className].filter(Boolean).join(" "), children: inlineNodes(source, { allowImages: false, onLinkClick }, "i") });
4449
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: ["fd-md-inline", className].filter(Boolean).join(" "), children: inlineNodes(source, { allowImages: false, onLinkClick }, "i") });
3640
4450
  }
3641
4451
  function markdownToText(src) {
3642
4452
  return String(src == null ? "" : src).replace(/```[\w+#-]*\n?([\s\S]*?)```/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").replace(/^\s{0,3}#{1,6}\s+/gm, "").replace(/\*\*\*([^*]+)\*\*\*|\*\*([^*]+)\*\*|__([^_]+)__/g, "$1$2$3").replace(/(^|\W)[*_]([^*_\n]+)[*_](\W|$)/g, "$1$2$3").replace(/~~([^~]+)~~/g, "$1").replace(/^\s*>\s?/gm, "").trim();
3643
4453
  }
3644
4454
 
3645
4455
  // src/components/data/Meter.tsx
3646
- var import_jsx_runtime45 = require("react/jsx-runtime");
4456
+ var import_jsx_runtime49 = require("react/jsx-runtime");
3647
4457
  function Meter({ segments = [], unallocated = 0, height = 8, label, legend = false, className = "" }) {
3648
4458
  const total = segments.reduce((s, x) => s + x.value, 0) + unallocated;
3649
4459
  const pct = (v) => total ? v / total * 100 : 0;
3650
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 8 }, children: [
3651
- label ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-label-lg fd-secondary", children: label }) : null,
3652
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "fd-meterbar", style: { height }, children: [
3653
- segments.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
4460
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 8 }, children: [
4461
+ label ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-label-lg fd-secondary", children: label }) : null,
4462
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-meterbar", style: { height }, children: [
4463
+ segments.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3654
4464
  "span",
3655
4465
  {
3656
4466
  className: "fd-meterbar-seg",
@@ -3659,15 +4469,15 @@ function Meter({ segments = [], unallocated = 0, height = 8, label, legend = fal
3659
4469
  },
3660
4470
  i
3661
4471
  )),
3662
- unallocated > 0 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-meterbar-seg fd-meterbar-unallocated", title: "Unallocated", style: { width: pct(unallocated) + "%" } }) : null
4472
+ unallocated > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-meterbar-seg fd-meterbar-unallocated", title: "Unallocated", style: { width: pct(unallocated) + "%" } }) : null
3663
4473
  ] }),
3664
- legend ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap" }, children: [
3665
- segments.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-row fd-body-sm fd-secondary", style: { gap: 7 }, children: [
3666
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { style: { width: 9, height: 9, borderRadius: 2, background: s.color || "var(--chart-" + (i % 8 + 1) + ")" } }),
4474
+ legend ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap" }, children: [
4475
+ segments.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "fd-row fd-body-sm fd-secondary", style: { gap: 7 }, children: [
4476
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { style: { width: 9, height: 9, borderRadius: 2, background: s.color || "var(--chart-" + (i % 8 + 1) + ")" } }),
3667
4477
  s.label
3668
4478
  ] }, i)),
3669
- unallocated > 0 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-row fd-body-sm fd-secondary", style: { gap: 7 }, children: [
3670
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-meterbar-unallocated", style: { width: 9, height: 9, borderRadius: 2 } }),
4479
+ unallocated > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "fd-row fd-body-sm fd-secondary", style: { gap: 7 }, children: [
4480
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-meterbar-unallocated", style: { width: 9, height: 9, borderRadius: 2 } }),
3671
4481
  "Unallocated"
3672
4482
  ] }) : null
3673
4483
  ] }) : null
@@ -3675,7 +4485,7 @@ function Meter({ segments = [], unallocated = 0, height = 8, label, legend = fal
3675
4485
  }
3676
4486
 
3677
4487
  // src/components/data/Pagination.tsx
3678
- var import_jsx_runtime46 = require("react/jsx-runtime");
4488
+ var import_jsx_runtime50 = require("react/jsx-runtime");
3679
4489
  var unitPluralRules = new Intl.PluralRules("en-US");
3680
4490
  function pluralizeUnit(n, singular, irregularPlural) {
3681
4491
  return unitPluralRules.select(n) === "one" ? singular : irregularPlural ?? `${singular}s`;
@@ -3706,12 +4516,12 @@ function Pagination({
3706
4516
  if (i === 1 || i === totalPages || Math.abs(i - page) <= span) nums.push(i);
3707
4517
  else if (nums[nums.length - 1] !== "\u2026") nums.push("\u2026");
3708
4518
  }
3709
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: ["fd-pag", className].filter(Boolean).join(" "), ...rest, children: [
3710
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-pag-count", children: loading ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-skel fd-skel-text", style: { display: "inline-block", height: 12, width: 108 } }) : total === 0 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
4519
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: ["fd-pag", className].filter(Boolean).join(" "), ...rest, children: [
4520
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-pag-count", children: loading ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-skel fd-skel-text", style: { display: "inline-block", height: 12, width: 108 } }) : total === 0 ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_jsx_runtime50.Fragment, { children: [
3711
4521
  "No ",
3712
4522
  unitLabel
3713
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
3714
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("strong", { children: [
4523
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_jsx_runtime50.Fragment, { children: [
4524
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("strong", { children: [
3715
4525
  from.toLocaleString(),
3716
4526
  "\u2013",
3717
4527
  to.toLocaleString()
@@ -3721,14 +4531,14 @@ function Pagination({
3721
4531
  " ",
3722
4532
  unitLabel
3723
4533
  ] }) }),
3724
- onPageSizeChange ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("label", { className: "fd-pag-size", children: [
3725
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { children: "Rows" }),
3726
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("select", { value: pageSize, onChange: (e) => onPageSizeChange(Number(e.target.value)), "aria-label": "Rows per page", children: pageSizes.map((n) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: n, children: n }, n)) })
4534
+ onPageSizeChange ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("label", { className: "fd-pag-size", children: [
4535
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { children: "Rows" }),
4536
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("select", { value: pageSize, onChange: (e) => onPageSizeChange(Number(e.target.value)), "aria-label": "Rows per page", children: pageSizes.map((n) => /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("option", { value: n, children: n }, n)) })
3727
4537
  ] }) : null,
3728
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "fd-pag-nav", children: [
3729
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", onClick: () => go(1), disabled: page <= 1, "aria-label": "First page", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { className: "ph ph-caret-double-left" }) }),
3730
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", onClick: () => go(page - 1), disabled: page <= 1, "aria-label": "Previous page", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { className: "ph ph-caret-left" }) }),
3731
- nums.map((n, i) => n === "\u2026" ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-pag-gap", "aria-hidden": "true", children: "\u2026" }, "e" + i) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
4538
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "fd-pag-nav", children: [
4539
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", onClick: () => go(1), disabled: page <= 1, "aria-label": "First page", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-caret-double-left" }) }),
4540
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", onClick: () => go(page - 1), disabled: page <= 1, "aria-label": "Previous page", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-caret-left" }) }),
4541
+ nums.map((n, i) => n === "\u2026" ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-pag-gap", "aria-hidden": "true", children: "\u2026" }, "e" + i) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3732
4542
  "button",
3733
4543
  {
3734
4544
  type: "button",
@@ -3739,15 +4549,15 @@ function Pagination({
3739
4549
  },
3740
4550
  n
3741
4551
  )),
3742
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", onClick: () => go(page + 1), disabled: page >= totalPages, "aria-label": "Next page", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { className: "ph ph-caret-right" }) }),
3743
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", onClick: () => go(totalPages), disabled: page >= totalPages, "aria-label": "Last page", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { className: "ph ph-caret-double-right" }) })
4552
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", onClick: () => go(page + 1), disabled: page >= totalPages, "aria-label": "Next page", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-caret-right" }) }),
4553
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", onClick: () => go(totalPages), disabled: page >= totalPages, "aria-label": "Last page", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-caret-double-right" }) })
3744
4554
  ] })
3745
4555
  ] });
3746
4556
  }
3747
4557
 
3748
4558
  // src/components/data/RelativeTime.tsx
3749
- var React23 = __toESM(require("react"), 1);
3750
- var import_jsx_runtime47 = require("react/jsx-runtime");
4559
+ var React26 = __toESM(require("react"), 1);
4560
+ var import_jsx_runtime51 = require("react/jsx-runtime");
3751
4561
  var MIN = 6e4;
3752
4562
  var HOUR = 36e5;
3753
4563
  var DAY = 864e5;
@@ -3798,9 +4608,9 @@ function formatDuration(ms) {
3798
4608
  return h + "h" + (m % 60 ? " " + m % 60 + "m" : "");
3799
4609
  }
3800
4610
  function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true, ...rest }) {
3801
- const [, force] = React23.useState(0);
4611
+ const [, force] = React26.useState(0);
3802
4612
  const t = value instanceof Date ? value.getTime() : Date.parse(value);
3803
- React23.useEffect(() => {
4613
+ React26.useEffect(() => {
3804
4614
  if (!refresh2 || !t || isNaN(t)) return;
3805
4615
  const abs = Math.abs(t - Date.now());
3806
4616
  if (abs > DAY) return;
@@ -3809,15 +4619,15 @@ function RelativeTime({ value, prefix, className = "", refresh: refresh2 = true,
3809
4619
  return () => clearInterval(id);
3810
4620
  }, [t, refresh2]);
3811
4621
  if (!t || isNaN(t)) return null;
3812
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("time", { className, dateTime: new Date(t).toISOString(), title: formatAbsolute(new Date(t)), ...rest, children: [
4622
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("time", { className, dateTime: new Date(t).toISOString(), title: formatAbsolute(new Date(t)), ...rest, children: [
3813
4623
  prefix ? prefix + " " : "",
3814
4624
  formatRelative(new Date(t))
3815
4625
  ] });
3816
4626
  }
3817
4627
 
3818
4628
  // src/components/data/ScoreMeter.tsx
3819
- var React24 = __toESM(require("react"), 1);
3820
- var import_jsx_runtime48 = require("react/jsx-runtime");
4629
+ var React27 = __toESM(require("react"), 1);
4630
+ var import_jsx_runtime52 = require("react/jsx-runtime");
3821
4631
  function ScoreMeter({
3822
4632
  score,
3823
4633
  segments,
@@ -3831,15 +4641,15 @@ function ScoreMeter({
3831
4641
  breakdownWidth = 280,
3832
4642
  className = ""
3833
4643
  }) {
3834
- const [open, setOpen] = React24.useState(false);
3835
- const ref = React24.useRef(null);
4644
+ const [open, setOpen] = React27.useState(false);
4645
+ const ref = React27.useRef(null);
3836
4646
  const value = Math.max(0, Math.min(100, Math.round(Number(score) || 0)));
3837
- const body = /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(React24.Fragment, { children: [
3838
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-scoremeter-rail", style: { width }, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(SegmentedMeter, { total: 100, segments, height, showTotal: false, showPercent: false, legend: false }) }),
3839
- showScore ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
4647
+ const body = /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React27.Fragment, { children: [
4648
+ /* @__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 }) }),
4649
+ showScore ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-scoremeter-value fd-tabular", "aria-hidden": "true", children: value }) : null
3840
4650
  ] });
3841
4651
  if (!breakdown) {
3842
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
4652
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
3843
4653
  "span",
3844
4654
  {
3845
4655
  className: ["fd-scoremeter", className].filter(Boolean).join(" "),
@@ -3853,8 +4663,8 @@ function ScoreMeter({
3853
4663
  }
3854
4664
  );
3855
4665
  }
3856
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(React24.Fragment, { children: [
3857
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
4666
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React27.Fragment, { children: [
4667
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
3858
4668
  "button",
3859
4669
  {
3860
4670
  type: "button",
@@ -3867,7 +4677,7 @@ function ScoreMeter({
3867
4677
  children: body
3868
4678
  }
3869
4679
  ),
3870
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
4680
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
3871
4681
  Popover,
3872
4682
  {
3873
4683
  open,
@@ -3884,13 +4694,13 @@ function ScoreMeter({
3884
4694
  }
3885
4695
 
3886
4696
  // src/components/data/SortMenu.tsx
3887
- var React25 = __toESM(require("react"), 1);
3888
- var import_jsx_runtime49 = require("react/jsx-runtime");
4697
+ var React28 = __toESM(require("react"), 1);
4698
+ var import_jsx_runtime53 = require("react/jsx-runtime");
3889
4699
  function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", className = "", ...rest }) {
3890
- const [open, setOpen] = React25.useState(false);
4700
+ const [open, setOpen] = React28.useState(false);
3891
4701
  const zIndex = useOverlayLayer(open);
3892
- const ref = React25.useRef(null);
3893
- React25.useEffect(() => {
4702
+ const ref = React28.useRef(null);
4703
+ React28.useEffect(() => {
3894
4704
  if (!open) return;
3895
4705
  const away = (e) => {
3896
4706
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -3910,7 +4720,7 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
3910
4720
  const arrow = (f, d) => {
3911
4721
  const on = cur && cur.key === f.key && dir === d;
3912
4722
  const label = d === "asc" ? f.numeric ? "lowest first" : "A to Z" : f.numeric ? "highest first" : "Z to A";
3913
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
4723
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
3914
4724
  "button",
3915
4725
  {
3916
4726
  type: "button",
@@ -3928,21 +4738,21 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
3928
4738
  background: on ? "var(--brand)" : "var(--surface)",
3929
4739
  color: on ? "#fff" : "var(--text-muted)"
3930
4740
  },
3931
- children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-arrow-" + (d === "asc" ? "up" : "down"), style: { fontSize: 13 } })
4741
+ children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-arrow-" + (d === "asc" ? "up" : "down"), style: { fontSize: 13 } })
3932
4742
  }
3933
4743
  );
3934
4744
  };
3935
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className, style: { position: "relative", display: "inline-flex" }, ref, ...rest, children: [
3936
- /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(Button, { size, variant: "secondary", icon: dir === "asc" ? "sort-ascending" : "sort-descending", onClick: () => setOpen(!open), children: [
4745
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { className, style: { position: "relative", display: "inline-flex" }, ref, ...rest, children: [
4746
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(Button, { size, variant: "secondary", icon: dir === "asc" ? "sort-ascending" : "sort-descending", onClick: () => setOpen(!open), children: [
3937
4747
  cur ? cur.label : "Unsorted",
3938
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-" + (dir === "asc" ? "arrow-up" : "arrow-down"), style: { fontSize: 12, marginLeft: 6, opacity: 0.75 } })
4748
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-" + (dir === "asc" ? "arrow-up" : "arrow-down"), style: { fontSize: 12, marginLeft: 6, opacity: 0.75 } })
3939
4749
  ] }),
3940
- open ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-view-enter", style: { position: "absolute", top: "calc(100% + 6px)", [align]: 0, zIndex, width: 280, maxWidth: "calc(100vw - 32px)", display: "block", background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 10, boxShadow: "0 16px 44px rgba(11,13,17,.18)", padding: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
3941
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "4px 8px 6px" }, children: "Sort by" }),
4750
+ open ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-view-enter", style: { position: "absolute", top: "calc(100% + 6px)", [align]: 0, zIndex, width: 280, maxWidth: "calc(100vw - 32px)", display: "block", background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 10, boxShadow: "0 16px 44px rgba(11,13,17,.18)", padding: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
4751
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "4px 8px 6px" }, children: "Sort by" }),
3942
4752
  fields.map((f) => {
3943
4753
  const active = cur && cur.key === f.key;
3944
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "fd-row", style: { gap: 8, padding: "4px 8px", borderRadius: 7, background: active ? "var(--surface-brand)" : "transparent" }, children: [
3945
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-body-sm", style: { flex: 1, fontWeight: active ? 700 : 500, color: active ? "var(--text-on-surface-brand)" : "var(--text)" }, children: f.label }),
4754
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { className: "fd-row", style: { gap: 8, padding: "4px 8px", borderRadius: 7, background: active ? "var(--surface-brand)" : "transparent" }, children: [
4755
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-body-sm", style: { flex: 1, fontWeight: active ? 700 : 500, color: active ? "var(--text-on-surface-brand)" : "var(--text)" }, children: f.label }),
3946
4756
  arrow(f, "asc"),
3947
4757
  arrow(f, "desc")
3948
4758
  ] }, f.key);
@@ -3952,8 +4762,8 @@ function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", cla
3952
4762
  }
3953
4763
 
3954
4764
  // src/components/data/StepList.tsx
3955
- var React26 = __toESM(require("react"), 1);
3956
- var import_jsx_runtime50 = require("react/jsx-runtime");
4765
+ var React29 = __toESM(require("react"), 1);
4766
+ var import_jsx_runtime54 = require("react/jsx-runtime");
3957
4767
  var KIND_ICON = { tool: "wrench", search: "magnifying-glass", read: "file-text", write: "pencil-simple", reasoning: "brain", run: "terminal", fetch: "cloud-arrow-down" };
3958
4768
  function StepList({
3959
4769
  steps = [],
@@ -3965,9 +4775,9 @@ function StepList({
3965
4775
  dense = false,
3966
4776
  className = ""
3967
4777
  }) {
3968
- const [openState, setOpenState] = React26.useState(defaultOpen);
4778
+ const [openState, setOpenState] = React29.useState(defaultOpen);
3969
4779
  const open = openProp == null ? openState : openProp;
3970
- const [expanded, setExpanded] = React26.useState({});
4780
+ const [expanded, setExpanded] = React29.useState({});
3971
4781
  if (!steps.length) return null;
3972
4782
  const running = steps.some((s) => s.status === "running");
3973
4783
  const failed = steps.filter((s) => s.status === "error").length;
@@ -3979,30 +4789,30 @@ function StepList({
3979
4789
  if (openProp == null) setOpenState(next);
3980
4790
  onToggle && onToggle(next);
3981
4791
  };
3982
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: ["fd-steps", dense ? "is-dense" : "", open ? "is-open" : "", className].filter(Boolean).join(" "), children: [
3983
- /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("button", { type: "button", className: "fd-steps-head", onClick: toggle, "aria-expanded": open, children: [
3984
- running ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-steps-spin", "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-" + (failed ? "warning-circle" : "check-circle"), "aria-hidden": "true" }),
3985
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-steps-title", title: truncationTitle(summary), children: summary }),
3986
- /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "fd-steps-count fd-tabular", children: [
4792
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: ["fd-steps", dense ? "is-dense" : "", open ? "is-open" : "", className].filter(Boolean).join(" "), children: [
4793
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("button", { type: "button", className: "fd-steps-head", onClick: toggle, "aria-expanded": open, children: [
4794
+ running ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-steps-spin", "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-" + (failed ? "warning-circle" : "check-circle"), "aria-hidden": "true" }),
4795
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-steps-title", title: truncationTitle(summary), children: summary }),
4796
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-steps-count fd-tabular", children: [
3987
4797
  steps.length,
3988
4798
  " step",
3989
4799
  steps.length === 1 ? "" : "s",
3990
- failed ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "fd-steps-failed", children: [
4800
+ failed ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-steps-failed", children: [
3991
4801
  " \xB7 ",
3992
4802
  failed,
3993
4803
  " failed"
3994
4804
  ] }) : null
3995
4805
  ] }),
3996
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down") + " fd-steps-caret", "aria-hidden": "true" })
4806
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down") + " fd-steps-caret", "aria-hidden": "true" })
3997
4807
  ] }),
3998
- open ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("ol", { className: "fd-steps-list", children: steps.map((s, i) => {
4808
+ open ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("ol", { className: "fd-steps-list", children: steps.map((s, i) => {
3999
4809
  const id = s.id || i;
4000
4810
  const isOpen = !!expanded[id];
4001
4811
  const icon = KIND_ICON[s.kind || ""] || "dot-outline";
4002
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("li", { className: "fd-step is-" + (s.status || "ok"), children: [
4003
- /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-step-row", children: [
4004
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-step-icon", "aria-hidden": "true", children: s.status === "running" ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-steps-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-" + icon }) }),
4005
- s.detail ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
4812
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("li", { className: "fd-step is-" + (s.status || "ok"), children: [
4813
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-step-row", children: [
4814
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-step-icon", "aria-hidden": "true", children: s.status === "running" ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-steps-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-" + icon }) }),
4815
+ s.detail ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
4006
4816
  "button",
4007
4817
  {
4008
4818
  type: "button",
@@ -4010,23 +4820,23 @@ function StepList({
4010
4820
  "aria-expanded": isOpen,
4011
4821
  onClick: () => setExpanded((m) => Object.assign({}, m, { [id]: !isOpen })),
4012
4822
  children: [
4013
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { title: truncationTitle(s.label), children: s.label }),
4014
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-caret-" + (isOpen ? "up" : "down"), "aria-hidden": "true" })
4823
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { title: truncationTitle(s.label), children: s.label }),
4824
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-caret-" + (isOpen ? "up" : "down"), "aria-hidden": "true" })
4015
4825
  ]
4016
4826
  }
4017
- ) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-step-label is-static", title: truncationTitle(s.label), children: s.label }),
4018
- s.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-step-badge is-error", children: "failed" }) : null,
4019
- showDurations && s.durationMs ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-step-dur fd-tabular", children: formatDuration(s.durationMs) }) : null
4827
+ ) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-step-label is-static", title: truncationTitle(s.label), children: s.label }),
4828
+ s.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-step-badge is-error", children: "failed" }) : null,
4829
+ showDurations && s.durationMs ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-step-dur fd-tabular", children: formatDuration(s.durationMs) }) : null
4020
4830
  ] }),
4021
- s.detail && isOpen ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("pre", { className: "fd-step-detail", children: s.detail }) : null
4831
+ s.detail && isOpen ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("pre", { className: "fd-step-detail", children: s.detail }) : null
4022
4832
  ] }, id);
4023
4833
  }) }) : null
4024
4834
  ] });
4025
4835
  }
4026
4836
 
4027
4837
  // src/components/data/VirtualList.tsx
4028
- var React27 = __toESM(require("react"), 1);
4029
- var import_jsx_runtime51 = require("react/jsx-runtime");
4838
+ var React30 = __toESM(require("react"), 1);
4839
+ var import_jsx_runtime55 = require("react/jsx-runtime");
4030
4840
  var VIRTUAL_LIST_BUFFER_ROWS = 20;
4031
4841
  var VIRTUAL_LIST_ROW_GAP = 6;
4032
4842
  function computeVirtualWindow(opts) {
@@ -4077,35 +4887,35 @@ function VirtualList({
4077
4887
  className = "",
4078
4888
  style
4079
4889
  }) {
4080
- const [scrollTop, setScrollTop] = React27.useState(0);
4081
- const loaded = React27.useMemo(
4890
+ const [scrollTop, setScrollTop] = React30.useState(0);
4891
+ const loaded = React30.useMemo(
4082
4892
  () => ({ firstItemIndex, count: items.length }),
4083
4893
  [firstItemIndex, items.length]
4084
4894
  );
4085
4895
  const total = Math.max(totalCount == null ? 0 : totalCount, firstItemIndex + items.length);
4086
4896
  const bandKey = firstItemIndex + ":" + items.length;
4087
- const win = React27.useMemo(
4897
+ const win = React30.useMemo(
4088
4898
  () => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: total, loaded }),
4089
4899
  [scrollTop, height, itemHeight, total, loaded]
4090
4900
  );
4091
- const need = React27.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
4901
+ const need = React30.useMemo(() => computeNeedMore(win, loaded), [win, loaded]);
4092
4902
  const wantStart = need.start && hasMore?.start !== false;
4093
4903
  const wantEnd = need.end && hasMore?.end !== false;
4094
4904
  const bucket2 = Math.floor(win.visibleStart / VIRTUAL_LIST_BUFFER_ROWS);
4095
4905
  const askKey = bandKey + "@" + bucket2;
4096
- const asked = React27.useRef({ start: null, end: null });
4097
- React27.useEffect(() => {
4906
+ const asked = React30.useRef({ start: null, end: null });
4907
+ React30.useEffect(() => {
4098
4908
  if (loading || !wantStart || asked.current.start === askKey) return;
4099
4909
  asked.current.start = askKey;
4100
4910
  onNeedMore("start", win);
4101
4911
  }, [wantStart, loading, askKey, onNeedMore, win]);
4102
- React27.useEffect(() => {
4912
+ React30.useEffect(() => {
4103
4913
  if (loading || !wantEnd || asked.current.end === askKey) return;
4104
4914
  asked.current.end = askKey;
4105
4915
  onNeedMore("end", win);
4106
4916
  }, [wantEnd, loading, askKey, onNeedMore, win]);
4107
- const lastKeysRef = React27.useRef(null);
4108
- const newKeys = React27.useMemo(() => {
4917
+ const lastKeysRef = React30.useRef(null);
4918
+ const newKeys = React30.useMemo(() => {
4109
4919
  const prev = lastKeysRef.current;
4110
4920
  if (!prev) return /* @__PURE__ */ new Set();
4111
4921
  const fresh = /* @__PURE__ */ new Set();
@@ -4115,12 +4925,12 @@ function VirtualList({
4115
4925
  }
4116
4926
  return fresh;
4117
4927
  }, [items]);
4118
- React27.useEffect(() => {
4928
+ React30.useEffect(() => {
4119
4929
  lastKeysRef.current = new Set(items.map(keyOf));
4120
4930
  }, [items]);
4121
4931
  const gapStyle = { "--fd-vlist-gap": rowGap + "px" };
4122
4932
  if (!items.length && !loading && !refreshing && emptyState) {
4123
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: ["fd-vlist-wrap", className].filter(Boolean).join(" "), style: { height, position: "relative", ...style }, children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "fd-vlist fd-scrollbar", style: { height: "100%", overflow: "auto" }, children: emptyState }) });
4933
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: ["fd-vlist-wrap", className].filter(Boolean).join(" "), style: { height, position: "relative", ...style }, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "fd-vlist fd-scrollbar", style: { height: "100%", overflow: "auto" }, children: emptyState }) });
4124
4934
  }
4125
4935
  const rows = [];
4126
4936
  for (let i = win.startIndex; i <= win.endIndex; i++) {
@@ -4128,40 +4938,40 @@ function VirtualList({
4128
4938
  if (item === void 0) continue;
4129
4939
  const key = keyOf(item);
4130
4940
  rows.push(
4131
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
4941
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
4132
4942
  "div",
4133
4943
  {
4134
4944
  className: "fd-vlist-row",
4135
4945
  style: { height: itemHeight, boxSizing: "border-box", transform: "translateY(" + i * itemHeight + "px)" },
4136
- children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: newKeys.has(key) ? "fd-vlist-row-content fd-vlist-row-enter" : "fd-vlist-row-content", children: renderItem(item, i) })
4946
+ children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: newKeys.has(key) ? "fd-vlist-row-content fd-vlist-row-enter" : "fd-vlist-row-content", children: renderItem(item, i) })
4137
4947
  },
4138
4948
  key
4139
4949
  )
4140
4950
  );
4141
4951
  }
4142
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: ["fd-vlist-wrap", className].filter(Boolean).join(" "), style: { height, position: "relative", ...gapStyle, ...style }, children: [
4143
- /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
4952
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: ["fd-vlist-wrap", className].filter(Boolean).join(" "), style: { height, position: "relative", ...gapStyle, ...style }, children: [
4953
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
4144
4954
  "div",
4145
4955
  {
4146
4956
  className: "fd-vlist fd-scrollbar",
4147
4957
  style: { height: "100%", overflowY: "auto", overflowX: "hidden", position: "relative" },
4148
4958
  onScroll: (e) => setScrollTop(e.currentTarget.scrollTop),
4149
4959
  children: [
4150
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { style: { height: win.totalHeight, position: "relative" }, children: rows }),
4151
- loading ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { style: { position: "sticky", bottom: 0, left: 0, right: 0, display: "grid", placeItems: "center", padding: "8px 0", background: "var(--surface)" }, children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-spinner", "aria-hidden": "true" }) }) : null
4960
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { style: { height: win.totalHeight, position: "relative" }, children: rows }),
4961
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { style: { position: "sticky", bottom: 0, left: 0, right: 0, display: "grid", placeItems: "center", padding: "8px 0", background: "var(--surface)" }, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-spinner", "aria-hidden": "true" }) }) : null
4152
4962
  ]
4153
4963
  }
4154
4964
  ),
4155
- refreshing ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "fd-vlist-refresh-scrim", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "fd-vlist-refresh-card", children: [
4156
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-spinner", "aria-hidden": "true" }),
4157
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-body-sm", children: refreshingLabel })
4965
+ refreshing ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "fd-vlist-refresh-scrim", children: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "fd-vlist-refresh-card", children: [
4966
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-spinner", "aria-hidden": "true" }),
4967
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-body-sm", children: refreshingLabel })
4158
4968
  ] }) }) : null
4159
4969
  ] });
4160
4970
  }
4161
4971
 
4162
4972
  // src/components/data/EntityRow.tsx
4163
- var React28 = __toESM(require("react"), 1);
4164
- var import_jsx_runtime52 = require("react/jsx-runtime");
4973
+ var React31 = __toESM(require("react"), 1);
4974
+ var import_jsx_runtime56 = require("react/jsx-runtime");
4165
4975
  var ENTITY_ROW_METRIC_WIDTH = 74;
4166
4976
  var METRIC_TONE_COLOR = {
4167
4977
  default: "var(--text-2)",
@@ -4169,16 +4979,16 @@ var METRIC_TONE_COLOR = {
4169
4979
  danger: "var(--danger-text)"
4170
4980
  };
4171
4981
  function EntityRowMetrics({ metrics, className = "", style }) {
4172
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: ["fd-erow-metrics", className].filter(Boolean).join(" "), style, children: metrics.map((m, i) => {
4982
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: ["fd-erow-metrics", className].filter(Boolean).join(" "), style, children: metrics.map((m, i) => {
4173
4983
  const key = m.id || m.label || i;
4174
4984
  const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
4175
4985
  const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
4176
- const content = /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React28.Fragment, { children: [
4177
- m.icon ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
4178
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
4179
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-sr", children: " " + m.label })
4986
+ const content = /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(React31.Fragment, { children: [
4987
+ m.icon ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
4988
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
4989
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-sr", children: " " + m.label })
4180
4990
  ] });
4181
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-erow-cell", style: { "--erow-metric-w": (m.width || ENTITY_ROW_METRIC_WIDTH) + "px" }, children: m.tooltip == null ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: className2, style: tone, title: m.label, children: content }) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(Tooltip, { label: m.tooltip, children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("button", { type: "button", className: className2, style: tone, children: content }) }) }, key);
4991
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-erow-cell", style: { "--erow-metric-w": (m.width || ENTITY_ROW_METRIC_WIDTH) + "px" }, children: m.tooltip == null ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: className2, style: tone, title: m.label, children: content }) : /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Tooltip, { label: m.tooltip, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("button", { type: "button", className: className2, style: tone, children: content }) }) }, key);
4182
4992
  }) });
4183
4993
  }
4184
4994
  function EntityRow({
@@ -4195,7 +5005,7 @@ function EntityRow({
4195
5005
  className = ""
4196
5006
  }) {
4197
5007
  const hasStrip = metrics && metrics.length > 0 || accessory != null;
4198
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
5008
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
4199
5009
  "div",
4200
5010
  {
4201
5011
  onPointerDown,
@@ -4221,33 +5031,33 @@ function EntityRow({
4221
5031
  // font-size moved to the .fd-erow-grip stylesheet rule, same reason as the
4222
5032
  // row's own padding above: .fd-tlist-footer's indent reads it back as
4223
5033
  // --erow-grip-size.
4224
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("i", { className: "ph ph-dots-six-vertical fd-erow-grip", "aria-hidden": "true", style: { flex: "none", color: "var(--text-muted)" } })
5034
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-dots-six-vertical fd-erow-grip", "aria-hidden": "true", style: { flex: "none", color: "var(--text-muted)" } })
4225
5035
  ) : null,
4226
- /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("span", { className: "fd-erow-body", children: [
4227
- /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("span", { className: "fd-erow-titleline", children: [
4228
- titleIcon ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(Tooltip, { label: titleIcon.tooltip, children: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
5036
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-erow-body", children: [
5037
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-erow-titleline", children: [
5038
+ titleIcon ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Tooltip, { label: titleIcon.tooltip, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
4229
5039
  "button",
4230
5040
  {
4231
5041
  type: "button",
4232
5042
  className: ["fd-erow-title-icon", titleIcon.tone ? "is-" + titleIcon.tone : ""].filter(Boolean).join(" "),
4233
5043
  children: [
4234
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("i", { className: "ph ph-" + titleIcon.icon, "aria-hidden": "true" }),
4235
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-erow-title fd-body-sm", children: title })
5044
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-" + titleIcon.icon, "aria-hidden": "true" }),
5045
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-erow-title fd-body-sm", children: title })
4236
5046
  ]
4237
5047
  }
4238
5048
  ) }) : (
4239
5049
  // MP-141: dense-row identifier, no Tooltip wrapper in this branch — a native
4240
5050
  // `title` is the exposure mechanism, same rule as every other identifier.
4241
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-erow-title fd-body-sm", title: truncationTitle(title), children: title })
5051
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-erow-title fd-body-sm", title: truncationTitle(title), children: title })
4242
5052
  ),
4243
- meta ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-erow-meta", title: truncationTitle(meta), children: meta }) : null
5053
+ meta ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-erow-meta", title: truncationTitle(meta), children: meta }) : null
4244
5054
  ] }),
4245
- hasStrip ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("span", { className: "fd-erow-strip", children: [
4246
- metrics && metrics.length ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(EntityRowMetrics, { metrics }) : null,
4247
- accessory ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-erow-accessory", children: accessory }) : null
5055
+ hasStrip ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-erow-strip", children: [
5056
+ metrics && metrics.length ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(EntityRowMetrics, { metrics }) : null,
5057
+ accessory ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-erow-accessory", children: accessory }) : null
4248
5058
  ] }) : null
4249
5059
  ] }),
4250
- action ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
5060
+ action ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
4251
5061
  IconButton,
4252
5062
  {
4253
5063
  icon: action.icon,
@@ -4265,30 +5075,11 @@ function EntityRow({
4265
5075
  }
4266
5076
 
4267
5077
  // src/components/data/TransferList.tsx
4268
- var React30 = __toESM(require("react"), 1);
5078
+ var React32 = __toESM(require("react"), 1);
4269
5079
  var import_react_dom5 = require("react-dom");
4270
5080
 
4271
- // src/components/forms/field.tsx
4272
- var React29 = __toESM(require("react"), 1);
4273
- var import_jsx_runtime53 = require("react/jsx-runtime");
4274
- function useFieldId(id) {
4275
- const generated = React29.useId();
4276
- return id || generated;
4277
- }
4278
- function FieldLabel({ htmlFor, id, required = false, onClick, children }) {
4279
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("label", { className: "fd-field-label", htmlFor, id, onClick, children: [
4280
- children,
4281
- required ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-field-req", "aria-hidden": "true", children: "*" }) : null
4282
- ] });
4283
- }
4284
- function useTriggerLabelling(label, id) {
4285
- const fieldId = useFieldId(id);
4286
- const labelId = fieldId + "-label";
4287
- return { fieldId, labelId, ariaLabelledBy: label ? labelId + " " + fieldId : void 0 };
4288
- }
4289
-
4290
5081
  // src/components/forms/Input.tsx
4291
- var import_jsx_runtime54 = require("react/jsx-runtime");
5082
+ var import_jsx_runtime57 = require("react/jsx-runtime");
4292
5083
  function Input({
4293
5084
  label,
4294
5085
  help,
@@ -4315,24 +5106,24 @@ function Input({
4315
5106
  disabled ? "fd-input-disabled" : "",
4316
5107
  size === "lg" ? "fd-input-lg" : ""
4317
5108
  ].filter(Boolean).join(" ");
4318
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
4319
- label ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
4320
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: box, children: [
4321
- icon ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-" + icon, "aria-hidden": "true" }) }) : null,
4322
- prefix ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
4323
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("input", { id: fieldId, disabled, style: inputStyle, "aria-invalid": error ? "true" : void 0, ...rest }),
4324
- loading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading" }) : null,
4325
- suffix && !loading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-input-affix", children: suffix }) : null
5109
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
5110
+ label ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
5111
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: box, children: [
5112
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: "ph ph-" + icon, "aria-hidden": "true" }) }) : null,
5113
+ prefix ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
5114
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("input", { id: fieldId, disabled, style: inputStyle, "aria-invalid": error ? "true" : void 0, ...rest }),
5115
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading" }) : null,
5116
+ suffix && !loading ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-input-affix", children: suffix }) : null
4326
5117
  ] }),
4327
- error ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-field-error", children: [
4328
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
5118
+ error ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-field-error", children: [
5119
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
4329
5120
  error
4330
- ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-field-help", children: help }) : null
5121
+ ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-field-help", children: help }) : null
4331
5122
  ] });
4332
5123
  }
4333
5124
 
4334
5125
  // src/components/forms/SearchField.tsx
4335
- var import_jsx_runtime55 = require("react/jsx-runtime");
5126
+ var import_jsx_runtime58 = require("react/jsx-runtime");
4336
5127
  function SearchField({
4337
5128
  value,
4338
5129
  onChange,
@@ -4347,7 +5138,7 @@ function SearchField({
4347
5138
  ...rest
4348
5139
  }) {
4349
5140
  const clear = onClear || (() => onChange(""));
4350
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
5141
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
4351
5142
  Input,
4352
5143
  {
4353
5144
  id,
@@ -4360,14 +5151,14 @@ function SearchField({
4360
5151
  style,
4361
5152
  className,
4362
5153
  onChange: (e) => onChange(e.target.value),
4363
- suffix: value ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
5154
+ suffix: value ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
4364
5155
  "button",
4365
5156
  {
4366
5157
  type: "button",
4367
5158
  "aria-label": "Clear search",
4368
5159
  onClick: clear,
4369
5160
  style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
4370
- children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 }, "aria-hidden": "true" })
5161
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 }, "aria-hidden": "true" })
4371
5162
  }
4372
5163
  ) : void 0,
4373
5164
  ...rest
@@ -4376,7 +5167,7 @@ function SearchField({
4376
5167
  }
4377
5168
 
4378
5169
  // src/components/data/TransferList.tsx
4379
- var import_jsx_runtime56 = require("react/jsx-runtime");
5170
+ var import_jsx_runtime59 = require("react/jsx-runtime");
4380
5171
  var emptyHasMore = {};
4381
5172
  var DRAG_THRESHOLD_PX = 5;
4382
5173
  function TransferList({
@@ -4390,12 +5181,12 @@ function TransferList({
4390
5181
  listHeight = 440,
4391
5182
  className = ""
4392
5183
  }) {
4393
- const [drag, setDrag] = React30.useState(null);
4394
- const [dragOverSide, setDragOverSide] = React30.useState(null);
4395
- const dragRef = React30.useRef(null);
4396
- const armedRef = React30.useRef(null);
4397
- const sideRefs = React30.useRef({ left: null, right: null });
4398
- const hitTestSide = React30.useCallback((x, y) => {
5184
+ const [drag, setDrag] = React32.useState(null);
5185
+ const [dragOverSide, setDragOverSide] = React32.useState(null);
5186
+ const dragRef = React32.useRef(null);
5187
+ const armedRef = React32.useRef(null);
5188
+ const sideRefs = React32.useRef({ left: null, right: null });
5189
+ const hitTestSide = React32.useCallback((x, y) => {
4399
5190
  for (const side of ["left", "right"]) {
4400
5191
  const el = sideRefs.current[side];
4401
5192
  if (!el) continue;
@@ -4404,7 +5195,7 @@ function TransferList({
4404
5195
  }
4405
5196
  return null;
4406
5197
  }, []);
4407
- const findItem = React30.useCallback(
5198
+ const findItem = React32.useCallback(
4408
5199
  (side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
4409
5200
  [left.items, right.items, keyOf]
4410
5201
  );
@@ -4426,7 +5217,7 @@ function TransferList({
4426
5217
  height: rect.height
4427
5218
  };
4428
5219
  };
4429
- React30.useEffect(() => {
5220
+ React32.useEffect(() => {
4430
5221
  const onMovePointer = (e) => {
4431
5222
  const armed = armedRef.current;
4432
5223
  if (!armed || e.pointerId !== armed.pointerId) return;
@@ -4479,7 +5270,7 @@ function TransferList({
4479
5270
  window.removeEventListener("pointercancel", endDrag);
4480
5271
  };
4481
5272
  }, [hitTestSide, findItem, onMove]);
4482
- React30.useEffect(() => {
5273
+ React32.useEffect(() => {
4483
5274
  if (!drag || typeof document === "undefined") return;
4484
5275
  const prev = document.body.style.userSelect;
4485
5276
  document.body.style.userSelect = "none";
@@ -4489,7 +5280,7 @@ function TransferList({
4489
5280
  }, [drag]);
4490
5281
  const renderSide = (side, cfg, opposite) => {
4491
5282
  const showOverlay = drag != null && dragOverSide === side;
4492
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
5283
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
4493
5284
  "div",
4494
5285
  {
4495
5286
  ref: (el) => {
@@ -4497,16 +5288,16 @@ function TransferList({
4497
5288
  },
4498
5289
  className: ["fd-tlist-side", dragOverSide === side ? "is-drop-target" : ""].filter(Boolean).join(" "),
4499
5290
  children: [
4500
- cfg.label ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-overline fd-muted", children: [
5291
+ cfg.label ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-overline fd-muted", children: [
4501
5292
  cfg.label,
4502
5293
  cfg.total != null ? " (" + cfg.total.toLocaleString() + ")" : ""
4503
5294
  ] }) : null,
4504
- cfg.header ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-tlist-header", children: cfg.header }) : null,
4505
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
4506
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(SearchField, { value: cfg.search, onChange: cfg.onSearchChange, placeholder: "Search", "aria-label": (cfg.label || side) + " search", style: { flex: 1 } }),
4507
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(SortMenu, { fields: cfg.sortFields, sort: cfg.sort, onSort: cfg.onSort, align: side === "left" ? "left" : "right" })
5295
+ cfg.header ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "fd-tlist-header", children: cfg.header }) : null,
5296
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
5297
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(SearchField, { value: cfg.search, onChange: cfg.onSearchChange, placeholder: "Search", "aria-label": (cfg.label || side) + " search", style: { flex: 1 } }),
5298
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(SortMenu, { fields: cfg.sortFields, sort: cfg.sort, onSort: cfg.onSort, align: side === "left" ? "left" : "right" })
4508
5299
  ] }),
4509
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
5300
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
4510
5301
  VirtualList,
4511
5302
  {
4512
5303
  items: cfg.items,
@@ -4520,15 +5311,15 @@ function TransferList({
4520
5311
  firstItemIndex: cfg.firstItemIndex,
4521
5312
  totalCount: cfg.totalCount,
4522
5313
  onNeedMore: cfg.onNeedMore,
4523
- emptyState: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(EmptyState, { icon: "tray", title: "Nothing here" }),
5314
+ emptyState: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(EmptyState, { icon: "tray", title: "Nothing here" }),
4524
5315
  renderItem: (item) => {
4525
5316
  const isBeingDragged = drag != null && drag.from === side && drag.key === keyOf(item);
4526
5317
  if (isBeingDragged) {
4527
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-erow-placeholder", "aria-hidden": "true" });
5318
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "fd-erow-placeholder", "aria-hidden": "true" });
4528
5319
  }
4529
5320
  const content = renderRow(item);
4530
5321
  const destination = (side === "left" ? right : left).label || "the other list";
4531
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
5322
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
4532
5323
  EntityRow,
4533
5324
  {
4534
5325
  ...content,
@@ -4548,252 +5339,95 @@ function TransferList({
4548
5339
  }
4549
5340
  }
4550
5341
  ),
4551
- cfg.footer ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-tlist-footer", children: cfg.footer }) : null,
4552
- showOverlay ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-tlist-drop-overlay", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-tlist-drop-card", children: [
4553
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-tray-arrow-down", style: { fontSize: 18 }, "aria-hidden": "true" }),
4554
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: cfg.dropLabel || "Drop here" + (cfg.label ? " \u2014 " + cfg.label : "") })
5342
+ cfg.footer ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "fd-tlist-footer", children: cfg.footer }) : null,
5343
+ showOverlay ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "fd-tlist-drop-overlay", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-tlist-drop-card", children: [
5344
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-tray-arrow-down", style: { fontSize: 18 }, "aria-hidden": "true" }),
5345
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: cfg.dropLabel || "Drop here" + (cfg.label ? " \u2014 " + cfg.label : "") })
4555
5346
  ] }) }) : null
4556
5347
  ]
4557
5348
  }
4558
5349
  );
4559
5350
  };
4560
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: ["fd-tlist", className].filter(Boolean).join(" "), children: [
4561
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-tlist-panes", children: [
5351
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: ["fd-tlist", className].filter(Boolean).join(" "), children: [
5352
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-tlist-panes", children: [
4562
5353
  renderSide("left", left, "right"),
4563
5354
  renderSide("right", right, "left")
4564
5355
  ] }),
4565
5356
  drag ? (0, import_react_dom5.createPortal)(
4566
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
5357
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
4567
5358
  "div",
4568
5359
  {
4569
- "aria-hidden": "true",
4570
- className: "fd-erow-ghost",
4571
- style: {
4572
- position: "fixed",
4573
- left: 0,
4574
- top: 0,
4575
- width: drag.width,
4576
- height: drag.height,
4577
- transform: `translate(${drag.x - drag.offsetX}px, ${drag.y - drag.offsetY}px) rotate(-3deg)`,
4578
- pointerEvents: "none",
4579
- zIndex: OVERLAY_CEILING
4580
- },
4581
- children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(EntityRow, { ...renderRow(drag.item), draggable: true, className: "fd-erow-dragging" })
4582
- }
4583
- ),
4584
- document.body
4585
- ) : null
4586
- ] });
4587
- }
4588
-
4589
- // src/components/forms/Checkbox.tsx
4590
- var React31 = __toESM(require("react"), 1);
4591
- var import_jsx_runtime57 = require("react/jsx-runtime");
4592
- function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
4593
- const ref = React31.useRef(null);
4594
- React31.useEffect(() => {
4595
- if (ref.current) ref.current.indeterminate = indeterminate;
4596
- }, [indeterminate]);
4597
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
4598
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-choice-input", children: [
4599
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("input", { ref, type: "checkbox", ...rest }),
4600
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-choice-box", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: indeterminate ? "ph ph-minus" : "ph ph-check" }) })
4601
- ] }),
4602
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-choice-text", children: [
4603
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-choice-title", children: label }),
4604
- description ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-choice-desc", children: description }) : null
4605
- ] })
4606
- ] });
4607
- }
4608
-
4609
- // src/components/forms/Radio.tsx
4610
- var import_jsx_runtime58 = require("react/jsx-runtime");
4611
- function Radio({ label, description, card = false, className = "", ...rest }) {
4612
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
4613
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-choice-input", children: [
4614
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("input", { type: "radio", ...rest }),
4615
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-choice-dot" }) })
4616
- ] }),
4617
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-choice-text", children: [
4618
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-choice-title", children: label }),
4619
- description ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-choice-desc", children: description }) : null
4620
- ] })
4621
- ] });
4622
- }
4623
-
4624
- // src/components/forms/Switch.tsx
4625
- var import_jsx_runtime59 = require("react/jsx-runtime");
4626
- function Switch({ label, description, className = "", ...rest }) {
4627
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
4628
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("input", { type: "checkbox", role: "switch", ...rest }),
4629
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-switch-track", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-switch-thumb" }) }),
4630
- label ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-choice-text", children: [
4631
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-switch-label", children: label }),
4632
- description ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-choice-desc", children: description }) : null
4633
- ] }) : null
4634
- ] });
4635
- }
4636
-
4637
- // src/components/forms/Textarea.tsx
4638
- var import_jsx_runtime60 = require("react/jsx-runtime");
4639
- function Textarea({ label, help, error, required = false, rows = 4, disabled = false, id, className = "", style, ...rest }) {
4640
- const fieldId = useFieldId(id);
4641
- const box = ["fd-input", "fd-input-textarea", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
4642
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
4643
- label ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
4644
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: box, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("textarea", { id: fieldId, rows, disabled, "aria-invalid": error ? "true" : void 0, ...rest }) }),
4645
- error ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-field-error", children: [
4646
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
4647
- error
4648
- ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-field-help", children: help }) : null
4649
- ] });
4650
- }
4651
-
4652
- // src/components/forms/NumberInput.tsx
4653
- var React32 = __toESM(require("react"), 1);
4654
- var import_jsx_runtime61 = require("react/jsx-runtime");
4655
- function NumberInput({
4656
- label,
4657
- help,
4658
- error,
4659
- prefix,
4660
- suffix,
4661
- required = false,
4662
- disabled = false,
4663
- min = -Infinity,
4664
- max = Infinity,
4665
- step = 1,
4666
- bigStep,
4667
- value,
4668
- onChange,
4669
- format = true,
4670
- className = "",
4671
- style,
4672
- placeholder,
4673
- id,
4674
- "aria-label": ariaLabel
4675
- }) {
4676
- const fieldId = useFieldId(id);
4677
- const num = (v) => {
4678
- const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
4679
- return isNaN(n) ? null : n;
4680
- };
4681
- const [text, setText] = React32.useState(value == null || value === "" ? "" : String(value));
4682
- const [editing, setEditing] = React32.useState(false);
4683
- const timer = React32.useRef(null);
4684
- React32.useEffect(() => {
4685
- if (!editing) setText(value == null || value === "" ? "" : String(value));
4686
- }, [value, editing]);
4687
- const clamp = (n) => Math.min(max, Math.max(min, n));
4688
- const fire = (n) => onChange && onChange({ target: { value: n } });
4689
- const bump = (dir, mult = 1) => {
4690
- const cur = num(text) ?? num(value) ?? (min === -Infinity ? 0 : min);
4691
- const next = clamp(cur + dir * (bigStep && mult > 1 ? bigStep : step) * (bigStep ? 1 : mult));
4692
- setText(String(next));
4693
- fire(next);
4694
- };
4695
- const hold = (dir) => {
4696
- bump(dir);
4697
- let n = 0;
4698
- const tick = () => {
4699
- n++;
4700
- bump(dir, n > 6 ? 4 : 1);
4701
- timer.current = setTimeout(tick, n > 12 ? 40 : n > 6 ? 70 : 120);
4702
- };
4703
- timer.current = setTimeout(tick, 420);
4704
- };
4705
- const release = () => {
4706
- if (timer.current) clearTimeout(timer.current);
4707
- };
4708
- React32.useEffect(() => () => {
4709
- if (timer.current) clearTimeout(timer.current);
4710
- }, []);
4711
- const shown = editing ? text : (() => {
4712
- const n = num(text);
4713
- return n == null ? "" : format ? n.toLocaleString() : String(n);
4714
- })();
4715
- const box = ["fd-input", "fd-input-num", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
4716
- const fieldName = label || ariaLabel;
4717
- const stepperName = (verb) => fieldName ? verb + " " + fieldName : verb;
4718
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
4719
- label ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
4720
- /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: box, style: { gap: 8 }, children: [
4721
- prefix ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
4722
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
4723
- "input",
4724
- {
4725
- id: fieldId,
4726
- "aria-label": ariaLabel,
4727
- inputMode: "numeric",
4728
- disabled,
4729
- placeholder,
4730
- value: shown,
4731
- onFocus: () => setEditing(true),
4732
- onBlur: () => {
4733
- setEditing(false);
4734
- const n = num(text);
4735
- if (n != null) {
4736
- const c = clamp(n);
4737
- setText(String(c));
4738
- fire(c);
4739
- }
4740
- },
4741
- onChange: (e) => {
4742
- setText(e.target.value);
4743
- const n = num(e.target.value);
4744
- if (n != null) fire(n);
5360
+ "aria-hidden": "true",
5361
+ className: "fd-erow-ghost",
5362
+ style: {
5363
+ position: "fixed",
5364
+ left: 0,
5365
+ top: 0,
5366
+ width: drag.width,
5367
+ height: drag.height,
5368
+ transform: `translate(${drag.x - drag.offsetX}px, ${drag.y - drag.offsetY}px) rotate(-3deg)`,
5369
+ pointerEvents: "none",
5370
+ zIndex: OVERLAY_CEILING
4745
5371
  },
4746
- onKeyDown: (e) => {
4747
- if (e.key === "ArrowUp") {
4748
- e.preventDefault();
4749
- bump(1, e.shiftKey ? 2 : 1);
4750
- } else if (e.key === "ArrowDown") {
4751
- e.preventDefault();
4752
- bump(-1, e.shiftKey ? 2 : 1);
4753
- }
4754
- }
5372
+ children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(EntityRow, { ...renderRow(drag.item), draggable: true, className: "fd-erow-dragging" })
4755
5373
  }
4756
5374
  ),
4757
- suffix ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-input-affix", children: suffix }) : null,
4758
- /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-row", style: { gap: 4, flex: "none" }, children: [
4759
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
4760
- "button",
4761
- {
4762
- type: "button",
4763
- className: "fd-stepbtn",
4764
- "aria-label": stepperName("Decrease"),
4765
- disabled: disabled || (num(text) ?? 0) <= min,
4766
- onPointerDown: () => hold(-1),
4767
- onPointerUp: release,
4768
- onPointerLeave: release,
4769
- children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("i", { className: "ph ph-minus" })
4770
- }
4771
- ),
4772
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
4773
- "button",
4774
- {
4775
- type: "button",
4776
- className: "fd-stepbtn",
4777
- "aria-label": stepperName("Increase"),
4778
- disabled: disabled || (num(text) ?? 0) >= max,
4779
- onPointerDown: () => hold(1),
4780
- onPointerUp: release,
4781
- onPointerLeave: release,
4782
- children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("i", { className: "ph ph-plus" })
4783
- }
4784
- )
4785
- ] })
4786
- ] }),
4787
- error ? /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-field-error", children: [
4788
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
4789
- error
4790
- ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-field-help", children: help }) : null
5375
+ document.body
5376
+ ) : null
4791
5377
  ] });
4792
5378
  }
4793
5379
 
4794
- // src/components/forms/Select.tsx
5380
+ // src/components/forms/Checkbox.tsx
4795
5381
  var React33 = __toESM(require("react"), 1);
5382
+ var import_jsx_runtime60 = require("react/jsx-runtime");
5383
+ function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
5384
+ const ref = React33.useRef(null);
5385
+ React33.useEffect(() => {
5386
+ if (ref.current) ref.current.indeterminate = indeterminate;
5387
+ }, [indeterminate]);
5388
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
5389
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-choice-input", children: [
5390
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("input", { ref, type: "checkbox", ...rest }),
5391
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-choice-box", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: indeterminate ? "ph ph-minus" : "ph ph-check" }) })
5392
+ ] }),
5393
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-choice-text", children: [
5394
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-choice-title", children: label }),
5395
+ description ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-choice-desc", children: description }) : null
5396
+ ] })
5397
+ ] });
5398
+ }
5399
+
5400
+ // src/components/forms/Radio.tsx
5401
+ var import_jsx_runtime61 = require("react/jsx-runtime");
5402
+ function Radio({ label, description, card = false, className = "", ...rest }) {
5403
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
5404
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-choice-input", children: [
5405
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("input", { type: "radio", ...rest }),
5406
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-choice-dot" }) })
5407
+ ] }),
5408
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-choice-text", children: [
5409
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-choice-title", children: label }),
5410
+ description ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-choice-desc", children: description }) : null
5411
+ ] })
5412
+ ] });
5413
+ }
5414
+
5415
+ // src/components/forms/Switch.tsx
4796
5416
  var import_jsx_runtime62 = require("react/jsx-runtime");
5417
+ function Switch({ label, description, className = "", ...rest }) {
5418
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
5419
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("input", { type: "checkbox", role: "switch", ...rest }),
5420
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-switch-track", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-switch-thumb" }) }),
5421
+ label ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-choice-text", children: [
5422
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-switch-label", children: label }),
5423
+ description ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-choice-desc", children: description }) : null
5424
+ ] }) : null
5425
+ ] });
5426
+ }
5427
+
5428
+ // src/components/forms/Select.tsx
5429
+ var React34 = __toESM(require("react"), 1);
5430
+ var import_jsx_runtime63 = require("react/jsx-runtime");
4797
5431
  var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
4798
5432
  function Select({
4799
5433
  label,
@@ -4819,13 +5453,13 @@ function Select({
4819
5453
  const isOn = (v) => multiple ? vals.includes(v) : v === value;
4820
5454
  const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
4821
5455
  const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
4822
- const [open, setOpen] = React33.useState(false);
4823
- const [q, setQ] = React33.useState("");
4824
- const [active, setActive] = React33.useState(-1);
4825
- const rootRef = React33.useRef(null);
4826
- const boxRef = React33.useRef(null);
4827
- const listRef = React33.useRef(null);
4828
- const typeBuf = React33.useRef({ s: "", t: 0 });
5456
+ const [open, setOpen] = React34.useState(false);
5457
+ const [q, setQ] = React34.useState("");
5458
+ const [active, setActive] = React34.useState(-1);
5459
+ const rootRef = React34.useRef(null);
5460
+ const boxRef = React34.useRef(null);
5461
+ const listRef = React34.useRef(null);
5462
+ const typeBuf = React34.useRef({ s: "", t: 0 });
4829
5463
  const selected = multiple ? null : opts.find((o) => o.value === value);
4830
5464
  const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
4831
5465
  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;
@@ -4850,7 +5484,7 @@ function Select({
4850
5484
  }
4851
5485
  setOpen(!open);
4852
5486
  };
4853
- React33.useEffect(() => {
5487
+ React34.useEffect(() => {
4854
5488
  if (!open || active < 0 || !listRef.current) return;
4855
5489
  const el = listRef.current.querySelector('[data-i="' + active + '"]');
4856
5490
  if (el) {
@@ -4903,10 +5537,10 @@ function Select({
4903
5537
  else last.items.push({ o, i });
4904
5538
  });
4905
5539
  const box = ["fd-input", "fd-select", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
4906
- return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
4907
- label ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(FieldLabel, { id: labelId, required, onClick: toggle, children: label }) : null,
4908
- /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: box, style: { cursor: disabled ? "not-allowed" : "pointer" }, ref: boxRef, children: [
4909
- /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
5540
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
5541
+ label ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(FieldLabel, { id: labelId, required, onClick: toggle, children: label }) : null,
5542
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: box, style: { cursor: disabled ? "not-allowed" : "pointer" }, ref: boxRef, children: [
5543
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
4910
5544
  "button",
4911
5545
  {
4912
5546
  type: "button",
@@ -4920,13 +5554,13 @@ function Select({
4920
5554
  "aria-labelledby": ariaLabelledBy,
4921
5555
  style: { all: "unset", flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: 8, cursor: "inherit", overflow: "hidden" },
4922
5556
  children: [
4923
- selected && selected.icon ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-" + selected.icon, style: { flex: "none", color: "var(--text-2)" } }) : null,
4924
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { title: truncationTitle(boxText), style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: (multiple ? chosen.length : selected) ? "var(--text)" : "var(--text-muted)" }, children: boxText }),
4925
- multiple && chosen.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mono", style: { flex: "none", fontSize: 11, fontWeight: 700, padding: "1px 6px", borderRadius: 99, background: "var(--brand)", color: "#fff" }, children: chosen.length }) : null
5557
+ selected && selected.icon ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-" + selected.icon, style: { flex: "none", color: "var(--text-2)" } }) : null,
5558
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { title: truncationTitle(boxText), style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: (multiple ? chosen.length : selected) ? "var(--text)" : "var(--text-muted)" }, children: boxText }),
5559
+ multiple && chosen.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-mono", style: { flex: "none", fontSize: 11, fontWeight: 700, padding: "1px 6px", borderRadius: 99, background: "var(--brand)", color: "#fff" }, children: chosen.length }) : null
4926
5560
  ]
4927
5561
  }
4928
5562
  ),
4929
- clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
5563
+ clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
4930
5564
  "button",
4931
5565
  {
4932
5566
  type: "button",
@@ -4936,12 +5570,12 @@ function Select({
4936
5570
  fire(multiple ? [] : "");
4937
5571
  },
4938
5572
  style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
4939
- children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 } })
5573
+ children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 } })
4940
5574
  }
4941
5575
  ) : null,
4942
- loading ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading options" }) : /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-select-caret", onClick: toggle, children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
5576
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading options" }) : /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-select-caret", onClick: toggle, children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
4943
5577
  ] }),
4944
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
5578
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
4945
5579
  Popover,
4946
5580
  {
4947
5581
  open,
@@ -4954,9 +5588,9 @@ function Select({
4954
5588
  minWidth: 260,
4955
5589
  role: "presentation",
4956
5590
  style: { maxWidth: 380 },
4957
- header: hasSearch ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "fd-pop-search", children: [
4958
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-magnifying-glass", style: { color: "var(--text-muted)", fontSize: 14 } }),
4959
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
5591
+ header: hasSearch ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "fd-pop-search", children: [
5592
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-magnifying-glass", style: { color: "var(--text-muted)", fontSize: 14 } }),
5593
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
4960
5594
  "input",
4961
5595
  {
4962
5596
  autoFocus: true,
@@ -4969,10 +5603,10 @@ function Select({
4969
5603
  }
4970
5604
  }
4971
5605
  ),
4972
- q ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
5606
+ q ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
4973
5607
  ] }) : void 0,
4974
- footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(React33.Fragment, { children: [
4975
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
5608
+ footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(React34.Fragment, { children: [
5609
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
4976
5610
  "button",
4977
5611
  {
4978
5612
  type: "button",
@@ -4981,13 +5615,13 @@ function Select({
4981
5615
  children: "Select all"
4982
5616
  }
4983
5617
  ),
4984
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { flex: 1 } }),
4985
- /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
5618
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { style: { flex: 1 } }),
5619
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
4986
5620
  vals.length,
4987
5621
  " of ",
4988
5622
  opts.length
4989
5623
  ] }),
4990
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
5624
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
4991
5625
  "button",
4992
5626
  {
4993
5627
  type: "button",
@@ -4998,13 +5632,13 @@ function Select({
4998
5632
  }
4999
5633
  )
5000
5634
  ] }) : void 0,
5001
- children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "fd-pop-list", role: "listbox", "aria-multiselectable": multiple || void 0, ref: listRef, children: visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "fd-pop-empty", children: [
5635
+ children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "fd-pop-list", role: "listbox", "aria-multiselectable": multiple || void 0, ref: listRef, children: visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "fd-pop-empty", children: [
5002
5636
  'Nothing matches "',
5003
5637
  q,
5004
5638
  '".'
5005
- ] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(React33.Fragment, { children: [
5006
- grp.g ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
5007
- grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
5639
+ ] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(React34.Fragment, { children: [
5640
+ grp.g ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
5641
+ grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
5008
5642
  "button",
5009
5643
  {
5010
5644
  type: "button",
@@ -5016,14 +5650,14 @@ function Select({
5016
5650
  onMouseEnter: () => setActive(i),
5017
5651
  onClick: () => pick(o),
5018
5652
  children: [
5019
- multiple ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { "aria-hidden": "true", style: { flex: "none", display: "grid", placeItems: "center", width: 16, height: 16, borderRadius: 4, border: "1.5px solid " + (isOn(o.value) ? "var(--brand)" : "var(--border-strong, var(--border))"), background: isOn(o.value) ? "var(--brand)" : "var(--surface)", color: "#fff" }, children: isOn(o.value) ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-check", style: { fontSize: 11 } }) : null }) : null,
5020
- o.icon ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-opt-icon", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-" + o.icon }) }) : null,
5021
- /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { style: { flex: 1, minWidth: 0 }, children: [
5022
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-opt-label", children: o.label }),
5023
- o.description ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-opt-desc", children: o.description }) : null
5653
+ multiple ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { "aria-hidden": "true", style: { flex: "none", display: "grid", placeItems: "center", width: 16, height: 16, borderRadius: 4, border: "1.5px solid " + (isOn(o.value) ? "var(--brand)" : "var(--border-strong, var(--border))"), background: isOn(o.value) ? "var(--brand)" : "var(--surface)", color: "#fff" }, children: isOn(o.value) ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-check", style: { fontSize: 11 } }) : null }) : null,
5654
+ o.icon ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-opt-icon", children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-" + o.icon }) }) : null,
5655
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { style: { flex: 1, minWidth: 0 }, children: [
5656
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-opt-label", children: o.label }),
5657
+ o.description ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-opt-desc", children: o.description }) : null
5024
5658
  ] }),
5025
- o.meta ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-opt-meta", children: o.meta }) : null,
5026
- multiple ? null : /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-opt-check", children: o.value === value ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-check" }) : null })
5659
+ o.meta ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-opt-meta", children: o.meta }) : null,
5660
+ multiple ? null : /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-opt-check", children: o.value === value ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-check" }) : null })
5027
5661
  ]
5028
5662
  },
5029
5663
  String(o.value)
@@ -5031,208 +5665,6 @@ function Select({
5031
5665
  ] }, grp.g || "_")) })
5032
5666
  }
5033
5667
  ),
5034
- error ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-field-error", children: [
5035
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
5036
- error
5037
- ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-field-help", children: help }) : null
5038
- ] });
5039
- }
5040
-
5041
- // src/components/forms/DatePicker.tsx
5042
- var React34 = __toESM(require("react"), 1);
5043
- var import_jsx_runtime63 = require("react/jsx-runtime");
5044
- var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
5045
- var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
5046
- var iso = (d) => d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
5047
- var parse = (s) => {
5048
- if (!s) return null;
5049
- const [y, m, d] = s.split("-").map(Number);
5050
- return new Date(y, m - 1, d);
5051
- };
5052
- var fmt = (s) => {
5053
- const d = parse(s);
5054
- return d ? MONTHS[d.getMonth()].slice(0, 3) + " " + d.getDate() + ", " + d.getFullYear() : "";
5055
- };
5056
- function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
5057
- const today = /* @__PURE__ */ new Date();
5058
- const sel = range ? value || {} : { start: value, end: value };
5059
- const anchor = parse(sel.start) || parse(initialMonth) || today;
5060
- const [vy, setVy] = React34.useState(anchor.getFullYear());
5061
- const [vm, setVm] = React34.useState(anchor.getMonth());
5062
- const [mode2, setMode] = React34.useState("days");
5063
- const [hover, setHover] = React34.useState(null);
5064
- const s = parse(sel.start), e = parse(sel.end);
5065
- const hoverEnd = range && s && !e && hover ? parse(hover) : null;
5066
- const inRange = (d) => {
5067
- const lo = s, hi = e || hoverEnd;
5068
- return lo && hi && d > (lo < hi ? lo : hi) && d < (lo < hi ? hi : lo);
5069
- };
5070
- const isEdge = (d) => s && iso(d) === iso(s) || e && iso(d) === iso(e);
5071
- const clickDay = (d) => {
5072
- const v = iso(d);
5073
- if (!range) {
5074
- onPick(v);
5075
- return;
5076
- }
5077
- if (!sel.start || sel.start && sel.end) onPick({ start: v, end: "" });
5078
- else {
5079
- const a = parse(sel.start);
5080
- onPick(d < a ? { start: v, end: sel.start } : { start: sel.start, end: v });
5081
- }
5082
- };
5083
- const nav = (d) => {
5084
- let m = vm + d, y = vy;
5085
- if (m < 0) {
5086
- m = 11;
5087
- y--;
5088
- }
5089
- if (m > 11) {
5090
- m = 0;
5091
- y++;
5092
- }
5093
- setVm(m);
5094
- setVy(y);
5095
- };
5096
- const monthGrid = (y, m) => {
5097
- const startPad = new Date(y, m, 1).getDay();
5098
- const cells = [];
5099
- for (let i = 0; i < 42; i++) cells.push(new Date(y, m, i - startPad + 1));
5100
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "fd-cal-grid", style: { width: months > 1 ? 252 : "auto", flex: "none" }, onMouseLeave: () => setHover(null), children: [
5101
- DOW.map((d) => /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-cal-dow", children: d }, d)),
5102
- cells.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
5103
- "button",
5104
- {
5105
- type: "button",
5106
- className: ["fd-cal-day", d.getMonth() !== m ? "is-out" : "", iso(d) === iso(today) ? "is-today" : "", inRange(d) ? "in-range" : "", isEdge(d) ? "is-edge" : ""].filter(Boolean).join(" "),
5107
- onClick: () => clickDay(d),
5108
- onMouseEnter: () => range && setHover(iso(d)),
5109
- children: d.getDate()
5110
- },
5111
- i
5112
- ))
5113
- ] });
5114
- };
5115
- const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
5116
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, children: [
5117
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "fd-cal-head", children: [
5118
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Previous", onClick: () => mode2 === "years" ? setVy(vy - 12) : mode2 === "months" ? setVy(vy - 1) : nav(-1), children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-caret-left" }) }),
5119
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("button", { type: "button", className: "fd-cal-title", onClick: () => setMode(mode2 === "days" ? "months" : mode2 === "months" ? "years" : "days"), children: [
5120
- mode2 === "days" ? MONTHS[vm] + " " + vy : mode2 === "months" ? vy : vy - 5 + " \u2013 " + (vy + 6),
5121
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-caret-down", style: { fontSize: 10, marginLeft: 6, color: "var(--text-muted)" } })
5122
- ] }),
5123
- months > 1 && mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-cal-title", style: { cursor: "default", background: "none" }, children: MONTHS[nextM] + " " + nextY }) : null,
5124
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Next", onClick: () => mode2 === "years" ? setVy(vy + 12) : mode2 === "months" ? setVy(vy + 1) : nav(1), children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-caret-right" }) })
5125
- ] }),
5126
- mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { style: { display: "flex", gap: 18 }, children: [
5127
- monthGrid(vy, vm),
5128
- months > 1 ? monthGrid(nextY, nextM) : null
5129
- ] }) : mode2 === "months" ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "fd-cal-grid-months", children: MONTHS.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
5130
- "button",
5131
- {
5132
- type: "button",
5133
- className: "fd-cal-cell" + (i === vm && s && s.getFullYear() === vy ? " is-sel" : ""),
5134
- onClick: () => {
5135
- setVm(i);
5136
- setMode("days");
5137
- },
5138
- children: m.slice(0, 3)
5139
- },
5140
- m
5141
- )) }) : /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "fd-cal-grid-months", children: Array.from({ length: 12 }, (_, i) => vy - 5 + i).map((y) => /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
5142
- "button",
5143
- {
5144
- type: "button",
5145
- className: "fd-cal-cell" + (y === vy ? " is-sel" : ""),
5146
- onClick: () => {
5147
- setVy(y);
5148
- setMode("months");
5149
- },
5150
- children: y
5151
- },
5152
- y
5153
- )) }),
5154
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "fd-cal-foot", children: [
5155
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
5156
- "button",
5157
- {
5158
- type: "button",
5159
- className: "fd-btn fd-btn-link",
5160
- style: { fontSize: 12.5 },
5161
- onClick: () => {
5162
- setVy(today.getFullYear());
5163
- setVm(today.getMonth());
5164
- setMode("days");
5165
- },
5166
- children: "Today"
5167
- }
5168
- ),
5169
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { style: { flex: 1 } }),
5170
- range && sel.start ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
5171
- fmt(sel.start),
5172
- sel.end ? " \u2192 " + fmt(sel.end) : " \u2192 pick an end"
5173
- ] }) : null
5174
- ] })
5175
- ] });
5176
- }
5177
- function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, ...rest }) {
5178
- const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
5179
- const [open, setOpen] = React34.useState(false);
5180
- const rootRef = React34.useRef(null);
5181
- const boxRef = React34.useRef(null);
5182
- const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
5183
- const toggle = () => {
5184
- if (!disabled) setOpen(!open);
5185
- };
5186
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
5187
- label ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(FieldLabel, { id: labelId, required, onClick: toggle, children: label }) : null,
5188
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: ["fd-input", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" "), style: { cursor: disabled ? "not-allowed" : "pointer" }, onClick: toggle, ref: boxRef, children: [
5189
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }) }),
5190
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
5191
- "button",
5192
- {
5193
- type: "button",
5194
- id: fieldId,
5195
- "aria-labelledby": ariaLabelledBy,
5196
- title: truncationTitle(display),
5197
- disabled,
5198
- onKeyDown: (e) => {
5199
- if (e.key === "Enter" || e.key === " ") {
5200
- e.preventDefault();
5201
- toggle();
5202
- }
5203
- },
5204
- style: { all: "unset", flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", cursor: "inherit", color: display ? "var(--text)" : "var(--text-muted)" },
5205
- ...rest,
5206
- children: display || placeholder || (range ? "Pick a date range" : "Pick a date")
5207
- }
5208
- ),
5209
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-select-caret", children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
5210
- ] }),
5211
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
5212
- Popover,
5213
- {
5214
- open,
5215
- anchorRef: boxRef,
5216
- triggerRef: rootRef,
5217
- onClose: () => setOpen(false),
5218
- placement: "bottom-start",
5219
- offset: 6,
5220
- role: "presentation",
5221
- style: { width: "max-content" },
5222
- children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
5223
- Calendar,
5224
- {
5225
- range,
5226
- months: range ? 2 : 1,
5227
- value,
5228
- onPick: (v) => {
5229
- onChange && onChange({ target: { value: v } });
5230
- if (!range || v.start && v.end) setOpen(false);
5231
- }
5232
- }
5233
- )
5234
- }
5235
- ),
5236
5668
  error ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "fd-field-error", children: [
5237
5669
  /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
5238
5670
  error