@estiva-app/ui 0.19.0 → 0.20.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.
Files changed (69) hide show
  1. package/dist/AttachmentCard.d.ts.map +1 -1
  2. package/dist/Breadcrumb.d.ts.map +1 -1
  3. package/dist/Button.d.ts +6 -1
  4. package/dist/Button.d.ts.map +1 -1
  5. package/dist/Card.d.ts +6 -1
  6. package/dist/Card.d.ts.map +1 -1
  7. package/dist/DialogShell.d.ts.map +1 -1
  8. package/dist/Divider.d.ts +7 -0
  9. package/dist/Divider.d.ts.map +1 -1
  10. package/dist/IconButton.d.ts +12 -2
  11. package/dist/IconButton.d.ts.map +1 -1
  12. package/dist/IdentityMenu.d.ts.map +1 -1
  13. package/dist/Link.d.ts +6 -1
  14. package/dist/Link.d.ts.map +1 -1
  15. package/dist/Menu.d.ts.map +1 -1
  16. package/dist/Popover.d.ts.map +1 -1
  17. package/dist/ReactionPicker.d.ts.map +1 -1
  18. package/dist/SectionLabel.d.ts +6 -1
  19. package/dist/SectionLabel.d.ts.map +1 -1
  20. package/dist/Tooltip.d.ts.map +1 -1
  21. package/dist/eslint/index.d.ts +2 -0
  22. package/dist/eslint/index.d.ts.map +1 -1
  23. package/dist/eslint/index.js +514 -6
  24. package/dist/eslint/index.js.map +4 -4
  25. package/dist/eslint/no-restyled-part.d.ts +81 -0
  26. package/dist/eslint/no-restyled-part.d.ts.map +1 -0
  27. package/dist/index.js +290 -266
  28. package/dist/index.js.map +4 -4
  29. package/package.json +1 -1
  30. package/src/AttachmentCard.tsx +7 -2
  31. package/src/Banner.tsx +2 -2
  32. package/src/Breadcrumb.tsx +9 -4
  33. package/src/Button.mdx +7 -0
  34. package/src/Button.stories.tsx +4 -1
  35. package/src/Button.tsx +10 -2
  36. package/src/Card.mdx +7 -0
  37. package/src/Card.stories.tsx +11 -0
  38. package/src/Card.tsx +8 -0
  39. package/src/CommandPalette.tsx +1 -1
  40. package/src/ConfirmDialog.tsx +2 -2
  41. package/src/DialogShell.tsx +6 -7
  42. package/src/Divider.mdx +3 -0
  43. package/src/Divider.tsx +12 -2
  44. package/src/EditableText.mdx +5 -0
  45. package/src/IconButton.mdx +9 -0
  46. package/src/IconButton.stories.tsx +10 -1
  47. package/src/IconButton.tsx +22 -3
  48. package/src/IdentityMenu.tsx +4 -1
  49. package/src/Link.mdx +6 -0
  50. package/src/Link.stories.tsx +12 -0
  51. package/src/Link.tsx +7 -2
  52. package/src/Menu.stories.tsx +1 -1
  53. package/src/Menu.test.tsx +2 -2
  54. package/src/Menu.tsx +6 -3
  55. package/src/Person.stories.tsx +5 -5
  56. package/src/Popover.test.tsx +2 -2
  57. package/src/Popover.tsx +3 -2
  58. package/src/PreviewCard.tsx +1 -1
  59. package/src/Property.stories.tsx +2 -2
  60. package/src/ReactionPicker.tsx +6 -3
  61. package/src/ScrollArea.stories.tsx +21 -7
  62. package/src/SectionLabel.mdx +3 -2
  63. package/src/SectionLabel.stories.tsx +3 -0
  64. package/src/SectionLabel.tsx +7 -2
  65. package/src/Tooltip.tsx +12 -14
  66. package/src/eslint/index.test.ts +32 -7
  67. package/src/eslint/index.ts +10 -1
  68. package/src/eslint/no-restyled-part.test.ts +301 -0
  69. package/src/eslint/no-restyled-part.ts +647 -0
package/dist/index.js CHANGED
@@ -163,13 +163,13 @@ var VARIANT_CLASSES = {
163
163
  underlined: "underline underline-offset-2 hover:text-text-primary",
164
164
  plain: ""
165
165
  };
166
- function Link({ href, variant = "text", external = false, className, children, ...props }) {
166
+ function Link({ href, variant = "text", external = false, truncate = false, className, children, ...props }) {
167
167
  return /* @__PURE__ */ jsx4(
168
168
  "a",
169
169
  {
170
170
  href,
171
171
  ...external ? { target: "_blank", rel: "noopener noreferrer" } : {},
172
- className: cn(VARIANT_CLASSES[variant], className),
172
+ className: cn(VARIANT_CLASSES[variant], truncate && "truncate", className),
173
173
  ...props,
174
174
  children
175
175
  }
@@ -210,6 +210,7 @@ function Card({
210
210
  active = false,
211
211
  attention,
212
212
  unreadable = false,
213
+ clip = false,
213
214
  className,
214
215
  children,
215
216
  ...props
@@ -231,12 +232,16 @@ function Card({
231
232
  active && "bg-bg-selected border-accent-primary",
232
233
  !active && attention && ATTENTION_CLASSES[attention],
233
234
  unreadable && "border-dashed",
235
+ clip && "overflow-hidden",
234
236
  href && "block",
235
237
  className
236
238
  );
237
239
  if (href !== void 0) {
238
240
  const { ref, ...anchorProps } = props;
239
- return /* @__PURE__ */ jsx5(Link, { href, variant: "plain", ref, className: classes, ...anchorProps, children });
241
+ return (
242
+ // @estiva-escape: a card that leads somewhere is drawn on Link's anchor (UIG-27 ruling 1), so this frame is Card's own look, not Link restyled
243
+ /* @__PURE__ */ jsx5(Link, { href, variant: "plain", ref, className: classes, ...anchorProps, children })
244
+ );
240
245
  }
241
246
  return /* @__PURE__ */ jsx5("div", { className: classes, ...props, children });
242
247
  }
@@ -298,19 +303,13 @@ function TooltipSurface({ label, shortcut, placement }) {
298
303
  children: /* @__PURE__ */ jsx7(
299
304
  BaseTooltip.Popup,
300
305
  {
301
- render: /* @__PURE__ */ jsx7(
302
- Tooltip,
303
- {
304
- label,
305
- shortcut,
306
- className: cn(
307
- "transition-[opacity,transform] duration-[120ms] ease-out motion-reduce:transition-none",
308
- "data-[ending-style]:duration-[80ms] data-[instant]:duration-0",
309
- "data-[starting-style]:opacity-0 data-[ending-style]:opacity-0",
310
- "data-[side=top]:data-[starting-style]:translate-y-[4px] data-[side=top]:data-[ending-style]:translate-y-[4px]",
311
- "data-[side=bottom]:data-[starting-style]:-translate-y-[4px] data-[side=bottom]:data-[ending-style]:-translate-y-[4px]"
312
- )
313
- }
306
+ render: /* @__PURE__ */ jsx7(Tooltip, { label, shortcut }),
307
+ className: cn(
308
+ "transition-[opacity,transform] duration-[120ms] ease-out motion-reduce:transition-none",
309
+ "data-[ending-style]:duration-[80ms] data-[instant]:duration-0",
310
+ "data-[starting-style]:opacity-0 data-[ending-style]:opacity-0",
311
+ "data-[side=top]:data-[starting-style]:translate-y-[4px] data-[side=top]:data-[ending-style]:translate-y-[4px]",
312
+ "data-[side=bottom]:data-[starting-style]:-translate-y-[4px] data-[side=bottom]:data-[ending-style]:-translate-y-[4px]"
314
313
  )
315
314
  }
316
315
  )
@@ -334,6 +333,8 @@ function TooltipTrigger({ label, shortcut, placement = "top", children }) {
334
333
  import { jsx as jsx8 } from "react/jsx-runtime";
335
334
  function IconButton({
336
335
  variant = "muted",
336
+ pressed,
337
+ glow = false,
337
338
  className,
338
339
  children,
339
340
  disabled,
@@ -365,11 +366,17 @@ function IconButton({
365
366
  // stretched and carries no `self-center` — see the note there.
366
367
  "flex items-center justify-center p-1 rounded-lg transition-colors shrink-0 self-center cursor-pointer",
367
368
  !state.disabled && variant === "primary" && "bg-accent-primary hover:bg-accent-hover text-text-inverse",
368
- !state.disabled && variant === "muted" && "text-text-secondary hover:bg-bg-hover hover:text-text-primary",
369
+ !state.disabled && (variant === "muted" || variant === "resolve") && "text-text-secondary hover:bg-bg-hover hover:text-text-primary",
369
370
  !state.disabled && variant === "outlined" && "border border-border-default hover:bg-bg-hover text-text-secondary",
371
+ !state.disabled && variant === "current" && "hover:bg-bg-hover",
370
372
  state.disabled && variant === "primary" && "bg-bg-disabled text-text-disabled",
371
- state.disabled && variant === "muted" && "text-text-disabled",
373
+ state.disabled && (variant === "muted" || variant === "resolve") && "text-text-disabled",
372
374
  state.disabled && variant === "outlined" && "border border-border-default text-text-disabled",
375
+ // Always, disabled too: the colour of where it sits, and Resolve's green.
376
+ variant === "current" && "text-current",
377
+ variant === "resolve" && "signal:hover:bg-success-muted signal:hover:text-success-default",
378
+ pressed && "bg-bg-active text-text-primary",
379
+ glow && "signal:shadow-glow-accent",
373
380
  // `pointer-events-none` only where the button is truly out of reach:
374
381
  // with a `disabledReason` the button IS the tooltip's trigger, and a
375
382
  // trigger the pointer cannot land on never opens one. Base UI already
@@ -378,6 +385,7 @@ function IconButton({
378
385
  state.disabled && "cursor-not-allowed",
379
386
  className
380
387
  ),
388
+ "aria-pressed": pressed,
381
389
  ...props,
382
390
  children
383
391
  }
@@ -471,75 +479,85 @@ function AttachmentCard({
471
479
  if (pending) {
472
480
  const failed = state === "failed";
473
481
  const warning = state === "warning";
474
- return /* @__PURE__ */ jsxs5(
475
- Card,
476
- {
477
- fill: "elevated",
478
- className: cn("group relative flex items-center gap-2 w-[200px] p-1.5 pr-3", failed ? "border-error-default" : warning && "border-warning-default", className),
479
- ...props,
480
- children: [
481
- /* @__PURE__ */ jsx9("div", { className: cn(TILE_CLASSES, "overflow-hidden"), children: state === "uploading" ? /* @__PURE__ */ jsx9(IconLoader2, { size: 16, stroke: 1.5, className: "animate-spin" }) : failed ? /* @__PURE__ */ jsx9(IconAlertCircle, { size: 16, stroke: 1.5, className: "text-error-default" }) : warning ? /* @__PURE__ */ jsx9(IconAlertTriangle, { size: 16, stroke: 1.5, className: "text-warning-default" }) : image && src ? /* @__PURE__ */ jsx9("img", { src, alt: name, className: "size-full object-cover" }) : /* @__PURE__ */ jsx9("span", { className: "text-menu font-semibold", children: typeLabelOf(name) }) }),
482
- /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-[1px] min-w-0", children: [
483
- /* @__PURE__ */ jsx9(Truncating, { text: name, className: NAME_CLASSES }),
484
- /* @__PURE__ */ jsx9(
485
- Truncating,
482
+ return (
483
+ // @estiva-escape: a failed or warning file's strong hairline is AttachmentCard's own state; Card's attention hairlines are the soft ones (UIG-9, Katerina 17 September)
484
+ /* @__PURE__ */ jsxs5(
485
+ Card,
486
+ {
487
+ fill: "elevated",
488
+ className: cn("group relative flex items-center gap-2 w-[200px] p-1.5 pr-3", failed ? "border-error-default" : warning && "border-warning-default", className),
489
+ ...props,
490
+ children: [
491
+ /* @__PURE__ */ jsx9("div", { className: cn(TILE_CLASSES, "overflow-hidden"), children: state === "uploading" ? /* @__PURE__ */ jsx9(IconLoader2, { size: 16, stroke: 1.5, className: "animate-spin" }) : failed ? /* @__PURE__ */ jsx9(IconAlertCircle, { size: 16, stroke: 1.5, className: "text-error-default" }) : warning ? /* @__PURE__ */ jsx9(IconAlertTriangle, { size: 16, stroke: 1.5, className: "text-warning-default" }) : image && src ? /* @__PURE__ */ jsx9("img", { src, alt: name, className: "size-full object-cover" }) : /* @__PURE__ */ jsx9("span", { className: "text-menu font-semibold", children: typeLabelOf(name) }) }),
492
+ /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-[1px] min-w-0", children: [
493
+ /* @__PURE__ */ jsx9(Truncating, { text: name, className: NAME_CLASSES }),
494
+ /* @__PURE__ */ jsx9(
495
+ Truncating,
496
+ {
497
+ text: (failed || warning ? note : state === "uploading" ? note ?? "Uploading\u2026" : note ?? sizeText) ?? "",
498
+ hint: noteHint,
499
+ className: cn(NOTE_CLASSES, failed ? "text-error-default" : warning ? "text-warning-default" : "text-text-secondary")
500
+ }
501
+ )
502
+ ] }),
503
+ onRemove && /* @__PURE__ */ jsx9(
504
+ BaseButton2,
486
505
  {
487
- text: (failed || warning ? note : state === "uploading" ? note ?? "Uploading\u2026" : note ?? sizeText) ?? "",
488
- hint: noteHint,
489
- className: cn(NOTE_CLASSES, failed ? "text-error-default" : warning ? "text-warning-default" : "text-text-secondary")
506
+ type: "button",
507
+ "aria-label": `Remove ${name}`,
508
+ className: "absolute -top-1.5 -right-1.5 size-5 rounded-full bg-bg-elevated border border-border-strong flex items-center justify-center text-text-secondary hover:text-text-primary opacity-0 group-hover:opacity-100 transition-opacity",
509
+ onClick: (event) => {
510
+ event.stopPropagation();
511
+ onRemove();
512
+ },
513
+ children: /* @__PURE__ */ jsx9(IconX, { size: 11, stroke: 1.75 })
490
514
  }
491
515
  )
492
- ] }),
493
- onRemove && /* @__PURE__ */ jsx9(
494
- BaseButton2,
495
- {
496
- type: "button",
497
- "aria-label": `Remove ${name}`,
498
- className: "absolute -top-1.5 -right-1.5 size-5 rounded-full bg-bg-elevated border border-border-strong flex items-center justify-center text-text-secondary hover:text-text-primary opacity-0 group-hover:opacity-100 transition-opacity",
499
- onClick: (event) => {
500
- event.stopPropagation();
501
- onRemove();
502
- },
503
- children: /* @__PURE__ */ jsx9(IconX, { size: 11, stroke: 1.75 })
504
- }
505
- )
506
- ]
507
- }
516
+ ]
517
+ }
518
+ )
508
519
  );
509
520
  }
510
- const download = onDownload ? /* @__PURE__ */ jsx9(
511
- IconButton,
512
- {
513
- variant: "muted",
514
- tooltip: "Download",
515
- "aria-label": `Download ${name}`,
516
- className: "opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100 transition-opacity",
517
- onClick: (event) => {
518
- event.stopPropagation();
519
- onDownload();
520
- },
521
- children: /* @__PURE__ */ jsx9(IconDownload, { size: 16, stroke: 1.5 })
522
- }
521
+ const download = onDownload ? (
522
+ // @estiva-escape: Download shows when its card is pointed at or focused, AttachmentCard's own action; IconButton has no reveal on its card's hover (UIG-9, Katerina 17 September)
523
+ /* @__PURE__ */ jsx9(
524
+ IconButton,
525
+ {
526
+ variant: "muted",
527
+ tooltip: "Download",
528
+ "aria-label": `Download ${name}`,
529
+ className: "opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100 transition-opacity",
530
+ onClick: (event) => {
531
+ event.stopPropagation();
532
+ onDownload();
533
+ },
534
+ children: /* @__PURE__ */ jsx9(IconDownload, { size: 16, stroke: 1.5 })
535
+ }
536
+ )
523
537
  ) : null;
524
538
  if (state === "loading") {
525
539
  return (
526
540
  // `role="status"`: a plain box may not carry a name (axe, aria-prohibited-attr), and a
527
541
  // status says what it is doing — loading — to a reader that cannot see the pulse.
542
+ // @estiva-escape: the loading pulse is AttachmentCard's own state; Card has no loading state (UIG-9, Katerina 17 September)
528
543
  /* @__PURE__ */ jsx9(Card, { role: "status", fill: "inset", "aria-busy": "true", "aria-label": `Loading ${name}`, className: cn("w-[180px] h-28 animate-pulse", className), ...props, children: null })
529
544
  );
530
545
  }
531
546
  if (state === "unreadable") {
532
- return /* @__PURE__ */ jsxs5(Card, { fill: "inset", unreadable: true, className: cn("flex items-center gap-2 w-[240px] p-1.5 opacity-70", className), ...props, children: [
533
- /* @__PURE__ */ jsx9("div", { className: TILE_CLASSES, children: /* @__PURE__ */ jsx9(TypeIcon, { name }) }),
534
- /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-[1px] min-w-0 text-left", children: [
535
- /* @__PURE__ */ jsx9(Truncating, { text: name, className: NAME_CLASSES }),
536
- /* @__PURE__ */ jsx9("span", { className: cn(NOTE_CLASSES, "text-text-secondary"), children: note ?? "Could not be loaded" })
547
+ return (
548
+ // @estiva-escape: a file that could not be read is faded as well as dashed, AttachmentCard's own state; Card has no faded state (UIG-9, Katerina 17 September)
549
+ /* @__PURE__ */ jsxs5(Card, { fill: "inset", unreadable: true, className: cn("flex items-center gap-2 w-[240px] p-1.5 opacity-70", className), ...props, children: [
550
+ /* @__PURE__ */ jsx9("div", { className: TILE_CLASSES, children: /* @__PURE__ */ jsx9(TypeIcon, { name }) }),
551
+ /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-[1px] min-w-0 text-left", children: [
552
+ /* @__PURE__ */ jsx9(Truncating, { text: name, className: NAME_CLASSES }),
553
+ /* @__PURE__ */ jsx9("span", { className: cn(NOTE_CLASSES, "text-text-secondary"), children: note ?? "Could not be loaded" })
554
+ ] })
537
555
  ] })
538
- ] });
556
+ );
539
557
  }
540
558
  if (image && src) {
541
559
  const picture = /* @__PURE__ */ jsx9("img", { src, alt: name, className: "w-full h-28 object-cover" });
542
- return /* @__PURE__ */ jsxs5(Card, { fill: "inset", hover: "hairline", className: cn("group relative flex flex-col w-[180px] overflow-hidden", className), ...props, children: [
560
+ return /* @__PURE__ */ jsxs5(Card, { fill: "inset", hover: "hairline", clip: true, className: cn("group relative flex flex-col w-[180px]", className), ...props, children: [
543
561
  onOpen ? /* @__PURE__ */ jsx9(
544
562
  BaseButton2,
545
563
  {
@@ -566,10 +584,13 @@ function AttachmentCard({
566
584
  /* @__PURE__ */ jsx9("span", { className: cn(NOTE_CLASSES, "text-text-secondary"), children: note ?? `${typeLabelOf(name)} \xB7 ${sizeText}` })
567
585
  ] })
568
586
  ] });
569
- return /* @__PURE__ */ jsxs5(Card, { fill: "inset", hover: href ? "hairline" : "none", className: cn("group flex items-center gap-2 w-[240px] p-1.5 pr-1", !href && "opacity-70", className), ...props, children: [
570
- href ? /* @__PURE__ */ jsx9(Link, { href, external: true, variant: "plain", className: "flex items-center gap-2 min-w-0 flex-1 cursor-pointer", onClick: (event) => event.stopPropagation(), children: body }) : /* @__PURE__ */ jsx9("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: body }),
571
- download
572
- ] });
587
+ return (
588
+ // @estiva-escape: a file that cannot be opened is faded, AttachmentCard's own state; Card has no faded state (UIG-9, Katerina 17 September)
589
+ /* @__PURE__ */ jsxs5(Card, { fill: "inset", hover: href ? "hairline" : "none", className: cn("group flex items-center gap-2 w-[240px] p-1.5 pr-1", !href && "opacity-70", className), ...props, children: [
590
+ href ? /* @__PURE__ */ jsx9(Link, { href, external: true, variant: "plain", className: "flex items-center gap-2 min-w-0 flex-1", onClick: (event) => event.stopPropagation(), children: body }) : /* @__PURE__ */ jsx9("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: body }),
591
+ download
592
+ ] })
593
+ );
573
594
  }
574
595
 
575
596
  // src/Avatar.tsx
@@ -671,7 +692,7 @@ function Banner({ tone, children, onDismiss, dismissLabel = "Dismiss", className
671
692
  }
672
693
  return /* @__PURE__ */ jsxs7("div", { role, className: cn("flex items-center gap-3 px-4 py-2 text-body-2", TONE_STYLES[tone], className), children: [
673
694
  /* @__PURE__ */ jsx12("span", { className: "min-w-0 flex-1", children }),
674
- /* @__PURE__ */ jsx12(IconButton, { "aria-label": dismissLabel, onClick: onDismiss, className: "-mr-1 shrink-0 text-current hover:text-current", children: /* @__PURE__ */ jsx12(IconX2, { size: 16, stroke: 1.5 }) })
695
+ /* @__PURE__ */ jsx12(IconButton, { variant: "current", "aria-label": dismissLabel, onClick: onDismiss, className: "-mr-1 shrink-0", children: /* @__PURE__ */ jsx12(IconX2, { size: 16, stroke: 1.5 }) })
675
696
  ] });
676
697
  }
677
698
 
@@ -715,7 +736,7 @@ function Button({
715
736
  // Extra right padding beside a leading icon, for optical balance.
716
737
  size === "default" && (hasLeadingIcon ? "pl-2 pr-3" : "px-2"),
717
738
  size === "small" && (hasLeadingIcon ? "pl-1.5 pr-2" : "px-1.5"),
718
- !state.disabled && variant === "primary" && "bg-accent-primary hover:bg-accent-hover text-text-inverse cursor-pointer signal:font-semibold",
739
+ !state.disabled && (variant === "primary" || variant === "resolve") && "bg-accent-primary hover:bg-accent-hover text-text-inverse cursor-pointer signal:font-semibold",
719
740
  !state.disabled && variant === "outlined" && "border border-border-default hover:bg-bg-hover text-text-primary cursor-pointer",
720
741
  !state.disabled && variant === "muted" && "hover:bg-bg-hover text-text-primary cursor-pointer",
721
742
  !state.disabled && variant === "destructive" && "hover:bg-error-muted text-error-default cursor-pointer",
@@ -727,6 +748,8 @@ function Button({
727
748
  // and a prevented `onClick`), so nothing else needs it.
728
749
  state.disabled && !disabledReason && "pointer-events-none",
729
750
  state.disabled && variant === "outlined" && "border border-border-default",
751
+ // Disabled too, as it always drew.
752
+ variant === "resolve" && "signal:bg-transparent signal:border signal:border-border-default signal:text-text-primary signal:shadow-none signal:hover:bg-success-muted signal:hover:border-success-outline signal:hover:text-success-default signal:transition-colors",
730
753
  className
731
754
  ),
732
755
  ...props,
@@ -822,8 +845,8 @@ function Chip({ type = "neutral", label, leadingIcon, trailingIcon, className })
822
845
 
823
846
  // src/CommandPalette.tsx
824
847
  import {
825
- createContext as createContext3,
826
- useContext as useContext3,
848
+ createContext as createContext4,
849
+ useContext as useContext4,
827
850
  useEffect,
828
851
  useLayoutEffect as useLayoutEffect3,
829
852
  useMemo as useMemo2,
@@ -841,10 +864,42 @@ import { Combobox } from "@base-ui/react/combobox";
841
864
  import { IconX as IconX3 } from "@tabler/icons-react";
842
865
 
843
866
  // src/Menu.tsx
844
- import { createContext as createContext2, useContext as useContext2 } from "react";
867
+ import { createContext as createContext3, useContext as useContext3 } from "react";
845
868
  import { IconChevronRight } from "@tabler/icons-react";
846
869
  import { Menu as BaseMenu } from "@base-ui/react/menu";
847
870
 
871
+ // src/Divider.tsx
872
+ import { createContext as createContext2, useContext as useContext2 } from "react";
873
+ import { Separator } from "@base-ui/react/separator";
874
+ import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
875
+ var DividerInPanel = createContext2(false);
876
+ function Divider({ orientation = "horizontal", label, tone = "default", className }) {
877
+ const inset = useContext2(DividerInPanel) ? "mx-0" : "mx-3";
878
+ if (label && orientation === "horizontal") {
879
+ const line = tone === "warning" ? "bg-warning-muted" : "bg-border-subtle";
880
+ return /* @__PURE__ */ jsxs11(
881
+ Separator,
882
+ {
883
+ orientation: "horizontal",
884
+ "aria-label": label,
885
+ className: cn("flex shrink-0 items-center gap-2", inset, className),
886
+ children: [
887
+ /* @__PURE__ */ jsx16("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
888
+ /* @__PURE__ */ jsx16("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
889
+ /* @__PURE__ */ jsx16("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
890
+ ]
891
+ }
892
+ );
893
+ }
894
+ return /* @__PURE__ */ jsx16(
895
+ Separator,
896
+ {
897
+ orientation,
898
+ className: cn("shrink-0 bg-border-subtle", orientation === "horizontal" ? cn("h-px", inset) : "w-px self-stretch", className)
899
+ }
900
+ );
901
+ }
902
+
848
903
  // src/triggerDisabled.ts
849
904
  function triggerDisabled(trigger) {
850
905
  const props = trigger.props;
@@ -852,13 +907,14 @@ function triggerDisabled(trigger) {
852
907
  }
853
908
 
854
909
  // src/SectionLabel.tsx
855
- import { jsx as jsx16 } from "react/jsx-runtime";
856
- function SectionLabel({ children, className }) {
857
- return /* @__PURE__ */ jsx16(
910
+ import { jsx as jsx17 } from "react/jsx-runtime";
911
+ function SectionLabel({ children, tone = "primary", className }) {
912
+ return /* @__PURE__ */ jsx17(
858
913
  "span",
859
914
  {
860
915
  className: cn(
861
- "text-h5 leading-3 text-text-primary signal:font-mono signal:text-small signal:uppercase signal:tracking-widest",
916
+ "text-h5 leading-3 signal:font-mono signal:text-small signal:uppercase signal:tracking-widest",
917
+ tone === "secondary" ? "text-text-secondary" : "text-text-primary",
862
918
  className
863
919
  ),
864
920
  children
@@ -867,10 +923,10 @@ function SectionLabel({ children, className }) {
867
923
  }
868
924
 
869
925
  // src/Menu.tsx
870
- import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
871
- var MenuContext = createContext2(null);
926
+ import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
927
+ var MenuContext = createContext3(null);
872
928
  function MenuPanel({ children, className, ...props }) {
873
- return /* @__PURE__ */ jsx17(
929
+ return /* @__PURE__ */ jsx18(
874
930
  "div",
875
931
  {
876
932
  className: cn(
@@ -900,7 +956,7 @@ var VIEWPORT_PAD2 = 8;
900
956
  var HOVER_OPEN_DELAY = 0;
901
957
  var HOVER_CLOSE_DELAY = 150;
902
958
  function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange, actionsRef, children, className, contentClassName }) {
903
- return /* @__PURE__ */ jsxs11(
959
+ return /* @__PURE__ */ jsxs12(
904
960
  BaseMenu.Root,
905
961
  {
906
962
  open,
@@ -908,7 +964,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
908
964
  actionsRef,
909
965
  modal: false,
910
966
  children: [
911
- /* @__PURE__ */ jsx17(
967
+ /* @__PURE__ */ jsx18(
912
968
  BaseMenu.Trigger,
913
969
  {
914
970
  render: trigger,
@@ -918,7 +974,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
918
974
  closeDelay: HOVER_CLOSE_DELAY
919
975
  }
920
976
  ),
921
- /* @__PURE__ */ jsx17(BaseMenu.Portal, { children: /* @__PURE__ */ jsx17(
977
+ /* @__PURE__ */ jsx18(BaseMenu.Portal, { children: /* @__PURE__ */ jsx18(
922
978
  BaseMenu.Positioner,
923
979
  {
924
980
  side: "bottom",
@@ -926,13 +982,13 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
926
982
  sideOffset: GAP2,
927
983
  collisionPadding: VIEWPORT_PAD2,
928
984
  className: "z-50 data-[anchor-hidden]:hidden",
929
- children: /* @__PURE__ */ jsx17(
985
+ children: /* @__PURE__ */ jsx18(
930
986
  BaseMenu.Popup,
931
987
  {
932
988
  "data-interactive": true,
933
989
  className: cn("min-w-[180px] outline-none p-0", className),
934
- render: /* @__PURE__ */ jsx17(MenuPanel, {}),
935
- children: /* @__PURE__ */ jsx17(ScrollArea, { viewportClassName: "max-h-[var(--available-height)]", contentClassName: cn("flex flex-col p-2 [&>[role=separator]]:mx-0", contentClassName), children: /* @__PURE__ */ jsx17(MenuContext.Provider, { value: { openOnHover }, children }) })
990
+ render: /* @__PURE__ */ jsx18(MenuPanel, {}),
991
+ children: /* @__PURE__ */ jsx18(ScrollArea, { viewportClassName: "max-h-[var(--available-height)]", contentClassName: cn("flex flex-col p-2", contentClassName), children: /* @__PURE__ */ jsx18(MenuContext.Provider, { value: { openOnHover }, children: /* @__PURE__ */ jsx18(DividerInPanel.Provider, { value: true, children }) }) })
936
992
  }
937
993
  )
938
994
  }
@@ -942,26 +998,26 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
942
998
  );
943
999
  }
944
1000
  function MenuSub({ label, leading, selected, children, className }) {
945
- const menu = useContext2(MenuContext);
1001
+ const menu = useContext3(MenuContext);
946
1002
  if (!isProduction() && menu?.openOnHover) {
947
1003
  console.error(
948
1004
  '[@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".'
949
1005
  );
950
1006
  }
951
- return /* @__PURE__ */ jsxs11(BaseMenu.SubmenuRoot, { children: [
952
- /* @__PURE__ */ jsx17(
1007
+ return /* @__PURE__ */ jsxs12(BaseMenu.SubmenuRoot, { children: [
1008
+ /* @__PURE__ */ jsx18(
953
1009
  BaseMenu.SubmenuTrigger,
954
1010
  {
955
1011
  openOnHover: true,
956
1012
  delay: 0,
957
1013
  closeDelay: 150,
958
1014
  nativeButton: true,
959
- render: /* @__PURE__ */ jsx17("button", { type: "button" }),
1015
+ render: /* @__PURE__ */ jsx18("button", { type: "button" }),
960
1016
  className: menuItemClassName({ size: "default", selected }),
961
- children: /* @__PURE__ */ jsx17(MenuItemBody, { label, leading, submenu: true })
1017
+ children: /* @__PURE__ */ jsx18(MenuItemBody, { label, leading, submenu: true })
962
1018
  }
963
1019
  ),
964
- /* @__PURE__ */ jsx17(BaseMenu.Portal, { children: /* @__PURE__ */ jsx17(
1020
+ /* @__PURE__ */ jsx18(BaseMenu.Portal, { children: /* @__PURE__ */ jsx18(
965
1021
  BaseMenu.Positioner,
966
1022
  {
967
1023
  side: "inline-end",
@@ -969,7 +1025,7 @@ function MenuSub({ label, leading, selected, children, className }) {
969
1025
  sideOffset: GAP2,
970
1026
  collisionPadding: VIEWPORT_PAD2,
971
1027
  className: "z-50 data-[anchor-hidden]:hidden",
972
- children: /* @__PURE__ */ jsx17(BaseMenu.Popup, { className: cn("w-[160px]", className), "data-interactive": true, render: /* @__PURE__ */ jsx17(MenuPanel, {}), children })
1028
+ children: /* @__PURE__ */ jsx18(BaseMenu.Popup, { className: cn("w-[160px]", className), "data-interactive": true, render: /* @__PURE__ */ jsx18(MenuPanel, {}), children })
973
1029
  }
974
1030
  ) })
975
1031
  ] });
@@ -1004,25 +1060,25 @@ function menuItemClassName({ size, selected, className }) {
1004
1060
  );
1005
1061
  }
1006
1062
  function MenuItemBody({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected }) {
1007
- const edge = trailing ?? (shortcut ? /* @__PURE__ */ jsx17(Kbd, { children: shortcut }) : submenu ? /* @__PURE__ */ jsx17(IconChevronRight, { size: 16, stroke: 1.5, className: "shrink-0 text-text-muted" }) : null);
1008
- return /* @__PURE__ */ jsxs11(Fragment2, { children: [
1009
- leading && /* @__PURE__ */ jsx17("span", { className: "flex shrink-0 items-center", children: leading }),
1010
- children ?? /* @__PURE__ */ jsxs11("span", { className: cn("flex min-w-0 flex-1 flex-col", size === "tall" && "gap-[2px]"), children: [
1011
- /* @__PURE__ */ jsx17("span", { className: cn("truncate text-body-2", destructive ? "text-error-default" : "text-text-primary"), children: label }),
1012
- description && /* @__PURE__ */ jsx17("span", { className: "truncate text-caption text-text-secondary", children: description })
1063
+ const edge = trailing ?? (shortcut ? /* @__PURE__ */ jsx18(Kbd, { children: shortcut }) : submenu ? /* @__PURE__ */ jsx18(IconChevronRight, { size: 16, stroke: 1.5, className: "shrink-0 text-text-muted" }) : null);
1064
+ return /* @__PURE__ */ jsxs12(Fragment2, { children: [
1065
+ leading && /* @__PURE__ */ jsx18("span", { className: "flex shrink-0 items-center", children: leading }),
1066
+ children ?? /* @__PURE__ */ jsxs12("span", { className: cn("flex min-w-0 flex-1 flex-col", size === "tall" && "gap-[2px]"), children: [
1067
+ /* @__PURE__ */ jsx18("span", { className: cn("truncate text-body-2", destructive ? "text-error-default" : "text-text-primary"), children: label }),
1068
+ description && /* @__PURE__ */ jsx18("span", { className: "truncate text-caption text-text-secondary", children: description })
1013
1069
  ] }),
1014
1070
  (edge || hint) && // One grid cell holding both, right-aligned: the slot is as wide as
1015
1071
  // the wider of the two and never changes, so revealing the hint moves
1016
1072
  // nothing. No transition here either — the hint switches on the same
1017
1073
  // :hover / `selected` as the fill, in the same frame.
1018
- /* @__PURE__ */ jsxs11("span", { className: "grid shrink-0 items-center justify-items-end [&>*]:col-start-1 [&>*]:row-start-1", children: [
1019
- edge && /* @__PURE__ */ jsx17("span", { className: cn("flex items-center", hint && "group-hover:opacity-0 group-data-[highlighted]:opacity-0", hint && selected && "opacity-0"), children: edge }),
1020
- hint && /* @__PURE__ */ jsx17("span", { className: cn("flex items-center opacity-0 group-hover:opacity-100 group-data-[highlighted]:opacity-100", selected && "opacity-100"), children: hint })
1074
+ /* @__PURE__ */ jsxs12("span", { className: "grid shrink-0 items-center justify-items-end [&>*]:col-start-1 [&>*]:row-start-1", children: [
1075
+ edge && /* @__PURE__ */ jsx18("span", { className: cn("flex items-center", hint && "group-hover:opacity-0 group-data-[highlighted]:opacity-0", hint && selected && "opacity-0"), children: edge }),
1076
+ hint && /* @__PURE__ */ jsx18("span", { className: cn("flex items-center opacity-0 group-hover:opacity-100 group-data-[highlighted]:opacity-100", selected && "opacity-100"), children: hint })
1021
1077
  ] })
1022
1078
  ] });
1023
1079
  }
1024
1080
  function MenuItem({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected, className, ...props }) {
1025
- const body = /* @__PURE__ */ jsx17(
1081
+ const body = /* @__PURE__ */ jsx18(
1026
1082
  MenuItemBody,
1027
1083
  {
1028
1084
  label,
@@ -1039,14 +1095,14 @@ function MenuItem({ label, children, size = "default", description, leading, tra
1039
1095
  }
1040
1096
  );
1041
1097
  const rowClassName = menuItemClassName({ size, selected, className });
1042
- if (!useContext2(MenuContext)) {
1043
- return /* @__PURE__ */ jsx17("button", { type: "button", className: rowClassName, ...props, children: body });
1098
+ if (!useContext3(MenuContext)) {
1099
+ return /* @__PURE__ */ jsx18("button", { type: "button", className: rowClassName, ...props, children: body });
1044
1100
  }
1045
- return /* @__PURE__ */ jsx17(
1101
+ return /* @__PURE__ */ jsx18(
1046
1102
  BaseMenu.Item,
1047
1103
  {
1048
1104
  nativeButton: true,
1049
- render: /* @__PURE__ */ jsx17("button", { type: "button" }),
1105
+ render: /* @__PURE__ */ jsx18("button", { type: "button" }),
1050
1106
  className: rowClassName,
1051
1107
  ...props,
1052
1108
  children: body
@@ -1054,31 +1110,31 @@ function MenuItem({ label, children, size = "default", description, leading, tra
1054
1110
  );
1055
1111
  }
1056
1112
  function EnterHint({ target }) {
1057
- return /* @__PURE__ */ jsxs11("span", { className: "flex shrink-0 items-center gap-1.5 text-text-muted", children: [
1058
- /* @__PURE__ */ jsx17(Kbd, { children: "\u21A9 Enter" }),
1059
- target && /* @__PURE__ */ jsx17("span", { className: "text-menu signal:font-mono signal:text-small signal:tracking-wider", children: target })
1113
+ return /* @__PURE__ */ jsxs12("span", { className: "flex shrink-0 items-center gap-1.5 text-text-muted", children: [
1114
+ /* @__PURE__ */ jsx18(Kbd, { children: "\u21A9 Enter" }),
1115
+ target && /* @__PURE__ */ jsx18("span", { className: "text-menu signal:font-mono signal:text-small signal:tracking-wider", children: target })
1060
1116
  ] });
1061
1117
  }
1062
1118
  function MenuSection({ label, children, className }) {
1063
- const inMenu = useContext2(MenuContext) !== null;
1064
- const heading = /* @__PURE__ */ jsx17("div", { className: cn("flex h-8 items-center px-2", className), children: /* @__PURE__ */ jsx17(SectionLabel, { className: "text-text-secondary", children: label }) });
1119
+ const inMenu = useContext3(MenuContext) !== null;
1120
+ const heading = /* @__PURE__ */ jsx18("div", { className: cn("flex h-8 items-center px-2", className), children: /* @__PURE__ */ jsx18(SectionLabel, { tone: "secondary", children: label }) });
1065
1121
  if (!inMenu) {
1066
- return /* @__PURE__ */ jsxs11("div", { className: "flex flex-col", children: [
1122
+ return /* @__PURE__ */ jsxs12("div", { className: "flex flex-col", children: [
1067
1123
  heading,
1068
1124
  children
1069
1125
  ] });
1070
1126
  }
1071
- return /* @__PURE__ */ jsxs11(BaseMenu.Group, { className: "flex flex-col", children: [
1072
- /* @__PURE__ */ jsx17(BaseMenu.GroupLabel, { render: heading }),
1127
+ return /* @__PURE__ */ jsxs12(BaseMenu.Group, { className: "flex flex-col", children: [
1128
+ /* @__PURE__ */ jsx18(BaseMenu.GroupLabel, { render: heading }),
1073
1129
  children
1074
1130
  ] });
1075
1131
  }
1076
1132
  function MenuRow({ children, className }) {
1077
- return /* @__PURE__ */ jsx17("div", { className: cn("flex items-center gap-2 px-2 py-1.5", className), children });
1133
+ return /* @__PURE__ */ jsx18("div", { className: cn("flex items-center gap-2 px-2 py-1.5", className), children });
1078
1134
  }
1079
1135
 
1080
1136
  // src/ChipInput.tsx
1081
- import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
1137
+ import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
1082
1138
  var CHIP_BOX = (
1083
1139
  // Curved, not a pill (Katerina, 2026-09-01): the Avatar keeps its own
1084
1140
  // rounded-sm corners — never a forced circle — and the chip's corner
@@ -1089,10 +1145,10 @@ var CHIP_LABEL = "text-caption font-medium text-text-primary";
1089
1145
  var CHIP_REMOVE = "size-4 flex items-center justify-center rounded-full hover:bg-bg-hover text-text-secondary";
1090
1146
  var chipPadding = (leading, removable) => cn(leading ? "pl-[2px]" : "pl-2", removable ? "pr-1" : "pr-2");
1091
1147
  function InputChip({ label, leading, onRemove, removeLabel, truncate, className }) {
1092
- return /* @__PURE__ */ jsxs12("div", { className: cn(CHIP_BOX, chipPadding(!!leading, !!onRemove), className), children: [
1093
- leading && /* @__PURE__ */ jsx18("span", { className: "flex shrink-0 items-center", children: leading }),
1094
- /* @__PURE__ */ jsx18("span", { className: cn(CHIP_LABEL, truncate && "min-w-0 truncate"), children: label }),
1095
- onRemove && /* @__PURE__ */ jsx18(
1148
+ return /* @__PURE__ */ jsxs13("div", { className: cn(CHIP_BOX, chipPadding(!!leading, !!onRemove), className), children: [
1149
+ leading && /* @__PURE__ */ jsx19("span", { className: "flex shrink-0 items-center", children: leading }),
1150
+ /* @__PURE__ */ jsx19("span", { className: cn(CHIP_LABEL, truncate && "min-w-0 truncate"), children: label }),
1151
+ onRemove && /* @__PURE__ */ jsx19(
1096
1152
  BaseButton4,
1097
1153
  {
1098
1154
  type: "button",
@@ -1102,7 +1158,7 @@ function InputChip({ label, leading, onRemove, removeLabel, truncate, className
1102
1158
  },
1103
1159
  className: cn(CHIP_REMOVE, truncate && "shrink-0"),
1104
1160
  "aria-label": removeLabel ?? `Remove ${label}`,
1105
- children: /* @__PURE__ */ jsx18(IconX3, { size: 10, stroke: 1.5 })
1161
+ children: /* @__PURE__ */ jsx19(IconX3, { size: 10, stroke: 1.5 })
1106
1162
  }
1107
1163
  )
1108
1164
  ] });
@@ -1155,7 +1211,7 @@ function ChipInput({
1155
1211
  setQuery("");
1156
1212
  }
1157
1213
  }
1158
- return /* @__PURE__ */ jsxs12(
1214
+ return /* @__PURE__ */ jsxs13(
1159
1215
  Combobox.Root,
1160
1216
  {
1161
1217
  multiple: true,
@@ -1172,13 +1228,13 @@ function ChipInput({
1172
1228
  filter,
1173
1229
  itemToStringLabel: (option) => option.label,
1174
1230
  children: [
1175
- /* @__PURE__ */ jsxs12(Combobox.Chips, { ref: setBox, className: "bg-bg-inset border border-border-default hover:border-border-strong focus-within:border-border-focus focus-within:hover:border-border-focus rounded-lg px-3 py-1.5 flex flex-wrap items-center gap-1.5 transition-colors min-h-[38px] cursor-text signal:transition-shadow signal:focus-within:shadow-focus-ring", children: [
1176
- value.map((option) => /* @__PURE__ */ jsxs12(Combobox.Chip, { className: cn(CHIP_BOX, chipPadding(!!chipLeading, true)), children: [
1177
- chipLeading && /* @__PURE__ */ jsx18("span", { className: "flex shrink-0 items-center", children: chipLeading(option) }),
1178
- /* @__PURE__ */ jsx18("span", { className: CHIP_LABEL, children: option.label }),
1179
- /* @__PURE__ */ jsx18(Combobox.ChipRemove, { className: CHIP_REMOVE, "aria-label": `Remove ${option.label}`, children: /* @__PURE__ */ jsx18(IconX3, { size: 10, stroke: 1.5 }) })
1231
+ /* @__PURE__ */ jsxs13(Combobox.Chips, { ref: setBox, className: "bg-bg-inset border border-border-default hover:border-border-strong focus-within:border-border-focus focus-within:hover:border-border-focus rounded-lg px-3 py-1.5 flex flex-wrap items-center gap-1.5 transition-colors min-h-[38px] cursor-text signal:transition-shadow signal:focus-within:shadow-focus-ring", children: [
1232
+ value.map((option) => /* @__PURE__ */ jsxs13(Combobox.Chip, { className: cn(CHIP_BOX, chipPadding(!!chipLeading, true)), children: [
1233
+ chipLeading && /* @__PURE__ */ jsx19("span", { className: "flex shrink-0 items-center", children: chipLeading(option) }),
1234
+ /* @__PURE__ */ jsx19("span", { className: CHIP_LABEL, children: option.label }),
1235
+ /* @__PURE__ */ jsx19(Combobox.ChipRemove, { className: CHIP_REMOVE, "aria-label": `Remove ${option.label}`, children: /* @__PURE__ */ jsx19(IconX3, { size: 10, stroke: 1.5 }) })
1180
1236
  ] }, option.id)),
1181
- /* @__PURE__ */ jsx18(
1237
+ /* @__PURE__ */ jsx19(
1182
1238
  Combobox.Input,
1183
1239
  {
1184
1240
  autoFocus,
@@ -1190,18 +1246,18 @@ function ChipInput({
1190
1246
  }
1191
1247
  )
1192
1248
  ] }),
1193
- /* @__PURE__ */ jsx18(Combobox.Portal, { children: /* @__PURE__ */ jsx18(
1249
+ /* @__PURE__ */ jsx19(Combobox.Portal, { children: /* @__PURE__ */ jsx19(
1194
1250
  Combobox.Positioner,
1195
1251
  {
1196
1252
  anchor: box,
1197
1253
  sideOffset: GAP3,
1198
1254
  collisionPadding: VIEWPORT_PAD3,
1199
1255
  className: "z-50 data-[anchor-hidden]:hidden",
1200
- children: /* @__PURE__ */ jsx18(Combobox.Popup, { className: "w-[var(--anchor-width)] p-0", render: /* @__PURE__ */ jsx18(MenuPanel, {}), children: /* @__PURE__ */ jsx18(ScrollArea, { viewportClassName: "max-h-[240px]", contentClassName: "flex flex-col p-2", children: /* @__PURE__ */ jsx18(Combobox.List, { children: (option) => /* @__PURE__ */ jsx18(
1256
+ children: /* @__PURE__ */ jsx19(Combobox.Popup, { className: "w-[var(--anchor-width)] p-0", render: /* @__PURE__ */ jsx19(MenuPanel, {}), children: /* @__PURE__ */ jsx19(ScrollArea, { viewportClassName: "max-h-[240px]", contentClassName: "flex flex-col p-2", children: /* @__PURE__ */ jsx19(Combobox.List, { children: (option) => /* @__PURE__ */ jsx19(
1201
1257
  Combobox.Item,
1202
1258
  {
1203
1259
  value: option,
1204
- render: /* @__PURE__ */ jsx18(
1260
+ render: /* @__PURE__ */ jsx19(
1205
1261
  MenuItem,
1206
1262
  {
1207
1263
  size: "tall",
@@ -1224,21 +1280,21 @@ var VIEWPORT_PAD3 = 8;
1224
1280
 
1225
1281
  // src/EmptyState.tsx
1226
1282
  import { IconMessage2 } from "@tabler/icons-react";
1227
- import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
1283
+ import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
1228
1284
  function EmptyState({ icon, message, scope = "page", className }) {
1229
1285
  if (scope === "section") {
1230
- return /* @__PURE__ */ jsx19("p", { className: cn("text-caption text-text-muted", className), children: message });
1286
+ return /* @__PURE__ */ jsx20("p", { className: cn("text-caption text-text-muted", className), children: message });
1231
1287
  }
1232
- return /* @__PURE__ */ jsxs13("div", { className: cn("flex flex-1 flex-col items-center justify-center gap-2", className), children: [
1233
- /* @__PURE__ */ jsx19("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx19(IconMessage2, { size: 16, stroke: 1.5 }) }),
1234
- /* @__PURE__ */ jsx19("p", { className: "text-body-2 text-text-secondary text-center", children: message })
1288
+ return /* @__PURE__ */ jsxs14("div", { className: cn("flex flex-1 flex-col items-center justify-center gap-2", className), children: [
1289
+ /* @__PURE__ */ jsx20("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx20(IconMessage2, { size: 16, stroke: 1.5 }) }),
1290
+ /* @__PURE__ */ jsx20("p", { className: "text-body-2 text-text-secondary text-center", children: message })
1235
1291
  ] });
1236
1292
  }
1237
1293
 
1238
1294
  // src/Field.tsx
1239
1295
  import { cloneElement, isValidElement } from "react";
1240
1296
  import { Field as BaseField2 } from "@base-ui/react/field";
1241
- import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
1297
+ import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
1242
1298
  var LINE_STYLES = {
1243
1299
  helper: "text-caption text-text-muted",
1244
1300
  warning: "text-caption text-warning-default",
@@ -1248,26 +1304,26 @@ function Field({ label, required = false, helper, error, children }) {
1248
1304
  const control = required && isValidElement(children) ? cloneElement(children, {
1249
1305
  "aria-required": children.props["aria-required"] ?? true
1250
1306
  }) : children;
1251
- return /* @__PURE__ */ jsxs14(BaseField2.Root, { invalid: !!error, className: "flex flex-col gap-2", children: [
1252
- /* @__PURE__ */ jsxs14(BaseField2.Label, { className: cn("text-input-label text-text-primary", required && "flex items-center"), children: [
1307
+ return /* @__PURE__ */ jsxs15(BaseField2.Root, { invalid: !!error, className: "flex flex-col gap-2", children: [
1308
+ /* @__PURE__ */ jsxs15(BaseField2.Label, { className: cn("text-input-label text-text-primary", required && "flex items-center"), children: [
1253
1309
  label,
1254
- required && /* @__PURE__ */ jsx20("span", { "aria-hidden": "true", className: "text-error-default ml-0.5", children: "*" })
1310
+ required && /* @__PURE__ */ jsx21("span", { "aria-hidden": "true", className: "text-error-default ml-0.5", children: "*" })
1255
1311
  ] }),
1256
- /* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1.5", children: [
1312
+ /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-1.5", children: [
1257
1313
  control,
1258
- error != null ? /* @__PURE__ */ jsx20(BaseField2.Error, { match: true, className: LINE_STYLES.error, children: error }) : helper != null ? /* @__PURE__ */ jsx20(BaseField2.Description, { className: LINE_STYLES.helper, children: helper }) : null
1314
+ error != null ? /* @__PURE__ */ jsx21(BaseField2.Error, { match: true, className: LINE_STYLES.error, children: error }) : helper != null ? /* @__PURE__ */ jsx21(BaseField2.Description, { className: LINE_STYLES.helper, children: helper }) : null
1259
1315
  ] })
1260
1316
  ] });
1261
1317
  }
1262
1318
  function FieldLine({ tone = "helper", children, className }) {
1263
- return /* @__PURE__ */ jsx20("p", { role: tone === "error" ? "alert" : "status", className: cn(LINE_STYLES[tone], className), children });
1319
+ return /* @__PURE__ */ jsx21("p", { role: tone === "error" ? "alert" : "status", className: cn(LINE_STYLES[tone], className), children });
1264
1320
  }
1265
1321
 
1266
1322
  // src/Form.tsx
1267
1323
  import { useLayoutEffect as useLayoutEffect2, useRef as useRef2 } from "react";
1268
1324
  import { Fieldset } from "@base-ui/react/fieldset";
1269
1325
  import { Form as BaseForm } from "@base-ui/react/form";
1270
- import { jsx as jsx21 } from "react/jsx-runtime";
1326
+ import { jsx as jsx22 } from "react/jsx-runtime";
1271
1327
  var CONTROL = 'input:not([type="hidden"]), textarea, select, button, [role="checkbox"], [role="combobox"], [tabindex]:not([tabindex="-1"])';
1272
1328
  var ONE_LINE = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
1273
1329
  function usable(element) {
@@ -1326,7 +1382,7 @@ function Form({ onSubmit, busy: ownBusy = false, enterSends = true, className, c
1326
1382
  const oneLine = ONE_LINE.has((target.getAttribute("type") ?? "").toLowerCase()) && target.getAttribute("role") !== "combobox";
1327
1383
  if (enterSends && oneLine) form.current?.requestSubmit();
1328
1384
  };
1329
- return /* @__PURE__ */ jsx21(
1385
+ return /* @__PURE__ */ jsx22(
1330
1386
  BaseForm,
1331
1387
  {
1332
1388
  ref: form,
@@ -1348,32 +1404,32 @@ function Form({ onSubmit, busy: ownBusy = false, enterSends = true, className, c
1348
1404
  if (busyNow.current) return;
1349
1405
  void onSubmit();
1350
1406
  },
1351
- children: /* @__PURE__ */ jsx21(Fieldset.Root, { disabled: busy, className: "contents", children: /* @__PURE__ */ jsx21(FormBusyContext.Provider, { value: busy, children }) })
1407
+ children: /* @__PURE__ */ jsx22(Fieldset.Root, { disabled: busy, className: "contents", children: /* @__PURE__ */ jsx22(FormBusyContext.Provider, { value: busy, children }) })
1352
1408
  }
1353
1409
  );
1354
1410
  }
1355
1411
 
1356
1412
  // src/Skeleton.tsx
1357
- import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
1413
+ import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
1358
1414
  function SkeletonBar({ className, style }) {
1359
- return /* @__PURE__ */ jsx22("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
1415
+ return /* @__PURE__ */ jsx23("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
1360
1416
  }
1361
1417
  var ROW_BAR_WIDTHS = [150, 100, 170, 120, 90, 140, 110, 160];
1362
1418
  function SkeletonRow({ barWidth = 130 }) {
1363
- return /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2 px-2 h-[32px] rounded-lg", children: [
1364
- /* @__PURE__ */ jsx22(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
1365
- /* @__PURE__ */ jsx22(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
1419
+ return /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 px-2 h-[32px] rounded-lg", children: [
1420
+ /* @__PURE__ */ jsx23(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
1421
+ /* @__PURE__ */ jsx23(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
1366
1422
  ] });
1367
1423
  }
1368
1424
  function SkeletonList({ rows = 8, className }) {
1369
- return /* @__PURE__ */ jsx22("div", { className: cn("flex flex-col gap-0.5 animate-skeleton-in", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx22(SkeletonRow, { barWidth: ROW_BAR_WIDTHS[i % ROW_BAR_WIDTHS.length] }, i)) });
1425
+ return /* @__PURE__ */ jsx23("div", { className: cn("flex flex-col gap-0.5 animate-skeleton-in", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx23(SkeletonRow, { barWidth: ROW_BAR_WIDTHS[i % ROW_BAR_WIDTHS.length] }, i)) });
1370
1426
  }
1371
1427
 
1372
1428
  // src/CommandPalette.tsx
1373
- import { Fragment as Fragment3, jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
1374
- var PaletteContext = createContext3(null);
1429
+ import { Fragment as Fragment3, jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
1430
+ var PaletteContext = createContext4(null);
1375
1431
  function usePalette(part) {
1376
- const palette = useContext3(PaletteContext);
1432
+ const palette = useContext4(PaletteContext);
1377
1433
  if (!palette) throw new Error(`[@estiva-app/ui] ${part} must be inside a CommandPalette.`);
1378
1434
  return palette;
1379
1435
  }
@@ -1396,9 +1452,9 @@ function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", chi
1396
1452
  return () => cancelAnimationFrame(frame);
1397
1453
  });
1398
1454
  const context = useMemo2(() => ({ where, modKey, popupRef }), [where, modKey]);
1399
- return /* @__PURE__ */ jsx23(Dialog.Root, { open, onOpenChange: (next) => onOpenChange(next), children: /* @__PURE__ */ jsxs16(Dialog.Portal, { children: [
1400
- /* @__PURE__ */ jsx23(Dialog.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
1401
- /* @__PURE__ */ jsx23(Dialog.Viewport, { className: "fixed inset-0 z-50 flex items-start justify-center pt-[16vh]", children: /* @__PURE__ */ jsx23(
1455
+ return /* @__PURE__ */ jsx24(Dialog.Root, { open, onOpenChange: (next) => onOpenChange(next), children: /* @__PURE__ */ jsxs17(Dialog.Portal, { children: [
1456
+ /* @__PURE__ */ jsx24(Dialog.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
1457
+ /* @__PURE__ */ jsx24(Dialog.Viewport, { className: "fixed inset-0 z-50 flex items-start justify-center pt-[16vh]", children: /* @__PURE__ */ jsx24(
1402
1458
  Dialog.Popup,
1403
1459
  {
1404
1460
  ref: popupRef,
@@ -1408,13 +1464,13 @@ function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", chi
1408
1464
  if (e.target === popupRef.current) firstControl(popupRef.current)?.focus();
1409
1465
  },
1410
1466
  className: "flex w-[658px] max-w-[calc(100vw-32px)] flex-col overflow-hidden rounded-lg border border-border-default bg-bg-elevated shadow-lg outline-none",
1411
- children: /* @__PURE__ */ jsx23(PaletteContext.Provider, { value: context, children })
1467
+ children: /* @__PURE__ */ jsx24(PaletteContext.Provider, { value: context, children })
1412
1468
  }
1413
1469
  ) })
1414
1470
  ] }) });
1415
1471
  }
1416
1472
  function LevelChip({ chip, onBack }) {
1417
- return /* @__PURE__ */ jsx23(InputChip, { label: chip.label, leading: chip.leading, onRemove: onBack, removeLabel: `Leave ${chip.label}`, truncate: true, className: "max-w-[272px] shrink-0" });
1473
+ return /* @__PURE__ */ jsx24(InputChip, { label: chip.label, leading: chip.leading, onRemove: onBack, removeLabel: `Leave ${chip.label}`, truncate: true, className: "max-w-[272px] shrink-0" });
1418
1474
  }
1419
1475
  function useBack(chip, popupRef) {
1420
1476
  return () => {
@@ -1425,10 +1481,10 @@ function useBack(chip, popupRef) {
1425
1481
  }
1426
1482
  function Footer({ keys }) {
1427
1483
  const { where } = usePalette("The footer");
1428
- return /* @__PURE__ */ jsxs16("div", { className: "flex h-9 shrink-0 items-center gap-4 border-t border-border-subtle px-5 text-caption text-text-secondary signal:font-mono signal:text-small signal:text-text-muted", children: [
1429
- /* @__PURE__ */ jsx23("span", { className: "min-w-0 flex-1 truncate", children: where }),
1430
- keys.map(([key, word]) => /* @__PURE__ */ jsxs16("span", { className: "flex shrink-0 items-center gap-1.5", children: [
1431
- /* @__PURE__ */ jsx23(Kbd, { children: key }),
1484
+ return /* @__PURE__ */ jsxs17("div", { className: "flex h-9 shrink-0 items-center gap-4 border-t border-border-subtle px-5 text-caption text-text-secondary signal:font-mono signal:text-small signal:text-text-muted", children: [
1485
+ /* @__PURE__ */ jsx24("span", { className: "min-w-0 flex-1 truncate", children: where }),
1486
+ keys.map(([key, word]) => /* @__PURE__ */ jsxs17("span", { className: "flex shrink-0 items-center gap-1.5", children: [
1487
+ /* @__PURE__ */ jsx24(Kbd, { children: key }),
1432
1488
  " ",
1433
1489
  word
1434
1490
  ] }, key))
@@ -1505,7 +1561,7 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
1505
1561
  ...chip && query === "" ? [["Backspace", "back"]] : [],
1506
1562
  ["Esc", "close"]
1507
1563
  ];
1508
- return /* @__PURE__ */ jsxs16(
1564
+ return /* @__PURE__ */ jsxs17(
1509
1565
  Autocomplete.Root,
1510
1566
  {
1511
1567
  items,
@@ -1528,10 +1584,10 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
1528
1584
  setLitId(id);
1529
1585
  },
1530
1586
  children: [
1531
- /* @__PURE__ */ jsxs16("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
1532
- /* @__PURE__ */ jsx23(IconSearch, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" }),
1533
- chip && /* @__PURE__ */ jsx23(LevelChip, { chip, onBack: back }),
1534
- /* @__PURE__ */ jsx23(
1587
+ /* @__PURE__ */ jsxs17("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
1588
+ /* @__PURE__ */ jsx24(IconSearch, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" }),
1589
+ chip && /* @__PURE__ */ jsx24(LevelChip, { chip, onBack: back }),
1590
+ /* @__PURE__ */ jsx24(
1535
1591
  Autocomplete.Input,
1536
1592
  {
1537
1593
  ref: inputRef,
@@ -1543,43 +1599,43 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
1543
1599
  }
1544
1600
  )
1545
1601
  ] }),
1546
- /* @__PURE__ */ jsxs16(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col p-2", children: [
1547
- children != null && /* @__PURE__ */ jsx23("div", { className: "flex flex-col gap-2 px-3 pb-2 pt-3", children }),
1548
- /* @__PURE__ */ jsx23(Autocomplete.List, { className: "flex flex-col", children: (group) => /* @__PURE__ */ jsxs16(Autocomplete.Group, { items: group.items, className: "flex flex-col", children: [
1549
- /* @__PURE__ */ jsx23(Autocomplete.GroupLabel, { className: "flex h-7 shrink-0 items-center px-3", children: /* @__PURE__ */ jsx23(SectionLabel, { className: "text-text-secondary", children: group.value }) }),
1550
- /* @__PURE__ */ jsx23(Autocomplete.Collection, { children: (row) => (
1602
+ /* @__PURE__ */ jsxs17(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col p-2", children: [
1603
+ children != null && /* @__PURE__ */ jsx24("div", { className: "flex flex-col gap-2 px-3 pb-2 pt-3", children }),
1604
+ /* @__PURE__ */ jsx24(Autocomplete.List, { className: "flex flex-col", children: (group) => /* @__PURE__ */ jsxs17(Autocomplete.Group, { items: group.items, className: "flex flex-col", children: [
1605
+ /* @__PURE__ */ jsx24(Autocomplete.GroupLabel, { className: "flex h-7 shrink-0 items-center px-3", children: /* @__PURE__ */ jsx24(SectionLabel, { tone: "secondary", children: group.value }) }),
1606
+ /* @__PURE__ */ jsx24(Autocomplete.Collection, { children: (row) => (
1551
1607
  /* The menu row, as the list's own option — the way Select
1552
1608
  puts it on `Select.Item`. One row, two parts. */
1553
- /* @__PURE__ */ jsx23(Autocomplete.Item, { value: row, onClick: () => row.onSelect(), className: menuItemClassName({ size: "tall" }), children: /* @__PURE__ */ jsx23(
1609
+ /* @__PURE__ */ jsx24(Autocomplete.Item, { value: row, onClick: () => row.onSelect(), className: menuItemClassName({ size: "tall" }), children: /* @__PURE__ */ jsx24(
1554
1610
  MenuItemBody,
1555
1611
  {
1556
1612
  size: "tall",
1557
1613
  label: row.label,
1558
1614
  description: row.description,
1559
- leading: /* @__PURE__ */ jsx23(RowLeading, { row }),
1615
+ leading: /* @__PURE__ */ jsx24(RowLeading, { row }),
1560
1616
  submenu: !!row.onGoIn,
1561
- hint: row.onGoIn ? /* @__PURE__ */ jsx23(Kbd, { children: "Tab" }) : /* @__PURE__ */ jsx23(EnterHint, {})
1617
+ hint: row.onGoIn ? /* @__PURE__ */ jsx24(Kbd, { children: "Tab" }) : /* @__PURE__ */ jsx24(EnterHint, {})
1562
1618
  }
1563
1619
  ) }, row.id)
1564
1620
  ) })
1565
1621
  ] }, group.value) }),
1566
- /* @__PURE__ */ jsx23(Autocomplete.Status, { className: "flex items-center gap-2 px-3 [&:not(:empty)]:h-8", children: pending && /* @__PURE__ */ jsxs16(Fragment3, { children: [
1567
- /* @__PURE__ */ jsx23(IconLoader22, { size: 12, stroke: 1.5, className: "shrink-0 animate-spin text-text-muted" }),
1568
- /* @__PURE__ */ jsx23("span", { className: "text-caption text-text-muted", children: pending })
1622
+ /* @__PURE__ */ jsx24(Autocomplete.Status, { className: "flex items-center gap-2 px-3 [&:not(:empty)]:h-8", children: pending && /* @__PURE__ */ jsxs17(Fragment3, { children: [
1623
+ /* @__PURE__ */ jsx24(IconLoader22, { size: 12, stroke: 1.5, className: "shrink-0 animate-spin text-text-muted" }),
1624
+ /* @__PURE__ */ jsx24("span", { className: "text-caption text-text-muted", children: pending })
1569
1625
  ] }) }),
1570
- notes.map((note) => /* @__PURE__ */ jsx23("div", { className: "flex min-h-8 items-center px-3", children: /* @__PURE__ */ jsx23(FieldLine, { children: note }) }, note)),
1571
- /* @__PURE__ */ jsx23(Autocomplete.Empty, { className: "flex items-center px-3 [&:not(:empty)]:min-h-10", children: empty && /* @__PURE__ */ jsx23(EmptyState, { scope: "section", message: empty }) })
1626
+ notes.map((note) => /* @__PURE__ */ jsx24("div", { className: "flex min-h-8 items-center px-3", children: /* @__PURE__ */ jsx24(FieldLine, { children: note }) }, note)),
1627
+ /* @__PURE__ */ jsx24(Autocomplete.Empty, { className: "flex items-center px-3 [&:not(:empty)]:min-h-10", children: empty && /* @__PURE__ */ jsx24(EmptyState, { scope: "section", message: empty }) })
1572
1628
  ] }),
1573
- /* @__PURE__ */ jsx23(Footer, { keys })
1629
+ /* @__PURE__ */ jsx24(Footer, { keys })
1574
1630
  ]
1575
1631
  }
1576
1632
  );
1577
1633
  }
1578
1634
  function RowLeading({ row }) {
1579
1635
  if (row.icon != null) {
1580
- return /* @__PURE__ */ jsx23("span", { className: "flex size-8 items-center justify-center rounded-sm bg-bg-inset text-text-secondary", children: row.icon });
1636
+ return /* @__PURE__ */ jsx24("span", { className: "flex size-8 items-center justify-center rounded-sm bg-bg-inset text-text-secondary", children: row.icon });
1581
1637
  }
1582
- return /* @__PURE__ */ jsx23("span", { className: "flex size-8 items-center justify-center", children: row.leading });
1638
+ return /* @__PURE__ */ jsx24("span", { className: "flex size-8 items-center justify-center", children: row.leading });
1583
1639
  }
1584
1640
  var TEXT_TYPES = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
1585
1641
  function isTextField(el) {
@@ -1621,56 +1677,56 @@ function CommandPaletteForm({ chip, icon, submitLabel, onSubmit, submitWaits, wo
1621
1677
  ...backNamed ? [["Backspace", "back"]] : [],
1622
1678
  ["Esc", "close"]
1623
1679
  ];
1624
- return /* @__PURE__ */ jsxs16("div", { ref: frameRef, tabIndex: -1, onKeyDown, onFocus: measure, onBlur: measure, onInput: measure, className: "flex min-h-0 flex-col outline-none", children: [
1625
- /* @__PURE__ */ jsxs16("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
1626
- icon != null && /* @__PURE__ */ jsx23("span", { className: "flex shrink-0 items-center text-text-secondary", children: icon }),
1627
- /* @__PURE__ */ jsx23(LevelChip, { chip, onBack: back })
1680
+ return /* @__PURE__ */ jsxs17("div", { ref: frameRef, tabIndex: -1, onKeyDown, onFocus: measure, onBlur: measure, onInput: measure, className: "flex min-h-0 flex-col outline-none", children: [
1681
+ /* @__PURE__ */ jsxs17("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
1682
+ icon != null && /* @__PURE__ */ jsx24("span", { className: "flex shrink-0 items-center text-text-secondary", children: icon }),
1683
+ /* @__PURE__ */ jsx24(LevelChip, { chip, onBack: back })
1628
1684
  ] }),
1629
- /* @__PURE__ */ jsxs16(Form, { "data-command-palette-fields": "", busy, enterSends: false, onSubmit: submit, className: "flex min-h-0 flex-col", children: [
1630
- /* @__PURE__ */ jsx23(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col px-5 py-4", children: /* @__PURE__ */ jsx23("div", { className: "flex flex-col gap-4", children }) }),
1631
- /* @__PURE__ */ jsxs16("div", { className: "flex shrink-0 items-center gap-3 px-5 pb-4", children: [
1632
- /* @__PURE__ */ jsx23("div", { className: "min-w-0 flex-1", children: working ? /* @__PURE__ */ jsx23(FieldLine, { children: working.line }) : error ? /* @__PURE__ */ jsx23(FieldLine, { tone: "error", children: error }) : null }),
1633
- /* @__PURE__ */ jsx23(
1685
+ /* @__PURE__ */ jsxs17(Form, { "data-command-palette-fields": "", busy, enterSends: false, onSubmit: submit, className: "flex min-h-0 flex-col", children: [
1686
+ /* @__PURE__ */ jsx24(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col px-5 py-4", children: /* @__PURE__ */ jsx24("div", { className: "flex flex-col gap-4", children }) }),
1687
+ /* @__PURE__ */ jsxs17("div", { className: "flex shrink-0 items-center gap-3 px-5 pb-4", children: [
1688
+ /* @__PURE__ */ jsx24("div", { className: "min-w-0 flex-1", children: working ? /* @__PURE__ */ jsx24(FieldLine, { children: working.line }) : error ? /* @__PURE__ */ jsx24(FieldLine, { tone: "error", children: error }) : null }),
1689
+ /* @__PURE__ */ jsx24(
1634
1690
  Button,
1635
1691
  {
1636
1692
  type: "submit",
1637
1693
  variant: "primary",
1638
1694
  disabled: busy,
1639
1695
  disabledReason: busy ? void 0 : submitWaits,
1640
- leadingIcon: busy ? /* @__PURE__ */ jsx23(IconLoader22, { size: 16, stroke: 1.5, className: "animate-spin" }) : void 0,
1696
+ leadingIcon: busy ? /* @__PURE__ */ jsx24(IconLoader22, { size: 16, stroke: 1.5, className: "animate-spin" }) : void 0,
1641
1697
  children: working ? working.button : submitLabel
1642
1698
  }
1643
1699
  )
1644
1700
  ] })
1645
1701
  ] }),
1646
- /* @__PURE__ */ jsx23(Footer, { keys })
1702
+ /* @__PURE__ */ jsx24(Footer, { keys })
1647
1703
  ] });
1648
1704
  }
1649
1705
  var BAR_WIDTHS = ["w-4/5", "w-3/5", "w-2/3"];
1650
1706
  function CommandPaletteWorking({ children, bars = 2 }) {
1651
- return /* @__PURE__ */ jsxs16("div", { role: "status", className: "flex flex-col gap-2", children: [
1652
- /* @__PURE__ */ jsxs16("span", { className: "flex items-center gap-2 text-caption text-text-secondary", children: [
1653
- /* @__PURE__ */ jsx23(IconLoader22, { size: 14, stroke: 1.5, className: "shrink-0 animate-spin" }),
1707
+ return /* @__PURE__ */ jsxs17("div", { role: "status", className: "flex flex-col gap-2", children: [
1708
+ /* @__PURE__ */ jsxs17("span", { className: "flex items-center gap-2 text-caption text-text-secondary", children: [
1709
+ /* @__PURE__ */ jsx24(IconLoader22, { size: 14, stroke: 1.5, className: "shrink-0 animate-spin" }),
1654
1710
  children
1655
1711
  ] }),
1656
- BAR_WIDTHS.slice(0, bars).map((width) => /* @__PURE__ */ jsx23(SkeletonBar, { className: cn("h-3", width) }, width))
1712
+ BAR_WIDTHS.slice(0, bars).map((width) => /* @__PURE__ */ jsx24(SkeletonBar, { className: cn("h-3", width) }, width))
1657
1713
  ] });
1658
1714
  }
1659
1715
  function CommandPaletteAnswer({ children, note }) {
1660
1716
  const paragraphs = children.split(/\n\s*\n/).filter((p) => p.trim() !== "");
1661
- return /* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-2", children: [
1662
- paragraphs.map((paragraph, i) => /* @__PURE__ */ jsx23("p", { className: "whitespace-pre-wrap text-body-2 text-text-primary", children: paragraph.split(/\s*(\[\d+\])/).map(
1663
- (part, j) => /^\[\d+\]$/.test(part) ? /* @__PURE__ */ jsx23("sup", { className: "ml-0.5 font-mono text-small text-accent-primary", children: part.slice(1, -1) }, j) : part
1717
+ return /* @__PURE__ */ jsxs17("div", { className: "flex flex-col gap-2", children: [
1718
+ paragraphs.map((paragraph, i) => /* @__PURE__ */ jsx24("p", { className: "whitespace-pre-wrap text-body-2 text-text-primary", children: paragraph.split(/\s*(\[\d+\])/).map(
1719
+ (part, j) => /^\[\d+\]$/.test(part) ? /* @__PURE__ */ jsx24("sup", { className: "ml-0.5 font-mono text-small text-accent-primary", children: part.slice(1, -1) }, j) : part
1664
1720
  ) }, i)),
1665
- note && /* @__PURE__ */ jsx23(FieldLine, { children: note })
1721
+ note && /* @__PURE__ */ jsx24(FieldLine, { children: note })
1666
1722
  ] });
1667
1723
  }
1668
1724
  function CommandPaletteQuote({ children }) {
1669
- return /* @__PURE__ */ jsx23("p", { className: "whitespace-pre-wrap border-l-2 border-border-default pl-3 text-body-2 text-text-primary", children });
1725
+ return /* @__PURE__ */ jsx24("p", { className: "whitespace-pre-wrap border-l-2 border-border-default pl-3 text-body-2 text-text-primary", children });
1670
1726
  }
1671
1727
 
1672
1728
  // src/InlineChip.tsx
1673
- import { Fragment as Fragment4, jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
1729
+ import { Fragment as Fragment4, jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
1674
1730
  var INLINE_CHIP_CLASSES = "inline-flex h-[1.4em] items-center gap-1 rounded-sm px-1 mx-0.5 align-top text-body-2 font-normal select-none";
1675
1731
  var INLINE_CHIP_TONE_CLASSES = {
1676
1732
  /** A thing or a place — anything that is not a person. */
@@ -1692,49 +1748,20 @@ function inlineChipClassName(tone, className) {
1692
1748
  return cn(INLINE_CHIP_CLASSES, INLINE_CHIP_TONE_CLASSES[tone], className);
1693
1749
  }
1694
1750
  function InlineChip({ tone = "neutral", icon, href, className, children, ...props }) {
1695
- const body = /* @__PURE__ */ jsxs17(Fragment4, { children: [
1696
- icon && /* @__PURE__ */ jsx24("span", { className: "flex size-4 shrink-0 items-center justify-center text-text-secondary", children: icon }),
1751
+ const body = /* @__PURE__ */ jsxs18(Fragment4, { children: [
1752
+ icon && /* @__PURE__ */ jsx25("span", { className: "flex size-4 shrink-0 items-center justify-center text-text-secondary", children: icon }),
1697
1753
  children
1698
1754
  ] });
1699
1755
  const classes = inlineChipClassName(tone, className);
1700
1756
  if (href === void 0) {
1701
- return /* @__PURE__ */ jsx24("span", { className: classes, ...props, children: body });
1757
+ return /* @__PURE__ */ jsx25("span", { className: classes, ...props, children: body });
1702
1758
  }
1703
- return /* @__PURE__ */ jsx24("a", { href, className: classes, ...props, children: body });
1759
+ return /* @__PURE__ */ jsx25("a", { href, className: classes, ...props, children: body });
1704
1760
  }
1705
1761
 
1706
1762
  // src/IdentityMenu.tsx
1707
1763
  import { useCallback, useRef as useRef4 } from "react";
1708
1764
 
1709
- // src/Divider.tsx
1710
- import { Separator } from "@base-ui/react/separator";
1711
- import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
1712
- function Divider({ orientation = "horizontal", label, tone = "default", className }) {
1713
- if (label && orientation === "horizontal") {
1714
- const line = tone === "warning" ? "bg-warning-muted" : "bg-border-subtle";
1715
- return /* @__PURE__ */ jsxs18(
1716
- Separator,
1717
- {
1718
- orientation: "horizontal",
1719
- "aria-label": label,
1720
- className: cn("flex shrink-0 items-center gap-2 mx-3", className),
1721
- children: [
1722
- /* @__PURE__ */ jsx25("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
1723
- /* @__PURE__ */ jsx25("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
1724
- /* @__PURE__ */ jsx25("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
1725
- ]
1726
- }
1727
- );
1728
- }
1729
- return /* @__PURE__ */ jsx25(
1730
- Separator,
1731
- {
1732
- orientation,
1733
- className: cn("shrink-0 bg-border-subtle", orientation === "horizontal" ? "h-px mx-3" : "w-px self-stretch", className)
1734
- }
1735
- );
1736
- }
1737
-
1738
1765
  // src/Person.tsx
1739
1766
  import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
1740
1767
  function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
@@ -1807,7 +1834,7 @@ function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, on
1807
1834
  const appRows = typeof children === "function" ? children(onClose) : children;
1808
1835
  return /* @__PURE__ */ jsxs21(Fragment5, { children: [
1809
1836
  /* @__PURE__ */ jsxs21(MenuSection, { label: signedIn ? "Signed in as" : "Acting as", children: [
1810
- /* @__PURE__ */ jsx28(MenuRow, { children: /* @__PURE__ */ jsx28(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28, className: "text-body-2-strong" }) }),
1837
+ /* @__PURE__ */ jsx28(MenuRow, { children: /* @__PURE__ */ jsx28("div", { className: "flex min-w-0 text-body-2-strong", children: /* @__PURE__ */ jsx28(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28 }) }) }),
1811
1838
  /* @__PURE__ */ jsx28(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." }),
1812
1839
  me.email && /* @__PURE__ */ jsxs21(Note, { children: [
1813
1840
  me.email,
@@ -2098,14 +2125,9 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
2098
2125
  }
2099
2126
  )
2100
2127
  ] }),
2101
- bodyMaxHeight ? /* @__PURE__ */ jsx33(
2102
- ScrollArea,
2103
- {
2104
- className: cn(footer != null && "border-b border-border-subtle"),
2105
- viewportClassName: bodyMaxHeight,
2106
- contentClassName: cn("pl-5 pr-4 py-4", bodyClassName),
2107
- children
2108
- }
2128
+ bodyMaxHeight ? (
2129
+ // The line above the footer on a box of the shell's own, not pushed into ScrollArea (UIG-9).
2130
+ /* @__PURE__ */ jsx33("div", { className: cn(footer != null && "border-b border-border-subtle"), children: /* @__PURE__ */ jsx33(ScrollArea, { viewportClassName: bodyMaxHeight, contentClassName: cn("pl-5 pr-4 py-4", bodyClassName), children }) })
2109
2131
  ) : /* @__PURE__ */ jsx33("div", { className: cn("pl-5 pr-4 py-4", footer != null && "border-b border-border-subtle", bodyClassName), children }),
2110
2132
  footer != null && /* @__PURE__ */ jsx33("div", { className: "h-12 flex items-center justify-end gap-2 pl-5 pr-4 shrink-0", children: footer })
2111
2133
  ]
@@ -2135,12 +2157,11 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
2135
2157
  alert: true,
2136
2158
  title,
2137
2159
  onClose,
2138
- bodyClassName: "flex flex-col gap-3 text-body-2 text-text-primary",
2139
2160
  footer: /* @__PURE__ */ jsxs24(Fragment6, { children: [
2140
2161
  /* @__PURE__ */ jsx34(Button, { variant: "muted", onClick: onClose, disabled: busy, children: "Cancel" }),
2141
2162
  /* @__PURE__ */ jsx34(Button, { variant: destructive ? "destructive" : "primary", onClick: () => void confirm(), disabled: busy, children: confirmLabel })
2142
2163
  ] }),
2143
- children
2164
+ children: /* @__PURE__ */ jsx34("div", { className: "flex flex-col gap-3 text-body-2 text-text-primary", children })
2144
2165
  }
2145
2166
  );
2146
2167
  }
@@ -2319,8 +2340,11 @@ function Breadcrumb({ items, className }) {
2319
2340
  const crumb = item.href ? (
2320
2341
  // `plain` adds no look of its own: a crumb keeps the trail's size and
2321
2342
  // tone, and brightens on hover. The package's own Link, so a trail
2322
- // follows whatever a link learns to do (UIG-5).
2323
- /* @__PURE__ */ jsx37(Link, { ref: setLabelRef, variant: "plain", href: item.href, onClick: item.onClick, className: cn(text, "hover:text-text-primary"), children: item.label })
2343
+ // follows whatever a link learns to do (UIG-5). The size and tone are
2344
+ // on a box around it, which the link takes them from, rather than
2345
+ // pushed into it (UIG-9); the link is still the one element that
2346
+ // truncates and is measured.
2347
+ /* @__PURE__ */ jsx37("span", { className: cn("flex min-w-0", item.mono && "shrink-0 font-mono text-caption", tone, "hover:text-text-primary"), children: /* @__PURE__ */ jsx37(Link, { ref: setLabelRef, variant: "plain", truncate: true, href: item.href, onClick: item.onClick, children: item.label }) })
2324
2348
  ) : /* @__PURE__ */ jsx37("span", { ref: setLabelRef, className: text, "aria-current": last ? "page" : void 0, children: item.label });
2325
2349
  return /* @__PURE__ */ jsxs25(Fragment7, { children: [
2326
2350
  index > 0 && /* @__PURE__ */ jsx37("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
@@ -2403,8 +2427,8 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
2403
2427
  ScrollArea,
2404
2428
  {
2405
2429
  viewportClassName: maxHeight ?? "max-h-[var(--available-height)]",
2406
- contentClassName: cn("flex flex-col p-2 [&>[role=separator]]:mx-0", contentClassName),
2407
- children
2430
+ contentClassName: cn("flex flex-col p-2", contentClassName),
2431
+ children: /* @__PURE__ */ jsx39(DividerInPanel.Provider, { value: true, children })
2408
2432
  }
2409
2433
  )
2410
2434
  }
@@ -2476,8 +2500,8 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
2476
2500
  "aria-label": option.label,
2477
2501
  tooltip: option.label,
2478
2502
  onClick: () => onSelect(option.emoji),
2479
- className: "size-7 text-h3 leading-none",
2480
- children: /* @__PURE__ */ jsx41("span", { "aria-hidden": "true", children: option.emoji })
2503
+ className: "size-7",
2504
+ children: /* @__PURE__ */ jsx41("span", { "aria-hidden": "true", className: "text-h3 leading-none", children: option.emoji })
2481
2505
  },
2482
2506
  option.emoji
2483
2507
  )
@@ -2515,7 +2539,7 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
2515
2539
  {
2516
2540
  className: cn("w-[360px] p-3 outline-none", className),
2517
2541
  render: /* @__PURE__ */ jsx42(MenuPanel, {}),
2518
- children: /* @__PURE__ */ jsx42(ScrollArea, { viewportClassName: "max-h-[calc(min(300px,var(--available-height))_-_1.5rem)]", contentClassName: "flex flex-col gap-3 [&>*]:shrink-0", children: content })
2542
+ children: /* @__PURE__ */ jsx42(ScrollArea, { viewportClassName: "max-h-[calc(min(300px,var(--available-height))_-_1.5rem)]", contentClassName: "flex flex-col gap-3", children: content })
2519
2543
  }
2520
2544
  )
2521
2545
  }
@@ -2807,7 +2831,7 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
2807
2831
  }
2808
2832
 
2809
2833
  // src/Toast.tsx
2810
- import { createContext as createContext4, useContext as useContext4, useMemo as useMemo4 } from "react";
2834
+ import { createContext as createContext5, useContext as useContext5, useMemo as useMemo4 } from "react";
2811
2835
  import { Toast as BaseToast } from "@base-ui/react/toast";
2812
2836
  import { IconAlertCircle as IconAlertCircle2, IconCircleCheck, IconCircleX } from "@tabler/icons-react";
2813
2837
  import { jsx as jsx52, jsxs as jsxs36 } from "react/jsx-runtime";
@@ -2858,7 +2882,7 @@ function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAct
2858
2882
  hasAction && /* @__PURE__ */ jsx52(Button, { variant: "outlined", size: "small", onClick: onAction, children: actionLabel })
2859
2883
  ] });
2860
2884
  }
2861
- var ToastContext = createContext4(null);
2885
+ var ToastContext = createContext5(null);
2862
2886
  var VISIBLE_TOASTS = 3;
2863
2887
  function ToastProvider({ children }) {
2864
2888
  const manager = useMemo4(() => BaseToast.createToastManager(), []);
@@ -2914,7 +2938,7 @@ function ToastList() {
2914
2938
  });
2915
2939
  }
2916
2940
  function useToast() {
2917
- const ctx = useContext4(ToastContext);
2941
+ const ctx = useContext5(ToastContext);
2918
2942
  if (!ctx) throw new Error("useToast must be used within ToastProvider");
2919
2943
  return ctx;
2920
2944
  }