@estiva-app/ui 0.12.10 → 0.13.0

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