@estiva-app/ui 0.12.10 → 0.13.1

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 (43) hide show
  1. package/dist/AttachmentCard.d.ts +52 -0
  2. package/dist/AttachmentCard.d.ts.map +1 -0
  3. package/dist/Card.d.ts +54 -0
  4. package/dist/Card.d.ts.map +1 -0
  5. package/dist/InlineChip.d.ts +59 -0
  6. package/dist/InlineChip.d.ts.map +1 -0
  7. package/dist/Link.d.ts +37 -0
  8. package/dist/Link.d.ts.map +1 -0
  9. package/dist/ProgressBar.d.ts +32 -0
  10. package/dist/ProgressBar.d.ts.map +1 -0
  11. package/dist/index.d.ts +5 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +704 -355
  14. package/dist/index.js.map +4 -4
  15. package/package.json +1 -1
  16. package/src/AttachmentCard.mdx +62 -0
  17. package/src/AttachmentCard.stories.tsx +92 -0
  18. package/src/AttachmentCard.test.tsx +172 -0
  19. package/src/AttachmentCard.tsx +324 -0
  20. package/src/Card.mdx +74 -0
  21. package/src/Card.stories.tsx +112 -0
  22. package/src/Card.test.tsx +147 -0
  23. package/src/Card.tsx +133 -0
  24. package/src/EmptyState.mdx +14 -0
  25. package/src/EmptyState.stories.tsx +28 -7
  26. package/src/EmptyState.test.tsx +8 -0
  27. package/src/InlineChip.mdx +56 -0
  28. package/src/InlineChip.stories.tsx +59 -0
  29. package/src/InlineChip.test.tsx +81 -0
  30. package/src/InlineChip.tsx +90 -0
  31. package/src/Link.mdx +59 -0
  32. package/src/Link.stories.tsx +102 -0
  33. package/src/Link.test.tsx +100 -0
  34. package/src/Link.tsx +58 -0
  35. package/src/Person.stories.tsx +1 -1
  36. package/src/PersonTrigger.stories.tsx +1 -1
  37. package/src/ProgressBar.mdx +47 -0
  38. package/src/ProgressBar.stories.tsx +48 -0
  39. package/src/ProgressBar.test.tsx +62 -0
  40. package/src/ProgressBar.tsx +56 -0
  41. package/src/ReactionPicker.stories.tsx +1 -1
  42. package/src/index.ts +12 -0
  43. package/stories/Choosing.mdx +5 -0
package/dist/index.js CHANGED
@@ -133,77 +133,113 @@ function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav
133
133
  );
134
134
  }
135
135
 
136
- // src/Avatar.tsx
137
- import { useState } from "react";
138
- import { IconUserFilled } from "@tabler/icons-react";
136
+ // src/AttachmentCard.tsx
137
+ import { useLayoutEffect, useRef, useState } from "react";
138
+ import { Button as BaseButton2 } from "@base-ui/react/button";
139
+ import {
140
+ IconAlertCircle,
141
+ IconAlertTriangle,
142
+ IconDownload,
143
+ IconFile,
144
+ IconFileTypeCsv,
145
+ IconFileTypeDocx,
146
+ IconFileTypePdf,
147
+ IconFileTypePpt,
148
+ IconFileTypeTxt,
149
+ IconFileTypeXls,
150
+ IconFileTypeZip,
151
+ IconJson,
152
+ IconLoader2,
153
+ IconMarkdown,
154
+ IconX
155
+ } from "@tabler/icons-react";
156
+
157
+ // src/Link.tsx
139
158
  import { jsx as jsx4 } from "react/jsx-runtime";
140
- var HUES = ["#56c8ff", "#ff8f6b", "#4ade8c", "#b18cff", "#ffc94d", "#ff7eb0", "#7ea8ff", "#5fdfd6"];
141
- var hueFor = (key) => {
142
- let h = 0;
143
- for (let i = 0; i < key.length; i++) h = h * 31 + key.charCodeAt(i) | 0;
144
- return HUES[Math.abs(h) % HUES.length];
159
+ var VARIANT_CLASSES = {
160
+ text: "text-info-default underline underline-offset-2 hover:opacity-80",
161
+ quiet: "hover:underline",
162
+ underlined: "underline underline-offset-2 hover:text-text-primary",
163
+ plain: ""
145
164
  };
146
- var initialsFor = (name) => {
147
- const words = name.split(/\s+/).slice(0, 2).filter((w) => /^[\p{L}\p{N}]/u.test(w));
148
- const initials = words.map((w) => w[0]).join("") || name.trim().charAt(0);
149
- return initials.toUpperCase();
150
- };
151
- function Avatar({ src, name, alt = "", size = 36, label: spoken, className }) {
152
- const [broken, setBroken] = useState(false);
153
- const label = name || alt;
154
- const picture = src && !broken ? src : void 0;
165
+ function Link({ href, variant = "text", external = false, className, children, ...props }) {
155
166
  return /* @__PURE__ */ jsx4(
156
- "div",
167
+ "a",
157
168
  {
158
- ...spoken ? { role: "img", "aria-label": spoken } : { "aria-hidden": true },
159
- className: cn("rounded-sm overflow-hidden shrink-0 bg-bg-inset", className),
160
- style: { width: size, height: size },
161
- children: picture ? /* @__PURE__ */ jsx4("img", { src: picture, alt: "", className: "w-full h-full object-cover", onError: () => setBroken(true) }) : label ? /* @__PURE__ */ jsx4(
162
- "div",
163
- {
164
- className: "w-full h-full flex items-center justify-center font-semibold leading-none",
165
- style: {
166
- // The one ink colour that reads on all eight hues, which are a
167
- // palette rather than tokens (see the note at the top) — so its
168
- // ink cannot be a token either.
169
- color: "#08121c",
170
- fontSize: Math.round(size * 0.36),
171
- background: `linear-gradient(160deg, color-mix(in srgb, ${hueFor(label)} 92%, #fff) 0%, color-mix(in srgb, ${hueFor(label)} 70%, #0b0d11) 100%)`
172
- },
173
- children: initialsFor(label)
174
- }
175
- ) : /* @__PURE__ */ jsx4("div", { className: "w-full h-full bg-accent-muted flex items-center justify-center text-text-muted", children: /* @__PURE__ */ jsx4(IconUserFilled, { size: Math.round(size * 0.5) }) })
169
+ href,
170
+ ...external ? { target: "_blank", rel: "noopener noreferrer" } : {},
171
+ className: cn(VARIANT_CLASSES[variant], className),
172
+ ...props,
173
+ children
176
174
  }
177
175
  );
178
176
  }
179
177
 
180
- // src/AvatarGroup.tsx
178
+ // src/Card.tsx
181
179
  import { jsx as jsx5 } from "react/jsx-runtime";
182
- function AvatarGroup({ members, size = 24 }) {
183
- const visible = members.slice(0, 3);
184
- const overlap = Math.round(size / 3);
185
- const ring = size / 12;
186
- return /* @__PURE__ */ jsx5("div", { className: "flex items-center", style: { paddingRight: overlap }, children: visible.map((member, i) => (
187
- /*
188
- The wrapper carries the overlap and the ring; the face carries
189
- neither. It must never clip — see the note at the top of the file —
190
- so it has the avatar's own radius and no overflow of its own.
191
- */
192
- /* @__PURE__ */ jsx5(
193
- "span",
194
- {
195
- className: "relative flex rounded-sm",
196
- style: { marginRight: -overlap, boxShadow: `0 0 0 ${ring}px var(--bg-surface)` },
197
- children: /* @__PURE__ */ jsx5(Avatar, { size, name: member.name, src: member.picture, label: member.name })
198
- },
199
- i
200
- )
201
- )) });
180
+ var FILL_CLASSES = {
181
+ surface: "bg-bg-surface border-border-default",
182
+ elevated: "bg-bg-elevated border-border-default",
183
+ inset: "bg-bg-inset border-border-subtle",
184
+ none: "border-border-subtle"
185
+ };
186
+ var HAIRLINE_HOVER_CLASSES = {
187
+ surface: "hover:border-border-strong",
188
+ elevated: "hover:border-border-strong",
189
+ inset: "hover:border-border-default",
190
+ none: "hover:border-border-default"
191
+ };
192
+ var HAIRLINE_HELD_CLASSES = {
193
+ surface: "border-border-strong",
194
+ elevated: "border-border-strong",
195
+ inset: "border-border-default",
196
+ none: "border-border-default"
197
+ };
198
+ var ATTENTION_CLASSES = {
199
+ accent: "border-accent-muted hover:border-accent-muted",
200
+ warning: "border-warning-muted hover:border-warning-muted"
201
+ };
202
+ function Card({
203
+ fill = "surface",
204
+ href,
205
+ hover = href ? "hairline" : "none",
206
+ quietUntilHover = false,
207
+ hovered = false,
208
+ selected = false,
209
+ active = false,
210
+ attention,
211
+ unreadable = false,
212
+ className,
213
+ children,
214
+ ...props
215
+ }) {
216
+ const still = selected || active;
217
+ const classes = cn(
218
+ "rounded-lg border",
219
+ // A card that never changes has nothing to ease between, and the apps' still cards carry no transition.
220
+ hover !== "none" && "transition-colors",
221
+ FILL_CLASSES[fill],
222
+ quietUntilHover && "border-transparent",
223
+ !still && hover === "hairline" && HAIRLINE_HOVER_CLASSES[fill],
224
+ !still && hover === "fill" && "hover:bg-bg-hover hover:border-border-default",
225
+ !still && hovered && hover === "hairline" && HAIRLINE_HELD_CLASSES[fill],
226
+ !still && hovered && hover === "fill" && "bg-bg-hover border-border-default",
227
+ // The one you are on can still be clicked (it opens again); the one being changed cannot.
228
+ !active && hover !== "none" && !href && props.onClick && "cursor-pointer",
229
+ selected && "bg-bg-selected border-border-subtle",
230
+ active && "bg-bg-selected border-accent-primary",
231
+ !active && attention && ATTENTION_CLASSES[attention],
232
+ unreadable && "border-dashed",
233
+ href && "block",
234
+ className
235
+ );
236
+ if (href !== void 0) {
237
+ const { ref, ...anchorProps } = props;
238
+ return /* @__PURE__ */ jsx5(Link, { href, variant: "plain", ref, className: classes, ...anchorProps, children });
239
+ }
240
+ return /* @__PURE__ */ jsx5("div", { className: classes, ...props, children });
202
241
  }
203
242
 
204
- // src/Banner.tsx
205
- import { IconX } from "@tabler/icons-react";
206
-
207
243
  // src/IconButton.tsx
208
244
  import { Button as BaseButton } from "@base-ui/react/button";
209
245
 
@@ -344,8 +380,260 @@ function IconButton({
344
380
  return button;
345
381
  }
346
382
 
383
+ // src/AttachmentCard.tsx
384
+ import { Fragment, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
385
+ var ICON_BY_EXTENSION = {
386
+ pdf: IconFileTypePdf,
387
+ doc: IconFileTypeDocx,
388
+ docx: IconFileTypeDocx,
389
+ xls: IconFileTypeXls,
390
+ xlsx: IconFileTypeXls,
391
+ ppt: IconFileTypePpt,
392
+ pptx: IconFileTypePpt,
393
+ csv: IconFileTypeCsv,
394
+ txt: IconFileTypeTxt,
395
+ rtf: IconFileTypeTxt,
396
+ zip: IconFileTypeZip,
397
+ json: IconJson,
398
+ md: IconMarkdown
399
+ };
400
+ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set(["png", "jpg", "jpeg", "gif", "webp", "heic", "heif", "svg"]);
401
+ var extensionOf = (name) => {
402
+ const dot = name.lastIndexOf(".");
403
+ return dot >= 0 ? name.slice(dot + 1).toLowerCase() : "";
404
+ };
405
+ var isImage = (name, contentType) => IMAGE_EXTENSIONS.has(extensionOf(name)) || (contentType?.startsWith("image/") ?? false);
406
+ var formatBytes = (bytes) => {
407
+ if (bytes < 1024) return `${bytes} bytes`;
408
+ const kb = bytes / 1024;
409
+ if (kb < 1024) return `${Math.round(kb)} KB`;
410
+ return `${(kb / 1024).toFixed(1)} MB`;
411
+ };
412
+ var typeLabelOf = (name) => extensionOf(name).toUpperCase() || "FILE";
413
+ var TILE = "size-9 rounded-md bg-bg-active flex items-center justify-center shrink-0 text-text-secondary";
414
+ var NAME = "text-[12px] font-medium leading-[1.3] text-text-primary truncate";
415
+ var NOTE = "text-[10px] leading-[1.2] truncate";
416
+ function TypeIcon({ name }) {
417
+ const Icon = ICON_BY_EXTENSION[extensionOf(name)] ?? IconFile;
418
+ return /* @__PURE__ */ jsx9(Icon, { size: 20, stroke: 1.5 });
419
+ }
420
+ function Truncating({ text, hint, className, wrapperClassName }) {
421
+ const ref = useRef(null);
422
+ const [cut, setCut] = useState(false);
423
+ useLayoutEffect(() => {
424
+ const el = ref.current;
425
+ if (!el) return;
426
+ let live = true;
427
+ const measure = () => {
428
+ if (live) setCut(el.scrollWidth > el.clientWidth);
429
+ };
430
+ measure();
431
+ void document.fonts?.ready.then(measure);
432
+ if (typeof ResizeObserver === "undefined") return () => void (live = false);
433
+ const observer = new ResizeObserver(measure);
434
+ observer.observe(el);
435
+ return () => {
436
+ live = false;
437
+ observer.disconnect();
438
+ };
439
+ }, [text, cut]);
440
+ const line = /* @__PURE__ */ jsx9("span", { ref, className, children: text });
441
+ if (!hint && !cut) return line;
442
+ return /* @__PURE__ */ jsx9(WithTooltip, { label: hint ?? text, wrapperClassName: cn("min-w-0 flex-col", wrapperClassName), children: line });
443
+ }
444
+ function AttachmentCard({
445
+ name,
446
+ size,
447
+ contentType,
448
+ href,
449
+ src,
450
+ onOpen,
451
+ onDownload,
452
+ pending = false,
453
+ onRemove,
454
+ state = "ready",
455
+ note,
456
+ noteHint,
457
+ className,
458
+ ...props
459
+ }) {
460
+ const image = isImage(name, contentType);
461
+ const sizeText = size === void 0 ? "" : formatBytes(size);
462
+ if (pending) {
463
+ const failed = state === "failed";
464
+ const warning = state === "warning";
465
+ return /* @__PURE__ */ jsxs5(
466
+ Card,
467
+ {
468
+ fill: "elevated",
469
+ 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),
470
+ ...props,
471
+ children: [
472
+ /* @__PURE__ */ jsx9("div", { className: cn(TILE, "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-[9px] font-semibold", children: typeLabelOf(name) }) }),
473
+ /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-[1px] min-w-0", children: [
474
+ /* @__PURE__ */ jsx9(Truncating, { text: name, className: NAME }),
475
+ /* @__PURE__ */ jsx9(
476
+ Truncating,
477
+ {
478
+ text: (failed || warning ? note : state === "uploading" ? note ?? "Uploading\u2026" : note ?? sizeText) ?? "",
479
+ hint: noteHint,
480
+ className: cn(NOTE, failed ? "text-error-default" : warning ? "text-warning-default" : "text-text-secondary")
481
+ }
482
+ )
483
+ ] }),
484
+ onRemove && /* @__PURE__ */ jsx9(
485
+ BaseButton2,
486
+ {
487
+ type: "button",
488
+ "aria-label": `Remove ${name}`,
489
+ 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",
490
+ onClick: (event) => {
491
+ event.stopPropagation();
492
+ onRemove();
493
+ },
494
+ children: /* @__PURE__ */ jsx9(IconX, { size: 11, stroke: 1.75 })
495
+ }
496
+ )
497
+ ]
498
+ }
499
+ );
500
+ }
501
+ const download = onDownload ? /* @__PURE__ */ jsx9(
502
+ IconButton,
503
+ {
504
+ variant: "muted",
505
+ tooltip: "Download",
506
+ "aria-label": `Download ${name}`,
507
+ className: "opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100 transition-opacity",
508
+ onClick: (event) => {
509
+ event.stopPropagation();
510
+ onDownload();
511
+ },
512
+ children: /* @__PURE__ */ jsx9(IconDownload, { size: 16, stroke: 1.5 })
513
+ }
514
+ ) : null;
515
+ if (state === "loading") {
516
+ return (
517
+ // `role="status"`: a plain box may not carry a name (axe, aria-prohibited-attr), and a
518
+ // status says what it is doing — loading — to a reader that cannot see the pulse.
519
+ /* @__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 })
520
+ );
521
+ }
522
+ if (state === "unreadable") {
523
+ 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: [
524
+ /* @__PURE__ */ jsx9("div", { className: TILE, children: /* @__PURE__ */ jsx9(TypeIcon, { name }) }),
525
+ /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-[1px] min-w-0 text-left", children: [
526
+ /* @__PURE__ */ jsx9(Truncating, { text: name, className: NAME }),
527
+ /* @__PURE__ */ jsx9("span", { className: cn(NOTE, "text-text-secondary"), children: note ?? "Could not be loaded" })
528
+ ] })
529
+ ] });
530
+ }
531
+ if (image && src) {
532
+ const picture = /* @__PURE__ */ jsx9("img", { src, alt: name, className: "w-full h-28 object-cover" });
533
+ return /* @__PURE__ */ jsxs5(Card, { fill: "inset", hover: "hairline", className: cn("group relative flex flex-col w-[180px] overflow-hidden", className), ...props, children: [
534
+ onOpen ? /* @__PURE__ */ jsx9(
535
+ BaseButton2,
536
+ {
537
+ type: "button",
538
+ className: "block w-full",
539
+ "aria-label": `Preview ${name}`,
540
+ onClick: (event) => {
541
+ event.stopPropagation();
542
+ onOpen();
543
+ },
544
+ children: picture
545
+ }
546
+ ) : /* @__PURE__ */ jsx9("div", { className: "block w-full", children: picture }),
547
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1 pl-2 pr-1 py-1 min-w-0", children: [
548
+ /* @__PURE__ */ jsx9(Truncating, { text: name, className: "flex-1 text-[12px] leading-[1.3] text-text-primary truncate", wrapperClassName: "flex-1" }),
549
+ download
550
+ ] })
551
+ ] });
552
+ }
553
+ const body = /* @__PURE__ */ jsxs5(Fragment, { children: [
554
+ /* @__PURE__ */ jsx9("div", { className: TILE, children: /* @__PURE__ */ jsx9(TypeIcon, { name }) }),
555
+ /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-[1px] min-w-0 text-left", children: [
556
+ /* @__PURE__ */ jsx9(Truncating, { text: name, className: NAME }),
557
+ /* @__PURE__ */ jsx9("span", { className: cn(NOTE, "text-text-secondary"), children: note ?? `${typeLabelOf(name)} \xB7 ${sizeText}` })
558
+ ] })
559
+ ] });
560
+ 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: [
561
+ 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 }),
562
+ download
563
+ ] });
564
+ }
565
+
566
+ // src/Avatar.tsx
567
+ import { useState as useState2 } from "react";
568
+ import { IconUserFilled } from "@tabler/icons-react";
569
+ import { jsx as jsx10 } from "react/jsx-runtime";
570
+ var HUES = ["#56c8ff", "#ff8f6b", "#4ade8c", "#b18cff", "#ffc94d", "#ff7eb0", "#7ea8ff", "#5fdfd6"];
571
+ var hueFor = (key) => {
572
+ let h = 0;
573
+ for (let i = 0; i < key.length; i++) h = h * 31 + key.charCodeAt(i) | 0;
574
+ return HUES[Math.abs(h) % HUES.length];
575
+ };
576
+ var initialsFor = (name) => {
577
+ const words = name.split(/\s+/).slice(0, 2).filter((w) => /^[\p{L}\p{N}]/u.test(w));
578
+ const initials = words.map((w) => w[0]).join("") || name.trim().charAt(0);
579
+ return initials.toUpperCase();
580
+ };
581
+ function Avatar({ src, name, alt = "", size = 36, label: spoken, className }) {
582
+ const [broken, setBroken] = useState2(false);
583
+ const label = name || alt;
584
+ const picture = src && !broken ? src : void 0;
585
+ return /* @__PURE__ */ jsx10(
586
+ "div",
587
+ {
588
+ ...spoken ? { role: "img", "aria-label": spoken } : { "aria-hidden": true },
589
+ className: cn("rounded-sm overflow-hidden shrink-0 bg-bg-inset", className),
590
+ style: { width: size, height: size },
591
+ children: picture ? /* @__PURE__ */ jsx10("img", { src: picture, alt: "", className: "w-full h-full object-cover", onError: () => setBroken(true) }) : label ? /* @__PURE__ */ jsx10(
592
+ "div",
593
+ {
594
+ className: "w-full h-full flex items-center justify-center font-semibold leading-none",
595
+ style: {
596
+ // The one ink colour that reads on all eight hues, which are a
597
+ // palette rather than tokens (see the note at the top) — so its
598
+ // ink cannot be a token either.
599
+ color: "#08121c",
600
+ fontSize: Math.round(size * 0.36),
601
+ background: `linear-gradient(160deg, color-mix(in srgb, ${hueFor(label)} 92%, #fff) 0%, color-mix(in srgb, ${hueFor(label)} 70%, #0b0d11) 100%)`
602
+ },
603
+ children: initialsFor(label)
604
+ }
605
+ ) : /* @__PURE__ */ jsx10("div", { className: "w-full h-full bg-accent-muted flex items-center justify-center text-text-muted", children: /* @__PURE__ */ jsx10(IconUserFilled, { size: Math.round(size * 0.5) }) })
606
+ }
607
+ );
608
+ }
609
+
610
+ // src/AvatarGroup.tsx
611
+ import { jsx as jsx11 } from "react/jsx-runtime";
612
+ function AvatarGroup({ members, size = 24 }) {
613
+ const visible = members.slice(0, 3);
614
+ const overlap = Math.round(size / 3);
615
+ const ring = size / 12;
616
+ return /* @__PURE__ */ jsx11("div", { className: "flex items-center", style: { paddingRight: overlap }, children: visible.map((member, i) => (
617
+ /*
618
+ The wrapper carries the overlap and the ring; the face carries
619
+ neither. It must never clip — see the note at the top of the file —
620
+ so it has the avatar's own radius and no overflow of its own.
621
+ */
622
+ /* @__PURE__ */ jsx11(
623
+ "span",
624
+ {
625
+ className: "relative flex rounded-sm",
626
+ style: { marginRight: -overlap, boxShadow: `0 0 0 ${ring}px var(--bg-surface)` },
627
+ children: /* @__PURE__ */ jsx11(Avatar, { size, name: member.name, src: member.picture, label: member.name })
628
+ },
629
+ i
630
+ )
631
+ )) });
632
+ }
633
+
347
634
  // src/Banner.tsx
348
- import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
635
+ import { IconX as IconX2 } from "@tabler/icons-react";
636
+ import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
349
637
  var TONE_STYLES = {
350
638
  ok: "bg-success-muted text-success-default",
351
639
  error: "bg-error-muted text-error-default",
@@ -355,17 +643,17 @@ var TONE_STYLES = {
355
643
  function Banner({ tone, children, onDismiss, dismissLabel = "Dismiss", className }) {
356
644
  const role = tone === "error" ? "alert" : "status";
357
645
  if (!onDismiss) {
358
- return /* @__PURE__ */ jsx9("div", { role, className: cn("px-4 py-2 text-body-2", TONE_STYLES[tone], className), children });
646
+ return /* @__PURE__ */ jsx12("div", { role, className: cn("px-4 py-2 text-body-2", TONE_STYLES[tone], className), children });
359
647
  }
360
- return /* @__PURE__ */ jsxs5("div", { role, className: cn("flex items-center gap-3 px-4 py-2 text-body-2", TONE_STYLES[tone], className), children: [
361
- /* @__PURE__ */ jsx9("span", { className: "min-w-0 flex-1", children }),
362
- /* @__PURE__ */ jsx9(IconButton, { "aria-label": dismissLabel, onClick: onDismiss, className: "-mr-1 shrink-0 text-current hover:text-current", children: /* @__PURE__ */ jsx9(IconX, { size: 16, stroke: 1.5 }) })
648
+ return /* @__PURE__ */ jsxs6("div", { role, className: cn("flex items-center gap-3 px-4 py-2 text-body-2", TONE_STYLES[tone], className), children: [
649
+ /* @__PURE__ */ jsx12("span", { className: "min-w-0 flex-1", children }),
650
+ /* @__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 }) })
363
651
  ] });
364
652
  }
365
653
 
366
654
  // src/Button.tsx
367
- import { Button as BaseButton2 } from "@base-ui/react/button";
368
- import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
655
+ import { Button as BaseButton3 } from "@base-ui/react/button";
656
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
369
657
  function Button({
370
658
  variant = "muted",
371
659
  size = "default",
@@ -378,8 +666,8 @@ function Button({
378
666
  ...props
379
667
  }) {
380
668
  const hasLeadingIcon = !!leadingIcon;
381
- const button = /* @__PURE__ */ jsxs6(
382
- BaseButton2,
669
+ const button = /* @__PURE__ */ jsxs7(
670
+ BaseButton3,
383
671
  {
384
672
  type,
385
673
  disabled: disabled || !!disabledReason,
@@ -423,13 +711,13 @@ function Button({
423
711
  ]
424
712
  }
425
713
  );
426
- return disabledReason ? /* @__PURE__ */ jsx10(TooltipTrigger, { label: disabledReason, children: button }) : button;
714
+ return disabledReason ? /* @__PURE__ */ jsx13(TooltipTrigger, { label: disabledReason, children: button }) : button;
427
715
  }
428
716
 
429
717
  // src/Checkbox.tsx
430
718
  import { Checkbox as BaseCheckbox } from "@base-ui/react/checkbox";
431
719
  import { IconCheck } from "@tabler/icons-react";
432
- import { jsx as jsx11 } from "react/jsx-runtime";
720
+ import { jsx as jsx14 } from "react/jsx-runtime";
433
721
  function squareClasses(checked, disabled, interactive, className) {
434
722
  return cn(
435
723
  "inline-flex items-center justify-center size-4 shrink-0 rounded-[4px] border transition-colors",
@@ -442,9 +730,9 @@ function squareClasses(checked, disabled, interactive, className) {
442
730
  var tickClasses = (checked) => cn("flex", !checked && "invisible");
443
731
  function Checkbox({ checked, onChange, disabled = false, className, ...aria }) {
444
732
  if (!onChange) {
445
- return /* @__PURE__ */ jsx11("span", { "aria-hidden": "true", className: squareClasses(checked, disabled, false, className), children: /* @__PURE__ */ jsx11("span", { className: tickClasses(checked), children: /* @__PURE__ */ jsx11(IconCheck, { size: 12, stroke: 3 }) }) });
733
+ return /* @__PURE__ */ jsx14("span", { "aria-hidden": "true", className: squareClasses(checked, disabled, false, className), children: /* @__PURE__ */ jsx14("span", { className: tickClasses(checked), children: /* @__PURE__ */ jsx14(IconCheck, { size: 12, stroke: 3 }) }) });
446
734
  }
447
- return /* @__PURE__ */ jsx11(
735
+ return /* @__PURE__ */ jsx14(
448
736
  BaseCheckbox.Root,
449
737
  {
450
738
  checked,
@@ -454,13 +742,13 @@ function Checkbox({ checked, onChange, disabled = false, className, ...aria }) {
454
742
  onCheckedChange: (next) => onChange(next),
455
743
  onClick: (e) => e.stopPropagation(),
456
744
  className: (state) => squareClasses(state.checked, state.disabled, true, className),
457
- children: /* @__PURE__ */ jsx11(BaseCheckbox.Indicator, { keepMounted: true, className: (state) => tickClasses(state.checked), children: /* @__PURE__ */ jsx11(IconCheck, { size: 12, stroke: 3 }) })
745
+ children: /* @__PURE__ */ jsx14(BaseCheckbox.Indicator, { keepMounted: true, className: (state) => tickClasses(state.checked), children: /* @__PURE__ */ jsx14(IconCheck, { size: 12, stroke: 3 }) })
458
746
  }
459
747
  );
460
748
  }
461
749
 
462
750
  // src/Chip.tsx
463
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
751
+ import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
464
752
  var typeStyles = {
465
753
  neutral: "bg-bg-inset text-text-primary",
466
754
  brand: "bg-accent-muted text-accent-primary signal:border signal:border-accent-outline",
@@ -470,8 +758,8 @@ var typeStyles = {
470
758
  error: "bg-error-muted text-error-default signal:border signal:border-error-outline"
471
759
  };
472
760
  function Chip({ type = "neutral", label, leadingIcon, trailingIcon, className }) {
473
- return /* @__PURE__ */ jsxs7("div", { className: cn("inline-flex min-w-0 items-center justify-center gap-1.5 rounded-full max-h-[20px] px-2 py-1", typeStyles[type], className), children: [
474
- leadingIcon && /* @__PURE__ */ jsx12("span", { className: "flex size-3 shrink-0 items-center justify-center", children: leadingIcon }),
761
+ return /* @__PURE__ */ jsxs8("div", { className: cn("inline-flex min-w-0 items-center justify-center gap-1.5 rounded-full max-h-[20px] px-2 py-1", typeStyles[type], className), children: [
762
+ leadingIcon && /* @__PURE__ */ jsx15("span", { className: "flex size-3 shrink-0 items-center justify-center", children: leadingIcon }),
475
763
  label && // A chip given a `max-w-*` cuts a long label with an ellipsis instead
476
764
  // of growing past it — Ship's project chip on an issue row
477
765
  // (2026-09-09). Clipped sideways only: `overflow-x-clip`, not
@@ -480,16 +768,16 @@ function Chip({ type = "neutral", label, leadingIcon, trailingIcon, className })
480
768
  // the screenshot diff caught every descender cut off. `clip` is the
481
769
  // one overflow that leaves the other axis visible. A chip with no cap
482
770
  // draws exactly as before.
483
- /* @__PURE__ */ jsx12("span", { className: "min-w-0 overflow-x-clip text-ellipsis whitespace-nowrap text-chip signal:font-mono signal:text-[10px] signal:font-semibold signal:tracking-[0.02em] signal:tabular-nums", children: label }),
484
- trailingIcon && /* @__PURE__ */ jsx12("span", { className: "flex size-3 shrink-0 items-center justify-center", children: trailingIcon })
771
+ /* @__PURE__ */ jsx15("span", { className: "min-w-0 overflow-x-clip text-ellipsis whitespace-nowrap text-chip signal:font-mono signal:text-[10px] signal:font-semibold signal:tracking-[0.02em] signal:tabular-nums", children: label }),
772
+ trailingIcon && /* @__PURE__ */ jsx15("span", { className: "flex size-3 shrink-0 items-center justify-center", children: trailingIcon })
485
773
  ] });
486
774
  }
487
775
 
488
776
  // src/ChipInput.tsx
489
- import { useMemo, useState as useState2 } from "react";
490
- import { Button as BaseButton3 } from "@base-ui/react/button";
777
+ import { useMemo, useState as useState3 } from "react";
778
+ import { Button as BaseButton4 } from "@base-ui/react/button";
491
779
  import { Combobox } from "@base-ui/react/combobox";
492
- import { IconX as IconX2 } from "@tabler/icons-react";
780
+ import { IconX as IconX3 } from "@tabler/icons-react";
493
781
 
494
782
  // src/Menu.tsx
495
783
  import { createContext, useContext } from "react";
@@ -503,9 +791,9 @@ function triggerDisabled(trigger) {
503
791
  }
504
792
 
505
793
  // src/SectionLabel.tsx
506
- import { jsx as jsx13 } from "react/jsx-runtime";
794
+ import { jsx as jsx16 } from "react/jsx-runtime";
507
795
  function SectionLabel({ children, className }) {
508
- return /* @__PURE__ */ jsx13(
796
+ return /* @__PURE__ */ jsx16(
509
797
  "span",
510
798
  {
511
799
  className: cn(
@@ -518,10 +806,10 @@ function SectionLabel({ children, className }) {
518
806
  }
519
807
 
520
808
  // src/Menu.tsx
521
- import { Fragment, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
809
+ import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
522
810
  var MenuContext = createContext(null);
523
811
  function MenuPanel({ children, className, ...props }) {
524
- return /* @__PURE__ */ jsx14(
812
+ return /* @__PURE__ */ jsx17(
525
813
  "div",
526
814
  {
527
815
  className: cn(
@@ -551,7 +839,7 @@ var VIEWPORT_PAD2 = 8;
551
839
  var HOVER_OPEN_DELAY = 0;
552
840
  var HOVER_CLOSE_DELAY = 150;
553
841
  function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange, actionsRef, children, className, contentClassName }) {
554
- return /* @__PURE__ */ jsxs8(
842
+ return /* @__PURE__ */ jsxs9(
555
843
  BaseMenu.Root,
556
844
  {
557
845
  open,
@@ -559,7 +847,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
559
847
  actionsRef,
560
848
  modal: false,
561
849
  children: [
562
- /* @__PURE__ */ jsx14(
850
+ /* @__PURE__ */ jsx17(
563
851
  BaseMenu.Trigger,
564
852
  {
565
853
  render: trigger,
@@ -569,7 +857,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
569
857
  closeDelay: HOVER_CLOSE_DELAY
570
858
  }
571
859
  ),
572
- /* @__PURE__ */ jsx14(BaseMenu.Portal, { children: /* @__PURE__ */ jsx14(
860
+ /* @__PURE__ */ jsx17(BaseMenu.Portal, { children: /* @__PURE__ */ jsx17(
573
861
  BaseMenu.Positioner,
574
862
  {
575
863
  side: "bottom",
@@ -577,13 +865,13 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
577
865
  sideOffset: GAP2,
578
866
  collisionPadding: VIEWPORT_PAD2,
579
867
  className: "z-50 data-[anchor-hidden]:hidden",
580
- children: /* @__PURE__ */ jsx14(
868
+ children: /* @__PURE__ */ jsx17(
581
869
  BaseMenu.Popup,
582
870
  {
583
871
  "data-interactive": true,
584
872
  className: cn("min-w-[180px] outline-none p-0", className),
585
- render: /* @__PURE__ */ jsx14(MenuPanel, {}),
586
- children: /* @__PURE__ */ jsx14(ScrollArea, { viewportClassName: "max-h-[var(--available-height)]", contentClassName: cn("flex flex-col p-2 [&>[role=separator]]:mx-0", contentClassName), children: /* @__PURE__ */ jsx14(MenuContext.Provider, { value: { openOnHover }, children }) })
873
+ render: /* @__PURE__ */ jsx17(MenuPanel, {}),
874
+ 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 }) })
587
875
  }
588
876
  )
589
877
  }
@@ -599,20 +887,20 @@ function MenuSub({ label, leading, selected, children, className }) {
599
887
  '[@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".'
600
888
  );
601
889
  }
602
- return /* @__PURE__ */ jsxs8(BaseMenu.SubmenuRoot, { children: [
603
- /* @__PURE__ */ jsx14(
890
+ return /* @__PURE__ */ jsxs9(BaseMenu.SubmenuRoot, { children: [
891
+ /* @__PURE__ */ jsx17(
604
892
  BaseMenu.SubmenuTrigger,
605
893
  {
606
894
  openOnHover: true,
607
895
  delay: 0,
608
896
  closeDelay: 150,
609
897
  nativeButton: true,
610
- render: /* @__PURE__ */ jsx14("button", { type: "button" }),
898
+ render: /* @__PURE__ */ jsx17("button", { type: "button" }),
611
899
  className: menuItemClassName({ size: "default", selected }),
612
- children: /* @__PURE__ */ jsx14(MenuItemBody, { label, leading, submenu: true })
900
+ children: /* @__PURE__ */ jsx17(MenuItemBody, { label, leading, submenu: true })
613
901
  }
614
902
  ),
615
- /* @__PURE__ */ jsx14(BaseMenu.Portal, { children: /* @__PURE__ */ jsx14(
903
+ /* @__PURE__ */ jsx17(BaseMenu.Portal, { children: /* @__PURE__ */ jsx17(
616
904
  BaseMenu.Positioner,
617
905
  {
618
906
  side: "inline-end",
@@ -620,7 +908,7 @@ function MenuSub({ label, leading, selected, children, className }) {
620
908
  sideOffset: GAP2,
621
909
  collisionPadding: VIEWPORT_PAD2,
622
910
  className: "z-50 data-[anchor-hidden]:hidden",
623
- children: /* @__PURE__ */ jsx14(BaseMenu.Popup, { className: cn("w-[160px]", className), "data-interactive": true, render: /* @__PURE__ */ jsx14(MenuPanel, {}), children })
911
+ children: /* @__PURE__ */ jsx17(BaseMenu.Popup, { className: cn("w-[160px]", className), "data-interactive": true, render: /* @__PURE__ */ jsx17(MenuPanel, {}), children })
624
912
  }
625
913
  ) })
626
914
  ] });
@@ -655,25 +943,25 @@ function menuItemClassName({ size, selected, className }) {
655
943
  );
656
944
  }
657
945
  function MenuItemBody({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected }) {
658
- const edge = trailing ?? (shortcut ? /* @__PURE__ */ jsx14(Kbd, { children: shortcut }) : submenu ? /* @__PURE__ */ jsx14(IconChevronRight, { size: 16, stroke: 1.5, className: "shrink-0 text-text-muted" }) : null);
659
- return /* @__PURE__ */ jsxs8(Fragment, { children: [
660
- leading && /* @__PURE__ */ jsx14("span", { className: "flex shrink-0 items-center", children: leading }),
661
- children ?? /* @__PURE__ */ jsxs8("span", { className: cn("flex min-w-0 flex-1 flex-col", size === "tall" && "gap-[2px]"), children: [
662
- /* @__PURE__ */ jsx14("span", { className: cn("truncate text-[14px] leading-[140%]", destructive ? "text-error-default" : "text-text-primary"), children: label }),
663
- description && /* @__PURE__ */ jsx14("span", { className: "truncate text-[12px] leading-[120%] text-text-secondary", children: description })
946
+ 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);
947
+ return /* @__PURE__ */ jsxs9(Fragment2, { children: [
948
+ leading && /* @__PURE__ */ jsx17("span", { className: "flex shrink-0 items-center", children: leading }),
949
+ children ?? /* @__PURE__ */ jsxs9("span", { className: cn("flex min-w-0 flex-1 flex-col", size === "tall" && "gap-[2px]"), children: [
950
+ /* @__PURE__ */ jsx17("span", { className: cn("truncate text-[14px] leading-[140%]", destructive ? "text-error-default" : "text-text-primary"), children: label }),
951
+ description && /* @__PURE__ */ jsx17("span", { className: "truncate text-[12px] leading-[120%] text-text-secondary", children: description })
664
952
  ] }),
665
953
  (edge || hint) && // One grid cell holding both, right-aligned: the slot is as wide as
666
954
  // the wider of the two and never changes, so revealing the hint moves
667
955
  // nothing. No transition here either — the hint switches on the same
668
956
  // :hover / `selected` as the fill, in the same frame.
669
- /* @__PURE__ */ jsxs8("span", { className: "grid shrink-0 items-center justify-items-end [&>*]:col-start-1 [&>*]:row-start-1", children: [
670
- edge && /* @__PURE__ */ jsx14("span", { className: cn("flex items-center", hint && "group-hover:opacity-0 group-data-[highlighted]:opacity-0", hint && selected && "opacity-0"), children: edge }),
671
- hint && /* @__PURE__ */ jsx14("span", { className: cn("flex items-center opacity-0 group-hover:opacity-100 group-data-[highlighted]:opacity-100", selected && "opacity-100"), children: hint })
957
+ /* @__PURE__ */ jsxs9("span", { className: "grid shrink-0 items-center justify-items-end [&>*]:col-start-1 [&>*]:row-start-1", children: [
958
+ 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 }),
959
+ 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 })
672
960
  ] })
673
961
  ] });
674
962
  }
675
963
  function MenuItem({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected, className, ...props }) {
676
- const body = /* @__PURE__ */ jsx14(
964
+ const body = /* @__PURE__ */ jsx17(
677
965
  MenuItemBody,
678
966
  {
679
967
  label,
@@ -691,13 +979,13 @@ function MenuItem({ label, children, size = "default", description, leading, tra
691
979
  );
692
980
  const rowClassName = menuItemClassName({ size, selected, className });
693
981
  if (!useContext(MenuContext)) {
694
- return /* @__PURE__ */ jsx14("button", { type: "button", className: rowClassName, ...props, children: body });
982
+ return /* @__PURE__ */ jsx17("button", { type: "button", className: rowClassName, ...props, children: body });
695
983
  }
696
- return /* @__PURE__ */ jsx14(
984
+ return /* @__PURE__ */ jsx17(
697
985
  BaseMenu.Item,
698
986
  {
699
987
  nativeButton: true,
700
- render: /* @__PURE__ */ jsx14("button", { type: "button" }),
988
+ render: /* @__PURE__ */ jsx17("button", { type: "button" }),
701
989
  className: rowClassName,
702
990
  ...props,
703
991
  children: body
@@ -705,31 +993,31 @@ function MenuItem({ label, children, size = "default", description, leading, tra
705
993
  );
706
994
  }
707
995
  function EnterHint({ target }) {
708
- return /* @__PURE__ */ jsxs8("span", { className: "flex shrink-0 items-center gap-1.5 text-text-muted", children: [
709
- /* @__PURE__ */ jsx14(Kbd, { children: "\u21A9 Enter" }),
710
- target && /* @__PURE__ */ jsx14("span", { className: "text-[9px] font-medium leading-[115%] signal:font-mono signal:text-[9.5px] signal:tracking-[0.04em]", children: target })
996
+ return /* @__PURE__ */ jsxs9("span", { className: "flex shrink-0 items-center gap-1.5 text-text-muted", children: [
997
+ /* @__PURE__ */ jsx17(Kbd, { children: "\u21A9 Enter" }),
998
+ target && /* @__PURE__ */ jsx17("span", { className: "text-[9px] font-medium leading-[115%] signal:font-mono signal:text-[9.5px] signal:tracking-[0.04em]", children: target })
711
999
  ] });
712
1000
  }
713
1001
  function MenuSection({ label, children, className }) {
714
1002
  const inMenu = useContext(MenuContext) !== null;
715
- const heading = /* @__PURE__ */ jsx14("div", { className: cn("flex h-8 items-center px-2", className), children: /* @__PURE__ */ jsx14(SectionLabel, { className: "text-text-secondary", children: label }) });
1003
+ 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 }) });
716
1004
  if (!inMenu) {
717
- return /* @__PURE__ */ jsxs8("div", { className: "flex flex-col", children: [
1005
+ return /* @__PURE__ */ jsxs9("div", { className: "flex flex-col", children: [
718
1006
  heading,
719
1007
  children
720
1008
  ] });
721
1009
  }
722
- return /* @__PURE__ */ jsxs8(BaseMenu.Group, { className: "flex flex-col", children: [
723
- /* @__PURE__ */ jsx14(BaseMenu.GroupLabel, { render: heading }),
1010
+ return /* @__PURE__ */ jsxs9(BaseMenu.Group, { className: "flex flex-col", children: [
1011
+ /* @__PURE__ */ jsx17(BaseMenu.GroupLabel, { render: heading }),
724
1012
  children
725
1013
  ] });
726
1014
  }
727
1015
  function MenuRow({ children, className }) {
728
- return /* @__PURE__ */ jsx14("div", { className: cn("flex items-center gap-2 px-2 py-1.5", className), children });
1016
+ return /* @__PURE__ */ jsx17("div", { className: cn("flex items-center gap-2 px-2 py-1.5", className), children });
729
1017
  }
730
1018
 
731
1019
  // src/ChipInput.tsx
732
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1020
+ import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
733
1021
  var CHIP_BOX = (
734
1022
  // Curved, not a pill (Katerina, 2026-09-01): the Avatar keeps its own
735
1023
  // rounded-sm corners — never a forced circle — and the chip's corner
@@ -740,11 +1028,11 @@ var CHIP_LABEL = "text-caption font-medium text-text-primary";
740
1028
  var CHIP_REMOVE = "size-4 flex items-center justify-center rounded-full hover:bg-bg-hover text-text-secondary";
741
1029
  var chipPadding = (leading, removable) => cn(leading ? "pl-[2px]" : "pl-2", removable ? "pr-1" : "pr-2");
742
1030
  function InputChip({ label, leading, onRemove, className }) {
743
- return /* @__PURE__ */ jsxs9("div", { className: cn(CHIP_BOX, chipPadding(!!leading, !!onRemove), className), children: [
744
- leading && /* @__PURE__ */ jsx15("span", { className: "flex shrink-0 items-center", children: leading }),
745
- /* @__PURE__ */ jsx15("span", { className: CHIP_LABEL, children: label }),
746
- onRemove && /* @__PURE__ */ jsx15(
747
- BaseButton3,
1031
+ return /* @__PURE__ */ jsxs10("div", { className: cn(CHIP_BOX, chipPadding(!!leading, !!onRemove), className), children: [
1032
+ leading && /* @__PURE__ */ jsx18("span", { className: "flex shrink-0 items-center", children: leading }),
1033
+ /* @__PURE__ */ jsx18("span", { className: CHIP_LABEL, children: label }),
1034
+ onRemove && /* @__PURE__ */ jsx18(
1035
+ BaseButton4,
748
1036
  {
749
1037
  type: "button",
750
1038
  onClick: (e) => {
@@ -753,7 +1041,7 @@ function InputChip({ label, leading, onRemove, className }) {
753
1041
  },
754
1042
  className: CHIP_REMOVE,
755
1043
  "aria-label": `Remove ${label}`,
756
- children: /* @__PURE__ */ jsx15(IconX2, { size: 10, stroke: 1.5 })
1044
+ children: /* @__PURE__ */ jsx18(IconX3, { size: 10, stroke: 1.5 })
757
1045
  }
758
1046
  )
759
1047
  ] });
@@ -769,8 +1057,8 @@ function ChipInput({
769
1057
  rowLeading,
770
1058
  ...aria
771
1059
  }) {
772
- const [query, setQuery] = useState2("");
773
- const [box, setBox] = useState2(null);
1060
+ const [query, setQuery] = useState3("");
1061
+ const [box, setBox] = useState3(null);
774
1062
  const available = useMemo(() => {
775
1063
  const chosen = new Set(value.map((o) => o.id));
776
1064
  const excluded = new Set(excludeIds);
@@ -806,7 +1094,7 @@ function ChipInput({
806
1094
  setQuery("");
807
1095
  }
808
1096
  }
809
- return /* @__PURE__ */ jsxs9(
1097
+ return /* @__PURE__ */ jsxs10(
810
1098
  Combobox.Root,
811
1099
  {
812
1100
  multiple: true,
@@ -823,13 +1111,13 @@ function ChipInput({
823
1111
  filter,
824
1112
  itemToStringLabel: (option) => option.label,
825
1113
  children: [
826
- /* @__PURE__ */ jsxs9(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: [
827
- value.map((option) => /* @__PURE__ */ jsxs9(Combobox.Chip, { className: cn(CHIP_BOX, chipPadding(!!chipLeading, true)), children: [
828
- chipLeading && /* @__PURE__ */ jsx15("span", { className: "flex shrink-0 items-center", children: chipLeading(option) }),
829
- /* @__PURE__ */ jsx15("span", { className: CHIP_LABEL, children: option.label }),
830
- /* @__PURE__ */ jsx15(Combobox.ChipRemove, { className: CHIP_REMOVE, "aria-label": `Remove ${option.label}`, children: /* @__PURE__ */ jsx15(IconX2, { size: 10, stroke: 1.5 }) })
1114
+ /* @__PURE__ */ jsxs10(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: [
1115
+ value.map((option) => /* @__PURE__ */ jsxs10(Combobox.Chip, { className: cn(CHIP_BOX, chipPadding(!!chipLeading, true)), children: [
1116
+ chipLeading && /* @__PURE__ */ jsx18("span", { className: "flex shrink-0 items-center", children: chipLeading(option) }),
1117
+ /* @__PURE__ */ jsx18("span", { className: CHIP_LABEL, children: option.label }),
1118
+ /* @__PURE__ */ jsx18(Combobox.ChipRemove, { className: CHIP_REMOVE, "aria-label": `Remove ${option.label}`, children: /* @__PURE__ */ jsx18(IconX3, { size: 10, stroke: 1.5 }) })
831
1119
  ] }, option.id)),
832
- /* @__PURE__ */ jsx15(
1120
+ /* @__PURE__ */ jsx18(
833
1121
  Combobox.Input,
834
1122
  {
835
1123
  autoFocus,
@@ -841,18 +1129,18 @@ function ChipInput({
841
1129
  }
842
1130
  )
843
1131
  ] }),
844
- /* @__PURE__ */ jsx15(Combobox.Portal, { children: /* @__PURE__ */ jsx15(
1132
+ /* @__PURE__ */ jsx18(Combobox.Portal, { children: /* @__PURE__ */ jsx18(
845
1133
  Combobox.Positioner,
846
1134
  {
847
1135
  anchor: box,
848
1136
  sideOffset: GAP3,
849
1137
  collisionPadding: VIEWPORT_PAD3,
850
1138
  className: "z-50 data-[anchor-hidden]:hidden",
851
- children: /* @__PURE__ */ jsx15(Combobox.Popup, { className: "w-[var(--anchor-width)] p-0", render: /* @__PURE__ */ jsx15(MenuPanel, {}), children: /* @__PURE__ */ jsx15(ScrollArea, { viewportClassName: "max-h-[240px]", contentClassName: "flex flex-col p-2", children: /* @__PURE__ */ jsx15(Combobox.List, { children: (option) => /* @__PURE__ */ jsx15(
1139
+ 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(
852
1140
  Combobox.Item,
853
1141
  {
854
1142
  value: option,
855
- render: /* @__PURE__ */ jsx15(
1143
+ render: /* @__PURE__ */ jsx18(
856
1144
  MenuItem,
857
1145
  {
858
1146
  size: "tall",
@@ -873,15 +1161,49 @@ function ChipInput({
873
1161
  var GAP3 = 4;
874
1162
  var VIEWPORT_PAD3 = 8;
875
1163
 
1164
+ // src/InlineChip.tsx
1165
+ import { Fragment as Fragment3, jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
1166
+ 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";
1167
+ var INLINE_CHIP_TONE_CLASSES = {
1168
+ /** A thing or a place — anything that is not a person. */
1169
+ neutral: "bg-bg-active text-text-primary",
1170
+ /** A person. */
1171
+ person: "bg-accent-muted text-accent-primary",
1172
+ /** A person, called urgently. */
1173
+ urgent: "bg-warning-muted text-warning-default",
1174
+ /**
1175
+ * A reference nobody could resolve — still a mention, just an anonymous one.
1176
+ * Its height is the body line's 19.6px written out, because `1.4em` here is
1177
+ * the caption's em: 16.8px, with the letters 1.8px above the sentence's
1178
+ * baseline. At 19.6px they sit 0.4px off it (measured 2026-09-14; Peek's
1179
+ * copy of this chip still has the 16.8px box).
1180
+ */
1181
+ quiet: "h-[19.6px] bg-bg-active text-text-muted font-mono text-caption"
1182
+ };
1183
+ function inlineChipClassName(tone, className) {
1184
+ return cn(INLINE_CHIP_CLASSES, INLINE_CHIP_TONE_CLASSES[tone], className);
1185
+ }
1186
+ function InlineChip({ tone = "neutral", icon, href, className, children, ...props }) {
1187
+ const body = /* @__PURE__ */ jsxs11(Fragment3, { children: [
1188
+ icon && /* @__PURE__ */ jsx19("span", { className: "flex size-4 shrink-0 items-center justify-center text-text-secondary", children: icon }),
1189
+ children
1190
+ ] });
1191
+ const classes = inlineChipClassName(tone, className);
1192
+ if (href === void 0) {
1193
+ return /* @__PURE__ */ jsx19("span", { className: classes, ...props, children: body });
1194
+ }
1195
+ return /* @__PURE__ */ jsx19("a", { href, className: classes, ...props, children: body });
1196
+ }
1197
+
876
1198
  // src/IdentityMenu.tsx
877
- import { useCallback, useRef } from "react";
1199
+ import { useCallback, useRef as useRef2 } from "react";
878
1200
 
879
1201
  // src/Divider.tsx
880
- import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
1202
+ import { jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
881
1203
  function Divider({ orientation = "horizontal", label, tone = "default", className }) {
882
1204
  if (label && orientation === "horizontal") {
883
1205
  const line = tone === "warning" ? "bg-warning-muted" : "bg-border-subtle";
884
- return /* @__PURE__ */ jsxs10(
1206
+ return /* @__PURE__ */ jsxs12(
885
1207
  "div",
886
1208
  {
887
1209
  role: "separator",
@@ -889,14 +1211,14 @@ function Divider({ orientation = "horizontal", label, tone = "default", classNam
889
1211
  "aria-label": label,
890
1212
  className: cn("flex shrink-0 items-center gap-2 mx-3", className),
891
1213
  children: [
892
- /* @__PURE__ */ jsx16("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
893
- /* @__PURE__ */ jsx16("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
894
- /* @__PURE__ */ jsx16("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
1214
+ /* @__PURE__ */ jsx20("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
1215
+ /* @__PURE__ */ jsx20("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
1216
+ /* @__PURE__ */ jsx20("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
895
1217
  ]
896
1218
  }
897
1219
  );
898
1220
  }
899
- return /* @__PURE__ */ jsx16(
1221
+ return /* @__PURE__ */ jsx20(
900
1222
  "div",
901
1223
  {
902
1224
  role: "separator",
@@ -907,27 +1229,27 @@ function Divider({ orientation = "horizontal", label, tone = "default", classNam
907
1229
  }
908
1230
 
909
1231
  // src/Person.tsx
910
- import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
1232
+ import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
911
1233
  function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
912
1234
  return (
913
1235
  // gap-2: the face-to-name distance is one rule (8px) wherever a person
914
1236
  // appears — Katerina, 2026-09-01, set on Person so PersonTrigger and every
915
1237
  // row agree by construction.
916
- /* @__PURE__ */ jsxs11("span", { className: cn("flex min-w-0 items-center gap-2", className), children: [
917
- /* @__PURE__ */ jsx17(Avatar, { name, src: picture, size }),
918
- /* @__PURE__ */ jsx17("span", { className: cn("truncate", !name && "text-text-muted"), children: name ?? fallback })
1238
+ /* @__PURE__ */ jsxs13("span", { className: cn("flex min-w-0 items-center gap-2", className), children: [
1239
+ /* @__PURE__ */ jsx21(Avatar, { name, src: picture, size }),
1240
+ /* @__PURE__ */ jsx21("span", { className: cn("truncate", !name && "text-text-muted"), children: name ?? fallback })
919
1241
  ] })
920
1242
  );
921
1243
  }
922
1244
 
923
1245
  // src/PersonTrigger.tsx
924
- import { Button as BaseButton4 } from "@base-ui/react/button";
1246
+ import { Button as BaseButton5 } from "@base-ui/react/button";
925
1247
  import { IconChevronDown } from "@tabler/icons-react";
926
- import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
1248
+ import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
927
1249
  function PersonTrigger({ name, picture, fallback, size, open = false, compact = false, className, ...props }) {
928
1250
  if (compact) {
929
- return /* @__PURE__ */ jsx18(
930
- BaseButton4,
1251
+ return /* @__PURE__ */ jsx22(
1252
+ BaseButton5,
931
1253
  {
932
1254
  type: "button",
933
1255
  "aria-haspopup": "menu",
@@ -935,12 +1257,12 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
935
1257
  "aria-label": props["aria-label"] ?? name ?? fallback,
936
1258
  className: cn("cursor-pointer rounded-full", className),
937
1259
  ...props,
938
- children: /* @__PURE__ */ jsx18(Avatar, { name, src: picture, size: size ?? 36 })
1260
+ children: /* @__PURE__ */ jsx22(Avatar, { name, src: picture, size: size ?? 36 })
939
1261
  }
940
1262
  );
941
1263
  }
942
- return /* @__PURE__ */ jsxs12(
943
- BaseButton4,
1264
+ return /* @__PURE__ */ jsxs14(
1265
+ BaseButton5,
944
1266
  {
945
1267
  type: "button",
946
1268
  "aria-haspopup": "menu",
@@ -957,18 +1279,18 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
957
1279
  ),
958
1280
  ...props,
959
1281
  children: [
960
- /* @__PURE__ */ jsx18(Person, { name, picture, fallback, size: size ?? 22 }),
961
- /* @__PURE__ */ jsx18(IconChevronDown, { size: 14, stroke: 1.5, className: "shrink-0 text-text-muted" })
1282
+ /* @__PURE__ */ jsx22(Person, { name, picture, fallback, size: size ?? 22 }),
1283
+ /* @__PURE__ */ jsx22(IconChevronDown, { size: 14, stroke: 1.5, className: "shrink-0 text-text-muted" })
962
1284
  ]
963
1285
  }
964
1286
  );
965
1287
  }
966
1288
 
967
1289
  // src/IdentityMenu.tsx
968
- import { Fragment as Fragment2, jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
1290
+ import { Fragment as Fragment4, jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
969
1291
  function IdentityPanel({ className, onClose = () => {
970
1292
  }, ...rest }) {
971
- return /* @__PURE__ */ jsx19(MenuPanel, { className: cn("w-72", className), children: /* @__PURE__ */ jsx19(IdentityRows, { ...rest, onClose }) });
1293
+ return /* @__PURE__ */ jsx23(MenuPanel, { className: cn("w-72", className), children: /* @__PURE__ */ jsx23(IdentityRows, { ...rest, onClose }) });
972
1294
  }
973
1295
  function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, onClose, children }) {
974
1296
  const act = (action) => () => {
@@ -976,53 +1298,53 @@ function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, on
976
1298
  action();
977
1299
  };
978
1300
  const appRows = typeof children === "function" ? children(onClose) : children;
979
- return /* @__PURE__ */ jsxs13(Fragment2, { children: [
980
- /* @__PURE__ */ jsxs13(MenuSection, { label: signedIn ? "Signed in as" : "Acting as", children: [
981
- /* @__PURE__ */ jsx19(MenuRow, { children: /* @__PURE__ */ jsx19(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28, className: "text-body-2-strong" }) }),
982
- /* @__PURE__ */ jsx19(Note, { children: signedIn ? "Your Estiva ID. The same person you are in every Estiva app." : "A key held by this browser only. Nobody else knows who you are." }),
983
- me.email && /* @__PURE__ */ jsxs13(Note, { children: [
1301
+ return /* @__PURE__ */ jsxs15(Fragment4, { children: [
1302
+ /* @__PURE__ */ jsxs15(MenuSection, { label: signedIn ? "Signed in as" : "Acting as", children: [
1303
+ /* @__PURE__ */ jsx23(MenuRow, { children: /* @__PURE__ */ jsx23(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28, className: "text-body-2-strong" }) }),
1304
+ /* @__PURE__ */ jsx23(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." }),
1305
+ me.email && /* @__PURE__ */ jsxs15(Note, { children: [
984
1306
  me.email,
985
1307
  " \xB7 known to Estiva, never published to the relay"
986
1308
  ] })
987
1309
  ] }),
988
- relayUrl && /* @__PURE__ */ jsxs13(Fragment2, { children: [
989
- /* @__PURE__ */ jsx19(Divider, { className: "mx-0 my-2" }),
990
- /* @__PURE__ */ jsxs13(MenuSection, { label: "Workspace", children: [
991
- /* @__PURE__ */ jsx19(MenuRow, { children: /* @__PURE__ */ jsx19("span", { className: "break-all font-mono text-caption text-text-primary", children: relayUrl }) }),
992
- /* @__PURE__ */ jsx19(Note, { children: "Everyone on this relay shares this workspace, in every app." })
1310
+ relayUrl && /* @__PURE__ */ jsxs15(Fragment4, { children: [
1311
+ /* @__PURE__ */ jsx23(Divider, { className: "mx-0 my-2" }),
1312
+ /* @__PURE__ */ jsxs15(MenuSection, { label: "Workspace", children: [
1313
+ /* @__PURE__ */ jsx23(MenuRow, { children: /* @__PURE__ */ jsx23("span", { className: "break-all font-mono text-caption text-text-primary", children: relayUrl }) }),
1314
+ /* @__PURE__ */ jsx23(Note, { children: "Everyone on this relay shares this workspace, in every app." })
993
1315
  ] })
994
1316
  ] }),
995
- appRows && /* @__PURE__ */ jsxs13(Fragment2, { children: [
996
- /* @__PURE__ */ jsx19(Divider, { className: "mx-0 my-2" }),
1317
+ appRows && /* @__PURE__ */ jsxs15(Fragment4, { children: [
1318
+ /* @__PURE__ */ jsx23(Divider, { className: "mx-0 my-2" }),
997
1319
  appRows
998
1320
  ] }),
999
- signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */ jsx19(Divider, { className: "mx-0 my-2" }) : null,
1000
- signedIn && idBase && /* @__PURE__ */ jsx19(
1321
+ signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */ jsx23(Divider, { className: "mx-0 my-2" }) : null,
1322
+ signedIn && idBase && /* @__PURE__ */ jsx23(
1001
1323
  MenuItem,
1002
1324
  {
1003
1325
  label: "Edit your profile in Estiva ID",
1004
1326
  onClick: act(() => window.open(idBase, "_blank", "noopener,noreferrer"))
1005
1327
  }
1006
1328
  ),
1007
- onCopyKey && /* @__PURE__ */ jsx19(MenuItem, { label: "Copy public key", onClick: act(onCopyKey) }),
1008
- idBase && onSignOut && /* @__PURE__ */ jsx19(MenuItem, { label: "Sign out", onClick: act(onSignOut) })
1329
+ onCopyKey && /* @__PURE__ */ jsx23(MenuItem, { label: "Copy public key", onClick: act(onCopyKey) }),
1330
+ idBase && onSignOut && /* @__PURE__ */ jsx23(MenuItem, { label: "Sign out", onClick: act(onSignOut) })
1009
1331
  ] });
1010
1332
  }
1011
1333
  function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, compact = false, className, children }) {
1012
- const actions = useRef(null);
1334
+ const actions = useRef2(null);
1013
1335
  const close = useCallback(() => actions.current?.close(), []);
1014
1336
  return (
1015
1337
  /* The wrapper carries the caller's `className` and nothing else. It used
1016
1338
  to be `relative`, because the panel was positioned against it; the panel
1017
1339
  hangs from the trigger and portals now, so a positioning context here
1018
1340
  would only be a lie about what this box does. */
1019
- /* @__PURE__ */ jsx19("div", { className, children: /* @__PURE__ */ jsx19(
1341
+ /* @__PURE__ */ jsx23("div", { className, children: /* @__PURE__ */ jsx23(
1020
1342
  Menu,
1021
1343
  {
1022
1344
  align: "right",
1023
1345
  actionsRef: actions,
1024
1346
  className: "w-72",
1025
- trigger: /* @__PURE__ */ jsx19(
1347
+ trigger: /* @__PURE__ */ jsx23(
1026
1348
  PersonTrigger,
1027
1349
  {
1028
1350
  name: me.name,
@@ -1033,7 +1355,7 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
1033
1355
  "aria-label": compact ? "Account menu" : void 0
1034
1356
  }
1035
1357
  ),
1036
- children: /* @__PURE__ */ jsx19(
1358
+ children: /* @__PURE__ */ jsx23(
1037
1359
  IdentityRows,
1038
1360
  {
1039
1361
  me,
@@ -1051,13 +1373,13 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
1051
1373
  );
1052
1374
  }
1053
1375
  function Note({ children }) {
1054
- return /* @__PURE__ */ jsx19("span", { className: "px-2 pb-1.5 text-caption text-text-secondary", children });
1376
+ return /* @__PURE__ */ jsx23("span", { className: "px-2 pb-1.5 text-caption text-text-secondary", children });
1055
1377
  }
1056
1378
 
1057
1379
  // src/Field.tsx
1058
1380
  import { cloneElement, isValidElement } from "react";
1059
1381
  import { Field as BaseField } from "@base-ui/react/field";
1060
- import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
1382
+ import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
1061
1383
  var LINE_STYLES = {
1062
1384
  helper: "text-caption text-text-muted",
1063
1385
  warning: "text-caption text-warning-default",
@@ -1067,30 +1389,30 @@ function Field({ label, required = false, helper, error, children }) {
1067
1389
  const control = required && isValidElement(children) ? cloneElement(children, {
1068
1390
  "aria-required": children.props["aria-required"] ?? true
1069
1391
  }) : children;
1070
- return /* @__PURE__ */ jsxs14(BaseField.Root, { invalid: !!error, className: "flex flex-col gap-2", children: [
1071
- /* @__PURE__ */ jsxs14(BaseField.Label, { className: cn("text-input-label text-text-primary", required && "flex items-center"), children: [
1392
+ return /* @__PURE__ */ jsxs16(BaseField.Root, { invalid: !!error, className: "flex flex-col gap-2", children: [
1393
+ /* @__PURE__ */ jsxs16(BaseField.Label, { className: cn("text-input-label text-text-primary", required && "flex items-center"), children: [
1072
1394
  label,
1073
- required && /* @__PURE__ */ jsx20("span", { "aria-hidden": "true", className: "text-error-default ml-0.5", children: "*" })
1395
+ required && /* @__PURE__ */ jsx24("span", { "aria-hidden": "true", className: "text-error-default ml-0.5", children: "*" })
1074
1396
  ] }),
1075
- /* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1.5", children: [
1397
+ /* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-1.5", children: [
1076
1398
  control,
1077
- error != null ? /* @__PURE__ */ jsx20(BaseField.Error, { match: true, className: LINE_STYLES.error, children: error }) : helper != null ? /* @__PURE__ */ jsx20(BaseField.Description, { className: LINE_STYLES.helper, children: helper }) : null
1399
+ error != null ? /* @__PURE__ */ jsx24(BaseField.Error, { match: true, className: LINE_STYLES.error, children: error }) : helper != null ? /* @__PURE__ */ jsx24(BaseField.Description, { className: LINE_STYLES.helper, children: helper }) : null
1078
1400
  ] })
1079
1401
  ] });
1080
1402
  }
1081
1403
  function FieldLine({ tone = "helper", children, className }) {
1082
- return /* @__PURE__ */ jsx20("p", { role: tone === "error" ? "alert" : "status", className: cn(LINE_STYLES[tone], className), children });
1404
+ return /* @__PURE__ */ jsx24("p", { role: tone === "error" ? "alert" : "status", className: cn(LINE_STYLES[tone], className), children });
1083
1405
  }
1084
1406
 
1085
1407
  // src/Select.tsx
1086
1408
  import { IconCheck as IconCheck2, IconChevronDown as IconChevronDown2 } from "@tabler/icons-react";
1087
1409
  import { Select as BaseSelect } from "@base-ui/react/select";
1088
- import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
1410
+ import { jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
1089
1411
  var GAP4 = 4;
1090
1412
  var VIEWPORT_PAD4 = 8;
1091
1413
  function Select({ value, onChange, options, size = "default", ariaLabel, placeholder = "Select\u2026", disabled, className, ...aria }) {
1092
1414
  const selected = options.find((o) => o.value === value);
1093
- return /* @__PURE__ */ jsxs15(
1415
+ return /* @__PURE__ */ jsxs17(
1094
1416
  BaseSelect.Root,
1095
1417
  {
1096
1418
  value,
@@ -1098,7 +1420,7 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
1098
1420
  disabled,
1099
1421
  modal: false,
1100
1422
  children: [
1101
- /* @__PURE__ */ jsxs15(
1423
+ /* @__PURE__ */ jsxs17(
1102
1424
  BaseSelect.Trigger,
1103
1425
  {
1104
1426
  "aria-label": ariaLabel,
@@ -1125,20 +1447,20 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
1125
1447
  className
1126
1448
  ),
1127
1449
  children: [
1128
- /* @__PURE__ */ jsxs15("span", { className: cn("flex min-w-0 items-center gap-2", !selected && "text-text-muted"), children: [
1129
- selected?.leading && /* @__PURE__ */ jsx21("span", { className: "flex shrink-0 items-center", children: selected.leading }),
1130
- /* @__PURE__ */ jsx21(BaseSelect.Value, { className: "truncate", children: () => selected?.label ?? placeholder })
1450
+ /* @__PURE__ */ jsxs17("span", { className: cn("flex min-w-0 items-center gap-2", !selected && "text-text-muted"), children: [
1451
+ selected?.leading && /* @__PURE__ */ jsx25("span", { className: "flex shrink-0 items-center", children: selected.leading }),
1452
+ /* @__PURE__ */ jsx25(BaseSelect.Value, { className: "truncate", children: () => selected?.label ?? placeholder })
1131
1453
  ] }),
1132
- /* @__PURE__ */ jsx21(
1454
+ /* @__PURE__ */ jsx25(
1133
1455
  BaseSelect.Icon,
1134
1456
  {
1135
- render: /* @__PURE__ */ jsx21(IconChevronDown2, { size: size === "small" ? 14 : 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
1457
+ render: /* @__PURE__ */ jsx25(IconChevronDown2, { size: size === "small" ? 14 : 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
1136
1458
  }
1137
1459
  )
1138
1460
  ]
1139
1461
  }
1140
1462
  ),
1141
- /* @__PURE__ */ jsx21(BaseSelect.Portal, { children: /* @__PURE__ */ jsx21(
1463
+ /* @__PURE__ */ jsx25(BaseSelect.Portal, { children: /* @__PURE__ */ jsx25(
1142
1464
  BaseSelect.Positioner,
1143
1465
  {
1144
1466
  side: "bottom",
@@ -1147,25 +1469,25 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
1147
1469
  collisionPadding: VIEWPORT_PAD4,
1148
1470
  alignItemWithTrigger: false,
1149
1471
  className: "z-50 data-[anchor-hidden]:hidden",
1150
- children: /* @__PURE__ */ jsx21(
1472
+ children: /* @__PURE__ */ jsx25(
1151
1473
  BaseSelect.Popup,
1152
1474
  {
1153
- render: /* @__PURE__ */ jsx21(MenuPanel, {}),
1475
+ render: /* @__PURE__ */ jsx25(MenuPanel, {}),
1154
1476
  className: "min-w-[var(--anchor-width)] p-0",
1155
- children: /* @__PURE__ */ jsx21(ScrollArea, { viewportClassName: "max-h-[min(288px,var(--available-height))]", contentClassName: "flex flex-col p-2", children: options.map((option) => /* @__PURE__ */ jsxs15(
1477
+ children: /* @__PURE__ */ jsx25(ScrollArea, { viewportClassName: "max-h-[min(288px,var(--available-height))]", contentClassName: "flex flex-col p-2", children: options.map((option) => /* @__PURE__ */ jsxs17(
1156
1478
  BaseSelect.Item,
1157
1479
  {
1158
1480
  value: option.value,
1159
1481
  className: cn(menuItemClassName({ size: "default" }), "justify-between data-[selected]:font-medium"),
1160
1482
  children: [
1161
- /* @__PURE__ */ jsxs15("span", { className: "flex min-w-0 items-center gap-2", children: [
1162
- option.leading && /* @__PURE__ */ jsx21("span", { className: "flex shrink-0 items-center", children: option.leading }),
1163
- /* @__PURE__ */ jsx21(BaseSelect.ItemText, { className: "truncate text-[14px] leading-[140%] text-text-primary", children: option.label })
1483
+ /* @__PURE__ */ jsxs17("span", { className: "flex min-w-0 items-center gap-2", children: [
1484
+ option.leading && /* @__PURE__ */ jsx25("span", { className: "flex shrink-0 items-center", children: option.leading }),
1485
+ /* @__PURE__ */ jsx25(BaseSelect.ItemText, { className: "truncate text-[14px] leading-[140%] text-text-primary", children: option.label })
1164
1486
  ] }),
1165
- /* @__PURE__ */ jsx21(
1487
+ /* @__PURE__ */ jsx25(
1166
1488
  BaseSelect.ItemIndicator,
1167
1489
  {
1168
- render: /* @__PURE__ */ jsx21(IconCheck2, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
1490
+ render: /* @__PURE__ */ jsx25(IconCheck2, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
1169
1491
  }
1170
1492
  )
1171
1493
  ]
@@ -1184,9 +1506,9 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
1184
1506
  // src/TextInput.tsx
1185
1507
  import { forwardRef } from "react";
1186
1508
  import { Input } from "@base-ui/react/input";
1187
- import { jsx as jsx22 } from "react/jsx-runtime";
1509
+ import { jsx as jsx26 } from "react/jsx-runtime";
1188
1510
  var TextInput = forwardRef(function TextInput2({ className, type = "text", ...props }, ref) {
1189
- return /* @__PURE__ */ jsx22(
1511
+ return /* @__PURE__ */ jsx26(
1190
1512
  Input,
1191
1513
  {
1192
1514
  ref,
@@ -1207,13 +1529,13 @@ var TextInput = forwardRef(function TextInput2({ className, type = "text", ...pr
1207
1529
  // src/Textarea.tsx
1208
1530
  import { forwardRef as forwardRef2 } from "react";
1209
1531
  import { Field as BaseField2 } from "@base-ui/react/field";
1210
- import { jsx as jsx23 } from "react/jsx-runtime";
1532
+ import { jsx as jsx27 } from "react/jsx-runtime";
1211
1533
  var Textarea = forwardRef2(function Textarea2({ className, ...props }, ref) {
1212
- return /* @__PURE__ */ jsx23(
1534
+ return /* @__PURE__ */ jsx27(
1213
1535
  BaseField2.Control,
1214
1536
  {
1215
1537
  ref,
1216
- render: /* @__PURE__ */ jsx23("textarea", {}),
1538
+ render: /* @__PURE__ */ jsx27("textarea", {}),
1217
1539
  className: cn(
1218
1540
  "bg-bg-inset border border-border-default focus:border-border-focus rounded-lg px-3 py-2",
1219
1541
  "text-[14px] leading-[1.4] font-normal text-text-primary placeholder:text-text-muted",
@@ -1228,27 +1550,27 @@ var Textarea = forwardRef2(function Textarea2({ className, ...props }, ref) {
1228
1550
  });
1229
1551
 
1230
1552
  // src/ConfirmDialog.tsx
1231
- import { useState as useState3 } from "react";
1553
+ import { useState as useState4 } from "react";
1232
1554
 
1233
1555
  // src/DialogShell.tsx
1234
- import { useRef as useRef2 } from "react";
1556
+ import { useRef as useRef3 } from "react";
1235
1557
  import { Dialog } from "@base-ui/react/dialog";
1236
1558
  import { AlertDialog } from "@base-ui/react/alert-dialog";
1237
- import { IconX as IconX3 } from "@tabler/icons-react";
1238
- import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
1559
+ import { IconX as IconX4 } from "@tabler/icons-react";
1560
+ import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
1239
1561
  function DialogShell({ title, onClose, headerContent, footer, children, bodyClassName, bodyMaxHeight, width = 502, alert = false }) {
1240
1562
  const Parts = alert ? AlertDialog : Dialog;
1241
- const popupRef = useRef2(null);
1242
- return /* @__PURE__ */ jsx24(
1563
+ const popupRef = useRef3(null);
1564
+ return /* @__PURE__ */ jsx28(
1243
1565
  Parts.Root,
1244
1566
  {
1245
1567
  open: true,
1246
1568
  onOpenChange: (open) => {
1247
1569
  if (!open) onClose();
1248
1570
  },
1249
- children: /* @__PURE__ */ jsxs16(Parts.Portal, { children: [
1250
- /* @__PURE__ */ jsx24(Parts.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
1251
- /* @__PURE__ */ jsx24("div", { className: "fixed inset-0 z-50 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs16(
1571
+ children: /* @__PURE__ */ jsxs18(Parts.Portal, { children: [
1572
+ /* @__PURE__ */ jsx28(Parts.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
1573
+ /* @__PURE__ */ jsx28("div", { className: "fixed inset-0 z-50 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs18(
1252
1574
  Parts.Popup,
1253
1575
  {
1254
1576
  ref: popupRef,
@@ -1257,16 +1579,16 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
1257
1579
  className: "bg-bg-elevated border border-border-subtle rounded-lg shadow-lg pointer-events-auto flex flex-col overflow-hidden outline-none",
1258
1580
  style: { width },
1259
1581
  children: [
1260
- /* @__PURE__ */ jsxs16("div", { className: "h-12 flex items-center justify-between pl-5 pr-4 border-b border-border-subtle shrink-0", children: [
1261
- headerContent ?? /* @__PURE__ */ jsx24(Parts.Title, { className: "text-h4 text-text-primary", render: /* @__PURE__ */ jsx24("span", {}), children: title }),
1262
- /* @__PURE__ */ jsx24(
1582
+ /* @__PURE__ */ jsxs18("div", { className: "h-12 flex items-center justify-between pl-5 pr-4 border-b border-border-subtle shrink-0", children: [
1583
+ headerContent ?? /* @__PURE__ */ jsx28(Parts.Title, { className: "text-h4 text-text-primary", render: /* @__PURE__ */ jsx28("span", {}), children: title }),
1584
+ /* @__PURE__ */ jsx28(
1263
1585
  Parts.Close,
1264
1586
  {
1265
- render: /* @__PURE__ */ jsx24(IconButton, { tooltip: "Close", "aria-label": "Close", children: /* @__PURE__ */ jsx24(IconX3, { size: 16, stroke: 1.5 }) })
1587
+ render: /* @__PURE__ */ jsx28(IconButton, { tooltip: "Close", "aria-label": "Close", children: /* @__PURE__ */ jsx28(IconX4, { size: 16, stroke: 1.5 }) })
1266
1588
  }
1267
1589
  )
1268
1590
  ] }),
1269
- bodyMaxHeight ? /* @__PURE__ */ jsx24(
1591
+ bodyMaxHeight ? /* @__PURE__ */ jsx28(
1270
1592
  ScrollArea,
1271
1593
  {
1272
1594
  className: cn(footer != null && "border-b border-border-subtle"),
@@ -1274,8 +1596,8 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
1274
1596
  contentClassName: cn("pl-5 pr-4 py-4", bodyClassName),
1275
1597
  children
1276
1598
  }
1277
- ) : /* @__PURE__ */ jsx24("div", { className: cn("pl-5 pr-4 py-4", footer != null && "border-b border-border-subtle", bodyClassName), children }),
1278
- footer != null && /* @__PURE__ */ jsx24("div", { className: "h-12 flex items-center justify-end gap-2 pl-5 pr-4 shrink-0", children: footer })
1599
+ ) : /* @__PURE__ */ jsx28("div", { className: cn("pl-5 pr-4 py-4", footer != null && "border-b border-border-subtle", bodyClassName), children }),
1600
+ footer != null && /* @__PURE__ */ jsx28("div", { className: "h-12 flex items-center justify-end gap-2 pl-5 pr-4 shrink-0", children: footer })
1279
1601
  ]
1280
1602
  }
1281
1603
  ) })
@@ -1285,9 +1607,9 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
1285
1607
  }
1286
1608
 
1287
1609
  // src/ConfirmDialog.tsx
1288
- import { Fragment as Fragment3, jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
1610
+ import { Fragment as Fragment5, jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
1289
1611
  function ConfirmDialog({ title, children, confirmLabel, destructive = false, onConfirm, onClose }) {
1290
- const [busy, setBusy] = useState3(false);
1612
+ const [busy, setBusy] = useState4(false);
1291
1613
  const confirm = async () => {
1292
1614
  setBusy(true);
1293
1615
  try {
@@ -1297,16 +1619,16 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
1297
1619
  setBusy(false);
1298
1620
  }
1299
1621
  };
1300
- return /* @__PURE__ */ jsx25(
1622
+ return /* @__PURE__ */ jsx29(
1301
1623
  DialogShell,
1302
1624
  {
1303
1625
  alert: true,
1304
1626
  title,
1305
1627
  onClose,
1306
1628
  bodyClassName: "flex flex-col gap-3 text-body-2 text-text-primary",
1307
- footer: /* @__PURE__ */ jsxs17(Fragment3, { children: [
1308
- /* @__PURE__ */ jsx25(Button, { variant: "muted", onClick: onClose, disabled: busy, children: "Cancel" }),
1309
- /* @__PURE__ */ jsx25(Button, { variant: destructive ? "destructive" : "primary", onClick: () => void confirm(), disabled: busy, children: confirmLabel })
1629
+ footer: /* @__PURE__ */ jsxs19(Fragment5, { children: [
1630
+ /* @__PURE__ */ jsx29(Button, { variant: "muted", onClick: onClose, disabled: busy, children: "Cancel" }),
1631
+ /* @__PURE__ */ jsx29(Button, { variant: destructive ? "destructive" : "primary", onClick: () => void confirm(), disabled: busy, children: confirmLabel })
1310
1632
  ] }),
1311
1633
  children
1312
1634
  }
@@ -1314,15 +1636,15 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
1314
1636
  }
1315
1637
 
1316
1638
  // src/EditableText.tsx
1317
- import { useEffect, useRef as useRef3, useState as useState4 } from "react";
1639
+ import { useEffect, useRef as useRef4, useState as useState5 } from "react";
1318
1640
  import { Field as BaseField3 } from "@base-ui/react/field";
1319
1641
  import { Input as Input2 } from "@base-ui/react/input";
1320
- import { jsx as jsx26 } from "react/jsx-runtime";
1642
+ import { jsx as jsx30 } from "react/jsx-runtime";
1321
1643
  function EditableText({ value, display, displayNode, placeholder, onCommit, multiline = false, className, label, readOnly = false }) {
1322
- const [editing, setEditing] = useState4(false);
1323
- const [draft, setDraft] = useState4(value);
1324
- const [busy, setBusy] = useState4(false);
1325
- const fieldRef = useRef3(null);
1644
+ const [editing, setEditing] = useState5(false);
1645
+ const [draft, setDraft] = useState5(value);
1646
+ const [busy, setBusy] = useState5(false);
1647
+ const fieldRef = useRef4(null);
1326
1648
  useEffect(() => {
1327
1649
  if (editing) {
1328
1650
  fieldRef.current?.focus();
@@ -1375,7 +1697,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
1375
1697
  written and never read. Read-only, this is a line of text: whatever
1376
1698
  names the region around it (a `Field`, a `Property`) names this too.
1377
1699
  */
1378
- /* @__PURE__ */ jsx26(
1700
+ /* @__PURE__ */ jsx30(
1379
1701
  "div",
1380
1702
  {
1381
1703
  className: cn("w-full px-2 py-1", multiline && !displayNode && "whitespace-pre-wrap", display ?? value ? "text-text-primary" : "text-text-muted", className),
@@ -1385,11 +1707,11 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
1385
1707
  );
1386
1708
  }
1387
1709
  if (editing) {
1388
- return multiline ? /* @__PURE__ */ jsx26(
1710
+ return multiline ? /* @__PURE__ */ jsx30(
1389
1711
  BaseField3.Control,
1390
1712
  {
1391
1713
  ref: fieldRef,
1392
- render: /* @__PURE__ */ jsx26("textarea", { rows: 4 }),
1714
+ render: /* @__PURE__ */ jsx30("textarea", { rows: 4 }),
1393
1715
  "aria-label": label,
1394
1716
  value: draft,
1395
1717
  disabled: busy,
@@ -1398,7 +1720,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
1398
1720
  onBlur: () => void commit(),
1399
1721
  className: fieldClass
1400
1722
  }
1401
- ) : /* @__PURE__ */ jsx26(
1723
+ ) : /* @__PURE__ */ jsx30(
1402
1724
  Input2,
1403
1725
  {
1404
1726
  ref: fieldRef,
@@ -1412,7 +1734,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
1412
1734
  }
1413
1735
  );
1414
1736
  }
1415
- return /* @__PURE__ */ jsx26(
1737
+ return /* @__PURE__ */ jsx30(
1416
1738
  "button",
1417
1739
  {
1418
1740
  type: "button",
@@ -1431,40 +1753,59 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
1431
1753
 
1432
1754
  // src/EmptyState.tsx
1433
1755
  import { IconMessage2 } from "@tabler/icons-react";
1434
- import { jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
1756
+ import { jsx as jsx31, jsxs as jsxs20 } from "react/jsx-runtime";
1435
1757
  function EmptyState({ icon, message, scope = "page", className }) {
1436
1758
  if (scope === "section") {
1437
- return /* @__PURE__ */ jsx27("p", { className: cn("text-body-2 text-text-secondary", className), children: message });
1759
+ return /* @__PURE__ */ jsx31("p", { className: cn("text-body-2 text-text-secondary", className), children: message });
1438
1760
  }
1439
- return /* @__PURE__ */ jsxs18("div", { className: cn("flex flex-1 flex-col items-center justify-center gap-2", className), children: [
1440
- /* @__PURE__ */ jsx27("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx27(IconMessage2, { size: 16, stroke: 1.5 }) }),
1441
- /* @__PURE__ */ jsx27("p", { className: "text-body-2 text-text-secondary text-center", children: message })
1761
+ return /* @__PURE__ */ jsxs20("div", { className: cn("flex flex-1 flex-col items-center justify-center gap-2", className), children: [
1762
+ /* @__PURE__ */ jsx31("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx31(IconMessage2, { size: 16, stroke: 1.5 }) }),
1763
+ /* @__PURE__ */ jsx31("p", { className: "text-body-2 text-text-secondary text-center", children: message })
1442
1764
  ] });
1443
1765
  }
1444
1766
 
1767
+ // src/ProgressBar.tsx
1768
+ import { Progress } from "@base-ui/react/progress";
1769
+ import { jsx as jsx32 } from "react/jsx-runtime";
1770
+ var TRACK_CLASSES = {
1771
+ default: "h-1.5 w-full overflow-hidden rounded-full bg-bg-inset",
1772
+ // 4px, Katerina's ruling of 14 September; Peek's own bar is 3px until it takes this one.
1773
+ quiet: "h-1 w-full overflow-hidden rounded-full bg-bg-inset"
1774
+ };
1775
+ var INDICATOR_CLASSES = {
1776
+ default: "h-full rounded-full bg-success-default transition-[width]",
1777
+ quiet: "h-full rounded-full bg-success-muted transition-[width] duration-300"
1778
+ };
1779
+ function ProgressBar({ value, max, label, variant = "default", className }) {
1780
+ return (
1781
+ // `max={0}` needs no guard: Base UI reads the 0/0 share as an empty bar.
1782
+ /* @__PURE__ */ jsx32(Progress.Root, { value, max, "aria-label": label, className, children: /* @__PURE__ */ jsx32(Progress.Track, { className: TRACK_CLASSES[variant], children: /* @__PURE__ */ jsx32(Progress.Indicator, { className: INDICATOR_CLASSES[variant] }) }) })
1783
+ );
1784
+ }
1785
+
1445
1786
  // src/Skeleton.tsx
1446
- import { jsx as jsx28, jsxs as jsxs19 } from "react/jsx-runtime";
1787
+ import { jsx as jsx33, jsxs as jsxs21 } from "react/jsx-runtime";
1447
1788
  function SkeletonBar({ className, style }) {
1448
- return /* @__PURE__ */ jsx28("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
1789
+ return /* @__PURE__ */ jsx33("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
1449
1790
  }
1450
1791
  var ROW_BAR_WIDTHS = [150, 100, 170, 120, 90, 140, 110, 160];
1451
1792
  function SkeletonRow({ barWidth = 130 }) {
1452
- return /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2 px-2 h-[32px] rounded-lg", children: [
1453
- /* @__PURE__ */ jsx28(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
1454
- /* @__PURE__ */ jsx28(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
1793
+ return /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-2 px-2 h-[32px] rounded-lg", children: [
1794
+ /* @__PURE__ */ jsx33(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
1795
+ /* @__PURE__ */ jsx33(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
1455
1796
  ] });
1456
1797
  }
1457
1798
  function SkeletonList({ rows = 8, className }) {
1458
- return /* @__PURE__ */ jsx28("div", { className: cn("flex flex-col gap-0.5 animate-skeleton-in", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx28(SkeletonRow, { barWidth: ROW_BAR_WIDTHS[i % ROW_BAR_WIDTHS.length] }, i)) });
1799
+ return /* @__PURE__ */ jsx33("div", { className: cn("flex flex-col gap-0.5 animate-skeleton-in", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx33(SkeletonRow, { barWidth: ROW_BAR_WIDTHS[i % ROW_BAR_WIDTHS.length] }, i)) });
1459
1800
  }
1460
1801
 
1461
1802
  // src/Breadcrumb.tsx
1462
- import { Fragment as Fragment4, useCallback as useCallback2, useLayoutEffect, useRef as useRef4, useState as useState5 } from "react";
1463
- import { jsx as jsx29, jsxs as jsxs20 } from "react/jsx-runtime";
1803
+ import { Fragment as Fragment6, useCallback as useCallback2, useLayoutEffect as useLayoutEffect2, useRef as useRef5, useState as useState6 } from "react";
1804
+ import { jsx as jsx34, jsxs as jsxs22 } from "react/jsx-runtime";
1464
1805
  function Breadcrumb({ items, className }) {
1465
- const navRef = useRef4(null);
1466
- const labelRefs = useRef4([]);
1467
- const [truncated, setTruncated] = useState5(/* @__PURE__ */ new Set());
1806
+ const navRef = useRef5(null);
1807
+ const labelRefs = useRef5([]);
1808
+ const [truncated, setTruncated] = useState6(/* @__PURE__ */ new Set());
1468
1809
  const measure = useCallback2(() => {
1469
1810
  const next = /* @__PURE__ */ new Set();
1470
1811
  labelRefs.current.forEach((el, index) => {
@@ -1472,7 +1813,7 @@ function Breadcrumb({ items, className }) {
1472
1813
  });
1473
1814
  setTruncated((prev) => prev.size === next.size && [...next].every((i) => prev.has(i)) ? prev : next);
1474
1815
  }, []);
1475
- useLayoutEffect(() => {
1816
+ useLayoutEffect2(() => {
1476
1817
  measure();
1477
1818
  const nav = navRef.current;
1478
1819
  if (!nav || typeof ResizeObserver === "undefined") return;
@@ -1480,7 +1821,7 @@ function Breadcrumb({ items, className }) {
1480
1821
  observer.observe(nav);
1481
1822
  return () => observer.disconnect();
1482
1823
  }, [measure, items]);
1483
- return /* @__PURE__ */ jsx29("nav", { ref: navRef, "aria-label": "Breadcrumb", className: cn("flex min-w-0 items-center gap-1.5 text-[14px] leading-[140%]", className), children: items.map((item, index) => {
1824
+ return /* @__PURE__ */ jsx34("nav", { ref: navRef, "aria-label": "Breadcrumb", className: cn("flex min-w-0 items-center gap-1.5 text-[14px] leading-[140%]", className), children: items.map((item, index) => {
1484
1825
  const last = index === items.length - 1;
1485
1826
  const tone = item.muted || last && item.mono ? "text-text-muted" : last ? "text-text-primary" : "text-text-secondary";
1486
1827
  const text = cn(
@@ -1494,24 +1835,24 @@ function Breadcrumb({ items, className }) {
1494
1835
  const setLabelRef = (el) => {
1495
1836
  labelRefs.current[index] = el;
1496
1837
  };
1497
- const crumb = item.href ? /* @__PURE__ */ jsx29("a", { ref: setLabelRef, href: item.href, onClick: item.onClick, className: cn(text, "hover:text-text-primary"), children: item.label }) : /* @__PURE__ */ jsx29("span", { ref: setLabelRef, className: text, "aria-current": last ? "page" : void 0, children: item.label });
1498
- return /* @__PURE__ */ jsxs20(Fragment4, { children: [
1499
- index > 0 && /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
1500
- item.icon && /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", className: cn("flex shrink-0", tone), children: item.icon }),
1838
+ const crumb = item.href ? /* @__PURE__ */ jsx34("a", { ref: setLabelRef, href: item.href, onClick: item.onClick, className: cn(text, "hover:text-text-primary"), children: item.label }) : /* @__PURE__ */ jsx34("span", { ref: setLabelRef, className: text, "aria-current": last ? "page" : void 0, children: item.label });
1839
+ return /* @__PURE__ */ jsxs22(Fragment6, { children: [
1840
+ index > 0 && /* @__PURE__ */ jsx34("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
1841
+ item.icon && /* @__PURE__ */ jsx34("span", { "aria-hidden": "true", className: cn("flex shrink-0", tone), children: item.icon }),
1501
1842
  truncated.has(index) ? (
1502
1843
  // `min-w-0 shrink` undoes the wrapper's own shrink-0 — the crumb
1503
1844
  // must keep truncating inside it, or wrapping it would widen the
1504
1845
  // trail and the tooltip would never be needed again.
1505
- /* @__PURE__ */ jsx29(WithTooltip, { label: item.label, wrapperClassName: "min-w-0 shrink", children: crumb })
1846
+ /* @__PURE__ */ jsx34(WithTooltip, { label: item.label, wrapperClassName: "min-w-0 shrink", children: crumb })
1506
1847
  ) : crumb
1507
1848
  ] }, `${item.label}-${index}`);
1508
1849
  }) });
1509
1850
  }
1510
1851
 
1511
1852
  // src/NavItem.tsx
1512
- import { jsx as jsx30, jsxs as jsxs21 } from "react/jsx-runtime";
1853
+ import { jsx as jsx35, jsxs as jsxs23 } from "react/jsx-runtime";
1513
1854
  function NavItem({ label, href, count, countLabel, active = false, icon, className, ...props }) {
1514
- return /* @__PURE__ */ jsxs21(
1855
+ return /* @__PURE__ */ jsxs23(
1515
1856
  "a",
1516
1857
  {
1517
1858
  href,
@@ -1526,9 +1867,9 @@ function NavItem({ label, href, count, countLabel, active = false, icon, classNa
1526
1867
  ),
1527
1868
  ...props,
1528
1869
  children: [
1529
- icon && /* @__PURE__ */ jsx30("span", { className: "flex shrink-0 items-center", children: icon }),
1530
- /* @__PURE__ */ jsx30("span", { className: "flex-1 truncate", children: label }),
1531
- count ? /* @__PURE__ */ jsx30(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx30("span", { className: "min-w-4 shrink-0 text-center font-mono text-caption tabular-nums text-text-muted", children: count }) }) : null
1870
+ icon && /* @__PURE__ */ jsx35("span", { className: "flex shrink-0 items-center", children: icon }),
1871
+ /* @__PURE__ */ jsx35("span", { className: "flex-1 truncate", children: label }),
1872
+ count ? /* @__PURE__ */ jsx35(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx35("span", { className: "min-w-4 shrink-0 text-center font-mono text-caption tabular-nums text-text-muted", children: count }) }) : null
1532
1873
  ]
1533
1874
  }
1534
1875
  );
@@ -1537,7 +1878,7 @@ function NavItem({ label, href, count, countLabel, active = false, icon, classNa
1537
1878
  // src/Popover.tsx
1538
1879
  import { useMemo as useMemo2 } from "react";
1539
1880
  import { Popover as BasePopover } from "@base-ui/react/popover";
1540
- import { jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
1881
+ import { jsx as jsx36, jsxs as jsxs24 } from "react/jsx-runtime";
1541
1882
  var GAP5 = 4;
1542
1883
  var VIEWPORT_PAD5 = 8;
1543
1884
  function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpenChange, finalFocus, actionsRef, ariaLabel, children, className, contentClassName, maxHeight }) {
@@ -1546,7 +1887,7 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
1546
1887
  if (anchor instanceof Element) return anchor;
1547
1888
  return { getBoundingClientRect: () => anchor };
1548
1889
  }, [anchor]);
1549
- return /* @__PURE__ */ jsxs22(
1890
+ return /* @__PURE__ */ jsxs24(
1550
1891
  BasePopover.Root,
1551
1892
  {
1552
1893
  open,
@@ -1554,8 +1895,8 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
1554
1895
  actionsRef,
1555
1896
  modal: false,
1556
1897
  children: [
1557
- trigger && /* @__PURE__ */ jsx31(BasePopover.Trigger, { render: trigger, disabled: triggerDisabled(trigger) }),
1558
- /* @__PURE__ */ jsx31(BasePopover.Portal, { children: /* @__PURE__ */ jsx31(
1898
+ trigger && /* @__PURE__ */ jsx36(BasePopover.Trigger, { render: trigger, disabled: triggerDisabled(trigger) }),
1899
+ /* @__PURE__ */ jsx36(BasePopover.Portal, { children: /* @__PURE__ */ jsx36(
1559
1900
  BasePopover.Positioner,
1560
1901
  {
1561
1902
  anchor: anchorTarget,
@@ -1564,15 +1905,15 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
1564
1905
  sideOffset: GAP5,
1565
1906
  collisionPadding: VIEWPORT_PAD5,
1566
1907
  className: "z-50 data-[anchor-hidden]:hidden",
1567
- children: /* @__PURE__ */ jsx31(
1908
+ children: /* @__PURE__ */ jsx36(
1568
1909
  BasePopover.Popup,
1569
1910
  {
1570
1911
  "aria-label": ariaLabel,
1571
1912
  initialFocus: trigger ? void 0 : false,
1572
1913
  finalFocus,
1573
1914
  className: cn("min-w-[180px] outline-none p-0", className),
1574
- render: /* @__PURE__ */ jsx31(MenuPanel, {}),
1575
- children: /* @__PURE__ */ jsx31(
1915
+ render: /* @__PURE__ */ jsx36(MenuPanel, {}),
1916
+ children: /* @__PURE__ */ jsx36(
1576
1917
  ScrollArea,
1577
1918
  {
1578
1919
  viewportClassName: maxHeight ?? "max-h-[var(--available-height)]",
@@ -1591,9 +1932,9 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
1591
1932
 
1592
1933
  // src/Toolbar.tsx
1593
1934
  import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar";
1594
- import { jsx as jsx32 } from "react/jsx-runtime";
1935
+ import { jsx as jsx37 } from "react/jsx-runtime";
1595
1936
  function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocus = true, surface = true, children, className }) {
1596
- const strip = /* @__PURE__ */ jsx32(
1937
+ const strip = /* @__PURE__ */ jsx37(
1597
1938
  BaseToolbar.Root,
1598
1939
  {
1599
1940
  "aria-label": ariaLabel,
@@ -1604,24 +1945,24 @@ function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocu
1604
1945
  }
1605
1946
  );
1606
1947
  if (!surface) return strip;
1607
- return /* @__PURE__ */ jsx32(MenuPanel, { className: "w-fit p-1", children: strip });
1948
+ return /* @__PURE__ */ jsx37(MenuPanel, { className: "w-fit p-1", children: strip });
1608
1949
  }
1609
1950
  function ToolbarButton({ ref, disabled, disabledReason, ...props }) {
1610
- return /* @__PURE__ */ jsx32(
1951
+ return /* @__PURE__ */ jsx37(
1611
1952
  BaseToolbar.Button,
1612
1953
  {
1613
1954
  ref,
1614
1955
  disabled: disabled || !!disabledReason,
1615
1956
  focusableWhenDisabled: true,
1616
- render: /* @__PURE__ */ jsx32(IconButton, { disabled, disabledReason, ...props })
1957
+ render: /* @__PURE__ */ jsx37(IconButton, { disabled, disabledReason, ...props })
1617
1958
  }
1618
1959
  );
1619
1960
  }
1620
1961
  function ToolbarInput(props) {
1621
- return /* @__PURE__ */ jsx32(BaseToolbar.Input, { render: /* @__PURE__ */ jsx32(TextInput, {}), ...props });
1962
+ return /* @__PURE__ */ jsx37(BaseToolbar.Input, { render: /* @__PURE__ */ jsx37(TextInput, {}), ...props });
1622
1963
  }
1623
1964
  function ToolbarSeparator({ className }) {
1624
- return /* @__PURE__ */ jsx32(
1965
+ return /* @__PURE__ */ jsx37(
1625
1966
  BaseToolbar.Separator,
1626
1967
  {
1627
1968
  orientation: "vertical",
@@ -1631,9 +1972,9 @@ function ToolbarSeparator({ className }) {
1631
1972
  }
1632
1973
 
1633
1974
  // src/ReactionPicker.tsx
1634
- import { jsx as jsx33 } from "react/jsx-runtime";
1975
+ import { jsx as jsx38 } from "react/jsx-runtime";
1635
1976
  function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reactions", surface = true, className }) {
1636
- return /* @__PURE__ */ jsx33(Toolbar, { "aria-label": ariaLabel, surface, className: cn("gap-0.5", className), children: options.map((option) => (
1977
+ return /* @__PURE__ */ jsx38(Toolbar, { "aria-label": ariaLabel, surface, className: cn("gap-0.5", className), children: options.map((option) => (
1637
1978
  /*
1638
1979
  A `ToolbarButton`, not a button in a tooltip wrapper. The wrapper
1639
1980
  would become the toolbar's item and the button inside it would never
@@ -1643,14 +1984,14 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
1643
1984
  The tooltip names it for a pointer, `aria-label` for everything else,
1644
1985
  and both say the meaning rather than the glyph.
1645
1986
  */
1646
- /* @__PURE__ */ jsx33(
1987
+ /* @__PURE__ */ jsx38(
1647
1988
  ToolbarButton,
1648
1989
  {
1649
1990
  "aria-label": option.label,
1650
1991
  tooltip: option.label,
1651
1992
  onClick: () => onSelect(option.emoji),
1652
1993
  className: "size-7 text-[18px] leading-none",
1653
- children: /* @__PURE__ */ jsx33("span", { "aria-hidden": "true", children: option.emoji })
1994
+ children: /* @__PURE__ */ jsx38("span", { "aria-hidden": "true", children: option.emoji })
1654
1995
  },
1655
1996
  option.emoji
1656
1997
  )
@@ -1659,23 +2000,23 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
1659
2000
 
1660
2001
  // src/PreviewCard.tsx
1661
2002
  import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card";
1662
- import { jsx as jsx34, jsxs as jsxs23 } from "react/jsx-runtime";
2003
+ import { jsx as jsx39, jsxs as jsxs25 } from "react/jsx-runtime";
1663
2004
  var GAP6 = 12;
1664
2005
  var VIEWPORT_PAD6 = 8;
1665
2006
  var OPEN_DELAY2 = 350;
1666
2007
  var CLOSE_DELAY = 200;
1667
2008
  function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, closeDelay = CLOSE_DELAY, className, wrapperClassName }) {
1668
- return /* @__PURE__ */ jsxs23(BasePreviewCard.Root, { children: [
1669
- /* @__PURE__ */ jsx34(
2009
+ return /* @__PURE__ */ jsxs25(BasePreviewCard.Root, { children: [
2010
+ /* @__PURE__ */ jsx39(
1670
2011
  BasePreviewCard.Trigger,
1671
2012
  {
1672
2013
  delay,
1673
2014
  closeDelay,
1674
- render: /* @__PURE__ */ jsx34("span", { className: cn("inline-flex", wrapperClassName) }),
2015
+ render: /* @__PURE__ */ jsx39("span", { className: cn("inline-flex", wrapperClassName) }),
1675
2016
  children
1676
2017
  }
1677
2018
  ),
1678
- /* @__PURE__ */ jsx34(BasePreviewCard.Portal, { children: /* @__PURE__ */ jsx34(
2019
+ /* @__PURE__ */ jsx39(BasePreviewCard.Portal, { children: /* @__PURE__ */ jsx39(
1679
2020
  BasePreviewCard.Positioner,
1680
2021
  {
1681
2022
  side,
@@ -1683,12 +2024,12 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
1683
2024
  sideOffset: GAP6,
1684
2025
  collisionPadding: VIEWPORT_PAD6,
1685
2026
  className: "z-50 data-[anchor-hidden]:hidden",
1686
- children: /* @__PURE__ */ jsx34(
2027
+ children: /* @__PURE__ */ jsx39(
1687
2028
  BasePreviewCard.Popup,
1688
2029
  {
1689
2030
  className: cn("w-[360px] p-3 outline-none", className),
1690
- render: /* @__PURE__ */ jsx34(MenuPanel, {}),
1691
- children: /* @__PURE__ */ jsx34(ScrollArea, { viewportClassName: "max-h-[calc(min(300px,var(--available-height))_-_1.5rem)]", contentClassName: "flex flex-col gap-3 [&>*]:shrink-0", children: content })
2031
+ render: /* @__PURE__ */ jsx39(MenuPanel, {}),
2032
+ children: /* @__PURE__ */ jsx39(ScrollArea, { viewportClassName: "max-h-[calc(min(300px,var(--available-height))_-_1.5rem)]", contentClassName: "flex flex-col gap-3 [&>*]:shrink-0", children: content })
1692
2033
  }
1693
2034
  )
1694
2035
  }
@@ -1697,15 +2038,15 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
1697
2038
  }
1698
2039
 
1699
2040
  // src/Rail.tsx
1700
- import { jsx as jsx35 } from "react/jsx-runtime";
2041
+ import { jsx as jsx40 } from "react/jsx-runtime";
1701
2042
  function Rail({ "aria-label": ariaLabel = "Navigation", children, className }) {
1702
- return /* @__PURE__ */ jsx35("nav", { "aria-label": ariaLabel, className: cn("flex w-16 shrink-0 flex-col items-start gap-2 px-2 py-3", className), children });
2043
+ return /* @__PURE__ */ jsx40("nav", { "aria-label": ariaLabel, className: cn("flex w-16 shrink-0 flex-col items-start gap-2 px-2 py-3", className), children });
1703
2044
  }
1704
2045
 
1705
2046
  // src/RailItem.tsx
1706
- import { jsx as jsx36, jsxs as jsxs24 } from "react/jsx-runtime";
2047
+ import { jsx as jsx41, jsxs as jsxs26 } from "react/jsx-runtime";
1707
2048
  function RailItem({ href, icon, label, active = false, className, ...props }) {
1708
- return /* @__PURE__ */ jsxs24(
2049
+ return /* @__PURE__ */ jsxs26(
1709
2050
  "a",
1710
2051
  {
1711
2052
  href,
@@ -1713,14 +2054,14 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
1713
2054
  className: cn("group flex w-full shrink-0 flex-col items-center gap-0.5 px-2 py-0.5", className),
1714
2055
  ...props,
1715
2056
  children: [
1716
- /* @__PURE__ */ jsx36(
2057
+ /* @__PURE__ */ jsx41(
1717
2058
  "div",
1718
2059
  {
1719
2060
  className: cn(
1720
2061
  "flex items-center justify-center rounded-lg p-2 transition-colors",
1721
2062
  active ? "bg-bg-selected" : "group-hover:bg-bg-hover"
1722
2063
  ),
1723
- children: /* @__PURE__ */ jsx36(
2064
+ children: /* @__PURE__ */ jsx41(
1724
2065
  "span",
1725
2066
  {
1726
2067
  className: cn(
@@ -1732,49 +2073,49 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
1732
2073
  )
1733
2074
  }
1734
2075
  ),
1735
- /* @__PURE__ */ jsx36("span", { className: cn("text-center text-[9px] font-medium leading-[115%]", active ? "text-text-primary" : "text-text-secondary"), children: label })
2076
+ /* @__PURE__ */ jsx41("span", { className: cn("text-center text-[9px] font-medium leading-[115%]", active ? "text-text-primary" : "text-text-secondary"), children: label })
1736
2077
  ]
1737
2078
  }
1738
2079
  );
1739
2080
  }
1740
2081
 
1741
2082
  // src/Sidebar.tsx
1742
- import { jsx as jsx37 } from "react/jsx-runtime";
2083
+ import { jsx as jsx42 } from "react/jsx-runtime";
1743
2084
  function Sidebar({ "aria-label": ariaLabel = "Workspace", children, className }) {
1744
- return /* @__PURE__ */ jsx37(
2085
+ return /* @__PURE__ */ jsx42(
1745
2086
  "nav",
1746
2087
  {
1747
2088
  "aria-label": ariaLabel,
1748
2089
  className: cn("flex w-60 shrink-0 flex-col border-r border-border-default bg-bg-surface", className),
1749
- children: /* @__PURE__ */ jsx37(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex flex-col gap-px px-2.5 py-3", children })
2090
+ children: /* @__PURE__ */ jsx42(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex flex-col gap-px px-2.5 py-3", children })
1750
2091
  }
1751
2092
  );
1752
2093
  }
1753
2094
 
1754
2095
  // src/Property.tsx
1755
- import { jsx as jsx38, jsxs as jsxs25 } from "react/jsx-runtime";
2096
+ import { jsx as jsx43, jsxs as jsxs27 } from "react/jsx-runtime";
1756
2097
  function Property({ label, layout = "row", children, className }) {
1757
2098
  if (layout === "stacked") {
1758
2099
  return (
1759
2100
  // gap-3 — the one label-above-content distance (Katerina, 2026-09-01):
1760
2101
  // Peek's topic-details sections already sit at 12px, Ship's rail was
1761
2102
  // 6px, and unifying means the bigger, calmer one.
1762
- /* @__PURE__ */ jsxs25("div", { className: cn("flex flex-col gap-3", className), children: [
1763
- /* @__PURE__ */ jsx38("span", { className: "text-menu uppercase tracking-[0.08em] text-text-secondary", children: label }),
2103
+ /* @__PURE__ */ jsxs27("div", { className: cn("flex flex-col gap-3", className), children: [
2104
+ /* @__PURE__ */ jsx43("span", { className: "text-menu uppercase tracking-[0.08em] text-text-secondary", children: label }),
1764
2105
  children
1765
2106
  ] })
1766
2107
  );
1767
2108
  }
1768
- return /* @__PURE__ */ jsxs25("div", { className: cn("flex items-center gap-2", className), children: [
1769
- /* @__PURE__ */ jsx38("span", { className: "w-[68px] shrink-0 text-caption text-text-secondary", children: label }),
2109
+ return /* @__PURE__ */ jsxs27("div", { className: cn("flex items-center gap-2", className), children: [
2110
+ /* @__PURE__ */ jsx43("span", { className: "w-[68px] shrink-0 text-caption text-text-secondary", children: label }),
1770
2111
  children
1771
2112
  ] });
1772
2113
  }
1773
2114
 
1774
2115
  // src/Reaction.tsx
1775
- import { jsx as jsx39, jsxs as jsxs26 } from "react/jsx-runtime";
2116
+ import { jsx as jsx44, jsxs as jsxs28 } from "react/jsx-runtime";
1776
2117
  function Reaction({ emoji, count, pressed = false, className, type, ...props }) {
1777
- return /* @__PURE__ */ jsxs26(
2118
+ return /* @__PURE__ */ jsxs28(
1778
2119
  "button",
1779
2120
  {
1780
2121
  type: type ?? "button",
@@ -1797,8 +2138,8 @@ function Reaction({ emoji, count, pressed = false, className, type, ...props })
1797
2138
  ),
1798
2139
  ...props,
1799
2140
  children: [
1800
- /* @__PURE__ */ jsx39("span", { "aria-hidden": "true", className: "shrink-0 text-[16px] leading-none", children: emoji }),
1801
- /* @__PURE__ */ jsx39("span", { className: "text-chip signal:font-mono signal:text-[10px] signal:font-semibold signal:tabular-nums", children: count })
2141
+ /* @__PURE__ */ jsx44("span", { "aria-hidden": "true", className: "shrink-0 text-[16px] leading-none", children: emoji }),
2142
+ /* @__PURE__ */ jsx44("span", { className: "text-chip signal:font-mono signal:text-[10px] signal:font-semibold signal:tabular-nums", children: count })
1802
2143
  ]
1803
2144
  }
1804
2145
  );
@@ -1807,9 +2148,9 @@ function Reaction({ emoji, count, pressed = false, className, type, ...props })
1807
2148
  // src/SearchInput.tsx
1808
2149
  import "react";
1809
2150
  import { Input as Input3 } from "@base-ui/react/input";
1810
- import { jsx as jsx40, jsxs as jsxs27 } from "react/jsx-runtime";
2151
+ import { jsx as jsx45, jsxs as jsxs29 } from "react/jsx-runtime";
1811
2152
  function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...props }) {
1812
- return /* @__PURE__ */ jsxs27(
2153
+ return /* @__PURE__ */ jsxs29(
1813
2154
  "div",
1814
2155
  {
1815
2156
  className: cn(
@@ -1819,7 +2160,7 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
1819
2160
  className
1820
2161
  ),
1821
2162
  children: [
1822
- /* @__PURE__ */ jsx40(
2163
+ /* @__PURE__ */ jsx45(
1823
2164
  Input3,
1824
2165
  {
1825
2166
  className: "flex-1 min-w-0 bg-transparent text-input-value text-text-primary placeholder:text-text-muted outline-none",
@@ -1827,7 +2168,7 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
1827
2168
  ...props
1828
2169
  }
1829
2170
  ),
1830
- shortcut && /* @__PURE__ */ jsx40(Kbd, { children: shortcut })
2171
+ shortcut && /* @__PURE__ */ jsx45(Kbd, { children: shortcut })
1831
2172
  ]
1832
2173
  }
1833
2174
  );
@@ -1836,17 +2177,17 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
1836
2177
  // src/SectionHeader.tsx
1837
2178
  import { IconChevronRight as IconChevronRight2 } from "@tabler/icons-react";
1838
2179
  import { useRender } from "@base-ui/react/use-render";
1839
- import { Fragment as Fragment5, jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
2180
+ import { Fragment as Fragment7, jsx as jsx46, jsxs as jsxs30 } from "react/jsx-runtime";
1840
2181
  function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, trailing, actions, showActions = "hover", render, className }) {
1841
2182
  const titleElement = useRender({
1842
- render: render ?? (chevron ? /* @__PURE__ */ jsx41("button", { type: "button", onClick: onToggle, "aria-expanded": isExpanded }) : /* @__PURE__ */ jsx41("span", {})),
2183
+ render: render ?? (chevron ? /* @__PURE__ */ jsx46("button", { type: "button", onClick: onToggle, "aria-expanded": isExpanded }) : /* @__PURE__ */ jsx46("span", {})),
1843
2184
  props: {
1844
2185
  // `text-left`: a button centres its text. `h-full` and `flex-1`: the
1845
2186
  // whole row up to the actions is the hit target, as it was when the
1846
2187
  // row itself carried the click.
1847
2188
  className: "flex h-full min-w-0 flex-1 items-center gap-1 text-left",
1848
- children: /* @__PURE__ */ jsxs28(Fragment5, { children: [
1849
- chevron && /* @__PURE__ */ jsx41(
2189
+ children: /* @__PURE__ */ jsxs30(Fragment7, { children: [
2190
+ chevron && /* @__PURE__ */ jsx46(
1850
2191
  IconChevronRight2,
1851
2192
  {
1852
2193
  size: 12,
@@ -1854,11 +2195,11 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
1854
2195
  className: cn("shrink-0 text-text-secondary transition-transform duration-150", isExpanded && "rotate-90")
1855
2196
  }
1856
2197
  ),
1857
- /* @__PURE__ */ jsx41(SectionLabel, { children: title })
2198
+ /* @__PURE__ */ jsx46(SectionLabel, { children: title })
1858
2199
  ] })
1859
2200
  }
1860
2201
  });
1861
- return /* @__PURE__ */ jsxs28(
2202
+ return /* @__PURE__ */ jsxs30(
1862
2203
  "div",
1863
2204
  {
1864
2205
  className: cn(
@@ -1871,15 +2212,15 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
1871
2212
  ),
1872
2213
  children: [
1873
2214
  titleElement,
1874
- trailing != null && /* @__PURE__ */ jsx41("div", { className: "flex shrink-0 items-center", children: trailing }),
1875
- actions && actions.length > 0 && /* @__PURE__ */ jsx41(
2215
+ trailing != null && /* @__PURE__ */ jsx46("div", { className: "flex shrink-0 items-center", children: trailing }),
2216
+ actions && actions.length > 0 && /* @__PURE__ */ jsx46(
1876
2217
  "div",
1877
2218
  {
1878
2219
  className: cn(
1879
2220
  "-mr-1 flex shrink-0 items-center gap-1",
1880
2221
  showActions === "hover" && "opacity-0 transition-opacity focus-within:opacity-100 group-hover:opacity-100"
1881
2222
  ),
1882
- children: actions.map((action) => /* @__PURE__ */ jsx41(IconButton, { tooltip: action.tooltip, "aria-label": action.tooltip, onClick: action.onClick, children: action.icon }, action.tooltip))
2223
+ children: actions.map((action) => /* @__PURE__ */ jsx46(IconButton, { tooltip: action.tooltip, "aria-label": action.tooltip, onClick: action.onClick, children: action.icon }, action.tooltip))
1883
2224
  }
1884
2225
  )
1885
2226
  ]
@@ -1888,9 +2229,9 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
1888
2229
  }
1889
2230
 
1890
2231
  // src/CollapsibleSection.tsx
1891
- import { useState as useState6 } from "react";
2232
+ import { useState as useState7 } from "react";
1892
2233
  import { Collapsible } from "@base-ui/react/collapsible";
1893
- import { jsx as jsx42, jsxs as jsxs29 } from "react/jsx-runtime";
2234
+ import { jsx as jsx47, jsxs as jsxs31 } from "react/jsx-runtime";
1894
2235
  var OPEN = "open";
1895
2236
  var CLOSED = "closed";
1896
2237
  function readStored(key) {
@@ -1910,21 +2251,21 @@ function writeStored(key, open) {
1910
2251
  }
1911
2252
  }
1912
2253
  function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenChange, storageKey, trailing, actions, showActions, children, className, contentClassName }) {
1913
- const [openState, setOpenState] = useState6(() => readStored(storageKey) ?? defaultOpen);
2254
+ const [openState, setOpenState] = useState7(() => readStored(storageKey) ?? defaultOpen);
1914
2255
  const open = openProp ?? openState;
1915
2256
  const setOpen = (next) => {
1916
2257
  setOpenState(next);
1917
2258
  writeStored(storageKey, next);
1918
2259
  onOpenChange?.(next);
1919
2260
  };
1920
- return /* @__PURE__ */ jsxs29(Collapsible.Root, { open, onOpenChange: setOpen, className: cn("flex flex-col", className), children: [
1921
- /* @__PURE__ */ jsx42(SectionHeader, { title, chevron: true, isExpanded: open, trailing, actions, showActions, className: "shrink-0", render: /* @__PURE__ */ jsx42(Collapsible.Trigger, {}) }),
1922
- /* @__PURE__ */ jsx42(
2261
+ return /* @__PURE__ */ jsxs31(Collapsible.Root, { open, onOpenChange: setOpen, className: cn("flex flex-col", className), children: [
2262
+ /* @__PURE__ */ jsx47(SectionHeader, { title, chevron: true, isExpanded: open, trailing, actions, showActions, className: "shrink-0", render: /* @__PURE__ */ jsx47(Collapsible.Trigger, {}) }),
2263
+ /* @__PURE__ */ jsx47(
1923
2264
  Collapsible.Panel,
1924
2265
  {
1925
2266
  hiddenUntilFound: true,
1926
2267
  className: "h-[var(--collapsible-panel-height)] overflow-hidden transition-[height] duration-150 ease-out motion-reduce:transition-none data-[starting-style]:h-0 data-[ending-style]:h-0",
1927
- children: /* @__PURE__ */ jsx42("div", { className: cn("flex flex-col", contentClassName), children })
2268
+ children: /* @__PURE__ */ jsx47("div", { className: cn("flex flex-col", contentClassName), children })
1928
2269
  }
1929
2270
  )
1930
2271
  ] });
@@ -1932,9 +2273,9 @@ function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenC
1932
2273
 
1933
2274
  // src/Tabs.tsx
1934
2275
  import { Tabs as BaseTabs } from "@base-ui/react/tabs";
1935
- import { jsx as jsx43, jsxs as jsxs30 } from "react/jsx-runtime";
2276
+ import { jsx as jsx48, jsxs as jsxs32 } from "react/jsx-runtime";
1936
2277
  function Tabs({ tabs, active, onChange, size = "default", className, ...aria }) {
1937
- return /* @__PURE__ */ jsx43(
2278
+ return /* @__PURE__ */ jsx48(
1938
2279
  BaseTabs.Root,
1939
2280
  {
1940
2281
  value: active,
@@ -1942,14 +2283,14 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
1942
2283
  if (details.reason === "none") onChange(value);
1943
2284
  },
1944
2285
  className,
1945
- children: /* @__PURE__ */ jsx43(
2286
+ children: /* @__PURE__ */ jsx48(
1946
2287
  BaseTabs.List,
1947
2288
  {
1948
2289
  activateOnFocus: true,
1949
2290
  "aria-label": aria["aria-label"],
1950
2291
  "aria-labelledby": aria["aria-labelledby"],
1951
2292
  className: "flex items-center gap-2",
1952
- children: tabs.map((tab) => /* @__PURE__ */ jsxs30(
2293
+ children: tabs.map((tab) => /* @__PURE__ */ jsxs32(
1953
2294
  BaseTabs.Tab,
1954
2295
  {
1955
2296
  value: tab.id,
@@ -1962,9 +2303,9 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
1962
2303
  ),
1963
2304
  children: [
1964
2305
  tab.icon,
1965
- /* @__PURE__ */ jsxs30("span", { className: "flex items-baseline", children: [
2306
+ /* @__PURE__ */ jsxs32("span", { className: "flex items-baseline", children: [
1966
2307
  tab.label,
1967
- tab.count !== void 0 ? /* @__PURE__ */ jsx43("span", { className: "ml-2.5 font-mono text-caption tabular-nums text-text-secondary", children: tab.count }) : null
2308
+ tab.count !== void 0 ? /* @__PURE__ */ jsx48("span", { className: "ml-2.5 font-mono text-caption tabular-nums text-text-secondary", children: tab.count }) : null
1968
2309
  ] })
1969
2310
  ]
1970
2311
  },
@@ -1977,10 +2318,10 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
1977
2318
  }
1978
2319
 
1979
2320
  // src/Toast.tsx
1980
- import { createContext as createContext2, useCallback as useCallback3, useContext as useContext2, useEffect as useEffect2, useMemo as useMemo3, useState as useState7 } from "react";
2321
+ import { createContext as createContext2, useCallback as useCallback3, useContext as useContext2, useEffect as useEffect2, useMemo as useMemo3, useState as useState8 } from "react";
1981
2322
  import { createPortal } from "react-dom";
1982
- import { IconAlertCircle, IconCircleCheck, IconCircleX } from "@tabler/icons-react";
1983
- import { jsx as jsx44, jsxs as jsxs31 } from "react/jsx-runtime";
2323
+ import { IconAlertCircle as IconAlertCircle2, IconCircleCheck, IconCircleX } from "@tabler/icons-react";
2324
+ import { jsx as jsx49, jsxs as jsxs33 } from "react/jsx-runtime";
1984
2325
  var SURFACE_STYLES = {
1985
2326
  success: "bg-success-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-[shadow:var(--shadow-md)]",
1986
2327
  brand: "bg-accent-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-[shadow:var(--shadow-md)]",
@@ -1992,7 +2333,7 @@ var ICONS = {
1992
2333
  success: IconCircleCheck,
1993
2334
  brand: IconCircleCheck,
1994
2335
  neutral: IconCircleCheck,
1995
- warning: IconAlertCircle,
2336
+ warning: IconAlertCircle2,
1996
2337
  error: IconCircleX
1997
2338
  };
1998
2339
  var ICON_STYLES = {
@@ -2015,7 +2356,7 @@ var ACTION_BORDER_STYLES = {
2015
2356
  function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAction, className }) {
2016
2357
  const hasAction = !!(actionLabel && onAction);
2017
2358
  const LeadingIcon = ICONS[type];
2018
- return /* @__PURE__ */ jsxs31(
2359
+ return /* @__PURE__ */ jsxs33(
2019
2360
  "div",
2020
2361
  {
2021
2362
  className: cn(
@@ -2027,11 +2368,11 @@ function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAct
2027
2368
  className
2028
2369
  ),
2029
2370
  children: [
2030
- /* @__PURE__ */ jsxs31("div", { className: "flex items-center gap-2 shrink-0", children: [
2031
- leadingIcon && /* @__PURE__ */ jsx44(LeadingIcon, { size: 16, stroke: 1.5, className: cn("text-text-primary shrink-0", ICON_STYLES[type]) }),
2032
- /* @__PURE__ */ jsx44("span", { className: "font-normal text-[14px] leading-[1.4] text-text-primary whitespace-nowrap", children: label })
2371
+ /* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-2 shrink-0", children: [
2372
+ leadingIcon && /* @__PURE__ */ jsx49(LeadingIcon, { size: 16, stroke: 1.5, className: cn("text-text-primary shrink-0", ICON_STYLES[type]) }),
2373
+ /* @__PURE__ */ jsx49("span", { className: "font-normal text-[14px] leading-[1.4] text-text-primary whitespace-nowrap", children: label })
2033
2374
  ] }),
2034
- hasAction && /* @__PURE__ */ jsx44(
2375
+ hasAction && /* @__PURE__ */ jsx49(
2035
2376
  "button",
2036
2377
  {
2037
2378
  type: "button",
@@ -2041,7 +2382,7 @@ function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAct
2041
2382
  ACTION_BORDER_STYLES[type],
2042
2383
  type === "neutral" ? "hover:border-border-strong" : "hover:opacity-80"
2043
2384
  ),
2044
- children: /* @__PURE__ */ jsx44("span", { className: "font-medium text-[12px] leading-[12px] text-text-primary whitespace-nowrap", children: actionLabel })
2385
+ children: /* @__PURE__ */ jsx49("span", { className: "font-medium text-[12px] leading-[12px] text-text-primary whitespace-nowrap", children: actionLabel })
2045
2386
  }
2046
2387
  )
2047
2388
  ]
@@ -2051,7 +2392,7 @@ function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAct
2051
2392
  var ToastContext = createContext2(null);
2052
2393
  var toastSeq = 0;
2053
2394
  function ToastProvider({ children }) {
2054
- const [toast, setToast] = useState7(null);
2395
+ const [toast, setToast] = useState8(null);
2055
2396
  const showToast = useCallback3((opts) => {
2056
2397
  setToast({ ...opts, id: ++toastSeq });
2057
2398
  }, []);
@@ -2068,10 +2409,10 @@ function ToastProvider({ children }) {
2068
2409
  return () => clearTimeout(timer);
2069
2410
  }, [toast]);
2070
2411
  const value = useMemo3(() => ({ showToast, dismissToast }), [showToast, dismissToast]);
2071
- return /* @__PURE__ */ jsxs31(ToastContext.Provider, { value, children: [
2412
+ return /* @__PURE__ */ jsxs33(ToastContext.Provider, { value, children: [
2072
2413
  children,
2073
2414
  toast && createPortal(
2074
- /* @__PURE__ */ jsx44("div", { className: "fixed bottom-4 left-4 z-[100] pointer-events-none", children: /* @__PURE__ */ jsx44(
2415
+ /* @__PURE__ */ jsx49("div", { className: "fixed bottom-4 left-4 z-[100] pointer-events-none", children: /* @__PURE__ */ jsx49(
2075
2416
  Toast,
2076
2417
  {
2077
2418
  className: "pointer-events-auto",
@@ -2096,11 +2437,13 @@ function useToast() {
2096
2437
  }
2097
2438
  export {
2098
2439
  AppShell,
2440
+ AttachmentCard,
2099
2441
  Avatar,
2100
2442
  AvatarGroup,
2101
2443
  Banner,
2102
2444
  Breadcrumb,
2103
2445
  Button,
2446
+ Card,
2104
2447
  Checkbox,
2105
2448
  Chip,
2106
2449
  ChipInput,
@@ -2113,11 +2456,15 @@ export {
2113
2456
  EnterHint,
2114
2457
  Field,
2115
2458
  FieldLine,
2459
+ INLINE_CHIP_CLASSES,
2460
+ INLINE_CHIP_TONE_CLASSES,
2116
2461
  IconButton,
2117
2462
  IdentityMenu,
2118
2463
  IdentityPanel,
2464
+ InlineChip,
2119
2465
  InputChip,
2120
2466
  Kbd,
2467
+ Link,
2121
2468
  Menu,
2122
2469
  MenuItem,
2123
2470
  MenuPanel,
@@ -2129,6 +2476,7 @@ export {
2129
2476
  PersonTrigger,
2130
2477
  Popover,
2131
2478
  PreviewCard,
2479
+ ProgressBar,
2132
2480
  Property,
2133
2481
  Rail,
2134
2482
  RailItem,
@@ -2159,6 +2507,7 @@ export {
2159
2507
  cn,
2160
2508
  hueFor,
2161
2509
  initialsFor,
2510
+ inlineChipClassName,
2162
2511
  useToast
2163
2512
  };
2164
2513
  //# sourceMappingURL=index.js.map