@estiva-app/ui 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -453,10 +453,32 @@ import { createContext, useContext } from "react";
453
453
  import { IconChevronRight } from "@tabler/icons-react";
454
454
  import { Menu as BaseMenu } from "@base-ui/react/menu";
455
455
 
456
+ // src/triggerDisabled.ts
457
+ function triggerDisabled(trigger) {
458
+ const props = trigger.props;
459
+ return !!(props.disabled || props.disabledReason);
460
+ }
461
+
462
+ // src/ScrollArea.tsx
463
+ import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area";
464
+ import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
465
+ 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";
466
+ var THUMB = "rounded-full bg-border-strong";
467
+ function ScrollArea({ orientation = "vertical", className, viewportClassName, contentClassName, children }) {
468
+ const vertical = orientation !== "horizontal";
469
+ const horizontal = orientation !== "vertical";
470
+ return /* @__PURE__ */ jsxs7(BaseScrollArea.Root, { className: cn("relative min-h-0 min-w-0", className), children: [
471
+ /* @__PURE__ */ jsx12(BaseScrollArea.Viewport, { className: cn("h-full w-full overscroll-contain outline-none", viewportClassName), children: /* @__PURE__ */ jsx12(BaseScrollArea.Content, { className: contentClassName, style: horizontal ? void 0 : { minWidth: 0 }, children }) }),
472
+ 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") }) }),
473
+ 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") }) }),
474
+ vertical && horizontal && /* @__PURE__ */ jsx12(BaseScrollArea.Corner, {})
475
+ ] });
476
+ }
477
+
456
478
  // src/SectionLabel.tsx
457
- import { jsx as jsx12 } from "react/jsx-runtime";
479
+ import { jsx as jsx13 } from "react/jsx-runtime";
458
480
  function SectionLabel({ children, className }) {
459
- return /* @__PURE__ */ jsx12(
481
+ return /* @__PURE__ */ jsx13(
460
482
  "span",
461
483
  {
462
484
  className: cn(
@@ -469,10 +491,10 @@ function SectionLabel({ children, className }) {
469
491
  }
470
492
 
471
493
  // src/Menu.tsx
472
- import { Fragment, jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
494
+ import { Fragment, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
473
495
  var MenuContext = createContext(null);
474
496
  function MenuPanel({ children, className, ...props }) {
475
- return /* @__PURE__ */ jsx13(
497
+ return /* @__PURE__ */ jsx14(
476
498
  "div",
477
499
  {
478
500
  className: cn(
@@ -502,7 +524,7 @@ var VIEWPORT_PAD2 = 8;
502
524
  var HOVER_OPEN_DELAY = 0;
503
525
  var HOVER_CLOSE_DELAY = 150;
504
526
  function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange, actionsRef, children, className }) {
505
- return /* @__PURE__ */ jsxs7(
527
+ return /* @__PURE__ */ jsxs8(
506
528
  BaseMenu.Root,
507
529
  {
508
530
  open,
@@ -510,16 +532,17 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
510
532
  actionsRef,
511
533
  modal: false,
512
534
  children: [
513
- /* @__PURE__ */ jsx13(
535
+ /* @__PURE__ */ jsx14(
514
536
  BaseMenu.Trigger,
515
537
  {
516
538
  render: trigger,
539
+ disabled: triggerDisabled(trigger),
517
540
  openOnHover,
518
541
  delay: HOVER_OPEN_DELAY,
519
542
  closeDelay: HOVER_CLOSE_DELAY
520
543
  }
521
544
  ),
522
- /* @__PURE__ */ jsx13(BaseMenu.Portal, { children: /* @__PURE__ */ jsx13(
545
+ /* @__PURE__ */ jsx14(BaseMenu.Portal, { children: /* @__PURE__ */ jsx14(
523
546
  BaseMenu.Positioner,
524
547
  {
525
548
  side: "bottom",
@@ -527,13 +550,13 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
527
550
  sideOffset: GAP3,
528
551
  collisionPadding: VIEWPORT_PAD2,
529
552
  className: "z-50 data-[anchor-hidden]:hidden",
530
- children: /* @__PURE__ */ jsx13(
553
+ children: /* @__PURE__ */ jsx14(
531
554
  BaseMenu.Popup,
532
555
  {
533
556
  "data-interactive": true,
534
- className: cn("min-w-[180px] max-h-[var(--available-height)] overflow-y-auto outline-none", className),
535
- render: /* @__PURE__ */ jsx13(MenuPanel, {}),
536
- children: /* @__PURE__ */ jsx13(MenuContext.Provider, { value: { openOnHover }, children })
557
+ className: cn("min-w-[180px] outline-none", className),
558
+ render: /* @__PURE__ */ jsx14(MenuPanel, {}),
559
+ 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 }) })
537
560
  }
538
561
  )
539
562
  }
@@ -549,20 +572,20 @@ function MenuSub({ label, leading, selected, children, className }) {
549
572
  '[@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".'
550
573
  );
551
574
  }
552
- return /* @__PURE__ */ jsxs7(BaseMenu.SubmenuRoot, { children: [
553
- /* @__PURE__ */ jsx13(
575
+ return /* @__PURE__ */ jsxs8(BaseMenu.SubmenuRoot, { children: [
576
+ /* @__PURE__ */ jsx14(
554
577
  BaseMenu.SubmenuTrigger,
555
578
  {
556
579
  openOnHover: true,
557
580
  delay: 0,
558
581
  closeDelay: 150,
559
582
  nativeButton: true,
560
- render: /* @__PURE__ */ jsx13("button", { type: "button" }),
583
+ render: /* @__PURE__ */ jsx14("button", { type: "button" }),
561
584
  className: menuItemClassName({ size: "default", selected }),
562
- children: /* @__PURE__ */ jsx13(MenuItemBody, { label, leading, submenu: true })
585
+ children: /* @__PURE__ */ jsx14(MenuItemBody, { label, leading, submenu: true })
563
586
  }
564
587
  ),
565
- /* @__PURE__ */ jsx13(BaseMenu.Portal, { children: /* @__PURE__ */ jsx13(
588
+ /* @__PURE__ */ jsx14(BaseMenu.Portal, { children: /* @__PURE__ */ jsx14(
566
589
  BaseMenu.Positioner,
567
590
  {
568
591
  side: "inline-end",
@@ -570,7 +593,7 @@ function MenuSub({ label, leading, selected, children, className }) {
570
593
  sideOffset: GAP3,
571
594
  collisionPadding: VIEWPORT_PAD2,
572
595
  className: "z-50 data-[anchor-hidden]:hidden",
573
- children: /* @__PURE__ */ jsx13(BaseMenu.Popup, { className: cn("w-[160px]", className), "data-interactive": true, render: /* @__PURE__ */ jsx13(MenuPanel, {}), children })
596
+ children: /* @__PURE__ */ jsx14(BaseMenu.Popup, { className: cn("w-[160px]", className), "data-interactive": true, render: /* @__PURE__ */ jsx14(MenuPanel, {}), children })
574
597
  }
575
598
  ) })
576
599
  ] });
@@ -602,25 +625,25 @@ function menuItemClassName({ size, selected, className }) {
602
625
  );
603
626
  }
604
627
  function MenuItemBody({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected }) {
605
- const edge = trailing ?? (shortcut ? /* @__PURE__ */ jsx13(Kbd, { children: shortcut }) : submenu ? /* @__PURE__ */ jsx13(IconChevronRight, { size: 16, stroke: 1.5, className: "shrink-0 text-text-muted" }) : null);
606
- return /* @__PURE__ */ jsxs7(Fragment, { children: [
607
- leading && /* @__PURE__ */ jsx13("span", { className: "flex shrink-0 items-center", children: leading }),
608
- children ?? /* @__PURE__ */ jsxs7("span", { className: cn("flex min-w-0 flex-1 flex-col", size === "tall" && "gap-[2px]"), children: [
609
- /* @__PURE__ */ jsx13("span", { className: cn("truncate text-[14px] leading-[140%]", destructive ? "text-error-default" : "text-text-primary"), children: label }),
610
- description && /* @__PURE__ */ jsx13("span", { className: "truncate text-[12px] leading-[120%] text-text-secondary", children: description })
628
+ 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);
629
+ return /* @__PURE__ */ jsxs8(Fragment, { children: [
630
+ leading && /* @__PURE__ */ jsx14("span", { className: "flex shrink-0 items-center", children: leading }),
631
+ children ?? /* @__PURE__ */ jsxs8("span", { className: cn("flex min-w-0 flex-1 flex-col", size === "tall" && "gap-[2px]"), children: [
632
+ /* @__PURE__ */ jsx14("span", { className: cn("truncate text-[14px] leading-[140%]", destructive ? "text-error-default" : "text-text-primary"), children: label }),
633
+ description && /* @__PURE__ */ jsx14("span", { className: "truncate text-[12px] leading-[120%] text-text-secondary", children: description })
611
634
  ] }),
612
635
  (edge || hint) && // One grid cell holding both, right-aligned: the slot is as wide as
613
636
  // the wider of the two and never changes, so revealing the hint moves
614
637
  // nothing. No transition here either — the hint switches on the same
615
638
  // :hover / `selected` as the fill, in the same frame.
616
- /* @__PURE__ */ jsxs7("span", { className: "grid shrink-0 items-center justify-items-end [&>*]:col-start-1 [&>*]:row-start-1", children: [
617
- edge && /* @__PURE__ */ jsx13("span", { className: cn("flex items-center", hint && "group-hover:opacity-0 group-data-[highlighted]:opacity-0", hint && selected && "opacity-0"), children: edge }),
618
- hint && /* @__PURE__ */ jsx13("span", { className: cn("flex items-center opacity-0 group-hover:opacity-100 group-data-[highlighted]:opacity-100", selected && "opacity-100"), children: hint })
639
+ /* @__PURE__ */ jsxs8("span", { className: "grid shrink-0 items-center justify-items-end [&>*]:col-start-1 [&>*]:row-start-1", children: [
640
+ 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 }),
641
+ 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 })
619
642
  ] })
620
643
  ] });
621
644
  }
622
645
  function MenuItem({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected, className, ...props }) {
623
- const body = /* @__PURE__ */ jsx13(
646
+ const body = /* @__PURE__ */ jsx14(
624
647
  MenuItemBody,
625
648
  {
626
649
  label,
@@ -638,13 +661,13 @@ function MenuItem({ label, children, size = "default", description, leading, tra
638
661
  );
639
662
  const rowClassName = menuItemClassName({ size, selected, className });
640
663
  if (!useContext(MenuContext)) {
641
- return /* @__PURE__ */ jsx13("button", { type: "button", className: rowClassName, ...props, children: body });
664
+ return /* @__PURE__ */ jsx14("button", { type: "button", className: rowClassName, ...props, children: body });
642
665
  }
643
- return /* @__PURE__ */ jsx13(
666
+ return /* @__PURE__ */ jsx14(
644
667
  BaseMenu.Item,
645
668
  {
646
669
  nativeButton: true,
647
- render: /* @__PURE__ */ jsx13("button", { type: "button" }),
670
+ render: /* @__PURE__ */ jsx14("button", { type: "button" }),
648
671
  className: rowClassName,
649
672
  ...props,
650
673
  children: body
@@ -652,33 +675,33 @@ function MenuItem({ label, children, size = "default", description, leading, tra
652
675
  );
653
676
  }
654
677
  function EnterHint({ target }) {
655
- return /* @__PURE__ */ jsxs7("span", { className: "flex shrink-0 items-center gap-1.5 text-text-muted", children: [
656
- /* @__PURE__ */ jsx13(Kbd, { children: "\u21A9 Enter" }),
657
- target && /* @__PURE__ */ jsx13("span", { className: "text-[9px] font-medium leading-[115%] signal:font-mono signal:text-[9.5px] signal:tracking-[0.04em]", children: target })
678
+ return /* @__PURE__ */ jsxs8("span", { className: "flex shrink-0 items-center gap-1.5 text-text-muted", children: [
679
+ /* @__PURE__ */ jsx14(Kbd, { children: "\u21A9 Enter" }),
680
+ target && /* @__PURE__ */ jsx14("span", { className: "text-[9px] font-medium leading-[115%] signal:font-mono signal:text-[9.5px] signal:tracking-[0.04em]", children: target })
658
681
  ] });
659
682
  }
660
683
  function MenuSection({ label, children, className }) {
661
684
  const inMenu = useContext(MenuContext) !== null;
662
- const heading = /* @__PURE__ */ jsx13("div", { className: cn("flex h-8 items-center px-2", className), children: /* @__PURE__ */ jsx13(SectionLabel, { className: "text-text-secondary", children: label }) });
685
+ 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 }) });
663
686
  if (!inMenu) {
664
- return /* @__PURE__ */ jsxs7("div", { className: "flex flex-col", children: [
687
+ return /* @__PURE__ */ jsxs8("div", { className: "flex flex-col", children: [
665
688
  heading,
666
689
  children
667
690
  ] });
668
691
  }
669
- return /* @__PURE__ */ jsxs7(BaseMenu.Group, { className: "flex flex-col", children: [
670
- /* @__PURE__ */ jsx13(BaseMenu.GroupLabel, { render: heading }),
692
+ return /* @__PURE__ */ jsxs8(BaseMenu.Group, { className: "flex flex-col", children: [
693
+ /* @__PURE__ */ jsx14(BaseMenu.GroupLabel, { render: heading }),
671
694
  children
672
695
  ] });
673
696
  }
674
697
  function MenuRow({ children, className }) {
675
- return /* @__PURE__ */ jsx13("div", { className: cn("flex items-center gap-2 px-2 py-1.5", className), children });
698
+ return /* @__PURE__ */ jsx14("div", { className: cn("flex items-center gap-2 px-2 py-1.5", className), children });
676
699
  }
677
700
 
678
701
  // src/ChipInput.tsx
679
- import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
702
+ import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
680
703
  function InputChip({ label, leading, onRemove, className }) {
681
- return /* @__PURE__ */ jsxs8(
704
+ return /* @__PURE__ */ jsxs9(
682
705
  "div",
683
706
  {
684
707
  className: cn(
@@ -694,9 +717,9 @@ function InputChip({ label, leading, onRemove, className }) {
694
717
  className
695
718
  ),
696
719
  children: [
697
- leading && /* @__PURE__ */ jsx14("span", { className: "flex shrink-0 items-center", children: leading }),
698
- /* @__PURE__ */ jsx14("span", { className: "text-caption font-medium text-text-primary", children: label }),
699
- onRemove && /* @__PURE__ */ jsx14(
720
+ leading && /* @__PURE__ */ jsx15("span", { className: "flex shrink-0 items-center", children: leading }),
721
+ /* @__PURE__ */ jsx15("span", { className: "text-caption font-medium text-text-primary", children: label }),
722
+ onRemove && /* @__PURE__ */ jsx15(
700
723
  "button",
701
724
  {
702
725
  type: "button",
@@ -706,7 +729,7 @@ function InputChip({ label, leading, onRemove, className }) {
706
729
  },
707
730
  className: "size-4 flex items-center justify-center rounded-full hover:bg-bg-hover text-text-secondary",
708
731
  "aria-label": `Remove ${label}`,
709
- children: /* @__PURE__ */ jsx14(IconX2, { size: 10, stroke: 1.5 })
732
+ children: /* @__PURE__ */ jsx15(IconX2, { size: 10, stroke: 1.5 })
710
733
  }
711
734
  )
712
735
  ]
@@ -795,16 +818,16 @@ function ChipInput({
795
818
  }
796
819
  }
797
820
  }
798
- return /* @__PURE__ */ jsxs8("div", { className: "relative", children: [
799
- /* @__PURE__ */ jsxs8(
821
+ return /* @__PURE__ */ jsxs9("div", { className: "relative", children: [
822
+ /* @__PURE__ */ jsxs9(
800
823
  "div",
801
824
  {
802
825
  ref: wrapperRef,
803
826
  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",
804
827
  onClick: () => inputRef.current?.focus(),
805
828
  children: [
806
- value.map((o) => /* @__PURE__ */ jsx14(InputChip, { label: o.label, leading: chipLeading?.(o), onRemove: () => removeOption(o.id) }, o.id)),
807
- /* @__PURE__ */ jsx14(
829
+ value.map((o) => /* @__PURE__ */ jsx15(InputChip, { label: o.label, leading: chipLeading?.(o), onRemove: () => removeOption(o.id) }, o.id)),
830
+ /* @__PURE__ */ jsx15(
808
831
  "input",
809
832
  {
810
833
  ref: inputRef,
@@ -826,7 +849,7 @@ function ChipInput({
826
849
  }
827
850
  ),
828
851
  showDropdown && anchorRect && createPortal(
829
- /* @__PURE__ */ jsx14(
852
+ /* @__PURE__ */ jsx15(
830
853
  "div",
831
854
  {
832
855
  className: "fixed z-[60] overflow-y-auto bg-bg-elevated border border-border-default rounded-lg shadow-lg",
@@ -839,7 +862,7 @@ function ChipInput({
839
862
  }),
840
863
  width: anchorRect.width
841
864
  },
842
- children: matches.map((o, i) => /* @__PURE__ */ jsx14(
865
+ children: matches.map((o, i) => /* @__PURE__ */ jsx15(
843
866
  MenuItem,
844
867
  {
845
868
  size: "tall",
@@ -867,9 +890,26 @@ function ChipInput({
867
890
  import { useCallback, useRef as useRef2 } from "react";
868
891
 
869
892
  // src/Divider.tsx
870
- import { jsx as jsx15 } from "react/jsx-runtime";
871
- function Divider({ orientation = "horizontal", className }) {
872
- return /* @__PURE__ */ jsx15(
893
+ import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
894
+ function Divider({ orientation = "horizontal", label, tone = "default", className }) {
895
+ if (label && orientation === "horizontal") {
896
+ const line = tone === "warning" ? "bg-warning-muted" : "bg-border-subtle";
897
+ return /* @__PURE__ */ jsxs10(
898
+ "div",
899
+ {
900
+ role: "separator",
901
+ "aria-orientation": "horizontal",
902
+ "aria-label": label,
903
+ className: cn("flex shrink-0 items-center gap-2 mx-3", className),
904
+ children: [
905
+ /* @__PURE__ */ jsx16("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
906
+ /* @__PURE__ */ jsx16("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
907
+ /* @__PURE__ */ jsx16("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
908
+ ]
909
+ }
910
+ );
911
+ }
912
+ return /* @__PURE__ */ jsx16(
873
913
  "div",
874
914
  {
875
915
  role: "separator",
@@ -880,15 +920,15 @@ function Divider({ orientation = "horizontal", className }) {
880
920
  }
881
921
 
882
922
  // src/Person.tsx
883
- import { jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
923
+ import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
884
924
  function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
885
925
  return (
886
926
  // gap-2: the face-to-name distance is one rule (8px) wherever a person
887
927
  // appears — Katerina, 2026-09-01, set on Person so PersonTrigger and every
888
928
  // row agree by construction.
889
- /* @__PURE__ */ jsxs9("span", { className: cn("flex min-w-0 items-center gap-2", className), children: [
890
- /* @__PURE__ */ jsx16(Avatar, { name, src: picture, size }),
891
- /* @__PURE__ */ jsx16("span", { className: cn("truncate", !name && "text-text-muted"), children: name ?? fallback })
929
+ /* @__PURE__ */ jsxs11("span", { className: cn("flex min-w-0 items-center gap-2", className), children: [
930
+ /* @__PURE__ */ jsx17(Avatar, { name, src: picture, size }),
931
+ /* @__PURE__ */ jsx17("span", { className: cn("truncate", !name && "text-text-muted"), children: name ?? fallback })
892
932
  ] })
893
933
  );
894
934
  }
@@ -896,10 +936,10 @@ function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
896
936
  // src/PersonTrigger.tsx
897
937
  import { Button as BaseButton3 } from "@base-ui/react/button";
898
938
  import { IconChevronDown } from "@tabler/icons-react";
899
- import { jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
939
+ import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
900
940
  function PersonTrigger({ name, picture, fallback, size, open = false, compact = false, className, ...props }) {
901
941
  if (compact) {
902
- return /* @__PURE__ */ jsx17(
942
+ return /* @__PURE__ */ jsx18(
903
943
  BaseButton3,
904
944
  {
905
945
  type: "button",
@@ -908,11 +948,11 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
908
948
  "aria-label": props["aria-label"] ?? name ?? fallback,
909
949
  className: cn("cursor-pointer rounded-full", className),
910
950
  ...props,
911
- children: /* @__PURE__ */ jsx17(Avatar, { name, src: picture, size: size ?? 36 })
951
+ children: /* @__PURE__ */ jsx18(Avatar, { name, src: picture, size: size ?? 36 })
912
952
  }
913
953
  );
914
954
  }
915
- return /* @__PURE__ */ jsxs10(
955
+ return /* @__PURE__ */ jsxs12(
916
956
  BaseButton3,
917
957
  {
918
958
  type: "button",
@@ -930,18 +970,18 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
930
970
  ),
931
971
  ...props,
932
972
  children: [
933
- /* @__PURE__ */ jsx17(Person, { name, picture, fallback, size: size ?? 22 }),
934
- /* @__PURE__ */ jsx17(IconChevronDown, { size: 14, stroke: 1.5, className: "shrink-0 text-text-muted" })
973
+ /* @__PURE__ */ jsx18(Person, { name, picture, fallback, size: size ?? 22 }),
974
+ /* @__PURE__ */ jsx18(IconChevronDown, { size: 14, stroke: 1.5, className: "shrink-0 text-text-muted" })
935
975
  ]
936
976
  }
937
977
  );
938
978
  }
939
979
 
940
980
  // src/IdentityMenu.tsx
941
- import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
981
+ import { Fragment as Fragment2, jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
942
982
  function IdentityPanel({ className, onClose = () => {
943
983
  }, ...rest }) {
944
- return /* @__PURE__ */ jsx18(MenuPanel, { className: cn("w-72", className), children: /* @__PURE__ */ jsx18(IdentityRows, { ...rest, onClose }) });
984
+ return /* @__PURE__ */ jsx19(MenuPanel, { className: cn("w-72", className), children: /* @__PURE__ */ jsx19(IdentityRows, { ...rest, onClose }) });
945
985
  }
946
986
  function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, onClose, children }) {
947
987
  const act = (action) => () => {
@@ -949,36 +989,36 @@ function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, on
949
989
  action();
950
990
  };
951
991
  const appRows = typeof children === "function" ? children(onClose) : children;
952
- return /* @__PURE__ */ jsxs11(Fragment2, { children: [
953
- /* @__PURE__ */ jsxs11(MenuSection, { label: signedIn ? "Signed in as" : "Acting as", children: [
954
- /* @__PURE__ */ jsx18(MenuRow, { children: /* @__PURE__ */ jsx18(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28, className: "text-body-2-strong" }) }),
955
- /* @__PURE__ */ jsx18(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." }),
956
- me.email && /* @__PURE__ */ jsxs11(Note, { children: [
992
+ return /* @__PURE__ */ jsxs13(Fragment2, { children: [
993
+ /* @__PURE__ */ jsxs13(MenuSection, { label: signedIn ? "Signed in as" : "Acting as", children: [
994
+ /* @__PURE__ */ jsx19(MenuRow, { children: /* @__PURE__ */ jsx19(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28, className: "text-body-2-strong" }) }),
995
+ /* @__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." }),
996
+ me.email && /* @__PURE__ */ jsxs13(Note, { children: [
957
997
  me.email,
958
998
  " \xB7 known to Estiva, never published to the relay"
959
999
  ] })
960
1000
  ] }),
961
- relayUrl && /* @__PURE__ */ jsxs11(Fragment2, { children: [
962
- /* @__PURE__ */ jsx18(Divider, { className: "mx-0 my-2" }),
963
- /* @__PURE__ */ jsxs11(MenuSection, { label: "Workspace", children: [
964
- /* @__PURE__ */ jsx18(MenuRow, { children: /* @__PURE__ */ jsx18("span", { className: "break-all font-mono text-caption text-text-primary", children: relayUrl }) }),
965
- /* @__PURE__ */ jsx18(Note, { children: "Everyone on this relay shares this workspace, in every app." })
1001
+ relayUrl && /* @__PURE__ */ jsxs13(Fragment2, { children: [
1002
+ /* @__PURE__ */ jsx19(Divider, { className: "mx-0 my-2" }),
1003
+ /* @__PURE__ */ jsxs13(MenuSection, { label: "Workspace", children: [
1004
+ /* @__PURE__ */ jsx19(MenuRow, { children: /* @__PURE__ */ jsx19("span", { className: "break-all font-mono text-caption text-text-primary", children: relayUrl }) }),
1005
+ /* @__PURE__ */ jsx19(Note, { children: "Everyone on this relay shares this workspace, in every app." })
966
1006
  ] })
967
1007
  ] }),
968
- appRows && /* @__PURE__ */ jsxs11(Fragment2, { children: [
969
- /* @__PURE__ */ jsx18(Divider, { className: "mx-0 my-2" }),
1008
+ appRows && /* @__PURE__ */ jsxs13(Fragment2, { children: [
1009
+ /* @__PURE__ */ jsx19(Divider, { className: "mx-0 my-2" }),
970
1010
  appRows
971
1011
  ] }),
972
- signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */ jsx18(Divider, { className: "mx-0 my-2" }) : null,
973
- signedIn && idBase && /* @__PURE__ */ jsx18(
1012
+ signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */ jsx19(Divider, { className: "mx-0 my-2" }) : null,
1013
+ signedIn && idBase && /* @__PURE__ */ jsx19(
974
1014
  MenuItem,
975
1015
  {
976
1016
  label: "Edit your profile in Estiva ID",
977
1017
  onClick: act(() => window.open(idBase, "_blank", "noopener,noreferrer"))
978
1018
  }
979
1019
  ),
980
- onCopyKey && /* @__PURE__ */ jsx18(MenuItem, { label: "Copy public key", onClick: act(onCopyKey) }),
981
- idBase && onSignOut && /* @__PURE__ */ jsx18(MenuItem, { label: "Sign out", onClick: act(onSignOut) })
1020
+ onCopyKey && /* @__PURE__ */ jsx19(MenuItem, { label: "Copy public key", onClick: act(onCopyKey) }),
1021
+ idBase && onSignOut && /* @__PURE__ */ jsx19(MenuItem, { label: "Sign out", onClick: act(onSignOut) })
982
1022
  ] });
983
1023
  }
984
1024
  function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, compact = false, className, children }) {
@@ -989,13 +1029,13 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
989
1029
  to be `relative`, because the panel was positioned against it; the panel
990
1030
  hangs from the trigger and portals now, so a positioning context here
991
1031
  would only be a lie about what this box does. */
992
- /* @__PURE__ */ jsx18("div", { className, children: /* @__PURE__ */ jsx18(
1032
+ /* @__PURE__ */ jsx19("div", { className, children: /* @__PURE__ */ jsx19(
993
1033
  Menu,
994
1034
  {
995
1035
  align: "right",
996
1036
  actionsRef: actions,
997
1037
  className: "w-72",
998
- trigger: /* @__PURE__ */ jsx18(
1038
+ trigger: /* @__PURE__ */ jsx19(
999
1039
  PersonTrigger,
1000
1040
  {
1001
1041
  name: me.name,
@@ -1006,7 +1046,7 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
1006
1046
  "aria-label": compact ? "Account menu" : void 0
1007
1047
  }
1008
1048
  ),
1009
- children: /* @__PURE__ */ jsx18(
1049
+ children: /* @__PURE__ */ jsx19(
1010
1050
  IdentityRows,
1011
1051
  {
1012
1052
  me,
@@ -1024,26 +1064,25 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
1024
1064
  );
1025
1065
  }
1026
1066
  function Note({ children }) {
1027
- return /* @__PURE__ */ jsx18("span", { className: "px-2 pb-1.5 text-caption text-text-secondary", children });
1067
+ return /* @__PURE__ */ jsx19("span", { className: "px-2 pb-1.5 text-caption text-text-secondary", children });
1028
1068
  }
1029
1069
 
1030
1070
  // src/Field.tsx
1031
1071
  import { cloneElement, isValidElement } from "react";
1032
1072
  import { Field as BaseField } from "@base-ui/react/field";
1033
- import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
1073
+ import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
1034
1074
  function Field({ label, required = false, helper, error, children }) {
1035
- const line = error ?? helper;
1036
1075
  const control = required && isValidElement(children) ? cloneElement(children, {
1037
1076
  "aria-required": children.props["aria-required"] ?? true
1038
1077
  }) : children;
1039
- return /* @__PURE__ */ jsxs12(BaseField.Root, { invalid: !!error, className: "flex flex-col gap-2", children: [
1040
- /* @__PURE__ */ jsxs12(BaseField.Label, { className: cn("text-input-label text-text-primary", required && "flex items-center"), children: [
1078
+ return /* @__PURE__ */ jsxs14(BaseField.Root, { invalid: !!error, className: "flex flex-col gap-2", children: [
1079
+ /* @__PURE__ */ jsxs14(BaseField.Label, { className: cn("text-input-label text-text-primary", required && "flex items-center"), children: [
1041
1080
  label,
1042
- required && /* @__PURE__ */ jsx19("span", { className: "text-error-default ml-0.5", children: "*" })
1081
+ required && /* @__PURE__ */ jsx20("span", { "aria-hidden": "true", className: "text-error-default ml-0.5", children: "*" })
1043
1082
  ] }),
1044
- line == null ? control : /* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-1.5", children: [
1083
+ /* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1.5", children: [
1045
1084
  control,
1046
- error != null ? /* @__PURE__ */ jsx19(BaseField.Error, { match: true, className: "text-caption text-error-default", children: error }) : /* @__PURE__ */ jsx19(BaseField.Description, { className: "text-caption text-text-muted", children: helper })
1085
+ 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
1047
1086
  ] })
1048
1087
  ] });
1049
1088
  }
@@ -1051,12 +1090,12 @@ function Field({ label, required = false, helper, error, children }) {
1051
1090
  // src/Select.tsx
1052
1091
  import { IconCheck as IconCheck2, IconChevronDown as IconChevronDown2 } from "@tabler/icons-react";
1053
1092
  import { Select as BaseSelect } from "@base-ui/react/select";
1054
- import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
1093
+ import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
1055
1094
  var GAP4 = 4;
1056
1095
  var VIEWPORT_PAD3 = 8;
1057
1096
  function Select({ value, onChange, options, size = "default", ariaLabel, placeholder = "Select\u2026", disabled, className, ...aria }) {
1058
1097
  const selected = options.find((o) => o.value === value);
1059
- return /* @__PURE__ */ jsxs13(
1098
+ return /* @__PURE__ */ jsxs15(
1060
1099
  BaseSelect.Root,
1061
1100
  {
1062
1101
  value,
@@ -1064,7 +1103,7 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
1064
1103
  disabled,
1065
1104
  modal: false,
1066
1105
  children: [
1067
- /* @__PURE__ */ jsxs13(
1106
+ /* @__PURE__ */ jsxs15(
1068
1107
  BaseSelect.Trigger,
1069
1108
  {
1070
1109
  "aria-label": ariaLabel,
@@ -1091,20 +1130,20 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
1091
1130
  className
1092
1131
  ),
1093
1132
  children: [
1094
- /* @__PURE__ */ jsxs13("span", { className: cn("flex min-w-0 items-center gap-2", !selected && "text-text-muted"), children: [
1095
- selected?.leading && /* @__PURE__ */ jsx20("span", { className: "flex shrink-0 items-center", children: selected.leading }),
1096
- /* @__PURE__ */ jsx20(BaseSelect.Value, { className: "truncate", children: () => selected?.label ?? placeholder })
1133
+ /* @__PURE__ */ jsxs15("span", { className: cn("flex min-w-0 items-center gap-2", !selected && "text-text-muted"), children: [
1134
+ selected?.leading && /* @__PURE__ */ jsx21("span", { className: "flex shrink-0 items-center", children: selected.leading }),
1135
+ /* @__PURE__ */ jsx21(BaseSelect.Value, { className: "truncate", children: () => selected?.label ?? placeholder })
1097
1136
  ] }),
1098
- /* @__PURE__ */ jsx20(
1137
+ /* @__PURE__ */ jsx21(
1099
1138
  BaseSelect.Icon,
1100
1139
  {
1101
- render: /* @__PURE__ */ jsx20(IconChevronDown2, { size: size === "small" ? 14 : 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
1140
+ render: /* @__PURE__ */ jsx21(IconChevronDown2, { size: size === "small" ? 14 : 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
1102
1141
  }
1103
1142
  )
1104
1143
  ]
1105
1144
  }
1106
1145
  ),
1107
- /* @__PURE__ */ jsx20(BaseSelect.Portal, { children: /* @__PURE__ */ jsx20(
1146
+ /* @__PURE__ */ jsx21(BaseSelect.Portal, { children: /* @__PURE__ */ jsx21(
1108
1147
  BaseSelect.Positioner,
1109
1148
  {
1110
1149
  side: "bottom",
@@ -1113,30 +1152,30 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
1113
1152
  collisionPadding: VIEWPORT_PAD3,
1114
1153
  alignItemWithTrigger: false,
1115
1154
  className: "z-50 data-[anchor-hidden]:hidden",
1116
- children: /* @__PURE__ */ jsx20(
1155
+ children: /* @__PURE__ */ jsx21(
1117
1156
  BaseSelect.Popup,
1118
1157
  {
1119
- className: "max-h-[min(288px,var(--available-height))] min-w-[var(--anchor-width)] overflow-y-auto rounded-lg border border-border-default bg-bg-elevated p-1 shadow-lg",
1120
- children: options.map((option) => /* @__PURE__ */ jsxs13(
1158
+ className: "min-w-[var(--anchor-width)] rounded-lg border border-border-default bg-bg-elevated p-1 shadow-lg",
1159
+ 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(
1121
1160
  BaseSelect.Item,
1122
1161
  {
1123
1162
  value: option.value,
1124
1163
  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",
1125
1164
  children: [
1126
- /* @__PURE__ */ jsxs13("span", { className: "flex min-w-0 items-center gap-2", children: [
1127
- option.leading && /* @__PURE__ */ jsx20("span", { className: "flex shrink-0 items-center", children: option.leading }),
1128
- /* @__PURE__ */ jsx20(BaseSelect.ItemText, { className: "truncate", children: option.label })
1165
+ /* @__PURE__ */ jsxs15("span", { className: "flex min-w-0 items-center gap-2", children: [
1166
+ option.leading && /* @__PURE__ */ jsx21("span", { className: "flex shrink-0 items-center", children: option.leading }),
1167
+ /* @__PURE__ */ jsx21(BaseSelect.ItemText, { className: "truncate", children: option.label })
1129
1168
  ] }),
1130
- /* @__PURE__ */ jsx20(
1169
+ /* @__PURE__ */ jsx21(
1131
1170
  BaseSelect.ItemIndicator,
1132
1171
  {
1133
- render: /* @__PURE__ */ jsx20(IconCheck2, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
1172
+ render: /* @__PURE__ */ jsx21(IconCheck2, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
1134
1173
  }
1135
1174
  )
1136
1175
  ]
1137
1176
  },
1138
1177
  option.value
1139
- ))
1178
+ )) })
1140
1179
  }
1141
1180
  )
1142
1181
  }
@@ -1149,9 +1188,9 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
1149
1188
  // src/TextInput.tsx
1150
1189
  import { forwardRef } from "react";
1151
1190
  import { Input } from "@base-ui/react/input";
1152
- import { jsx as jsx21 } from "react/jsx-runtime";
1191
+ import { jsx as jsx22 } from "react/jsx-runtime";
1153
1192
  var TextInput = forwardRef(function TextInput2({ className, type = "text", ...props }, ref) {
1154
- return /* @__PURE__ */ jsx21(
1193
+ return /* @__PURE__ */ jsx22(
1155
1194
  Input,
1156
1195
  {
1157
1196
  ref,
@@ -1172,13 +1211,13 @@ var TextInput = forwardRef(function TextInput2({ className, type = "text", ...pr
1172
1211
  // src/Textarea.tsx
1173
1212
  import { forwardRef as forwardRef2 } from "react";
1174
1213
  import { Field as BaseField2 } from "@base-ui/react/field";
1175
- import { jsx as jsx22 } from "react/jsx-runtime";
1214
+ import { jsx as jsx23 } from "react/jsx-runtime";
1176
1215
  var Textarea = forwardRef2(function Textarea2({ className, ...props }, ref) {
1177
- return /* @__PURE__ */ jsx22(
1216
+ return /* @__PURE__ */ jsx23(
1178
1217
  BaseField2.Control,
1179
1218
  {
1180
1219
  ref,
1181
- render: /* @__PURE__ */ jsx22("textarea", {}),
1220
+ render: /* @__PURE__ */ jsx23("textarea", {}),
1182
1221
  className: cn(
1183
1222
  "bg-bg-inset border border-border-default focus:border-border-focus rounded-lg px-3 py-2",
1184
1223
  "text-[14px] leading-[1.4] font-normal text-text-primary placeholder:text-text-muted",
@@ -1200,20 +1239,20 @@ import { useRef as useRef3 } from "react";
1200
1239
  import { Dialog } from "@base-ui/react/dialog";
1201
1240
  import { AlertDialog } from "@base-ui/react/alert-dialog";
1202
1241
  import { IconX as IconX3 } from "@tabler/icons-react";
1203
- import { jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
1242
+ import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
1204
1243
  function DialogShell({ title, onClose, headerContent, footer, children, bodyClassName, width = 502, alert = false }) {
1205
1244
  const Parts = alert ? AlertDialog : Dialog;
1206
1245
  const popupRef = useRef3(null);
1207
- return /* @__PURE__ */ jsx23(
1246
+ return /* @__PURE__ */ jsx24(
1208
1247
  Parts.Root,
1209
1248
  {
1210
1249
  open: true,
1211
1250
  onOpenChange: (open) => {
1212
1251
  if (!open) onClose();
1213
1252
  },
1214
- children: /* @__PURE__ */ jsxs14(Parts.Portal, { children: [
1215
- /* @__PURE__ */ jsx23(Parts.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
1216
- /* @__PURE__ */ jsx23("div", { className: "fixed inset-0 z-50 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs14(
1253
+ children: /* @__PURE__ */ jsxs16(Parts.Portal, { children: [
1254
+ /* @__PURE__ */ jsx24(Parts.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
1255
+ /* @__PURE__ */ jsx24("div", { className: "fixed inset-0 z-50 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs16(
1217
1256
  Parts.Popup,
1218
1257
  {
1219
1258
  ref: popupRef,
@@ -1222,17 +1261,17 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
1222
1261
  className: "bg-bg-elevated border border-border-subtle rounded-lg shadow-lg pointer-events-auto flex flex-col overflow-hidden outline-none",
1223
1262
  style: { width },
1224
1263
  children: [
1225
- /* @__PURE__ */ jsxs14("div", { className: "h-12 flex items-center justify-between pl-5 pr-4 border-b border-border-subtle shrink-0", children: [
1226
- headerContent ?? /* @__PURE__ */ jsx23(Parts.Title, { className: "text-h4 text-text-primary", render: /* @__PURE__ */ jsx23("span", {}), children: title }),
1227
- /* @__PURE__ */ jsx23(
1264
+ /* @__PURE__ */ jsxs16("div", { className: "h-12 flex items-center justify-between pl-5 pr-4 border-b border-border-subtle shrink-0", children: [
1265
+ headerContent ?? /* @__PURE__ */ jsx24(Parts.Title, { className: "text-h4 text-text-primary", render: /* @__PURE__ */ jsx24("span", {}), children: title }),
1266
+ /* @__PURE__ */ jsx24(
1228
1267
  Parts.Close,
1229
1268
  {
1230
- render: /* @__PURE__ */ jsx23(IconButton, { tooltip: "Close", "aria-label": "Close", children: /* @__PURE__ */ jsx23(IconX3, { size: 16, stroke: 1.5 }) })
1269
+ render: /* @__PURE__ */ jsx24(IconButton, { tooltip: "Close", "aria-label": "Close", children: /* @__PURE__ */ jsx24(IconX3, { size: 16, stroke: 1.5 }) })
1231
1270
  }
1232
1271
  )
1233
1272
  ] }),
1234
- /* @__PURE__ */ jsx23("div", { className: cn("pl-5 pr-4 py-4", footer != null && "border-b border-border-subtle", bodyClassName), children }),
1235
- footer != null && /* @__PURE__ */ jsx23("div", { className: "h-12 flex items-center justify-end gap-2 pl-5 pr-4 shrink-0", children: footer })
1273
+ /* @__PURE__ */ jsx24("div", { className: cn("pl-5 pr-4 py-4", footer != null && "border-b border-border-subtle", bodyClassName), children }),
1274
+ footer != null && /* @__PURE__ */ jsx24("div", { className: "h-12 flex items-center justify-end gap-2 pl-5 pr-4 shrink-0", children: footer })
1236
1275
  ]
1237
1276
  }
1238
1277
  ) })
@@ -1242,7 +1281,7 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
1242
1281
  }
1243
1282
 
1244
1283
  // src/ConfirmDialog.tsx
1245
- import { Fragment as Fragment3, jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
1284
+ import { Fragment as Fragment3, jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
1246
1285
  function ConfirmDialog({ title, children, confirmLabel, destructive = false, onConfirm, onClose }) {
1247
1286
  const [busy, setBusy] = useState3(false);
1248
1287
  const confirm = async () => {
@@ -1254,16 +1293,16 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
1254
1293
  setBusy(false);
1255
1294
  }
1256
1295
  };
1257
- return /* @__PURE__ */ jsx24(
1296
+ return /* @__PURE__ */ jsx25(
1258
1297
  DialogShell,
1259
1298
  {
1260
1299
  alert: true,
1261
1300
  title,
1262
1301
  onClose,
1263
1302
  bodyClassName: "flex flex-col gap-3 text-body-2 text-text-primary",
1264
- footer: /* @__PURE__ */ jsxs15(Fragment3, { children: [
1265
- /* @__PURE__ */ jsx24(Button, { variant: "muted", onClick: onClose, disabled: busy, children: "Cancel" }),
1266
- /* @__PURE__ */ jsx24(Button, { variant: destructive ? "destructive" : "primary", onClick: () => void confirm(), disabled: busy, children: confirmLabel })
1303
+ footer: /* @__PURE__ */ jsxs17(Fragment3, { children: [
1304
+ /* @__PURE__ */ jsx25(Button, { variant: "muted", onClick: onClose, disabled: busy, children: "Cancel" }),
1305
+ /* @__PURE__ */ jsx25(Button, { variant: destructive ? "destructive" : "primary", onClick: () => void confirm(), disabled: busy, children: confirmLabel })
1267
1306
  ] }),
1268
1307
  children
1269
1308
  }
@@ -1274,7 +1313,7 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
1274
1313
  import { useEffect as useEffect2, useRef as useRef4, useState as useState4 } from "react";
1275
1314
  import { Field as BaseField3 } from "@base-ui/react/field";
1276
1315
  import { Input as Input2 } from "@base-ui/react/input";
1277
- import { jsx as jsx25 } from "react/jsx-runtime";
1316
+ import { jsx as jsx26 } from "react/jsx-runtime";
1278
1317
  function EditableText({ value, display, displayNode, placeholder, onCommit, multiline = false, className, label, readOnly = false }) {
1279
1318
  const [editing, setEditing] = useState4(false);
1280
1319
  const [draft, setDraft] = useState4(value);
@@ -1332,7 +1371,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
1332
1371
  written and never read. Read-only, this is a line of text: whatever
1333
1372
  names the region around it (a `Field`, a `Property`) names this too.
1334
1373
  */
1335
- /* @__PURE__ */ jsx25(
1374
+ /* @__PURE__ */ jsx26(
1336
1375
  "div",
1337
1376
  {
1338
1377
  className: cn("w-full px-2 py-1", multiline && !displayNode && "whitespace-pre-wrap", display ?? value ? "text-text-primary" : "text-text-muted", className),
@@ -1342,11 +1381,11 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
1342
1381
  );
1343
1382
  }
1344
1383
  if (editing) {
1345
- return multiline ? /* @__PURE__ */ jsx25(
1384
+ return multiline ? /* @__PURE__ */ jsx26(
1346
1385
  BaseField3.Control,
1347
1386
  {
1348
1387
  ref: fieldRef,
1349
- render: /* @__PURE__ */ jsx25("textarea", { rows: 4 }),
1388
+ render: /* @__PURE__ */ jsx26("textarea", { rows: 4 }),
1350
1389
  "aria-label": label,
1351
1390
  value: draft,
1352
1391
  disabled: busy,
@@ -1355,7 +1394,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
1355
1394
  onBlur: () => void commit(),
1356
1395
  className: fieldClass
1357
1396
  }
1358
- ) : /* @__PURE__ */ jsx25(
1397
+ ) : /* @__PURE__ */ jsx26(
1359
1398
  Input2,
1360
1399
  {
1361
1400
  ref: fieldRef,
@@ -1369,7 +1408,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
1369
1408
  }
1370
1409
  );
1371
1410
  }
1372
- return /* @__PURE__ */ jsx25(
1411
+ return /* @__PURE__ */ jsx26(
1373
1412
  "button",
1374
1413
  {
1375
1414
  type: "button",
@@ -1388,33 +1427,33 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
1388
1427
 
1389
1428
  // src/EmptyState.tsx
1390
1429
  import { IconMessage2 } from "@tabler/icons-react";
1391
- import { jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
1430
+ import { jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
1392
1431
  function EmptyState({ icon, message, className }) {
1393
- return /* @__PURE__ */ jsxs16("div", { className: cn("flex flex-col gap-2 items-center", className), children: [
1394
- /* @__PURE__ */ jsx26("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx26(IconMessage2, { size: 16, stroke: 1.5 }) }),
1395
- /* @__PURE__ */ jsx26("p", { className: "text-body-2 text-text-secondary text-center", children: message })
1432
+ return /* @__PURE__ */ jsxs18("div", { className: cn("flex flex-col gap-2 items-center", className), children: [
1433
+ /* @__PURE__ */ jsx27("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx27(IconMessage2, { size: 16, stroke: 1.5 }) }),
1434
+ /* @__PURE__ */ jsx27("p", { className: "text-body-2 text-text-secondary text-center", children: message })
1396
1435
  ] });
1397
1436
  }
1398
1437
 
1399
1438
  // src/Skeleton.tsx
1400
- import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
1439
+ import { jsx as jsx28, jsxs as jsxs19 } from "react/jsx-runtime";
1401
1440
  function SkeletonBar({ className, style }) {
1402
- return /* @__PURE__ */ jsx27("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
1441
+ return /* @__PURE__ */ jsx28("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
1403
1442
  }
1404
1443
  var ROW_BAR_WIDTHS = [150, 100, 170, 120, 90, 140, 110, 160];
1405
1444
  function SkeletonRow({ barWidth = 130 }) {
1406
- return /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2 px-2 h-[32px] rounded-lg", children: [
1407
- /* @__PURE__ */ jsx27(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
1408
- /* @__PURE__ */ jsx27(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
1445
+ return /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2 px-2 h-[32px] rounded-lg", children: [
1446
+ /* @__PURE__ */ jsx28(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
1447
+ /* @__PURE__ */ jsx28(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
1409
1448
  ] });
1410
1449
  }
1411
1450
  function SkeletonList({ rows = 8, className }) {
1412
- return /* @__PURE__ */ jsx27("div", { className: cn("flex flex-col gap-0.5 animate-skeleton-in", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx27(SkeletonRow, { barWidth: ROW_BAR_WIDTHS[i % ROW_BAR_WIDTHS.length] }, i)) });
1451
+ 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)) });
1413
1452
  }
1414
1453
 
1415
1454
  // src/Breadcrumb.tsx
1416
1455
  import { Fragment as Fragment4, useCallback as useCallback2, useLayoutEffect as useLayoutEffect2, useRef as useRef5, useState as useState5 } from "react";
1417
- import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
1456
+ import { jsx as jsx29, jsxs as jsxs20 } from "react/jsx-runtime";
1418
1457
  function Breadcrumb({ items, className }) {
1419
1458
  const navRef = useRef5(null);
1420
1459
  const labelRefs = useRef5([]);
@@ -1434,7 +1473,7 @@ function Breadcrumb({ items, className }) {
1434
1473
  observer.observe(nav);
1435
1474
  return () => observer.disconnect();
1436
1475
  }, [measure, items]);
1437
- return /* @__PURE__ */ jsx28("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) => {
1476
+ 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) => {
1438
1477
  const last = index === items.length - 1;
1439
1478
  const text = cn(
1440
1479
  "truncate",
@@ -1447,23 +1486,23 @@ function Breadcrumb({ items, className }) {
1447
1486
  const setLabelRef = (el) => {
1448
1487
  labelRefs.current[index] = el;
1449
1488
  };
1450
- const crumb = item.href ? /* @__PURE__ */ jsx28("a", { ref: setLabelRef, href: item.href, onClick: item.onClick, className: cn(text, "hover:text-text-primary"), children: item.label }) : /* @__PURE__ */ jsx28("span", { ref: setLabelRef, className: text, "aria-current": last ? "page" : void 0, children: item.label });
1451
- return /* @__PURE__ */ jsxs18(Fragment4, { children: [
1452
- index > 0 && /* @__PURE__ */ jsx28("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
1489
+ 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 });
1490
+ return /* @__PURE__ */ jsxs20(Fragment4, { children: [
1491
+ index > 0 && /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
1453
1492
  truncated.has(index) ? (
1454
1493
  // `min-w-0 shrink` undoes the wrapper's own shrink-0 — the crumb
1455
1494
  // must keep truncating inside it, or wrapping it would widen the
1456
1495
  // trail and the tooltip would never be needed again.
1457
- /* @__PURE__ */ jsx28(WithTooltip, { label: item.label, wrapperClassName: "min-w-0 shrink", children: crumb })
1496
+ /* @__PURE__ */ jsx29(WithTooltip, { label: item.label, wrapperClassName: "min-w-0 shrink", children: crumb })
1458
1497
  ) : crumb
1459
1498
  ] }, `${item.label}-${index}`);
1460
1499
  }) });
1461
1500
  }
1462
1501
 
1463
1502
  // src/NavItem.tsx
1464
- import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
1503
+ import { jsx as jsx30, jsxs as jsxs21 } from "react/jsx-runtime";
1465
1504
  function NavItem({ label, href, count, countLabel, active = false, icon, className, ...props }) {
1466
- return /* @__PURE__ */ jsxs19(
1505
+ return /* @__PURE__ */ jsxs21(
1467
1506
  "a",
1468
1507
  {
1469
1508
  href,
@@ -1478,9 +1517,9 @@ function NavItem({ label, href, count, countLabel, active = false, icon, classNa
1478
1517
  ),
1479
1518
  ...props,
1480
1519
  children: [
1481
- icon && /* @__PURE__ */ jsx29("span", { className: "flex shrink-0 items-center", children: icon }),
1482
- /* @__PURE__ */ jsx29("span", { className: "flex-1 truncate", children: label }),
1483
- count ? /* @__PURE__ */ jsx29(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx29("span", { className: "shrink-0 font-mono text-caption tabular-nums text-text-muted", children: count }) }) : null
1520
+ icon && /* @__PURE__ */ jsx30("span", { className: "flex shrink-0 items-center", children: icon }),
1521
+ /* @__PURE__ */ jsx30("span", { className: "flex-1 truncate", children: label }),
1522
+ count ? /* @__PURE__ */ jsx30(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx30("span", { className: "shrink-0 font-mono text-caption tabular-nums text-text-muted", children: count }) }) : null
1484
1523
  ]
1485
1524
  }
1486
1525
  );
@@ -1489,7 +1528,7 @@ function NavItem({ label, href, count, countLabel, active = false, icon, classNa
1489
1528
  // src/Popover.tsx
1490
1529
  import { useMemo as useMemo2 } from "react";
1491
1530
  import { Popover as BasePopover } from "@base-ui/react/popover";
1492
- import { jsx as jsx30, jsxs as jsxs20 } from "react/jsx-runtime";
1531
+ import { jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
1493
1532
  var GAP5 = 4;
1494
1533
  var VIEWPORT_PAD4 = 8;
1495
1534
  function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpenChange, finalFocus, actionsRef, ariaLabel, children, className }) {
@@ -1498,7 +1537,7 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
1498
1537
  if (anchor instanceof Element) return anchor;
1499
1538
  return { getBoundingClientRect: () => anchor };
1500
1539
  }, [anchor]);
1501
- return /* @__PURE__ */ jsxs20(
1540
+ return /* @__PURE__ */ jsxs22(
1502
1541
  BasePopover.Root,
1503
1542
  {
1504
1543
  open,
@@ -1506,8 +1545,8 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
1506
1545
  actionsRef,
1507
1546
  modal: false,
1508
1547
  children: [
1509
- trigger && /* @__PURE__ */ jsx30(BasePopover.Trigger, { render: trigger }),
1510
- /* @__PURE__ */ jsx30(BasePopover.Portal, { children: /* @__PURE__ */ jsx30(
1548
+ trigger && /* @__PURE__ */ jsx31(BasePopover.Trigger, { render: trigger, disabled: triggerDisabled(trigger) }),
1549
+ /* @__PURE__ */ jsx31(BasePopover.Portal, { children: /* @__PURE__ */ jsx31(
1511
1550
  BasePopover.Positioner,
1512
1551
  {
1513
1552
  anchor: anchorTarget,
@@ -1516,15 +1555,15 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
1516
1555
  sideOffset: GAP5,
1517
1556
  collisionPadding: VIEWPORT_PAD4,
1518
1557
  className: "z-50 data-[anchor-hidden]:hidden",
1519
- children: /* @__PURE__ */ jsx30(
1558
+ children: /* @__PURE__ */ jsx31(
1520
1559
  BasePopover.Popup,
1521
1560
  {
1522
1561
  "aria-label": ariaLabel,
1523
1562
  initialFocus: trigger ? void 0 : false,
1524
1563
  finalFocus,
1525
- className: cn("min-w-[180px] max-h-[var(--available-height)] overflow-y-auto outline-none", className),
1526
- render: /* @__PURE__ */ jsx30(MenuPanel, {}),
1527
- children
1564
+ className: cn("min-w-[180px] outline-none", className),
1565
+ render: /* @__PURE__ */ jsx31(MenuPanel, {}),
1566
+ children: /* @__PURE__ */ jsx31(ScrollArea, { viewportClassName: "max-h-[calc(var(--available-height)_-_1rem)]", contentClassName: "flex flex-col [&>[role=separator]]:mx-0", children })
1528
1567
  }
1529
1568
  )
1530
1569
  }
@@ -1536,9 +1575,9 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
1536
1575
 
1537
1576
  // src/Toolbar.tsx
1538
1577
  import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar";
1539
- import { jsx as jsx31 } from "react/jsx-runtime";
1578
+ import { jsx as jsx32 } from "react/jsx-runtime";
1540
1579
  function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocus = true, surface = true, children, className }) {
1541
- const strip = /* @__PURE__ */ jsx31(
1580
+ const strip = /* @__PURE__ */ jsx32(
1542
1581
  BaseToolbar.Root,
1543
1582
  {
1544
1583
  "aria-label": ariaLabel,
@@ -1549,24 +1588,24 @@ function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocu
1549
1588
  }
1550
1589
  );
1551
1590
  if (!surface) return strip;
1552
- return /* @__PURE__ */ jsx31(MenuPanel, { className: "w-fit p-1", children: strip });
1591
+ return /* @__PURE__ */ jsx32(MenuPanel, { className: "w-fit p-1", children: strip });
1553
1592
  }
1554
1593
  function ToolbarButton({ ref, disabled, disabledReason, ...props }) {
1555
- return /* @__PURE__ */ jsx31(
1594
+ return /* @__PURE__ */ jsx32(
1556
1595
  BaseToolbar.Button,
1557
1596
  {
1558
1597
  ref,
1559
1598
  disabled: disabled || !!disabledReason,
1560
1599
  focusableWhenDisabled: true,
1561
- render: /* @__PURE__ */ jsx31(IconButton, { disabled, disabledReason, ...props })
1600
+ render: /* @__PURE__ */ jsx32(IconButton, { disabled, disabledReason, ...props })
1562
1601
  }
1563
1602
  );
1564
1603
  }
1565
1604
  function ToolbarInput(props) {
1566
- return /* @__PURE__ */ jsx31(BaseToolbar.Input, { render: /* @__PURE__ */ jsx31(TextInput, {}), ...props });
1605
+ return /* @__PURE__ */ jsx32(BaseToolbar.Input, { render: /* @__PURE__ */ jsx32(TextInput, {}), ...props });
1567
1606
  }
1568
1607
  function ToolbarSeparator({ className }) {
1569
- return /* @__PURE__ */ jsx31(
1608
+ return /* @__PURE__ */ jsx32(
1570
1609
  BaseToolbar.Separator,
1571
1610
  {
1572
1611
  orientation: "vertical",
@@ -1576,9 +1615,9 @@ function ToolbarSeparator({ className }) {
1576
1615
  }
1577
1616
 
1578
1617
  // src/ReactionPicker.tsx
1579
- import { jsx as jsx32 } from "react/jsx-runtime";
1618
+ import { jsx as jsx33 } from "react/jsx-runtime";
1580
1619
  function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reactions", surface = true, className }) {
1581
- return /* @__PURE__ */ jsx32(Toolbar, { "aria-label": ariaLabel, surface, className: cn("gap-0.5", className), children: options.map((option) => (
1620
+ return /* @__PURE__ */ jsx33(Toolbar, { "aria-label": ariaLabel, surface, className: cn("gap-0.5", className), children: options.map((option) => (
1582
1621
  /*
1583
1622
  A `ToolbarButton`, not a button in a tooltip wrapper. The wrapper
1584
1623
  would become the toolbar's item and the button inside it would never
@@ -1588,14 +1627,14 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
1588
1627
  The tooltip names it for a pointer, `aria-label` for everything else,
1589
1628
  and both say the meaning rather than the glyph.
1590
1629
  */
1591
- /* @__PURE__ */ jsx32(
1630
+ /* @__PURE__ */ jsx33(
1592
1631
  ToolbarButton,
1593
1632
  {
1594
1633
  "aria-label": option.label,
1595
1634
  tooltip: option.label,
1596
1635
  onClick: () => onSelect(option.emoji),
1597
1636
  className: "size-7 text-[18px] leading-none",
1598
- children: /* @__PURE__ */ jsx32("span", { "aria-hidden": "true", children: option.emoji })
1637
+ children: /* @__PURE__ */ jsx33("span", { "aria-hidden": "true", children: option.emoji })
1599
1638
  },
1600
1639
  option.emoji
1601
1640
  )
@@ -1604,23 +1643,23 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
1604
1643
 
1605
1644
  // src/PreviewCard.tsx
1606
1645
  import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card";
1607
- import { jsx as jsx33, jsxs as jsxs21 } from "react/jsx-runtime";
1646
+ import { jsx as jsx34, jsxs as jsxs23 } from "react/jsx-runtime";
1608
1647
  var GAP6 = 12;
1609
1648
  var VIEWPORT_PAD5 = 8;
1610
1649
  var OPEN_DELAY2 = 350;
1611
1650
  var CLOSE_DELAY = 200;
1612
1651
  function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, closeDelay = CLOSE_DELAY, className, wrapperClassName }) {
1613
- return /* @__PURE__ */ jsxs21(BasePreviewCard.Root, { children: [
1614
- /* @__PURE__ */ jsx33(
1652
+ return /* @__PURE__ */ jsxs23(BasePreviewCard.Root, { children: [
1653
+ /* @__PURE__ */ jsx34(
1615
1654
  BasePreviewCard.Trigger,
1616
1655
  {
1617
1656
  delay,
1618
1657
  closeDelay,
1619
- render: /* @__PURE__ */ jsx33("span", { className: cn("inline-flex", wrapperClassName) }),
1658
+ render: /* @__PURE__ */ jsx34("span", { className: cn("inline-flex", wrapperClassName) }),
1620
1659
  children
1621
1660
  }
1622
1661
  ),
1623
- /* @__PURE__ */ jsx33(BasePreviewCard.Portal, { children: /* @__PURE__ */ jsx33(
1662
+ /* @__PURE__ */ jsx34(BasePreviewCard.Portal, { children: /* @__PURE__ */ jsx34(
1624
1663
  BasePreviewCard.Positioner,
1625
1664
  {
1626
1665
  side,
@@ -1628,12 +1667,12 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
1628
1667
  sideOffset: GAP6,
1629
1668
  collisionPadding: VIEWPORT_PAD5,
1630
1669
  className: "z-50 data-[anchor-hidden]:hidden",
1631
- children: /* @__PURE__ */ jsx33(
1670
+ children: /* @__PURE__ */ jsx34(
1632
1671
  BasePreviewCard.Popup,
1633
1672
  {
1634
- className: cn("w-[360px] max-h-[min(300px,var(--available-height))] gap-3 overflow-y-auto p-3 outline-none [&>*]:shrink-0", className),
1635
- render: /* @__PURE__ */ jsx33(MenuPanel, {}),
1636
- children: content
1673
+ className: cn("w-[360px] p-3 outline-none", className),
1674
+ render: /* @__PURE__ */ jsx34(MenuPanel, {}),
1675
+ 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 })
1637
1676
  }
1638
1677
  )
1639
1678
  }
@@ -1642,15 +1681,15 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
1642
1681
  }
1643
1682
 
1644
1683
  // src/Rail.tsx
1645
- import { jsx as jsx34 } from "react/jsx-runtime";
1684
+ import { jsx as jsx35 } from "react/jsx-runtime";
1646
1685
  function Rail({ "aria-label": ariaLabel = "Navigation", children, className }) {
1647
- return /* @__PURE__ */ jsx34("nav", { "aria-label": ariaLabel, className: cn("flex w-16 shrink-0 flex-col items-start gap-2 px-2 py-3", className), children });
1686
+ 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 });
1648
1687
  }
1649
1688
 
1650
1689
  // src/RailItem.tsx
1651
- import { jsx as jsx35, jsxs as jsxs22 } from "react/jsx-runtime";
1690
+ import { jsx as jsx36, jsxs as jsxs24 } from "react/jsx-runtime";
1652
1691
  function RailItem({ href, icon, label, active = false, className, ...props }) {
1653
- return /* @__PURE__ */ jsxs22(
1692
+ return /* @__PURE__ */ jsxs24(
1654
1693
  "a",
1655
1694
  {
1656
1695
  href,
@@ -1658,14 +1697,14 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
1658
1697
  className: cn("group flex w-full shrink-0 flex-col items-center gap-0.5 px-2 py-0.5", className),
1659
1698
  ...props,
1660
1699
  children: [
1661
- /* @__PURE__ */ jsx35(
1700
+ /* @__PURE__ */ jsx36(
1662
1701
  "div",
1663
1702
  {
1664
1703
  className: cn(
1665
1704
  "flex items-center justify-center rounded-lg p-2 transition-colors",
1666
1705
  active ? "bg-bg-selected" : "group-hover:bg-bg-hover"
1667
1706
  ),
1668
- children: /* @__PURE__ */ jsx35(
1707
+ children: /* @__PURE__ */ jsx36(
1669
1708
  "span",
1670
1709
  {
1671
1710
  className: cn(
@@ -1677,52 +1716,49 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
1677
1716
  )
1678
1717
  }
1679
1718
  ),
1680
- /* @__PURE__ */ jsx35("span", { className: cn("text-center text-[9px] font-medium leading-[115%]", active ? "text-text-primary" : "text-text-secondary"), children: label })
1719
+ /* @__PURE__ */ jsx36("span", { className: cn("text-center text-[9px] font-medium leading-[115%]", active ? "text-text-primary" : "text-text-secondary"), children: label })
1681
1720
  ]
1682
1721
  }
1683
1722
  );
1684
1723
  }
1685
1724
 
1686
1725
  // src/Sidebar.tsx
1687
- import { jsx as jsx36 } from "react/jsx-runtime";
1726
+ import { jsx as jsx37 } from "react/jsx-runtime";
1688
1727
  function Sidebar({ "aria-label": ariaLabel = "Workspace", children, className }) {
1689
- return /* @__PURE__ */ jsx36(
1728
+ return /* @__PURE__ */ jsx37(
1690
1729
  "nav",
1691
1730
  {
1692
1731
  "aria-label": ariaLabel,
1693
- className: cn(
1694
- "flex w-60 shrink-0 flex-col gap-px overflow-y-auto border-r border-border-default bg-bg-surface px-2.5 py-3",
1695
- className
1696
- ),
1697
- children
1732
+ className: cn("flex w-60 shrink-0 flex-col border-r border-border-default bg-bg-surface", className),
1733
+ children: /* @__PURE__ */ jsx37(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex flex-col gap-px px-2.5 py-3", children })
1698
1734
  }
1699
1735
  );
1700
1736
  }
1701
1737
 
1702
1738
  // src/Property.tsx
1703
- import { jsx as jsx37, jsxs as jsxs23 } from "react/jsx-runtime";
1739
+ import { jsx as jsx38, jsxs as jsxs25 } from "react/jsx-runtime";
1704
1740
  function Property({ label, layout = "row", children, className }) {
1705
1741
  if (layout === "stacked") {
1706
1742
  return (
1707
1743
  // gap-3 — the one label-above-content distance (Katerina, 2026-09-01):
1708
1744
  // Peek's topic-details sections already sit at 12px, Ship's rail was
1709
1745
  // 6px, and unifying means the bigger, calmer one.
1710
- /* @__PURE__ */ jsxs23("div", { className: cn("flex flex-col gap-3", className), children: [
1711
- /* @__PURE__ */ jsx37("span", { className: "text-menu uppercase tracking-[0.08em] text-text-secondary", children: label }),
1746
+ /* @__PURE__ */ jsxs25("div", { className: cn("flex flex-col gap-3", className), children: [
1747
+ /* @__PURE__ */ jsx38("span", { className: "text-menu uppercase tracking-[0.08em] text-text-secondary", children: label }),
1712
1748
  children
1713
1749
  ] })
1714
1750
  );
1715
1751
  }
1716
- return /* @__PURE__ */ jsxs23("div", { className: cn("flex items-center gap-2", className), children: [
1717
- /* @__PURE__ */ jsx37("span", { className: "w-[68px] shrink-0 text-caption text-text-secondary", children: label }),
1752
+ return /* @__PURE__ */ jsxs25("div", { className: cn("flex items-center gap-2", className), children: [
1753
+ /* @__PURE__ */ jsx38("span", { className: "w-[68px] shrink-0 text-caption text-text-secondary", children: label }),
1718
1754
  children
1719
1755
  ] });
1720
1756
  }
1721
1757
 
1722
1758
  // src/Reaction.tsx
1723
- import { jsx as jsx38, jsxs as jsxs24 } from "react/jsx-runtime";
1759
+ import { jsx as jsx39, jsxs as jsxs26 } from "react/jsx-runtime";
1724
1760
  function Reaction({ emoji, count, pressed = false, className, type, ...props }) {
1725
- return /* @__PURE__ */ jsxs24(
1761
+ return /* @__PURE__ */ jsxs26(
1726
1762
  "button",
1727
1763
  {
1728
1764
  type: type ?? "button",
@@ -1733,13 +1769,20 @@ function Reaction({ emoji, count, pressed = false, className, type, ...props })
1733
1769
  "inline-flex h-6 items-center justify-center gap-1.5 rounded-full px-2",
1734
1770
  "border transition-colors",
1735
1771
  "disabled:cursor-not-allowed disabled:opacity-50",
1736
- pressed ? "border-accent-primary bg-accent-muted text-accent-primary hover:border-accent-hover" : "border-border-default bg-bg-inset text-text-primary hover:border-border-strong hover:bg-bg-hover",
1772
+ pressed ? (
1773
+ /* In the ship theme the accent on its own wash measures 2.70:1
1774
+ (Finding 4), and the count was the thing that vanished
1775
+ (Katerina, 2026-09-08). The number reads in the text colour
1776
+ there; the accent keeps the edge and the fill. Signal keeps
1777
+ Peek's blue-on-wash, which reads. */
1778
+ "border-accent-primary bg-accent-muted text-accent-primary hover:border-accent-hover ship:text-text-primary"
1779
+ ) : "border-border-default bg-bg-inset text-text-primary hover:border-border-strong hover:bg-bg-hover",
1737
1780
  className
1738
1781
  ),
1739
1782
  ...props,
1740
1783
  children: [
1741
- /* @__PURE__ */ jsx38("span", { "aria-hidden": "true", className: "shrink-0 text-[16px] leading-none", children: emoji }),
1742
- /* @__PURE__ */ jsx38("span", { className: "text-chip signal:font-mono signal:text-[10px] signal:font-semibold signal:tabular-nums", children: count })
1784
+ /* @__PURE__ */ jsx39("span", { "aria-hidden": "true", className: "shrink-0 text-[16px] leading-none", children: emoji }),
1785
+ /* @__PURE__ */ jsx39("span", { className: "text-chip signal:font-mono signal:text-[10px] signal:font-semibold signal:tabular-nums", children: count })
1743
1786
  ]
1744
1787
  }
1745
1788
  );
@@ -1748,9 +1791,9 @@ function Reaction({ emoji, count, pressed = false, className, type, ...props })
1748
1791
  // src/SearchInput.tsx
1749
1792
  import "react";
1750
1793
  import { Input as Input3 } from "@base-ui/react/input";
1751
- import { jsx as jsx39, jsxs as jsxs25 } from "react/jsx-runtime";
1794
+ import { jsx as jsx40, jsxs as jsxs27 } from "react/jsx-runtime";
1752
1795
  function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...props }) {
1753
- return /* @__PURE__ */ jsxs25(
1796
+ return /* @__PURE__ */ jsxs27(
1754
1797
  "div",
1755
1798
  {
1756
1799
  className: cn(
@@ -1760,7 +1803,7 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
1760
1803
  className
1761
1804
  ),
1762
1805
  children: [
1763
- /* @__PURE__ */ jsx39(
1806
+ /* @__PURE__ */ jsx40(
1764
1807
  Input3,
1765
1808
  {
1766
1809
  className: "flex-1 min-w-0 bg-transparent text-input-value text-text-primary placeholder:text-text-muted outline-none",
@@ -1768,7 +1811,7 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
1768
1811
  ...props
1769
1812
  }
1770
1813
  ),
1771
- shortcut && /* @__PURE__ */ jsx39(Kbd, { children: shortcut })
1814
+ shortcut && /* @__PURE__ */ jsx40(Kbd, { children: shortcut })
1772
1815
  ]
1773
1816
  }
1774
1817
  );
@@ -1777,10 +1820,10 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
1777
1820
  // src/SectionHeader.tsx
1778
1821
  import { useState as useState6 } from "react";
1779
1822
  import { IconChevronRight as IconChevronRight2 } from "@tabler/icons-react";
1780
- import { jsx as jsx40, jsxs as jsxs26 } from "react/jsx-runtime";
1823
+ import { jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
1781
1824
  function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, actions, showActions = "hover", className }) {
1782
1825
  const [isHovered, setIsHovered] = useState6(false);
1783
- return /* @__PURE__ */ jsxs26(
1826
+ return /* @__PURE__ */ jsxs28(
1784
1827
  "div",
1785
1828
  {
1786
1829
  className: cn(
@@ -1793,8 +1836,8 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, ac
1793
1836
  onMouseEnter: () => setIsHovered(true),
1794
1837
  onMouseLeave: () => setIsHovered(false),
1795
1838
  children: [
1796
- /* @__PURE__ */ jsxs26("div", { className: "flex shrink-0 items-center gap-1", children: [
1797
- chevron && /* @__PURE__ */ jsx40(
1839
+ /* @__PURE__ */ jsxs28("div", { className: "flex shrink-0 items-center gap-1", children: [
1840
+ chevron && /* @__PURE__ */ jsx41(
1798
1841
  IconChevronRight2,
1799
1842
  {
1800
1843
  size: 12,
@@ -1802,9 +1845,9 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, ac
1802
1845
  className: cn("text-text-secondary transition-transform duration-150", isExpanded && "rotate-90")
1803
1846
  }
1804
1847
  ),
1805
- /* @__PURE__ */ jsx40(SectionLabel, { children: title })
1848
+ /* @__PURE__ */ jsx41(SectionLabel, { children: title })
1806
1849
  ] }),
1807
- (showActions === "always" || isHovered) && actions && actions.length > 0 && /* @__PURE__ */ jsx40("div", { className: "flex items-center gap-1", children: actions.map((action) => /* @__PURE__ */ jsx40(
1850
+ (showActions === "always" || isHovered) && actions && actions.length > 0 && /* @__PURE__ */ jsx41("div", { className: "flex items-center gap-1", children: actions.map((action) => /* @__PURE__ */ jsx41(
1808
1851
  IconButton,
1809
1852
  {
1810
1853
  tooltip: action.tooltip,
@@ -1824,9 +1867,9 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, ac
1824
1867
 
1825
1868
  // src/Tabs.tsx
1826
1869
  import { Tabs as BaseTabs } from "@base-ui/react/tabs";
1827
- import { jsx as jsx41, jsxs as jsxs27 } from "react/jsx-runtime";
1870
+ import { jsx as jsx42, jsxs as jsxs29 } from "react/jsx-runtime";
1828
1871
  function Tabs({ tabs, active, onChange, size = "default", className, ...aria }) {
1829
- return /* @__PURE__ */ jsx41(
1872
+ return /* @__PURE__ */ jsx42(
1830
1873
  BaseTabs.Root,
1831
1874
  {
1832
1875
  value: active,
@@ -1834,14 +1877,14 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
1834
1877
  if (details.reason === "none") onChange(value);
1835
1878
  },
1836
1879
  className,
1837
- children: /* @__PURE__ */ jsx41(
1880
+ children: /* @__PURE__ */ jsx42(
1838
1881
  BaseTabs.List,
1839
1882
  {
1840
1883
  activateOnFocus: true,
1841
1884
  "aria-label": aria["aria-label"],
1842
1885
  "aria-labelledby": aria["aria-labelledby"],
1843
1886
  className: "flex items-center gap-2",
1844
- children: tabs.map((tab) => /* @__PURE__ */ jsxs27(
1887
+ children: tabs.map((tab) => /* @__PURE__ */ jsxs29(
1845
1888
  BaseTabs.Tab,
1846
1889
  {
1847
1890
  value: tab.id,
@@ -1854,9 +1897,9 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
1854
1897
  ),
1855
1898
  children: [
1856
1899
  tab.icon,
1857
- /* @__PURE__ */ jsxs27("span", { className: "flex items-baseline", children: [
1900
+ /* @__PURE__ */ jsxs29("span", { className: "flex items-baseline", children: [
1858
1901
  tab.label,
1859
- tab.count !== void 0 ? /* @__PURE__ */ jsx41("span", { className: "ml-2.5 font-mono text-caption tabular-nums text-text-secondary", children: tab.count }) : null
1902
+ tab.count !== void 0 ? /* @__PURE__ */ jsx42("span", { className: "ml-2.5 font-mono text-caption tabular-nums text-text-secondary", children: tab.count }) : null
1860
1903
  ] })
1861
1904
  ]
1862
1905
  },
@@ -1872,7 +1915,7 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
1872
1915
  import { createContext as createContext2, useCallback as useCallback3, useContext as useContext2, useEffect as useEffect3, useMemo as useMemo3, useState as useState7 } from "react";
1873
1916
  import { createPortal as createPortal2 } from "react-dom";
1874
1917
  import { IconCircleCheck } from "@tabler/icons-react";
1875
- import { jsx as jsx42, jsxs as jsxs28 } from "react/jsx-runtime";
1918
+ import { jsx as jsx43, jsxs as jsxs30 } from "react/jsx-runtime";
1876
1919
  var SURFACE_STYLES = {
1877
1920
  success: "bg-success-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-[shadow:var(--shadow-md)]",
1878
1921
  brand: "bg-accent-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-[shadow:var(--shadow-md)]",
@@ -1890,7 +1933,7 @@ var ACTION_BORDER_STYLES = {
1890
1933
  };
1891
1934
  function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAction, className }) {
1892
1935
  const hasAction = !!(actionLabel && onAction);
1893
- return /* @__PURE__ */ jsxs28(
1936
+ return /* @__PURE__ */ jsxs30(
1894
1937
  "div",
1895
1938
  {
1896
1939
  className: cn(
@@ -1902,11 +1945,11 @@ function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAct
1902
1945
  className
1903
1946
  ),
1904
1947
  children: [
1905
- /* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-2 shrink-0", children: [
1906
- leadingIcon && /* @__PURE__ */ jsx42(IconCircleCheck, { size: 16, stroke: 1.5, className: cn("text-text-primary shrink-0", ICON_STYLES[type]) }),
1907
- /* @__PURE__ */ jsx42("span", { className: "font-normal text-[14px] leading-[1.4] text-text-primary whitespace-nowrap", children: label })
1948
+ /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2 shrink-0", children: [
1949
+ leadingIcon && /* @__PURE__ */ jsx43(IconCircleCheck, { size: 16, stroke: 1.5, className: cn("text-text-primary shrink-0", ICON_STYLES[type]) }),
1950
+ /* @__PURE__ */ jsx43("span", { className: "font-normal text-[14px] leading-[1.4] text-text-primary whitespace-nowrap", children: label })
1908
1951
  ] }),
1909
- hasAction && /* @__PURE__ */ jsx42(
1952
+ hasAction && /* @__PURE__ */ jsx43(
1910
1953
  "button",
1911
1954
  {
1912
1955
  type: "button",
@@ -1916,7 +1959,7 @@ function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAct
1916
1959
  ACTION_BORDER_STYLES[type],
1917
1960
  type === "neutral" ? "hover:border-border-strong" : "hover:opacity-80"
1918
1961
  ),
1919
- children: /* @__PURE__ */ jsx42("span", { className: "font-medium text-[12px] leading-[12px] text-text-primary whitespace-nowrap", children: actionLabel })
1962
+ children: /* @__PURE__ */ jsx43("span", { className: "font-medium text-[12px] leading-[12px] text-text-primary whitespace-nowrap", children: actionLabel })
1920
1963
  }
1921
1964
  )
1922
1965
  ]
@@ -1943,10 +1986,10 @@ function ToastProvider({ children }) {
1943
1986
  return () => clearTimeout(timer);
1944
1987
  }, [toast]);
1945
1988
  const value = useMemo3(() => ({ showToast, dismissToast }), [showToast, dismissToast]);
1946
- return /* @__PURE__ */ jsxs28(ToastContext.Provider, { value, children: [
1989
+ return /* @__PURE__ */ jsxs30(ToastContext.Provider, { value, children: [
1947
1990
  children,
1948
1991
  toast && createPortal2(
1949
- /* @__PURE__ */ jsx42("div", { className: "fixed bottom-4 left-4 z-[100] pointer-events-none", children: /* @__PURE__ */ jsx42(
1992
+ /* @__PURE__ */ jsx43("div", { className: "fixed bottom-4 left-4 z-[100] pointer-events-none", children: /* @__PURE__ */ jsx43(
1950
1993
  Toast,
1951
1994
  {
1952
1995
  className: "pointer-events-auto",
@@ -2007,6 +2050,7 @@ export {
2007
2050
  RailItem,
2008
2051
  Reaction,
2009
2052
  ReactionPicker,
2053
+ ScrollArea,
2010
2054
  SearchInput,
2011
2055
  SectionHeader,
2012
2056
  SectionLabel,