@flytedan/flytebot-design-system 0.10.0 → 0.11.1
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 +665 -658
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +120 -13
- package/dist/index.d.ts +120 -13
- package/dist/index.js +674 -668
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/styles/components.css +165 -16
- package/styles/tokens.css +20 -0
package/dist/index.cjs
CHANGED
|
@@ -106,6 +106,7 @@ __export(index_exports, {
|
|
|
106
106
|
ModeSwitch: () => ModeSwitch,
|
|
107
107
|
ModelControls: () => ModelControls,
|
|
108
108
|
NumberInput: () => NumberInput,
|
|
109
|
+
POPOVER_BODY_MIN: () => POPOVER_BODY_MIN,
|
|
109
110
|
PacketCard: () => PacketCard,
|
|
110
111
|
Pagination: () => Pagination,
|
|
111
112
|
PermissionDenied: () => PermissionDenied,
|
|
@@ -259,6 +260,7 @@ function IconButton({
|
|
|
259
260
|
label,
|
|
260
261
|
size = "md",
|
|
261
262
|
variant = "ghost",
|
|
263
|
+
tone = "neutral",
|
|
262
264
|
round = false,
|
|
263
265
|
disabled = false,
|
|
264
266
|
className = "",
|
|
@@ -266,7 +268,8 @@ function IconButton({
|
|
|
266
268
|
}) {
|
|
267
269
|
const cls = [
|
|
268
270
|
"fd-btn-icon",
|
|
269
|
-
variant === "outline" ? "fd-btn-icon-outline" : "",
|
|
271
|
+
variant === "outline" ? "fd-btn-icon-outline" : variant === "solid" ? "fd-btn-icon-solid" : "",
|
|
272
|
+
tone !== "neutral" ? "is-" + tone : "",
|
|
270
273
|
size === "sm" ? "fd-btn-icon-sm" : size === "lg" ? "fd-btn-icon-lg" : "",
|
|
271
274
|
round ? "fd-btn-icon-round" : "",
|
|
272
275
|
className
|
|
@@ -287,6 +290,23 @@ var samePosition = (a, b) => {
|
|
|
287
290
|
if (!a || !b) return a === b;
|
|
288
291
|
return a.left === b.left && a.top === b.top && a.bottom === b.bottom && a.width === b.width && a.minWidth === b.minWidth && a.maxH === b.maxH && a.side === b.side && a.anchorWidth === b.anchorWidth;
|
|
289
292
|
};
|
|
293
|
+
var SCROLL_REGIONS = ".fd-pop-body, .fd-pop-list";
|
|
294
|
+
var PINNED_REGIONS = ":scope > .fd-pop-header, :scope > .fd-pop-footer";
|
|
295
|
+
var POPOVER_BODY_MIN = 96;
|
|
296
|
+
function measureLayer(el) {
|
|
297
|
+
if (!el || !el.offsetHeight) return { width: el ? el.offsetWidth : 0, height: 0, pinned: 0 };
|
|
298
|
+
let hidden = 0;
|
|
299
|
+
el.querySelectorAll(SCROLL_REGIONS).forEach((r) => {
|
|
300
|
+
hidden += Math.max(0, r.scrollHeight - r.clientHeight);
|
|
301
|
+
});
|
|
302
|
+
let pinned = 0;
|
|
303
|
+
el.querySelectorAll(PINNED_REGIONS).forEach((r) => {
|
|
304
|
+
pinned += r.offsetHeight;
|
|
305
|
+
});
|
|
306
|
+
const border = Math.max(0, el.offsetHeight - el.clientHeight);
|
|
307
|
+
const content = Math.max(el.scrollHeight, el.clientHeight);
|
|
308
|
+
return { width: el.offsetWidth, height: content + border + hidden, pinned: pinned + border };
|
|
309
|
+
}
|
|
290
310
|
function usePopoverPosition(open, anchorRef, opts) {
|
|
291
311
|
const o = opts || {};
|
|
292
312
|
const { side: wantSide, align } = parsePlacement(o.placement);
|
|
@@ -294,6 +314,7 @@ function usePopoverPosition(open, anchorRef, opts) {
|
|
|
294
314
|
const posRef = React.useRef(null);
|
|
295
315
|
const detachRef = React.useRef(o.onDetach);
|
|
296
316
|
detachRef.current = o.onDetach;
|
|
317
|
+
const layerRef = o.layerRef;
|
|
297
318
|
React.useLayoutEffect(() => {
|
|
298
319
|
if (!open || !anchorRef || !anchorRef.current) {
|
|
299
320
|
posRef.current = null;
|
|
@@ -305,23 +326,36 @@ function usePopoverPosition(open, anchorRef, opts) {
|
|
|
305
326
|
if (!el) return;
|
|
306
327
|
const r = el.getBoundingClientRect();
|
|
307
328
|
const offset = o.offset == null ? 8 : o.offset;
|
|
308
|
-
const
|
|
309
|
-
const
|
|
329
|
+
const layer = measureLayer(layerRef ? layerRef.current : null);
|
|
330
|
+
const vh = window.innerHeight;
|
|
331
|
+
const need = layer.height || Math.min(o.estHeight || 300, 180);
|
|
332
|
+
const below = vh - r.bottom - offset - MARGIN;
|
|
310
333
|
const above = r.top - offset - MARGIN;
|
|
311
334
|
let side = wantSide;
|
|
312
|
-
if (side === "bottom" && below <
|
|
313
|
-
else if (side === "top" && above <
|
|
314
|
-
const
|
|
315
|
-
const
|
|
335
|
+
if (side === "bottom" && below < need && above > below) side = "top";
|
|
336
|
+
else if (side === "top" && above < need && below > above) side = "bottom";
|
|
337
|
+
const ceiling = Math.min(vh - 2 * MARGIN, o.maxHeight != null ? o.maxHeight : Infinity);
|
|
338
|
+
const floor = Math.min(
|
|
339
|
+
ceiling,
|
|
340
|
+
layer.height ? layer.pinned + Math.min(POPOVER_BODY_MIN, layer.height - layer.pinned) : Math.min(need, 140)
|
|
341
|
+
);
|
|
342
|
+
const room = side === "top" ? above : below;
|
|
343
|
+
const beside = room >= floor;
|
|
344
|
+
const edge = beside ? 0 : Math.max(MARGIN, vh - MARGIN - Math.min(need, ceiling));
|
|
345
|
+
const top = side === "bottom" ? beside ? r.bottom + offset : edge : null;
|
|
346
|
+
const bottom = side === "top" ? beside ? vh - r.top + offset : edge : null;
|
|
347
|
+
const maxH = beside ? room : vh - MARGIN - edge;
|
|
348
|
+
const exact = o.matchWidth === true;
|
|
349
|
+
const width = exact ? r.width : Math.max(o.width || 0, o.minWidth || 0, o.matchWidth === "min" ? r.width : 0);
|
|
350
|
+
const w = exact || o.width ? width : Math.max(layer.width, width) || o.estWidth || 260;
|
|
316
351
|
let left = align === "end" ? r.right - w : align === "center" ? r.left + r.width / 2 - w / 2 : r.left;
|
|
317
352
|
left = Math.max(MARGIN, Math.min(left, window.innerWidth - w - MARGIN));
|
|
318
|
-
const maxH = Math.max(140, side === "top" ? above : below);
|
|
319
353
|
const next = {
|
|
320
354
|
left,
|
|
321
|
-
width:
|
|
355
|
+
width: exact ? r.width : void 0,
|
|
322
356
|
minWidth: o.minWidth,
|
|
323
|
-
top
|
|
324
|
-
bottom
|
|
357
|
+
top,
|
|
358
|
+
bottom,
|
|
325
359
|
maxH,
|
|
326
360
|
side,
|
|
327
361
|
anchorWidth: r.width
|
|
@@ -344,7 +378,7 @@ function usePopoverPosition(open, anchorRef, opts) {
|
|
|
344
378
|
};
|
|
345
379
|
raf = requestAnimationFrame(tick);
|
|
346
380
|
return () => cancelAnimationFrame(raf);
|
|
347
|
-
}, [open, o.placement, o.offset, o.matchWidth, o.width, o.minWidth, o.estHeight]);
|
|
381
|
+
}, [open, o.placement, o.offset, o.matchWidth, o.width, o.minWidth, o.maxHeight, o.estHeight]);
|
|
348
382
|
return pos;
|
|
349
383
|
}
|
|
350
384
|
var portal = (node) => {
|
|
@@ -354,6 +388,7 @@ var portal = (node) => {
|
|
|
354
388
|
function Popover({
|
|
355
389
|
open,
|
|
356
390
|
anchorRef,
|
|
391
|
+
triggerRef,
|
|
357
392
|
onClose,
|
|
358
393
|
placement = "bottom-start",
|
|
359
394
|
offset = 8,
|
|
@@ -369,6 +404,8 @@ function Popover({
|
|
|
369
404
|
returnFocus = true,
|
|
370
405
|
className = "",
|
|
371
406
|
style,
|
|
407
|
+
header,
|
|
408
|
+
footer,
|
|
372
409
|
children
|
|
373
410
|
}) {
|
|
374
411
|
const ref = React.useRef(null);
|
|
@@ -378,8 +415,10 @@ function Popover({
|
|
|
378
415
|
matchWidth,
|
|
379
416
|
width,
|
|
380
417
|
minWidth,
|
|
418
|
+
maxHeight,
|
|
381
419
|
estHeight: maxHeight || 320,
|
|
382
|
-
onDetach: onClose
|
|
420
|
+
onDetach: onClose,
|
|
421
|
+
layerRef: ref
|
|
383
422
|
});
|
|
384
423
|
const restore = React.useRef(null);
|
|
385
424
|
React.useEffect(() => {
|
|
@@ -400,7 +439,8 @@ function Popover({
|
|
|
400
439
|
if (!closeOnOutside) return;
|
|
401
440
|
const target = e.target;
|
|
402
441
|
if (ref.current && ref.current.contains(target)) return;
|
|
403
|
-
|
|
442
|
+
const trigger = (triggerRef || anchorRef).current;
|
|
443
|
+
if (trigger && trigger.contains(target)) return;
|
|
404
444
|
if (e.target.closest && e.target.closest(".fd-pop")) return;
|
|
405
445
|
onClose && onClose();
|
|
406
446
|
};
|
|
@@ -416,23 +456,23 @@ function Popover({
|
|
|
416
456
|
document.removeEventListener("pointerdown", away, true);
|
|
417
457
|
document.removeEventListener("keydown", key);
|
|
418
458
|
};
|
|
419
|
-
}, [open, closeOnOutside, closeOnEscape, onClose, anchorRef]);
|
|
459
|
+
}, [open, closeOnOutside, closeOnEscape, onClose, anchorRef, triggerRef]);
|
|
420
460
|
if (!open || !pos) return null;
|
|
421
461
|
return portal(
|
|
422
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
462
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
423
463
|
"div",
|
|
424
464
|
{
|
|
425
465
|
ref,
|
|
426
466
|
role,
|
|
427
467
|
"aria-label": label,
|
|
428
|
-
className: ["fd-pop", pos.side === "top" ? "is-up" : "",
|
|
468
|
+
className: ["fd-pop", pos.side === "top" ? "is-up" : "", className].filter(Boolean).join(" "),
|
|
429
469
|
style: {
|
|
430
470
|
position: "fixed",
|
|
431
471
|
left: pos.left,
|
|
432
472
|
top: pos.top == null ? "auto" : pos.top,
|
|
433
473
|
bottom: pos.bottom == null ? "auto" : pos.bottom,
|
|
434
|
-
width: matchWidth ? pos.width : width,
|
|
435
|
-
minWidth: minWidth || (matchWidth ? void 0 : 200),
|
|
474
|
+
width: matchWidth === true ? pos.width : width,
|
|
475
|
+
minWidth: matchWidth === "min" ? Math.max(pos.anchorWidth, minWidth || 0) : minWidth || (matchWidth ? void 0 : 200),
|
|
436
476
|
// Size to content by default — cap only at real available room between the
|
|
437
477
|
// anchor and the viewport edge (pos.maxH, computed by usePopoverPosition).
|
|
438
478
|
// A caller-supplied `maxHeight` narrows that further (e.g. a long menu that
|
|
@@ -445,7 +485,11 @@ function Popover({
|
|
|
445
485
|
zIndex: 140,
|
|
446
486
|
...style
|
|
447
487
|
},
|
|
448
|
-
children
|
|
488
|
+
children: [
|
|
489
|
+
header != null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "fd-pop-header", children: header }) : null,
|
|
490
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: ["fd-pop-body", padded ? "fd-pop-padded" : ""].filter(Boolean).join(" "), children }),
|
|
491
|
+
footer != null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "fd-pop-footer", children: footer }) : null
|
|
492
|
+
]
|
|
449
493
|
}
|
|
450
494
|
)
|
|
451
495
|
);
|
|
@@ -520,77 +564,79 @@ function Menu({ items = [], onSelect, onClose, autoFocus = true, className = "",
|
|
|
520
564
|
};
|
|
521
565
|
const sub = openSub != null ? items[openSub] : null;
|
|
522
566
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(React.Fragment, { children: [
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
{
|
|
541
|
-
type: "button",
|
|
542
|
-
"data-i": i,
|
|
543
|
-
role: it.checked != null ? "menuitemradio" : "menuitem",
|
|
544
|
-
"aria-checked": it.checked != null ? on : void 0,
|
|
545
|
-
"aria-haspopup": it.submenu ? "menu" : void 0,
|
|
546
|
-
"aria-expanded": it.submenu ? openSub === i : void 0,
|
|
547
|
-
"aria-disabled": it.disabled || void 0,
|
|
548
|
-
className: ["fd-opt", "fd-menu-item", i === active ? "is-active" : "", on ? "is-selected" : ""].filter(Boolean).join(" "),
|
|
549
|
-
onMouseEnter: () => {
|
|
550
|
-
setActive(i);
|
|
551
|
-
if (openSub != null && openSub !== i) setOpenSub(null);
|
|
552
|
-
},
|
|
553
|
-
onClick: () => choose(it, i),
|
|
554
|
-
children: [
|
|
555
|
-
it.icon ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fd-menu-icon", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) }) : null,
|
|
556
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "fd-menu-text", children: [
|
|
557
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fd-opt-label", children: it.label }),
|
|
558
|
-
it.description ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fd-opt-desc", children: it.description }) : null
|
|
559
|
-
] }),
|
|
560
|
-
it.meta ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fd-opt-meta", children: it.meta }) : null,
|
|
561
|
-
it.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fd-menu-shortcut", "aria-hidden": "true", children: it.shortcut }) : null,
|
|
562
|
-
it.submenu ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", { className: "ph ph-caret-right fd-menu-more", "aria-hidden": "true" }) : null,
|
|
563
|
-
it.checked != null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fd-opt-check", children: on ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null }) : null
|
|
564
|
-
]
|
|
565
|
-
},
|
|
566
|
-
it.id || it.label || i
|
|
567
|
-
);
|
|
568
|
-
const ta = it.trailingAction;
|
|
569
|
-
if (!ta) return row;
|
|
570
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "fd-menu-row", onMouseEnter: () => setActive(i), children: [
|
|
571
|
-
row,
|
|
572
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
567
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "fd-menu-frame", children: [
|
|
568
|
+
header != null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "fd-menu-header", children: header }) : null,
|
|
569
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
570
|
+
"div",
|
|
571
|
+
{
|
|
572
|
+
ref: listRef,
|
|
573
|
+
tabIndex: -1,
|
|
574
|
+
role: "menu",
|
|
575
|
+
onKeyDown: onKey,
|
|
576
|
+
className: ["fd-pop-list", "fd-menu", className].filter(Boolean).join(" "),
|
|
577
|
+
children: items.map((it, i) => {
|
|
578
|
+
if (!it) return null;
|
|
579
|
+
if (it.kind === "separator") return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "fd-menu-sep", role: "separator" }, "s" + i);
|
|
580
|
+
if (it.kind === "section") return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "fd-pop-group", role: "presentation", children: it.label }, "h" + i);
|
|
581
|
+
if (it.kind === "custom") return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "fd-menu-custom", children: it.render ? it.render() : null }, "c" + i);
|
|
582
|
+
const on = !!it.checked;
|
|
583
|
+
const row = /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
573
584
|
"button",
|
|
574
585
|
{
|
|
575
586
|
type: "button",
|
|
576
|
-
|
|
577
|
-
"
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
587
|
+
"data-i": i,
|
|
588
|
+
role: it.checked != null ? "menuitemradio" : "menuitem",
|
|
589
|
+
"aria-checked": it.checked != null ? on : void 0,
|
|
590
|
+
"aria-haspopup": it.submenu ? "menu" : void 0,
|
|
591
|
+
"aria-expanded": it.submenu ? openSub === i : void 0,
|
|
592
|
+
"aria-disabled": it.disabled || void 0,
|
|
593
|
+
className: ["fd-opt", "fd-menu-item", i === active ? "is-active" : "", on ? "is-selected" : ""].filter(Boolean).join(" "),
|
|
594
|
+
onMouseEnter: () => {
|
|
595
|
+
setActive(i);
|
|
596
|
+
if (openSub != null && openSub !== i) setOpenSub(null);
|
|
585
597
|
},
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
598
|
+
onClick: () => choose(it, i),
|
|
599
|
+
children: [
|
|
600
|
+
it.icon ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fd-menu-icon", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) }) : null,
|
|
601
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "fd-menu-text", children: [
|
|
602
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fd-opt-label", children: it.label }),
|
|
603
|
+
it.description ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fd-opt-desc", children: it.description }) : null
|
|
604
|
+
] }),
|
|
605
|
+
it.meta ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fd-opt-meta", children: it.meta }) : null,
|
|
606
|
+
it.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fd-menu-shortcut", "aria-hidden": "true", children: it.shortcut }) : null,
|
|
607
|
+
it.submenu ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", { className: "ph ph-caret-right fd-menu-more", "aria-hidden": "true" }) : null,
|
|
608
|
+
it.checked != null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "fd-opt-check", children: on ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null }) : null
|
|
609
|
+
]
|
|
610
|
+
},
|
|
611
|
+
it.id || it.label || i
|
|
612
|
+
);
|
|
613
|
+
const ta = it.trailingAction;
|
|
614
|
+
if (!ta) return row;
|
|
615
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "fd-menu-row", onMouseEnter: () => setActive(i), children: [
|
|
616
|
+
row,
|
|
617
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
618
|
+
"button",
|
|
619
|
+
{
|
|
620
|
+
type: "button",
|
|
621
|
+
className: ["fd-menu-row-act", ta.danger ? "is-danger" : ""].filter(Boolean).join(" "),
|
|
622
|
+
"aria-label": ta.label,
|
|
623
|
+
title: ta.label,
|
|
624
|
+
onClick: (e) => {
|
|
625
|
+
e.stopPropagation();
|
|
626
|
+
ta.onSelect && ta.onSelect(it);
|
|
627
|
+
if (ta.closeOnSelect !== false) {
|
|
628
|
+
onClose && onClose();
|
|
629
|
+
}
|
|
630
|
+
},
|
|
631
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", { className: "ph ph-" + (ta.icon || "trash"), "aria-hidden": "true" })
|
|
632
|
+
}
|
|
633
|
+
)
|
|
634
|
+
] }, it.id || it.label || i);
|
|
635
|
+
})
|
|
636
|
+
}
|
|
637
|
+
),
|
|
638
|
+
footer != null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "fd-menu-footer", children: footer }) : null
|
|
639
|
+
] }),
|
|
594
640
|
sub && sub.submenu ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
595
641
|
Popover,
|
|
596
642
|
{
|
|
@@ -1218,20 +1264,123 @@ function Toast({ title, children, tone = "success", onUndo, onDismiss, className
|
|
|
1218
1264
|
// src/components/feedback/Tooltip.tsx
|
|
1219
1265
|
var React6 = __toESM(require("react"), 1);
|
|
1220
1266
|
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1267
|
+
var CLOSE_DELAY_MS = 120;
|
|
1221
1268
|
function Tooltip({ label, placement = "top", children, className = "" }) {
|
|
1222
|
-
const
|
|
1223
|
-
const
|
|
1269
|
+
const anchorRef = React6.useRef(null);
|
|
1270
|
+
const bubbleRef = React6.useRef(null);
|
|
1271
|
+
const [reason, setReason] = React6.useState(null);
|
|
1272
|
+
const closeTimer = React6.useRef(null);
|
|
1273
|
+
const id = React6.useId();
|
|
1274
|
+
const descId = id + "-desc";
|
|
1275
|
+
const open = reason != null;
|
|
1276
|
+
const cancelClose = React6.useCallback(() => {
|
|
1277
|
+
if (closeTimer.current) {
|
|
1278
|
+
clearTimeout(closeTimer.current);
|
|
1279
|
+
closeTimer.current = null;
|
|
1280
|
+
}
|
|
1281
|
+
}, []);
|
|
1282
|
+
const show = (why) => {
|
|
1283
|
+
cancelClose();
|
|
1284
|
+
setReason(why);
|
|
1285
|
+
};
|
|
1286
|
+
const hide = React6.useCallback(() => {
|
|
1287
|
+
cancelClose();
|
|
1288
|
+
setReason(null);
|
|
1289
|
+
}, [cancelClose]);
|
|
1290
|
+
const hover = () => {
|
|
1291
|
+
cancelClose();
|
|
1292
|
+
setReason((r) => r || "hover");
|
|
1293
|
+
};
|
|
1294
|
+
const hideSoon = () => {
|
|
1295
|
+
cancelClose();
|
|
1296
|
+
closeTimer.current = setTimeout(() => {
|
|
1297
|
+
closeTimer.current = null;
|
|
1298
|
+
setReason((r) => r === "hover" ? null : r);
|
|
1299
|
+
}, CLOSE_DELAY_MS);
|
|
1300
|
+
};
|
|
1301
|
+
React6.useEffect(() => cancelClose, [cancelClose]);
|
|
1302
|
+
const pos = usePopoverPosition(open, anchorRef, {
|
|
1303
|
+
placement: placement === "bottom" ? "bottom-center" : "top-center",
|
|
1304
|
+
offset: 8,
|
|
1305
|
+
estHeight: 40,
|
|
1306
|
+
estWidth: 160,
|
|
1307
|
+
layerRef: bubbleRef,
|
|
1308
|
+
onDetach: hide
|
|
1309
|
+
});
|
|
1310
|
+
React6.useEffect(() => {
|
|
1311
|
+
if (!open) return;
|
|
1312
|
+
const key = (e) => {
|
|
1313
|
+
if (e.key === "Escape") hide();
|
|
1314
|
+
};
|
|
1315
|
+
const away = (e) => {
|
|
1316
|
+
const t = e.target;
|
|
1317
|
+
if (anchorRef.current && anchorRef.current.contains(t)) return;
|
|
1318
|
+
if (bubbleRef.current && bubbleRef.current.contains(t)) return;
|
|
1319
|
+
hide();
|
|
1320
|
+
};
|
|
1321
|
+
document.addEventListener("keydown", key);
|
|
1322
|
+
document.addEventListener("pointerdown", away, true);
|
|
1323
|
+
return () => {
|
|
1324
|
+
document.removeEventListener("keydown", key);
|
|
1325
|
+
document.removeEventListener("pointerdown", away, true);
|
|
1326
|
+
};
|
|
1327
|
+
}, [open, hide]);
|
|
1328
|
+
const isMouse = (e) => e.pointerType === "mouse";
|
|
1329
|
+
const onFocus = (e) => {
|
|
1330
|
+
const el = e.target;
|
|
1331
|
+
let keyboard = true;
|
|
1332
|
+
try {
|
|
1333
|
+
keyboard = el.matches(":focus-visible");
|
|
1334
|
+
} catch {
|
|
1335
|
+
}
|
|
1336
|
+
if (keyboard) show("focus");
|
|
1337
|
+
};
|
|
1338
|
+
const described = React6.isValidElement(children) ? React6.cloneElement(children, {
|
|
1339
|
+
"aria-describedby": [children.props["aria-describedby"], descId].filter(Boolean).join(" ")
|
|
1340
|
+
}) : children;
|
|
1224
1341
|
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
1225
1342
|
"span",
|
|
1226
1343
|
{
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1344
|
+
ref: anchorRef,
|
|
1345
|
+
className: "fd-tooltip-anchor",
|
|
1346
|
+
"aria-describedby": React6.isValidElement(children) ? void 0 : descId,
|
|
1347
|
+
onPointerEnter: (e) => {
|
|
1348
|
+
if (isMouse(e)) hover();
|
|
1349
|
+
},
|
|
1350
|
+
onPointerLeave: (e) => {
|
|
1351
|
+
if (isMouse(e)) hideSoon();
|
|
1352
|
+
},
|
|
1353
|
+
onPointerUp: (e) => {
|
|
1354
|
+
if (!isMouse(e)) {
|
|
1355
|
+
if (reason === "tap") hide();
|
|
1356
|
+
else show("tap");
|
|
1357
|
+
}
|
|
1358
|
+
},
|
|
1359
|
+
onFocus,
|
|
1360
|
+
onBlur: () => {
|
|
1361
|
+
if (reason === "focus") hide();
|
|
1362
|
+
},
|
|
1232
1363
|
children: [
|
|
1233
|
-
|
|
1234
|
-
|
|
1364
|
+
described,
|
|
1365
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { id: descId, hidden: true, children: label }),
|
|
1366
|
+
open && pos ? portal(
|
|
1367
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1368
|
+
"span",
|
|
1369
|
+
{
|
|
1370
|
+
ref: bubbleRef,
|
|
1371
|
+
role: "tooltip",
|
|
1372
|
+
className: ["fd-tooltip", pos.side === "bottom" ? "is-below" : "", className].filter(Boolean).join(" "),
|
|
1373
|
+
style: { left: pos.left, top: pos.top == null ? "auto" : pos.top, bottom: pos.bottom == null ? "auto" : pos.bottom },
|
|
1374
|
+
onPointerEnter: (e) => {
|
|
1375
|
+
if (isMouse(e)) cancelClose();
|
|
1376
|
+
},
|
|
1377
|
+
onPointerLeave: (e) => {
|
|
1378
|
+
if (isMouse(e)) hideSoon();
|
|
1379
|
+
},
|
|
1380
|
+
children: label
|
|
1381
|
+
}
|
|
1382
|
+
)
|
|
1383
|
+
) : null
|
|
1235
1384
|
]
|
|
1236
1385
|
}
|
|
1237
1386
|
);
|
|
@@ -2865,6 +3014,7 @@ function VirtualList({
|
|
|
2865
3014
|
}
|
|
2866
3015
|
|
|
2867
3016
|
// src/components/data/EntityRow.tsx
|
|
3017
|
+
var React17 = __toESM(require("react"), 1);
|
|
2868
3018
|
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
2869
3019
|
var ENTITY_ROW_METRIC_WIDTH = 74;
|
|
2870
3020
|
var METRIC_TONE_COLOR = {
|
|
@@ -2873,20 +3023,20 @@ var METRIC_TONE_COLOR = {
|
|
|
2873
3023
|
danger: "var(--danger-text)"
|
|
2874
3024
|
};
|
|
2875
3025
|
function EntityRowMetrics({ metrics, className = "", style }) {
|
|
2876
|
-
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: ["fd-erow-metrics", className].filter(Boolean).join(" "), style, children: metrics.map((m, i) =>
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
children:
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
}
|
|
2888
|
-
|
|
2889
|
-
)
|
|
3026
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: ["fd-erow-metrics", className].filter(Boolean).join(" "), style, children: metrics.map((m, i) => {
|
|
3027
|
+
const key = m.id || m.label || i;
|
|
3028
|
+
const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
|
|
3029
|
+
const cellStyle = { width: (m.width || ENTITY_ROW_METRIC_WIDTH) + "px", color: METRIC_TONE_COLOR[m.tone || "default"] };
|
|
3030
|
+
const content = /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(React17.Fragment, { children: [
|
|
3031
|
+
m.icon ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
|
|
3032
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
|
|
3033
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-sr", children: " " + m.label })
|
|
3034
|
+
] });
|
|
3035
|
+
if (m.tooltip == null) {
|
|
3036
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: className2, style: cellStyle, title: m.label, children: content }, key);
|
|
3037
|
+
}
|
|
3038
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Tooltip, { label: m.tooltip, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("button", { type: "button", className: className2, style: cellStyle, children: content }) }, key);
|
|
3039
|
+
}) });
|
|
2890
3040
|
}
|
|
2891
3041
|
function EntityRow({
|
|
2892
3042
|
title,
|
|
@@ -2936,8 +3086,10 @@ function EntityRow({
|
|
|
2936
3086
|
icon: action.icon,
|
|
2937
3087
|
label: action.label,
|
|
2938
3088
|
size: "sm",
|
|
2939
|
-
|
|
2940
|
-
|
|
3089
|
+
variant: "solid",
|
|
3090
|
+
tone: action.tone === "add" ? "ok" : action.tone === "remove" ? "danger" : "neutral",
|
|
3091
|
+
className: "fd-erow-action",
|
|
3092
|
+
onClick: action.onClick
|
|
2941
3093
|
}
|
|
2942
3094
|
) : null
|
|
2943
3095
|
]
|
|
@@ -2946,14 +3098,14 @@ function EntityRow({
|
|
|
2946
3098
|
}
|
|
2947
3099
|
|
|
2948
3100
|
// src/components/data/TransferList.tsx
|
|
2949
|
-
var
|
|
3101
|
+
var React19 = __toESM(require("react"), 1);
|
|
2950
3102
|
var import_react_dom4 = require("react-dom");
|
|
2951
3103
|
|
|
2952
3104
|
// src/components/forms/field.tsx
|
|
2953
|
-
var
|
|
3105
|
+
var React18 = __toESM(require("react"), 1);
|
|
2954
3106
|
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
2955
3107
|
function useFieldId(id) {
|
|
2956
|
-
const generated =
|
|
3108
|
+
const generated = React18.useId();
|
|
2957
3109
|
return id || generated;
|
|
2958
3110
|
}
|
|
2959
3111
|
function FieldLabel({ htmlFor, id, required = false, onClick, children }) {
|
|
@@ -2994,10 +3146,9 @@ function Input({
|
|
|
2994
3146
|
numeric ? "fd-input-num" : "",
|
|
2995
3147
|
error ? "fd-input-error" : "",
|
|
2996
3148
|
disabled ? "fd-input-disabled" : "",
|
|
2997
|
-
size === "lg" ? "fd-input-lg" : ""
|
|
2998
|
-
className
|
|
3149
|
+
size === "lg" ? "fd-input-lg" : ""
|
|
2999
3150
|
].filter(Boolean).join(" ");
|
|
3000
|
-
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "fd-field", style, children: [
|
|
3151
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
|
|
3001
3152
|
label ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
|
|
3002
3153
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: box, children: [
|
|
3003
3154
|
icon ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("i", { className: "ph ph-" + icon, "aria-hidden": "true" }) }) : null,
|
|
@@ -3072,12 +3223,12 @@ function TransferList({
|
|
|
3072
3223
|
listHeight = 440,
|
|
3073
3224
|
className = ""
|
|
3074
3225
|
}) {
|
|
3075
|
-
const [drag, setDrag] =
|
|
3076
|
-
const [dragOverSide, setDragOverSide] =
|
|
3077
|
-
const dragRef =
|
|
3078
|
-
const armedRef =
|
|
3079
|
-
const sideRefs =
|
|
3080
|
-
const hitTestSide =
|
|
3226
|
+
const [drag, setDrag] = React19.useState(null);
|
|
3227
|
+
const [dragOverSide, setDragOverSide] = React19.useState(null);
|
|
3228
|
+
const dragRef = React19.useRef(null);
|
|
3229
|
+
const armedRef = React19.useRef(null);
|
|
3230
|
+
const sideRefs = React19.useRef({ left: null, right: null });
|
|
3231
|
+
const hitTestSide = React19.useCallback((x, y) => {
|
|
3081
3232
|
for (const side of ["left", "right"]) {
|
|
3082
3233
|
const el = sideRefs.current[side];
|
|
3083
3234
|
if (!el) continue;
|
|
@@ -3086,7 +3237,7 @@ function TransferList({
|
|
|
3086
3237
|
}
|
|
3087
3238
|
return null;
|
|
3088
3239
|
}, []);
|
|
3089
|
-
const findItem =
|
|
3240
|
+
const findItem = React19.useCallback(
|
|
3090
3241
|
(side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
|
|
3091
3242
|
[left.items, right.items, keyOf]
|
|
3092
3243
|
);
|
|
@@ -3108,7 +3259,7 @@ function TransferList({
|
|
|
3108
3259
|
height: rect.height
|
|
3109
3260
|
};
|
|
3110
3261
|
};
|
|
3111
|
-
|
|
3262
|
+
React19.useEffect(() => {
|
|
3112
3263
|
const onMovePointer = (e) => {
|
|
3113
3264
|
const armed = armedRef.current;
|
|
3114
3265
|
if (!armed || e.pointerId !== armed.pointerId) return;
|
|
@@ -3161,7 +3312,7 @@ function TransferList({
|
|
|
3161
3312
|
window.removeEventListener("pointercancel", endDrag);
|
|
3162
3313
|
};
|
|
3163
3314
|
}, [hitTestSide, findItem, onMove]);
|
|
3164
|
-
|
|
3315
|
+
React19.useEffect(() => {
|
|
3165
3316
|
if (!drag || typeof document === "undefined") return;
|
|
3166
3317
|
const prev = document.body.style.userSelect;
|
|
3167
3318
|
document.body.style.userSelect = "none";
|
|
@@ -3273,11 +3424,11 @@ function TransferList({
|
|
|
3273
3424
|
}
|
|
3274
3425
|
|
|
3275
3426
|
// src/components/forms/Checkbox.tsx
|
|
3276
|
-
var
|
|
3427
|
+
var React20 = __toESM(require("react"), 1);
|
|
3277
3428
|
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
3278
3429
|
function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
|
|
3279
|
-
const ref =
|
|
3280
|
-
|
|
3430
|
+
const ref = React20.useRef(null);
|
|
3431
|
+
React20.useEffect(() => {
|
|
3281
3432
|
if (ref.current) ref.current.indeterminate = indeterminate;
|
|
3282
3433
|
}, [indeterminate]);
|
|
3283
3434
|
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
@@ -3324,8 +3475,8 @@ function Switch({ label, description, className = "", ...rest }) {
|
|
|
3324
3475
|
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
3325
3476
|
function Textarea({ label, help, error, required = false, rows = 4, disabled = false, id, className = "", style, ...rest }) {
|
|
3326
3477
|
const fieldId = useFieldId(id);
|
|
3327
|
-
const box = ["fd-input", "fd-input-textarea", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""
|
|
3328
|
-
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fd-field", style, children: [
|
|
3478
|
+
const box = ["fd-input", "fd-input-textarea", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
3479
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
|
|
3329
3480
|
label ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
|
|
3330
3481
|
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: box, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("textarea", { id: fieldId, rows, disabled, "aria-invalid": error ? "true" : void 0, ...rest }) }),
|
|
3331
3482
|
error ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "fd-field-error", children: [
|
|
@@ -3336,7 +3487,7 @@ function Textarea({ label, help, error, required = false, rows = 4, disabled = f
|
|
|
3336
3487
|
}
|
|
3337
3488
|
|
|
3338
3489
|
// src/components/forms/NumberInput.tsx
|
|
3339
|
-
var
|
|
3490
|
+
var React21 = __toESM(require("react"), 1);
|
|
3340
3491
|
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
3341
3492
|
function NumberInput({
|
|
3342
3493
|
label,
|
|
@@ -3364,10 +3515,10 @@ function NumberInput({
|
|
|
3364
3515
|
const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
|
|
3365
3516
|
return isNaN(n) ? null : n;
|
|
3366
3517
|
};
|
|
3367
|
-
const [text, setText] =
|
|
3368
|
-
const [editing, setEditing] =
|
|
3369
|
-
const timer =
|
|
3370
|
-
|
|
3518
|
+
const [text, setText] = React21.useState(value == null || value === "" ? "" : String(value));
|
|
3519
|
+
const [editing, setEditing] = React21.useState(false);
|
|
3520
|
+
const timer = React21.useRef(null);
|
|
3521
|
+
React21.useEffect(() => {
|
|
3371
3522
|
if (!editing) setText(value == null || value === "" ? "" : String(value));
|
|
3372
3523
|
}, [value, editing]);
|
|
3373
3524
|
const clamp = (n) => Math.min(max, Math.max(min, n));
|
|
@@ -3391,7 +3542,7 @@ function NumberInput({
|
|
|
3391
3542
|
const release = () => {
|
|
3392
3543
|
if (timer.current) clearTimeout(timer.current);
|
|
3393
3544
|
};
|
|
3394
|
-
|
|
3545
|
+
React21.useEffect(() => () => {
|
|
3395
3546
|
if (timer.current) clearTimeout(timer.current);
|
|
3396
3547
|
}, []);
|
|
3397
3548
|
const shown = editing ? text : (() => {
|
|
@@ -3478,52 +3629,9 @@ function NumberInput({
|
|
|
3478
3629
|
}
|
|
3479
3630
|
|
|
3480
3631
|
// src/components/forms/Select.tsx
|
|
3481
|
-
var
|
|
3482
|
-
var import_react_dom5 = require("react-dom");
|
|
3632
|
+
var React22 = __toESM(require("react"), 1);
|
|
3483
3633
|
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
3484
3634
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
3485
|
-
function usePopPos(open, ref, estH, estW) {
|
|
3486
|
-
const [pos, setPos] = React21.useState(null);
|
|
3487
|
-
React21.useLayoutEffect(() => {
|
|
3488
|
-
if (!open || !ref.current) {
|
|
3489
|
-
setPos(null);
|
|
3490
|
-
return;
|
|
3491
|
-
}
|
|
3492
|
-
const calc = () => {
|
|
3493
|
-
const r = ref.current.getBoundingClientRect();
|
|
3494
|
-
const below = window.innerHeight - r.bottom;
|
|
3495
|
-
const up = below < estH && r.top > below;
|
|
3496
|
-
const w = Math.max(r.width, estW || 0);
|
|
3497
|
-
const maxH = Math.min(window.innerHeight - 16, Math.max(160, (up ? r.top : below) - 14));
|
|
3498
|
-
setPos({
|
|
3499
|
-
left: Math.max(8, Math.min(r.left, window.innerWidth - w - 8)),
|
|
3500
|
-
width: r.width,
|
|
3501
|
-
top: up ? null : r.bottom + 6,
|
|
3502
|
-
bottom: up ? window.innerHeight - r.top + 6 : null,
|
|
3503
|
-
up,
|
|
3504
|
-
maxH
|
|
3505
|
-
});
|
|
3506
|
-
};
|
|
3507
|
-
calc();
|
|
3508
|
-
window.addEventListener("scroll", calc, true);
|
|
3509
|
-
window.addEventListener("resize", calc);
|
|
3510
|
-
return () => {
|
|
3511
|
-
window.removeEventListener("scroll", calc, true);
|
|
3512
|
-
window.removeEventListener("resize", calc);
|
|
3513
|
-
};
|
|
3514
|
-
}, [open]);
|
|
3515
|
-
return pos;
|
|
3516
|
-
}
|
|
3517
|
-
var popStyle = (pos, extra) => ({
|
|
3518
|
-
position: "fixed",
|
|
3519
|
-
left: pos.left,
|
|
3520
|
-
top: pos.top == null ? "auto" : pos.top,
|
|
3521
|
-
bottom: pos.bottom == null ? "auto" : pos.bottom,
|
|
3522
|
-
transformOrigin: pos.up ? "bottom center" : "top center",
|
|
3523
|
-
maxHeight: pos.maxH,
|
|
3524
|
-
overflowY: "auto",
|
|
3525
|
-
...extra
|
|
3526
|
-
});
|
|
3527
3635
|
function Select({
|
|
3528
3636
|
label,
|
|
3529
3637
|
help,
|
|
@@ -3548,17 +3656,15 @@ function Select({
|
|
|
3548
3656
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
3549
3657
|
const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
|
|
3550
3658
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
3551
|
-
const [open, setOpen] =
|
|
3552
|
-
const [q, setQ] =
|
|
3553
|
-
const [active, setActive] =
|
|
3554
|
-
const rootRef =
|
|
3555
|
-
const boxRef =
|
|
3556
|
-
const
|
|
3557
|
-
const
|
|
3558
|
-
const typeBuf = React21.useRef({ s: "", t: 0 });
|
|
3659
|
+
const [open, setOpen] = React22.useState(false);
|
|
3660
|
+
const [q, setQ] = React22.useState("");
|
|
3661
|
+
const [active, setActive] = React22.useState(-1);
|
|
3662
|
+
const rootRef = React22.useRef(null);
|
|
3663
|
+
const boxRef = React22.useRef(null);
|
|
3664
|
+
const listRef = React22.useRef(null);
|
|
3665
|
+
const typeBuf = React22.useRef({ s: "", t: 0 });
|
|
3559
3666
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
3560
3667
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
3561
|
-
const pos = usePopPos(open, boxRef, hasSearch ? 390 : 340, 260);
|
|
3562
3668
|
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;
|
|
3563
3669
|
const visible = q ? opts.filter((o) => (o.label + " " + (o.description || "") + " " + (o.group || "")).toLowerCase().includes(q.toLowerCase())) : opts;
|
|
3564
3670
|
const fire = (v) => {
|
|
@@ -3581,17 +3687,7 @@ function Select({
|
|
|
3581
3687
|
}
|
|
3582
3688
|
setOpen(!open);
|
|
3583
3689
|
};
|
|
3584
|
-
|
|
3585
|
-
if (!open) return;
|
|
3586
|
-
const away = (e) => {
|
|
3587
|
-
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
3588
|
-
if (popRef.current && popRef.current.contains(e.target)) return;
|
|
3589
|
-
setOpen(false);
|
|
3590
|
-
};
|
|
3591
|
-
document.addEventListener("pointerdown", away);
|
|
3592
|
-
return () => document.removeEventListener("pointerdown", away);
|
|
3593
|
-
}, [open]);
|
|
3594
|
-
React21.useEffect(() => {
|
|
3690
|
+
React22.useEffect(() => {
|
|
3595
3691
|
if (!open || active < 0 || !listRef.current) return;
|
|
3596
3692
|
const el = listRef.current.querySelector('[data-i="' + active + '"]');
|
|
3597
3693
|
if (el) {
|
|
@@ -3682,94 +3778,96 @@ function Select({
|
|
|
3682
3778
|
) : null,
|
|
3683
3779
|
loading ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading options" }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-select-caret", onClick: toggle, children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
|
|
3684
3780
|
] }),
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
)
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
]
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
}
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3781
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3782
|
+
Popover,
|
|
3783
|
+
{
|
|
3784
|
+
open,
|
|
3785
|
+
anchorRef: boxRef,
|
|
3786
|
+
triggerRef: rootRef,
|
|
3787
|
+
onClose: () => setOpen(false),
|
|
3788
|
+
placement: "bottom-start",
|
|
3789
|
+
offset: 6,
|
|
3790
|
+
matchWidth: "min",
|
|
3791
|
+
minWidth: 260,
|
|
3792
|
+
role: "presentation",
|
|
3793
|
+
style: { maxWidth: 380, zIndex: 130 },
|
|
3794
|
+
header: hasSearch ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-pop-search", children: [
|
|
3795
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-magnifying-glass", style: { color: "var(--text-muted)", fontSize: 14 } }),
|
|
3796
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3797
|
+
"input",
|
|
3798
|
+
{
|
|
3799
|
+
autoFocus: true,
|
|
3800
|
+
placeholder: "Search\u2026",
|
|
3801
|
+
value: q,
|
|
3802
|
+
onKeyDown: onKey,
|
|
3803
|
+
onChange: (e) => {
|
|
3804
|
+
setQ(e.target.value);
|
|
3805
|
+
setActive(0);
|
|
3806
|
+
}
|
|
3807
|
+
}
|
|
3808
|
+
),
|
|
3809
|
+
q ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
3810
|
+
] }) : void 0,
|
|
3811
|
+
footer: multiple ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(React22.Fragment, { children: [
|
|
3812
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3813
|
+
"button",
|
|
3814
|
+
{
|
|
3815
|
+
type: "button",
|
|
3816
|
+
onClick: () => fire(visible.filter((o) => !o.disabled).map((o) => o.value)),
|
|
3817
|
+
style: { all: "unset", cursor: "pointer", fontSize: "var(--body-sm-size)", fontWeight: 600, color: "var(--brand)" },
|
|
3818
|
+
children: "Select all"
|
|
3819
|
+
}
|
|
3820
|
+
),
|
|
3821
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { style: { flex: 1 } }),
|
|
3822
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
3823
|
+
vals.length,
|
|
3824
|
+
" of ",
|
|
3825
|
+
opts.length
|
|
3826
|
+
] }),
|
|
3827
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3828
|
+
"button",
|
|
3829
|
+
{
|
|
3830
|
+
type: "button",
|
|
3831
|
+
disabled: !vals.length,
|
|
3832
|
+
onClick: () => fire([]),
|
|
3833
|
+
style: { all: "unset", cursor: vals.length ? "pointer" : "default", fontSize: "var(--body-sm-size)", fontWeight: 600, color: vals.length ? "var(--text-2)" : "var(--text-muted)" },
|
|
3834
|
+
children: "Clear"
|
|
3835
|
+
}
|
|
3836
|
+
)
|
|
3837
|
+
] }) : void 0,
|
|
3838
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "fd-pop-list", role: "listbox", "aria-multiselectable": multiple || void 0, ref: listRef, children: visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-pop-empty", children: [
|
|
3839
|
+
'Nothing matches "',
|
|
3840
|
+
q,
|
|
3841
|
+
'".'
|
|
3842
|
+
] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(React22.Fragment, { children: [
|
|
3843
|
+
grp.g ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
|
|
3844
|
+
grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
3845
|
+
"button",
|
|
3846
|
+
{
|
|
3847
|
+
type: "button",
|
|
3848
|
+
"data-i": i,
|
|
3849
|
+
role: "option",
|
|
3850
|
+
"aria-selected": isOn(o.value),
|
|
3851
|
+
"aria-disabled": o.disabled || void 0,
|
|
3852
|
+
className: ["fd-opt", i === active ? "is-active" : "", isOn(o.value) ? "is-selected" : ""].filter(Boolean).join(" "),
|
|
3853
|
+
onMouseEnter: () => setActive(i),
|
|
3854
|
+
onClick: () => pick(o),
|
|
3855
|
+
children: [
|
|
3856
|
+
multiple ? /* @__PURE__ */ (0, import_jsx_runtime50.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_runtime50.jsx)("i", { className: "ph ph-check", style: { fontSize: 11 } }) : null }) : null,
|
|
3857
|
+
o.icon ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-opt-icon", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-" + o.icon }) }) : null,
|
|
3858
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { style: { flex: 1, minWidth: 0 }, children: [
|
|
3859
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-opt-label", children: o.label }),
|
|
3860
|
+
o.description ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-opt-desc", children: o.description }) : null
|
|
3861
|
+
] }),
|
|
3862
|
+
o.meta ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-opt-meta", children: o.meta }) : null,
|
|
3863
|
+
multiple ? null : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-opt-check", children: o.value === value ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-check" }) : null })
|
|
3864
|
+
]
|
|
3865
|
+
},
|
|
3866
|
+
String(o.value)
|
|
3867
|
+
))
|
|
3868
|
+
] }, grp.g || "_")) })
|
|
3869
|
+
}
|
|
3870
|
+
),
|
|
3773
3871
|
error ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "fd-field-error", children: [
|
|
3774
3872
|
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3775
3873
|
error
|
|
@@ -3778,8 +3876,7 @@ function Select({
|
|
|
3778
3876
|
}
|
|
3779
3877
|
|
|
3780
3878
|
// src/components/forms/DatePicker.tsx
|
|
3781
|
-
var
|
|
3782
|
-
var import_react_dom6 = require("react-dom");
|
|
3879
|
+
var React23 = __toESM(require("react"), 1);
|
|
3783
3880
|
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
3784
3881
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
3785
3882
|
var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
@@ -3793,56 +3890,14 @@ var fmt = (s) => {
|
|
|
3793
3890
|
const d = parse(s);
|
|
3794
3891
|
return d ? MONTHS[d.getMonth()].slice(0, 3) + " " + d.getDate() + ", " + d.getFullYear() : "";
|
|
3795
3892
|
};
|
|
3796
|
-
function usePopPos2(open, ref, estH, estW) {
|
|
3797
|
-
const [pos, setPos] = React22.useState(null);
|
|
3798
|
-
React22.useLayoutEffect(() => {
|
|
3799
|
-
if (!open || !ref.current) {
|
|
3800
|
-
setPos(null);
|
|
3801
|
-
return;
|
|
3802
|
-
}
|
|
3803
|
-
const calc = () => {
|
|
3804
|
-
const r = ref.current.getBoundingClientRect();
|
|
3805
|
-
const below = window.innerHeight - r.bottom;
|
|
3806
|
-
const up = below < estH && r.top > below;
|
|
3807
|
-
const w = Math.max(r.width, estW || 0);
|
|
3808
|
-
const maxH = Math.min(window.innerHeight - 16, Math.max(160, (up ? r.top : below) - 14));
|
|
3809
|
-
setPos({
|
|
3810
|
-
left: Math.max(8, Math.min(r.left, window.innerWidth - w - 8)),
|
|
3811
|
-
width: r.width,
|
|
3812
|
-
top: up ? null : r.bottom + 6,
|
|
3813
|
-
bottom: up ? window.innerHeight - r.top + 6 : null,
|
|
3814
|
-
up,
|
|
3815
|
-
maxH
|
|
3816
|
-
});
|
|
3817
|
-
};
|
|
3818
|
-
calc();
|
|
3819
|
-
window.addEventListener("scroll", calc, true);
|
|
3820
|
-
window.addEventListener("resize", calc);
|
|
3821
|
-
return () => {
|
|
3822
|
-
window.removeEventListener("scroll", calc, true);
|
|
3823
|
-
window.removeEventListener("resize", calc);
|
|
3824
|
-
};
|
|
3825
|
-
}, [open]);
|
|
3826
|
-
return pos;
|
|
3827
|
-
}
|
|
3828
|
-
var popStyle2 = (pos, extra) => ({
|
|
3829
|
-
position: "fixed",
|
|
3830
|
-
left: pos.left,
|
|
3831
|
-
top: pos.top == null ? "auto" : pos.top,
|
|
3832
|
-
bottom: pos.bottom == null ? "auto" : pos.bottom,
|
|
3833
|
-
transformOrigin: pos.up ? "bottom center" : "top center",
|
|
3834
|
-
maxHeight: pos.maxH,
|
|
3835
|
-
overflowY: "auto",
|
|
3836
|
-
...extra
|
|
3837
|
-
});
|
|
3838
3893
|
function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
3839
3894
|
const today = /* @__PURE__ */ new Date();
|
|
3840
3895
|
const sel = range ? value || {} : { start: value, end: value };
|
|
3841
3896
|
const anchor = parse(sel.start) || parse(initialMonth) || today;
|
|
3842
|
-
const [vy, setVy] =
|
|
3843
|
-
const [vm, setVm] =
|
|
3844
|
-
const [mode2, setMode] =
|
|
3845
|
-
const [hover, setHover] =
|
|
3897
|
+
const [vy, setVy] = React23.useState(anchor.getFullYear());
|
|
3898
|
+
const [vm, setVm] = React23.useState(anchor.getMonth());
|
|
3899
|
+
const [mode2, setMode] = React23.useState("days");
|
|
3900
|
+
const [hover, setHover] = React23.useState(null);
|
|
3846
3901
|
const s = parse(sel.start), e = parse(sel.end);
|
|
3847
3902
|
const hoverEnd = range && s && !e && hover ? parse(hover) : null;
|
|
3848
3903
|
const inRange = (d) => {
|
|
@@ -3958,28 +4013,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3958
4013
|
}
|
|
3959
4014
|
function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, ...rest }) {
|
|
3960
4015
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
3961
|
-
const [open, setOpen] =
|
|
3962
|
-
const rootRef =
|
|
3963
|
-
const boxRef =
|
|
3964
|
-
const popRef = React22.useRef(null);
|
|
3965
|
-
const pos = usePopPos2(open, boxRef, 430, range ? 600 : 316);
|
|
3966
|
-
React22.useEffect(() => {
|
|
3967
|
-
if (!open) return;
|
|
3968
|
-
const away = (e) => {
|
|
3969
|
-
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
3970
|
-
if (popRef.current && popRef.current.contains(e.target)) return;
|
|
3971
|
-
setOpen(false);
|
|
3972
|
-
};
|
|
3973
|
-
const esc = (e) => {
|
|
3974
|
-
if (e.key === "Escape") setOpen(false);
|
|
3975
|
-
};
|
|
3976
|
-
document.addEventListener("pointerdown", away);
|
|
3977
|
-
document.addEventListener("keydown", esc);
|
|
3978
|
-
return () => {
|
|
3979
|
-
document.removeEventListener("pointerdown", away);
|
|
3980
|
-
document.removeEventListener("keydown", esc);
|
|
3981
|
-
};
|
|
3982
|
-
}, [open]);
|
|
4016
|
+
const [open, setOpen] = React23.useState(false);
|
|
4017
|
+
const rootRef = React23.useRef(null);
|
|
4018
|
+
const boxRef = React23.useRef(null);
|
|
3983
4019
|
const display = range ? value && value.start ? fmt(value.start) + (value.end ? " \u2192 " + fmt(value.end) : " \u2192 \u2026") : "" : fmt(value);
|
|
3984
4020
|
const toggle = () => {
|
|
3985
4021
|
if (!disabled) setOpen(!open);
|
|
@@ -4008,21 +4044,31 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
4008
4044
|
),
|
|
4009
4045
|
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-select-caret", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
|
|
4010
4046
|
] }),
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4047
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
4048
|
+
Popover,
|
|
4049
|
+
{
|
|
4050
|
+
open,
|
|
4051
|
+
anchorRef: boxRef,
|
|
4052
|
+
triggerRef: rootRef,
|
|
4053
|
+
onClose: () => setOpen(false),
|
|
4054
|
+
placement: "bottom-start",
|
|
4055
|
+
offset: 6,
|
|
4056
|
+
role: "presentation",
|
|
4057
|
+
style: { width: "max-content", zIndex: 130 },
|
|
4058
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
4059
|
+
Calendar,
|
|
4060
|
+
{
|
|
4061
|
+
range,
|
|
4062
|
+
months: range ? 2 : 1,
|
|
4063
|
+
value,
|
|
4064
|
+
onPick: (v) => {
|
|
4065
|
+
onChange && onChange({ target: { value: v } });
|
|
4066
|
+
if (!range || v.start && v.end) setOpen(false);
|
|
4067
|
+
}
|
|
4021
4068
|
}
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
) : null,
|
|
4069
|
+
)
|
|
4070
|
+
}
|
|
4071
|
+
),
|
|
4026
4072
|
error ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("span", { className: "fd-field-error", children: [
|
|
4027
4073
|
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
4028
4074
|
error
|
|
@@ -4031,61 +4077,18 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
4031
4077
|
}
|
|
4032
4078
|
|
|
4033
4079
|
// src/components/forms/TimePicker.tsx
|
|
4034
|
-
var
|
|
4035
|
-
var import_react_dom7 = require("react-dom");
|
|
4080
|
+
var React24 = __toESM(require("react"), 1);
|
|
4036
4081
|
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
4037
4082
|
var pad = (n) => String(n).padStart(2, "0");
|
|
4038
|
-
function usePopPos3(open, ref, estH, estW) {
|
|
4039
|
-
const [pos, setPos] = React23.useState(null);
|
|
4040
|
-
React23.useLayoutEffect(() => {
|
|
4041
|
-
if (!open || !ref.current) {
|
|
4042
|
-
setPos(null);
|
|
4043
|
-
return;
|
|
4044
|
-
}
|
|
4045
|
-
const calc = () => {
|
|
4046
|
-
const r = ref.current.getBoundingClientRect();
|
|
4047
|
-
const below = window.innerHeight - r.bottom;
|
|
4048
|
-
const up = below < estH && r.top > below;
|
|
4049
|
-
const w = Math.max(r.width, estW || 0);
|
|
4050
|
-
const maxH = Math.min(window.innerHeight - 16, Math.max(160, (up ? r.top : below) - 14));
|
|
4051
|
-
setPos({
|
|
4052
|
-
left: Math.max(8, Math.min(r.left, window.innerWidth - w - 8)),
|
|
4053
|
-
width: r.width,
|
|
4054
|
-
top: up ? null : r.bottom + 6,
|
|
4055
|
-
bottom: up ? window.innerHeight - r.top + 6 : null,
|
|
4056
|
-
up,
|
|
4057
|
-
maxH
|
|
4058
|
-
});
|
|
4059
|
-
};
|
|
4060
|
-
calc();
|
|
4061
|
-
window.addEventListener("scroll", calc, true);
|
|
4062
|
-
window.addEventListener("resize", calc);
|
|
4063
|
-
return () => {
|
|
4064
|
-
window.removeEventListener("scroll", calc, true);
|
|
4065
|
-
window.removeEventListener("resize", calc);
|
|
4066
|
-
};
|
|
4067
|
-
}, [open]);
|
|
4068
|
-
return pos;
|
|
4069
|
-
}
|
|
4070
|
-
var popStyle3 = (pos, extra) => ({
|
|
4071
|
-
position: "fixed",
|
|
4072
|
-
left: pos.left,
|
|
4073
|
-
top: pos.top == null ? "auto" : pos.top,
|
|
4074
|
-
bottom: pos.bottom == null ? "auto" : pos.bottom,
|
|
4075
|
-
transformOrigin: pos.up ? "bottom center" : "top center",
|
|
4076
|
-
maxHeight: pos.maxH,
|
|
4077
|
-
overflowY: "auto",
|
|
4078
|
-
...extra
|
|
4079
|
-
});
|
|
4080
4083
|
function ClockFace({ value = "09:00", onChange }) {
|
|
4081
4084
|
let [h24, m] = value.split(":").map(Number);
|
|
4082
4085
|
if (isNaN(h24)) h24 = 9;
|
|
4083
4086
|
if (isNaN(m)) m = 0;
|
|
4084
4087
|
const pm = h24 >= 12;
|
|
4085
4088
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
4086
|
-
const [mode2, setMode] =
|
|
4087
|
-
const faceRef =
|
|
4088
|
-
const dragging =
|
|
4089
|
+
const [mode2, setMode] = React24.useState("h");
|
|
4090
|
+
const faceRef = React24.useRef(null);
|
|
4091
|
+
const dragging = React24.useRef(false);
|
|
4089
4092
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
4090
4093
|
const R = 108, NR = 80;
|
|
4091
4094
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -4158,28 +4161,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
4158
4161
|
}
|
|
4159
4162
|
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
|
|
4160
4163
|
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
4161
|
-
const [open, setOpen] =
|
|
4162
|
-
const rootRef =
|
|
4163
|
-
const boxRef =
|
|
4164
|
-
const popRef = React23.useRef(null);
|
|
4165
|
-
const pos = usePopPos3(open, boxRef, 420, 262);
|
|
4166
|
-
React23.useEffect(() => {
|
|
4167
|
-
if (!open) return;
|
|
4168
|
-
const away = (e) => {
|
|
4169
|
-
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
4170
|
-
if (popRef.current && popRef.current.contains(e.target)) return;
|
|
4171
|
-
setOpen(false);
|
|
4172
|
-
};
|
|
4173
|
-
const esc = (e) => {
|
|
4174
|
-
if (e.key === "Escape") setOpen(false);
|
|
4175
|
-
};
|
|
4176
|
-
document.addEventListener("pointerdown", away);
|
|
4177
|
-
document.addEventListener("keydown", esc);
|
|
4178
|
-
return () => {
|
|
4179
|
-
document.removeEventListener("pointerdown", away);
|
|
4180
|
-
document.removeEventListener("keydown", esc);
|
|
4181
|
-
};
|
|
4182
|
-
}, [open]);
|
|
4164
|
+
const [open, setOpen] = React24.useState(false);
|
|
4165
|
+
const rootRef = React24.useRef(null);
|
|
4166
|
+
const boxRef = React24.useRef(null);
|
|
4183
4167
|
const disp = () => {
|
|
4184
4168
|
if (!value) return "";
|
|
4185
4169
|
const [h, m] = value.split(":").map(Number);
|
|
@@ -4211,10 +4195,19 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4211
4195
|
),
|
|
4212
4196
|
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-select-caret", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
|
|
4213
4197
|
] }),
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4198
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
4199
|
+
Popover,
|
|
4200
|
+
{
|
|
4201
|
+
open,
|
|
4202
|
+
anchorRef: boxRef,
|
|
4203
|
+
triggerRef: rootRef,
|
|
4204
|
+
onClose: () => setOpen(false),
|
|
4205
|
+
placement: "bottom-start",
|
|
4206
|
+
offset: 6,
|
|
4207
|
+
width: 262,
|
|
4208
|
+
role: "presentation",
|
|
4209
|
+
style: { zIndex: 130 },
|
|
4210
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React24.Fragment, { children: [
|
|
4218
4211
|
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
4219
4212
|
"button",
|
|
4220
4213
|
{
|
|
@@ -4230,10 +4223,10 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4230
4223
|
),
|
|
4231
4224
|
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { style: { flex: 1 } }),
|
|
4232
4225
|
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", onClick: () => setOpen(false), children: "Done" })
|
|
4233
|
-
] })
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
)
|
|
4226
|
+
] }),
|
|
4227
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(ClockFace, { value: value || "09:00", onChange: (v) => onChange && onChange({ target: { value: v } }) })
|
|
4228
|
+
}
|
|
4229
|
+
),
|
|
4237
4230
|
error ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("span", { className: "fd-field-error", children: [
|
|
4238
4231
|
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
4239
4232
|
error
|
|
@@ -4242,7 +4235,7 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4242
4235
|
}
|
|
4243
4236
|
|
|
4244
4237
|
// src/components/forms/Slider.tsx
|
|
4245
|
-
var
|
|
4238
|
+
var React25 = __toESM(require("react"), 1);
|
|
4246
4239
|
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
4247
4240
|
function Slider({
|
|
4248
4241
|
label,
|
|
@@ -4260,7 +4253,7 @@ function Slider({
|
|
|
4260
4253
|
...rest
|
|
4261
4254
|
}) {
|
|
4262
4255
|
const fieldId = useFieldId(id);
|
|
4263
|
-
const [dragging, setDragging] =
|
|
4256
|
+
const [dragging, setDragging] = React25.useState(false);
|
|
4264
4257
|
const v = value === void 0 ? min : Number(value);
|
|
4265
4258
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
4266
4259
|
return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
|
|
@@ -4294,7 +4287,7 @@ function Slider({
|
|
|
4294
4287
|
}
|
|
4295
4288
|
|
|
4296
4289
|
// src/components/forms/RangeSlider.tsx
|
|
4297
|
-
var
|
|
4290
|
+
var React26 = __toESM(require("react"), 1);
|
|
4298
4291
|
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
4299
4292
|
function RangeSlider({
|
|
4300
4293
|
label,
|
|
@@ -4314,9 +4307,9 @@ function RangeSlider({
|
|
|
4314
4307
|
}) {
|
|
4315
4308
|
const fmt2 = format || ((v) => String(v));
|
|
4316
4309
|
const [a, b] = value || [min, max];
|
|
4317
|
-
const [drag, setDrag] =
|
|
4318
|
-
const [focus, setFocus] =
|
|
4319
|
-
const railRef =
|
|
4310
|
+
const [drag, setDrag] = React26.useState(null);
|
|
4311
|
+
const [focus, setFocus] = React26.useState(null);
|
|
4312
|
+
const railRef = React26.useRef(null);
|
|
4320
4313
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
4321
4314
|
const clampPair = (i, v) => {
|
|
4322
4315
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -4331,7 +4324,7 @@ function RangeSlider({
|
|
|
4331
4324
|
const r = railRef.current.getBoundingClientRect();
|
|
4332
4325
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
4333
4326
|
};
|
|
4334
|
-
|
|
4327
|
+
React26.useEffect(() => {
|
|
4335
4328
|
if (drag === null) return;
|
|
4336
4329
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
4337
4330
|
const upH = () => setDrag(null);
|
|
@@ -4412,7 +4405,7 @@ function RangeSlider({
|
|
|
4412
4405
|
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
|
|
4413
4406
|
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-rail", ref: railRef }),
|
|
4414
4407
|
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
|
|
4415
|
-
marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
4408
|
+
marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(React26.Fragment, { children: [
|
|
4416
4409
|
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
|
|
4417
4410
|
m.label ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
|
|
4418
4411
|
] }, m.value)),
|
|
@@ -4441,7 +4434,7 @@ function RangeSlider({
|
|
|
4441
4434
|
}
|
|
4442
4435
|
|
|
4443
4436
|
// src/components/forms/Dropzone.tsx
|
|
4444
|
-
var
|
|
4437
|
+
var React27 = __toESM(require("react"), 1);
|
|
4445
4438
|
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
4446
4439
|
function Dropzone({
|
|
4447
4440
|
onFiles,
|
|
@@ -4456,8 +4449,8 @@ function Dropzone({
|
|
|
4456
4449
|
className = "",
|
|
4457
4450
|
style
|
|
4458
4451
|
}) {
|
|
4459
|
-
const [over, setOver] =
|
|
4460
|
-
const depth =
|
|
4452
|
+
const [over, setOver] = React27.useState(false);
|
|
4453
|
+
const depth = React27.useRef(0);
|
|
4461
4454
|
const has = (e) => {
|
|
4462
4455
|
const dt = e.dataTransfer;
|
|
4463
4456
|
if (!dt) return false;
|
|
@@ -4519,8 +4512,8 @@ function FilePickButton({
|
|
|
4519
4512
|
className = "",
|
|
4520
4513
|
children
|
|
4521
4514
|
}) {
|
|
4522
|
-
const ref =
|
|
4523
|
-
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
|
|
4515
|
+
const ref = React27.useRef(null);
|
|
4516
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(React27.Fragment, { children: [
|
|
4524
4517
|
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4525
4518
|
"button",
|
|
4526
4519
|
{
|
|
@@ -4553,10 +4546,10 @@ function FilePickButton({
|
|
|
4553
4546
|
}
|
|
4554
4547
|
function useStagedFiles(upload, opts) {
|
|
4555
4548
|
const o = opts || {};
|
|
4556
|
-
const [items, setItems] =
|
|
4557
|
-
const controllers =
|
|
4549
|
+
const [items, setItems] = React27.useState([]);
|
|
4550
|
+
const controllers = React27.useRef({});
|
|
4558
4551
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
4559
|
-
const run =
|
|
4552
|
+
const run = React27.useCallback((att) => {
|
|
4560
4553
|
if (!upload) return;
|
|
4561
4554
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
4562
4555
|
controllers.current[att.id] = ac;
|
|
@@ -4573,14 +4566,14 @@ function useStagedFiles(upload, opts) {
|
|
|
4573
4566
|
delete controllers.current[att.id];
|
|
4574
4567
|
});
|
|
4575
4568
|
}, [upload]);
|
|
4576
|
-
const add =
|
|
4569
|
+
const add = React27.useCallback((files) => {
|
|
4577
4570
|
if (!upload) return [];
|
|
4578
4571
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
4579
4572
|
setItems((list) => list.concat(atts));
|
|
4580
4573
|
atts.forEach(run);
|
|
4581
4574
|
return atts;
|
|
4582
4575
|
}, [upload, run]);
|
|
4583
|
-
const remove =
|
|
4576
|
+
const remove = React27.useCallback((att) => {
|
|
4584
4577
|
const ac = controllers.current[att.id];
|
|
4585
4578
|
if (ac) {
|
|
4586
4579
|
try {
|
|
@@ -4591,10 +4584,10 @@ function useStagedFiles(upload, opts) {
|
|
|
4591
4584
|
}
|
|
4592
4585
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
4593
4586
|
}, []);
|
|
4594
|
-
const retry =
|
|
4587
|
+
const retry = React27.useCallback((att) => {
|
|
4595
4588
|
run(att);
|
|
4596
4589
|
}, [run]);
|
|
4597
|
-
const clear =
|
|
4590
|
+
const clear = React27.useCallback(() => {
|
|
4598
4591
|
Object.values(controllers.current).forEach((ac) => {
|
|
4599
4592
|
try {
|
|
4600
4593
|
ac && ac.abort();
|
|
@@ -4718,7 +4711,7 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
4718
4711
|
}
|
|
4719
4712
|
|
|
4720
4713
|
// src/components/forms/MarkdownEditor.tsx
|
|
4721
|
-
var
|
|
4714
|
+
var React28 = __toESM(require("react"), 1);
|
|
4722
4715
|
var import_jsx_runtime57 = require("react/jsx-runtime");
|
|
4723
4716
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
4724
4717
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
@@ -4932,7 +4925,7 @@ function syncDom(root, value) {
|
|
|
4932
4925
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
4933
4926
|
}
|
|
4934
4927
|
var LIST_CONT = RE_LI;
|
|
4935
|
-
var MarkdownEditor =
|
|
4928
|
+
var MarkdownEditor = React28.forwardRef(function MarkdownEditor2({
|
|
4936
4929
|
value = "",
|
|
4937
4930
|
onChange,
|
|
4938
4931
|
onSubmit,
|
|
@@ -4951,10 +4944,10 @@ var MarkdownEditor = React27.forwardRef(function MarkdownEditor2({
|
|
|
4951
4944
|
className = "",
|
|
4952
4945
|
id
|
|
4953
4946
|
}, ref) {
|
|
4954
|
-
const boxRef =
|
|
4955
|
-
const composing =
|
|
4956
|
-
const pendingCaret =
|
|
4957
|
-
|
|
4947
|
+
const boxRef = React28.useRef(null);
|
|
4948
|
+
const composing = React28.useRef(false);
|
|
4949
|
+
const pendingCaret = React28.useRef(null);
|
|
4950
|
+
React28.useLayoutEffect(() => {
|
|
4958
4951
|
const root = boxRef.current;
|
|
4959
4952
|
if (!root || composing.current) return;
|
|
4960
4953
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -4963,7 +4956,7 @@ var MarkdownEditor = React27.forwardRef(function MarkdownEditor2({
|
|
|
4963
4956
|
pendingCaret.current = null;
|
|
4964
4957
|
if (active && caret != null) placeCaret(root, caret);
|
|
4965
4958
|
}, [value]);
|
|
4966
|
-
|
|
4959
|
+
React28.useEffect(() => {
|
|
4967
4960
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
4968
4961
|
}, [autoFocus]);
|
|
4969
4962
|
const caretNow = () => {
|
|
@@ -5030,7 +5023,7 @@ var MarkdownEditor = React27.forwardRef(function MarkdownEditor2({
|
|
|
5030
5023
|
api.replaceRange(from, to, next, from + next.length);
|
|
5031
5024
|
}
|
|
5032
5025
|
};
|
|
5033
|
-
|
|
5026
|
+
React28.useImperativeHandle(ref, () => api);
|
|
5034
5027
|
function detect(text, caret) {
|
|
5035
5028
|
if (!onTrigger) return;
|
|
5036
5029
|
const upto = text.slice(0, caret);
|
|
@@ -5182,10 +5175,10 @@ var MarkdownEditor = React27.forwardRef(function MarkdownEditor2({
|
|
|
5182
5175
|
});
|
|
5183
5176
|
|
|
5184
5177
|
// src/components/platform/AccountMenu.tsx
|
|
5185
|
-
var
|
|
5178
|
+
var React30 = __toESM(require("react"), 1);
|
|
5186
5179
|
|
|
5187
5180
|
// src/kits/session.ts
|
|
5188
|
-
var
|
|
5181
|
+
var React29 = __toESM(require("react"), 1);
|
|
5189
5182
|
var PERMISSION_CATALOG = [
|
|
5190
5183
|
{ group: "Plans", items: [
|
|
5191
5184
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -6752,8 +6745,8 @@ function roadmap(overrides) {
|
|
|
6752
6745
|
};
|
|
6753
6746
|
}
|
|
6754
6747
|
function useSession() {
|
|
6755
|
-
const [s, setS] =
|
|
6756
|
-
|
|
6748
|
+
const [s, setS] = React29.useState(getSession);
|
|
6749
|
+
React29.useEffect(() => subscribe(setS), []);
|
|
6757
6750
|
return s;
|
|
6758
6751
|
}
|
|
6759
6752
|
var SessionKit = {
|
|
@@ -6823,9 +6816,9 @@ function AccountMenu({
|
|
|
6823
6816
|
...rest
|
|
6824
6817
|
}) {
|
|
6825
6818
|
const session = SessionKit.useSession();
|
|
6826
|
-
const [open, setOpen] =
|
|
6827
|
-
const [switching, setSwitching] =
|
|
6828
|
-
const ref =
|
|
6819
|
+
const [open, setOpen] = React30.useState(false);
|
|
6820
|
+
const [switching, setSwitching] = React30.useState(false);
|
|
6821
|
+
const ref = React30.useRef(null);
|
|
6829
6822
|
const user = session.user;
|
|
6830
6823
|
const visibleAdmin = adminLinks.filter((l) => !l.perm || SessionKit.can(l.perm));
|
|
6831
6824
|
const pick = (item) => {
|
|
@@ -6877,7 +6870,7 @@ function AccountMenu({
|
|
|
6877
6870
|
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
|
|
6878
6871
|
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
|
|
6879
6872
|
] }),
|
|
6880
|
-
switching ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "fd-stack", style: { gap: 0
|
|
6873
|
+
switching ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: session.allUsers.filter((u) => u.status === "active").map((u) => /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
|
|
6881
6874
|
"button",
|
|
6882
6875
|
{
|
|
6883
6876
|
type: "button",
|
|
@@ -6909,14 +6902,14 @@ function AccountMenu({
|
|
|
6909
6902
|
}
|
|
6910
6903
|
|
|
6911
6904
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
6912
|
-
var
|
|
6905
|
+
var React31 = __toESM(require("react"), 1);
|
|
6913
6906
|
var import_jsx_runtime59 = require("react/jsx-runtime");
|
|
6914
6907
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
6915
6908
|
function Json({ obj }) {
|
|
6916
6909
|
return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
6917
6910
|
}
|
|
6918
6911
|
function Endpoint({ s, onRequest }) {
|
|
6919
|
-
const [tried, setTried] =
|
|
6912
|
+
const [tried, setTried] = React31.useState(null);
|
|
6920
6913
|
const run = async () => {
|
|
6921
6914
|
setTried("busy");
|
|
6922
6915
|
const t0 = (window.performance || Date).now();
|
|
@@ -6989,10 +6982,10 @@ function ApiSpecBrowser({
|
|
|
6989
6982
|
className = "",
|
|
6990
6983
|
...rest
|
|
6991
6984
|
}) {
|
|
6992
|
-
const [q, setQ] =
|
|
6993
|
-
const [method, setMethod] =
|
|
6994
|
-
const [mod, setMod] =
|
|
6995
|
-
const [listOnly, setListOnly] =
|
|
6985
|
+
const [q, setQ] = React31.useState("");
|
|
6986
|
+
const [method, setMethod] = React31.useState(null);
|
|
6987
|
+
const [mod, setMod] = React31.useState(null);
|
|
6988
|
+
const [listOnly, setListOnly] = React31.useState(false);
|
|
6996
6989
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
6997
6990
|
const hits = spec.filter((s) => (!method || s.method === method) && (!listOnly || s.isList) && (!activeModule || activeModule.endpoints.indexOf(s.id) >= 0) && (!q || (s.path + " " + s.title + " " + s.purpose + " " + (s.usedBy || []).join(" ")).toLowerCase().includes(q.toLowerCase())));
|
|
6998
6991
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
@@ -7071,7 +7064,7 @@ function ApiSpecBrowser({
|
|
|
7071
7064
|
}
|
|
7072
7065
|
|
|
7073
7066
|
// src/components/platform/ProfilePage.tsx
|
|
7074
|
-
var
|
|
7067
|
+
var React32 = __toESM(require("react"), 1);
|
|
7075
7068
|
var import_jsx_runtime60 = require("react/jsx-runtime");
|
|
7076
7069
|
var TIMEZONES = ["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles", "America/Anchorage", "Pacific/Honolulu", "Europe/London", "Europe/Berlin"];
|
|
7077
7070
|
var NOTIFY = [
|
|
@@ -7084,7 +7077,7 @@ var NOTIFY = [
|
|
|
7084
7077
|
function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSessions = true, className = "", ...rest }) {
|
|
7085
7078
|
const session = SessionKit.useSession();
|
|
7086
7079
|
const user = userProp || session.user;
|
|
7087
|
-
const [draft, setDraft] =
|
|
7080
|
+
const [draft, setDraft] = React32.useState(() => ({
|
|
7088
7081
|
name: user.name || "",
|
|
7089
7082
|
title: user.title || "",
|
|
7090
7083
|
email: user.email || "",
|
|
@@ -7093,8 +7086,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7093
7086
|
bio: user.bio || "",
|
|
7094
7087
|
notify: user.notify || { planShared: true, planChanged: true, goalMissed: true, flagChanged: false, weekly: true }
|
|
7095
7088
|
}));
|
|
7096
|
-
const [saving, setSaving] =
|
|
7097
|
-
const [saved, setSaved] =
|
|
7089
|
+
const [saving, setSaving] = React32.useState(false);
|
|
7090
|
+
const [saved, setSaved] = React32.useState(false);
|
|
7098
7091
|
const set = (k, v) => {
|
|
7099
7092
|
setDraft((d) => Object.assign({}, d, { [k]: v }));
|
|
7100
7093
|
setSaved(false);
|
|
@@ -7284,10 +7277,10 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7284
7277
|
}
|
|
7285
7278
|
|
|
7286
7279
|
// src/components/platform/RoadmapTimeline.tsx
|
|
7287
|
-
var
|
|
7280
|
+
var React34 = __toESM(require("react"), 1);
|
|
7288
7281
|
|
|
7289
7282
|
// src/kits/runtime.ts
|
|
7290
|
-
var
|
|
7283
|
+
var React33 = __toESM(require("react"), 1);
|
|
7291
7284
|
var WIRED_ENDPOINTS = [
|
|
7292
7285
|
// Nothing yet. Every id below would come from a real service:
|
|
7293
7286
|
// "plan.get", "placements.list", …
|
|
@@ -7458,8 +7451,8 @@ var RuntimeKit = {
|
|
|
7458
7451
|
};
|
|
7459
7452
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
7460
7453
|
function useRuntimeMode() {
|
|
7461
|
-
const [m, setM] =
|
|
7462
|
-
|
|
7454
|
+
const [m, setM] = React33.useState(RuntimeKit.getMode());
|
|
7455
|
+
React33.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
7463
7456
|
return m;
|
|
7464
7457
|
}
|
|
7465
7458
|
function useFeatureStatus(key) {
|
|
@@ -7542,12 +7535,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
7542
7535
|
}
|
|
7543
7536
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
7544
7537
|
const session = SessionKit.useSession();
|
|
7545
|
-
const [project, setProject] =
|
|
7546
|
-
const [q, setQ] =
|
|
7547
|
-
const scrollRef =
|
|
7548
|
-
const nowRef =
|
|
7549
|
-
const rm =
|
|
7550
|
-
const byKey =
|
|
7538
|
+
const [project, setProject] = React34.useState("");
|
|
7539
|
+
const [q, setQ] = React34.useState("");
|
|
7540
|
+
const scrollRef = React34.useRef(null);
|
|
7541
|
+
const nowRef = React34.useRef(null);
|
|
7542
|
+
const rm = React34.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
7543
|
+
const byKey = React34.useMemo(() => {
|
|
7551
7544
|
const m = {};
|
|
7552
7545
|
rm.items.forEach((i) => {
|
|
7553
7546
|
m[i.key] = i;
|
|
@@ -7556,7 +7549,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7556
7549
|
}, [rm]);
|
|
7557
7550
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
7558
7551
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
7559
|
-
|
|
7552
|
+
React34.useEffect(() => {
|
|
7560
7553
|
let raf1 = 0, raf2 = 0;
|
|
7561
7554
|
const place = () => {
|
|
7562
7555
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -7630,7 +7623,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7630
7623
|
lastPhase = item.phase;
|
|
7631
7624
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
7632
7625
|
const isBoundary = n === firstPending;
|
|
7633
|
-
return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
|
|
7626
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(React34.Fragment, { children: [
|
|
7634
7627
|
showPhase ? /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "fd-rm-era", children: [
|
|
7635
7628
|
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
7636
7629
|
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
@@ -7674,8 +7667,8 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7674
7667
|
}
|
|
7675
7668
|
|
|
7676
7669
|
// src/components/platform/ComingSoon.tsx
|
|
7677
|
-
var
|
|
7678
|
-
var
|
|
7670
|
+
var React35 = __toESM(require("react"), 1);
|
|
7671
|
+
var import_react_dom5 = require("react-dom");
|
|
7679
7672
|
var import_jsx_runtime62 = require("react/jsx-runtime");
|
|
7680
7673
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
7681
7674
|
function readBypassed() {
|
|
@@ -7692,8 +7685,8 @@ function writeBypassed(list) {
|
|
|
7692
7685
|
}
|
|
7693
7686
|
}
|
|
7694
7687
|
function useBypass(key) {
|
|
7695
|
-
const [on, setOn] =
|
|
7696
|
-
|
|
7688
|
+
const [on, setOn] = React35.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
7689
|
+
React35.useEffect(() => {
|
|
7697
7690
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
7698
7691
|
}, [key]);
|
|
7699
7692
|
const set = (next) => {
|
|
@@ -7740,9 +7733,9 @@ function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onB
|
|
|
7740
7733
|
] });
|
|
7741
7734
|
}
|
|
7742
7735
|
function useHoverCard(open) {
|
|
7743
|
-
const anchor =
|
|
7744
|
-
const [pos, setPos] =
|
|
7745
|
-
|
|
7736
|
+
const anchor = React35.useRef(null);
|
|
7737
|
+
const [pos, setPos] = React35.useState(null);
|
|
7738
|
+
React35.useLayoutEffect(() => {
|
|
7746
7739
|
if (!open || !anchor.current) {
|
|
7747
7740
|
setPos(null);
|
|
7748
7741
|
return;
|
|
@@ -7869,9 +7862,9 @@ function ComingSoon({
|
|
|
7869
7862
|
] });
|
|
7870
7863
|
}
|
|
7871
7864
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
7872
|
-
const [open, setOpen] =
|
|
7865
|
+
const [open, setOpen] = React35.useState(false);
|
|
7873
7866
|
const [anchor, pos] = useHoverCard(open);
|
|
7874
|
-
const close =
|
|
7867
|
+
const close = React35.useRef(null);
|
|
7875
7868
|
const show = () => {
|
|
7876
7869
|
if (close.current) {
|
|
7877
7870
|
clearTimeout(close.current);
|
|
@@ -7887,7 +7880,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7887
7880
|
setOpen(false);
|
|
7888
7881
|
}, 140);
|
|
7889
7882
|
};
|
|
7890
|
-
|
|
7883
|
+
React35.useEffect(() => () => {
|
|
7891
7884
|
if (close.current) clearTimeout(close.current);
|
|
7892
7885
|
}, []);
|
|
7893
7886
|
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
|
|
@@ -7916,7 +7909,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7916
7909
|
children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
7917
7910
|
}
|
|
7918
7911
|
),
|
|
7919
|
-
open && pos ? (0,
|
|
7912
|
+
open && pos ? (0, import_react_dom5.createPortal)(
|
|
7920
7913
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
7921
7914
|
"div",
|
|
7922
7915
|
{
|
|
@@ -8056,13 +8049,13 @@ function PermissionHint({ perm, children }) {
|
|
|
8056
8049
|
}
|
|
8057
8050
|
|
|
8058
8051
|
// src/components/platform/ModeSwitch.tsx
|
|
8059
|
-
var
|
|
8052
|
+
var React36 = __toESM(require("react"), 1);
|
|
8060
8053
|
var import_jsx_runtime64 = require("react/jsx-runtime");
|
|
8061
8054
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
8062
8055
|
const mode2 = useRuntimeMode();
|
|
8063
|
-
const [open, setOpen] =
|
|
8064
|
-
const ref =
|
|
8065
|
-
|
|
8056
|
+
const [open, setOpen] = React36.useState(false);
|
|
8057
|
+
const ref = React36.useRef(null);
|
|
8058
|
+
React36.useEffect(() => {
|
|
8066
8059
|
if (!open) return;
|
|
8067
8060
|
const away = (e) => {
|
|
8068
8061
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -8311,11 +8304,11 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8311
8304
|
}
|
|
8312
8305
|
|
|
8313
8306
|
// src/components/planner/MixGap.tsx
|
|
8314
|
-
var
|
|
8307
|
+
var React37 = __toESM(require("react"), 1);
|
|
8315
8308
|
var import_jsx_runtime67 = require("react/jsx-runtime");
|
|
8316
8309
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
8317
8310
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
8318
|
-
const [hover, setHover] =
|
|
8311
|
+
const [hover, setHover] = React37.useState(null);
|
|
8319
8312
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
8320
8313
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
8321
8314
|
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
|
|
@@ -8455,7 +8448,7 @@ function ChannelContribution({
|
|
|
8455
8448
|
}
|
|
8456
8449
|
|
|
8457
8450
|
// src/components/planner/BudgetReallocator.tsx
|
|
8458
|
-
var
|
|
8451
|
+
var React38 = __toESM(require("react"), 1);
|
|
8459
8452
|
var import_jsx_runtime69 = require("react/jsx-runtime");
|
|
8460
8453
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
8461
8454
|
function BudgetReallocator({
|
|
@@ -8471,8 +8464,8 @@ function BudgetReallocator({
|
|
|
8471
8464
|
onCancel,
|
|
8472
8465
|
className = ""
|
|
8473
8466
|
}) {
|
|
8474
|
-
const [draft, setDraft] =
|
|
8475
|
-
|
|
8467
|
+
const [draft, setDraft] = React38.useState(spend);
|
|
8468
|
+
React38.useEffect(() => setDraft(spend), [spend]);
|
|
8476
8469
|
const dirty = draft !== spend;
|
|
8477
8470
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
8478
8471
|
const nextBand = bandFor(nextCrp);
|
|
@@ -8642,7 +8635,7 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "" })
|
|
|
8642
8635
|
}
|
|
8643
8636
|
|
|
8644
8637
|
// src/components/planner/PreferenceMeter.tsx
|
|
8645
|
-
var
|
|
8638
|
+
var React39 = __toESM(require("react"), 1);
|
|
8646
8639
|
var import_jsx_runtime72 = require("react/jsx-runtime");
|
|
8647
8640
|
function preferenceScore(criteria) {
|
|
8648
8641
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
@@ -8672,7 +8665,7 @@ function PreferenceMeter({
|
|
|
8672
8665
|
className = ""
|
|
8673
8666
|
}) {
|
|
8674
8667
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
8675
|
-
const segments =
|
|
8668
|
+
const segments = React39.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
8676
8669
|
return /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
|
|
8677
8670
|
ScoreMeter,
|
|
8678
8671
|
{
|
|
@@ -8711,10 +8704,10 @@ function PreferenceMeter({
|
|
|
8711
8704
|
}
|
|
8712
8705
|
|
|
8713
8706
|
// src/components/chat/AgentChatPanel.tsx
|
|
8714
|
-
var
|
|
8707
|
+
var React45 = __toESM(require("react"), 1);
|
|
8715
8708
|
|
|
8716
8709
|
// src/components/chat/chatEngine.ts
|
|
8717
|
-
var
|
|
8710
|
+
var React40 = __toESM(require("react"), 1);
|
|
8718
8711
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
8719
8712
|
var JOB_PENDING = ["queued", "running"];
|
|
8720
8713
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -8768,22 +8761,22 @@ function useChatEngine(opts) {
|
|
|
8768
8761
|
onClear,
|
|
8769
8762
|
onFeedback
|
|
8770
8763
|
} = opts || {};
|
|
8771
|
-
const [status, setStatus] =
|
|
8772
|
-
const [threadId, setThreadId] =
|
|
8773
|
-
const [messages, setMessages] =
|
|
8774
|
-
const [queue, setQueue] =
|
|
8775
|
-
const [fatal, setFatal] =
|
|
8776
|
-
const [busy, setBusy] =
|
|
8777
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
8778
|
-
const listRef =
|
|
8779
|
-
const queueRef =
|
|
8780
|
-
const busyRef =
|
|
8781
|
-
const stoppedRef =
|
|
8782
|
-
const abortRef =
|
|
8783
|
-
const serverCount =
|
|
8784
|
-
const threadRef =
|
|
8785
|
-
const mounted =
|
|
8786
|
-
|
|
8764
|
+
const [status, setStatus] = React40.useState("idle");
|
|
8765
|
+
const [threadId, setThreadId] = React40.useState(null);
|
|
8766
|
+
const [messages, setMessages] = React40.useState([]);
|
|
8767
|
+
const [queue, setQueue] = React40.useState([]);
|
|
8768
|
+
const [fatal, setFatal] = React40.useState(null);
|
|
8769
|
+
const [busy, setBusy] = React40.useState(false);
|
|
8770
|
+
const [turnStartedAt, setTurnStartedAt] = React40.useState(null);
|
|
8771
|
+
const listRef = React40.useRef([]);
|
|
8772
|
+
const queueRef = React40.useRef([]);
|
|
8773
|
+
const busyRef = React40.useRef(false);
|
|
8774
|
+
const stoppedRef = React40.useRef(false);
|
|
8775
|
+
const abortRef = React40.useRef(null);
|
|
8776
|
+
const serverCount = React40.useRef(0);
|
|
8777
|
+
const threadRef = React40.useRef(null);
|
|
8778
|
+
const mounted = React40.useRef(true);
|
|
8779
|
+
React40.useEffect(() => {
|
|
8787
8780
|
mounted.current = true;
|
|
8788
8781
|
return () => {
|
|
8789
8782
|
mounted.current = false;
|
|
@@ -8805,14 +8798,14 @@ function useChatEngine(opts) {
|
|
|
8805
8798
|
}
|
|
8806
8799
|
return false;
|
|
8807
8800
|
};
|
|
8808
|
-
const loadThread =
|
|
8801
|
+
const loadThread = React40.useCallback(async (id) => {
|
|
8809
8802
|
const data = await apiAdapter.getThread(id);
|
|
8810
8803
|
const list = [...data && data.messages || []];
|
|
8811
8804
|
serverCount.current = list.length;
|
|
8812
8805
|
commit(list);
|
|
8813
8806
|
return list;
|
|
8814
8807
|
}, [apiAdapter]);
|
|
8815
|
-
|
|
8808
|
+
React40.useEffect(() => {
|
|
8816
8809
|
if (!apiAdapter) {
|
|
8817
8810
|
setStatus("idle");
|
|
8818
8811
|
setFatal(null);
|
|
@@ -9025,7 +9018,7 @@ function useChatEngine(opts) {
|
|
|
9025
9018
|
await dispatchTurn(turn);
|
|
9026
9019
|
}
|
|
9027
9020
|
}
|
|
9028
|
-
const send =
|
|
9021
|
+
const send = React40.useCallback((text, attachments) => {
|
|
9029
9022
|
const body = (text || "").trim();
|
|
9030
9023
|
if (!body && !(attachments && attachments.length)) return;
|
|
9031
9024
|
if (status === "disconnected") return;
|
|
@@ -9035,7 +9028,7 @@ function useChatEngine(opts) {
|
|
|
9035
9028
|
stoppedRef.current = false;
|
|
9036
9029
|
drain();
|
|
9037
9030
|
}, [status]);
|
|
9038
|
-
const stop =
|
|
9031
|
+
const stop = React40.useCallback(() => {
|
|
9039
9032
|
stoppedRef.current = true;
|
|
9040
9033
|
const ac = abortRef.current;
|
|
9041
9034
|
if (ac) {
|
|
@@ -9054,11 +9047,11 @@ function useChatEngine(opts) {
|
|
|
9054
9047
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
9055
9048
|
}
|
|
9056
9049
|
}, [apiAdapter]);
|
|
9057
|
-
const removeQueued =
|
|
9050
|
+
const removeQueued = React40.useCallback((id) => {
|
|
9058
9051
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
9059
9052
|
setQueue(queueRef.current.slice());
|
|
9060
9053
|
}, []);
|
|
9061
|
-
const retry =
|
|
9054
|
+
const retry = React40.useCallback(() => {
|
|
9062
9055
|
const list = listRef.current;
|
|
9063
9056
|
let at = -1;
|
|
9064
9057
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -9074,19 +9067,19 @@ function useChatEngine(opts) {
|
|
|
9074
9067
|
setQueue(queueRef.current.slice());
|
|
9075
9068
|
drain();
|
|
9076
9069
|
}, []);
|
|
9077
|
-
const clear =
|
|
9070
|
+
const clear = React40.useCallback(() => {
|
|
9078
9071
|
commit([]);
|
|
9079
9072
|
serverCount.current = 0;
|
|
9080
9073
|
queueRef.current = [];
|
|
9081
9074
|
setQueue([]);
|
|
9082
9075
|
onClear && onClear();
|
|
9083
9076
|
}, [onClear]);
|
|
9084
|
-
const setFeedback =
|
|
9077
|
+
const setFeedback = React40.useCallback((id, value) => {
|
|
9085
9078
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
9086
9079
|
const msg = listRef.current.find((m) => m.id === id);
|
|
9087
9080
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
9088
9081
|
}, [onFeedback]);
|
|
9089
|
-
const reload =
|
|
9082
|
+
const reload = React40.useCallback(async () => {
|
|
9090
9083
|
if (!threadRef.current) return;
|
|
9091
9084
|
setStatus("loading");
|
|
9092
9085
|
try {
|
|
@@ -9124,10 +9117,10 @@ var ChatKit = {
|
|
|
9124
9117
|
};
|
|
9125
9118
|
|
|
9126
9119
|
// src/components/chat/ChatTranscript.tsx
|
|
9127
|
-
var
|
|
9120
|
+
var React42 = __toESM(require("react"), 1);
|
|
9128
9121
|
|
|
9129
9122
|
// src/components/chat/ChatTurn.tsx
|
|
9130
|
-
var
|
|
9123
|
+
var React41 = __toESM(require("react"), 1);
|
|
9131
9124
|
var import_jsx_runtime73 = require("react/jsx-runtime");
|
|
9132
9125
|
function JsonView({ value }) {
|
|
9133
9126
|
let text;
|
|
@@ -9164,7 +9157,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
|
9164
9157
|
] });
|
|
9165
9158
|
}
|
|
9166
9159
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
9167
|
-
const [open, setOpen] =
|
|
9160
|
+
const [open, setOpen] = React41.useState(defaultOpen);
|
|
9168
9161
|
if (!text) return null;
|
|
9169
9162
|
return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
|
|
9170
9163
|
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -9181,7 +9174,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
|
9181
9174
|
] });
|
|
9182
9175
|
}
|
|
9183
9176
|
function Citations({ items = [], onOpen }) {
|
|
9184
|
-
const [open, setOpen] =
|
|
9177
|
+
const [open, setOpen] = React41.useState(false);
|
|
9185
9178
|
if (!items.length) return null;
|
|
9186
9179
|
return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fdc-cites", children: [
|
|
9187
9180
|
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -9207,7 +9200,7 @@ function clampText(text, max) {
|
|
|
9207
9200
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
9208
9201
|
}
|
|
9209
9202
|
function MessageBody({ message: m, ctx }) {
|
|
9210
|
-
const [expanded, setExpanded] =
|
|
9203
|
+
const [expanded, setExpanded] = React41.useState(false);
|
|
9211
9204
|
const isUser = m.role === "user";
|
|
9212
9205
|
const raw = m.text || "";
|
|
9213
9206
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
@@ -9274,9 +9267,9 @@ function MessageBody({ message: m, ctx }) {
|
|
|
9274
9267
|
] });
|
|
9275
9268
|
}
|
|
9276
9269
|
function useCopyRun() {
|
|
9277
|
-
const [done, setDone] =
|
|
9278
|
-
const t =
|
|
9279
|
-
|
|
9270
|
+
const [done, setDone] = React41.useState(false);
|
|
9271
|
+
const t = React41.useRef(null);
|
|
9272
|
+
React41.useEffect(() => () => {
|
|
9280
9273
|
if (t.current) clearTimeout(t.current);
|
|
9281
9274
|
}, []);
|
|
9282
9275
|
return [done, (text) => {
|
|
@@ -9303,7 +9296,7 @@ function RunActions({ group, ctx }) {
|
|
|
9303
9296
|
] }),
|
|
9304
9297
|
isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
9305
9298
|
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
9306
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
|
|
9299
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(React41.Fragment, { children: [
|
|
9307
9300
|
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
9308
9301
|
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
9309
9302
|
] }) : null,
|
|
@@ -9398,10 +9391,10 @@ function ChatTranscript({
|
|
|
9398
9391
|
renderEmpty,
|
|
9399
9392
|
className = ""
|
|
9400
9393
|
}) {
|
|
9401
|
-
const scroller =
|
|
9402
|
-
const stick =
|
|
9403
|
-
const [pill, setPill] =
|
|
9404
|
-
const seen =
|
|
9394
|
+
const scroller = React42.useRef(null);
|
|
9395
|
+
const stick = React42.useRef(true);
|
|
9396
|
+
const [pill, setPill] = React42.useState(0);
|
|
9397
|
+
const seen = React42.useRef(0);
|
|
9405
9398
|
const toBottom = (smooth) => {
|
|
9406
9399
|
const el = scroller.current;
|
|
9407
9400
|
if (!el) return;
|
|
@@ -9420,7 +9413,7 @@ function ChatTranscript({
|
|
|
9420
9413
|
seen.current = messages.length;
|
|
9421
9414
|
}
|
|
9422
9415
|
};
|
|
9423
|
-
|
|
9416
|
+
React42.useLayoutEffect(() => {
|
|
9424
9417
|
const el = scroller.current;
|
|
9425
9418
|
if (!el) return;
|
|
9426
9419
|
if (stick.current) {
|
|
@@ -9428,7 +9421,7 @@ function ChatTranscript({
|
|
|
9428
9421
|
seen.current = messages.length;
|
|
9429
9422
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
9430
9423
|
}, [messages]);
|
|
9431
|
-
|
|
9424
|
+
React42.useEffect(() => {
|
|
9432
9425
|
const el = scroller.current;
|
|
9433
9426
|
const inner = el && el.firstChild;
|
|
9434
9427
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -9438,7 +9431,7 @@ function ChatTranscript({
|
|
|
9438
9431
|
ro.observe(inner);
|
|
9439
9432
|
return () => ro.disconnect();
|
|
9440
9433
|
}, []);
|
|
9441
|
-
const groups =
|
|
9434
|
+
const groups = React42.useMemo(() => groupMessages(messages), [messages]);
|
|
9442
9435
|
const empty = !messages.length && status === "ready";
|
|
9443
9436
|
return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
9444
9437
|
/* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
@@ -9462,7 +9455,7 @@ function ChatTranscript({
|
|
|
9462
9455
|
const prev = groups[i - 1];
|
|
9463
9456
|
const k = dayKey(g.messages[0].timestamp);
|
|
9464
9457
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
9465
|
-
return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
|
|
9458
|
+
return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(React42.Fragment, { children: [
|
|
9466
9459
|
showDay ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { children: dayLabel(k) }) }) : null,
|
|
9467
9460
|
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)(ChatTurn, { group: g, ctx })
|
|
9468
9461
|
] }, g.key || i);
|
|
@@ -9479,7 +9472,7 @@ function ChatTranscript({
|
|
|
9479
9472
|
var TranscriptKit = { groupMessages };
|
|
9480
9473
|
|
|
9481
9474
|
// src/components/chat/ChatComposer.tsx
|
|
9482
|
-
var
|
|
9475
|
+
var React43 = __toESM(require("react"), 1);
|
|
9483
9476
|
var import_jsx_runtime75 = require("react/jsx-runtime");
|
|
9484
9477
|
function ChatComposer({
|
|
9485
9478
|
onSubmit,
|
|
@@ -9507,17 +9500,17 @@ function ChatComposer({
|
|
|
9507
9500
|
onReject,
|
|
9508
9501
|
onOpenAttachment
|
|
9509
9502
|
}) {
|
|
9510
|
-
const [text, setText] =
|
|
9511
|
-
const [trigger, setTrigger] =
|
|
9512
|
-
const [mentionItems, setMentionItems] =
|
|
9513
|
-
const [listening, setListening] =
|
|
9514
|
-
const [notice, setNotice] =
|
|
9515
|
-
const editor =
|
|
9516
|
-
const wrap =
|
|
9517
|
-
const stopVoice =
|
|
9503
|
+
const [text, setText] = React43.useState(draft || "");
|
|
9504
|
+
const [trigger, setTrigger] = React43.useState(null);
|
|
9505
|
+
const [mentionItems, setMentionItems] = React43.useState([]);
|
|
9506
|
+
const [listening, setListening] = React43.useState(false);
|
|
9507
|
+
const [notice, setNotice] = React43.useState(null);
|
|
9508
|
+
const editor = React43.useRef(null);
|
|
9509
|
+
const wrap = React43.useRef(null);
|
|
9510
|
+
const stopVoice = React43.useRef(null);
|
|
9518
9511
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
9519
9512
|
} });
|
|
9520
|
-
|
|
9513
|
+
React43.useEffect(() => {
|
|
9521
9514
|
if (draft != null && draft !== text) setText(draft);
|
|
9522
9515
|
}, [draft]);
|
|
9523
9516
|
const change = (v) => {
|
|
@@ -9551,7 +9544,7 @@ function ChatComposer({
|
|
|
9551
9544
|
e.preventDefault();
|
|
9552
9545
|
staged.add(found.files);
|
|
9553
9546
|
};
|
|
9554
|
-
|
|
9547
|
+
React43.useEffect(() => {
|
|
9555
9548
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
9556
9549
|
setMentionItems([]);
|
|
9557
9550
|
return;
|
|
@@ -9569,7 +9562,7 @@ function ChatComposer({
|
|
|
9569
9562
|
const q = (trigger.query || "").toLowerCase();
|
|
9570
9563
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
9571
9564
|
}, [trigger, mentionSources]);
|
|
9572
|
-
const slashItems =
|
|
9565
|
+
const slashItems = React43.useMemo(() => {
|
|
9573
9566
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
9574
9567
|
const q = (trigger.query || "").toLowerCase();
|
|
9575
9568
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -9743,12 +9736,12 @@ function ChatComposer({
|
|
|
9743
9736
|
}
|
|
9744
9737
|
|
|
9745
9738
|
// src/components/chat/ChatSessionBar.tsx
|
|
9746
|
-
var
|
|
9739
|
+
var React44 = __toESM(require("react"), 1);
|
|
9747
9740
|
var import_jsx_runtime76 = require("react/jsx-runtime");
|
|
9748
9741
|
var compact2 = meterFormats.compact;
|
|
9749
9742
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
9750
|
-
const [open, setOpen] =
|
|
9751
|
-
const anchor =
|
|
9743
|
+
const [open, setOpen] = React44.useState(false);
|
|
9744
|
+
const anchor = React44.useRef(null);
|
|
9752
9745
|
const stats = sessionStats || null;
|
|
9753
9746
|
const cu = contextUsage || null;
|
|
9754
9747
|
const limits = usageLimits || null;
|
|
@@ -9763,7 +9756,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9763
9756
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
9764
9757
|
if (cu) bits.push(pct + "% context");
|
|
9765
9758
|
const expandable = !!(cu || limits);
|
|
9766
|
-
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
|
|
9759
|
+
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React44.Fragment, { children: [
|
|
9767
9760
|
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fdc-bar", children: [
|
|
9768
9761
|
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
|
|
9769
9762
|
"button",
|
|
@@ -9784,60 +9777,73 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9784
9777
|
),
|
|
9785
9778
|
extras
|
|
9786
9779
|
] }),
|
|
9787
|
-
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
|
|
9795
|
-
|
|
9796
|
-
|
|
9797
|
-
|
|
9798
|
-
|
|
9799
|
-
|
|
9800
|
-
|
|
9801
|
-
|
|
9802
|
-
|
|
9803
|
-
|
|
9804
|
-
|
|
9805
|
-
|
|
9806
|
-
|
|
9807
|
-
|
|
9808
|
-
|
|
9809
|
-
|
|
9810
|
-
|
|
9811
|
-
|
|
9812
|
-
|
|
9813
|
-
|
|
9814
|
-
|
|
9815
|
-
|
|
9816
|
-
|
|
9817
|
-
|
|
9818
|
-
/* @__PURE__ */ (0, import_jsx_runtime76.
|
|
9819
|
-
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
|
|
9824
|
-
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
/* @__PURE__ */ (0, import_jsx_runtime76.
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
|
|
9835
|
-
|
|
9836
|
-
|
|
9837
|
-
|
|
9838
|
-
|
|
9839
|
-
|
|
9840
|
-
|
|
9780
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
9781
|
+
Popover,
|
|
9782
|
+
{
|
|
9783
|
+
open,
|
|
9784
|
+
anchorRef: anchor,
|
|
9785
|
+
placement: "top-start",
|
|
9786
|
+
onClose: () => setOpen(false),
|
|
9787
|
+
minWidth: 330,
|
|
9788
|
+
maxHeight: 460,
|
|
9789
|
+
padded: true,
|
|
9790
|
+
label: "Usage",
|
|
9791
|
+
footer: onClear ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
|
|
9792
|
+
setOpen(false);
|
|
9793
|
+
onClear();
|
|
9794
|
+
}, children: [
|
|
9795
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
|
|
9796
|
+
"Clear conversation"
|
|
9797
|
+
] }) : void 0,
|
|
9798
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fdc-usage", children: [
|
|
9799
|
+
cu ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
9800
|
+
SegmentedMeter,
|
|
9801
|
+
{
|
|
9802
|
+
total,
|
|
9803
|
+
segments: cu.segments,
|
|
9804
|
+
label: cu.label || "Context window",
|
|
9805
|
+
format: cu.format === "bytes" ? meterFormats.bytes : compact2,
|
|
9806
|
+
height: 8,
|
|
9807
|
+
legend: true,
|
|
9808
|
+
remainderLabel: "Free"
|
|
9809
|
+
}
|
|
9810
|
+
) }) : null,
|
|
9811
|
+
limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("section", { className: "fdc-usage-sec", children: [
|
|
9812
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
|
|
9813
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
9814
|
+
QuotaRow,
|
|
9815
|
+
{
|
|
9816
|
+
label: l.label,
|
|
9817
|
+
percent: l.percent,
|
|
9818
|
+
note: l.resetsAt ? "Resets " + formatRelative(l.resetsAt) : l.note
|
|
9819
|
+
},
|
|
9820
|
+
l.id
|
|
9821
|
+
)) })
|
|
9822
|
+
] }) : null,
|
|
9823
|
+
stats ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
|
|
9824
|
+
stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { children: [
|
|
9825
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { children: "Session" }),
|
|
9826
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
|
|
9827
|
+
] }) : null,
|
|
9828
|
+
stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { children: [
|
|
9829
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { children: "Tokens" }),
|
|
9830
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
|
|
9831
|
+
] }) : null,
|
|
9832
|
+
stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { children: [
|
|
9833
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { children: "Cost" }),
|
|
9834
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("b", { className: "fd-tabular", children: [
|
|
9835
|
+
"$",
|
|
9836
|
+
Number(stats.costUsd).toFixed(3)
|
|
9837
|
+
] })
|
|
9838
|
+
] }) : null,
|
|
9839
|
+
stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { children: [
|
|
9840
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { children: "Turns" }),
|
|
9841
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("b", { className: "fd-tabular", children: stats.turns })
|
|
9842
|
+
] }) : null
|
|
9843
|
+
] }) : null
|
|
9844
|
+
] })
|
|
9845
|
+
}
|
|
9846
|
+
)
|
|
9841
9847
|
] });
|
|
9842
9848
|
}
|
|
9843
9849
|
function ModelControls({
|
|
@@ -9891,7 +9897,7 @@ function ModelControls({
|
|
|
9891
9897
|
] })
|
|
9892
9898
|
});
|
|
9893
9899
|
}
|
|
9894
|
-
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
|
|
9900
|
+
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React44.Fragment, { children: [
|
|
9895
9901
|
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
9896
9902
|
MenuButton,
|
|
9897
9903
|
{
|
|
@@ -10008,11 +10014,11 @@ function AgentChatPanel({
|
|
|
10008
10014
|
onFeedback,
|
|
10009
10015
|
onEditMessage
|
|
10010
10016
|
}) {
|
|
10011
|
-
const [panelWidth, setPanelWidth] =
|
|
10012
|
-
const [applied, setApplied] =
|
|
10013
|
-
const [draft, setDraft] =
|
|
10014
|
-
const dragging =
|
|
10015
|
-
|
|
10017
|
+
const [panelWidth, setPanelWidth] = React45.useState(width);
|
|
10018
|
+
const [applied, setApplied] = React45.useState({});
|
|
10019
|
+
const [draft, setDraft] = React45.useState("");
|
|
10020
|
+
const dragging = React45.useRef(null);
|
|
10021
|
+
React45.useEffect(() => setPanelWidth(width), [width]);
|
|
10016
10022
|
const engine = useChatEngine({
|
|
10017
10023
|
contextType,
|
|
10018
10024
|
contextId,
|
|
@@ -10216,7 +10222,7 @@ function AgentChatPanel({
|
|
|
10216
10222
|
}
|
|
10217
10223
|
|
|
10218
10224
|
// src/kits/query.ts
|
|
10219
|
-
var
|
|
10225
|
+
var React46 = __toESM(require("react"), 1);
|
|
10220
10226
|
function eqFilter(get2) {
|
|
10221
10227
|
return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
|
|
10222
10228
|
}
|
|
@@ -10248,22 +10254,22 @@ function compare(a, b, dir) {
|
|
|
10248
10254
|
var API = null;
|
|
10249
10255
|
var PREFS = null;
|
|
10250
10256
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
10251
|
-
const [query, setQuery] =
|
|
10257
|
+
const [query, setQuery] = React46.useState(() => {
|
|
10252
10258
|
const store = PREFS || window.PlannerPrefs;
|
|
10253
10259
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
10254
10260
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
10255
10261
|
});
|
|
10256
|
-
const savePref =
|
|
10262
|
+
const savePref = React46.useCallback((patch2) => {
|
|
10257
10263
|
const store = PREFS || window.PlannerPrefs;
|
|
10258
10264
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
10259
10265
|
}, [prefsKey]);
|
|
10260
|
-
const [res, setRes] =
|
|
10261
|
-
const [loading, setLoading] =
|
|
10262
|
-
const seq2 =
|
|
10266
|
+
const [res, setRes] = React46.useState(null);
|
|
10267
|
+
const [loading, setLoading] = React46.useState(true);
|
|
10268
|
+
const seq2 = React46.useRef(0);
|
|
10263
10269
|
const depKey = (deps || []).join("|");
|
|
10264
10270
|
const paramKey = JSON.stringify(params || {});
|
|
10265
10271
|
const queryKey = JSON.stringify(query);
|
|
10266
|
-
|
|
10272
|
+
React46.useEffect(() => {
|
|
10267
10273
|
const id = ++seq2.current;
|
|
10268
10274
|
setLoading(true);
|
|
10269
10275
|
const t = setTimeout(() => {
|
|
@@ -10638,6 +10644,7 @@ function createVersionStore(initialState, options) {
|
|
|
10638
10644
|
ModeSwitch,
|
|
10639
10645
|
ModelControls,
|
|
10640
10646
|
NumberInput,
|
|
10647
|
+
POPOVER_BODY_MIN,
|
|
10641
10648
|
PacketCard,
|
|
10642
10649
|
Pagination,
|
|
10643
10650
|
PermissionDenied,
|