@estiva-app/ui 0.24.1 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AttachmentCard.d.ts +48 -6
- package/dist/AttachmentCard.d.ts.map +1 -1
- package/dist/ErrorBoundary.d.ts +32 -0
- package/dist/ErrorBoundary.d.ts.map +1 -0
- package/dist/Lightbox.d.ts +30 -0
- package/dist/Lightbox.d.ts.map +1 -0
- package/dist/ListColumn.d.ts +9 -8
- package/dist/ListColumn.d.ts.map +1 -1
- package/dist/Menu.d.ts +7 -0
- package/dist/Menu.d.ts.map +1 -1
- package/dist/eslint/index.js +4 -4
- package/dist/eslint/index.js.map +2 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +634 -456
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/registry.json +157 -20
- package/src/AttachmentCard.mdx +32 -8
- package/src/AttachmentCard.stories.tsx +54 -0
- package/src/AttachmentCard.test.tsx +115 -0
- package/src/AttachmentCard.tsx +212 -37
- package/src/CollapsibleSection.mdx +1 -1
- package/src/Divider.mdx +3 -3
- package/src/ErrorBoundary.mdx +66 -0
- package/src/ErrorBoundary.stories.tsx +64 -0
- package/src/ErrorBoundary.test.tsx +79 -0
- package/src/ErrorBoundary.tsx +54 -0
- package/src/Lightbox.mdx +71 -0
- package/src/Lightbox.stories.tsx +72 -0
- package/src/Lightbox.test.tsx +65 -0
- package/src/Lightbox.tsx +87 -0
- package/src/ListColumn.mdx +11 -3
- package/src/ListColumn.stories.tsx +34 -10
- package/src/ListColumn.test.tsx +20 -7
- package/src/ListColumn.tsx +34 -11
- package/src/Menu.mdx +5 -2
- package/src/Menu.stories.tsx +6 -7
- package/src/Menu.test.tsx +19 -1
- package/src/Menu.tsx +11 -1
- package/src/SectionHeader.mdx +5 -1
- package/src/SectionLabel.mdx +4 -2
- package/src/eslint/no-rebuilt-behaviour.ts +4 -4
- package/src/index.ts +3 -1
- package/src/registry/registry.test.ts +6 -6
- package/tailwind-preset.js +3 -0
- package/tokens.css +4 -0
package/dist/index.js
CHANGED
|
@@ -140,7 +140,7 @@ function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
// src/AttachmentCard.tsx
|
|
143
|
-
import { useLayoutEffect, useRef, useState } from "react";
|
|
143
|
+
import { useEffect, useLayoutEffect, useRef as useRef2, useState } from "react";
|
|
144
144
|
import { Button as BaseButton2 } from "@base-ui/react/button";
|
|
145
145
|
import {
|
|
146
146
|
IconAlertCircle,
|
|
@@ -157,7 +157,7 @@ import {
|
|
|
157
157
|
IconJson,
|
|
158
158
|
IconLoader2,
|
|
159
159
|
IconMarkdown,
|
|
160
|
-
IconX
|
|
160
|
+
IconX as IconX2
|
|
161
161
|
} from "@tabler/icons-react";
|
|
162
162
|
|
|
163
163
|
// src/Link.tsx
|
|
@@ -406,8 +406,58 @@ function IconButton({
|
|
|
406
406
|
return button;
|
|
407
407
|
}
|
|
408
408
|
|
|
409
|
+
// src/Lightbox.tsx
|
|
410
|
+
import { useRef } from "react";
|
|
411
|
+
import { Dialog } from "@base-ui/react/dialog";
|
|
412
|
+
import { IconX } from "@tabler/icons-react";
|
|
413
|
+
import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
414
|
+
function Lightbox({ src, alt, onClose, className }) {
|
|
415
|
+
const popupRef = useRef(null);
|
|
416
|
+
return /* @__PURE__ */ jsx9(
|
|
417
|
+
Dialog.Root,
|
|
418
|
+
{
|
|
419
|
+
open: true,
|
|
420
|
+
onOpenChange: (open) => {
|
|
421
|
+
if (!open) onClose();
|
|
422
|
+
},
|
|
423
|
+
children: /* @__PURE__ */ jsxs5(Dialog.Portal, { children: [
|
|
424
|
+
/* @__PURE__ */ jsx9(Dialog.Backdrop, { className: "fixed inset-0 z-40 bg-scrim-strong" }),
|
|
425
|
+
/* @__PURE__ */ jsxs5(
|
|
426
|
+
Dialog.Popup,
|
|
427
|
+
{
|
|
428
|
+
ref: popupRef,
|
|
429
|
+
initialFocus: popupRef,
|
|
430
|
+
"aria-label": alt,
|
|
431
|
+
className: "fixed inset-0 z-50 flex items-center justify-center p-8 outline-none",
|
|
432
|
+
onClick: onClose,
|
|
433
|
+
children: [
|
|
434
|
+
/* @__PURE__ */ jsx9(
|
|
435
|
+
"img",
|
|
436
|
+
{
|
|
437
|
+
src,
|
|
438
|
+
alt,
|
|
439
|
+
onClick: (e) => e.stopPropagation(),
|
|
440
|
+
className: cn("max-w-full max-h-full object-contain rounded-lg", className)
|
|
441
|
+
}
|
|
442
|
+
),
|
|
443
|
+
/* @__PURE__ */ jsx9(
|
|
444
|
+
Dialog.Close,
|
|
445
|
+
{
|
|
446
|
+
"aria-label": "Close",
|
|
447
|
+
className: "absolute top-4 right-4 size-8 rounded-full bg-bg-elevated border border-border-strong flex items-center justify-center text-text-secondary hover:text-text-primary",
|
|
448
|
+
children: /* @__PURE__ */ jsx9(IconX, { size: 16, stroke: 1.5 })
|
|
449
|
+
}
|
|
450
|
+
)
|
|
451
|
+
]
|
|
452
|
+
}
|
|
453
|
+
)
|
|
454
|
+
] })
|
|
455
|
+
}
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
|
|
409
459
|
// src/AttachmentCard.tsx
|
|
410
|
-
import { Fragment, jsx as
|
|
460
|
+
import { Fragment, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
411
461
|
var ICON_BY_EXTENSION = {
|
|
412
462
|
pdf: IconFileTypePdf,
|
|
413
463
|
doc: IconFileTypeDocx,
|
|
@@ -441,10 +491,10 @@ var NAME_CLASSES = "text-caption font-medium text-text-primary truncate";
|
|
|
441
491
|
var NOTE_CLASSES = "text-small tracking-wide leading-tight truncate";
|
|
442
492
|
function TypeIcon({ name }) {
|
|
443
493
|
const Icon = ICON_BY_EXTENSION[extensionOf(name)] ?? IconFile;
|
|
444
|
-
return /* @__PURE__ */
|
|
494
|
+
return /* @__PURE__ */ jsx10(Icon, { size: 20, stroke: 1.5 });
|
|
445
495
|
}
|
|
446
496
|
function Truncating({ text, hint, className, wrapperClassName, placement }) {
|
|
447
|
-
const ref =
|
|
497
|
+
const ref = useRef2(null);
|
|
448
498
|
const [cut, setCut] = useState(false);
|
|
449
499
|
useLayoutEffect(() => {
|
|
450
500
|
const el = ref.current;
|
|
@@ -463,9 +513,54 @@ function Truncating({ text, hint, className, wrapperClassName, placement }) {
|
|
|
463
513
|
observer.disconnect();
|
|
464
514
|
};
|
|
465
515
|
}, [text, cut]);
|
|
466
|
-
const line = /* @__PURE__ */
|
|
516
|
+
const line = /* @__PURE__ */ jsx10("span", { ref, className, children: text });
|
|
467
517
|
if (!hint && !cut) return line;
|
|
468
|
-
return /* @__PURE__ */
|
|
518
|
+
return /* @__PURE__ */ jsx10(WithTooltip, { label: hint ?? text, placement, wrapperClassName: cn("min-w-0 flex-col", wrapperClassName), children: line });
|
|
519
|
+
}
|
|
520
|
+
function useRemoteImage(url, fetchImage) {
|
|
521
|
+
const [result, setResult] = useState({});
|
|
522
|
+
const fetcher = useRef2(fetchImage);
|
|
523
|
+
fetcher.current = fetchImage;
|
|
524
|
+
useEffect(() => {
|
|
525
|
+
if (!url || !fetcher.current) return;
|
|
526
|
+
let live = true;
|
|
527
|
+
fetcher.current(url).then(
|
|
528
|
+
(src) => {
|
|
529
|
+
if (live) setResult({ for: url, src });
|
|
530
|
+
},
|
|
531
|
+
() => {
|
|
532
|
+
if (live) setResult({ for: url, failed: true });
|
|
533
|
+
}
|
|
534
|
+
);
|
|
535
|
+
return () => {
|
|
536
|
+
live = false;
|
|
537
|
+
};
|
|
538
|
+
}, [url]);
|
|
539
|
+
const current = result.for === url;
|
|
540
|
+
return { src: current ? result.src : void 0, failed: current ? !!result.failed : false };
|
|
541
|
+
}
|
|
542
|
+
async function saveFile(source, name) {
|
|
543
|
+
if (source.startsWith("blob:") || source.startsWith("data:")) {
|
|
544
|
+
handToAnchor(source, name);
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
try {
|
|
548
|
+
const res = await fetch(source);
|
|
549
|
+
if (!res.ok) throw new Error(String(res.status));
|
|
550
|
+
const objectUrl = URL.createObjectURL(await res.blob());
|
|
551
|
+
handToAnchor(objectUrl, name);
|
|
552
|
+
URL.revokeObjectURL(objectUrl);
|
|
553
|
+
} catch {
|
|
554
|
+
window.open(source, "_blank", "noopener");
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
function handToAnchor(url, name) {
|
|
558
|
+
const a = document.createElement("a");
|
|
559
|
+
a.href = url;
|
|
560
|
+
a.download = name;
|
|
561
|
+
document.body.appendChild(a);
|
|
562
|
+
a.click();
|
|
563
|
+
a.remove();
|
|
469
564
|
}
|
|
470
565
|
function AttachmentCard({
|
|
471
566
|
name,
|
|
@@ -473,8 +568,13 @@ function AttachmentCard({
|
|
|
473
568
|
contentType,
|
|
474
569
|
href,
|
|
475
570
|
src,
|
|
571
|
+
alt,
|
|
572
|
+
remoteSrc,
|
|
573
|
+
remoteFullSrc,
|
|
574
|
+
fetchImage,
|
|
476
575
|
onOpen,
|
|
477
576
|
onDownload,
|
|
577
|
+
download = false,
|
|
478
578
|
pending = false,
|
|
479
579
|
onRemove,
|
|
480
580
|
state = "ready",
|
|
@@ -485,22 +585,48 @@ function AttachmentCard({
|
|
|
485
585
|
}) {
|
|
486
586
|
const image = isImage(name, contentType);
|
|
487
587
|
const sizeText = size === void 0 ? "" : formatBytes(size);
|
|
588
|
+
const remote = useRemoteImage(src ? void 0 : remoteSrc, fetchImage);
|
|
589
|
+
const picture = image ? src ?? remote.src : void 0;
|
|
590
|
+
const fetching = !src && !!remoteSrc && !!fetchImage;
|
|
591
|
+
const drawnState = state !== "ready" ? state : image && fetching ? remote.failed ? "unreadable" : picture ? "ready" : "loading" : state;
|
|
592
|
+
const address = href ?? (!image && fetching ? remote.src : void 0);
|
|
593
|
+
const [opened, setOpened] = useState(false);
|
|
594
|
+
const full = useRemoteImage(opened ? remoteFullSrc : void 0, fetchImage);
|
|
595
|
+
const openable = image && !!picture && !pending;
|
|
596
|
+
const openPicture = onOpen ?? (openable ? () => setOpened(true) : void 0);
|
|
597
|
+
const viewer = opened && picture ? /* @__PURE__ */ jsx10(Lightbox, { src: full.src ?? picture, alt: alt ?? name, onClose: () => setOpened(false) }) : null;
|
|
598
|
+
const saveHere = download ? () => {
|
|
599
|
+
const source = remoteFullSrc ?? remoteSrc;
|
|
600
|
+
if (source && fetchImage) {
|
|
601
|
+
void fetchImage(source).then(
|
|
602
|
+
(resolved) => saveFile(resolved, name),
|
|
603
|
+
// Without this a refused read is an unhandled rejection in the page
|
|
604
|
+
// rather than a download that did not happen.
|
|
605
|
+
() => {
|
|
606
|
+
}
|
|
607
|
+
);
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
const local = address ?? picture;
|
|
611
|
+
if (local) void saveFile(local, name);
|
|
612
|
+
} : void 0;
|
|
613
|
+
const saving = onDownload ?? saveHere;
|
|
488
614
|
if (pending) {
|
|
489
615
|
const failed = state === "failed";
|
|
490
616
|
const warning = state === "warning";
|
|
491
617
|
return (
|
|
492
618
|
// @estiva-escape: a failed or warning file's strong hairline is AttachmentCard's own state; Card's attention hairlines are the soft ones (UIG-9, Katerina 17 September)
|
|
493
|
-
/* @__PURE__ */
|
|
619
|
+
/* @__PURE__ */ jsxs6(
|
|
494
620
|
Card,
|
|
495
621
|
{
|
|
496
622
|
fill: "elevated",
|
|
497
623
|
className: cn("group relative flex items-center gap-2 w-[200px] p-1.5 pr-3", failed ? "border-error-default" : warning && "border-warning-default", className),
|
|
498
624
|
...props,
|
|
499
625
|
children: [
|
|
500
|
-
/* @__PURE__ */
|
|
501
|
-
/* @__PURE__ */
|
|
502
|
-
/* @__PURE__ */
|
|
503
|
-
/* @__PURE__ */
|
|
626
|
+
/* @__PURE__ */ jsx10("div", { className: cn(TILE_CLASSES, "overflow-hidden"), children: state === "uploading" ? /* @__PURE__ */ jsx10(IconLoader2, { size: 16, stroke: 1.5, className: "animate-spin" }) : failed ? /* @__PURE__ */ jsx10(IconAlertCircle, { size: 16, stroke: 1.5, className: "text-error-default" }) : warning ? /* @__PURE__ */ jsx10(IconAlertTriangle, { size: 16, stroke: 1.5, className: "text-warning-default" }) : image && src ? /* @__PURE__ */ jsx10("img", { src, alt: name, className: "size-full object-cover" }) : /* @__PURE__ */ jsx10("span", { className: "text-menu font-semibold", children: typeLabelOf(name) }) }),
|
|
627
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-[1px] min-w-0", children: [
|
|
628
|
+
/* @__PURE__ */ jsx10(Truncating, { text: name, className: NAME_CLASSES, placement: onRemove ? "bottom" : void 0 }),
|
|
629
|
+
/* @__PURE__ */ jsx10(
|
|
504
630
|
Truncating,
|
|
505
631
|
{
|
|
506
632
|
text: (failed || warning ? note : state === "uploading" ? note ?? "Uploading\u2026" : note ?? sizeText) ?? "",
|
|
@@ -509,7 +635,7 @@ function AttachmentCard({
|
|
|
509
635
|
}
|
|
510
636
|
)
|
|
511
637
|
] }),
|
|
512
|
-
onRemove && /* @__PURE__ */
|
|
638
|
+
onRemove && /* @__PURE__ */ jsx10(
|
|
513
639
|
BaseButton2,
|
|
514
640
|
{
|
|
515
641
|
type: "button",
|
|
@@ -519,7 +645,7 @@ function AttachmentCard({
|
|
|
519
645
|
event.stopPropagation();
|
|
520
646
|
onRemove();
|
|
521
647
|
},
|
|
522
|
-
children: /* @__PURE__ */
|
|
648
|
+
children: /* @__PURE__ */ jsx10(IconX2, { size: 11, stroke: 1.75 })
|
|
523
649
|
}
|
|
524
650
|
)
|
|
525
651
|
]
|
|
@@ -527,9 +653,9 @@ function AttachmentCard({
|
|
|
527
653
|
)
|
|
528
654
|
);
|
|
529
655
|
}
|
|
530
|
-
const
|
|
656
|
+
const downloadControl = saving ? (
|
|
531
657
|
// @estiva-escape: Download shows when its card is pointed at or focused, AttachmentCard's own action; IconButton has no reveal on its card's hover (UIG-9, Katerina 17 September)
|
|
532
|
-
/* @__PURE__ */
|
|
658
|
+
/* @__PURE__ */ jsx10(
|
|
533
659
|
IconButton,
|
|
534
660
|
{
|
|
535
661
|
variant: "muted",
|
|
@@ -538,66 +664,69 @@ function AttachmentCard({
|
|
|
538
664
|
className: "opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100 transition-opacity",
|
|
539
665
|
onClick: (event) => {
|
|
540
666
|
event.stopPropagation();
|
|
541
|
-
|
|
667
|
+
saving();
|
|
542
668
|
},
|
|
543
|
-
children: /* @__PURE__ */
|
|
669
|
+
children: /* @__PURE__ */ jsx10(IconDownload, { size: 16, stroke: 1.5 })
|
|
544
670
|
}
|
|
545
671
|
)
|
|
546
672
|
) : null;
|
|
547
|
-
if (
|
|
673
|
+
if (drawnState === "loading") {
|
|
548
674
|
return (
|
|
549
675
|
// `role="status"`: a plain box may not carry a name (axe, aria-prohibited-attr), and a
|
|
550
676
|
// status says what it is doing — loading — to a reader that cannot see the pulse.
|
|
551
677
|
// @estiva-escape: the loading pulse is AttachmentCard's own state; Card has no loading state (UIG-9, Katerina 17 September)
|
|
552
|
-
/* @__PURE__ */
|
|
678
|
+
/* @__PURE__ */ jsx10(Card, { role: "status", fill: "inset", "aria-busy": "true", "aria-label": `Loading ${name}`, className: cn("w-[180px] h-28 animate-pulse", className), ...props, children: null })
|
|
553
679
|
);
|
|
554
680
|
}
|
|
555
|
-
if (
|
|
681
|
+
if (drawnState === "unreadable") {
|
|
556
682
|
return (
|
|
557
683
|
// @estiva-escape: a file that could not be read is faded as well as dashed, AttachmentCard's own state; Card has no faded state (UIG-9, Katerina 17 September)
|
|
558
|
-
/* @__PURE__ */
|
|
559
|
-
/* @__PURE__ */
|
|
560
|
-
/* @__PURE__ */
|
|
561
|
-
/* @__PURE__ */
|
|
562
|
-
/* @__PURE__ */
|
|
684
|
+
/* @__PURE__ */ jsxs6(Card, { fill: "inset", unreadable: true, className: cn("flex items-center gap-2 w-[240px] p-1.5 opacity-70", className), ...props, children: [
|
|
685
|
+
/* @__PURE__ */ jsx10("div", { className: TILE_CLASSES, children: /* @__PURE__ */ jsx10(TypeIcon, { name }) }),
|
|
686
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-[1px] min-w-0 text-left", children: [
|
|
687
|
+
/* @__PURE__ */ jsx10(Truncating, { text: name, className: NAME_CLASSES }),
|
|
688
|
+
/* @__PURE__ */ jsx10("span", { className: cn(NOTE_CLASSES, "text-text-secondary"), children: note ?? "Could not be loaded" })
|
|
563
689
|
] })
|
|
564
690
|
] })
|
|
565
691
|
);
|
|
566
692
|
}
|
|
567
|
-
if (image &&
|
|
568
|
-
const
|
|
569
|
-
return /* @__PURE__ */
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
event
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
/* @__PURE__ */
|
|
585
|
-
|
|
586
|
-
|
|
693
|
+
if (image && picture) {
|
|
694
|
+
const thumbnail = /* @__PURE__ */ jsx10("img", { src: picture, alt: alt ?? name, className: "w-full h-28 object-cover" });
|
|
695
|
+
return /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
696
|
+
/* @__PURE__ */ jsxs6(Card, { fill: "inset", hover: "hairline", clip: true, className: cn("group relative flex flex-col w-[180px]", className), ...props, children: [
|
|
697
|
+
openPicture ? /* @__PURE__ */ jsx10(
|
|
698
|
+
BaseButton2,
|
|
699
|
+
{
|
|
700
|
+
type: "button",
|
|
701
|
+
className: "block w-full",
|
|
702
|
+
"aria-label": `Preview ${name}`,
|
|
703
|
+
onClick: (event) => {
|
|
704
|
+
event.stopPropagation();
|
|
705
|
+
openPicture();
|
|
706
|
+
},
|
|
707
|
+
children: thumbnail
|
|
708
|
+
}
|
|
709
|
+
) : /* @__PURE__ */ jsx10("div", { className: "block w-full", children: thumbnail }),
|
|
710
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1 pl-2 pr-1 py-1 min-w-0", children: [
|
|
711
|
+
/* @__PURE__ */ jsx10(Truncating, { text: name, className: "flex-1 text-caption text-text-primary truncate", wrapperClassName: "flex-1" }),
|
|
712
|
+
downloadControl
|
|
713
|
+
] })
|
|
714
|
+
] }),
|
|
715
|
+
viewer
|
|
587
716
|
] });
|
|
588
717
|
}
|
|
589
|
-
const body = /* @__PURE__ */
|
|
590
|
-
/* @__PURE__ */
|
|
591
|
-
/* @__PURE__ */
|
|
592
|
-
/* @__PURE__ */
|
|
593
|
-
/* @__PURE__ */
|
|
718
|
+
const body = /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
719
|
+
/* @__PURE__ */ jsx10("div", { className: TILE_CLASSES, children: /* @__PURE__ */ jsx10(TypeIcon, { name }) }),
|
|
720
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-[1px] min-w-0 text-left", children: [
|
|
721
|
+
/* @__PURE__ */ jsx10(Truncating, { text: name, className: NAME_CLASSES }),
|
|
722
|
+
/* @__PURE__ */ jsx10("span", { className: cn(NOTE_CLASSES, "text-text-secondary"), children: note ?? `${typeLabelOf(name)} \xB7 ${sizeText}` })
|
|
594
723
|
] })
|
|
595
724
|
] });
|
|
596
725
|
return (
|
|
597
726
|
// @estiva-escape: a file that cannot be opened is faded, AttachmentCard's own state; Card has no faded state (UIG-9, Katerina 17 September)
|
|
598
|
-
/* @__PURE__ */
|
|
599
|
-
|
|
600
|
-
|
|
727
|
+
/* @__PURE__ */ jsxs6(Card, { fill: "inset", hover: address ? "hairline" : "none", className: cn("group flex items-center gap-2 w-[240px] p-1.5 pr-1", !address && "opacity-70", className), ...props, children: [
|
|
728
|
+
address ? /* @__PURE__ */ jsx10(Link, { href: address, external: true, variant: "plain", className: "flex items-center gap-2 min-w-0 flex-1", onClick: (event) => event.stopPropagation(), children: body }) : /* @__PURE__ */ jsx10("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: body }),
|
|
729
|
+
downloadControl
|
|
601
730
|
] })
|
|
602
731
|
);
|
|
603
732
|
}
|
|
@@ -605,7 +734,7 @@ function AttachmentCard({
|
|
|
605
734
|
// src/Avatar.tsx
|
|
606
735
|
import { Avatar as BaseAvatar } from "@base-ui/react/avatar";
|
|
607
736
|
import { IconUserFilled } from "@tabler/icons-react";
|
|
608
|
-
import { jsx as
|
|
737
|
+
import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
609
738
|
var HUES = ["#56c8ff", "#ff8f6b", "#4ade8c", "#b18cff", "#ffc94d", "#ff7eb0", "#7ea8ff", "#5fdfd6"];
|
|
610
739
|
var hueFor = (key) => {
|
|
611
740
|
let h = 0;
|
|
@@ -619,15 +748,15 @@ var initialsFor = (name) => {
|
|
|
619
748
|
};
|
|
620
749
|
function Avatar({ src, name, alt = "", size = 36, label: spoken, className }) {
|
|
621
750
|
const label = name || alt;
|
|
622
|
-
return /* @__PURE__ */
|
|
751
|
+
return /* @__PURE__ */ jsxs7(
|
|
623
752
|
BaseAvatar.Root,
|
|
624
753
|
{
|
|
625
|
-
render: /* @__PURE__ */
|
|
754
|
+
render: /* @__PURE__ */ jsx11("div", {}),
|
|
626
755
|
...spoken ? { role: "img", "aria-label": spoken } : { "aria-hidden": true },
|
|
627
756
|
className: cn("rounded-sm overflow-hidden shrink-0 bg-bg-inset", className),
|
|
628
757
|
style: { width: size, height: size },
|
|
629
758
|
children: [
|
|
630
|
-
src && /* @__PURE__ */
|
|
759
|
+
src && /* @__PURE__ */ jsx11(
|
|
631
760
|
BaseAvatar.Image,
|
|
632
761
|
{
|
|
633
762
|
src,
|
|
@@ -636,10 +765,10 @@ function Avatar({ src, name, alt = "", size = 36, label: spoken, className }) {
|
|
|
636
765
|
className: "w-full h-full object-cover data-[error]:hidden"
|
|
637
766
|
}
|
|
638
767
|
),
|
|
639
|
-
label ? /* @__PURE__ */
|
|
768
|
+
label ? /* @__PURE__ */ jsx11(
|
|
640
769
|
BaseAvatar.Fallback,
|
|
641
770
|
{
|
|
642
|
-
render: /* @__PURE__ */
|
|
771
|
+
render: /* @__PURE__ */ jsx11("div", {}),
|
|
643
772
|
className: "w-full h-full flex items-center justify-center font-semibold leading-none",
|
|
644
773
|
style: {
|
|
645
774
|
/* eslint-disable no-restricted-syntax -- @estiva-escape: the per-person palette (the note at
|
|
@@ -653,32 +782,32 @@ function Avatar({ src, name, alt = "", size = 36, label: spoken, className }) {
|
|
|
653
782
|
background: `linear-gradient(160deg, color-mix(in srgb, ${hueFor(label)} 92%, #fff) 0%, color-mix(in srgb, ${hueFor(label)} 70%, #0b0d11) 100%)`
|
|
654
783
|
/* eslint-enable no-restricted-syntax */
|
|
655
784
|
},
|
|
656
|
-
children: /* @__PURE__ */
|
|
785
|
+
children: /* @__PURE__ */ jsx11("span", { className: "[text-box:trim-both_cap_alphabetic]", children: initialsFor(label) })
|
|
657
786
|
}
|
|
658
|
-
) : /* @__PURE__ */
|
|
787
|
+
) : /* @__PURE__ */ jsx11(BaseAvatar.Fallback, { render: /* @__PURE__ */ jsx11("div", {}), className: "w-full h-full bg-accent-muted flex items-center justify-center text-text-muted", children: /* @__PURE__ */ jsx11(IconUserFilled, { size: Math.round(size * 0.5) }) })
|
|
659
788
|
]
|
|
660
789
|
}
|
|
661
790
|
);
|
|
662
791
|
}
|
|
663
792
|
|
|
664
793
|
// src/AvatarGroup.tsx
|
|
665
|
-
import { jsx as
|
|
794
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
666
795
|
function AvatarGroup({ members, size = 24 }) {
|
|
667
796
|
const visible = members.slice(0, 3);
|
|
668
797
|
const overlap = Math.round(size / 3);
|
|
669
798
|
const ring = size / 12;
|
|
670
|
-
return /* @__PURE__ */
|
|
799
|
+
return /* @__PURE__ */ jsx12("div", { className: "flex items-center", style: { paddingRight: overlap }, children: visible.map((member, i) => (
|
|
671
800
|
/*
|
|
672
801
|
The wrapper carries the overlap and the ring; the face carries
|
|
673
802
|
neither. It must never clip — see the note at the top of the file —
|
|
674
803
|
so it has the avatar's own radius and no overflow of its own.
|
|
675
804
|
*/
|
|
676
|
-
/* @__PURE__ */
|
|
805
|
+
/* @__PURE__ */ jsx12(
|
|
677
806
|
"span",
|
|
678
807
|
{
|
|
679
808
|
className: "relative flex rounded-sm",
|
|
680
809
|
style: { marginRight: -overlap, boxShadow: `0 0 0 ${ring}px var(--bg-surface)` },
|
|
681
|
-
children: /* @__PURE__ */
|
|
810
|
+
children: /* @__PURE__ */ jsx12(Avatar, { size, name: member.name, src: member.picture, label: member.name })
|
|
682
811
|
},
|
|
683
812
|
i
|
|
684
813
|
)
|
|
@@ -686,11 +815,11 @@ function AvatarGroup({ members, size = 24 }) {
|
|
|
686
815
|
}
|
|
687
816
|
|
|
688
817
|
// src/Banner.tsx
|
|
689
|
-
import { IconX as
|
|
818
|
+
import { IconX as IconX3 } from "@tabler/icons-react";
|
|
690
819
|
|
|
691
820
|
// src/Button.tsx
|
|
692
821
|
import { Button as BaseButton3 } from "@base-ui/react/button";
|
|
693
|
-
import { jsx as
|
|
822
|
+
import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
694
823
|
function Button({
|
|
695
824
|
variant = "muted",
|
|
696
825
|
size = "default",
|
|
@@ -704,7 +833,7 @@ function Button({
|
|
|
704
833
|
}) {
|
|
705
834
|
const hasLeadingIcon = !!leadingIcon;
|
|
706
835
|
const formBusy = useFormBusy();
|
|
707
|
-
const button = /* @__PURE__ */
|
|
836
|
+
const button = /* @__PURE__ */ jsxs8(
|
|
708
837
|
BaseButton3,
|
|
709
838
|
{
|
|
710
839
|
type,
|
|
@@ -751,11 +880,11 @@ function Button({
|
|
|
751
880
|
]
|
|
752
881
|
}
|
|
753
882
|
);
|
|
754
|
-
return disabledReason ? /* @__PURE__ */
|
|
883
|
+
return disabledReason ? /* @__PURE__ */ jsx13(TooltipTrigger, { label: disabledReason, children: button }) : button;
|
|
755
884
|
}
|
|
756
885
|
|
|
757
886
|
// src/Banner.tsx
|
|
758
|
-
import { jsx as
|
|
887
|
+
import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
759
888
|
var TONE_STYLES = {
|
|
760
889
|
ok: "bg-success-muted text-success-default",
|
|
761
890
|
error: "bg-error-muted text-error-default",
|
|
@@ -765,14 +894,14 @@ var TONE_STYLES = {
|
|
|
765
894
|
function Banner({ tone, children, icon, action, onDismiss, dismissLabel = "Dismiss", className }) {
|
|
766
895
|
const role = tone === "error" ? "alert" : "status";
|
|
767
896
|
if (!onDismiss && !icon && !action) {
|
|
768
|
-
return /* @__PURE__ */
|
|
897
|
+
return /* @__PURE__ */ jsx14("div", { role, className: cn("px-4 py-2 text-body-2", TONE_STYLES[tone], className), children });
|
|
769
898
|
}
|
|
770
899
|
const oneLine = Boolean(icon || action);
|
|
771
|
-
return /* @__PURE__ */
|
|
772
|
-
icon && /* @__PURE__ */
|
|
773
|
-
/* @__PURE__ */
|
|
774
|
-
action && /* @__PURE__ */
|
|
775
|
-
onDismiss && /* @__PURE__ */
|
|
900
|
+
return /* @__PURE__ */ jsxs9("div", { role, className: cn("flex items-center gap-3 px-4 py-2 text-body-2", TONE_STYLES[tone], className), children: [
|
|
901
|
+
icon && /* @__PURE__ */ jsx14("span", { className: "flex shrink-0", children: icon }),
|
|
902
|
+
/* @__PURE__ */ jsx14("span", { className: cn("min-w-0 flex-1", oneLine && "truncate"), children }),
|
|
903
|
+
action && /* @__PURE__ */ jsx14(Button, { variant: "muted", size: "small", className: "shrink-0", onClick: action.onClick, children: action.label }),
|
|
904
|
+
onDismiss && /* @__PURE__ */ jsx14(IconButton, { variant: "current", "aria-label": dismissLabel, onClick: onDismiss, className: "-mr-1 shrink-0", children: /* @__PURE__ */ jsx14(IconX3, { size: 16, stroke: 1.5 }) })
|
|
776
905
|
] });
|
|
777
906
|
}
|
|
778
907
|
|
|
@@ -780,7 +909,7 @@ function Banner({ tone, children, icon, action, onDismiss, dismissLabel = "Dismi
|
|
|
780
909
|
import { Checkbox as BaseCheckbox } from "@base-ui/react/checkbox";
|
|
781
910
|
import { Field as BaseField } from "@base-ui/react/field";
|
|
782
911
|
import { IconCheck } from "@tabler/icons-react";
|
|
783
|
-
import { jsx as
|
|
912
|
+
import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
784
913
|
function squareClasses(checked, disabled, interactive, className) {
|
|
785
914
|
return cn(
|
|
786
915
|
"inline-flex items-center justify-center size-4 shrink-0 rounded-sm border transition-colors",
|
|
@@ -797,14 +926,14 @@ function Checkbox({ checked, onChange, disabled: ownDisabled = false, label, row
|
|
|
797
926
|
const formBusy = useFormBusy();
|
|
798
927
|
const disabled = ownDisabled || formBusy;
|
|
799
928
|
if (!onChange) {
|
|
800
|
-
const picture = /* @__PURE__ */
|
|
929
|
+
const picture = /* @__PURE__ */ jsx15("span", { "aria-hidden": "true", className: squareClasses(checked, disabled, false, className), children: /* @__PURE__ */ jsx15("span", { className: tickClasses(checked), children: /* @__PURE__ */ jsx15(IconCheck, { size: 12, stroke: 3 }) }) });
|
|
801
930
|
if (label === void 0) return picture;
|
|
802
|
-
return /* @__PURE__ */
|
|
931
|
+
return /* @__PURE__ */ jsxs10("span", { className: "flex items-center gap-2", children: [
|
|
803
932
|
picture,
|
|
804
|
-
/* @__PURE__ */
|
|
933
|
+
/* @__PURE__ */ jsx15("span", { className: WORDS_CLASSES, children: label })
|
|
805
934
|
] });
|
|
806
935
|
}
|
|
807
|
-
const box = /* @__PURE__ */
|
|
936
|
+
const box = /* @__PURE__ */ jsx15(
|
|
808
937
|
BaseCheckbox.Root,
|
|
809
938
|
{
|
|
810
939
|
checked,
|
|
@@ -814,25 +943,25 @@ function Checkbox({ checked, onChange, disabled: ownDisabled = false, label, row
|
|
|
814
943
|
onCheckedChange: (next) => onChange(next),
|
|
815
944
|
onClick: (e) => e.stopPropagation(),
|
|
816
945
|
className: (state) => squareClasses(state.checked, state.disabled, true, className),
|
|
817
|
-
children: /* @__PURE__ */
|
|
946
|
+
children: /* @__PURE__ */ jsx15(BaseCheckbox.Indicator, { keepMounted: true, className: (state) => tickClasses(state.checked), children: /* @__PURE__ */ jsx15(IconCheck, { size: 12, stroke: 3 }) })
|
|
818
947
|
}
|
|
819
948
|
);
|
|
820
949
|
if (label === void 0) return box;
|
|
821
950
|
if (row) {
|
|
822
|
-
return /* @__PURE__ */
|
|
951
|
+
return /* @__PURE__ */ jsx15(BaseField.Root, { disabled, children: /* @__PURE__ */ jsxs10(BaseField.Label, { className: cn(ROW_CLASSES, checked && "bg-bg-selected", !disabled && "cursor-pointer hover:bg-bg-hover"), children: [
|
|
823
952
|
leading,
|
|
824
|
-
/* @__PURE__ */
|
|
953
|
+
/* @__PURE__ */ jsx15("span", { className: cn("flex-1 min-w-0 truncate", WORDS_CLASSES), children: label }),
|
|
825
954
|
box
|
|
826
955
|
] }) });
|
|
827
956
|
}
|
|
828
|
-
return /* @__PURE__ */
|
|
957
|
+
return /* @__PURE__ */ jsx15(BaseField.Root, { disabled, children: /* @__PURE__ */ jsxs10(BaseField.Label, { className: cn("flex items-center gap-2", !disabled && "cursor-pointer"), children: [
|
|
829
958
|
box,
|
|
830
|
-
/* @__PURE__ */
|
|
959
|
+
/* @__PURE__ */ jsx15("span", { className: WORDS_CLASSES, children: label })
|
|
831
960
|
] }) });
|
|
832
961
|
}
|
|
833
962
|
|
|
834
963
|
// src/Chip.tsx
|
|
835
|
-
import { jsx as
|
|
964
|
+
import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
836
965
|
var typeStyles = {
|
|
837
966
|
neutral: "bg-bg-inset text-text-primary",
|
|
838
967
|
brand: "bg-accent-muted text-accent-primary signal:border signal:border-accent-outline",
|
|
@@ -842,8 +971,8 @@ var typeStyles = {
|
|
|
842
971
|
error: "bg-error-muted text-error-default signal:border signal:border-error-outline"
|
|
843
972
|
};
|
|
844
973
|
function Chip({ type = "neutral", label, leadingIcon, trailingIcon, className }) {
|
|
845
|
-
return /* @__PURE__ */
|
|
846
|
-
leadingIcon && /* @__PURE__ */
|
|
974
|
+
return /* @__PURE__ */ jsxs11("div", { className: cn("inline-flex min-w-0 items-center justify-center gap-1.5 rounded-full max-h-[20px] px-2 py-1", typeStyles[type], className), children: [
|
|
975
|
+
leadingIcon && /* @__PURE__ */ jsx16("span", { className: "flex size-3 shrink-0 items-center justify-center", children: leadingIcon }),
|
|
847
976
|
label && // A chip given a `max-w-*` cuts a long label with an ellipsis instead
|
|
848
977
|
// of growing past it — Ship's project chip on an issue row
|
|
849
978
|
// (2026-09-09). Clipped sideways only: `overflow-x-clip`, not
|
|
@@ -852,8 +981,8 @@ function Chip({ type = "neutral", label, leadingIcon, trailingIcon, className })
|
|
|
852
981
|
// the screenshot diff caught every descender cut off. `clip` is the
|
|
853
982
|
// one overflow that leaves the other axis visible. A chip with no cap
|
|
854
983
|
// draws exactly as before.
|
|
855
|
-
/* @__PURE__ */
|
|
856
|
-
trailingIcon && /* @__PURE__ */
|
|
984
|
+
/* @__PURE__ */ jsx16("span", { className: "min-w-0 overflow-x-clip text-ellipsis whitespace-nowrap text-chip signal:font-mono signal:text-small signal:font-semibold signal:tracking-wide signal:tabular-nums", children: label }),
|
|
985
|
+
trailingIcon && /* @__PURE__ */ jsx16("span", { className: "flex size-3 shrink-0 items-center justify-center", children: trailingIcon })
|
|
857
986
|
] });
|
|
858
987
|
}
|
|
859
988
|
|
|
@@ -861,13 +990,13 @@ function Chip({ type = "neutral", label, leadingIcon, trailingIcon, className })
|
|
|
861
990
|
import {
|
|
862
991
|
createContext as createContext4,
|
|
863
992
|
useContext as useContext4,
|
|
864
|
-
useEffect,
|
|
993
|
+
useEffect as useEffect2,
|
|
865
994
|
useLayoutEffect as useLayoutEffect3,
|
|
866
995
|
useMemo as useMemo2,
|
|
867
|
-
useRef as
|
|
996
|
+
useRef as useRef4,
|
|
868
997
|
useState as useState3
|
|
869
998
|
} from "react";
|
|
870
|
-
import { Dialog } from "@base-ui/react/dialog";
|
|
999
|
+
import { Dialog as Dialog2 } from "@base-ui/react/dialog";
|
|
871
1000
|
import { Autocomplete } from "@base-ui/react/autocomplete";
|
|
872
1001
|
import { IconLoader2 as IconLoader22, IconSearch } from "@tabler/icons-react";
|
|
873
1002
|
|
|
@@ -875,7 +1004,7 @@ import { IconLoader2 as IconLoader22, IconSearch } from "@tabler/icons-react";
|
|
|
875
1004
|
import { useMemo, useState as useState2 } from "react";
|
|
876
1005
|
import { Button as BaseButton4 } from "@base-ui/react/button";
|
|
877
1006
|
import { Combobox } from "@base-ui/react/combobox";
|
|
878
|
-
import { IconX as
|
|
1007
|
+
import { IconX as IconX4 } from "@tabler/icons-react";
|
|
879
1008
|
|
|
880
1009
|
// src/Menu.tsx
|
|
881
1010
|
import { createContext as createContext3, useContext as useContext3 } from "react";
|
|
@@ -885,27 +1014,27 @@ import { Menu as BaseMenu } from "@base-ui/react/menu";
|
|
|
885
1014
|
// src/Divider.tsx
|
|
886
1015
|
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
887
1016
|
import { Separator } from "@base-ui/react/separator";
|
|
888
|
-
import { jsx as
|
|
1017
|
+
import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
889
1018
|
var DividerInPanel = createContext2(false);
|
|
890
1019
|
function Divider({ orientation = "horizontal", label, tone = "default", className }) {
|
|
891
1020
|
const inset = useContext2(DividerInPanel) ? "mx-0" : "mx-3";
|
|
892
1021
|
if (label && orientation === "horizontal") {
|
|
893
1022
|
const line = tone === "warning" ? "bg-warning-muted" : "bg-border-subtle";
|
|
894
|
-
return /* @__PURE__ */
|
|
1023
|
+
return /* @__PURE__ */ jsxs12(
|
|
895
1024
|
Separator,
|
|
896
1025
|
{
|
|
897
1026
|
orientation: "horizontal",
|
|
898
1027
|
"aria-label": label,
|
|
899
1028
|
className: cn("flex shrink-0 items-center gap-2", inset, className),
|
|
900
1029
|
children: [
|
|
901
|
-
/* @__PURE__ */
|
|
902
|
-
/* @__PURE__ */
|
|
903
|
-
/* @__PURE__ */
|
|
1030
|
+
/* @__PURE__ */ jsx17("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
|
|
1031
|
+
/* @__PURE__ */ jsx17("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
|
|
1032
|
+
/* @__PURE__ */ jsx17("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
|
|
904
1033
|
]
|
|
905
1034
|
}
|
|
906
1035
|
);
|
|
907
1036
|
}
|
|
908
|
-
return /* @__PURE__ */
|
|
1037
|
+
return /* @__PURE__ */ jsx17(
|
|
909
1038
|
Separator,
|
|
910
1039
|
{
|
|
911
1040
|
orientation,
|
|
@@ -921,9 +1050,9 @@ function triggerDisabled(trigger) {
|
|
|
921
1050
|
}
|
|
922
1051
|
|
|
923
1052
|
// src/SectionLabel.tsx
|
|
924
|
-
import { jsx as
|
|
1053
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
925
1054
|
function SectionLabel({ children, tone = "primary", className }) {
|
|
926
|
-
return /* @__PURE__ */
|
|
1055
|
+
return /* @__PURE__ */ jsx18(
|
|
927
1056
|
"span",
|
|
928
1057
|
{
|
|
929
1058
|
className: cn(
|
|
@@ -937,10 +1066,10 @@ function SectionLabel({ children, tone = "primary", className }) {
|
|
|
937
1066
|
}
|
|
938
1067
|
|
|
939
1068
|
// src/Menu.tsx
|
|
940
|
-
import { Fragment as Fragment2, jsx as
|
|
1069
|
+
import { Fragment as Fragment2, jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
941
1070
|
var MenuContext = createContext3(null);
|
|
942
1071
|
function MenuPanel({ children, className, ...props }) {
|
|
943
|
-
return /* @__PURE__ */
|
|
1072
|
+
return /* @__PURE__ */ jsx19(
|
|
944
1073
|
"div",
|
|
945
1074
|
{
|
|
946
1075
|
className: cn(
|
|
@@ -970,7 +1099,7 @@ var VIEWPORT_PAD2 = 8;
|
|
|
970
1099
|
var HOVER_OPEN_DELAY = 0;
|
|
971
1100
|
var HOVER_CLOSE_DELAY = 150;
|
|
972
1101
|
function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange, actionsRef, children, className, contentClassName }) {
|
|
973
|
-
return /* @__PURE__ */
|
|
1102
|
+
return /* @__PURE__ */ jsxs13(
|
|
974
1103
|
BaseMenu.Root,
|
|
975
1104
|
{
|
|
976
1105
|
open,
|
|
@@ -978,7 +1107,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
978
1107
|
actionsRef,
|
|
979
1108
|
modal: false,
|
|
980
1109
|
children: [
|
|
981
|
-
/* @__PURE__ */
|
|
1110
|
+
/* @__PURE__ */ jsx19(
|
|
982
1111
|
BaseMenu.Trigger,
|
|
983
1112
|
{
|
|
984
1113
|
render: trigger,
|
|
@@ -988,7 +1117,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
988
1117
|
closeDelay: HOVER_CLOSE_DELAY
|
|
989
1118
|
}
|
|
990
1119
|
),
|
|
991
|
-
/* @__PURE__ */
|
|
1120
|
+
/* @__PURE__ */ jsx19(BaseMenu.Portal, { children: /* @__PURE__ */ jsx19(
|
|
992
1121
|
BaseMenu.Positioner,
|
|
993
1122
|
{
|
|
994
1123
|
side: "bottom",
|
|
@@ -996,13 +1125,13 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
996
1125
|
sideOffset: GAP2,
|
|
997
1126
|
collisionPadding: VIEWPORT_PAD2,
|
|
998
1127
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
999
|
-
children: /* @__PURE__ */
|
|
1128
|
+
children: /* @__PURE__ */ jsx19(
|
|
1000
1129
|
BaseMenu.Popup,
|
|
1001
1130
|
{
|
|
1002
1131
|
"data-interactive": true,
|
|
1003
1132
|
className: cn("min-w-[180px] outline-none p-0", className),
|
|
1004
|
-
render: /* @__PURE__ */
|
|
1005
|
-
children: /* @__PURE__ */
|
|
1133
|
+
render: /* @__PURE__ */ jsx19(MenuPanel, {}),
|
|
1134
|
+
children: /* @__PURE__ */ jsx19(ScrollArea, { viewportClassName: "max-h-[var(--available-height)]", contentClassName: cn("flex flex-col p-2", contentClassName), children: /* @__PURE__ */ jsx19(MenuContext.Provider, { value: { openOnHover }, children: /* @__PURE__ */ jsx19(DividerInPanel.Provider, { value: true, children }) }) })
|
|
1006
1135
|
}
|
|
1007
1136
|
)
|
|
1008
1137
|
}
|
|
@@ -1018,20 +1147,20 @@ function MenuSub({ label, leading, selected, children, className }) {
|
|
|
1018
1147
|
'[@estiva-app/ui] Menu: `openOnHover` and `MenuSub` cannot be used together \u2014 leaving the submenu panel strands the menu open. Open this menu on a press instead. See Menu.mdx, "Hover-opened menus".'
|
|
1019
1148
|
);
|
|
1020
1149
|
}
|
|
1021
|
-
return /* @__PURE__ */
|
|
1022
|
-
/* @__PURE__ */
|
|
1150
|
+
return /* @__PURE__ */ jsxs13(BaseMenu.SubmenuRoot, { children: [
|
|
1151
|
+
/* @__PURE__ */ jsx19(
|
|
1023
1152
|
BaseMenu.SubmenuTrigger,
|
|
1024
1153
|
{
|
|
1025
1154
|
openOnHover: true,
|
|
1026
1155
|
delay: 0,
|
|
1027
1156
|
closeDelay: 150,
|
|
1028
1157
|
nativeButton: true,
|
|
1029
|
-
render: /* @__PURE__ */
|
|
1158
|
+
render: /* @__PURE__ */ jsx19("button", { type: "button" }),
|
|
1030
1159
|
className: menuItemClassName({ size: "default", selected }),
|
|
1031
|
-
children: /* @__PURE__ */
|
|
1160
|
+
children: /* @__PURE__ */ jsx19(MenuItemBody, { label, leading, submenu: true })
|
|
1032
1161
|
}
|
|
1033
1162
|
),
|
|
1034
|
-
/* @__PURE__ */
|
|
1163
|
+
/* @__PURE__ */ jsx19(BaseMenu.Portal, { children: /* @__PURE__ */ jsx19(
|
|
1035
1164
|
BaseMenu.Positioner,
|
|
1036
1165
|
{
|
|
1037
1166
|
side: "inline-end",
|
|
@@ -1039,7 +1168,7 @@ function MenuSub({ label, leading, selected, children, className }) {
|
|
|
1039
1168
|
sideOffset: GAP2,
|
|
1040
1169
|
collisionPadding: VIEWPORT_PAD2,
|
|
1041
1170
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
1042
|
-
children: /* @__PURE__ */
|
|
1171
|
+
children: /* @__PURE__ */ jsx19(BaseMenu.Popup, { className: cn("w-[160px]", className), "data-interactive": true, render: /* @__PURE__ */ jsx19(MenuPanel, {}), children })
|
|
1043
1172
|
}
|
|
1044
1173
|
) })
|
|
1045
1174
|
] });
|
|
@@ -1074,25 +1203,25 @@ function menuItemClassName({ size, selected, className }) {
|
|
|
1074
1203
|
);
|
|
1075
1204
|
}
|
|
1076
1205
|
function MenuItemBody({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected }) {
|
|
1077
|
-
const edge = trailing ?? (shortcut ? /* @__PURE__ */
|
|
1078
|
-
return /* @__PURE__ */
|
|
1079
|
-
leading && /* @__PURE__ */
|
|
1080
|
-
children ?? /* @__PURE__ */
|
|
1081
|
-
/* @__PURE__ */
|
|
1082
|
-
description && /* @__PURE__ */
|
|
1206
|
+
const edge = trailing ?? (shortcut ? /* @__PURE__ */ jsx19(Kbd, { children: shortcut }) : submenu ? /* @__PURE__ */ jsx19(IconChevronRight, { size: 16, stroke: 1.5, className: "shrink-0 text-text-muted" }) : null);
|
|
1207
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
1208
|
+
leading && /* @__PURE__ */ jsx19("span", { className: "flex shrink-0 items-center", children: leading }),
|
|
1209
|
+
children ?? /* @__PURE__ */ jsxs13("span", { className: cn("flex min-w-0 flex-1 flex-col", size === "tall" && "gap-[2px]"), children: [
|
|
1210
|
+
/* @__PURE__ */ jsx19("span", { className: cn("truncate text-body-2", destructive ? "text-error-default" : "text-text-primary"), children: label }),
|
|
1211
|
+
description && /* @__PURE__ */ jsx19("span", { className: "truncate text-caption text-text-secondary", children: description })
|
|
1083
1212
|
] }),
|
|
1084
1213
|
(edge || hint) && // One grid cell holding both, right-aligned: the slot is as wide as
|
|
1085
1214
|
// the wider of the two and never changes, so revealing the hint moves
|
|
1086
1215
|
// nothing. No transition here either — the hint switches on the same
|
|
1087
1216
|
// :hover / `selected` as the fill, in the same frame.
|
|
1088
|
-
/* @__PURE__ */
|
|
1089
|
-
edge && /* @__PURE__ */
|
|
1090
|
-
hint && /* @__PURE__ */
|
|
1217
|
+
/* @__PURE__ */ jsxs13("span", { className: "grid shrink-0 items-center justify-items-end [&>*]:col-start-1 [&>*]:row-start-1", children: [
|
|
1218
|
+
edge && /* @__PURE__ */ jsx19("span", { className: cn("flex items-center", hint && "group-hover:opacity-0 group-data-[highlighted]:opacity-0", hint && selected && "opacity-0"), children: edge }),
|
|
1219
|
+
hint && /* @__PURE__ */ jsx19("span", { className: cn("flex items-center opacity-0 group-hover:opacity-100 group-data-[highlighted]:opacity-100", selected && "opacity-100"), children: hint })
|
|
1091
1220
|
] })
|
|
1092
1221
|
] });
|
|
1093
1222
|
}
|
|
1094
1223
|
function MenuItem({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected, className, ...props }) {
|
|
1095
|
-
const body = /* @__PURE__ */
|
|
1224
|
+
const body = /* @__PURE__ */ jsx19(
|
|
1096
1225
|
MenuItemBody,
|
|
1097
1226
|
{
|
|
1098
1227
|
label,
|
|
@@ -1110,13 +1239,13 @@ function MenuItem({ label, children, size = "default", description, leading, tra
|
|
|
1110
1239
|
);
|
|
1111
1240
|
const rowClassName = menuItemClassName({ size, selected, className });
|
|
1112
1241
|
if (!useContext3(MenuContext)) {
|
|
1113
|
-
return /* @__PURE__ */
|
|
1242
|
+
return /* @__PURE__ */ jsx19("button", { type: "button", className: rowClassName, ...props, children: body });
|
|
1114
1243
|
}
|
|
1115
|
-
return /* @__PURE__ */
|
|
1244
|
+
return /* @__PURE__ */ jsx19(
|
|
1116
1245
|
BaseMenu.Item,
|
|
1117
1246
|
{
|
|
1118
1247
|
nativeButton: true,
|
|
1119
|
-
render: /* @__PURE__ */
|
|
1248
|
+
render: /* @__PURE__ */ jsx19("button", { type: "button" }),
|
|
1120
1249
|
className: rowClassName,
|
|
1121
1250
|
...props,
|
|
1122
1251
|
children: body
|
|
@@ -1124,31 +1253,34 @@ function MenuItem({ label, children, size = "default", description, leading, tra
|
|
|
1124
1253
|
);
|
|
1125
1254
|
}
|
|
1126
1255
|
function EnterHint({ target }) {
|
|
1127
|
-
return /* @__PURE__ */
|
|
1128
|
-
/* @__PURE__ */
|
|
1129
|
-
target && /* @__PURE__ */
|
|
1256
|
+
return /* @__PURE__ */ jsxs13("span", { className: "flex shrink-0 items-center gap-1.5 text-text-muted", children: [
|
|
1257
|
+
/* @__PURE__ */ jsx19(Kbd, { children: "\u21A9 Enter" }),
|
|
1258
|
+
target && /* @__PURE__ */ jsx19("span", { className: "text-menu signal:font-mono signal:text-small signal:tracking-wider", children: target })
|
|
1130
1259
|
] });
|
|
1131
1260
|
}
|
|
1132
1261
|
function MenuSection({ label, children, className }) {
|
|
1133
1262
|
const inMenu = useContext3(MenuContext) !== null;
|
|
1134
|
-
const heading = /* @__PURE__ */
|
|
1263
|
+
const heading = /* @__PURE__ */ jsx19("div", { className: cn("flex h-8 items-center px-2", className), children: /* @__PURE__ */ jsx19(SectionLabel, { tone: "secondary", children: label }) });
|
|
1135
1264
|
if (!inMenu) {
|
|
1136
|
-
return /* @__PURE__ */
|
|
1265
|
+
return /* @__PURE__ */ jsxs13("div", { className: "flex flex-col", children: [
|
|
1137
1266
|
heading,
|
|
1138
1267
|
children
|
|
1139
1268
|
] });
|
|
1140
1269
|
}
|
|
1141
|
-
return /* @__PURE__ */
|
|
1142
|
-
/* @__PURE__ */
|
|
1270
|
+
return /* @__PURE__ */ jsxs13(BaseMenu.Group, { className: "flex flex-col", children: [
|
|
1271
|
+
/* @__PURE__ */ jsx19(BaseMenu.GroupLabel, { render: heading }),
|
|
1143
1272
|
children
|
|
1144
1273
|
] });
|
|
1145
1274
|
}
|
|
1275
|
+
function MenuSeparator() {
|
|
1276
|
+
return /* @__PURE__ */ jsx19(Divider, { className: "my-1" });
|
|
1277
|
+
}
|
|
1146
1278
|
function MenuRow({ children, className }) {
|
|
1147
|
-
return /* @__PURE__ */
|
|
1279
|
+
return /* @__PURE__ */ jsx19("div", { className: cn("flex items-center gap-2 px-2 py-1.5", className), children });
|
|
1148
1280
|
}
|
|
1149
1281
|
|
|
1150
1282
|
// src/ChipInput.tsx
|
|
1151
|
-
import { jsx as
|
|
1283
|
+
import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1152
1284
|
var CHIP_BOX = (
|
|
1153
1285
|
// Curved, not a pill (Katerina, 2026-09-01): the Avatar keeps its own
|
|
1154
1286
|
// rounded-sm corners — never a forced circle — and the chip's corner
|
|
@@ -1159,10 +1291,10 @@ var CHIP_LABEL = "text-caption font-medium text-text-primary";
|
|
|
1159
1291
|
var CHIP_REMOVE = "size-4 flex items-center justify-center rounded-full hover:bg-bg-hover text-text-secondary";
|
|
1160
1292
|
var chipPadding = (leading, removable) => cn(leading ? "pl-[2px]" : "pl-2", removable ? "pr-1" : "pr-2");
|
|
1161
1293
|
function InputChip({ label, leading, onRemove, removeLabel, truncate, className }) {
|
|
1162
|
-
return /* @__PURE__ */
|
|
1163
|
-
leading && /* @__PURE__ */
|
|
1164
|
-
/* @__PURE__ */
|
|
1165
|
-
onRemove && /* @__PURE__ */
|
|
1294
|
+
return /* @__PURE__ */ jsxs14("div", { className: cn(CHIP_BOX, chipPadding(!!leading, !!onRemove), className), children: [
|
|
1295
|
+
leading && /* @__PURE__ */ jsx20("span", { className: "flex shrink-0 items-center", children: leading }),
|
|
1296
|
+
/* @__PURE__ */ jsx20("span", { className: cn(CHIP_LABEL, truncate && "min-w-0 truncate"), children: label }),
|
|
1297
|
+
onRemove && /* @__PURE__ */ jsx20(
|
|
1166
1298
|
BaseButton4,
|
|
1167
1299
|
{
|
|
1168
1300
|
type: "button",
|
|
@@ -1172,7 +1304,7 @@ function InputChip({ label, leading, onRemove, removeLabel, truncate, className
|
|
|
1172
1304
|
},
|
|
1173
1305
|
className: cn(CHIP_REMOVE, truncate && "shrink-0"),
|
|
1174
1306
|
"aria-label": removeLabel ?? `Remove ${label}`,
|
|
1175
|
-
children: /* @__PURE__ */
|
|
1307
|
+
children: /* @__PURE__ */ jsx20(IconX4, { size: 10, stroke: 1.5 })
|
|
1176
1308
|
}
|
|
1177
1309
|
)
|
|
1178
1310
|
] });
|
|
@@ -1225,7 +1357,7 @@ function ChipInput({
|
|
|
1225
1357
|
setQuery("");
|
|
1226
1358
|
}
|
|
1227
1359
|
}
|
|
1228
|
-
return /* @__PURE__ */
|
|
1360
|
+
return /* @__PURE__ */ jsxs14(
|
|
1229
1361
|
Combobox.Root,
|
|
1230
1362
|
{
|
|
1231
1363
|
multiple: true,
|
|
@@ -1242,13 +1374,13 @@ function ChipInput({
|
|
|
1242
1374
|
filter,
|
|
1243
1375
|
itemToStringLabel: (option) => option.label,
|
|
1244
1376
|
children: [
|
|
1245
|
-
/* @__PURE__ */
|
|
1246
|
-
value.map((option) => /* @__PURE__ */
|
|
1247
|
-
chipLeading && /* @__PURE__ */
|
|
1248
|
-
/* @__PURE__ */
|
|
1249
|
-
/* @__PURE__ */
|
|
1377
|
+
/* @__PURE__ */ jsxs14(Combobox.Chips, { ref: setBox, className: "bg-bg-inset border border-border-default hover:border-border-strong focus-within:border-border-focus focus-within:hover:border-border-focus rounded-lg px-3 py-1.5 flex flex-wrap items-center gap-1.5 transition-colors min-h-[38px] cursor-text signal:transition-shadow signal:focus-within:shadow-focus-ring", children: [
|
|
1378
|
+
value.map((option) => /* @__PURE__ */ jsxs14(Combobox.Chip, { className: cn(CHIP_BOX, chipPadding(!!chipLeading, true)), children: [
|
|
1379
|
+
chipLeading && /* @__PURE__ */ jsx20("span", { className: "flex shrink-0 items-center", children: chipLeading(option) }),
|
|
1380
|
+
/* @__PURE__ */ jsx20("span", { className: CHIP_LABEL, children: option.label }),
|
|
1381
|
+
/* @__PURE__ */ jsx20(Combobox.ChipRemove, { className: CHIP_REMOVE, "aria-label": `Remove ${option.label}`, children: /* @__PURE__ */ jsx20(IconX4, { size: 10, stroke: 1.5 }) })
|
|
1250
1382
|
] }, option.id)),
|
|
1251
|
-
/* @__PURE__ */
|
|
1383
|
+
/* @__PURE__ */ jsx20(
|
|
1252
1384
|
Combobox.Input,
|
|
1253
1385
|
{
|
|
1254
1386
|
autoFocus,
|
|
@@ -1260,18 +1392,18 @@ function ChipInput({
|
|
|
1260
1392
|
}
|
|
1261
1393
|
)
|
|
1262
1394
|
] }),
|
|
1263
|
-
/* @__PURE__ */
|
|
1395
|
+
/* @__PURE__ */ jsx20(Combobox.Portal, { children: /* @__PURE__ */ jsx20(
|
|
1264
1396
|
Combobox.Positioner,
|
|
1265
1397
|
{
|
|
1266
1398
|
anchor: box,
|
|
1267
1399
|
sideOffset: GAP3,
|
|
1268
1400
|
collisionPadding: VIEWPORT_PAD3,
|
|
1269
1401
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
1270
|
-
children: /* @__PURE__ */
|
|
1402
|
+
children: /* @__PURE__ */ jsx20(Combobox.Popup, { className: "w-[var(--anchor-width)] p-0", render: /* @__PURE__ */ jsx20(MenuPanel, {}), children: /* @__PURE__ */ jsx20(ScrollArea, { viewportClassName: "max-h-[240px]", contentClassName: "flex flex-col p-2", children: /* @__PURE__ */ jsx20(Combobox.List, { children: (option) => /* @__PURE__ */ jsx20(
|
|
1271
1403
|
Combobox.Item,
|
|
1272
1404
|
{
|
|
1273
1405
|
value: option,
|
|
1274
|
-
render: /* @__PURE__ */
|
|
1406
|
+
render: /* @__PURE__ */ jsx20(
|
|
1275
1407
|
MenuItem,
|
|
1276
1408
|
{
|
|
1277
1409
|
size: "tall",
|
|
@@ -1294,22 +1426,22 @@ var VIEWPORT_PAD3 = 8;
|
|
|
1294
1426
|
|
|
1295
1427
|
// src/EmptyState.tsx
|
|
1296
1428
|
import { IconMessage2 } from "@tabler/icons-react";
|
|
1297
|
-
import { jsx as
|
|
1429
|
+
import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1298
1430
|
function EmptyState({ icon, message, scope = "page", action, className }) {
|
|
1299
1431
|
if (scope === "section") {
|
|
1300
|
-
return /* @__PURE__ */
|
|
1432
|
+
return /* @__PURE__ */ jsx21("p", { className: cn("text-caption text-text-muted", className), children: message });
|
|
1301
1433
|
}
|
|
1302
|
-
return /* @__PURE__ */
|
|
1303
|
-
/* @__PURE__ */
|
|
1304
|
-
/* @__PURE__ */
|
|
1305
|
-
action && /* @__PURE__ */
|
|
1434
|
+
return /* @__PURE__ */ jsxs15("div", { className: cn("flex flex-1 flex-col items-center justify-center gap-2", className), children: [
|
|
1435
|
+
/* @__PURE__ */ jsx21("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx21(IconMessage2, { size: 16, stroke: 1.5 }) }),
|
|
1436
|
+
/* @__PURE__ */ jsx21("p", { className: "text-body-2 text-text-secondary text-center", children: message }),
|
|
1437
|
+
action && /* @__PURE__ */ jsx21(Button, { variant: "outlined", className: "mt-2", onClick: action.onClick, children: action.label })
|
|
1306
1438
|
] });
|
|
1307
1439
|
}
|
|
1308
1440
|
|
|
1309
1441
|
// src/Field.tsx
|
|
1310
1442
|
import { cloneElement, isValidElement } from "react";
|
|
1311
1443
|
import { Field as BaseField2 } from "@base-ui/react/field";
|
|
1312
|
-
import { jsx as
|
|
1444
|
+
import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1313
1445
|
var LINE_STYLES = {
|
|
1314
1446
|
helper: "text-caption text-text-muted",
|
|
1315
1447
|
warning: "text-caption text-warning-default",
|
|
@@ -1319,26 +1451,26 @@ function Field({ label, required = false, helper, error, children }) {
|
|
|
1319
1451
|
const control = required && isValidElement(children) ? cloneElement(children, {
|
|
1320
1452
|
"aria-required": children.props["aria-required"] ?? true
|
|
1321
1453
|
}) : children;
|
|
1322
|
-
return /* @__PURE__ */
|
|
1323
|
-
/* @__PURE__ */
|
|
1454
|
+
return /* @__PURE__ */ jsxs16(BaseField2.Root, { invalid: !!error, className: "flex flex-col gap-2", children: [
|
|
1455
|
+
/* @__PURE__ */ jsxs16(BaseField2.Label, { className: cn("text-input-label text-text-primary", required && "flex items-center"), children: [
|
|
1324
1456
|
label,
|
|
1325
|
-
required && /* @__PURE__ */
|
|
1457
|
+
required && /* @__PURE__ */ jsx22("span", { "aria-hidden": "true", className: "text-error-default ml-0.5", children: "*" })
|
|
1326
1458
|
] }),
|
|
1327
|
-
/* @__PURE__ */
|
|
1459
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-1.5", children: [
|
|
1328
1460
|
control,
|
|
1329
|
-
error != null ? /* @__PURE__ */
|
|
1461
|
+
error != null ? /* @__PURE__ */ jsx22(BaseField2.Error, { match: true, className: LINE_STYLES.error, children: error }) : helper != null ? /* @__PURE__ */ jsx22(BaseField2.Description, { className: LINE_STYLES.helper, children: helper }) : null
|
|
1330
1462
|
] })
|
|
1331
1463
|
] });
|
|
1332
1464
|
}
|
|
1333
1465
|
function FieldLine({ tone = "helper", children, className }) {
|
|
1334
|
-
return /* @__PURE__ */
|
|
1466
|
+
return /* @__PURE__ */ jsx22("p", { role: tone === "error" ? "alert" : "status", className: cn(LINE_STYLES[tone], className), children });
|
|
1335
1467
|
}
|
|
1336
1468
|
|
|
1337
1469
|
// src/Form.tsx
|
|
1338
|
-
import { useLayoutEffect as useLayoutEffect2, useRef as
|
|
1470
|
+
import { useLayoutEffect as useLayoutEffect2, useRef as useRef3 } from "react";
|
|
1339
1471
|
import { Fieldset } from "@base-ui/react/fieldset";
|
|
1340
1472
|
import { Form as BaseForm } from "@base-ui/react/form";
|
|
1341
|
-
import { jsx as
|
|
1473
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
1342
1474
|
var CONTROL = 'input:not([type="hidden"]), textarea, select, button, [role="checkbox"], [role="combobox"], [tabindex]:not([tabindex="-1"])';
|
|
1343
1475
|
var ONE_LINE = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
|
|
1344
1476
|
function usable(element) {
|
|
@@ -1355,12 +1487,12 @@ function firstInvalid(form) {
|
|
|
1355
1487
|
function Form({ onSubmit, busy: ownBusy = false, enterSends = true, className, children, ...props }) {
|
|
1356
1488
|
const outerBusy = useFormBusy();
|
|
1357
1489
|
const busy = ownBusy || outerBusy;
|
|
1358
|
-
const form =
|
|
1359
|
-
const busyNow =
|
|
1490
|
+
const form = useRef3(null);
|
|
1491
|
+
const busyNow = useRef3(busy);
|
|
1360
1492
|
busyNow.current = busy;
|
|
1361
|
-
const sender =
|
|
1362
|
-
const holding =
|
|
1363
|
-
const lastInside =
|
|
1493
|
+
const sender = useRef3(null);
|
|
1494
|
+
const holding = useRef3(false);
|
|
1495
|
+
const lastInside = useRef3(null);
|
|
1364
1496
|
useLayoutEffect2(() => {
|
|
1365
1497
|
const element = form.current;
|
|
1366
1498
|
if (!element) return;
|
|
@@ -1397,7 +1529,7 @@ function Form({ onSubmit, busy: ownBusy = false, enterSends = true, className, c
|
|
|
1397
1529
|
const oneLine = ONE_LINE.has((target.getAttribute("type") ?? "").toLowerCase()) && target.getAttribute("role") !== "combobox";
|
|
1398
1530
|
if (enterSends && oneLine) form.current?.requestSubmit();
|
|
1399
1531
|
};
|
|
1400
|
-
return /* @__PURE__ */
|
|
1532
|
+
return /* @__PURE__ */ jsx23(
|
|
1401
1533
|
BaseForm,
|
|
1402
1534
|
{
|
|
1403
1535
|
ref: form,
|
|
@@ -1420,29 +1552,29 @@ function Form({ onSubmit, busy: ownBusy = false, enterSends = true, className, c
|
|
|
1420
1552
|
if (busyNow.current) return;
|
|
1421
1553
|
void onSubmit();
|
|
1422
1554
|
},
|
|
1423
|
-
children: /* @__PURE__ */
|
|
1555
|
+
children: /* @__PURE__ */ jsx23(Fieldset.Root, { disabled: busy, className: "contents", children: /* @__PURE__ */ jsx23(FormBusyContext.Provider, { value: busy, children }) })
|
|
1424
1556
|
}
|
|
1425
1557
|
);
|
|
1426
1558
|
}
|
|
1427
1559
|
|
|
1428
1560
|
// src/Skeleton.tsx
|
|
1429
|
-
import { jsx as
|
|
1561
|
+
import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1430
1562
|
function SkeletonBar({ className, style }) {
|
|
1431
|
-
return /* @__PURE__ */
|
|
1563
|
+
return /* @__PURE__ */ jsx24("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
|
|
1432
1564
|
}
|
|
1433
1565
|
var ROW_BAR_WIDTHS = [150, 100, 170, 120, 90, 140, 110, 160];
|
|
1434
1566
|
function SkeletonRow({ barWidth = 130 }) {
|
|
1435
|
-
return /* @__PURE__ */
|
|
1436
|
-
/* @__PURE__ */
|
|
1437
|
-
/* @__PURE__ */
|
|
1567
|
+
return /* @__PURE__ */ jsxs17("div", { className: "flex shrink-0 items-center gap-2 px-2 h-[32px] rounded-lg", children: [
|
|
1568
|
+
/* @__PURE__ */ jsx24(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
|
|
1569
|
+
/* @__PURE__ */ jsx24(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
|
|
1438
1570
|
] });
|
|
1439
1571
|
}
|
|
1440
1572
|
function SkeletonList({ rows = 8, className }) {
|
|
1441
|
-
return /* @__PURE__ */
|
|
1573
|
+
return /* @__PURE__ */ jsx24("div", { className: cn("flex flex-col gap-0.5 animate-skeleton-in", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx24(SkeletonRow, { barWidth: ROW_BAR_WIDTHS[i % ROW_BAR_WIDTHS.length] }, i)) });
|
|
1442
1574
|
}
|
|
1443
1575
|
|
|
1444
1576
|
// src/CommandPalette.tsx
|
|
1445
|
-
import { Fragment as Fragment3, jsx as
|
|
1577
|
+
import { Fragment as Fragment3, jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1446
1578
|
var PaletteContext = createContext4(null);
|
|
1447
1579
|
function usePalette(part) {
|
|
1448
1580
|
const palette = useContext4(PaletteContext);
|
|
@@ -1457,8 +1589,8 @@ function firstControl(popup) {
|
|
|
1457
1589
|
return popup.querySelector("[data-command-palette-fields]")?.querySelector(CONTROL2) ?? null;
|
|
1458
1590
|
}
|
|
1459
1591
|
function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", children }) {
|
|
1460
|
-
const popupRef =
|
|
1461
|
-
|
|
1592
|
+
const popupRef = useRef4(null);
|
|
1593
|
+
useEffect2(() => {
|
|
1462
1594
|
if (!open) return;
|
|
1463
1595
|
const frame = requestAnimationFrame(() => {
|
|
1464
1596
|
const popup = popupRef.current;
|
|
@@ -1468,10 +1600,10 @@ function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", chi
|
|
|
1468
1600
|
return () => cancelAnimationFrame(frame);
|
|
1469
1601
|
});
|
|
1470
1602
|
const context = useMemo2(() => ({ where, modKey, popupRef }), [where, modKey]);
|
|
1471
|
-
return /* @__PURE__ */
|
|
1472
|
-
/* @__PURE__ */
|
|
1473
|
-
/* @__PURE__ */
|
|
1474
|
-
|
|
1603
|
+
return /* @__PURE__ */ jsx25(Dialog2.Root, { open, onOpenChange: (next) => onOpenChange(next), children: /* @__PURE__ */ jsxs18(Dialog2.Portal, { children: [
|
|
1604
|
+
/* @__PURE__ */ jsx25(Dialog2.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
|
|
1605
|
+
/* @__PURE__ */ jsx25(Dialog2.Viewport, { className: "fixed inset-0 z-50 flex items-start justify-center pt-[16vh]", children: /* @__PURE__ */ jsx25(
|
|
1606
|
+
Dialog2.Popup,
|
|
1475
1607
|
{
|
|
1476
1608
|
ref: popupRef,
|
|
1477
1609
|
"aria-label": label,
|
|
@@ -1480,13 +1612,13 @@ function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", chi
|
|
|
1480
1612
|
if (e.target === popupRef.current) firstControl(popupRef.current)?.focus();
|
|
1481
1613
|
},
|
|
1482
1614
|
className: "flex w-[658px] max-w-[calc(100vw-32px)] flex-col overflow-hidden rounded-lg border border-border-default bg-bg-elevated shadow-lg outline-none",
|
|
1483
|
-
children: /* @__PURE__ */
|
|
1615
|
+
children: /* @__PURE__ */ jsx25(PaletteContext.Provider, { value: context, children })
|
|
1484
1616
|
}
|
|
1485
1617
|
) })
|
|
1486
1618
|
] }) });
|
|
1487
1619
|
}
|
|
1488
1620
|
function LevelChip({ chip, onBack }) {
|
|
1489
|
-
return /* @__PURE__ */
|
|
1621
|
+
return /* @__PURE__ */ jsx25(InputChip, { label: chip.label, leading: chip.leading, onRemove: onBack, removeLabel: `Leave ${chip.label}`, truncate: true, className: "max-w-[272px] shrink-0" });
|
|
1490
1622
|
}
|
|
1491
1623
|
function useBack(chip, popupRef) {
|
|
1492
1624
|
return () => {
|
|
@@ -1497,10 +1629,10 @@ function useBack(chip, popupRef) {
|
|
|
1497
1629
|
}
|
|
1498
1630
|
function Footer({ keys }) {
|
|
1499
1631
|
const { where } = usePalette("The footer");
|
|
1500
|
-
return /* @__PURE__ */
|
|
1501
|
-
/* @__PURE__ */
|
|
1502
|
-
keys.map(([key, word]) => /* @__PURE__ */
|
|
1503
|
-
/* @__PURE__ */
|
|
1632
|
+
return /* @__PURE__ */ jsxs18("div", { className: "flex h-9 shrink-0 items-center gap-4 border-t border-border-subtle px-5 text-caption text-text-secondary signal:font-mono signal:text-small signal:text-text-muted", children: [
|
|
1633
|
+
/* @__PURE__ */ jsx25("span", { className: "min-w-0 flex-1 truncate", children: where }),
|
|
1634
|
+
keys.map(([key, word]) => /* @__PURE__ */ jsxs18("span", { className: "flex shrink-0 items-center gap-1.5", children: [
|
|
1635
|
+
/* @__PURE__ */ jsx25(Kbd, { children: key }),
|
|
1504
1636
|
" ",
|
|
1505
1637
|
word
|
|
1506
1638
|
] }, key))
|
|
@@ -1514,10 +1646,10 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
|
|
|
1514
1646
|
const rows = items.flatMap((g) => g.items);
|
|
1515
1647
|
const [litId, setLitId] = useState3();
|
|
1516
1648
|
const lit = litId === void 0 ? void 0 : rows.find((r) => r.id === litId);
|
|
1517
|
-
const inputRef =
|
|
1518
|
-
const reported =
|
|
1519
|
-
const settled =
|
|
1520
|
-
const moved =
|
|
1649
|
+
const inputRef = useRef4(null);
|
|
1650
|
+
const reported = useRef4({});
|
|
1651
|
+
const settled = useRef4(null);
|
|
1652
|
+
const moved = useRef4(false);
|
|
1521
1653
|
useLayoutEffect3(() => {
|
|
1522
1654
|
const before = settled.current;
|
|
1523
1655
|
const now = reported.current;
|
|
@@ -1577,7 +1709,7 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
|
|
|
1577
1709
|
...chip && query === "" ? [["Backspace", "back"]] : [],
|
|
1578
1710
|
["Esc", "close"]
|
|
1579
1711
|
];
|
|
1580
|
-
return /* @__PURE__ */
|
|
1712
|
+
return /* @__PURE__ */ jsxs18(
|
|
1581
1713
|
Autocomplete.Root,
|
|
1582
1714
|
{
|
|
1583
1715
|
items,
|
|
@@ -1600,10 +1732,10 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
|
|
|
1600
1732
|
setLitId(id);
|
|
1601
1733
|
},
|
|
1602
1734
|
children: [
|
|
1603
|
-
/* @__PURE__ */
|
|
1604
|
-
/* @__PURE__ */
|
|
1605
|
-
chip && /* @__PURE__ */
|
|
1606
|
-
/* @__PURE__ */
|
|
1735
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
|
|
1736
|
+
/* @__PURE__ */ jsx25(IconSearch, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" }),
|
|
1737
|
+
chip && /* @__PURE__ */ jsx25(LevelChip, { chip, onBack: back }),
|
|
1738
|
+
/* @__PURE__ */ jsx25(
|
|
1607
1739
|
Autocomplete.Input,
|
|
1608
1740
|
{
|
|
1609
1741
|
ref: inputRef,
|
|
@@ -1615,43 +1747,43 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
|
|
|
1615
1747
|
}
|
|
1616
1748
|
)
|
|
1617
1749
|
] }),
|
|
1618
|
-
/* @__PURE__ */
|
|
1619
|
-
children != null && /* @__PURE__ */
|
|
1620
|
-
/* @__PURE__ */
|
|
1621
|
-
/* @__PURE__ */
|
|
1622
|
-
/* @__PURE__ */
|
|
1750
|
+
/* @__PURE__ */ jsxs18(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col p-2", children: [
|
|
1751
|
+
children != null && /* @__PURE__ */ jsx25("div", { className: "flex flex-col gap-2 px-3 pb-2 pt-3", children }),
|
|
1752
|
+
/* @__PURE__ */ jsx25(Autocomplete.List, { className: "flex flex-col", children: (group) => /* @__PURE__ */ jsxs18(Autocomplete.Group, { items: group.items, className: "flex flex-col", children: [
|
|
1753
|
+
/* @__PURE__ */ jsx25(Autocomplete.GroupLabel, { className: "flex h-7 shrink-0 items-center px-3", children: /* @__PURE__ */ jsx25(SectionLabel, { tone: "secondary", children: group.value }) }),
|
|
1754
|
+
/* @__PURE__ */ jsx25(Autocomplete.Collection, { children: (row) => (
|
|
1623
1755
|
/* The menu row, as the list's own option — the way Select
|
|
1624
1756
|
puts it on `Select.Item`. One row, two parts. */
|
|
1625
|
-
/* @__PURE__ */
|
|
1757
|
+
/* @__PURE__ */ jsx25(Autocomplete.Item, { value: row, onClick: () => row.onSelect(), className: menuItemClassName({ size: "tall" }), children: /* @__PURE__ */ jsx25(
|
|
1626
1758
|
MenuItemBody,
|
|
1627
1759
|
{
|
|
1628
1760
|
size: "tall",
|
|
1629
1761
|
label: row.label,
|
|
1630
1762
|
description: row.description,
|
|
1631
|
-
leading: /* @__PURE__ */
|
|
1763
|
+
leading: /* @__PURE__ */ jsx25(RowLeading, { row }),
|
|
1632
1764
|
submenu: !!row.onGoIn,
|
|
1633
|
-
hint: row.onGoIn ? /* @__PURE__ */
|
|
1765
|
+
hint: row.onGoIn ? /* @__PURE__ */ jsx25(Kbd, { children: "Tab" }) : /* @__PURE__ */ jsx25(EnterHint, {})
|
|
1634
1766
|
}
|
|
1635
1767
|
) }, row.id)
|
|
1636
1768
|
) })
|
|
1637
1769
|
] }, group.value) }),
|
|
1638
|
-
/* @__PURE__ */
|
|
1639
|
-
/* @__PURE__ */
|
|
1640
|
-
/* @__PURE__ */
|
|
1770
|
+
/* @__PURE__ */ jsx25(Autocomplete.Status, { className: "flex items-center gap-2 px-3 [&:not(:empty)]:h-8", children: pending && /* @__PURE__ */ jsxs18(Fragment3, { children: [
|
|
1771
|
+
/* @__PURE__ */ jsx25(IconLoader22, { size: 12, stroke: 1.5, className: "shrink-0 animate-spin text-text-muted" }),
|
|
1772
|
+
/* @__PURE__ */ jsx25("span", { className: "text-caption text-text-muted", children: pending })
|
|
1641
1773
|
] }) }),
|
|
1642
|
-
notes.map((note) => /* @__PURE__ */
|
|
1643
|
-
/* @__PURE__ */
|
|
1774
|
+
notes.map((note) => /* @__PURE__ */ jsx25("div", { className: "flex min-h-8 items-center px-3", children: /* @__PURE__ */ jsx25(FieldLine, { children: note }) }, note)),
|
|
1775
|
+
/* @__PURE__ */ jsx25(Autocomplete.Empty, { className: "flex items-center px-3 [&:not(:empty)]:min-h-10", children: empty && /* @__PURE__ */ jsx25(EmptyState, { scope: "section", message: empty }) })
|
|
1644
1776
|
] }),
|
|
1645
|
-
/* @__PURE__ */
|
|
1777
|
+
/* @__PURE__ */ jsx25(Footer, { keys })
|
|
1646
1778
|
]
|
|
1647
1779
|
}
|
|
1648
1780
|
);
|
|
1649
1781
|
}
|
|
1650
1782
|
function RowLeading({ row }) {
|
|
1651
1783
|
if (row.icon != null) {
|
|
1652
|
-
return /* @__PURE__ */
|
|
1784
|
+
return /* @__PURE__ */ jsx25("span", { className: "flex size-8 items-center justify-center rounded-sm bg-bg-inset text-text-secondary", children: row.icon });
|
|
1653
1785
|
}
|
|
1654
|
-
return /* @__PURE__ */
|
|
1786
|
+
return /* @__PURE__ */ jsx25("span", { className: "flex size-8 items-center justify-center", children: row.leading });
|
|
1655
1787
|
}
|
|
1656
1788
|
var TEXT_TYPES = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
|
|
1657
1789
|
function isTextField(el) {
|
|
@@ -1661,9 +1793,9 @@ function isTextField(el) {
|
|
|
1661
1793
|
function CommandPaletteForm({ chip, icon, submitLabel, onSubmit, submitWaits, working, error, children }) {
|
|
1662
1794
|
const { modKey, popupRef } = usePalette("CommandPaletteForm");
|
|
1663
1795
|
const back = useBack(chip, popupRef);
|
|
1664
|
-
const frameRef =
|
|
1796
|
+
const frameRef = useRef4(null);
|
|
1665
1797
|
const busy = !!working;
|
|
1666
|
-
const busyRef =
|
|
1798
|
+
const busyRef = useRef4(busy);
|
|
1667
1799
|
busyRef.current = busy;
|
|
1668
1800
|
const firstInvalid2 = () => frameRef.current?.querySelector("[data-invalid]")?.querySelector(CONTROL2) ?? null;
|
|
1669
1801
|
const submit = () => {
|
|
@@ -1693,56 +1825,56 @@ function CommandPaletteForm({ chip, icon, submitLabel, onSubmit, submitWaits, wo
|
|
|
1693
1825
|
...backNamed ? [["Backspace", "back"]] : [],
|
|
1694
1826
|
["Esc", "close"]
|
|
1695
1827
|
];
|
|
1696
|
-
return /* @__PURE__ */
|
|
1697
|
-
/* @__PURE__ */
|
|
1698
|
-
icon != null && /* @__PURE__ */
|
|
1699
|
-
/* @__PURE__ */
|
|
1828
|
+
return /* @__PURE__ */ jsxs18("div", { ref: frameRef, tabIndex: -1, onKeyDown, onFocus: measure, onBlur: measure, onInput: measure, className: "flex min-h-0 flex-col outline-none", children: [
|
|
1829
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
|
|
1830
|
+
icon != null && /* @__PURE__ */ jsx25("span", { className: "flex shrink-0 items-center text-text-secondary", children: icon }),
|
|
1831
|
+
/* @__PURE__ */ jsx25(LevelChip, { chip, onBack: back })
|
|
1700
1832
|
] }),
|
|
1701
|
-
/* @__PURE__ */
|
|
1702
|
-
/* @__PURE__ */
|
|
1703
|
-
/* @__PURE__ */
|
|
1704
|
-
/* @__PURE__ */
|
|
1705
|
-
/* @__PURE__ */
|
|
1833
|
+
/* @__PURE__ */ jsxs18(Form, { "data-command-palette-fields": "", busy, enterSends: false, onSubmit: submit, className: "flex min-h-0 flex-col", children: [
|
|
1834
|
+
/* @__PURE__ */ jsx25(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col px-5 py-4", children: /* @__PURE__ */ jsx25("div", { className: "flex flex-col gap-4", children }) }),
|
|
1835
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex shrink-0 items-center gap-3 px-5 pb-4", children: [
|
|
1836
|
+
/* @__PURE__ */ jsx25("div", { className: "min-w-0 flex-1", children: working ? /* @__PURE__ */ jsx25(FieldLine, { children: working.line }) : error ? /* @__PURE__ */ jsx25(FieldLine, { tone: "error", children: error }) : null }),
|
|
1837
|
+
/* @__PURE__ */ jsx25(
|
|
1706
1838
|
Button,
|
|
1707
1839
|
{
|
|
1708
1840
|
type: "submit",
|
|
1709
1841
|
variant: "primary",
|
|
1710
1842
|
disabled: busy,
|
|
1711
1843
|
disabledReason: busy ? void 0 : submitWaits,
|
|
1712
|
-
leadingIcon: busy ? /* @__PURE__ */
|
|
1844
|
+
leadingIcon: busy ? /* @__PURE__ */ jsx25(IconLoader22, { size: 16, stroke: 1.5, className: "animate-spin" }) : void 0,
|
|
1713
1845
|
children: working ? working.button : submitLabel
|
|
1714
1846
|
}
|
|
1715
1847
|
)
|
|
1716
1848
|
] })
|
|
1717
1849
|
] }),
|
|
1718
|
-
/* @__PURE__ */
|
|
1850
|
+
/* @__PURE__ */ jsx25(Footer, { keys })
|
|
1719
1851
|
] });
|
|
1720
1852
|
}
|
|
1721
1853
|
var BAR_WIDTHS = ["w-4/5", "w-3/5", "w-2/3"];
|
|
1722
1854
|
function CommandPaletteWorking({ children, bars = 2 }) {
|
|
1723
|
-
return /* @__PURE__ */
|
|
1724
|
-
/* @__PURE__ */
|
|
1725
|
-
/* @__PURE__ */
|
|
1855
|
+
return /* @__PURE__ */ jsxs18("div", { role: "status", className: "flex flex-col gap-2", children: [
|
|
1856
|
+
/* @__PURE__ */ jsxs18("span", { className: "flex items-center gap-2 text-caption text-text-secondary", children: [
|
|
1857
|
+
/* @__PURE__ */ jsx25(IconLoader22, { size: 14, stroke: 1.5, className: "shrink-0 animate-spin" }),
|
|
1726
1858
|
children
|
|
1727
1859
|
] }),
|
|
1728
|
-
BAR_WIDTHS.slice(0, bars).map((width) => /* @__PURE__ */
|
|
1860
|
+
BAR_WIDTHS.slice(0, bars).map((width) => /* @__PURE__ */ jsx25(SkeletonBar, { className: cn("h-3", width) }, width))
|
|
1729
1861
|
] });
|
|
1730
1862
|
}
|
|
1731
1863
|
function CommandPaletteAnswer({ children, note }) {
|
|
1732
1864
|
const paragraphs = children.split(/\n\s*\n/).filter((p) => p.trim() !== "");
|
|
1733
|
-
return /* @__PURE__ */
|
|
1734
|
-
paragraphs.map((paragraph, i) => /* @__PURE__ */
|
|
1735
|
-
(part, j) => /^\[\d+\]$/.test(part) ? /* @__PURE__ */
|
|
1865
|
+
return /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-2", children: [
|
|
1866
|
+
paragraphs.map((paragraph, i) => /* @__PURE__ */ jsx25("p", { className: "whitespace-pre-wrap text-body-2 text-text-primary", children: paragraph.split(/\s*(\[\d+\])/).map(
|
|
1867
|
+
(part, j) => /^\[\d+\]$/.test(part) ? /* @__PURE__ */ jsx25("sup", { className: "ml-0.5 font-mono text-small text-accent-primary", children: part.slice(1, -1) }, j) : part
|
|
1736
1868
|
) }, i)),
|
|
1737
|
-
note && /* @__PURE__ */
|
|
1869
|
+
note && /* @__PURE__ */ jsx25(FieldLine, { children: note })
|
|
1738
1870
|
] });
|
|
1739
1871
|
}
|
|
1740
1872
|
function CommandPaletteQuote({ children }) {
|
|
1741
|
-
return /* @__PURE__ */
|
|
1873
|
+
return /* @__PURE__ */ jsx25("p", { className: "whitespace-pre-wrap border-l-2 border-border-default pl-3 text-body-2 text-text-primary", children });
|
|
1742
1874
|
}
|
|
1743
1875
|
|
|
1744
1876
|
// src/InlineChip.tsx
|
|
1745
|
-
import { Fragment as Fragment4, jsx as
|
|
1877
|
+
import { Fragment as Fragment4, jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1746
1878
|
var INLINE_CHIP_CLASSES = "inline-flex h-[1.4em] items-center gap-1 rounded-sm px-1 mx-0.5 align-top text-body-2 font-normal select-none";
|
|
1747
1879
|
var INLINE_CHIP_TONE_CLASSES = {
|
|
1748
1880
|
/** A thing or a place — anything that is not a person. */
|
|
@@ -1764,30 +1896,30 @@ function inlineChipClassName(tone, className) {
|
|
|
1764
1896
|
return cn(INLINE_CHIP_CLASSES, INLINE_CHIP_TONE_CLASSES[tone], className);
|
|
1765
1897
|
}
|
|
1766
1898
|
function InlineChip({ tone = "neutral", icon, href, className, children, ...props }) {
|
|
1767
|
-
const body = /* @__PURE__ */
|
|
1768
|
-
icon && /* @__PURE__ */
|
|
1899
|
+
const body = /* @__PURE__ */ jsxs19(Fragment4, { children: [
|
|
1900
|
+
icon && /* @__PURE__ */ jsx26("span", { className: "flex size-4 shrink-0 items-center justify-center text-text-secondary", children: icon }),
|
|
1769
1901
|
children
|
|
1770
1902
|
] });
|
|
1771
1903
|
const classes = inlineChipClassName(tone, className);
|
|
1772
1904
|
if (href === void 0) {
|
|
1773
|
-
return /* @__PURE__ */
|
|
1905
|
+
return /* @__PURE__ */ jsx26("span", { className: classes, ...props, children: body });
|
|
1774
1906
|
}
|
|
1775
|
-
return /* @__PURE__ */
|
|
1907
|
+
return /* @__PURE__ */ jsx26("a", { href, className: classes, ...props, children: body });
|
|
1776
1908
|
}
|
|
1777
1909
|
|
|
1778
1910
|
// src/IdentityMenu.tsx
|
|
1779
|
-
import { useCallback, useRef as
|
|
1911
|
+
import { useCallback, useRef as useRef5 } from "react";
|
|
1780
1912
|
|
|
1781
1913
|
// src/Person.tsx
|
|
1782
|
-
import { jsx as
|
|
1914
|
+
import { jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1783
1915
|
function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
|
|
1784
1916
|
return (
|
|
1785
1917
|
// gap-2: the face-to-name distance is one rule (8px) wherever a person
|
|
1786
1918
|
// appears — Katerina, 2026-09-01, set on Person so PersonTrigger and every
|
|
1787
1919
|
// row agree by construction.
|
|
1788
|
-
/* @__PURE__ */
|
|
1789
|
-
/* @__PURE__ */
|
|
1790
|
-
/* @__PURE__ */
|
|
1920
|
+
/* @__PURE__ */ jsxs20("span", { className: cn("flex min-w-0 items-center gap-2", className), children: [
|
|
1921
|
+
/* @__PURE__ */ jsx27(Avatar, { name, src: picture, size }),
|
|
1922
|
+
/* @__PURE__ */ jsx27("span", { className: cn("truncate", !name && "text-text-muted"), children: name ?? fallback })
|
|
1791
1923
|
] })
|
|
1792
1924
|
);
|
|
1793
1925
|
}
|
|
@@ -1795,10 +1927,10 @@ function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
|
|
|
1795
1927
|
// src/PersonTrigger.tsx
|
|
1796
1928
|
import { Button as BaseButton5 } from "@base-ui/react/button";
|
|
1797
1929
|
import { IconChevronDown } from "@tabler/icons-react";
|
|
1798
|
-
import { jsx as
|
|
1930
|
+
import { jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1799
1931
|
function PersonTrigger({ name, picture, fallback, size, open = false, compact = false, className, ...props }) {
|
|
1800
1932
|
if (compact) {
|
|
1801
|
-
return /* @__PURE__ */
|
|
1933
|
+
return /* @__PURE__ */ jsx28(
|
|
1802
1934
|
BaseButton5,
|
|
1803
1935
|
{
|
|
1804
1936
|
type: "button",
|
|
@@ -1807,11 +1939,11 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
|
|
|
1807
1939
|
"aria-label": props["aria-label"] ?? name ?? fallback,
|
|
1808
1940
|
className: cn("cursor-pointer rounded-full", className),
|
|
1809
1941
|
...props,
|
|
1810
|
-
children: /* @__PURE__ */
|
|
1942
|
+
children: /* @__PURE__ */ jsx28(Avatar, { name, src: picture, size: size ?? 36 })
|
|
1811
1943
|
}
|
|
1812
1944
|
);
|
|
1813
1945
|
}
|
|
1814
|
-
return /* @__PURE__ */
|
|
1946
|
+
return /* @__PURE__ */ jsxs21(
|
|
1815
1947
|
BaseButton5,
|
|
1816
1948
|
{
|
|
1817
1949
|
type: "button",
|
|
@@ -1829,18 +1961,18 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
|
|
|
1829
1961
|
),
|
|
1830
1962
|
...props,
|
|
1831
1963
|
children: [
|
|
1832
|
-
/* @__PURE__ */
|
|
1833
|
-
/* @__PURE__ */
|
|
1964
|
+
/* @__PURE__ */ jsx28(Person, { name, picture, fallback, size: size ?? 22 }),
|
|
1965
|
+
/* @__PURE__ */ jsx28(IconChevronDown, { size: 14, stroke: 1.5, className: "shrink-0 text-text-muted" })
|
|
1834
1966
|
]
|
|
1835
1967
|
}
|
|
1836
1968
|
);
|
|
1837
1969
|
}
|
|
1838
1970
|
|
|
1839
1971
|
// src/IdentityMenu.tsx
|
|
1840
|
-
import { Fragment as Fragment5, jsx as
|
|
1972
|
+
import { Fragment as Fragment5, jsx as jsx29, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1841
1973
|
function IdentityPanel({ className, onClose = () => {
|
|
1842
1974
|
}, ...rest }) {
|
|
1843
|
-
return /* @__PURE__ */
|
|
1975
|
+
return /* @__PURE__ */ jsx29(MenuPanel, { className: cn("w-72", className), children: /* @__PURE__ */ jsx29(IdentityRows, { ...rest, onClose }) });
|
|
1844
1976
|
}
|
|
1845
1977
|
function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, onClose, children }) {
|
|
1846
1978
|
const act = (action) => () => {
|
|
@@ -1848,53 +1980,53 @@ function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, on
|
|
|
1848
1980
|
action();
|
|
1849
1981
|
};
|
|
1850
1982
|
const appRows = typeof children === "function" ? children(onClose) : children;
|
|
1851
|
-
return /* @__PURE__ */
|
|
1852
|
-
/* @__PURE__ */
|
|
1853
|
-
/* @__PURE__ */
|
|
1854
|
-
/* @__PURE__ */
|
|
1855
|
-
me.email && /* @__PURE__ */
|
|
1983
|
+
return /* @__PURE__ */ jsxs22(Fragment5, { children: [
|
|
1984
|
+
/* @__PURE__ */ jsxs22(MenuSection, { label: signedIn ? "Signed in as" : "Acting as", children: [
|
|
1985
|
+
/* @__PURE__ */ jsx29(MenuRow, { children: /* @__PURE__ */ jsx29("div", { className: "flex min-w-0 text-body-2-strong", children: /* @__PURE__ */ jsx29(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28 }) }) }),
|
|
1986
|
+
/* @__PURE__ */ jsx29(Note, { children: signedIn ? "Your Estiva ID. The same person you are in every Estiva app." : "A key held by this browser only. Nobody else knows who you are." }),
|
|
1987
|
+
me.email && /* @__PURE__ */ jsxs22(Note, { children: [
|
|
1856
1988
|
me.email,
|
|
1857
1989
|
" \xB7 known to Estiva, never published to the relay"
|
|
1858
1990
|
] })
|
|
1859
1991
|
] }),
|
|
1860
|
-
relayUrl && /* @__PURE__ */
|
|
1861
|
-
/* @__PURE__ */
|
|
1862
|
-
/* @__PURE__ */
|
|
1863
|
-
/* @__PURE__ */
|
|
1864
|
-
/* @__PURE__ */
|
|
1992
|
+
relayUrl && /* @__PURE__ */ jsxs22(Fragment5, { children: [
|
|
1993
|
+
/* @__PURE__ */ jsx29(Divider, { className: "mx-0 my-2" }),
|
|
1994
|
+
/* @__PURE__ */ jsxs22(MenuSection, { label: "Workspace", children: [
|
|
1995
|
+
/* @__PURE__ */ jsx29(MenuRow, { children: /* @__PURE__ */ jsx29("span", { className: "break-all font-mono text-caption text-text-primary", children: relayUrl }) }),
|
|
1996
|
+
/* @__PURE__ */ jsx29(Note, { children: "Everyone on this relay shares this workspace, in every app." })
|
|
1865
1997
|
] })
|
|
1866
1998
|
] }),
|
|
1867
|
-
appRows && /* @__PURE__ */
|
|
1868
|
-
/* @__PURE__ */
|
|
1999
|
+
appRows && /* @__PURE__ */ jsxs22(Fragment5, { children: [
|
|
2000
|
+
/* @__PURE__ */ jsx29(Divider, { className: "mx-0 my-2" }),
|
|
1869
2001
|
appRows
|
|
1870
2002
|
] }),
|
|
1871
|
-
signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */
|
|
1872
|
-
signedIn && idBase && /* @__PURE__ */
|
|
2003
|
+
signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */ jsx29(Divider, { className: "mx-0 my-2" }) : null,
|
|
2004
|
+
signedIn && idBase && /* @__PURE__ */ jsx29(
|
|
1873
2005
|
MenuItem,
|
|
1874
2006
|
{
|
|
1875
2007
|
label: "Edit your profile in Estiva ID",
|
|
1876
2008
|
onClick: act(() => window.open(idBase, "_blank", "noopener,noreferrer"))
|
|
1877
2009
|
}
|
|
1878
2010
|
),
|
|
1879
|
-
onCopyKey && /* @__PURE__ */
|
|
1880
|
-
idBase && onSignOut && /* @__PURE__ */
|
|
2011
|
+
onCopyKey && /* @__PURE__ */ jsx29(MenuItem, { label: "Copy public key", onClick: act(onCopyKey) }),
|
|
2012
|
+
idBase && onSignOut && /* @__PURE__ */ jsx29(MenuItem, { label: "Sign out", onClick: act(onSignOut) })
|
|
1881
2013
|
] });
|
|
1882
2014
|
}
|
|
1883
2015
|
function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, compact = false, className, children }) {
|
|
1884
|
-
const actions =
|
|
2016
|
+
const actions = useRef5(null);
|
|
1885
2017
|
const close = useCallback(() => actions.current?.close(), []);
|
|
1886
2018
|
return (
|
|
1887
2019
|
/* The wrapper carries the caller's `className` and nothing else. It used
|
|
1888
2020
|
to be `relative`, because the panel was positioned against it; the panel
|
|
1889
2021
|
hangs from the trigger and portals now, so a positioning context here
|
|
1890
2022
|
would only be a lie about what this box does. */
|
|
1891
|
-
/* @__PURE__ */
|
|
2023
|
+
/* @__PURE__ */ jsx29("div", { className, children: /* @__PURE__ */ jsx29(
|
|
1892
2024
|
Menu,
|
|
1893
2025
|
{
|
|
1894
2026
|
align: "right",
|
|
1895
2027
|
actionsRef: actions,
|
|
1896
2028
|
className: "w-72",
|
|
1897
|
-
trigger: /* @__PURE__ */
|
|
2029
|
+
trigger: /* @__PURE__ */ jsx29(
|
|
1898
2030
|
PersonTrigger,
|
|
1899
2031
|
{
|
|
1900
2032
|
name: me.name,
|
|
@@ -1905,7 +2037,7 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
|
|
|
1905
2037
|
"aria-label": compact ? "Account menu" : void 0
|
|
1906
2038
|
}
|
|
1907
2039
|
),
|
|
1908
|
-
children: /* @__PURE__ */
|
|
2040
|
+
children: /* @__PURE__ */ jsx29(
|
|
1909
2041
|
IdentityRows,
|
|
1910
2042
|
{
|
|
1911
2043
|
me,
|
|
@@ -1923,14 +2055,14 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
|
|
|
1923
2055
|
);
|
|
1924
2056
|
}
|
|
1925
2057
|
function Note({ children }) {
|
|
1926
|
-
return /* @__PURE__ */
|
|
2058
|
+
return /* @__PURE__ */ jsx29("span", { className: "px-2 pb-1.5 text-caption text-text-secondary", children });
|
|
1927
2059
|
}
|
|
1928
2060
|
|
|
1929
2061
|
// src/FilePicker.tsx
|
|
1930
2062
|
import { forwardRef } from "react";
|
|
1931
|
-
import { jsx as
|
|
2063
|
+
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
1932
2064
|
var FilePicker = forwardRef(function FilePicker2({ onPick, ...props }, ref) {
|
|
1933
|
-
return /* @__PURE__ */
|
|
2065
|
+
return /* @__PURE__ */ jsx30(
|
|
1934
2066
|
"input",
|
|
1935
2067
|
{
|
|
1936
2068
|
ref,
|
|
@@ -1951,13 +2083,13 @@ var FilePicker = forwardRef(function FilePicker2({ onPick, ...props }, ref) {
|
|
|
1951
2083
|
// src/Select.tsx
|
|
1952
2084
|
import { IconCheck as IconCheck2, IconChevronDown as IconChevronDown2 } from "@tabler/icons-react";
|
|
1953
2085
|
import { Select as BaseSelect } from "@base-ui/react/select";
|
|
1954
|
-
import { jsx as
|
|
2086
|
+
import { jsx as jsx31, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1955
2087
|
var GAP4 = 4;
|
|
1956
2088
|
var VIEWPORT_PAD4 = 8;
|
|
1957
2089
|
function Select({ value, onChange, options, size = "default", ariaLabel, placeholder = "Select\u2026", disabled, disabledReason, className, ...aria }) {
|
|
1958
2090
|
const selected = options.find((o) => o.value === value);
|
|
1959
2091
|
const held = Boolean(disabledReason);
|
|
1960
|
-
const trigger = /* @__PURE__ */
|
|
2092
|
+
const trigger = /* @__PURE__ */ jsxs23(
|
|
1961
2093
|
BaseSelect.Trigger,
|
|
1962
2094
|
{
|
|
1963
2095
|
"aria-label": ariaLabel,
|
|
@@ -1987,20 +2119,20 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
1987
2119
|
className
|
|
1988
2120
|
),
|
|
1989
2121
|
children: [
|
|
1990
|
-
/* @__PURE__ */
|
|
1991
|
-
selected?.leading && /* @__PURE__ */
|
|
1992
|
-
/* @__PURE__ */
|
|
2122
|
+
/* @__PURE__ */ jsxs23("span", { className: cn("flex min-w-0 items-center gap-2", !selected && "text-text-muted"), children: [
|
|
2123
|
+
selected?.leading && /* @__PURE__ */ jsx31("span", { className: "flex shrink-0 items-center", children: selected.leading }),
|
|
2124
|
+
/* @__PURE__ */ jsx31(BaseSelect.Value, { className: "truncate", children: () => selected?.label ?? placeholder })
|
|
1993
2125
|
] }),
|
|
1994
|
-
/* @__PURE__ */
|
|
2126
|
+
/* @__PURE__ */ jsx31(
|
|
1995
2127
|
BaseSelect.Icon,
|
|
1996
2128
|
{
|
|
1997
|
-
render: /* @__PURE__ */
|
|
2129
|
+
render: /* @__PURE__ */ jsx31(IconChevronDown2, { size: size === "small" ? 14 : 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
|
|
1998
2130
|
}
|
|
1999
2131
|
)
|
|
2000
2132
|
]
|
|
2001
2133
|
}
|
|
2002
2134
|
);
|
|
2003
|
-
return /* @__PURE__ */
|
|
2135
|
+
return /* @__PURE__ */ jsxs23(
|
|
2004
2136
|
BaseSelect.Root,
|
|
2005
2137
|
{
|
|
2006
2138
|
value,
|
|
@@ -2012,8 +2144,8 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
2012
2144
|
disabled: disabled && !held,
|
|
2013
2145
|
modal: false,
|
|
2014
2146
|
children: [
|
|
2015
|
-
held ? /* @__PURE__ */
|
|
2016
|
-
/* @__PURE__ */
|
|
2147
|
+
held ? /* @__PURE__ */ jsx31(TooltipTrigger, { label: disabledReason ?? "", children: trigger }) : trigger,
|
|
2148
|
+
/* @__PURE__ */ jsx31(BaseSelect.Portal, { children: /* @__PURE__ */ jsx31(
|
|
2017
2149
|
BaseSelect.Positioner,
|
|
2018
2150
|
{
|
|
2019
2151
|
side: "bottom",
|
|
@@ -2022,25 +2154,25 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
2022
2154
|
collisionPadding: VIEWPORT_PAD4,
|
|
2023
2155
|
alignItemWithTrigger: false,
|
|
2024
2156
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
2025
|
-
children: /* @__PURE__ */
|
|
2157
|
+
children: /* @__PURE__ */ jsx31(
|
|
2026
2158
|
BaseSelect.Popup,
|
|
2027
2159
|
{
|
|
2028
|
-
render: /* @__PURE__ */
|
|
2160
|
+
render: /* @__PURE__ */ jsx31(MenuPanel, {}),
|
|
2029
2161
|
className: "min-w-[var(--anchor-width)] p-0",
|
|
2030
|
-
children: /* @__PURE__ */
|
|
2162
|
+
children: /* @__PURE__ */ jsx31(ScrollArea, { viewportClassName: "max-h-[min(288px,var(--available-height))]", contentClassName: "flex flex-col p-2", children: options.map((option) => /* @__PURE__ */ jsxs23(
|
|
2031
2163
|
BaseSelect.Item,
|
|
2032
2164
|
{
|
|
2033
2165
|
value: option.value,
|
|
2034
2166
|
className: cn(menuItemClassName({ size: "default" }), "justify-between data-[selected]:font-medium"),
|
|
2035
2167
|
children: [
|
|
2036
|
-
/* @__PURE__ */
|
|
2037
|
-
option.leading && /* @__PURE__ */
|
|
2038
|
-
/* @__PURE__ */
|
|
2168
|
+
/* @__PURE__ */ jsxs23("span", { className: "flex min-w-0 items-center gap-2", children: [
|
|
2169
|
+
option.leading && /* @__PURE__ */ jsx31("span", { className: "flex shrink-0 items-center", children: option.leading }),
|
|
2170
|
+
/* @__PURE__ */ jsx31(BaseSelect.ItemText, { className: "truncate text-body-2 text-text-primary", children: option.label })
|
|
2039
2171
|
] }),
|
|
2040
|
-
/* @__PURE__ */
|
|
2172
|
+
/* @__PURE__ */ jsx31(
|
|
2041
2173
|
BaseSelect.ItemIndicator,
|
|
2042
2174
|
{
|
|
2043
|
-
render: /* @__PURE__ */
|
|
2175
|
+
render: /* @__PURE__ */ jsx31(IconCheck2, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
|
|
2044
2176
|
}
|
|
2045
2177
|
)
|
|
2046
2178
|
]
|
|
@@ -2059,9 +2191,9 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
2059
2191
|
// src/TextInput.tsx
|
|
2060
2192
|
import { forwardRef as forwardRef2 } from "react";
|
|
2061
2193
|
import { Input } from "@base-ui/react/input";
|
|
2062
|
-
import { jsx as
|
|
2194
|
+
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
2063
2195
|
var TextInput = forwardRef2(function TextInput2({ className, type = "text", size = "default", ...props }, ref) {
|
|
2064
|
-
return /* @__PURE__ */
|
|
2196
|
+
return /* @__PURE__ */ jsx32(
|
|
2065
2197
|
Input,
|
|
2066
2198
|
{
|
|
2067
2199
|
ref,
|
|
@@ -2088,13 +2220,13 @@ var TextInput = forwardRef2(function TextInput2({ className, type = "text", size
|
|
|
2088
2220
|
// src/Textarea.tsx
|
|
2089
2221
|
import { forwardRef as forwardRef3 } from "react";
|
|
2090
2222
|
import { Field as BaseField3 } from "@base-ui/react/field";
|
|
2091
|
-
import { jsx as
|
|
2223
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
2092
2224
|
var Textarea = forwardRef3(function Textarea2({ className, ...props }, ref) {
|
|
2093
|
-
return /* @__PURE__ */
|
|
2225
|
+
return /* @__PURE__ */ jsx33(
|
|
2094
2226
|
BaseField3.Control,
|
|
2095
2227
|
{
|
|
2096
2228
|
ref,
|
|
2097
|
-
render: /* @__PURE__ */
|
|
2229
|
+
render: /* @__PURE__ */ jsx33("textarea", {}),
|
|
2098
2230
|
className: cn(
|
|
2099
2231
|
// The border strengthens on hover, as Select's and ChipInput's do (Katerina, 16 September:
|
|
2100
2232
|
// "aren't there hover states in text input and text area?"). Focus comes after hover in
|
|
@@ -2115,24 +2247,24 @@ var Textarea = forwardRef3(function Textarea2({ className, ...props }, ref) {
|
|
|
2115
2247
|
import { useState as useState4 } from "react";
|
|
2116
2248
|
|
|
2117
2249
|
// src/DialogShell.tsx
|
|
2118
|
-
import { useRef as
|
|
2119
|
-
import { Dialog as
|
|
2250
|
+
import { useRef as useRef6 } from "react";
|
|
2251
|
+
import { Dialog as Dialog3 } from "@base-ui/react/dialog";
|
|
2120
2252
|
import { AlertDialog } from "@base-ui/react/alert-dialog";
|
|
2121
|
-
import { IconX as
|
|
2122
|
-
import { jsx as
|
|
2253
|
+
import { IconX as IconX5 } from "@tabler/icons-react";
|
|
2254
|
+
import { jsx as jsx34, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
2123
2255
|
function DialogShell({ title, onClose, headerContent, footer, children, bodyClassName, bodyMaxHeight, width = 502, alert = false }) {
|
|
2124
|
-
const Parts = alert ? AlertDialog :
|
|
2125
|
-
const popupRef =
|
|
2126
|
-
return /* @__PURE__ */
|
|
2256
|
+
const Parts = alert ? AlertDialog : Dialog3;
|
|
2257
|
+
const popupRef = useRef6(null);
|
|
2258
|
+
return /* @__PURE__ */ jsx34(
|
|
2127
2259
|
Parts.Root,
|
|
2128
2260
|
{
|
|
2129
2261
|
open: true,
|
|
2130
2262
|
onOpenChange: (open) => {
|
|
2131
2263
|
if (!open) onClose();
|
|
2132
2264
|
},
|
|
2133
|
-
children: /* @__PURE__ */
|
|
2134
|
-
/* @__PURE__ */
|
|
2135
|
-
/* @__PURE__ */
|
|
2265
|
+
children: /* @__PURE__ */ jsxs24(Parts.Portal, { children: [
|
|
2266
|
+
/* @__PURE__ */ jsx34(Parts.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
|
|
2267
|
+
/* @__PURE__ */ jsx34("div", { className: "fixed inset-0 z-50 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs24(
|
|
2136
2268
|
Parts.Popup,
|
|
2137
2269
|
{
|
|
2138
2270
|
ref: popupRef,
|
|
@@ -2141,20 +2273,20 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
2141
2273
|
className: "bg-bg-elevated border border-border-subtle rounded-lg shadow-lg pointer-events-auto flex flex-col overflow-hidden outline-none",
|
|
2142
2274
|
style: { width },
|
|
2143
2275
|
children: [
|
|
2144
|
-
/* @__PURE__ */
|
|
2145
|
-
headerContent ?? /* @__PURE__ */
|
|
2146
|
-
/* @__PURE__ */
|
|
2276
|
+
/* @__PURE__ */ jsxs24("div", { className: "h-12 flex items-center justify-between pl-5 pr-4 border-b border-border-subtle shrink-0", children: [
|
|
2277
|
+
headerContent ?? /* @__PURE__ */ jsx34(Parts.Title, { className: "text-h4 text-text-primary", render: /* @__PURE__ */ jsx34("span", {}), children: title }),
|
|
2278
|
+
/* @__PURE__ */ jsx34(
|
|
2147
2279
|
Parts.Close,
|
|
2148
2280
|
{
|
|
2149
|
-
render: /* @__PURE__ */
|
|
2281
|
+
render: /* @__PURE__ */ jsx34(IconButton, { tooltip: "Close", "aria-label": "Close", children: /* @__PURE__ */ jsx34(IconX5, { size: 16, stroke: 1.5 }) })
|
|
2150
2282
|
}
|
|
2151
2283
|
)
|
|
2152
2284
|
] }),
|
|
2153
2285
|
bodyMaxHeight ? (
|
|
2154
2286
|
// The line above the footer on a box of the shell's own, not pushed into ScrollArea (UIG-9).
|
|
2155
|
-
/* @__PURE__ */
|
|
2156
|
-
) : /* @__PURE__ */
|
|
2157
|
-
footer != null && /* @__PURE__ */
|
|
2287
|
+
/* @__PURE__ */ jsx34("div", { className: cn(footer != null && "border-b border-border-subtle"), children: /* @__PURE__ */ jsx34(ScrollArea, { viewportClassName: bodyMaxHeight, contentClassName: cn("pl-5 pr-4 py-4", bodyClassName), children }) })
|
|
2288
|
+
) : /* @__PURE__ */ jsx34("div", { className: cn("pl-5 pr-4 py-4", footer != null && "border-b border-border-subtle", bodyClassName), children }),
|
|
2289
|
+
footer != null && /* @__PURE__ */ jsx34("div", { className: "h-12 flex items-center justify-end gap-2 pl-5 pr-4 shrink-0", children: footer })
|
|
2158
2290
|
]
|
|
2159
2291
|
}
|
|
2160
2292
|
) })
|
|
@@ -2164,7 +2296,7 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
2164
2296
|
}
|
|
2165
2297
|
|
|
2166
2298
|
// src/ConfirmDialog.tsx
|
|
2167
|
-
import { Fragment as Fragment6, jsx as
|
|
2299
|
+
import { Fragment as Fragment6, jsx as jsx35, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
2168
2300
|
function ConfirmDialog({ title, children, confirmLabel, destructive = false, onConfirm, onClose }) {
|
|
2169
2301
|
const [busy, setBusy] = useState4(false);
|
|
2170
2302
|
const confirm = async () => {
|
|
@@ -2176,32 +2308,32 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
|
|
|
2176
2308
|
setBusy(false);
|
|
2177
2309
|
}
|
|
2178
2310
|
};
|
|
2179
|
-
return /* @__PURE__ */
|
|
2311
|
+
return /* @__PURE__ */ jsx35(
|
|
2180
2312
|
DialogShell,
|
|
2181
2313
|
{
|
|
2182
2314
|
alert: true,
|
|
2183
2315
|
title,
|
|
2184
2316
|
onClose,
|
|
2185
|
-
footer: /* @__PURE__ */
|
|
2186
|
-
/* @__PURE__ */
|
|
2187
|
-
/* @__PURE__ */
|
|
2317
|
+
footer: /* @__PURE__ */ jsxs25(Fragment6, { children: [
|
|
2318
|
+
/* @__PURE__ */ jsx35(Button, { variant: "muted", onClick: onClose, disabled: busy, children: "Cancel" }),
|
|
2319
|
+
/* @__PURE__ */ jsx35(Button, { variant: destructive ? "destructive" : "primary", onClick: () => void confirm(), disabled: busy, children: confirmLabel })
|
|
2188
2320
|
] }),
|
|
2189
|
-
children: /* @__PURE__ */
|
|
2321
|
+
children: /* @__PURE__ */ jsx35("div", { className: "flex flex-col gap-3 text-body-2 text-text-primary", children })
|
|
2190
2322
|
}
|
|
2191
2323
|
);
|
|
2192
2324
|
}
|
|
2193
2325
|
|
|
2194
2326
|
// src/EditableText.tsx
|
|
2195
|
-
import { useEffect as
|
|
2327
|
+
import { useEffect as useEffect3, useRef as useRef7, useState as useState5 } from "react";
|
|
2196
2328
|
import { Field as BaseField4 } from "@base-ui/react/field";
|
|
2197
2329
|
import { Input as Input2 } from "@base-ui/react/input";
|
|
2198
|
-
import { jsx as
|
|
2330
|
+
import { jsx as jsx36 } from "react/jsx-runtime";
|
|
2199
2331
|
function EditableText({ value, display, displayNode, placeholder, onCommit, multiline = false, className, label, readOnly = false }) {
|
|
2200
2332
|
const [editing, setEditing] = useState5(false);
|
|
2201
2333
|
const [draft, setDraft] = useState5(value);
|
|
2202
2334
|
const [busy, setBusy] = useState5(false);
|
|
2203
|
-
const fieldRef =
|
|
2204
|
-
|
|
2335
|
+
const fieldRef = useRef7(null);
|
|
2336
|
+
useEffect3(() => {
|
|
2205
2337
|
if (editing) {
|
|
2206
2338
|
fieldRef.current?.focus();
|
|
2207
2339
|
fieldRef.current?.select();
|
|
@@ -2253,7 +2385,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
2253
2385
|
written and never read. Read-only, this is a line of text: whatever
|
|
2254
2386
|
names the region around it (a `Field`, a `Property`) names this too.
|
|
2255
2387
|
*/
|
|
2256
|
-
/* @__PURE__ */
|
|
2388
|
+
/* @__PURE__ */ jsx36(
|
|
2257
2389
|
"div",
|
|
2258
2390
|
{
|
|
2259
2391
|
className: cn("w-full px-2 py-1", multiline && !displayNode && "whitespace-pre-wrap", display ?? value ? "text-text-primary" : "text-text-muted", className),
|
|
@@ -2263,11 +2395,11 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
2263
2395
|
);
|
|
2264
2396
|
}
|
|
2265
2397
|
if (editing) {
|
|
2266
|
-
return multiline ? /* @__PURE__ */
|
|
2398
|
+
return multiline ? /* @__PURE__ */ jsx36(
|
|
2267
2399
|
BaseField4.Control,
|
|
2268
2400
|
{
|
|
2269
2401
|
ref: fieldRef,
|
|
2270
|
-
render: /* @__PURE__ */
|
|
2402
|
+
render: /* @__PURE__ */ jsx36("textarea", { rows: 4 }),
|
|
2271
2403
|
"aria-label": label,
|
|
2272
2404
|
value: draft,
|
|
2273
2405
|
disabled: busy,
|
|
@@ -2276,7 +2408,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
2276
2408
|
onBlur: () => void commit(),
|
|
2277
2409
|
className: fieldClass
|
|
2278
2410
|
}
|
|
2279
|
-
) : /* @__PURE__ */
|
|
2411
|
+
) : /* @__PURE__ */ jsx36(
|
|
2280
2412
|
Input2,
|
|
2281
2413
|
{
|
|
2282
2414
|
ref: fieldRef,
|
|
@@ -2290,7 +2422,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
2290
2422
|
}
|
|
2291
2423
|
);
|
|
2292
2424
|
}
|
|
2293
|
-
return /* @__PURE__ */
|
|
2425
|
+
return /* @__PURE__ */ jsx36(
|
|
2294
2426
|
"button",
|
|
2295
2427
|
{
|
|
2296
2428
|
type: "button",
|
|
@@ -2307,9 +2439,36 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
2307
2439
|
);
|
|
2308
2440
|
}
|
|
2309
2441
|
|
|
2442
|
+
// src/ErrorBoundary.tsx
|
|
2443
|
+
import { Component } from "react";
|
|
2444
|
+
import { IconAlertTriangle as IconAlertTriangle2 } from "@tabler/icons-react";
|
|
2445
|
+
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
2446
|
+
var ErrorBoundary = class extends Component {
|
|
2447
|
+
state = { hasError: false };
|
|
2448
|
+
static getDerivedStateFromError() {
|
|
2449
|
+
return { hasError: true };
|
|
2450
|
+
}
|
|
2451
|
+
componentDidCatch(error, info) {
|
|
2452
|
+
console.error(`${this.props.label ?? "part of the page"} crashed:`, error, info.componentStack ?? "");
|
|
2453
|
+
}
|
|
2454
|
+
render() {
|
|
2455
|
+
if (!this.state.hasError) return this.props.children;
|
|
2456
|
+
const message = /* @__PURE__ */ jsx37(
|
|
2457
|
+
EmptyState,
|
|
2458
|
+
{
|
|
2459
|
+
icon: /* @__PURE__ */ jsx37(IconAlertTriangle2, { size: 16, stroke: 1.5 }),
|
|
2460
|
+
message: `Something went wrong${this.props.label ? ` in the ${this.props.label}` : ""}. Your data is safe \u2014 try again.`,
|
|
2461
|
+
action: { label: "Try again", onClick: () => this.setState({ hasError: false }) }
|
|
2462
|
+
}
|
|
2463
|
+
);
|
|
2464
|
+
if (this.props.frame) return this.props.frame(message);
|
|
2465
|
+
return this.props.fallbackClassName ? /* @__PURE__ */ jsx37("div", { className: this.props.fallbackClassName, children: message }) : message;
|
|
2466
|
+
}
|
|
2467
|
+
};
|
|
2468
|
+
|
|
2310
2469
|
// src/ProgressBar.tsx
|
|
2311
2470
|
import { Progress } from "@base-ui/react/progress";
|
|
2312
|
-
import { jsx as
|
|
2471
|
+
import { jsx as jsx38 } from "react/jsx-runtime";
|
|
2313
2472
|
var TRACK_CLASSES = {
|
|
2314
2473
|
default: "h-1.5 w-full overflow-hidden rounded-full bg-bg-inset",
|
|
2315
2474
|
// 4px, Katerina's ruling of 14 September; Peek's own bar is 3px until it takes this one.
|
|
@@ -2322,16 +2481,16 @@ var INDICATOR_CLASSES = {
|
|
|
2322
2481
|
function ProgressBar({ value, max, label, variant = "default", className }) {
|
|
2323
2482
|
return (
|
|
2324
2483
|
// `max={0}` needs no guard: Base UI reads the 0/0 share as an empty bar.
|
|
2325
|
-
/* @__PURE__ */
|
|
2484
|
+
/* @__PURE__ */ jsx38(Progress.Root, { value, max, "aria-label": label, className, children: /* @__PURE__ */ jsx38(Progress.Track, { className: TRACK_CLASSES[variant], children: /* @__PURE__ */ jsx38(Progress.Indicator, { className: INDICATOR_CLASSES[variant] }) }) })
|
|
2326
2485
|
);
|
|
2327
2486
|
}
|
|
2328
2487
|
|
|
2329
2488
|
// src/Breadcrumb.tsx
|
|
2330
|
-
import { Fragment as Fragment7, useCallback as useCallback2, useLayoutEffect as useLayoutEffect4, useRef as
|
|
2331
|
-
import { jsx as
|
|
2489
|
+
import { Fragment as Fragment7, useCallback as useCallback2, useLayoutEffect as useLayoutEffect4, useRef as useRef8, useState as useState6 } from "react";
|
|
2490
|
+
import { jsx as jsx39, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2332
2491
|
function Breadcrumb({ items, className }) {
|
|
2333
|
-
const navRef =
|
|
2334
|
-
const labelRefs =
|
|
2492
|
+
const navRef = useRef8(null);
|
|
2493
|
+
const labelRefs = useRef8([]);
|
|
2335
2494
|
const [truncated, setTruncated] = useState6(/* @__PURE__ */ new Set());
|
|
2336
2495
|
const measure = useCallback2(() => {
|
|
2337
2496
|
const next = /* @__PURE__ */ new Set();
|
|
@@ -2348,7 +2507,7 @@ function Breadcrumb({ items, className }) {
|
|
|
2348
2507
|
observer.observe(nav);
|
|
2349
2508
|
return () => observer.disconnect();
|
|
2350
2509
|
}, [measure, items]);
|
|
2351
|
-
return /* @__PURE__ */
|
|
2510
|
+
return /* @__PURE__ */ jsx39("nav", { ref: navRef, "aria-label": "Breadcrumb", className: cn("flex min-w-0 items-center gap-1.5 text-body-2", className), children: items.map((item, index) => {
|
|
2352
2511
|
const last = index === items.length - 1;
|
|
2353
2512
|
const tone = item.muted || last && item.mono ? "text-text-muted" : last ? "text-text-primary" : "text-text-secondary";
|
|
2354
2513
|
const text = cn(
|
|
@@ -2369,25 +2528,25 @@ function Breadcrumb({ items, className }) {
|
|
|
2369
2528
|
// on a box around it, which the link takes them from, rather than
|
|
2370
2529
|
// pushed into it (UIG-9); the link is still the one element that
|
|
2371
2530
|
// truncates and is measured.
|
|
2372
|
-
/* @__PURE__ */
|
|
2373
|
-
) : /* @__PURE__ */
|
|
2374
|
-
return /* @__PURE__ */
|
|
2375
|
-
index > 0 && /* @__PURE__ */
|
|
2376
|
-
item.icon && /* @__PURE__ */
|
|
2531
|
+
/* @__PURE__ */ jsx39("span", { className: cn("flex min-w-0", item.mono && "shrink-0 font-mono text-caption", tone, "hover:text-text-primary"), children: /* @__PURE__ */ jsx39(Link, { ref: setLabelRef, variant: "plain", truncate: true, href: item.href, onClick: item.onClick, children: item.label }) })
|
|
2532
|
+
) : /* @__PURE__ */ jsx39("span", { ref: setLabelRef, className: text, "aria-current": last ? "page" : void 0, children: item.label });
|
|
2533
|
+
return /* @__PURE__ */ jsxs26(Fragment7, { children: [
|
|
2534
|
+
index > 0 && /* @__PURE__ */ jsx39("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
|
|
2535
|
+
item.icon && /* @__PURE__ */ jsx39("span", { "aria-hidden": "true", className: cn("flex shrink-0", tone), children: item.icon }),
|
|
2377
2536
|
truncated.has(index) ? (
|
|
2378
2537
|
// `min-w-0 shrink` undoes the wrapper's own shrink-0 — the crumb
|
|
2379
2538
|
// must keep truncating inside it, or wrapping it would widen the
|
|
2380
2539
|
// trail and the tooltip would never be needed again.
|
|
2381
|
-
/* @__PURE__ */
|
|
2540
|
+
/* @__PURE__ */ jsx39(WithTooltip, { label: item.label, wrapperClassName: "min-w-0 shrink", children: crumb })
|
|
2382
2541
|
) : crumb
|
|
2383
2542
|
] }, `${item.label}-${index}`);
|
|
2384
2543
|
}) });
|
|
2385
2544
|
}
|
|
2386
2545
|
|
|
2387
2546
|
// src/NavItem.tsx
|
|
2388
|
-
import { jsx as
|
|
2547
|
+
import { jsx as jsx40, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2389
2548
|
function NavItem({ label, href, count, countLabel, active = false, icon, className, ...props }) {
|
|
2390
|
-
return /* @__PURE__ */
|
|
2549
|
+
return /* @__PURE__ */ jsxs27(
|
|
2391
2550
|
"a",
|
|
2392
2551
|
{
|
|
2393
2552
|
href,
|
|
@@ -2402,9 +2561,9 @@ function NavItem({ label, href, count, countLabel, active = false, icon, classNa
|
|
|
2402
2561
|
),
|
|
2403
2562
|
...props,
|
|
2404
2563
|
children: [
|
|
2405
|
-
icon && /* @__PURE__ */
|
|
2406
|
-
/* @__PURE__ */
|
|
2407
|
-
count ? /* @__PURE__ */
|
|
2564
|
+
icon && /* @__PURE__ */ jsx40("span", { className: "flex shrink-0 items-center", children: icon }),
|
|
2565
|
+
/* @__PURE__ */ jsx40("span", { className: "flex-1 truncate", children: label }),
|
|
2566
|
+
count ? /* @__PURE__ */ jsx40(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx40("span", { className: "min-w-4 shrink-0 text-center font-mono text-caption tabular-nums text-text-muted", children: count }) }) : null
|
|
2408
2567
|
]
|
|
2409
2568
|
}
|
|
2410
2569
|
);
|
|
@@ -2413,7 +2572,7 @@ function NavItem({ label, href, count, countLabel, active = false, icon, classNa
|
|
|
2413
2572
|
// src/Popover.tsx
|
|
2414
2573
|
import { useMemo as useMemo3 } from "react";
|
|
2415
2574
|
import { Popover as BasePopover } from "@base-ui/react/popover";
|
|
2416
|
-
import { jsx as
|
|
2575
|
+
import { jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2417
2576
|
var GAP5 = 4;
|
|
2418
2577
|
var VIEWPORT_PAD5 = 8;
|
|
2419
2578
|
function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpenChange, finalFocus, actionsRef, ariaLabel, children, className, contentClassName, maxHeight }) {
|
|
@@ -2422,7 +2581,7 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
2422
2581
|
if (anchor instanceof Element) return anchor;
|
|
2423
2582
|
return { getBoundingClientRect: () => anchor };
|
|
2424
2583
|
}, [anchor]);
|
|
2425
|
-
return /* @__PURE__ */
|
|
2584
|
+
return /* @__PURE__ */ jsxs28(
|
|
2426
2585
|
BasePopover.Root,
|
|
2427
2586
|
{
|
|
2428
2587
|
open,
|
|
@@ -2430,8 +2589,8 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
2430
2589
|
actionsRef,
|
|
2431
2590
|
modal: false,
|
|
2432
2591
|
children: [
|
|
2433
|
-
trigger && /* @__PURE__ */
|
|
2434
|
-
/* @__PURE__ */
|
|
2592
|
+
trigger && /* @__PURE__ */ jsx41(BasePopover.Trigger, { render: trigger, disabled: triggerDisabled(trigger) }),
|
|
2593
|
+
/* @__PURE__ */ jsx41(BasePopover.Portal, { children: /* @__PURE__ */ jsx41(
|
|
2435
2594
|
BasePopover.Positioner,
|
|
2436
2595
|
{
|
|
2437
2596
|
anchor: anchorTarget,
|
|
@@ -2440,20 +2599,20 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
2440
2599
|
sideOffset: GAP5,
|
|
2441
2600
|
collisionPadding: VIEWPORT_PAD5,
|
|
2442
2601
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
2443
|
-
children: /* @__PURE__ */
|
|
2602
|
+
children: /* @__PURE__ */ jsx41(
|
|
2444
2603
|
BasePopover.Popup,
|
|
2445
2604
|
{
|
|
2446
2605
|
"aria-label": ariaLabel,
|
|
2447
2606
|
initialFocus: trigger ? void 0 : false,
|
|
2448
2607
|
finalFocus,
|
|
2449
2608
|
className: cn("min-w-[180px] outline-none p-0", className),
|
|
2450
|
-
render: /* @__PURE__ */
|
|
2451
|
-
children: /* @__PURE__ */
|
|
2609
|
+
render: /* @__PURE__ */ jsx41(MenuPanel, {}),
|
|
2610
|
+
children: /* @__PURE__ */ jsx41(
|
|
2452
2611
|
ScrollArea,
|
|
2453
2612
|
{
|
|
2454
2613
|
viewportClassName: maxHeight ?? "max-h-[var(--available-height)]",
|
|
2455
2614
|
contentClassName: cn("flex flex-col p-2", contentClassName),
|
|
2456
|
-
children: /* @__PURE__ */
|
|
2615
|
+
children: /* @__PURE__ */ jsx41(DividerInPanel.Provider, { value: true, children })
|
|
2457
2616
|
}
|
|
2458
2617
|
)
|
|
2459
2618
|
}
|
|
@@ -2467,9 +2626,9 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
2467
2626
|
|
|
2468
2627
|
// src/Toolbar.tsx
|
|
2469
2628
|
import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar";
|
|
2470
|
-
import { jsx as
|
|
2629
|
+
import { jsx as jsx42 } from "react/jsx-runtime";
|
|
2471
2630
|
function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocus = true, surface = true, children, className }) {
|
|
2472
|
-
const strip = /* @__PURE__ */
|
|
2631
|
+
const strip = /* @__PURE__ */ jsx42(
|
|
2473
2632
|
BaseToolbar.Root,
|
|
2474
2633
|
{
|
|
2475
2634
|
"aria-label": ariaLabel,
|
|
@@ -2480,27 +2639,27 @@ function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocu
|
|
|
2480
2639
|
}
|
|
2481
2640
|
);
|
|
2482
2641
|
if (!surface) return strip;
|
|
2483
|
-
return /* @__PURE__ */
|
|
2642
|
+
return /* @__PURE__ */ jsx42(MenuPanel, { className: "w-fit p-1", children: strip });
|
|
2484
2643
|
}
|
|
2485
2644
|
function ToolbarButton({ ref, disabled, disabledReason, ...props }) {
|
|
2486
|
-
return /* @__PURE__ */
|
|
2645
|
+
return /* @__PURE__ */ jsx42(
|
|
2487
2646
|
BaseToolbar.Button,
|
|
2488
2647
|
{
|
|
2489
2648
|
ref,
|
|
2490
2649
|
disabled: disabled || !!disabledReason,
|
|
2491
2650
|
focusableWhenDisabled: true,
|
|
2492
|
-
render: /* @__PURE__ */
|
|
2651
|
+
render: /* @__PURE__ */ jsx42(IconButton, { disabled, disabledReason, ...props })
|
|
2493
2652
|
}
|
|
2494
2653
|
);
|
|
2495
2654
|
}
|
|
2496
2655
|
function ToolbarLink({ ref, href, ...props }) {
|
|
2497
|
-
return /* @__PURE__ */
|
|
2656
|
+
return /* @__PURE__ */ jsx42(BaseToolbar.Link, { ref, render: /* @__PURE__ */ jsx42(IconButton, { href, ...props }) });
|
|
2498
2657
|
}
|
|
2499
2658
|
function ToolbarInput({ size, ...props }) {
|
|
2500
|
-
return /* @__PURE__ */
|
|
2659
|
+
return /* @__PURE__ */ jsx42(BaseToolbar.Input, { render: /* @__PURE__ */ jsx42(TextInput, { size }), ...props });
|
|
2501
2660
|
}
|
|
2502
2661
|
function ToolbarSeparator({ className }) {
|
|
2503
|
-
return /* @__PURE__ */
|
|
2662
|
+
return /* @__PURE__ */ jsx42(
|
|
2504
2663
|
BaseToolbar.Separator,
|
|
2505
2664
|
{
|
|
2506
2665
|
orientation: "vertical",
|
|
@@ -2510,9 +2669,9 @@ function ToolbarSeparator({ className }) {
|
|
|
2510
2669
|
}
|
|
2511
2670
|
|
|
2512
2671
|
// src/ReactionPicker.tsx
|
|
2513
|
-
import { jsx as
|
|
2672
|
+
import { jsx as jsx43 } from "react/jsx-runtime";
|
|
2514
2673
|
function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reactions", surface = true, className }) {
|
|
2515
|
-
return /* @__PURE__ */
|
|
2674
|
+
return /* @__PURE__ */ jsx43(Toolbar, { "aria-label": ariaLabel, surface, className: cn("gap-0.5", className), children: options.map((option) => (
|
|
2516
2675
|
/*
|
|
2517
2676
|
A `ToolbarButton`, not a button in a tooltip wrapper. The wrapper
|
|
2518
2677
|
would become the toolbar's item and the button inside it would never
|
|
@@ -2522,14 +2681,14 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
|
|
|
2522
2681
|
The tooltip names it for a pointer, `aria-label` for everything else,
|
|
2523
2682
|
and both say the meaning rather than the glyph.
|
|
2524
2683
|
*/
|
|
2525
|
-
/* @__PURE__ */
|
|
2684
|
+
/* @__PURE__ */ jsx43(
|
|
2526
2685
|
ToolbarButton,
|
|
2527
2686
|
{
|
|
2528
2687
|
"aria-label": option.label,
|
|
2529
2688
|
tooltip: option.label,
|
|
2530
2689
|
onClick: () => onSelect(option.emoji),
|
|
2531
2690
|
className: "size-7",
|
|
2532
|
-
children: /* @__PURE__ */
|
|
2691
|
+
children: /* @__PURE__ */ jsx43("span", { "aria-hidden": "true", className: "text-h3 leading-none", children: option.emoji })
|
|
2533
2692
|
},
|
|
2534
2693
|
option.emoji
|
|
2535
2694
|
)
|
|
@@ -2538,23 +2697,23 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
|
|
|
2538
2697
|
|
|
2539
2698
|
// src/PreviewCard.tsx
|
|
2540
2699
|
import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card";
|
|
2541
|
-
import { jsx as
|
|
2700
|
+
import { jsx as jsx44, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2542
2701
|
var GAP6 = 12;
|
|
2543
2702
|
var VIEWPORT_PAD6 = 8;
|
|
2544
2703
|
var OPEN_DELAY2 = 350;
|
|
2545
2704
|
var CLOSE_DELAY = 200;
|
|
2546
2705
|
function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, closeDelay = CLOSE_DELAY, className, contentClassName, wrapperClassName }) {
|
|
2547
|
-
return /* @__PURE__ */
|
|
2548
|
-
/* @__PURE__ */
|
|
2706
|
+
return /* @__PURE__ */ jsxs29(BasePreviewCard.Root, { children: [
|
|
2707
|
+
/* @__PURE__ */ jsx44(
|
|
2549
2708
|
BasePreviewCard.Trigger,
|
|
2550
2709
|
{
|
|
2551
2710
|
delay,
|
|
2552
2711
|
closeDelay,
|
|
2553
|
-
render: /* @__PURE__ */
|
|
2712
|
+
render: /* @__PURE__ */ jsx44("span", { className: cn("inline-flex", wrapperClassName) }),
|
|
2554
2713
|
children
|
|
2555
2714
|
}
|
|
2556
2715
|
),
|
|
2557
|
-
/* @__PURE__ */
|
|
2716
|
+
/* @__PURE__ */ jsx44(BasePreviewCard.Portal, { children: /* @__PURE__ */ jsx44(
|
|
2558
2717
|
BasePreviewCard.Positioner,
|
|
2559
2718
|
{
|
|
2560
2719
|
side,
|
|
@@ -2562,12 +2721,12 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
|
|
|
2562
2721
|
sideOffset: GAP6,
|
|
2563
2722
|
collisionPadding: VIEWPORT_PAD6,
|
|
2564
2723
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
2565
|
-
children: /* @__PURE__ */
|
|
2724
|
+
children: /* @__PURE__ */ jsx44(
|
|
2566
2725
|
BasePreviewCard.Popup,
|
|
2567
2726
|
{
|
|
2568
2727
|
className: cn("w-[360px] p-0 outline-none", className),
|
|
2569
|
-
render: /* @__PURE__ */
|
|
2570
|
-
children: /* @__PURE__ */
|
|
2728
|
+
render: /* @__PURE__ */ jsx44(MenuPanel, {}),
|
|
2729
|
+
children: /* @__PURE__ */ jsx44(ScrollArea, { viewportClassName: "max-h-[min(300px,var(--available-height))]", contentClassName: cn("flex flex-col gap-3 p-3", contentClassName), children: content })
|
|
2571
2730
|
}
|
|
2572
2731
|
)
|
|
2573
2732
|
}
|
|
@@ -2576,15 +2735,15 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
|
|
|
2576
2735
|
}
|
|
2577
2736
|
|
|
2578
2737
|
// src/Rail.tsx
|
|
2579
|
-
import { jsx as
|
|
2738
|
+
import { jsx as jsx45 } from "react/jsx-runtime";
|
|
2580
2739
|
function Rail({ "aria-label": ariaLabel = "Navigation", children, className }) {
|
|
2581
|
-
return /* @__PURE__ */
|
|
2740
|
+
return /* @__PURE__ */ jsx45("nav", { "aria-label": ariaLabel, className: cn("flex w-16 shrink-0 flex-col items-start gap-2 px-2 py-3", className), children });
|
|
2582
2741
|
}
|
|
2583
2742
|
|
|
2584
2743
|
// src/RailItem.tsx
|
|
2585
|
-
import { jsx as
|
|
2744
|
+
import { jsx as jsx46, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2586
2745
|
function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
2587
|
-
return /* @__PURE__ */
|
|
2746
|
+
return /* @__PURE__ */ jsxs30(
|
|
2588
2747
|
"a",
|
|
2589
2748
|
{
|
|
2590
2749
|
href,
|
|
@@ -2592,14 +2751,14 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
|
2592
2751
|
className: cn("group flex h-12 w-full shrink-0 flex-col items-center gap-0.5 px-2 py-0.5", className),
|
|
2593
2752
|
...props,
|
|
2594
2753
|
children: [
|
|
2595
|
-
/* @__PURE__ */
|
|
2754
|
+
/* @__PURE__ */ jsx46(
|
|
2596
2755
|
"div",
|
|
2597
2756
|
{
|
|
2598
2757
|
className: cn(
|
|
2599
2758
|
"flex items-center justify-center rounded-lg p-2 transition-colors",
|
|
2600
2759
|
active ? "bg-bg-selected" : "group-hover:bg-bg-hover"
|
|
2601
2760
|
),
|
|
2602
|
-
children: /* @__PURE__ */
|
|
2761
|
+
children: /* @__PURE__ */ jsx46(
|
|
2603
2762
|
"span",
|
|
2604
2763
|
{
|
|
2605
2764
|
className: cn(
|
|
@@ -2611,27 +2770,27 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
|
2611
2770
|
)
|
|
2612
2771
|
}
|
|
2613
2772
|
),
|
|
2614
|
-
/* @__PURE__ */
|
|
2773
|
+
/* @__PURE__ */ jsx46("span", { className: cn("text-center text-menu", active ? "text-text-primary" : "text-text-secondary"), children: label })
|
|
2615
2774
|
]
|
|
2616
2775
|
}
|
|
2617
2776
|
);
|
|
2618
2777
|
}
|
|
2619
2778
|
|
|
2620
2779
|
// src/Sidebar.tsx
|
|
2621
|
-
import { jsx as
|
|
2780
|
+
import { jsx as jsx47 } from "react/jsx-runtime";
|
|
2622
2781
|
function Sidebar({ "aria-label": ariaLabel = "Workspace", children, className }) {
|
|
2623
|
-
return /* @__PURE__ */
|
|
2782
|
+
return /* @__PURE__ */ jsx47(
|
|
2624
2783
|
"nav",
|
|
2625
2784
|
{
|
|
2626
2785
|
"aria-label": ariaLabel,
|
|
2627
2786
|
className: cn("flex w-60 shrink-0 flex-col border-r border-border-default bg-bg-surface", className),
|
|
2628
|
-
children: /* @__PURE__ */
|
|
2787
|
+
children: /* @__PURE__ */ jsx47(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex flex-col gap-px px-2.5 py-3", children })
|
|
2629
2788
|
}
|
|
2630
2789
|
);
|
|
2631
2790
|
}
|
|
2632
2791
|
|
|
2633
2792
|
// src/Property.tsx
|
|
2634
|
-
import { jsx as
|
|
2793
|
+
import { jsx as jsx48, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2635
2794
|
var VALUE_CLASSES = "contents";
|
|
2636
2795
|
function Property({ label, layout = "row", children, className }) {
|
|
2637
2796
|
if (layout === "stacked") {
|
|
@@ -2639,23 +2798,23 @@ function Property({ label, layout = "row", children, className }) {
|
|
|
2639
2798
|
// gap-3 — the one label-above-content distance (Katerina, 2026-09-01):
|
|
2640
2799
|
// Peek's topic-details sections already sit at 12px, Ship's rail was
|
|
2641
2800
|
// 6px, and unifying means the bigger, calmer one.
|
|
2642
|
-
/* @__PURE__ */
|
|
2643
|
-
/* @__PURE__ */
|
|
2644
|
-
/* @__PURE__ */
|
|
2801
|
+
/* @__PURE__ */ jsxs31("dl", { className: cn("flex flex-col gap-3", className), children: [
|
|
2802
|
+
/* @__PURE__ */ jsx48("dt", { className: "text-menu uppercase tracking-widest text-text-secondary", children: label }),
|
|
2803
|
+
/* @__PURE__ */ jsx48("dd", { className: VALUE_CLASSES, children })
|
|
2645
2804
|
] })
|
|
2646
2805
|
);
|
|
2647
2806
|
}
|
|
2648
|
-
return /* @__PURE__ */
|
|
2649
|
-
/* @__PURE__ */
|
|
2650
|
-
/* @__PURE__ */
|
|
2807
|
+
return /* @__PURE__ */ jsxs31("dl", { className: cn("flex items-center gap-2", className), children: [
|
|
2808
|
+
/* @__PURE__ */ jsx48("dt", { className: "w-[68px] shrink-0 text-caption text-text-secondary", children: label }),
|
|
2809
|
+
/* @__PURE__ */ jsx48("dd", { className: VALUE_CLASSES, children })
|
|
2651
2810
|
] });
|
|
2652
2811
|
}
|
|
2653
2812
|
|
|
2654
2813
|
// src/Reaction.tsx
|
|
2655
2814
|
import { Toggle } from "@base-ui/react/toggle";
|
|
2656
|
-
import { jsx as
|
|
2815
|
+
import { jsx as jsx49, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
2657
2816
|
function Reaction({ emoji, count, pressed = false, className, ...props }) {
|
|
2658
|
-
return /* @__PURE__ */
|
|
2817
|
+
return /* @__PURE__ */ jsxs32(
|
|
2659
2818
|
Toggle,
|
|
2660
2819
|
{
|
|
2661
2820
|
pressed,
|
|
@@ -2677,8 +2836,8 @@ function Reaction({ emoji, count, pressed = false, className, ...props }) {
|
|
|
2677
2836
|
),
|
|
2678
2837
|
...props,
|
|
2679
2838
|
children: [
|
|
2680
|
-
/* @__PURE__ */
|
|
2681
|
-
/* @__PURE__ */
|
|
2839
|
+
/* @__PURE__ */ jsx49("span", { "aria-hidden": "true", className: "shrink-0 text-body-1 leading-none", children: emoji }),
|
|
2840
|
+
/* @__PURE__ */ jsx49("span", { className: "text-chip signal:font-mono signal:text-small signal:font-semibold signal:tabular-nums", children: count })
|
|
2682
2841
|
]
|
|
2683
2842
|
}
|
|
2684
2843
|
);
|
|
@@ -2687,9 +2846,9 @@ function Reaction({ emoji, count, pressed = false, className, ...props }) {
|
|
|
2687
2846
|
// src/SearchInput.tsx
|
|
2688
2847
|
import "react";
|
|
2689
2848
|
import { Input as Input3 } from "@base-ui/react/input";
|
|
2690
|
-
import { jsx as
|
|
2849
|
+
import { jsx as jsx50, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2691
2850
|
function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...props }) {
|
|
2692
|
-
return /* @__PURE__ */
|
|
2851
|
+
return /* @__PURE__ */ jsxs33(
|
|
2693
2852
|
"div",
|
|
2694
2853
|
{
|
|
2695
2854
|
className: cn(
|
|
@@ -2701,7 +2860,7 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
2701
2860
|
className
|
|
2702
2861
|
),
|
|
2703
2862
|
children: [
|
|
2704
|
-
/* @__PURE__ */
|
|
2863
|
+
/* @__PURE__ */ jsx50(
|
|
2705
2864
|
Input3,
|
|
2706
2865
|
{
|
|
2707
2866
|
className: "flex-1 min-w-0 bg-transparent text-input-value text-text-primary placeholder:text-text-muted outline-none",
|
|
@@ -2709,7 +2868,7 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
2709
2868
|
...props
|
|
2710
2869
|
}
|
|
2711
2870
|
),
|
|
2712
|
-
shortcut && /* @__PURE__ */
|
|
2871
|
+
shortcut && /* @__PURE__ */ jsx50(Kbd, { children: shortcut })
|
|
2713
2872
|
]
|
|
2714
2873
|
}
|
|
2715
2874
|
);
|
|
@@ -2718,17 +2877,17 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
2718
2877
|
// src/SectionHeader.tsx
|
|
2719
2878
|
import { IconChevronRight as IconChevronRight2 } from "@tabler/icons-react";
|
|
2720
2879
|
import { useRender } from "@base-ui/react/use-render";
|
|
2721
|
-
import { Fragment as Fragment8, jsx as
|
|
2880
|
+
import { Fragment as Fragment8, jsx as jsx51, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2722
2881
|
function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, trailing, actions, showActions = "hover", hover = "fill", render, className }) {
|
|
2723
2882
|
const titleElement = useRender({
|
|
2724
|
-
render: render ?? (chevron ? /* @__PURE__ */
|
|
2883
|
+
render: render ?? (chevron ? /* @__PURE__ */ jsx51("button", { type: "button", onClick: onToggle, "aria-expanded": isExpanded }) : /* @__PURE__ */ jsx51("span", {})),
|
|
2725
2884
|
props: {
|
|
2726
2885
|
// `text-left`: a button centres its text. `h-full` and `flex-1`: the
|
|
2727
2886
|
// whole row up to the actions is the hit target, as it was when the
|
|
2728
2887
|
// row itself carried the click.
|
|
2729
2888
|
className: "flex h-full min-w-0 flex-1 items-center gap-1 text-left",
|
|
2730
|
-
children: /* @__PURE__ */
|
|
2731
|
-
chevron && /* @__PURE__ */
|
|
2889
|
+
children: /* @__PURE__ */ jsxs34(Fragment8, { children: [
|
|
2890
|
+
chevron && /* @__PURE__ */ jsx51(
|
|
2732
2891
|
IconChevronRight2,
|
|
2733
2892
|
{
|
|
2734
2893
|
size: 12,
|
|
@@ -2736,11 +2895,11 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
|
|
|
2736
2895
|
className: cn("shrink-0 text-text-secondary transition-transform duration-150", isExpanded && "rotate-90")
|
|
2737
2896
|
}
|
|
2738
2897
|
),
|
|
2739
|
-
/* @__PURE__ */
|
|
2898
|
+
/* @__PURE__ */ jsx51(SectionLabel, { children: title })
|
|
2740
2899
|
] })
|
|
2741
2900
|
}
|
|
2742
2901
|
});
|
|
2743
|
-
return /* @__PURE__ */
|
|
2902
|
+
return /* @__PURE__ */ jsxs34(
|
|
2744
2903
|
"div",
|
|
2745
2904
|
{
|
|
2746
2905
|
className: cn(
|
|
@@ -2753,15 +2912,15 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
|
|
|
2753
2912
|
),
|
|
2754
2913
|
children: [
|
|
2755
2914
|
titleElement,
|
|
2756
|
-
trailing != null && /* @__PURE__ */
|
|
2757
|
-
actions && actions.length > 0 && /* @__PURE__ */
|
|
2915
|
+
trailing != null && /* @__PURE__ */ jsx51("div", { className: "flex shrink-0 items-center", children: trailing }),
|
|
2916
|
+
actions && actions.length > 0 && /* @__PURE__ */ jsx51(
|
|
2758
2917
|
"div",
|
|
2759
2918
|
{
|
|
2760
2919
|
className: cn(
|
|
2761
2920
|
"-mr-1 flex shrink-0 items-center gap-1",
|
|
2762
2921
|
showActions === "hover" && "opacity-0 transition-opacity focus-within:opacity-100 group-hover:opacity-100"
|
|
2763
2922
|
),
|
|
2764
|
-
children: actions.map((action) => /* @__PURE__ */
|
|
2923
|
+
children: actions.map((action) => /* @__PURE__ */ jsx51(IconButton, { tooltip: action.tooltip, "aria-label": action.tooltip, onClick: action.onClick, children: action.icon }, action.tooltip))
|
|
2765
2924
|
}
|
|
2766
2925
|
)
|
|
2767
2926
|
]
|
|
@@ -2771,22 +2930,22 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
|
|
|
2771
2930
|
|
|
2772
2931
|
// src/ContainerHeader.tsx
|
|
2773
2932
|
import { IconChevronDown as IconChevronDown3 } from "@tabler/icons-react";
|
|
2774
|
-
import { jsx as
|
|
2933
|
+
import { jsx as jsx52, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2775
2934
|
function ContainerHeader({ title, chevron = false, actions, className }) {
|
|
2776
2935
|
const text = typeof title === "string";
|
|
2777
|
-
return /* @__PURE__ */
|
|
2778
|
-
/* @__PURE__ */
|
|
2779
|
-
text ? /* @__PURE__ */
|
|
2780
|
-
chevron && /* @__PURE__ */
|
|
2936
|
+
return /* @__PURE__ */ jsxs35("div", { className: cn("flex h-12 shrink-0 items-center justify-between overflow-hidden border-b border-border-subtle py-2 pr-4 pl-5", className), children: [
|
|
2937
|
+
/* @__PURE__ */ jsx52("div", { className: cn("flex items-center gap-2 overflow-hidden", text ? "shrink-0" : "min-w-0 flex-1"), children: /* @__PURE__ */ jsxs35("div", { className: cn("flex items-center gap-1", text ? "shrink-0" : "min-w-0 flex-1"), children: [
|
|
2938
|
+
text ? /* @__PURE__ */ jsx52("span", { className: "whitespace-nowrap text-body-2-strong text-text-primary", children: title }) : /* @__PURE__ */ jsx52("div", { className: "min-w-0 flex-1", children: title }),
|
|
2939
|
+
chevron && /* @__PURE__ */ jsx52(IconChevronDown3, { size: 12, stroke: 1.5, className: "shrink-0 text-text-secondary" })
|
|
2781
2940
|
] }) }),
|
|
2782
|
-
actions && /* @__PURE__ */
|
|
2941
|
+
actions && /* @__PURE__ */ jsx52("div", { className: "flex shrink-0 items-center justify-end gap-3", children: /* @__PURE__ */ jsx52("div", { className: "flex shrink-0 items-center gap-1", children: actions }) })
|
|
2783
2942
|
] });
|
|
2784
2943
|
}
|
|
2785
2944
|
|
|
2786
2945
|
// src/ListColumn.tsx
|
|
2787
|
-
import { jsx as
|
|
2788
|
-
function
|
|
2789
|
-
return /* @__PURE__ */
|
|
2946
|
+
import { jsx as jsx53, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
2947
|
+
function Column({ title, chevron = false, actions, above, collapsed = false, children, className, broken = false }) {
|
|
2948
|
+
return /* @__PURE__ */ jsxs36(
|
|
2790
2949
|
"div",
|
|
2791
2950
|
{
|
|
2792
2951
|
className: cn(
|
|
@@ -2797,18 +2956,34 @@ function ListColumn({ title, chevron = false, actions, above, spacing = "rows",
|
|
|
2797
2956
|
),
|
|
2798
2957
|
"data-collapsed": collapsed || void 0,
|
|
2799
2958
|
children: [
|
|
2800
|
-
/* @__PURE__ */
|
|
2959
|
+
/* @__PURE__ */ jsx53(ContainerHeader, { title, chevron, actions }),
|
|
2801
2960
|
above,
|
|
2802
|
-
|
|
2961
|
+
broken ? (
|
|
2962
|
+
// The message takes the room the list had and centres itself in it (Katerina, 19 September).
|
|
2963
|
+
/* @__PURE__ */ jsx53("div", { className: "flex min-h-0 flex-1 flex-col px-3", children })
|
|
2964
|
+
) : /* @__PURE__ */ jsx53(ScrollArea, { className: "flex-1", contentClassName: "flex flex-col gap-0.5 px-3 pt-4 pb-3", children })
|
|
2803
2965
|
]
|
|
2804
2966
|
}
|
|
2805
2967
|
);
|
|
2806
2968
|
}
|
|
2969
|
+
function ListColumn(props) {
|
|
2970
|
+
return /* @__PURE__ */ jsx53(
|
|
2971
|
+
ErrorBoundary,
|
|
2972
|
+
{
|
|
2973
|
+
label: "list panel",
|
|
2974
|
+
frame: (message) => (
|
|
2975
|
+
// Only the name comes back with the message: the actions and the row above may be what threw.
|
|
2976
|
+
/* @__PURE__ */ jsx53(Column, { title: props.title, chevron: props.chevron, collapsed: props.collapsed, className: props.className, broken: true, children: message })
|
|
2977
|
+
),
|
|
2978
|
+
children: /* @__PURE__ */ jsx53(Column, { ...props })
|
|
2979
|
+
}
|
|
2980
|
+
);
|
|
2981
|
+
}
|
|
2807
2982
|
|
|
2808
2983
|
// src/CollapsibleSection.tsx
|
|
2809
2984
|
import { useState as useState7 } from "react";
|
|
2810
2985
|
import { Collapsible } from "@base-ui/react/collapsible";
|
|
2811
|
-
import { jsx as
|
|
2986
|
+
import { jsx as jsx54, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
2812
2987
|
var OPEN = "open";
|
|
2813
2988
|
var CLOSED = "closed";
|
|
2814
2989
|
function readStored(key) {
|
|
@@ -2835,14 +3010,14 @@ function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenC
|
|
|
2835
3010
|
writeStored(storageKey, next);
|
|
2836
3011
|
onOpenChange?.(next);
|
|
2837
3012
|
};
|
|
2838
|
-
return /* @__PURE__ */
|
|
2839
|
-
/* @__PURE__ */
|
|
2840
|
-
/* @__PURE__ */
|
|
3013
|
+
return /* @__PURE__ */ jsxs37(Collapsible.Root, { open, onOpenChange: setOpen, className: cn("flex flex-col", className), children: [
|
|
3014
|
+
/* @__PURE__ */ jsx54(SectionHeader, { title, chevron: true, isExpanded: open, trailing, actions, showActions, className: "shrink-0", render: /* @__PURE__ */ jsx54(Collapsible.Trigger, {}) }),
|
|
3015
|
+
/* @__PURE__ */ jsx54(
|
|
2841
3016
|
Collapsible.Panel,
|
|
2842
3017
|
{
|
|
2843
3018
|
hiddenUntilFound: true,
|
|
2844
3019
|
className: "h-[var(--collapsible-panel-height)] overflow-hidden transition-[height] duration-150 ease-out motion-reduce:transition-none data-[starting-style]:h-0 data-[ending-style]:h-0",
|
|
2845
|
-
children: /* @__PURE__ */
|
|
3020
|
+
children: /* @__PURE__ */ jsx54("div", { className: cn("flex flex-col", contentClassName), children })
|
|
2846
3021
|
}
|
|
2847
3022
|
)
|
|
2848
3023
|
] });
|
|
@@ -2850,9 +3025,9 @@ function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenC
|
|
|
2850
3025
|
|
|
2851
3026
|
// src/Tabs.tsx
|
|
2852
3027
|
import { Tabs as BaseTabs } from "@base-ui/react/tabs";
|
|
2853
|
-
import { jsx as
|
|
3028
|
+
import { jsx as jsx55, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
2854
3029
|
function Tabs({ tabs, active, onChange, size = "default", className, ...aria }) {
|
|
2855
|
-
return /* @__PURE__ */
|
|
3030
|
+
return /* @__PURE__ */ jsx55(
|
|
2856
3031
|
BaseTabs.Root,
|
|
2857
3032
|
{
|
|
2858
3033
|
value: active,
|
|
@@ -2860,14 +3035,14 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
2860
3035
|
if (details.reason === "none") onChange(value);
|
|
2861
3036
|
},
|
|
2862
3037
|
className,
|
|
2863
|
-
children: /* @__PURE__ */
|
|
3038
|
+
children: /* @__PURE__ */ jsx55(
|
|
2864
3039
|
BaseTabs.List,
|
|
2865
3040
|
{
|
|
2866
3041
|
activateOnFocus: true,
|
|
2867
3042
|
"aria-label": aria["aria-label"],
|
|
2868
3043
|
"aria-labelledby": aria["aria-labelledby"],
|
|
2869
3044
|
className: "flex items-center gap-2",
|
|
2870
|
-
children: tabs.map((tab) => /* @__PURE__ */
|
|
3045
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsxs38(
|
|
2871
3046
|
BaseTabs.Tab,
|
|
2872
3047
|
{
|
|
2873
3048
|
value: tab.id,
|
|
@@ -2880,9 +3055,9 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
2880
3055
|
),
|
|
2881
3056
|
children: [
|
|
2882
3057
|
tab.icon,
|
|
2883
|
-
/* @__PURE__ */
|
|
3058
|
+
/* @__PURE__ */ jsxs38("span", { className: "flex items-baseline", children: [
|
|
2884
3059
|
tab.label,
|
|
2885
|
-
tab.count !== void 0 ? /* @__PURE__ */
|
|
3060
|
+
tab.count !== void 0 ? /* @__PURE__ */ jsx55("span", { className: "ml-2.5 font-mono text-caption tabular-nums text-text-secondary", children: tab.count }) : null
|
|
2886
3061
|
] })
|
|
2887
3062
|
]
|
|
2888
3063
|
},
|
|
@@ -2898,7 +3073,7 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
2898
3073
|
import { createContext as createContext5, useContext as useContext5, useMemo as useMemo4 } from "react";
|
|
2899
3074
|
import { Toast as BaseToast } from "@base-ui/react/toast";
|
|
2900
3075
|
import { IconAlertCircle as IconAlertCircle2, IconCircleCheck, IconCircleX } from "@tabler/icons-react";
|
|
2901
|
-
import { jsx as
|
|
3076
|
+
import { jsx as jsx56, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
2902
3077
|
var SURFACE_STYLES = {
|
|
2903
3078
|
success: "bg-success-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md",
|
|
2904
3079
|
brand: "bg-accent-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md",
|
|
@@ -2934,16 +3109,16 @@ var pillClassName = (type, hasAction, className) => cn(
|
|
|
2934
3109
|
);
|
|
2935
3110
|
function LeadingIcon({ type }) {
|
|
2936
3111
|
const Icon = ICONS[type];
|
|
2937
|
-
return /* @__PURE__ */
|
|
3112
|
+
return /* @__PURE__ */ jsx56(Icon, { size: 16, stroke: 1.5, className: cn("text-text-primary shrink-0", ICON_STYLES[type]) });
|
|
2938
3113
|
}
|
|
2939
3114
|
function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAction, className }) {
|
|
2940
3115
|
const hasAction = !!(actionLabel && onAction);
|
|
2941
|
-
return /* @__PURE__ */
|
|
2942
|
-
/* @__PURE__ */
|
|
2943
|
-
leadingIcon && /* @__PURE__ */
|
|
2944
|
-
/* @__PURE__ */
|
|
3116
|
+
return /* @__PURE__ */ jsxs39("div", { className: pillClassName(type, hasAction, className), children: [
|
|
3117
|
+
/* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
3118
|
+
leadingIcon && /* @__PURE__ */ jsx56(LeadingIcon, { type }),
|
|
3119
|
+
/* @__PURE__ */ jsx56("span", { className: LABEL_CLASSES, children: label })
|
|
2945
3120
|
] }),
|
|
2946
|
-
hasAction && /* @__PURE__ */
|
|
3121
|
+
hasAction && /* @__PURE__ */ jsx56(Button, { variant: "outlined", size: "small", onClick: onAction, children: actionLabel })
|
|
2947
3122
|
] });
|
|
2948
3123
|
}
|
|
2949
3124
|
var ToastContext = createContext5(null);
|
|
@@ -2964,9 +3139,9 @@ function ToastProvider({ children }) {
|
|
|
2964
3139
|
}),
|
|
2965
3140
|
[manager]
|
|
2966
3141
|
);
|
|
2967
|
-
return /* @__PURE__ */
|
|
3142
|
+
return /* @__PURE__ */ jsx56(ToastContext.Provider, { value, children: /* @__PURE__ */ jsxs39(BaseToast.Provider, { toastManager: manager, limit: VISIBLE_TOASTS, children: [
|
|
2968
3143
|
children,
|
|
2969
|
-
/* @__PURE__ */
|
|
3144
|
+
/* @__PURE__ */ jsx56(BaseToast.Portal, { children: /* @__PURE__ */ jsx56(BaseToast.Viewport, { className: "fixed bottom-4 left-4 z-[100] flex flex-col-reverse items-start gap-2 pointer-events-none", children: /* @__PURE__ */ jsx56(ToastList, {}) }) })
|
|
2970
3145
|
] }) });
|
|
2971
3146
|
}
|
|
2972
3147
|
function ToastList() {
|
|
@@ -2974,25 +3149,25 @@ function ToastList() {
|
|
|
2974
3149
|
return toasts.map((toast) => {
|
|
2975
3150
|
const type = toast.type ?? "neutral";
|
|
2976
3151
|
const { leadingIcon = true, actionLabel, onAction } = toast.data ?? {};
|
|
2977
|
-
return /* @__PURE__ */
|
|
3152
|
+
return /* @__PURE__ */ jsxs39(
|
|
2978
3153
|
BaseToast.Root,
|
|
2979
3154
|
{
|
|
2980
3155
|
toast,
|
|
2981
3156
|
swipeDirection: ["left", "down"],
|
|
2982
3157
|
className: pillClassName(type, !!actionLabel, "pointer-events-auto data-[limited]:hidden"),
|
|
2983
3158
|
children: [
|
|
2984
|
-
/* @__PURE__ */
|
|
2985
|
-
leadingIcon && /* @__PURE__ */
|
|
2986
|
-
/* @__PURE__ */
|
|
3159
|
+
/* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
3160
|
+
leadingIcon && /* @__PURE__ */ jsx56(LeadingIcon, { type }),
|
|
3161
|
+
/* @__PURE__ */ jsx56(BaseToast.Title, { render: /* @__PURE__ */ jsx56("span", {}), className: LABEL_CLASSES })
|
|
2987
3162
|
] }),
|
|
2988
|
-
actionLabel && /* @__PURE__ */
|
|
3163
|
+
actionLabel && /* @__PURE__ */ jsx56(
|
|
2989
3164
|
BaseToast.Action,
|
|
2990
3165
|
{
|
|
2991
3166
|
onClick: () => {
|
|
2992
3167
|
onAction?.();
|
|
2993
3168
|
close(toast.id);
|
|
2994
3169
|
},
|
|
2995
|
-
render: /* @__PURE__ */
|
|
3170
|
+
render: /* @__PURE__ */ jsx56(Button, { variant: "outlined", size: "small", children: actionLabel })
|
|
2996
3171
|
}
|
|
2997
3172
|
)
|
|
2998
3173
|
]
|
|
@@ -3032,6 +3207,7 @@ export {
|
|
|
3032
3207
|
EditableText,
|
|
3033
3208
|
EmptyState,
|
|
3034
3209
|
EnterHint,
|
|
3210
|
+
ErrorBoundary,
|
|
3035
3211
|
Field,
|
|
3036
3212
|
FieldLine,
|
|
3037
3213
|
FilePicker,
|
|
@@ -3044,6 +3220,7 @@ export {
|
|
|
3044
3220
|
InlineChip,
|
|
3045
3221
|
InputChip,
|
|
3046
3222
|
Kbd,
|
|
3223
|
+
Lightbox,
|
|
3047
3224
|
Link,
|
|
3048
3225
|
ListColumn,
|
|
3049
3226
|
Menu,
|
|
@@ -3051,6 +3228,7 @@ export {
|
|
|
3051
3228
|
MenuPanel,
|
|
3052
3229
|
MenuRow,
|
|
3053
3230
|
MenuSection,
|
|
3231
|
+
MenuSeparator,
|
|
3054
3232
|
MenuSub,
|
|
3055
3233
|
NavItem,
|
|
3056
3234
|
Person,
|