@estiva-app/ui 0.10.1 → 0.12.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/AppShell.d.ts.map +1 -1
- package/dist/Breadcrumb.d.ts +7 -1
- package/dist/Breadcrumb.d.ts.map +1 -1
- package/dist/Chip.d.ts.map +1 -1
- package/dist/CollapsibleSection.d.ts +42 -0
- package/dist/CollapsibleSection.d.ts.map +1 -0
- package/dist/Divider.d.ts +15 -1
- package/dist/Divider.d.ts.map +1 -1
- package/dist/EmptyState.d.ts +19 -5
- package/dist/EmptyState.d.ts.map +1 -1
- package/dist/Menu.d.ts.map +1 -1
- package/dist/NavItem.d.ts.map +1 -1
- package/dist/Popover.d.ts.map +1 -1
- package/dist/PreviewCard.d.ts.map +1 -1
- package/dist/Reaction.d.ts.map +1 -1
- package/dist/ScrollArea.d.ts +46 -0
- package/dist/ScrollArea.d.ts.map +1 -0
- package/dist/SectionHeader.d.ts +31 -10
- package/dist/SectionHeader.d.ts.map +1 -1
- package/dist/Select.d.ts.map +1 -1
- package/dist/Sidebar.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +375 -266
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/src/AppShell.tsx +5 -0
- package/src/Breadcrumb.mdx +6 -0
- package/src/Breadcrumb.stories.tsx +12 -0
- package/src/Breadcrumb.test.tsx +10 -0
- package/src/Breadcrumb.tsx +17 -2
- package/src/Chip.tsx +10 -2
- package/src/CollapsibleSection.mdx +72 -0
- package/src/CollapsibleSection.stories.tsx +38 -0
- package/src/CollapsibleSection.test.tsx +81 -0
- package/src/CollapsibleSection.tsx +92 -0
- package/src/Divider.mdx +9 -0
- package/src/Divider.stories.tsx +25 -0
- package/src/Divider.test.tsx +26 -0
- package/src/Divider.tsx +30 -1
- package/src/EmptyState.mdx +30 -11
- package/src/EmptyState.stories.tsx +7 -3
- package/src/EmptyState.test.tsx +39 -0
- package/src/EmptyState.tsx +23 -6
- package/src/Menu.tsx +11 -2
- package/src/NavItem.tsx +5 -1
- package/src/Popover.tsx +6 -2
- package/src/PreviewCard.tsx +5 -2
- package/src/Reaction.tsx +6 -1
- package/src/ScrollArea.mdx +65 -0
- package/src/ScrollArea.stories.tsx +104 -0
- package/src/ScrollArea.test.tsx +65 -0
- package/src/ScrollArea.tsx +94 -0
- package/src/SectionHeader.mdx +26 -17
- package/src/SectionHeader.stories.tsx +4 -35
- package/src/SectionHeader.test.tsx +40 -0
- package/src/SectionHeader.tsx +70 -39
- package/src/Select.tsx +8 -1
- package/src/Sidebar.mdx +14 -10
- package/src/Sidebar.stories.tsx +17 -15
- package/src/Sidebar.tsx +8 -5
- package/src/index.ts +2 -0
- package/stories/Choosing.mdx +2 -1
package/dist/index.js
CHANGED
|
@@ -419,9 +419,17 @@ var typeStyles = {
|
|
|
419
419
|
error: "bg-error-muted text-error-default signal:border signal:border-error-outline"
|
|
420
420
|
};
|
|
421
421
|
function Chip({ type = "neutral", label, leadingIcon, trailingIcon, className }) {
|
|
422
|
-
return /* @__PURE__ */ jsxs6("div", { className: cn("inline-flex items-center justify-center gap-1.5 rounded-full max-h-[20px]
|
|
422
|
+
return /* @__PURE__ */ jsxs6("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: [
|
|
423
423
|
leadingIcon && /* @__PURE__ */ jsx11("span", { className: "flex size-3 shrink-0 items-center justify-center", children: leadingIcon }),
|
|
424
|
-
label &&
|
|
424
|
+
label && // A chip given a `max-w-*` cuts a long label with an ellipsis instead
|
|
425
|
+
// of growing past it — Ship's project chip on an issue row
|
|
426
|
+
// (2026-09-09). Clipped sideways only: `overflow-x-clip`, not
|
|
427
|
+
// `truncate`, because `truncate` is `overflow: hidden` on both axes and
|
|
428
|
+
// the label's line box (11px under Signal) is tighter than its glyphs —
|
|
429
|
+
// the screenshot diff caught every descender cut off. `clip` is the
|
|
430
|
+
// one overflow that leaves the other axis visible. A chip with no cap
|
|
431
|
+
// draws exactly as before.
|
|
432
|
+
/* @__PURE__ */ jsx11("span", { className: "min-w-0 overflow-x-clip text-ellipsis whitespace-nowrap text-chip signal:font-mono signal:text-[10px] signal:font-semibold signal:tracking-[0.02em] signal:tabular-nums", children: label }),
|
|
425
433
|
trailingIcon && /* @__PURE__ */ jsx11("span", { className: "flex size-3 shrink-0 items-center justify-center", children: trailingIcon })
|
|
426
434
|
] });
|
|
427
435
|
}
|
|
@@ -459,10 +467,35 @@ function triggerDisabled(trigger) {
|
|
|
459
467
|
return !!(props.disabled || props.disabledReason);
|
|
460
468
|
}
|
|
461
469
|
|
|
470
|
+
// src/ScrollArea.tsx
|
|
471
|
+
import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area";
|
|
472
|
+
import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
473
|
+
var BAR = "flex touch-none select-none rounded-full opacity-0 transition-opacity delay-300 data-[hovering]:opacity-100 data-[hovering]:delay-0 data-[scrolling]:opacity-100 data-[scrolling]:delay-0";
|
|
474
|
+
var THUMB = "rounded-full bg-border-strong";
|
|
475
|
+
function ScrollArea({ orientation = "vertical", className, viewportClassName, contentClassName, children }) {
|
|
476
|
+
const vertical = orientation !== "horizontal";
|
|
477
|
+
const horizontal = orientation !== "vertical";
|
|
478
|
+
return /* @__PURE__ */ jsxs7(BaseScrollArea.Root, { className: cn("relative min-h-0 min-w-0", className), children: [
|
|
479
|
+
/* @__PURE__ */ jsx12(
|
|
480
|
+
BaseScrollArea.Viewport,
|
|
481
|
+
{
|
|
482
|
+
className: cn(
|
|
483
|
+
"h-full w-full outline-none data-[has-overflow-x]:overscroll-x-contain data-[has-overflow-y]:overscroll-y-contain",
|
|
484
|
+
viewportClassName
|
|
485
|
+
),
|
|
486
|
+
children: /* @__PURE__ */ jsx12(BaseScrollArea.Content, { className: contentClassName, style: horizontal ? void 0 : { minWidth: 0 }, children })
|
|
487
|
+
}
|
|
488
|
+
),
|
|
489
|
+
vertical && /* @__PURE__ */ jsx12(BaseScrollArea.Scrollbar, { orientation: "vertical", className: cn(BAR, "w-1.5 justify-center py-0.5 pr-0.5"), children: /* @__PURE__ */ jsx12(BaseScrollArea.Thumb, { className: cn(THUMB, "w-full") }) }),
|
|
490
|
+
horizontal && /* @__PURE__ */ jsx12(BaseScrollArea.Scrollbar, { orientation: "horizontal", className: cn(BAR, "h-1.5 flex-col justify-center px-0.5 pb-0.5"), children: /* @__PURE__ */ jsx12(BaseScrollArea.Thumb, { className: cn(THUMB, "h-full") }) }),
|
|
491
|
+
vertical && horizontal && /* @__PURE__ */ jsx12(BaseScrollArea.Corner, {})
|
|
492
|
+
] });
|
|
493
|
+
}
|
|
494
|
+
|
|
462
495
|
// src/SectionLabel.tsx
|
|
463
|
-
import { jsx as
|
|
496
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
464
497
|
function SectionLabel({ children, className }) {
|
|
465
|
-
return /* @__PURE__ */
|
|
498
|
+
return /* @__PURE__ */ jsx13(
|
|
466
499
|
"span",
|
|
467
500
|
{
|
|
468
501
|
className: cn(
|
|
@@ -475,10 +508,10 @@ function SectionLabel({ children, className }) {
|
|
|
475
508
|
}
|
|
476
509
|
|
|
477
510
|
// src/Menu.tsx
|
|
478
|
-
import { Fragment, jsx as
|
|
511
|
+
import { Fragment, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
479
512
|
var MenuContext = createContext(null);
|
|
480
513
|
function MenuPanel({ children, className, ...props }) {
|
|
481
|
-
return /* @__PURE__ */
|
|
514
|
+
return /* @__PURE__ */ jsx14(
|
|
482
515
|
"div",
|
|
483
516
|
{
|
|
484
517
|
className: cn(
|
|
@@ -508,7 +541,7 @@ var VIEWPORT_PAD2 = 8;
|
|
|
508
541
|
var HOVER_OPEN_DELAY = 0;
|
|
509
542
|
var HOVER_CLOSE_DELAY = 150;
|
|
510
543
|
function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange, actionsRef, children, className }) {
|
|
511
|
-
return /* @__PURE__ */
|
|
544
|
+
return /* @__PURE__ */ jsxs8(
|
|
512
545
|
BaseMenu.Root,
|
|
513
546
|
{
|
|
514
547
|
open,
|
|
@@ -516,7 +549,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
516
549
|
actionsRef,
|
|
517
550
|
modal: false,
|
|
518
551
|
children: [
|
|
519
|
-
/* @__PURE__ */
|
|
552
|
+
/* @__PURE__ */ jsx14(
|
|
520
553
|
BaseMenu.Trigger,
|
|
521
554
|
{
|
|
522
555
|
render: trigger,
|
|
@@ -526,7 +559,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
526
559
|
closeDelay: HOVER_CLOSE_DELAY
|
|
527
560
|
}
|
|
528
561
|
),
|
|
529
|
-
/* @__PURE__ */
|
|
562
|
+
/* @__PURE__ */ jsx14(BaseMenu.Portal, { children: /* @__PURE__ */ jsx14(
|
|
530
563
|
BaseMenu.Positioner,
|
|
531
564
|
{
|
|
532
565
|
side: "bottom",
|
|
@@ -534,13 +567,13 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
|
|
|
534
567
|
sideOffset: GAP3,
|
|
535
568
|
collisionPadding: VIEWPORT_PAD2,
|
|
536
569
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
537
|
-
children: /* @__PURE__ */
|
|
570
|
+
children: /* @__PURE__ */ jsx14(
|
|
538
571
|
BaseMenu.Popup,
|
|
539
572
|
{
|
|
540
573
|
"data-interactive": true,
|
|
541
|
-
className: cn("min-w-[180px]
|
|
542
|
-
render: /* @__PURE__ */
|
|
543
|
-
children: /* @__PURE__ */
|
|
574
|
+
className: cn("min-w-[180px] outline-none", className),
|
|
575
|
+
render: /* @__PURE__ */ jsx14(MenuPanel, {}),
|
|
576
|
+
children: /* @__PURE__ */ jsx14(ScrollArea, { viewportClassName: "max-h-[calc(var(--available-height)_-_1rem)]", contentClassName: "flex flex-col [&>[role=separator]]:mx-0", children: /* @__PURE__ */ jsx14(MenuContext.Provider, { value: { openOnHover }, children }) })
|
|
544
577
|
}
|
|
545
578
|
)
|
|
546
579
|
}
|
|
@@ -556,20 +589,20 @@ function MenuSub({ label, leading, selected, children, className }) {
|
|
|
556
589
|
'[@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".'
|
|
557
590
|
);
|
|
558
591
|
}
|
|
559
|
-
return /* @__PURE__ */
|
|
560
|
-
/* @__PURE__ */
|
|
592
|
+
return /* @__PURE__ */ jsxs8(BaseMenu.SubmenuRoot, { children: [
|
|
593
|
+
/* @__PURE__ */ jsx14(
|
|
561
594
|
BaseMenu.SubmenuTrigger,
|
|
562
595
|
{
|
|
563
596
|
openOnHover: true,
|
|
564
597
|
delay: 0,
|
|
565
598
|
closeDelay: 150,
|
|
566
599
|
nativeButton: true,
|
|
567
|
-
render: /* @__PURE__ */
|
|
600
|
+
render: /* @__PURE__ */ jsx14("button", { type: "button" }),
|
|
568
601
|
className: menuItemClassName({ size: "default", selected }),
|
|
569
|
-
children: /* @__PURE__ */
|
|
602
|
+
children: /* @__PURE__ */ jsx14(MenuItemBody, { label, leading, submenu: true })
|
|
570
603
|
}
|
|
571
604
|
),
|
|
572
|
-
/* @__PURE__ */
|
|
605
|
+
/* @__PURE__ */ jsx14(BaseMenu.Portal, { children: /* @__PURE__ */ jsx14(
|
|
573
606
|
BaseMenu.Positioner,
|
|
574
607
|
{
|
|
575
608
|
side: "inline-end",
|
|
@@ -577,7 +610,7 @@ function MenuSub({ label, leading, selected, children, className }) {
|
|
|
577
610
|
sideOffset: GAP3,
|
|
578
611
|
collisionPadding: VIEWPORT_PAD2,
|
|
579
612
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
580
|
-
children: /* @__PURE__ */
|
|
613
|
+
children: /* @__PURE__ */ jsx14(BaseMenu.Popup, { className: cn("w-[160px]", className), "data-interactive": true, render: /* @__PURE__ */ jsx14(MenuPanel, {}), children })
|
|
581
614
|
}
|
|
582
615
|
) })
|
|
583
616
|
] });
|
|
@@ -609,25 +642,25 @@ function menuItemClassName({ size, selected, className }) {
|
|
|
609
642
|
);
|
|
610
643
|
}
|
|
611
644
|
function MenuItemBody({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected }) {
|
|
612
|
-
const edge = trailing ?? (shortcut ? /* @__PURE__ */
|
|
613
|
-
return /* @__PURE__ */
|
|
614
|
-
leading && /* @__PURE__ */
|
|
615
|
-
children ?? /* @__PURE__ */
|
|
616
|
-
/* @__PURE__ */
|
|
617
|
-
description && /* @__PURE__ */
|
|
645
|
+
const edge = trailing ?? (shortcut ? /* @__PURE__ */ jsx14(Kbd, { children: shortcut }) : submenu ? /* @__PURE__ */ jsx14(IconChevronRight, { size: 16, stroke: 1.5, className: "shrink-0 text-text-muted" }) : null);
|
|
646
|
+
return /* @__PURE__ */ jsxs8(Fragment, { children: [
|
|
647
|
+
leading && /* @__PURE__ */ jsx14("span", { className: "flex shrink-0 items-center", children: leading }),
|
|
648
|
+
children ?? /* @__PURE__ */ jsxs8("span", { className: cn("flex min-w-0 flex-1 flex-col", size === "tall" && "gap-[2px]"), children: [
|
|
649
|
+
/* @__PURE__ */ jsx14("span", { className: cn("truncate text-[14px] leading-[140%]", destructive ? "text-error-default" : "text-text-primary"), children: label }),
|
|
650
|
+
description && /* @__PURE__ */ jsx14("span", { className: "truncate text-[12px] leading-[120%] text-text-secondary", children: description })
|
|
618
651
|
] }),
|
|
619
652
|
(edge || hint) && // One grid cell holding both, right-aligned: the slot is as wide as
|
|
620
653
|
// the wider of the two and never changes, so revealing the hint moves
|
|
621
654
|
// nothing. No transition here either — the hint switches on the same
|
|
622
655
|
// :hover / `selected` as the fill, in the same frame.
|
|
623
|
-
/* @__PURE__ */
|
|
624
|
-
edge && /* @__PURE__ */
|
|
625
|
-
hint && /* @__PURE__ */
|
|
656
|
+
/* @__PURE__ */ jsxs8("span", { className: "grid shrink-0 items-center justify-items-end [&>*]:col-start-1 [&>*]:row-start-1", children: [
|
|
657
|
+
edge && /* @__PURE__ */ jsx14("span", { className: cn("flex items-center", hint && "group-hover:opacity-0 group-data-[highlighted]:opacity-0", hint && selected && "opacity-0"), children: edge }),
|
|
658
|
+
hint && /* @__PURE__ */ jsx14("span", { className: cn("flex items-center opacity-0 group-hover:opacity-100 group-data-[highlighted]:opacity-100", selected && "opacity-100"), children: hint })
|
|
626
659
|
] })
|
|
627
660
|
] });
|
|
628
661
|
}
|
|
629
662
|
function MenuItem({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected, className, ...props }) {
|
|
630
|
-
const body = /* @__PURE__ */
|
|
663
|
+
const body = /* @__PURE__ */ jsx14(
|
|
631
664
|
MenuItemBody,
|
|
632
665
|
{
|
|
633
666
|
label,
|
|
@@ -645,13 +678,13 @@ function MenuItem({ label, children, size = "default", description, leading, tra
|
|
|
645
678
|
);
|
|
646
679
|
const rowClassName = menuItemClassName({ size, selected, className });
|
|
647
680
|
if (!useContext(MenuContext)) {
|
|
648
|
-
return /* @__PURE__ */
|
|
681
|
+
return /* @__PURE__ */ jsx14("button", { type: "button", className: rowClassName, ...props, children: body });
|
|
649
682
|
}
|
|
650
|
-
return /* @__PURE__ */
|
|
683
|
+
return /* @__PURE__ */ jsx14(
|
|
651
684
|
BaseMenu.Item,
|
|
652
685
|
{
|
|
653
686
|
nativeButton: true,
|
|
654
|
-
render: /* @__PURE__ */
|
|
687
|
+
render: /* @__PURE__ */ jsx14("button", { type: "button" }),
|
|
655
688
|
className: rowClassName,
|
|
656
689
|
...props,
|
|
657
690
|
children: body
|
|
@@ -659,33 +692,33 @@ function MenuItem({ label, children, size = "default", description, leading, tra
|
|
|
659
692
|
);
|
|
660
693
|
}
|
|
661
694
|
function EnterHint({ target }) {
|
|
662
|
-
return /* @__PURE__ */
|
|
663
|
-
/* @__PURE__ */
|
|
664
|
-
target && /* @__PURE__ */
|
|
695
|
+
return /* @__PURE__ */ jsxs8("span", { className: "flex shrink-0 items-center gap-1.5 text-text-muted", children: [
|
|
696
|
+
/* @__PURE__ */ jsx14(Kbd, { children: "\u21A9 Enter" }),
|
|
697
|
+
target && /* @__PURE__ */ jsx14("span", { className: "text-[9px] font-medium leading-[115%] signal:font-mono signal:text-[9.5px] signal:tracking-[0.04em]", children: target })
|
|
665
698
|
] });
|
|
666
699
|
}
|
|
667
700
|
function MenuSection({ label, children, className }) {
|
|
668
701
|
const inMenu = useContext(MenuContext) !== null;
|
|
669
|
-
const heading = /* @__PURE__ */
|
|
702
|
+
const heading = /* @__PURE__ */ jsx14("div", { className: cn("flex h-8 items-center px-2", className), children: /* @__PURE__ */ jsx14(SectionLabel, { className: "text-text-secondary", children: label }) });
|
|
670
703
|
if (!inMenu) {
|
|
671
|
-
return /* @__PURE__ */
|
|
704
|
+
return /* @__PURE__ */ jsxs8("div", { className: "flex flex-col", children: [
|
|
672
705
|
heading,
|
|
673
706
|
children
|
|
674
707
|
] });
|
|
675
708
|
}
|
|
676
|
-
return /* @__PURE__ */
|
|
677
|
-
/* @__PURE__ */
|
|
709
|
+
return /* @__PURE__ */ jsxs8(BaseMenu.Group, { className: "flex flex-col", children: [
|
|
710
|
+
/* @__PURE__ */ jsx14(BaseMenu.GroupLabel, { render: heading }),
|
|
678
711
|
children
|
|
679
712
|
] });
|
|
680
713
|
}
|
|
681
714
|
function MenuRow({ children, className }) {
|
|
682
|
-
return /* @__PURE__ */
|
|
715
|
+
return /* @__PURE__ */ jsx14("div", { className: cn("flex items-center gap-2 px-2 py-1.5", className), children });
|
|
683
716
|
}
|
|
684
717
|
|
|
685
718
|
// src/ChipInput.tsx
|
|
686
|
-
import { jsx as
|
|
719
|
+
import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
687
720
|
function InputChip({ label, leading, onRemove, className }) {
|
|
688
|
-
return /* @__PURE__ */
|
|
721
|
+
return /* @__PURE__ */ jsxs9(
|
|
689
722
|
"div",
|
|
690
723
|
{
|
|
691
724
|
className: cn(
|
|
@@ -701,9 +734,9 @@ function InputChip({ label, leading, onRemove, className }) {
|
|
|
701
734
|
className
|
|
702
735
|
),
|
|
703
736
|
children: [
|
|
704
|
-
leading && /* @__PURE__ */
|
|
705
|
-
/* @__PURE__ */
|
|
706
|
-
onRemove && /* @__PURE__ */
|
|
737
|
+
leading && /* @__PURE__ */ jsx15("span", { className: "flex shrink-0 items-center", children: leading }),
|
|
738
|
+
/* @__PURE__ */ jsx15("span", { className: "text-caption font-medium text-text-primary", children: label }),
|
|
739
|
+
onRemove && /* @__PURE__ */ jsx15(
|
|
707
740
|
"button",
|
|
708
741
|
{
|
|
709
742
|
type: "button",
|
|
@@ -713,7 +746,7 @@ function InputChip({ label, leading, onRemove, className }) {
|
|
|
713
746
|
},
|
|
714
747
|
className: "size-4 flex items-center justify-center rounded-full hover:bg-bg-hover text-text-secondary",
|
|
715
748
|
"aria-label": `Remove ${label}`,
|
|
716
|
-
children: /* @__PURE__ */
|
|
749
|
+
children: /* @__PURE__ */ jsx15(IconX2, { size: 10, stroke: 1.5 })
|
|
717
750
|
}
|
|
718
751
|
)
|
|
719
752
|
]
|
|
@@ -802,16 +835,16 @@ function ChipInput({
|
|
|
802
835
|
}
|
|
803
836
|
}
|
|
804
837
|
}
|
|
805
|
-
return /* @__PURE__ */
|
|
806
|
-
/* @__PURE__ */
|
|
838
|
+
return /* @__PURE__ */ jsxs9("div", { className: "relative", children: [
|
|
839
|
+
/* @__PURE__ */ jsxs9(
|
|
807
840
|
"div",
|
|
808
841
|
{
|
|
809
842
|
ref: wrapperRef,
|
|
810
843
|
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",
|
|
811
844
|
onClick: () => inputRef.current?.focus(),
|
|
812
845
|
children: [
|
|
813
|
-
value.map((o) => /* @__PURE__ */
|
|
814
|
-
/* @__PURE__ */
|
|
846
|
+
value.map((o) => /* @__PURE__ */ jsx15(InputChip, { label: o.label, leading: chipLeading?.(o), onRemove: () => removeOption(o.id) }, o.id)),
|
|
847
|
+
/* @__PURE__ */ jsx15(
|
|
815
848
|
"input",
|
|
816
849
|
{
|
|
817
850
|
ref: inputRef,
|
|
@@ -833,7 +866,7 @@ function ChipInput({
|
|
|
833
866
|
}
|
|
834
867
|
),
|
|
835
868
|
showDropdown && anchorRect && createPortal(
|
|
836
|
-
/* @__PURE__ */
|
|
869
|
+
/* @__PURE__ */ jsx15(
|
|
837
870
|
"div",
|
|
838
871
|
{
|
|
839
872
|
className: "fixed z-[60] overflow-y-auto bg-bg-elevated border border-border-default rounded-lg shadow-lg",
|
|
@@ -846,7 +879,7 @@ function ChipInput({
|
|
|
846
879
|
}),
|
|
847
880
|
width: anchorRect.width
|
|
848
881
|
},
|
|
849
|
-
children: matches.map((o, i) => /* @__PURE__ */
|
|
882
|
+
children: matches.map((o, i) => /* @__PURE__ */ jsx15(
|
|
850
883
|
MenuItem,
|
|
851
884
|
{
|
|
852
885
|
size: "tall",
|
|
@@ -874,9 +907,26 @@ function ChipInput({
|
|
|
874
907
|
import { useCallback, useRef as useRef2 } from "react";
|
|
875
908
|
|
|
876
909
|
// src/Divider.tsx
|
|
877
|
-
import { jsx as
|
|
878
|
-
function Divider({ orientation = "horizontal", className }) {
|
|
879
|
-
|
|
910
|
+
import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
911
|
+
function Divider({ orientation = "horizontal", label, tone = "default", className }) {
|
|
912
|
+
if (label && orientation === "horizontal") {
|
|
913
|
+
const line = tone === "warning" ? "bg-warning-muted" : "bg-border-subtle";
|
|
914
|
+
return /* @__PURE__ */ jsxs10(
|
|
915
|
+
"div",
|
|
916
|
+
{
|
|
917
|
+
role: "separator",
|
|
918
|
+
"aria-orientation": "horizontal",
|
|
919
|
+
"aria-label": label,
|
|
920
|
+
className: cn("flex shrink-0 items-center gap-2 mx-3", className),
|
|
921
|
+
children: [
|
|
922
|
+
/* @__PURE__ */ jsx16("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
|
|
923
|
+
/* @__PURE__ */ jsx16("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
|
|
924
|
+
/* @__PURE__ */ jsx16("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
|
|
925
|
+
]
|
|
926
|
+
}
|
|
927
|
+
);
|
|
928
|
+
}
|
|
929
|
+
return /* @__PURE__ */ jsx16(
|
|
880
930
|
"div",
|
|
881
931
|
{
|
|
882
932
|
role: "separator",
|
|
@@ -887,15 +937,15 @@ function Divider({ orientation = "horizontal", className }) {
|
|
|
887
937
|
}
|
|
888
938
|
|
|
889
939
|
// src/Person.tsx
|
|
890
|
-
import { jsx as
|
|
940
|
+
import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
891
941
|
function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
|
|
892
942
|
return (
|
|
893
943
|
// gap-2: the face-to-name distance is one rule (8px) wherever a person
|
|
894
944
|
// appears — Katerina, 2026-09-01, set on Person so PersonTrigger and every
|
|
895
945
|
// row agree by construction.
|
|
896
|
-
/* @__PURE__ */
|
|
897
|
-
/* @__PURE__ */
|
|
898
|
-
/* @__PURE__ */
|
|
946
|
+
/* @__PURE__ */ jsxs11("span", { className: cn("flex min-w-0 items-center gap-2", className), children: [
|
|
947
|
+
/* @__PURE__ */ jsx17(Avatar, { name, src: picture, size }),
|
|
948
|
+
/* @__PURE__ */ jsx17("span", { className: cn("truncate", !name && "text-text-muted"), children: name ?? fallback })
|
|
899
949
|
] })
|
|
900
950
|
);
|
|
901
951
|
}
|
|
@@ -903,10 +953,10 @@ function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
|
|
|
903
953
|
// src/PersonTrigger.tsx
|
|
904
954
|
import { Button as BaseButton3 } from "@base-ui/react/button";
|
|
905
955
|
import { IconChevronDown } from "@tabler/icons-react";
|
|
906
|
-
import { jsx as
|
|
956
|
+
import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
907
957
|
function PersonTrigger({ name, picture, fallback, size, open = false, compact = false, className, ...props }) {
|
|
908
958
|
if (compact) {
|
|
909
|
-
return /* @__PURE__ */
|
|
959
|
+
return /* @__PURE__ */ jsx18(
|
|
910
960
|
BaseButton3,
|
|
911
961
|
{
|
|
912
962
|
type: "button",
|
|
@@ -915,11 +965,11 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
|
|
|
915
965
|
"aria-label": props["aria-label"] ?? name ?? fallback,
|
|
916
966
|
className: cn("cursor-pointer rounded-full", className),
|
|
917
967
|
...props,
|
|
918
|
-
children: /* @__PURE__ */
|
|
968
|
+
children: /* @__PURE__ */ jsx18(Avatar, { name, src: picture, size: size ?? 36 })
|
|
919
969
|
}
|
|
920
970
|
);
|
|
921
971
|
}
|
|
922
|
-
return /* @__PURE__ */
|
|
972
|
+
return /* @__PURE__ */ jsxs12(
|
|
923
973
|
BaseButton3,
|
|
924
974
|
{
|
|
925
975
|
type: "button",
|
|
@@ -937,18 +987,18 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
|
|
|
937
987
|
),
|
|
938
988
|
...props,
|
|
939
989
|
children: [
|
|
940
|
-
/* @__PURE__ */
|
|
941
|
-
/* @__PURE__ */
|
|
990
|
+
/* @__PURE__ */ jsx18(Person, { name, picture, fallback, size: size ?? 22 }),
|
|
991
|
+
/* @__PURE__ */ jsx18(IconChevronDown, { size: 14, stroke: 1.5, className: "shrink-0 text-text-muted" })
|
|
942
992
|
]
|
|
943
993
|
}
|
|
944
994
|
);
|
|
945
995
|
}
|
|
946
996
|
|
|
947
997
|
// src/IdentityMenu.tsx
|
|
948
|
-
import { Fragment as Fragment2, jsx as
|
|
998
|
+
import { Fragment as Fragment2, jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
949
999
|
function IdentityPanel({ className, onClose = () => {
|
|
950
1000
|
}, ...rest }) {
|
|
951
|
-
return /* @__PURE__ */
|
|
1001
|
+
return /* @__PURE__ */ jsx19(MenuPanel, { className: cn("w-72", className), children: /* @__PURE__ */ jsx19(IdentityRows, { ...rest, onClose }) });
|
|
952
1002
|
}
|
|
953
1003
|
function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, onClose, children }) {
|
|
954
1004
|
const act = (action) => () => {
|
|
@@ -956,36 +1006,36 @@ function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, on
|
|
|
956
1006
|
action();
|
|
957
1007
|
};
|
|
958
1008
|
const appRows = typeof children === "function" ? children(onClose) : children;
|
|
959
|
-
return /* @__PURE__ */
|
|
960
|
-
/* @__PURE__ */
|
|
961
|
-
/* @__PURE__ */
|
|
962
|
-
/* @__PURE__ */
|
|
963
|
-
me.email && /* @__PURE__ */
|
|
1009
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
1010
|
+
/* @__PURE__ */ jsxs13(MenuSection, { label: signedIn ? "Signed in as" : "Acting as", children: [
|
|
1011
|
+
/* @__PURE__ */ jsx19(MenuRow, { children: /* @__PURE__ */ jsx19(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28, className: "text-body-2-strong" }) }),
|
|
1012
|
+
/* @__PURE__ */ jsx19(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." }),
|
|
1013
|
+
me.email && /* @__PURE__ */ jsxs13(Note, { children: [
|
|
964
1014
|
me.email,
|
|
965
1015
|
" \xB7 known to Estiva, never published to the relay"
|
|
966
1016
|
] })
|
|
967
1017
|
] }),
|
|
968
|
-
relayUrl && /* @__PURE__ */
|
|
969
|
-
/* @__PURE__ */
|
|
970
|
-
/* @__PURE__ */
|
|
971
|
-
/* @__PURE__ */
|
|
972
|
-
/* @__PURE__ */
|
|
1018
|
+
relayUrl && /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
1019
|
+
/* @__PURE__ */ jsx19(Divider, { className: "mx-0 my-2" }),
|
|
1020
|
+
/* @__PURE__ */ jsxs13(MenuSection, { label: "Workspace", children: [
|
|
1021
|
+
/* @__PURE__ */ jsx19(MenuRow, { children: /* @__PURE__ */ jsx19("span", { className: "break-all font-mono text-caption text-text-primary", children: relayUrl }) }),
|
|
1022
|
+
/* @__PURE__ */ jsx19(Note, { children: "Everyone on this relay shares this workspace, in every app." })
|
|
973
1023
|
] })
|
|
974
1024
|
] }),
|
|
975
|
-
appRows && /* @__PURE__ */
|
|
976
|
-
/* @__PURE__ */
|
|
1025
|
+
appRows && /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
1026
|
+
/* @__PURE__ */ jsx19(Divider, { className: "mx-0 my-2" }),
|
|
977
1027
|
appRows
|
|
978
1028
|
] }),
|
|
979
|
-
signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */
|
|
980
|
-
signedIn && idBase && /* @__PURE__ */
|
|
1029
|
+
signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */ jsx19(Divider, { className: "mx-0 my-2" }) : null,
|
|
1030
|
+
signedIn && idBase && /* @__PURE__ */ jsx19(
|
|
981
1031
|
MenuItem,
|
|
982
1032
|
{
|
|
983
1033
|
label: "Edit your profile in Estiva ID",
|
|
984
1034
|
onClick: act(() => window.open(idBase, "_blank", "noopener,noreferrer"))
|
|
985
1035
|
}
|
|
986
1036
|
),
|
|
987
|
-
onCopyKey && /* @__PURE__ */
|
|
988
|
-
idBase && onSignOut && /* @__PURE__ */
|
|
1037
|
+
onCopyKey && /* @__PURE__ */ jsx19(MenuItem, { label: "Copy public key", onClick: act(onCopyKey) }),
|
|
1038
|
+
idBase && onSignOut && /* @__PURE__ */ jsx19(MenuItem, { label: "Sign out", onClick: act(onSignOut) })
|
|
989
1039
|
] });
|
|
990
1040
|
}
|
|
991
1041
|
function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, compact = false, className, children }) {
|
|
@@ -996,13 +1046,13 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
|
|
|
996
1046
|
to be `relative`, because the panel was positioned against it; the panel
|
|
997
1047
|
hangs from the trigger and portals now, so a positioning context here
|
|
998
1048
|
would only be a lie about what this box does. */
|
|
999
|
-
/* @__PURE__ */
|
|
1049
|
+
/* @__PURE__ */ jsx19("div", { className, children: /* @__PURE__ */ jsx19(
|
|
1000
1050
|
Menu,
|
|
1001
1051
|
{
|
|
1002
1052
|
align: "right",
|
|
1003
1053
|
actionsRef: actions,
|
|
1004
1054
|
className: "w-72",
|
|
1005
|
-
trigger: /* @__PURE__ */
|
|
1055
|
+
trigger: /* @__PURE__ */ jsx19(
|
|
1006
1056
|
PersonTrigger,
|
|
1007
1057
|
{
|
|
1008
1058
|
name: me.name,
|
|
@@ -1013,7 +1063,7 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
|
|
|
1013
1063
|
"aria-label": compact ? "Account menu" : void 0
|
|
1014
1064
|
}
|
|
1015
1065
|
),
|
|
1016
|
-
children: /* @__PURE__ */
|
|
1066
|
+
children: /* @__PURE__ */ jsx19(
|
|
1017
1067
|
IdentityRows,
|
|
1018
1068
|
{
|
|
1019
1069
|
me,
|
|
@@ -1031,25 +1081,25 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
|
|
|
1031
1081
|
);
|
|
1032
1082
|
}
|
|
1033
1083
|
function Note({ children }) {
|
|
1034
|
-
return /* @__PURE__ */
|
|
1084
|
+
return /* @__PURE__ */ jsx19("span", { className: "px-2 pb-1.5 text-caption text-text-secondary", children });
|
|
1035
1085
|
}
|
|
1036
1086
|
|
|
1037
1087
|
// src/Field.tsx
|
|
1038
1088
|
import { cloneElement, isValidElement } from "react";
|
|
1039
1089
|
import { Field as BaseField } from "@base-ui/react/field";
|
|
1040
|
-
import { jsx as
|
|
1090
|
+
import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1041
1091
|
function Field({ label, required = false, helper, error, children }) {
|
|
1042
1092
|
const control = required && isValidElement(children) ? cloneElement(children, {
|
|
1043
1093
|
"aria-required": children.props["aria-required"] ?? true
|
|
1044
1094
|
}) : children;
|
|
1045
|
-
return /* @__PURE__ */
|
|
1046
|
-
/* @__PURE__ */
|
|
1095
|
+
return /* @__PURE__ */ jsxs14(BaseField.Root, { invalid: !!error, className: "flex flex-col gap-2", children: [
|
|
1096
|
+
/* @__PURE__ */ jsxs14(BaseField.Label, { className: cn("text-input-label text-text-primary", required && "flex items-center"), children: [
|
|
1047
1097
|
label,
|
|
1048
|
-
required && /* @__PURE__ */
|
|
1098
|
+
required && /* @__PURE__ */ jsx20("span", { "aria-hidden": "true", className: "text-error-default ml-0.5", children: "*" })
|
|
1049
1099
|
] }),
|
|
1050
|
-
/* @__PURE__ */
|
|
1100
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1.5", children: [
|
|
1051
1101
|
control,
|
|
1052
|
-
error != null ? /* @__PURE__ */
|
|
1102
|
+
error != null ? /* @__PURE__ */ jsx20(BaseField.Error, { match: true, className: "text-caption text-error-default", children: error }) : helper != null ? /* @__PURE__ */ jsx20(BaseField.Description, { className: "text-caption text-text-muted", children: helper }) : null
|
|
1053
1103
|
] })
|
|
1054
1104
|
] });
|
|
1055
1105
|
}
|
|
@@ -1057,12 +1107,12 @@ function Field({ label, required = false, helper, error, children }) {
|
|
|
1057
1107
|
// src/Select.tsx
|
|
1058
1108
|
import { IconCheck as IconCheck2, IconChevronDown as IconChevronDown2 } from "@tabler/icons-react";
|
|
1059
1109
|
import { Select as BaseSelect } from "@base-ui/react/select";
|
|
1060
|
-
import { jsx as
|
|
1110
|
+
import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1061
1111
|
var GAP4 = 4;
|
|
1062
1112
|
var VIEWPORT_PAD3 = 8;
|
|
1063
1113
|
function Select({ value, onChange, options, size = "default", ariaLabel, placeholder = "Select\u2026", disabled, className, ...aria }) {
|
|
1064
1114
|
const selected = options.find((o) => o.value === value);
|
|
1065
|
-
return /* @__PURE__ */
|
|
1115
|
+
return /* @__PURE__ */ jsxs15(
|
|
1066
1116
|
BaseSelect.Root,
|
|
1067
1117
|
{
|
|
1068
1118
|
value,
|
|
@@ -1070,7 +1120,7 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
1070
1120
|
disabled,
|
|
1071
1121
|
modal: false,
|
|
1072
1122
|
children: [
|
|
1073
|
-
/* @__PURE__ */
|
|
1123
|
+
/* @__PURE__ */ jsxs15(
|
|
1074
1124
|
BaseSelect.Trigger,
|
|
1075
1125
|
{
|
|
1076
1126
|
"aria-label": ariaLabel,
|
|
@@ -1097,20 +1147,20 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
1097
1147
|
className
|
|
1098
1148
|
),
|
|
1099
1149
|
children: [
|
|
1100
|
-
/* @__PURE__ */
|
|
1101
|
-
selected?.leading && /* @__PURE__ */
|
|
1102
|
-
/* @__PURE__ */
|
|
1150
|
+
/* @__PURE__ */ jsxs15("span", { className: cn("flex min-w-0 items-center gap-2", !selected && "text-text-muted"), children: [
|
|
1151
|
+
selected?.leading && /* @__PURE__ */ jsx21("span", { className: "flex shrink-0 items-center", children: selected.leading }),
|
|
1152
|
+
/* @__PURE__ */ jsx21(BaseSelect.Value, { className: "truncate", children: () => selected?.label ?? placeholder })
|
|
1103
1153
|
] }),
|
|
1104
|
-
/* @__PURE__ */
|
|
1154
|
+
/* @__PURE__ */ jsx21(
|
|
1105
1155
|
BaseSelect.Icon,
|
|
1106
1156
|
{
|
|
1107
|
-
render: /* @__PURE__ */
|
|
1157
|
+
render: /* @__PURE__ */ jsx21(IconChevronDown2, { size: size === "small" ? 14 : 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
|
|
1108
1158
|
}
|
|
1109
1159
|
)
|
|
1110
1160
|
]
|
|
1111
1161
|
}
|
|
1112
1162
|
),
|
|
1113
|
-
/* @__PURE__ */
|
|
1163
|
+
/* @__PURE__ */ jsx21(BaseSelect.Portal, { children: /* @__PURE__ */ jsx21(
|
|
1114
1164
|
BaseSelect.Positioner,
|
|
1115
1165
|
{
|
|
1116
1166
|
side: "bottom",
|
|
@@ -1119,30 +1169,30 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
1119
1169
|
collisionPadding: VIEWPORT_PAD3,
|
|
1120
1170
|
alignItemWithTrigger: false,
|
|
1121
1171
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
1122
|
-
children: /* @__PURE__ */
|
|
1172
|
+
children: /* @__PURE__ */ jsx21(
|
|
1123
1173
|
BaseSelect.Popup,
|
|
1124
1174
|
{
|
|
1125
|
-
className: "
|
|
1126
|
-
children: options.map((option) => /* @__PURE__ */
|
|
1175
|
+
className: "min-w-[var(--anchor-width)] rounded-lg border border-border-default bg-bg-elevated p-1 shadow-lg",
|
|
1176
|
+
children: /* @__PURE__ */ jsx21(ScrollArea, { viewportClassName: "max-h-[calc(min(288px,var(--available-height))_-_0.5rem)]", contentClassName: "flex flex-col", children: options.map((option) => /* @__PURE__ */ jsxs15(
|
|
1127
1177
|
BaseSelect.Item,
|
|
1128
1178
|
{
|
|
1129
1179
|
value: option.value,
|
|
1130
1180
|
className: "flex h-9 cursor-pointer items-center justify-between gap-2 rounded-lg px-3 text-[14px] font-normal leading-[1.4] text-text-primary transition-colors data-[highlighted]:bg-bg-hover data-[selected]:font-medium",
|
|
1131
1181
|
children: [
|
|
1132
|
-
/* @__PURE__ */
|
|
1133
|
-
option.leading && /* @__PURE__ */
|
|
1134
|
-
/* @__PURE__ */
|
|
1182
|
+
/* @__PURE__ */ jsxs15("span", { className: "flex min-w-0 items-center gap-2", children: [
|
|
1183
|
+
option.leading && /* @__PURE__ */ jsx21("span", { className: "flex shrink-0 items-center", children: option.leading }),
|
|
1184
|
+
/* @__PURE__ */ jsx21(BaseSelect.ItemText, { className: "truncate", children: option.label })
|
|
1135
1185
|
] }),
|
|
1136
|
-
/* @__PURE__ */
|
|
1186
|
+
/* @__PURE__ */ jsx21(
|
|
1137
1187
|
BaseSelect.ItemIndicator,
|
|
1138
1188
|
{
|
|
1139
|
-
render: /* @__PURE__ */
|
|
1189
|
+
render: /* @__PURE__ */ jsx21(IconCheck2, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
|
|
1140
1190
|
}
|
|
1141
1191
|
)
|
|
1142
1192
|
]
|
|
1143
1193
|
},
|
|
1144
1194
|
option.value
|
|
1145
|
-
))
|
|
1195
|
+
)) })
|
|
1146
1196
|
}
|
|
1147
1197
|
)
|
|
1148
1198
|
}
|
|
@@ -1155,9 +1205,9 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
|
|
|
1155
1205
|
// src/TextInput.tsx
|
|
1156
1206
|
import { forwardRef } from "react";
|
|
1157
1207
|
import { Input } from "@base-ui/react/input";
|
|
1158
|
-
import { jsx as
|
|
1208
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
1159
1209
|
var TextInput = forwardRef(function TextInput2({ className, type = "text", ...props }, ref) {
|
|
1160
|
-
return /* @__PURE__ */
|
|
1210
|
+
return /* @__PURE__ */ jsx22(
|
|
1161
1211
|
Input,
|
|
1162
1212
|
{
|
|
1163
1213
|
ref,
|
|
@@ -1178,13 +1228,13 @@ var TextInput = forwardRef(function TextInput2({ className, type = "text", ...pr
|
|
|
1178
1228
|
// src/Textarea.tsx
|
|
1179
1229
|
import { forwardRef as forwardRef2 } from "react";
|
|
1180
1230
|
import { Field as BaseField2 } from "@base-ui/react/field";
|
|
1181
|
-
import { jsx as
|
|
1231
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
1182
1232
|
var Textarea = forwardRef2(function Textarea2({ className, ...props }, ref) {
|
|
1183
|
-
return /* @__PURE__ */
|
|
1233
|
+
return /* @__PURE__ */ jsx23(
|
|
1184
1234
|
BaseField2.Control,
|
|
1185
1235
|
{
|
|
1186
1236
|
ref,
|
|
1187
|
-
render: /* @__PURE__ */
|
|
1237
|
+
render: /* @__PURE__ */ jsx23("textarea", {}),
|
|
1188
1238
|
className: cn(
|
|
1189
1239
|
"bg-bg-inset border border-border-default focus:border-border-focus rounded-lg px-3 py-2",
|
|
1190
1240
|
"text-[14px] leading-[1.4] font-normal text-text-primary placeholder:text-text-muted",
|
|
@@ -1206,20 +1256,20 @@ import { useRef as useRef3 } from "react";
|
|
|
1206
1256
|
import { Dialog } from "@base-ui/react/dialog";
|
|
1207
1257
|
import { AlertDialog } from "@base-ui/react/alert-dialog";
|
|
1208
1258
|
import { IconX as IconX3 } from "@tabler/icons-react";
|
|
1209
|
-
import { jsx as
|
|
1259
|
+
import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1210
1260
|
function DialogShell({ title, onClose, headerContent, footer, children, bodyClassName, width = 502, alert = false }) {
|
|
1211
1261
|
const Parts = alert ? AlertDialog : Dialog;
|
|
1212
1262
|
const popupRef = useRef3(null);
|
|
1213
|
-
return /* @__PURE__ */
|
|
1263
|
+
return /* @__PURE__ */ jsx24(
|
|
1214
1264
|
Parts.Root,
|
|
1215
1265
|
{
|
|
1216
1266
|
open: true,
|
|
1217
1267
|
onOpenChange: (open) => {
|
|
1218
1268
|
if (!open) onClose();
|
|
1219
1269
|
},
|
|
1220
|
-
children: /* @__PURE__ */
|
|
1221
|
-
/* @__PURE__ */
|
|
1222
|
-
/* @__PURE__ */
|
|
1270
|
+
children: /* @__PURE__ */ jsxs16(Parts.Portal, { children: [
|
|
1271
|
+
/* @__PURE__ */ jsx24(Parts.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
|
|
1272
|
+
/* @__PURE__ */ jsx24("div", { className: "fixed inset-0 z-50 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs16(
|
|
1223
1273
|
Parts.Popup,
|
|
1224
1274
|
{
|
|
1225
1275
|
ref: popupRef,
|
|
@@ -1228,17 +1278,17 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
1228
1278
|
className: "bg-bg-elevated border border-border-subtle rounded-lg shadow-lg pointer-events-auto flex flex-col overflow-hidden outline-none",
|
|
1229
1279
|
style: { width },
|
|
1230
1280
|
children: [
|
|
1231
|
-
/* @__PURE__ */
|
|
1232
|
-
headerContent ?? /* @__PURE__ */
|
|
1233
|
-
/* @__PURE__ */
|
|
1281
|
+
/* @__PURE__ */ jsxs16("div", { className: "h-12 flex items-center justify-between pl-5 pr-4 border-b border-border-subtle shrink-0", children: [
|
|
1282
|
+
headerContent ?? /* @__PURE__ */ jsx24(Parts.Title, { className: "text-h4 text-text-primary", render: /* @__PURE__ */ jsx24("span", {}), children: title }),
|
|
1283
|
+
/* @__PURE__ */ jsx24(
|
|
1234
1284
|
Parts.Close,
|
|
1235
1285
|
{
|
|
1236
|
-
render: /* @__PURE__ */
|
|
1286
|
+
render: /* @__PURE__ */ jsx24(IconButton, { tooltip: "Close", "aria-label": "Close", children: /* @__PURE__ */ jsx24(IconX3, { size: 16, stroke: 1.5 }) })
|
|
1237
1287
|
}
|
|
1238
1288
|
)
|
|
1239
1289
|
] }),
|
|
1240
|
-
/* @__PURE__ */
|
|
1241
|
-
footer != null && /* @__PURE__ */
|
|
1290
|
+
/* @__PURE__ */ jsx24("div", { className: cn("pl-5 pr-4 py-4", footer != null && "border-b border-border-subtle", bodyClassName), children }),
|
|
1291
|
+
footer != null && /* @__PURE__ */ jsx24("div", { className: "h-12 flex items-center justify-end gap-2 pl-5 pr-4 shrink-0", children: footer })
|
|
1242
1292
|
]
|
|
1243
1293
|
}
|
|
1244
1294
|
) })
|
|
@@ -1248,7 +1298,7 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
|
|
|
1248
1298
|
}
|
|
1249
1299
|
|
|
1250
1300
|
// src/ConfirmDialog.tsx
|
|
1251
|
-
import { Fragment as Fragment3, jsx as
|
|
1301
|
+
import { Fragment as Fragment3, jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1252
1302
|
function ConfirmDialog({ title, children, confirmLabel, destructive = false, onConfirm, onClose }) {
|
|
1253
1303
|
const [busy, setBusy] = useState3(false);
|
|
1254
1304
|
const confirm = async () => {
|
|
@@ -1260,16 +1310,16 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
|
|
|
1260
1310
|
setBusy(false);
|
|
1261
1311
|
}
|
|
1262
1312
|
};
|
|
1263
|
-
return /* @__PURE__ */
|
|
1313
|
+
return /* @__PURE__ */ jsx25(
|
|
1264
1314
|
DialogShell,
|
|
1265
1315
|
{
|
|
1266
1316
|
alert: true,
|
|
1267
1317
|
title,
|
|
1268
1318
|
onClose,
|
|
1269
1319
|
bodyClassName: "flex flex-col gap-3 text-body-2 text-text-primary",
|
|
1270
|
-
footer: /* @__PURE__ */
|
|
1271
|
-
/* @__PURE__ */
|
|
1272
|
-
/* @__PURE__ */
|
|
1320
|
+
footer: /* @__PURE__ */ jsxs17(Fragment3, { children: [
|
|
1321
|
+
/* @__PURE__ */ jsx25(Button, { variant: "muted", onClick: onClose, disabled: busy, children: "Cancel" }),
|
|
1322
|
+
/* @__PURE__ */ jsx25(Button, { variant: destructive ? "destructive" : "primary", onClick: () => void confirm(), disabled: busy, children: confirmLabel })
|
|
1273
1323
|
] }),
|
|
1274
1324
|
children
|
|
1275
1325
|
}
|
|
@@ -1280,7 +1330,7 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
|
|
|
1280
1330
|
import { useEffect as useEffect2, useRef as useRef4, useState as useState4 } from "react";
|
|
1281
1331
|
import { Field as BaseField3 } from "@base-ui/react/field";
|
|
1282
1332
|
import { Input as Input2 } from "@base-ui/react/input";
|
|
1283
|
-
import { jsx as
|
|
1333
|
+
import { jsx as jsx26 } from "react/jsx-runtime";
|
|
1284
1334
|
function EditableText({ value, display, displayNode, placeholder, onCommit, multiline = false, className, label, readOnly = false }) {
|
|
1285
1335
|
const [editing, setEditing] = useState4(false);
|
|
1286
1336
|
const [draft, setDraft] = useState4(value);
|
|
@@ -1338,7 +1388,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
1338
1388
|
written and never read. Read-only, this is a line of text: whatever
|
|
1339
1389
|
names the region around it (a `Field`, a `Property`) names this too.
|
|
1340
1390
|
*/
|
|
1341
|
-
/* @__PURE__ */
|
|
1391
|
+
/* @__PURE__ */ jsx26(
|
|
1342
1392
|
"div",
|
|
1343
1393
|
{
|
|
1344
1394
|
className: cn("w-full px-2 py-1", multiline && !displayNode && "whitespace-pre-wrap", display ?? value ? "text-text-primary" : "text-text-muted", className),
|
|
@@ -1348,11 +1398,11 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
1348
1398
|
);
|
|
1349
1399
|
}
|
|
1350
1400
|
if (editing) {
|
|
1351
|
-
return multiline ? /* @__PURE__ */
|
|
1401
|
+
return multiline ? /* @__PURE__ */ jsx26(
|
|
1352
1402
|
BaseField3.Control,
|
|
1353
1403
|
{
|
|
1354
1404
|
ref: fieldRef,
|
|
1355
|
-
render: /* @__PURE__ */
|
|
1405
|
+
render: /* @__PURE__ */ jsx26("textarea", { rows: 4 }),
|
|
1356
1406
|
"aria-label": label,
|
|
1357
1407
|
value: draft,
|
|
1358
1408
|
disabled: busy,
|
|
@@ -1361,7 +1411,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
1361
1411
|
onBlur: () => void commit(),
|
|
1362
1412
|
className: fieldClass
|
|
1363
1413
|
}
|
|
1364
|
-
) : /* @__PURE__ */
|
|
1414
|
+
) : /* @__PURE__ */ jsx26(
|
|
1365
1415
|
Input2,
|
|
1366
1416
|
{
|
|
1367
1417
|
ref: fieldRef,
|
|
@@ -1375,7 +1425,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
1375
1425
|
}
|
|
1376
1426
|
);
|
|
1377
1427
|
}
|
|
1378
|
-
return /* @__PURE__ */
|
|
1428
|
+
return /* @__PURE__ */ jsx26(
|
|
1379
1429
|
"button",
|
|
1380
1430
|
{
|
|
1381
1431
|
type: "button",
|
|
@@ -1394,33 +1444,36 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
|
|
|
1394
1444
|
|
|
1395
1445
|
// src/EmptyState.tsx
|
|
1396
1446
|
import { IconMessage2 } from "@tabler/icons-react";
|
|
1397
|
-
import { jsx as
|
|
1398
|
-
function EmptyState({ icon, message, className }) {
|
|
1399
|
-
|
|
1400
|
-
/* @__PURE__ */
|
|
1401
|
-
|
|
1447
|
+
import { jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1448
|
+
function EmptyState({ icon, message, scope = "page", className }) {
|
|
1449
|
+
if (scope === "section") {
|
|
1450
|
+
return /* @__PURE__ */ jsx27("p", { className: cn("text-body-2 text-text-secondary", className), children: message });
|
|
1451
|
+
}
|
|
1452
|
+
return /* @__PURE__ */ jsxs18("div", { className: cn("flex flex-1 flex-col items-center justify-center gap-2", className), children: [
|
|
1453
|
+
/* @__PURE__ */ jsx27("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx27(IconMessage2, { size: 16, stroke: 1.5 }) }),
|
|
1454
|
+
/* @__PURE__ */ jsx27("p", { className: "text-body-2 text-text-secondary text-center", children: message })
|
|
1402
1455
|
] });
|
|
1403
1456
|
}
|
|
1404
1457
|
|
|
1405
1458
|
// src/Skeleton.tsx
|
|
1406
|
-
import { jsx as
|
|
1459
|
+
import { jsx as jsx28, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1407
1460
|
function SkeletonBar({ className, style }) {
|
|
1408
|
-
return /* @__PURE__ */
|
|
1461
|
+
return /* @__PURE__ */ jsx28("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
|
|
1409
1462
|
}
|
|
1410
1463
|
var ROW_BAR_WIDTHS = [150, 100, 170, 120, 90, 140, 110, 160];
|
|
1411
1464
|
function SkeletonRow({ barWidth = 130 }) {
|
|
1412
|
-
return /* @__PURE__ */
|
|
1413
|
-
/* @__PURE__ */
|
|
1414
|
-
/* @__PURE__ */
|
|
1465
|
+
return /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2 px-2 h-[32px] rounded-lg", children: [
|
|
1466
|
+
/* @__PURE__ */ jsx28(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
|
|
1467
|
+
/* @__PURE__ */ jsx28(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
|
|
1415
1468
|
] });
|
|
1416
1469
|
}
|
|
1417
1470
|
function SkeletonList({ rows = 8, className }) {
|
|
1418
|
-
return /* @__PURE__ */
|
|
1471
|
+
return /* @__PURE__ */ jsx28("div", { className: cn("flex flex-col gap-0.5 animate-skeleton-in", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx28(SkeletonRow, { barWidth: ROW_BAR_WIDTHS[i % ROW_BAR_WIDTHS.length] }, i)) });
|
|
1419
1472
|
}
|
|
1420
1473
|
|
|
1421
1474
|
// src/Breadcrumb.tsx
|
|
1422
1475
|
import { Fragment as Fragment4, useCallback as useCallback2, useLayoutEffect as useLayoutEffect2, useRef as useRef5, useState as useState5 } from "react";
|
|
1423
|
-
import { jsx as
|
|
1476
|
+
import { jsx as jsx29, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1424
1477
|
function Breadcrumb({ items, className }) {
|
|
1425
1478
|
const navRef = useRef5(null);
|
|
1426
1479
|
const labelRefs = useRef5([]);
|
|
@@ -1440,36 +1493,38 @@ function Breadcrumb({ items, className }) {
|
|
|
1440
1493
|
observer.observe(nav);
|
|
1441
1494
|
return () => observer.disconnect();
|
|
1442
1495
|
}, [measure, items]);
|
|
1443
|
-
return /* @__PURE__ */
|
|
1496
|
+
return /* @__PURE__ */ jsx29("nav", { ref: navRef, "aria-label": "Breadcrumb", className: cn("flex min-w-0 items-center gap-1.5 text-[14px] leading-[140%]", className), children: items.map((item, index) => {
|
|
1444
1497
|
const last = index === items.length - 1;
|
|
1498
|
+
const tone = item.muted || last && item.mono ? "text-text-muted" : last ? "text-text-primary" : "text-text-secondary";
|
|
1445
1499
|
const text = cn(
|
|
1446
1500
|
"truncate",
|
|
1447
1501
|
// A mono crumb is a ref — the identity. It never gives up width to a
|
|
1448
1502
|
// long name beside it (the LongName story always claimed "the ref
|
|
1449
1503
|
// stays"; flexbox was squeezing it anyway until this line).
|
|
1450
1504
|
item.mono && "shrink-0 font-mono text-[12px] leading-[120%]",
|
|
1451
|
-
|
|
1505
|
+
tone
|
|
1452
1506
|
);
|
|
1453
1507
|
const setLabelRef = (el) => {
|
|
1454
1508
|
labelRefs.current[index] = el;
|
|
1455
1509
|
};
|
|
1456
|
-
const crumb = item.href ? /* @__PURE__ */
|
|
1457
|
-
return /* @__PURE__ */
|
|
1458
|
-
index > 0 && /* @__PURE__ */
|
|
1510
|
+
const crumb = item.href ? /* @__PURE__ */ jsx29("a", { ref: setLabelRef, href: item.href, onClick: item.onClick, className: cn(text, "hover:text-text-primary"), children: item.label }) : /* @__PURE__ */ jsx29("span", { ref: setLabelRef, className: text, "aria-current": last ? "page" : void 0, children: item.label });
|
|
1511
|
+
return /* @__PURE__ */ jsxs20(Fragment4, { children: [
|
|
1512
|
+
index > 0 && /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
|
|
1513
|
+
item.icon && /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", className: cn("flex shrink-0", tone), children: item.icon }),
|
|
1459
1514
|
truncated.has(index) ? (
|
|
1460
1515
|
// `min-w-0 shrink` undoes the wrapper's own shrink-0 — the crumb
|
|
1461
1516
|
// must keep truncating inside it, or wrapping it would widen the
|
|
1462
1517
|
// trail and the tooltip would never be needed again.
|
|
1463
|
-
/* @__PURE__ */
|
|
1518
|
+
/* @__PURE__ */ jsx29(WithTooltip, { label: item.label, wrapperClassName: "min-w-0 shrink", children: crumb })
|
|
1464
1519
|
) : crumb
|
|
1465
1520
|
] }, `${item.label}-${index}`);
|
|
1466
1521
|
}) });
|
|
1467
1522
|
}
|
|
1468
1523
|
|
|
1469
1524
|
// src/NavItem.tsx
|
|
1470
|
-
import { jsx as
|
|
1525
|
+
import { jsx as jsx30, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1471
1526
|
function NavItem({ label, href, count, countLabel, active = false, icon, className, ...props }) {
|
|
1472
|
-
return /* @__PURE__ */
|
|
1527
|
+
return /* @__PURE__ */ jsxs21(
|
|
1473
1528
|
"a",
|
|
1474
1529
|
{
|
|
1475
1530
|
href,
|
|
@@ -1484,9 +1539,9 @@ function NavItem({ label, href, count, countLabel, active = false, icon, classNa
|
|
|
1484
1539
|
),
|
|
1485
1540
|
...props,
|
|
1486
1541
|
children: [
|
|
1487
|
-
icon && /* @__PURE__ */
|
|
1488
|
-
/* @__PURE__ */
|
|
1489
|
-
count ? /* @__PURE__ */
|
|
1542
|
+
icon && /* @__PURE__ */ jsx30("span", { className: "flex shrink-0 items-center", children: icon }),
|
|
1543
|
+
/* @__PURE__ */ jsx30("span", { className: "flex-1 truncate", children: label }),
|
|
1544
|
+
count ? /* @__PURE__ */ jsx30(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx30("span", { className: "min-w-4 shrink-0 text-center font-mono text-caption tabular-nums text-text-muted", children: count }) }) : null
|
|
1490
1545
|
]
|
|
1491
1546
|
}
|
|
1492
1547
|
);
|
|
@@ -1495,7 +1550,7 @@ function NavItem({ label, href, count, countLabel, active = false, icon, classNa
|
|
|
1495
1550
|
// src/Popover.tsx
|
|
1496
1551
|
import { useMemo as useMemo2 } from "react";
|
|
1497
1552
|
import { Popover as BasePopover } from "@base-ui/react/popover";
|
|
1498
|
-
import { jsx as
|
|
1553
|
+
import { jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1499
1554
|
var GAP5 = 4;
|
|
1500
1555
|
var VIEWPORT_PAD4 = 8;
|
|
1501
1556
|
function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpenChange, finalFocus, actionsRef, ariaLabel, children, className }) {
|
|
@@ -1504,7 +1559,7 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
1504
1559
|
if (anchor instanceof Element) return anchor;
|
|
1505
1560
|
return { getBoundingClientRect: () => anchor };
|
|
1506
1561
|
}, [anchor]);
|
|
1507
|
-
return /* @__PURE__ */
|
|
1562
|
+
return /* @__PURE__ */ jsxs22(
|
|
1508
1563
|
BasePopover.Root,
|
|
1509
1564
|
{
|
|
1510
1565
|
open,
|
|
@@ -1512,8 +1567,8 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
1512
1567
|
actionsRef,
|
|
1513
1568
|
modal: false,
|
|
1514
1569
|
children: [
|
|
1515
|
-
trigger && /* @__PURE__ */
|
|
1516
|
-
/* @__PURE__ */
|
|
1570
|
+
trigger && /* @__PURE__ */ jsx31(BasePopover.Trigger, { render: trigger, disabled: triggerDisabled(trigger) }),
|
|
1571
|
+
/* @__PURE__ */ jsx31(BasePopover.Portal, { children: /* @__PURE__ */ jsx31(
|
|
1517
1572
|
BasePopover.Positioner,
|
|
1518
1573
|
{
|
|
1519
1574
|
anchor: anchorTarget,
|
|
@@ -1522,15 +1577,15 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
1522
1577
|
sideOffset: GAP5,
|
|
1523
1578
|
collisionPadding: VIEWPORT_PAD4,
|
|
1524
1579
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
1525
|
-
children: /* @__PURE__ */
|
|
1580
|
+
children: /* @__PURE__ */ jsx31(
|
|
1526
1581
|
BasePopover.Popup,
|
|
1527
1582
|
{
|
|
1528
1583
|
"aria-label": ariaLabel,
|
|
1529
1584
|
initialFocus: trigger ? void 0 : false,
|
|
1530
1585
|
finalFocus,
|
|
1531
|
-
className: cn("min-w-[180px]
|
|
1532
|
-
render: /* @__PURE__ */
|
|
1533
|
-
children
|
|
1586
|
+
className: cn("min-w-[180px] outline-none", className),
|
|
1587
|
+
render: /* @__PURE__ */ jsx31(MenuPanel, {}),
|
|
1588
|
+
children: /* @__PURE__ */ jsx31(ScrollArea, { viewportClassName: "max-h-[calc(var(--available-height)_-_1rem)]", contentClassName: "flex flex-col [&>[role=separator]]:mx-0", children })
|
|
1534
1589
|
}
|
|
1535
1590
|
)
|
|
1536
1591
|
}
|
|
@@ -1542,9 +1597,9 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
1542
1597
|
|
|
1543
1598
|
// src/Toolbar.tsx
|
|
1544
1599
|
import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar";
|
|
1545
|
-
import { jsx as
|
|
1600
|
+
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
1546
1601
|
function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocus = true, surface = true, children, className }) {
|
|
1547
|
-
const strip = /* @__PURE__ */
|
|
1602
|
+
const strip = /* @__PURE__ */ jsx32(
|
|
1548
1603
|
BaseToolbar.Root,
|
|
1549
1604
|
{
|
|
1550
1605
|
"aria-label": ariaLabel,
|
|
@@ -1555,24 +1610,24 @@ function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocu
|
|
|
1555
1610
|
}
|
|
1556
1611
|
);
|
|
1557
1612
|
if (!surface) return strip;
|
|
1558
|
-
return /* @__PURE__ */
|
|
1613
|
+
return /* @__PURE__ */ jsx32(MenuPanel, { className: "w-fit p-1", children: strip });
|
|
1559
1614
|
}
|
|
1560
1615
|
function ToolbarButton({ ref, disabled, disabledReason, ...props }) {
|
|
1561
|
-
return /* @__PURE__ */
|
|
1616
|
+
return /* @__PURE__ */ jsx32(
|
|
1562
1617
|
BaseToolbar.Button,
|
|
1563
1618
|
{
|
|
1564
1619
|
ref,
|
|
1565
1620
|
disabled: disabled || !!disabledReason,
|
|
1566
1621
|
focusableWhenDisabled: true,
|
|
1567
|
-
render: /* @__PURE__ */
|
|
1622
|
+
render: /* @__PURE__ */ jsx32(IconButton, { disabled, disabledReason, ...props })
|
|
1568
1623
|
}
|
|
1569
1624
|
);
|
|
1570
1625
|
}
|
|
1571
1626
|
function ToolbarInput(props) {
|
|
1572
|
-
return /* @__PURE__ */
|
|
1627
|
+
return /* @__PURE__ */ jsx32(BaseToolbar.Input, { render: /* @__PURE__ */ jsx32(TextInput, {}), ...props });
|
|
1573
1628
|
}
|
|
1574
1629
|
function ToolbarSeparator({ className }) {
|
|
1575
|
-
return /* @__PURE__ */
|
|
1630
|
+
return /* @__PURE__ */ jsx32(
|
|
1576
1631
|
BaseToolbar.Separator,
|
|
1577
1632
|
{
|
|
1578
1633
|
orientation: "vertical",
|
|
@@ -1582,9 +1637,9 @@ function ToolbarSeparator({ className }) {
|
|
|
1582
1637
|
}
|
|
1583
1638
|
|
|
1584
1639
|
// src/ReactionPicker.tsx
|
|
1585
|
-
import { jsx as
|
|
1640
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
1586
1641
|
function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reactions", surface = true, className }) {
|
|
1587
|
-
return /* @__PURE__ */
|
|
1642
|
+
return /* @__PURE__ */ jsx33(Toolbar, { "aria-label": ariaLabel, surface, className: cn("gap-0.5", className), children: options.map((option) => (
|
|
1588
1643
|
/*
|
|
1589
1644
|
A `ToolbarButton`, not a button in a tooltip wrapper. The wrapper
|
|
1590
1645
|
would become the toolbar's item and the button inside it would never
|
|
@@ -1594,14 +1649,14 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
|
|
|
1594
1649
|
The tooltip names it for a pointer, `aria-label` for everything else,
|
|
1595
1650
|
and both say the meaning rather than the glyph.
|
|
1596
1651
|
*/
|
|
1597
|
-
/* @__PURE__ */
|
|
1652
|
+
/* @__PURE__ */ jsx33(
|
|
1598
1653
|
ToolbarButton,
|
|
1599
1654
|
{
|
|
1600
1655
|
"aria-label": option.label,
|
|
1601
1656
|
tooltip: option.label,
|
|
1602
1657
|
onClick: () => onSelect(option.emoji),
|
|
1603
1658
|
className: "size-7 text-[18px] leading-none",
|
|
1604
|
-
children: /* @__PURE__ */
|
|
1659
|
+
children: /* @__PURE__ */ jsx33("span", { "aria-hidden": "true", children: option.emoji })
|
|
1605
1660
|
},
|
|
1606
1661
|
option.emoji
|
|
1607
1662
|
)
|
|
@@ -1610,23 +1665,23 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
|
|
|
1610
1665
|
|
|
1611
1666
|
// src/PreviewCard.tsx
|
|
1612
1667
|
import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card";
|
|
1613
|
-
import { jsx as
|
|
1668
|
+
import { jsx as jsx34, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1614
1669
|
var GAP6 = 12;
|
|
1615
1670
|
var VIEWPORT_PAD5 = 8;
|
|
1616
1671
|
var OPEN_DELAY2 = 350;
|
|
1617
1672
|
var CLOSE_DELAY = 200;
|
|
1618
1673
|
function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, closeDelay = CLOSE_DELAY, className, wrapperClassName }) {
|
|
1619
|
-
return /* @__PURE__ */
|
|
1620
|
-
/* @__PURE__ */
|
|
1674
|
+
return /* @__PURE__ */ jsxs23(BasePreviewCard.Root, { children: [
|
|
1675
|
+
/* @__PURE__ */ jsx34(
|
|
1621
1676
|
BasePreviewCard.Trigger,
|
|
1622
1677
|
{
|
|
1623
1678
|
delay,
|
|
1624
1679
|
closeDelay,
|
|
1625
|
-
render: /* @__PURE__ */
|
|
1680
|
+
render: /* @__PURE__ */ jsx34("span", { className: cn("inline-flex", wrapperClassName) }),
|
|
1626
1681
|
children
|
|
1627
1682
|
}
|
|
1628
1683
|
),
|
|
1629
|
-
/* @__PURE__ */
|
|
1684
|
+
/* @__PURE__ */ jsx34(BasePreviewCard.Portal, { children: /* @__PURE__ */ jsx34(
|
|
1630
1685
|
BasePreviewCard.Positioner,
|
|
1631
1686
|
{
|
|
1632
1687
|
side,
|
|
@@ -1634,12 +1689,12 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
|
|
|
1634
1689
|
sideOffset: GAP6,
|
|
1635
1690
|
collisionPadding: VIEWPORT_PAD5,
|
|
1636
1691
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
1637
|
-
children: /* @__PURE__ */
|
|
1692
|
+
children: /* @__PURE__ */ jsx34(
|
|
1638
1693
|
BasePreviewCard.Popup,
|
|
1639
1694
|
{
|
|
1640
|
-
className: cn("w-[360px]
|
|
1641
|
-
render: /* @__PURE__ */
|
|
1642
|
-
children: content
|
|
1695
|
+
className: cn("w-[360px] p-3 outline-none", className),
|
|
1696
|
+
render: /* @__PURE__ */ jsx34(MenuPanel, {}),
|
|
1697
|
+
children: /* @__PURE__ */ jsx34(ScrollArea, { viewportClassName: "max-h-[calc(min(300px,var(--available-height))_-_1.5rem)]", contentClassName: "flex flex-col gap-3 [&>*]:shrink-0", children: content })
|
|
1643
1698
|
}
|
|
1644
1699
|
)
|
|
1645
1700
|
}
|
|
@@ -1648,15 +1703,15 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
|
|
|
1648
1703
|
}
|
|
1649
1704
|
|
|
1650
1705
|
// src/Rail.tsx
|
|
1651
|
-
import { jsx as
|
|
1706
|
+
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
1652
1707
|
function Rail({ "aria-label": ariaLabel = "Navigation", children, className }) {
|
|
1653
|
-
return /* @__PURE__ */
|
|
1708
|
+
return /* @__PURE__ */ jsx35("nav", { "aria-label": ariaLabel, className: cn("flex w-16 shrink-0 flex-col items-start gap-2 px-2 py-3", className), children });
|
|
1654
1709
|
}
|
|
1655
1710
|
|
|
1656
1711
|
// src/RailItem.tsx
|
|
1657
|
-
import { jsx as
|
|
1712
|
+
import { jsx as jsx36, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1658
1713
|
function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
1659
|
-
return /* @__PURE__ */
|
|
1714
|
+
return /* @__PURE__ */ jsxs24(
|
|
1660
1715
|
"a",
|
|
1661
1716
|
{
|
|
1662
1717
|
href,
|
|
@@ -1664,14 +1719,14 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
|
1664
1719
|
className: cn("group flex w-full shrink-0 flex-col items-center gap-0.5 px-2 py-0.5", className),
|
|
1665
1720
|
...props,
|
|
1666
1721
|
children: [
|
|
1667
|
-
/* @__PURE__ */
|
|
1722
|
+
/* @__PURE__ */ jsx36(
|
|
1668
1723
|
"div",
|
|
1669
1724
|
{
|
|
1670
1725
|
className: cn(
|
|
1671
1726
|
"flex items-center justify-center rounded-lg p-2 transition-colors",
|
|
1672
1727
|
active ? "bg-bg-selected" : "group-hover:bg-bg-hover"
|
|
1673
1728
|
),
|
|
1674
|
-
children: /* @__PURE__ */
|
|
1729
|
+
children: /* @__PURE__ */ jsx36(
|
|
1675
1730
|
"span",
|
|
1676
1731
|
{
|
|
1677
1732
|
className: cn(
|
|
@@ -1683,52 +1738,49 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
|
1683
1738
|
)
|
|
1684
1739
|
}
|
|
1685
1740
|
),
|
|
1686
|
-
/* @__PURE__ */
|
|
1741
|
+
/* @__PURE__ */ jsx36("span", { className: cn("text-center text-[9px] font-medium leading-[115%]", active ? "text-text-primary" : "text-text-secondary"), children: label })
|
|
1687
1742
|
]
|
|
1688
1743
|
}
|
|
1689
1744
|
);
|
|
1690
1745
|
}
|
|
1691
1746
|
|
|
1692
1747
|
// src/Sidebar.tsx
|
|
1693
|
-
import { jsx as
|
|
1748
|
+
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
1694
1749
|
function Sidebar({ "aria-label": ariaLabel = "Workspace", children, className }) {
|
|
1695
|
-
return /* @__PURE__ */
|
|
1750
|
+
return /* @__PURE__ */ jsx37(
|
|
1696
1751
|
"nav",
|
|
1697
1752
|
{
|
|
1698
1753
|
"aria-label": ariaLabel,
|
|
1699
|
-
className: cn(
|
|
1700
|
-
|
|
1701
|
-
className
|
|
1702
|
-
),
|
|
1703
|
-
children
|
|
1754
|
+
className: cn("flex w-60 shrink-0 flex-col border-r border-border-default bg-bg-surface", className),
|
|
1755
|
+
children: /* @__PURE__ */ jsx37(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex flex-col gap-px px-2.5 py-3", children })
|
|
1704
1756
|
}
|
|
1705
1757
|
);
|
|
1706
1758
|
}
|
|
1707
1759
|
|
|
1708
1760
|
// src/Property.tsx
|
|
1709
|
-
import { jsx as
|
|
1761
|
+
import { jsx as jsx38, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1710
1762
|
function Property({ label, layout = "row", children, className }) {
|
|
1711
1763
|
if (layout === "stacked") {
|
|
1712
1764
|
return (
|
|
1713
1765
|
// gap-3 — the one label-above-content distance (Katerina, 2026-09-01):
|
|
1714
1766
|
// Peek's topic-details sections already sit at 12px, Ship's rail was
|
|
1715
1767
|
// 6px, and unifying means the bigger, calmer one.
|
|
1716
|
-
/* @__PURE__ */
|
|
1717
|
-
/* @__PURE__ */
|
|
1768
|
+
/* @__PURE__ */ jsxs25("div", { className: cn("flex flex-col gap-3", className), children: [
|
|
1769
|
+
/* @__PURE__ */ jsx38("span", { className: "text-menu uppercase tracking-[0.08em] text-text-secondary", children: label }),
|
|
1718
1770
|
children
|
|
1719
1771
|
] })
|
|
1720
1772
|
);
|
|
1721
1773
|
}
|
|
1722
|
-
return /* @__PURE__ */
|
|
1723
|
-
/* @__PURE__ */
|
|
1774
|
+
return /* @__PURE__ */ jsxs25("div", { className: cn("flex items-center gap-2", className), children: [
|
|
1775
|
+
/* @__PURE__ */ jsx38("span", { className: "w-[68px] shrink-0 text-caption text-text-secondary", children: label }),
|
|
1724
1776
|
children
|
|
1725
1777
|
] });
|
|
1726
1778
|
}
|
|
1727
1779
|
|
|
1728
1780
|
// src/Reaction.tsx
|
|
1729
|
-
import { jsx as
|
|
1781
|
+
import { jsx as jsx39, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
1730
1782
|
function Reaction({ emoji, count, pressed = false, className, type, ...props }) {
|
|
1731
|
-
return /* @__PURE__ */
|
|
1783
|
+
return /* @__PURE__ */ jsxs26(
|
|
1732
1784
|
"button",
|
|
1733
1785
|
{
|
|
1734
1786
|
type: type ?? "button",
|
|
@@ -1739,13 +1791,20 @@ function Reaction({ emoji, count, pressed = false, className, type, ...props })
|
|
|
1739
1791
|
"inline-flex h-6 items-center justify-center gap-1.5 rounded-full px-2",
|
|
1740
1792
|
"border transition-colors",
|
|
1741
1793
|
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
1742
|
-
pressed ?
|
|
1794
|
+
pressed ? (
|
|
1795
|
+
/* In the ship theme the accent on its own wash measures 2.70:1
|
|
1796
|
+
(Finding 4), and the count was the thing that vanished
|
|
1797
|
+
(Katerina, 2026-09-08). The number reads in the text colour
|
|
1798
|
+
there; the accent keeps the edge and the fill. Signal keeps
|
|
1799
|
+
Peek's blue-on-wash, which reads. */
|
|
1800
|
+
"border-accent-primary bg-accent-muted text-accent-primary hover:border-accent-hover ship:text-text-primary"
|
|
1801
|
+
) : "border-border-default bg-bg-inset text-text-primary hover:border-border-strong hover:bg-bg-hover",
|
|
1743
1802
|
className
|
|
1744
1803
|
),
|
|
1745
1804
|
...props,
|
|
1746
1805
|
children: [
|
|
1747
|
-
/* @__PURE__ */
|
|
1748
|
-
/* @__PURE__ */
|
|
1806
|
+
/* @__PURE__ */ jsx39("span", { "aria-hidden": "true", className: "shrink-0 text-[16px] leading-none", children: emoji }),
|
|
1807
|
+
/* @__PURE__ */ jsx39("span", { className: "text-chip signal:font-mono signal:text-[10px] signal:font-semibold signal:tabular-nums", children: count })
|
|
1749
1808
|
]
|
|
1750
1809
|
}
|
|
1751
1810
|
);
|
|
@@ -1754,9 +1813,9 @@ function Reaction({ emoji, count, pressed = false, className, type, ...props })
|
|
|
1754
1813
|
// src/SearchInput.tsx
|
|
1755
1814
|
import "react";
|
|
1756
1815
|
import { Input as Input3 } from "@base-ui/react/input";
|
|
1757
|
-
import { jsx as
|
|
1816
|
+
import { jsx as jsx40, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
1758
1817
|
function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...props }) {
|
|
1759
|
-
return /* @__PURE__ */
|
|
1818
|
+
return /* @__PURE__ */ jsxs27(
|
|
1760
1819
|
"div",
|
|
1761
1820
|
{
|
|
1762
1821
|
className: cn(
|
|
@@ -1766,7 +1825,7 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
1766
1825
|
className
|
|
1767
1826
|
),
|
|
1768
1827
|
children: [
|
|
1769
|
-
/* @__PURE__ */
|
|
1828
|
+
/* @__PURE__ */ jsx40(
|
|
1770
1829
|
Input3,
|
|
1771
1830
|
{
|
|
1772
1831
|
className: "flex-1 min-w-0 bg-transparent text-input-value text-text-primary placeholder:text-text-muted outline-none",
|
|
@@ -1774,65 +1833,113 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
1774
1833
|
...props
|
|
1775
1834
|
}
|
|
1776
1835
|
),
|
|
1777
|
-
shortcut && /* @__PURE__ */
|
|
1836
|
+
shortcut && /* @__PURE__ */ jsx40(Kbd, { children: shortcut })
|
|
1778
1837
|
]
|
|
1779
1838
|
}
|
|
1780
1839
|
);
|
|
1781
1840
|
}
|
|
1782
1841
|
|
|
1783
1842
|
// src/SectionHeader.tsx
|
|
1784
|
-
import { useState as useState6 } from "react";
|
|
1785
1843
|
import { IconChevronRight as IconChevronRight2 } from "@tabler/icons-react";
|
|
1786
|
-
import {
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1844
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
1845
|
+
import { Fragment as Fragment5, jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
1846
|
+
function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, actions, showActions = "hover", render, className }) {
|
|
1847
|
+
const titleElement = useRender({
|
|
1848
|
+
render: render ?? (chevron ? /* @__PURE__ */ jsx41("button", { type: "button", onClick: onToggle, "aria-expanded": isExpanded }) : /* @__PURE__ */ jsx41("span", {})),
|
|
1849
|
+
props: {
|
|
1850
|
+
// `text-left`: a button centres its text. `h-full` and `flex-1`: the
|
|
1851
|
+
// whole row up to the actions is the hit target, as it was when the
|
|
1852
|
+
// row itself carried the click.
|
|
1853
|
+
className: "flex h-full min-w-0 flex-1 items-center gap-1 text-left",
|
|
1854
|
+
children: /* @__PURE__ */ jsxs28(Fragment5, { children: [
|
|
1855
|
+
chevron && /* @__PURE__ */ jsx41(
|
|
1856
|
+
IconChevronRight2,
|
|
1857
|
+
{
|
|
1858
|
+
size: 12,
|
|
1859
|
+
stroke: 1.5,
|
|
1860
|
+
className: cn("shrink-0 text-text-secondary transition-transform duration-150", isExpanded && "rotate-90")
|
|
1861
|
+
}
|
|
1862
|
+
),
|
|
1863
|
+
/* @__PURE__ */ jsx41(SectionLabel, { children: title })
|
|
1864
|
+
] })
|
|
1865
|
+
}
|
|
1866
|
+
});
|
|
1867
|
+
return /* @__PURE__ */ jsxs28(
|
|
1790
1868
|
"div",
|
|
1791
1869
|
{
|
|
1792
1870
|
className: cn(
|
|
1793
|
-
"flex h-[32px] items-center
|
|
1794
|
-
|
|
1795
|
-
|
|
1871
|
+
"group flex h-[32px] items-center gap-1 rounded-lg px-2 transition-colors",
|
|
1872
|
+
// The fill says "this does something": a row with a toggle or actions
|
|
1873
|
+
// lights up, a fixed heading over rows does not (2026-09-09, the
|
|
1874
|
+
// Sidebar's fixed group).
|
|
1875
|
+
(chevron || actions && actions.length > 0) && "hover:bg-bg-hover",
|
|
1796
1876
|
className
|
|
1797
1877
|
),
|
|
1798
|
-
onClick: chevron ? onToggle : void 0,
|
|
1799
|
-
onMouseEnter: () => setIsHovered(true),
|
|
1800
|
-
onMouseLeave: () => setIsHovered(false),
|
|
1801
1878
|
children: [
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
{
|
|
1806
|
-
size: 12,
|
|
1807
|
-
stroke: 1.5,
|
|
1808
|
-
className: cn("text-text-secondary transition-transform duration-150", isExpanded && "rotate-90")
|
|
1809
|
-
}
|
|
1810
|
-
),
|
|
1811
|
-
/* @__PURE__ */ jsx40(SectionLabel, { children: title })
|
|
1812
|
-
] }),
|
|
1813
|
-
(showActions === "always" || isHovered) && actions && actions.length > 0 && /* @__PURE__ */ jsx40("div", { className: "flex items-center gap-1", children: actions.map((action) => /* @__PURE__ */ jsx40(
|
|
1814
|
-
IconButton,
|
|
1879
|
+
titleElement,
|
|
1880
|
+
actions && actions.length > 0 && /* @__PURE__ */ jsx41(
|
|
1881
|
+
"div",
|
|
1815
1882
|
{
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
},
|
|
1824
|
-
action.tooltip
|
|
1825
|
-
)) })
|
|
1883
|
+
className: cn(
|
|
1884
|
+
"-mr-1 flex shrink-0 items-center gap-1",
|
|
1885
|
+
showActions === "hover" && "opacity-0 transition-opacity focus-within:opacity-100 group-hover:opacity-100"
|
|
1886
|
+
),
|
|
1887
|
+
children: actions.map((action) => /* @__PURE__ */ jsx41(IconButton, { tooltip: action.tooltip, "aria-label": action.tooltip, onClick: action.onClick, children: action.icon }, action.tooltip))
|
|
1888
|
+
}
|
|
1889
|
+
)
|
|
1826
1890
|
]
|
|
1827
1891
|
}
|
|
1828
1892
|
);
|
|
1829
1893
|
}
|
|
1830
1894
|
|
|
1895
|
+
// src/CollapsibleSection.tsx
|
|
1896
|
+
import { useState as useState6 } from "react";
|
|
1897
|
+
import { Collapsible } from "@base-ui/react/collapsible";
|
|
1898
|
+
import { jsx as jsx42, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
1899
|
+
var OPEN = "open";
|
|
1900
|
+
var CLOSED = "closed";
|
|
1901
|
+
function readStored(key) {
|
|
1902
|
+
if (!key) return void 0;
|
|
1903
|
+
try {
|
|
1904
|
+
const value = window.localStorage.getItem(key);
|
|
1905
|
+
return value === OPEN ? true : value === CLOSED ? false : void 0;
|
|
1906
|
+
} catch {
|
|
1907
|
+
return void 0;
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
function writeStored(key, open) {
|
|
1911
|
+
if (!key) return;
|
|
1912
|
+
try {
|
|
1913
|
+
window.localStorage.setItem(key, open ? OPEN : CLOSED);
|
|
1914
|
+
} catch {
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenChange, storageKey, actions, showActions, children, className, contentClassName }) {
|
|
1918
|
+
const [openState, setOpenState] = useState6(() => readStored(storageKey) ?? defaultOpen);
|
|
1919
|
+
const open = openProp ?? openState;
|
|
1920
|
+
const setOpen = (next) => {
|
|
1921
|
+
setOpenState(next);
|
|
1922
|
+
writeStored(storageKey, next);
|
|
1923
|
+
onOpenChange?.(next);
|
|
1924
|
+
};
|
|
1925
|
+
return /* @__PURE__ */ jsxs29(Collapsible.Root, { open, onOpenChange: setOpen, className: cn("flex flex-col", className), children: [
|
|
1926
|
+
/* @__PURE__ */ jsx42(SectionHeader, { title, chevron: true, isExpanded: open, actions, showActions, className: "shrink-0", render: /* @__PURE__ */ jsx42(Collapsible.Trigger, {}) }),
|
|
1927
|
+
/* @__PURE__ */ jsx42(
|
|
1928
|
+
Collapsible.Panel,
|
|
1929
|
+
{
|
|
1930
|
+
hiddenUntilFound: true,
|
|
1931
|
+
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",
|
|
1932
|
+
children: /* @__PURE__ */ jsx42("div", { className: cn("flex flex-col", contentClassName), children })
|
|
1933
|
+
}
|
|
1934
|
+
)
|
|
1935
|
+
] });
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1831
1938
|
// src/Tabs.tsx
|
|
1832
1939
|
import { Tabs as BaseTabs } from "@base-ui/react/tabs";
|
|
1833
|
-
import { jsx as
|
|
1940
|
+
import { jsx as jsx43, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
1834
1941
|
function Tabs({ tabs, active, onChange, size = "default", className, ...aria }) {
|
|
1835
|
-
return /* @__PURE__ */
|
|
1942
|
+
return /* @__PURE__ */ jsx43(
|
|
1836
1943
|
BaseTabs.Root,
|
|
1837
1944
|
{
|
|
1838
1945
|
value: active,
|
|
@@ -1840,14 +1947,14 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
1840
1947
|
if (details.reason === "none") onChange(value);
|
|
1841
1948
|
},
|
|
1842
1949
|
className,
|
|
1843
|
-
children: /* @__PURE__ */
|
|
1950
|
+
children: /* @__PURE__ */ jsx43(
|
|
1844
1951
|
BaseTabs.List,
|
|
1845
1952
|
{
|
|
1846
1953
|
activateOnFocus: true,
|
|
1847
1954
|
"aria-label": aria["aria-label"],
|
|
1848
1955
|
"aria-labelledby": aria["aria-labelledby"],
|
|
1849
1956
|
className: "flex items-center gap-2",
|
|
1850
|
-
children: tabs.map((tab) => /* @__PURE__ */
|
|
1957
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsxs30(
|
|
1851
1958
|
BaseTabs.Tab,
|
|
1852
1959
|
{
|
|
1853
1960
|
value: tab.id,
|
|
@@ -1860,9 +1967,9 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
1860
1967
|
),
|
|
1861
1968
|
children: [
|
|
1862
1969
|
tab.icon,
|
|
1863
|
-
/* @__PURE__ */
|
|
1970
|
+
/* @__PURE__ */ jsxs30("span", { className: "flex items-baseline", children: [
|
|
1864
1971
|
tab.label,
|
|
1865
|
-
tab.count !== void 0 ? /* @__PURE__ */
|
|
1972
|
+
tab.count !== void 0 ? /* @__PURE__ */ jsx43("span", { className: "ml-2.5 font-mono text-caption tabular-nums text-text-secondary", children: tab.count }) : null
|
|
1866
1973
|
] })
|
|
1867
1974
|
]
|
|
1868
1975
|
},
|
|
@@ -1878,7 +1985,7 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
1878
1985
|
import { createContext as createContext2, useCallback as useCallback3, useContext as useContext2, useEffect as useEffect3, useMemo as useMemo3, useState as useState7 } from "react";
|
|
1879
1986
|
import { createPortal as createPortal2 } from "react-dom";
|
|
1880
1987
|
import { IconCircleCheck } from "@tabler/icons-react";
|
|
1881
|
-
import { jsx as
|
|
1988
|
+
import { jsx as jsx44, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
1882
1989
|
var SURFACE_STYLES = {
|
|
1883
1990
|
success: "bg-success-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-[shadow:var(--shadow-md)]",
|
|
1884
1991
|
brand: "bg-accent-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-[shadow:var(--shadow-md)]",
|
|
@@ -1896,7 +2003,7 @@ var ACTION_BORDER_STYLES = {
|
|
|
1896
2003
|
};
|
|
1897
2004
|
function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAction, className }) {
|
|
1898
2005
|
const hasAction = !!(actionLabel && onAction);
|
|
1899
|
-
return /* @__PURE__ */
|
|
2006
|
+
return /* @__PURE__ */ jsxs31(
|
|
1900
2007
|
"div",
|
|
1901
2008
|
{
|
|
1902
2009
|
className: cn(
|
|
@@ -1908,11 +2015,11 @@ function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAct
|
|
|
1908
2015
|
className
|
|
1909
2016
|
),
|
|
1910
2017
|
children: [
|
|
1911
|
-
/* @__PURE__ */
|
|
1912
|
-
leadingIcon && /* @__PURE__ */
|
|
1913
|
-
/* @__PURE__ */
|
|
2018
|
+
/* @__PURE__ */ jsxs31("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
2019
|
+
leadingIcon && /* @__PURE__ */ jsx44(IconCircleCheck, { size: 16, stroke: 1.5, className: cn("text-text-primary shrink-0", ICON_STYLES[type]) }),
|
|
2020
|
+
/* @__PURE__ */ jsx44("span", { className: "font-normal text-[14px] leading-[1.4] text-text-primary whitespace-nowrap", children: label })
|
|
1914
2021
|
] }),
|
|
1915
|
-
hasAction && /* @__PURE__ */
|
|
2022
|
+
hasAction && /* @__PURE__ */ jsx44(
|
|
1916
2023
|
"button",
|
|
1917
2024
|
{
|
|
1918
2025
|
type: "button",
|
|
@@ -1922,7 +2029,7 @@ function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAct
|
|
|
1922
2029
|
ACTION_BORDER_STYLES[type],
|
|
1923
2030
|
type === "neutral" ? "hover:border-border-strong" : "hover:opacity-80"
|
|
1924
2031
|
),
|
|
1925
|
-
children: /* @__PURE__ */
|
|
2032
|
+
children: /* @__PURE__ */ jsx44("span", { className: "font-medium text-[12px] leading-[12px] text-text-primary whitespace-nowrap", children: actionLabel })
|
|
1926
2033
|
}
|
|
1927
2034
|
)
|
|
1928
2035
|
]
|
|
@@ -1949,10 +2056,10 @@ function ToastProvider({ children }) {
|
|
|
1949
2056
|
return () => clearTimeout(timer);
|
|
1950
2057
|
}, [toast]);
|
|
1951
2058
|
const value = useMemo3(() => ({ showToast, dismissToast }), [showToast, dismissToast]);
|
|
1952
|
-
return /* @__PURE__ */
|
|
2059
|
+
return /* @__PURE__ */ jsxs31(ToastContext.Provider, { value, children: [
|
|
1953
2060
|
children,
|
|
1954
2061
|
toast && createPortal2(
|
|
1955
|
-
/* @__PURE__ */
|
|
2062
|
+
/* @__PURE__ */ jsx44("div", { className: "fixed bottom-4 left-4 z-[100] pointer-events-none", children: /* @__PURE__ */ jsx44(
|
|
1956
2063
|
Toast,
|
|
1957
2064
|
{
|
|
1958
2065
|
className: "pointer-events-auto",
|
|
@@ -1985,6 +2092,7 @@ export {
|
|
|
1985
2092
|
Checkbox,
|
|
1986
2093
|
Chip,
|
|
1987
2094
|
ChipInput,
|
|
2095
|
+
CollapsibleSection,
|
|
1988
2096
|
ConfirmDialog,
|
|
1989
2097
|
DialogShell,
|
|
1990
2098
|
Divider,
|
|
@@ -2013,6 +2121,7 @@ export {
|
|
|
2013
2121
|
RailItem,
|
|
2014
2122
|
Reaction,
|
|
2015
2123
|
ReactionPicker,
|
|
2124
|
+
ScrollArea,
|
|
2016
2125
|
SearchInput,
|
|
2017
2126
|
SectionHeader,
|
|
2018
2127
|
SectionLabel,
|