@estiva-app/ui 0.18.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 (84) hide show
  1. package/README.md +13 -5
  2. package/dist/AttachmentCard.d.ts.map +1 -1
  3. package/dist/Breadcrumb.d.ts.map +1 -1
  4. package/dist/Button.d.ts +6 -1
  5. package/dist/Button.d.ts.map +1 -1
  6. package/dist/Card.d.ts +6 -1
  7. package/dist/Card.d.ts.map +1 -1
  8. package/dist/Checkbox.d.ts +16 -1
  9. package/dist/Checkbox.d.ts.map +1 -1
  10. package/dist/DialogShell.d.ts.map +1 -1
  11. package/dist/Divider.d.ts +7 -0
  12. package/dist/Divider.d.ts.map +1 -1
  13. package/dist/IconButton.d.ts +12 -2
  14. package/dist/IconButton.d.ts.map +1 -1
  15. package/dist/IdentityMenu.d.ts.map +1 -1
  16. package/dist/Link.d.ts +6 -1
  17. package/dist/Link.d.ts.map +1 -1
  18. package/dist/Menu.d.ts.map +1 -1
  19. package/dist/Popover.d.ts.map +1 -1
  20. package/dist/ReactionPicker.d.ts.map +1 -1
  21. package/dist/ScrollArea.d.ts +6 -0
  22. package/dist/ScrollArea.d.ts.map +1 -1
  23. package/dist/SectionLabel.d.ts +6 -1
  24. package/dist/SectionLabel.d.ts.map +1 -1
  25. package/dist/Tooltip.d.ts.map +1 -1
  26. package/dist/eslint/index.d.ts +4 -0
  27. package/dist/eslint/index.d.ts.map +1 -1
  28. package/dist/eslint/index.js +968 -3
  29. package/dist/eslint/index.js.map +4 -4
  30. package/dist/eslint/no-rebuilt-behaviour.d.ts +88 -0
  31. package/dist/eslint/no-rebuilt-behaviour.d.ts.map +1 -0
  32. package/dist/eslint/no-restyled-part.d.ts +81 -0
  33. package/dist/eslint/no-restyled-part.d.ts.map +1 -0
  34. package/dist/index.js +300 -268
  35. package/dist/index.js.map +4 -4
  36. package/package.json +1 -1
  37. package/src/AttachmentCard.tsx +7 -2
  38. package/src/Banner.tsx +2 -2
  39. package/src/Breadcrumb.tsx +9 -4
  40. package/src/Button.mdx +7 -0
  41. package/src/Button.stories.tsx +4 -1
  42. package/src/Button.tsx +10 -2
  43. package/src/Card.mdx +7 -0
  44. package/src/Card.stories.tsx +11 -0
  45. package/src/Card.tsx +8 -0
  46. package/src/Checkbox.mdx +20 -1
  47. package/src/Checkbox.stories.tsx +44 -0
  48. package/src/Checkbox.test.tsx +63 -0
  49. package/src/Checkbox.tsx +30 -1
  50. package/src/CommandPalette.tsx +1 -1
  51. package/src/ConfirmDialog.tsx +2 -2
  52. package/src/DialogShell.tsx +6 -7
  53. package/src/Divider.mdx +3 -0
  54. package/src/Divider.tsx +12 -2
  55. package/src/EditableText.mdx +5 -0
  56. package/src/IconButton.mdx +9 -0
  57. package/src/IconButton.stories.tsx +10 -1
  58. package/src/IconButton.tsx +22 -3
  59. package/src/IdentityMenu.tsx +4 -1
  60. package/src/Link.mdx +6 -0
  61. package/src/Link.stories.tsx +12 -0
  62. package/src/Link.tsx +7 -2
  63. package/src/Menu.stories.tsx +1 -1
  64. package/src/Menu.test.tsx +2 -2
  65. package/src/Menu.tsx +6 -3
  66. package/src/Person.stories.tsx +5 -5
  67. package/src/Popover.test.tsx +2 -2
  68. package/src/Popover.tsx +3 -2
  69. package/src/PreviewCard.tsx +1 -1
  70. package/src/Property.stories.tsx +2 -2
  71. package/src/ReactionPicker.tsx +6 -3
  72. package/src/ScrollArea.stories.tsx +38 -6
  73. package/src/ScrollArea.tsx +7 -1
  74. package/src/SectionLabel.mdx +3 -2
  75. package/src/SectionLabel.stories.tsx +3 -0
  76. package/src/SectionLabel.tsx +7 -2
  77. package/src/Tooltip.tsx +12 -14
  78. package/src/eslint/index.test.ts +58 -9
  79. package/src/eslint/index.ts +19 -3
  80. package/src/eslint/no-rebuilt-behaviour.test.ts +276 -0
  81. package/src/eslint/no-rebuilt-behaviour.ts +593 -0
  82. package/src/eslint/no-restyled-part.test.ts +301 -0
  83. package/src/eslint/no-restyled-part.ts +647 -0
  84. package/stories/Choosing.mdx +1 -1
package/dist/index.js CHANGED
@@ -38,7 +38,7 @@ function cn(...inputs) {
38
38
  // src/ScrollArea.tsx
39
39
  import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area";
40
40
  import { jsx, jsxs } from "react/jsx-runtime";
41
- 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";
41
+ var BAR = "z-10 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";
42
42
  var THUMB = "rounded-full bg-border-strong";
43
43
  function ScrollArea({ orientation = "vertical", className, viewportClassName, contentClassName, viewportRef, onScroll, children }) {
44
44
  const vertical = orientation !== "horizontal";
@@ -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,
@@ -755,7 +778,8 @@ function squareClasses(checked, disabled, interactive, className) {
755
778
  }
756
779
  var tickClasses = (checked) => cn("flex", !checked && "invisible");
757
780
  var WORDS_CLASSES = "text-body-2 text-text-primary";
758
- function Checkbox({ checked, onChange, disabled: ownDisabled = false, label, className, ...aria }) {
781
+ var ROW_CLASSES = "flex shrink-0 items-center gap-3 h-10 px-3 rounded-lg transition-colors";
782
+ function Checkbox({ checked, onChange, disabled: ownDisabled = false, label, row, leading, className, ...aria }) {
759
783
  const formBusy = useFormBusy();
760
784
  const disabled = ownDisabled || formBusy;
761
785
  if (!onChange) {
@@ -780,6 +804,13 @@ function Checkbox({ checked, onChange, disabled: ownDisabled = false, label, cla
780
804
  }
781
805
  );
782
806
  if (label === void 0) return box;
807
+ if (row) {
808
+ return /* @__PURE__ */ jsx14(BaseField.Root, { disabled, children: /* @__PURE__ */ jsxs9(BaseField.Label, { className: cn(ROW_CLASSES, checked && "bg-bg-selected", !disabled && "cursor-pointer hover:bg-bg-hover"), children: [
809
+ leading,
810
+ /* @__PURE__ */ jsx14("span", { className: cn("flex-1 min-w-0 truncate", WORDS_CLASSES), children: label }),
811
+ box
812
+ ] }) });
813
+ }
783
814
  return /* @__PURE__ */ jsx14(BaseField.Root, { disabled, children: /* @__PURE__ */ jsxs9(BaseField.Label, { className: cn("flex items-center gap-2", !disabled && "cursor-pointer"), children: [
784
815
  box,
785
816
  /* @__PURE__ */ jsx14("span", { className: WORDS_CLASSES, children: label })
@@ -814,8 +845,8 @@ function Chip({ type = "neutral", label, leadingIcon, trailingIcon, className })
814
845
 
815
846
  // src/CommandPalette.tsx
816
847
  import {
817
- createContext as createContext3,
818
- useContext as useContext3,
848
+ createContext as createContext4,
849
+ useContext as useContext4,
819
850
  useEffect,
820
851
  useLayoutEffect as useLayoutEffect3,
821
852
  useMemo as useMemo2,
@@ -833,10 +864,42 @@ import { Combobox } from "@base-ui/react/combobox";
833
864
  import { IconX as IconX3 } from "@tabler/icons-react";
834
865
 
835
866
  // src/Menu.tsx
836
- import { createContext as createContext2, useContext as useContext2 } from "react";
867
+ import { createContext as createContext3, useContext as useContext3 } from "react";
837
868
  import { IconChevronRight } from "@tabler/icons-react";
838
869
  import { Menu as BaseMenu } from "@base-ui/react/menu";
839
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
+
840
903
  // src/triggerDisabled.ts
841
904
  function triggerDisabled(trigger) {
842
905
  const props = trigger.props;
@@ -844,13 +907,14 @@ function triggerDisabled(trigger) {
844
907
  }
845
908
 
846
909
  // src/SectionLabel.tsx
847
- import { jsx as jsx16 } from "react/jsx-runtime";
848
- function SectionLabel({ children, className }) {
849
- return /* @__PURE__ */ jsx16(
910
+ import { jsx as jsx17 } from "react/jsx-runtime";
911
+ function SectionLabel({ children, tone = "primary", className }) {
912
+ return /* @__PURE__ */ jsx17(
850
913
  "span",
851
914
  {
852
915
  className: cn(
853
- "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",
854
918
  className
855
919
  ),
856
920
  children
@@ -859,10 +923,10 @@ function SectionLabel({ children, className }) {
859
923
  }
860
924
 
861
925
  // src/Menu.tsx
862
- import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
863
- var MenuContext = createContext2(null);
926
+ import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
927
+ var MenuContext = createContext3(null);
864
928
  function MenuPanel({ children, className, ...props }) {
865
- return /* @__PURE__ */ jsx17(
929
+ return /* @__PURE__ */ jsx18(
866
930
  "div",
867
931
  {
868
932
  className: cn(
@@ -892,7 +956,7 @@ var VIEWPORT_PAD2 = 8;
892
956
  var HOVER_OPEN_DELAY = 0;
893
957
  var HOVER_CLOSE_DELAY = 150;
894
958
  function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange, actionsRef, children, className, contentClassName }) {
895
- return /* @__PURE__ */ jsxs11(
959
+ return /* @__PURE__ */ jsxs12(
896
960
  BaseMenu.Root,
897
961
  {
898
962
  open,
@@ -900,7 +964,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
900
964
  actionsRef,
901
965
  modal: false,
902
966
  children: [
903
- /* @__PURE__ */ jsx17(
967
+ /* @__PURE__ */ jsx18(
904
968
  BaseMenu.Trigger,
905
969
  {
906
970
  render: trigger,
@@ -910,7 +974,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
910
974
  closeDelay: HOVER_CLOSE_DELAY
911
975
  }
912
976
  ),
913
- /* @__PURE__ */ jsx17(BaseMenu.Portal, { children: /* @__PURE__ */ jsx17(
977
+ /* @__PURE__ */ jsx18(BaseMenu.Portal, { children: /* @__PURE__ */ jsx18(
914
978
  BaseMenu.Positioner,
915
979
  {
916
980
  side: "bottom",
@@ -918,13 +982,13 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
918
982
  sideOffset: GAP2,
919
983
  collisionPadding: VIEWPORT_PAD2,
920
984
  className: "z-50 data-[anchor-hidden]:hidden",
921
- children: /* @__PURE__ */ jsx17(
985
+ children: /* @__PURE__ */ jsx18(
922
986
  BaseMenu.Popup,
923
987
  {
924
988
  "data-interactive": true,
925
989
  className: cn("min-w-[180px] outline-none p-0", className),
926
- render: /* @__PURE__ */ jsx17(MenuPanel, {}),
927
- 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 }) }) })
928
992
  }
929
993
  )
930
994
  }
@@ -934,26 +998,26 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
934
998
  );
935
999
  }
936
1000
  function MenuSub({ label, leading, selected, children, className }) {
937
- const menu = useContext2(MenuContext);
1001
+ const menu = useContext3(MenuContext);
938
1002
  if (!isProduction() && menu?.openOnHover) {
939
1003
  console.error(
940
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".'
941
1005
  );
942
1006
  }
943
- return /* @__PURE__ */ jsxs11(BaseMenu.SubmenuRoot, { children: [
944
- /* @__PURE__ */ jsx17(
1007
+ return /* @__PURE__ */ jsxs12(BaseMenu.SubmenuRoot, { children: [
1008
+ /* @__PURE__ */ jsx18(
945
1009
  BaseMenu.SubmenuTrigger,
946
1010
  {
947
1011
  openOnHover: true,
948
1012
  delay: 0,
949
1013
  closeDelay: 150,
950
1014
  nativeButton: true,
951
- render: /* @__PURE__ */ jsx17("button", { type: "button" }),
1015
+ render: /* @__PURE__ */ jsx18("button", { type: "button" }),
952
1016
  className: menuItemClassName({ size: "default", selected }),
953
- children: /* @__PURE__ */ jsx17(MenuItemBody, { label, leading, submenu: true })
1017
+ children: /* @__PURE__ */ jsx18(MenuItemBody, { label, leading, submenu: true })
954
1018
  }
955
1019
  ),
956
- /* @__PURE__ */ jsx17(BaseMenu.Portal, { children: /* @__PURE__ */ jsx17(
1020
+ /* @__PURE__ */ jsx18(BaseMenu.Portal, { children: /* @__PURE__ */ jsx18(
957
1021
  BaseMenu.Positioner,
958
1022
  {
959
1023
  side: "inline-end",
@@ -961,7 +1025,7 @@ function MenuSub({ label, leading, selected, children, className }) {
961
1025
  sideOffset: GAP2,
962
1026
  collisionPadding: VIEWPORT_PAD2,
963
1027
  className: "z-50 data-[anchor-hidden]:hidden",
964
- 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 })
965
1029
  }
966
1030
  ) })
967
1031
  ] });
@@ -996,25 +1060,25 @@ function menuItemClassName({ size, selected, className }) {
996
1060
  );
997
1061
  }
998
1062
  function MenuItemBody({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected }) {
999
- 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);
1000
- return /* @__PURE__ */ jsxs11(Fragment2, { children: [
1001
- leading && /* @__PURE__ */ jsx17("span", { className: "flex shrink-0 items-center", children: leading }),
1002
- children ?? /* @__PURE__ */ jsxs11("span", { className: cn("flex min-w-0 flex-1 flex-col", size === "tall" && "gap-[2px]"), children: [
1003
- /* @__PURE__ */ jsx17("span", { className: cn("truncate text-body-2", destructive ? "text-error-default" : "text-text-primary"), children: label }),
1004
- 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 })
1005
1069
  ] }),
1006
1070
  (edge || hint) && // One grid cell holding both, right-aligned: the slot is as wide as
1007
1071
  // the wider of the two and never changes, so revealing the hint moves
1008
1072
  // nothing. No transition here either — the hint switches on the same
1009
1073
  // :hover / `selected` as the fill, in the same frame.
1010
- /* @__PURE__ */ jsxs11("span", { className: "grid shrink-0 items-center justify-items-end [&>*]:col-start-1 [&>*]:row-start-1", children: [
1011
- 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 }),
1012
- 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 })
1013
1077
  ] })
1014
1078
  ] });
1015
1079
  }
1016
1080
  function MenuItem({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected, className, ...props }) {
1017
- const body = /* @__PURE__ */ jsx17(
1081
+ const body = /* @__PURE__ */ jsx18(
1018
1082
  MenuItemBody,
1019
1083
  {
1020
1084
  label,
@@ -1031,14 +1095,14 @@ function MenuItem({ label, children, size = "default", description, leading, tra
1031
1095
  }
1032
1096
  );
1033
1097
  const rowClassName = menuItemClassName({ size, selected, className });
1034
- if (!useContext2(MenuContext)) {
1035
- 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 });
1036
1100
  }
1037
- return /* @__PURE__ */ jsx17(
1101
+ return /* @__PURE__ */ jsx18(
1038
1102
  BaseMenu.Item,
1039
1103
  {
1040
1104
  nativeButton: true,
1041
- render: /* @__PURE__ */ jsx17("button", { type: "button" }),
1105
+ render: /* @__PURE__ */ jsx18("button", { type: "button" }),
1042
1106
  className: rowClassName,
1043
1107
  ...props,
1044
1108
  children: body
@@ -1046,31 +1110,31 @@ function MenuItem({ label, children, size = "default", description, leading, tra
1046
1110
  );
1047
1111
  }
1048
1112
  function EnterHint({ target }) {
1049
- return /* @__PURE__ */ jsxs11("span", { className: "flex shrink-0 items-center gap-1.5 text-text-muted", children: [
1050
- /* @__PURE__ */ jsx17(Kbd, { children: "\u21A9 Enter" }),
1051
- 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 })
1052
1116
  ] });
1053
1117
  }
1054
1118
  function MenuSection({ label, children, className }) {
1055
- const inMenu = useContext2(MenuContext) !== null;
1056
- 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 }) });
1057
1121
  if (!inMenu) {
1058
- return /* @__PURE__ */ jsxs11("div", { className: "flex flex-col", children: [
1122
+ return /* @__PURE__ */ jsxs12("div", { className: "flex flex-col", children: [
1059
1123
  heading,
1060
1124
  children
1061
1125
  ] });
1062
1126
  }
1063
- return /* @__PURE__ */ jsxs11(BaseMenu.Group, { className: "flex flex-col", children: [
1064
- /* @__PURE__ */ jsx17(BaseMenu.GroupLabel, { render: heading }),
1127
+ return /* @__PURE__ */ jsxs12(BaseMenu.Group, { className: "flex flex-col", children: [
1128
+ /* @__PURE__ */ jsx18(BaseMenu.GroupLabel, { render: heading }),
1065
1129
  children
1066
1130
  ] });
1067
1131
  }
1068
1132
  function MenuRow({ children, className }) {
1069
- 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 });
1070
1134
  }
1071
1135
 
1072
1136
  // src/ChipInput.tsx
1073
- import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
1137
+ import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
1074
1138
  var CHIP_BOX = (
1075
1139
  // Curved, not a pill (Katerina, 2026-09-01): the Avatar keeps its own
1076
1140
  // rounded-sm corners — never a forced circle — and the chip's corner
@@ -1081,10 +1145,10 @@ var CHIP_LABEL = "text-caption font-medium text-text-primary";
1081
1145
  var CHIP_REMOVE = "size-4 flex items-center justify-center rounded-full hover:bg-bg-hover text-text-secondary";
1082
1146
  var chipPadding = (leading, removable) => cn(leading ? "pl-[2px]" : "pl-2", removable ? "pr-1" : "pr-2");
1083
1147
  function InputChip({ label, leading, onRemove, removeLabel, truncate, className }) {
1084
- return /* @__PURE__ */ jsxs12("div", { className: cn(CHIP_BOX, chipPadding(!!leading, !!onRemove), className), children: [
1085
- leading && /* @__PURE__ */ jsx18("span", { className: "flex shrink-0 items-center", children: leading }),
1086
- /* @__PURE__ */ jsx18("span", { className: cn(CHIP_LABEL, truncate && "min-w-0 truncate"), children: label }),
1087
- 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(
1088
1152
  BaseButton4,
1089
1153
  {
1090
1154
  type: "button",
@@ -1094,7 +1158,7 @@ function InputChip({ label, leading, onRemove, removeLabel, truncate, className
1094
1158
  },
1095
1159
  className: cn(CHIP_REMOVE, truncate && "shrink-0"),
1096
1160
  "aria-label": removeLabel ?? `Remove ${label}`,
1097
- children: /* @__PURE__ */ jsx18(IconX3, { size: 10, stroke: 1.5 })
1161
+ children: /* @__PURE__ */ jsx19(IconX3, { size: 10, stroke: 1.5 })
1098
1162
  }
1099
1163
  )
1100
1164
  ] });
@@ -1147,7 +1211,7 @@ function ChipInput({
1147
1211
  setQuery("");
1148
1212
  }
1149
1213
  }
1150
- return /* @__PURE__ */ jsxs12(
1214
+ return /* @__PURE__ */ jsxs13(
1151
1215
  Combobox.Root,
1152
1216
  {
1153
1217
  multiple: true,
@@ -1164,13 +1228,13 @@ function ChipInput({
1164
1228
  filter,
1165
1229
  itemToStringLabel: (option) => option.label,
1166
1230
  children: [
1167
- /* @__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: [
1168
- value.map((option) => /* @__PURE__ */ jsxs12(Combobox.Chip, { className: cn(CHIP_BOX, chipPadding(!!chipLeading, true)), children: [
1169
- chipLeading && /* @__PURE__ */ jsx18("span", { className: "flex shrink-0 items-center", children: chipLeading(option) }),
1170
- /* @__PURE__ */ jsx18("span", { className: CHIP_LABEL, children: option.label }),
1171
- /* @__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 }) })
1172
1236
  ] }, option.id)),
1173
- /* @__PURE__ */ jsx18(
1237
+ /* @__PURE__ */ jsx19(
1174
1238
  Combobox.Input,
1175
1239
  {
1176
1240
  autoFocus,
@@ -1182,18 +1246,18 @@ function ChipInput({
1182
1246
  }
1183
1247
  )
1184
1248
  ] }),
1185
- /* @__PURE__ */ jsx18(Combobox.Portal, { children: /* @__PURE__ */ jsx18(
1249
+ /* @__PURE__ */ jsx19(Combobox.Portal, { children: /* @__PURE__ */ jsx19(
1186
1250
  Combobox.Positioner,
1187
1251
  {
1188
1252
  anchor: box,
1189
1253
  sideOffset: GAP3,
1190
1254
  collisionPadding: VIEWPORT_PAD3,
1191
1255
  className: "z-50 data-[anchor-hidden]:hidden",
1192
- 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(
1193
1257
  Combobox.Item,
1194
1258
  {
1195
1259
  value: option,
1196
- render: /* @__PURE__ */ jsx18(
1260
+ render: /* @__PURE__ */ jsx19(
1197
1261
  MenuItem,
1198
1262
  {
1199
1263
  size: "tall",
@@ -1216,21 +1280,21 @@ var VIEWPORT_PAD3 = 8;
1216
1280
 
1217
1281
  // src/EmptyState.tsx
1218
1282
  import { IconMessage2 } from "@tabler/icons-react";
1219
- import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
1283
+ import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
1220
1284
  function EmptyState({ icon, message, scope = "page", className }) {
1221
1285
  if (scope === "section") {
1222
- 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 });
1223
1287
  }
1224
- return /* @__PURE__ */ jsxs13("div", { className: cn("flex flex-1 flex-col items-center justify-center gap-2", className), children: [
1225
- /* @__PURE__ */ jsx19("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx19(IconMessage2, { size: 16, stroke: 1.5 }) }),
1226
- /* @__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 })
1227
1291
  ] });
1228
1292
  }
1229
1293
 
1230
1294
  // src/Field.tsx
1231
1295
  import { cloneElement, isValidElement } from "react";
1232
1296
  import { Field as BaseField2 } from "@base-ui/react/field";
1233
- import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
1297
+ import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
1234
1298
  var LINE_STYLES = {
1235
1299
  helper: "text-caption text-text-muted",
1236
1300
  warning: "text-caption text-warning-default",
@@ -1240,26 +1304,26 @@ function Field({ label, required = false, helper, error, children }) {
1240
1304
  const control = required && isValidElement(children) ? cloneElement(children, {
1241
1305
  "aria-required": children.props["aria-required"] ?? true
1242
1306
  }) : children;
1243
- return /* @__PURE__ */ jsxs14(BaseField2.Root, { invalid: !!error, className: "flex flex-col gap-2", children: [
1244
- /* @__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: [
1245
1309
  label,
1246
- 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: "*" })
1247
1311
  ] }),
1248
- /* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1.5", children: [
1312
+ /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-1.5", children: [
1249
1313
  control,
1250
- 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
1251
1315
  ] })
1252
1316
  ] });
1253
1317
  }
1254
1318
  function FieldLine({ tone = "helper", children, className }) {
1255
- 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 });
1256
1320
  }
1257
1321
 
1258
1322
  // src/Form.tsx
1259
1323
  import { useLayoutEffect as useLayoutEffect2, useRef as useRef2 } from "react";
1260
1324
  import { Fieldset } from "@base-ui/react/fieldset";
1261
1325
  import { Form as BaseForm } from "@base-ui/react/form";
1262
- import { jsx as jsx21 } from "react/jsx-runtime";
1326
+ import { jsx as jsx22 } from "react/jsx-runtime";
1263
1327
  var CONTROL = 'input:not([type="hidden"]), textarea, select, button, [role="checkbox"], [role="combobox"], [tabindex]:not([tabindex="-1"])';
1264
1328
  var ONE_LINE = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
1265
1329
  function usable(element) {
@@ -1318,7 +1382,7 @@ function Form({ onSubmit, busy: ownBusy = false, enterSends = true, className, c
1318
1382
  const oneLine = ONE_LINE.has((target.getAttribute("type") ?? "").toLowerCase()) && target.getAttribute("role") !== "combobox";
1319
1383
  if (enterSends && oneLine) form.current?.requestSubmit();
1320
1384
  };
1321
- return /* @__PURE__ */ jsx21(
1385
+ return /* @__PURE__ */ jsx22(
1322
1386
  BaseForm,
1323
1387
  {
1324
1388
  ref: form,
@@ -1340,32 +1404,32 @@ function Form({ onSubmit, busy: ownBusy = false, enterSends = true, className, c
1340
1404
  if (busyNow.current) return;
1341
1405
  void onSubmit();
1342
1406
  },
1343
- 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 }) })
1344
1408
  }
1345
1409
  );
1346
1410
  }
1347
1411
 
1348
1412
  // src/Skeleton.tsx
1349
- import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
1413
+ import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
1350
1414
  function SkeletonBar({ className, style }) {
1351
- 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 });
1352
1416
  }
1353
1417
  var ROW_BAR_WIDTHS = [150, 100, 170, 120, 90, 140, 110, 160];
1354
1418
  function SkeletonRow({ barWidth = 130 }) {
1355
- return /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2 px-2 h-[32px] rounded-lg", children: [
1356
- /* @__PURE__ */ jsx22(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
1357
- /* @__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 } })
1358
1422
  ] });
1359
1423
  }
1360
1424
  function SkeletonList({ rows = 8, className }) {
1361
- 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)) });
1362
1426
  }
1363
1427
 
1364
1428
  // src/CommandPalette.tsx
1365
- import { Fragment as Fragment3, jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
1366
- var PaletteContext = createContext3(null);
1429
+ import { Fragment as Fragment3, jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
1430
+ var PaletteContext = createContext4(null);
1367
1431
  function usePalette(part) {
1368
- const palette = useContext3(PaletteContext);
1432
+ const palette = useContext4(PaletteContext);
1369
1433
  if (!palette) throw new Error(`[@estiva-app/ui] ${part} must be inside a CommandPalette.`);
1370
1434
  return palette;
1371
1435
  }
@@ -1388,9 +1452,9 @@ function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", chi
1388
1452
  return () => cancelAnimationFrame(frame);
1389
1453
  });
1390
1454
  const context = useMemo2(() => ({ where, modKey, popupRef }), [where, modKey]);
1391
- return /* @__PURE__ */ jsx23(Dialog.Root, { open, onOpenChange: (next) => onOpenChange(next), children: /* @__PURE__ */ jsxs16(Dialog.Portal, { children: [
1392
- /* @__PURE__ */ jsx23(Dialog.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
1393
- /* @__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(
1394
1458
  Dialog.Popup,
1395
1459
  {
1396
1460
  ref: popupRef,
@@ -1400,13 +1464,13 @@ function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", chi
1400
1464
  if (e.target === popupRef.current) firstControl(popupRef.current)?.focus();
1401
1465
  },
1402
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",
1403
- children: /* @__PURE__ */ jsx23(PaletteContext.Provider, { value: context, children })
1467
+ children: /* @__PURE__ */ jsx24(PaletteContext.Provider, { value: context, children })
1404
1468
  }
1405
1469
  ) })
1406
1470
  ] }) });
1407
1471
  }
1408
1472
  function LevelChip({ chip, onBack }) {
1409
- 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" });
1410
1474
  }
1411
1475
  function useBack(chip, popupRef) {
1412
1476
  return () => {
@@ -1417,10 +1481,10 @@ function useBack(chip, popupRef) {
1417
1481
  }
1418
1482
  function Footer({ keys }) {
1419
1483
  const { where } = usePalette("The footer");
1420
- 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: [
1421
- /* @__PURE__ */ jsx23("span", { className: "min-w-0 flex-1 truncate", children: where }),
1422
- keys.map(([key, word]) => /* @__PURE__ */ jsxs16("span", { className: "flex shrink-0 items-center gap-1.5", children: [
1423
- /* @__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 }),
1424
1488
  " ",
1425
1489
  word
1426
1490
  ] }, key))
@@ -1497,7 +1561,7 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
1497
1561
  ...chip && query === "" ? [["Backspace", "back"]] : [],
1498
1562
  ["Esc", "close"]
1499
1563
  ];
1500
- return /* @__PURE__ */ jsxs16(
1564
+ return /* @__PURE__ */ jsxs17(
1501
1565
  Autocomplete.Root,
1502
1566
  {
1503
1567
  items,
@@ -1520,10 +1584,10 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
1520
1584
  setLitId(id);
1521
1585
  },
1522
1586
  children: [
1523
- /* @__PURE__ */ jsxs16("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
1524
- /* @__PURE__ */ jsx23(IconSearch, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" }),
1525
- chip && /* @__PURE__ */ jsx23(LevelChip, { chip, onBack: back }),
1526
- /* @__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(
1527
1591
  Autocomplete.Input,
1528
1592
  {
1529
1593
  ref: inputRef,
@@ -1535,43 +1599,43 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
1535
1599
  }
1536
1600
  )
1537
1601
  ] }),
1538
- /* @__PURE__ */ jsxs16(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col p-2", children: [
1539
- children != null && /* @__PURE__ */ jsx23("div", { className: "flex flex-col gap-2 px-3 pb-2 pt-3", children }),
1540
- /* @__PURE__ */ jsx23(Autocomplete.List, { className: "flex flex-col", children: (group) => /* @__PURE__ */ jsxs16(Autocomplete.Group, { items: group.items, className: "flex flex-col", children: [
1541
- /* @__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 }) }),
1542
- /* @__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) => (
1543
1607
  /* The menu row, as the list's own option — the way Select
1544
1608
  puts it on `Select.Item`. One row, two parts. */
1545
- /* @__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(
1546
1610
  MenuItemBody,
1547
1611
  {
1548
1612
  size: "tall",
1549
1613
  label: row.label,
1550
1614
  description: row.description,
1551
- leading: /* @__PURE__ */ jsx23(RowLeading, { row }),
1615
+ leading: /* @__PURE__ */ jsx24(RowLeading, { row }),
1552
1616
  submenu: !!row.onGoIn,
1553
- hint: row.onGoIn ? /* @__PURE__ */ jsx23(Kbd, { children: "Tab" }) : /* @__PURE__ */ jsx23(EnterHint, {})
1617
+ hint: row.onGoIn ? /* @__PURE__ */ jsx24(Kbd, { children: "Tab" }) : /* @__PURE__ */ jsx24(EnterHint, {})
1554
1618
  }
1555
1619
  ) }, row.id)
1556
1620
  ) })
1557
1621
  ] }, group.value) }),
1558
- /* @__PURE__ */ jsx23(Autocomplete.Status, { className: "flex items-center gap-2 px-3 [&:not(:empty)]:h-8", children: pending && /* @__PURE__ */ jsxs16(Fragment3, { children: [
1559
- /* @__PURE__ */ jsx23(IconLoader22, { size: 12, stroke: 1.5, className: "shrink-0 animate-spin text-text-muted" }),
1560
- /* @__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 })
1561
1625
  ] }) }),
1562
- notes.map((note) => /* @__PURE__ */ jsx23("div", { className: "flex min-h-8 items-center px-3", children: /* @__PURE__ */ jsx23(FieldLine, { children: note }) }, note)),
1563
- /* @__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 }) })
1564
1628
  ] }),
1565
- /* @__PURE__ */ jsx23(Footer, { keys })
1629
+ /* @__PURE__ */ jsx24(Footer, { keys })
1566
1630
  ]
1567
1631
  }
1568
1632
  );
1569
1633
  }
1570
1634
  function RowLeading({ row }) {
1571
1635
  if (row.icon != null) {
1572
- 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 });
1573
1637
  }
1574
- 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 });
1575
1639
  }
1576
1640
  var TEXT_TYPES = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
1577
1641
  function isTextField(el) {
@@ -1613,56 +1677,56 @@ function CommandPaletteForm({ chip, icon, submitLabel, onSubmit, submitWaits, wo
1613
1677
  ...backNamed ? [["Backspace", "back"]] : [],
1614
1678
  ["Esc", "close"]
1615
1679
  ];
1616
- 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: [
1617
- /* @__PURE__ */ jsxs16("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
1618
- icon != null && /* @__PURE__ */ jsx23("span", { className: "flex shrink-0 items-center text-text-secondary", children: icon }),
1619
- /* @__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 })
1620
1684
  ] }),
1621
- /* @__PURE__ */ jsxs16(Form, { "data-command-palette-fields": "", busy, enterSends: false, onSubmit: submit, className: "flex min-h-0 flex-col", children: [
1622
- /* @__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 }) }),
1623
- /* @__PURE__ */ jsxs16("div", { className: "flex shrink-0 items-center gap-3 px-5 pb-4", children: [
1624
- /* @__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 }),
1625
- /* @__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(
1626
1690
  Button,
1627
1691
  {
1628
1692
  type: "submit",
1629
1693
  variant: "primary",
1630
1694
  disabled: busy,
1631
1695
  disabledReason: busy ? void 0 : submitWaits,
1632
- 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,
1633
1697
  children: working ? working.button : submitLabel
1634
1698
  }
1635
1699
  )
1636
1700
  ] })
1637
1701
  ] }),
1638
- /* @__PURE__ */ jsx23(Footer, { keys })
1702
+ /* @__PURE__ */ jsx24(Footer, { keys })
1639
1703
  ] });
1640
1704
  }
1641
1705
  var BAR_WIDTHS = ["w-4/5", "w-3/5", "w-2/3"];
1642
1706
  function CommandPaletteWorking({ children, bars = 2 }) {
1643
- return /* @__PURE__ */ jsxs16("div", { role: "status", className: "flex flex-col gap-2", children: [
1644
- /* @__PURE__ */ jsxs16("span", { className: "flex items-center gap-2 text-caption text-text-secondary", children: [
1645
- /* @__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" }),
1646
1710
  children
1647
1711
  ] }),
1648
- 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))
1649
1713
  ] });
1650
1714
  }
1651
1715
  function CommandPaletteAnswer({ children, note }) {
1652
1716
  const paragraphs = children.split(/\n\s*\n/).filter((p) => p.trim() !== "");
1653
- return /* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-2", children: [
1654
- paragraphs.map((paragraph, i) => /* @__PURE__ */ jsx23("p", { className: "whitespace-pre-wrap text-body-2 text-text-primary", children: paragraph.split(/\s*(\[\d+\])/).map(
1655
- (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
1656
1720
  ) }, i)),
1657
- note && /* @__PURE__ */ jsx23(FieldLine, { children: note })
1721
+ note && /* @__PURE__ */ jsx24(FieldLine, { children: note })
1658
1722
  ] });
1659
1723
  }
1660
1724
  function CommandPaletteQuote({ children }) {
1661
- 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 });
1662
1726
  }
1663
1727
 
1664
1728
  // src/InlineChip.tsx
1665
- 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";
1666
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";
1667
1731
  var INLINE_CHIP_TONE_CLASSES = {
1668
1732
  /** A thing or a place — anything that is not a person. */
@@ -1684,49 +1748,20 @@ function inlineChipClassName(tone, className) {
1684
1748
  return cn(INLINE_CHIP_CLASSES, INLINE_CHIP_TONE_CLASSES[tone], className);
1685
1749
  }
1686
1750
  function InlineChip({ tone = "neutral", icon, href, className, children, ...props }) {
1687
- const body = /* @__PURE__ */ jsxs17(Fragment4, { children: [
1688
- 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 }),
1689
1753
  children
1690
1754
  ] });
1691
1755
  const classes = inlineChipClassName(tone, className);
1692
1756
  if (href === void 0) {
1693
- return /* @__PURE__ */ jsx24("span", { className: classes, ...props, children: body });
1757
+ return /* @__PURE__ */ jsx25("span", { className: classes, ...props, children: body });
1694
1758
  }
1695
- return /* @__PURE__ */ jsx24("a", { href, className: classes, ...props, children: body });
1759
+ return /* @__PURE__ */ jsx25("a", { href, className: classes, ...props, children: body });
1696
1760
  }
1697
1761
 
1698
1762
  // src/IdentityMenu.tsx
1699
1763
  import { useCallback, useRef as useRef4 } from "react";
1700
1764
 
1701
- // src/Divider.tsx
1702
- import { Separator } from "@base-ui/react/separator";
1703
- import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
1704
- function Divider({ orientation = "horizontal", label, tone = "default", className }) {
1705
- if (label && orientation === "horizontal") {
1706
- const line = tone === "warning" ? "bg-warning-muted" : "bg-border-subtle";
1707
- return /* @__PURE__ */ jsxs18(
1708
- Separator,
1709
- {
1710
- orientation: "horizontal",
1711
- "aria-label": label,
1712
- className: cn("flex shrink-0 items-center gap-2 mx-3", className),
1713
- children: [
1714
- /* @__PURE__ */ jsx25("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
1715
- /* @__PURE__ */ jsx25("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
1716
- /* @__PURE__ */ jsx25("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
1717
- ]
1718
- }
1719
- );
1720
- }
1721
- return /* @__PURE__ */ jsx25(
1722
- Separator,
1723
- {
1724
- orientation,
1725
- className: cn("shrink-0 bg-border-subtle", orientation === "horizontal" ? "h-px mx-3" : "w-px self-stretch", className)
1726
- }
1727
- );
1728
- }
1729
-
1730
1765
  // src/Person.tsx
1731
1766
  import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
1732
1767
  function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
@@ -1799,7 +1834,7 @@ function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, on
1799
1834
  const appRows = typeof children === "function" ? children(onClose) : children;
1800
1835
  return /* @__PURE__ */ jsxs21(Fragment5, { children: [
1801
1836
  /* @__PURE__ */ jsxs21(MenuSection, { label: signedIn ? "Signed in as" : "Acting as", children: [
1802
- /* @__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 }) }) }),
1803
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." }),
1804
1839
  me.email && /* @__PURE__ */ jsxs21(Note, { children: [
1805
1840
  me.email,
@@ -2090,14 +2125,9 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
2090
2125
  }
2091
2126
  )
2092
2127
  ] }),
2093
- bodyMaxHeight ? /* @__PURE__ */ jsx33(
2094
- ScrollArea,
2095
- {
2096
- className: cn(footer != null && "border-b border-border-subtle"),
2097
- viewportClassName: bodyMaxHeight,
2098
- contentClassName: cn("pl-5 pr-4 py-4", bodyClassName),
2099
- children
2100
- }
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 }) })
2101
2131
  ) : /* @__PURE__ */ jsx33("div", { className: cn("pl-5 pr-4 py-4", footer != null && "border-b border-border-subtle", bodyClassName), children }),
2102
2132
  footer != null && /* @__PURE__ */ jsx33("div", { className: "h-12 flex items-center justify-end gap-2 pl-5 pr-4 shrink-0", children: footer })
2103
2133
  ]
@@ -2127,12 +2157,11 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
2127
2157
  alert: true,
2128
2158
  title,
2129
2159
  onClose,
2130
- bodyClassName: "flex flex-col gap-3 text-body-2 text-text-primary",
2131
2160
  footer: /* @__PURE__ */ jsxs24(Fragment6, { children: [
2132
2161
  /* @__PURE__ */ jsx34(Button, { variant: "muted", onClick: onClose, disabled: busy, children: "Cancel" }),
2133
2162
  /* @__PURE__ */ jsx34(Button, { variant: destructive ? "destructive" : "primary", onClick: () => void confirm(), disabled: busy, children: confirmLabel })
2134
2163
  ] }),
2135
- children
2164
+ children: /* @__PURE__ */ jsx34("div", { className: "flex flex-col gap-3 text-body-2 text-text-primary", children })
2136
2165
  }
2137
2166
  );
2138
2167
  }
@@ -2311,8 +2340,11 @@ function Breadcrumb({ items, className }) {
2311
2340
  const crumb = item.href ? (
2312
2341
  // `plain` adds no look of its own: a crumb keeps the trail's size and
2313
2342
  // tone, and brightens on hover. The package's own Link, so a trail
2314
- // follows whatever a link learns to do (UIG-5).
2315
- /* @__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 }) })
2316
2348
  ) : /* @__PURE__ */ jsx37("span", { ref: setLabelRef, className: text, "aria-current": last ? "page" : void 0, children: item.label });
2317
2349
  return /* @__PURE__ */ jsxs25(Fragment7, { children: [
2318
2350
  index > 0 && /* @__PURE__ */ jsx37("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
@@ -2395,8 +2427,8 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
2395
2427
  ScrollArea,
2396
2428
  {
2397
2429
  viewportClassName: maxHeight ?? "max-h-[var(--available-height)]",
2398
- contentClassName: cn("flex flex-col p-2 [&>[role=separator]]:mx-0", contentClassName),
2399
- children
2430
+ contentClassName: cn("flex flex-col p-2", contentClassName),
2431
+ children: /* @__PURE__ */ jsx39(DividerInPanel.Provider, { value: true, children })
2400
2432
  }
2401
2433
  )
2402
2434
  }
@@ -2468,8 +2500,8 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
2468
2500
  "aria-label": option.label,
2469
2501
  tooltip: option.label,
2470
2502
  onClick: () => onSelect(option.emoji),
2471
- className: "size-7 text-h3 leading-none",
2472
- 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 })
2473
2505
  },
2474
2506
  option.emoji
2475
2507
  )
@@ -2507,7 +2539,7 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
2507
2539
  {
2508
2540
  className: cn("w-[360px] p-3 outline-none", className),
2509
2541
  render: /* @__PURE__ */ jsx42(MenuPanel, {}),
2510
- 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 })
2511
2543
  }
2512
2544
  )
2513
2545
  }
@@ -2799,7 +2831,7 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
2799
2831
  }
2800
2832
 
2801
2833
  // src/Toast.tsx
2802
- 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";
2803
2835
  import { Toast as BaseToast } from "@base-ui/react/toast";
2804
2836
  import { IconAlertCircle as IconAlertCircle2, IconCircleCheck, IconCircleX } from "@tabler/icons-react";
2805
2837
  import { jsx as jsx52, jsxs as jsxs36 } from "react/jsx-runtime";
@@ -2850,7 +2882,7 @@ function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAct
2850
2882
  hasAction && /* @__PURE__ */ jsx52(Button, { variant: "outlined", size: "small", onClick: onAction, children: actionLabel })
2851
2883
  ] });
2852
2884
  }
2853
- var ToastContext = createContext4(null);
2885
+ var ToastContext = createContext5(null);
2854
2886
  var VISIBLE_TOASTS = 3;
2855
2887
  function ToastProvider({ children }) {
2856
2888
  const manager = useMemo4(() => BaseToast.createToastManager(), []);
@@ -2906,7 +2938,7 @@ function ToastList() {
2906
2938
  });
2907
2939
  }
2908
2940
  function useToast() {
2909
- const ctx = useContext4(ToastContext);
2941
+ const ctx = useContext5(ToastContext);
2910
2942
  if (!ctx) throw new Error("useToast must be used within ToastProvider");
2911
2943
  return ctx;
2912
2944
  }