@estiva-app/ui 0.59.0 → 0.60.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 (71) hide show
  1. package/dist/AppProvider.d.ts +47 -0
  2. package/dist/AppProvider.d.ts.map +1 -0
  3. package/dist/AppShell.d.ts +6 -2
  4. package/dist/AppShell.d.ts.map +1 -1
  5. package/dist/Avatar.d.ts +1 -1
  6. package/dist/Avatar.d.ts.map +1 -1
  7. package/dist/Chip.d.ts.map +1 -1
  8. package/dist/IconButton.d.ts.map +1 -1
  9. package/dist/InlineChip.d.ts.map +1 -1
  10. package/dist/Link.d.ts +1 -1
  11. package/dist/Link.d.ts.map +1 -1
  12. package/dist/NavItem.d.ts +1 -1
  13. package/dist/NavItem.d.ts.map +1 -1
  14. package/dist/RailItem.d.ts +1 -1
  15. package/dist/RailItem.d.ts.map +1 -1
  16. package/dist/SearchInput.d.ts +3 -3
  17. package/dist/TopBar.d.ts +14 -3
  18. package/dist/TopBar.d.ts.map +1 -1
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +710 -642
  22. package/dist/index.js.map +4 -4
  23. package/dist/registry/{app-LDGOH6UW.js → app-X2GI4WTU.js} +2 -2
  24. package/dist/registry/app.d.ts.map +1 -1
  25. package/dist/registry/{chunk-TQ6UQER3.js → chunk-V67F474L.js} +8 -3
  26. package/dist/registry/chunk-V67F474L.js.map +7 -0
  27. package/dist/registry/cli.js +1 -1
  28. package/dist/registry/index.js +1 -1
  29. package/package.json +1 -1
  30. package/registry.json +87 -9
  31. package/skill/estiva-ui.md +2 -1
  32. package/src/AppProvider.mdx +69 -0
  33. package/src/AppProvider.stories.tsx +60 -0
  34. package/src/AppProvider.test.tsx +152 -0
  35. package/src/AppProvider.tsx +76 -0
  36. package/src/AppShell.mdx +4 -1
  37. package/src/AppShell.stories.tsx +5 -5
  38. package/src/AppShell.tsx +7 -3
  39. package/src/Avatar.tsx +7 -3
  40. package/src/Breadcrumb.mdx +2 -2
  41. package/src/Card.mdx +1 -1
  42. package/src/Chip.mdx +2 -2
  43. package/src/Chip.tsx +3 -1
  44. package/src/IconButton.mdx +2 -2
  45. package/src/IconButton.tsx +4 -1
  46. package/src/InlineChip.mdx +3 -3
  47. package/src/InlineChip.tsx +3 -1
  48. package/src/Link.mdx +5 -3
  49. package/src/Link.tsx +4 -1
  50. package/src/NavItem.mdx +3 -3
  51. package/src/NavItem.tsx +4 -0
  52. package/src/NavTree.mdx +3 -2
  53. package/src/RailItem.mdx +3 -3
  54. package/src/RailItem.tsx +4 -1
  55. package/src/SearchInput.mdx +3 -4
  56. package/src/SearchInput.tsx +3 -3
  57. package/src/Sidebar.mdx +2 -2
  58. package/src/TopBar.mdx +18 -9
  59. package/src/TopBar.stories.tsx +22 -4
  60. package/src/TopBar.test.tsx +97 -0
  61. package/src/TopBar.tsx +45 -4
  62. package/src/index.ts +1 -0
  63. package/src/pages.test.ts +3 -1
  64. package/src/registry/app.test.ts +24 -6
  65. package/src/registry/app.ts +21 -2
  66. package/src/registry/contract.test.ts +1 -1
  67. package/src/registry/gated.test.ts +1 -0
  68. package/src/registry/registry.test.ts +4 -4
  69. package/stories/Choosing.mdx +2 -0
  70. package/dist/registry/chunk-TQ6UQER3.js.map +0 -7
  71. /package/dist/registry/{app-LDGOH6UW.js.map → app-X2GI4WTU.js.map} +0 -0
package/dist/index.js CHANGED
@@ -1,3 +1,35 @@
1
+ // src/AppProvider.tsx
2
+ import { createContext, useContext, useMemo } from "react";
3
+ import { jsx } from "react/jsx-runtime";
4
+ var Setup = createContext({});
5
+ function AppProvider({ pictureFor, navigate, children }) {
6
+ const value = useMemo(() => ({ pictureFor, navigate }), [pictureFor, navigate]);
7
+ return /* @__PURE__ */ jsx(Setup.Provider, { value, children });
8
+ }
9
+ function usePictureFor() {
10
+ return useContext(Setup).pictureFor;
11
+ }
12
+ function useInAppClick(href, onClick) {
13
+ const navigate = useContext(Setup).navigate;
14
+ if (!navigate || href === void 0) return onClick;
15
+ return (event) => {
16
+ onClick?.(event);
17
+ if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
18
+ const link = event.currentTarget;
19
+ const target = link.getAttribute("target");
20
+ if (target && target !== "_self" || link.hasAttribute("download")) return;
21
+ let url;
22
+ try {
23
+ url = new URL(href, window.location.href);
24
+ } catch {
25
+ return;
26
+ }
27
+ if (url.origin !== window.location.origin) return;
28
+ event.preventDefault();
29
+ navigate(href);
30
+ };
31
+ }
32
+
1
33
  // src/cn.ts
2
34
  import { clsx } from "clsx";
3
35
  import { extendTailwindMerge } from "tailwind-merge";
@@ -36,7 +68,7 @@ function cn(...inputs) {
36
68
  }
37
69
 
38
70
  // src/Link.tsx
39
- import { jsx } from "react/jsx-runtime";
71
+ import { jsx as jsx2 } from "react/jsx-runtime";
40
72
  var COVER_CLASSES = "after:absolute after:inset-0 after:rounded-md focus-visible:outline-none focus-visible:after:[outline-style:auto]";
41
73
  var VARIANT_CLASSES = {
42
74
  text: "text-info-default underline underline-offset-2 hover:opacity-80",
@@ -44,21 +76,23 @@ var VARIANT_CLASSES = {
44
76
  underlined: "underline underline-offset-2 hover:text-text-primary",
45
77
  plain: ""
46
78
  };
47
- function Link({ href, variant = "text", external = false, truncate = false, cover = false, className, children, ...props }) {
48
- return /* @__PURE__ */ jsx(
79
+ function Link({ href, variant = "text", external = false, truncate = false, cover = false, className, children, onClick, ...props }) {
80
+ const inApp = useInAppClick(href, onClick);
81
+ return /* @__PURE__ */ jsx2(
49
82
  "a",
50
83
  {
51
84
  href,
52
85
  ...external ? { target: "_blank", rel: "noopener noreferrer" } : {},
53
86
  className: cn(VARIANT_CLASSES[variant], truncate && "truncate", cover && COVER_CLASSES, className),
54
87
  ...props,
88
+ onClick: inApp,
55
89
  children
56
90
  }
57
91
  );
58
92
  }
59
93
 
60
94
  // src/Card.tsx
61
- import { jsx as jsx2 } from "react/jsx-runtime";
95
+ import { jsx as jsx3 } from "react/jsx-runtime";
62
96
  var FILL_CLASSES = {
63
97
  surface: "bg-bg-surface border-border-default",
64
98
  elevated: "bg-bg-elevated border-border-default",
@@ -121,25 +155,25 @@ function Card({
121
155
  const { ref, ...anchorProps } = props;
122
156
  return (
123
157
  // @estiva-escape(no-copied-look, no-restyled-part): a card that leads somewhere is drawn on Link's anchor (UIG-27 ruling 1), so this frame is Card's own look, not Link restyled
124
- /* @__PURE__ */ jsx2(Link, { href, variant: "plain", ref, className: classes, ...anchorProps, children })
158
+ /* @__PURE__ */ jsx3(Link, { href, variant: "plain", ref, className: classes, ...anchorProps, children })
125
159
  );
126
160
  }
127
161
  return (
128
162
  // @estiva-escape(no-copied-look): N6 (Katerina, 24 September: leave alone): a card that cuts its content to its corners shares four words with the palette's window by coincidence
129
- /* @__PURE__ */ jsx2("div", { className: classes, ...props, children })
163
+ /* @__PURE__ */ jsx3("div", { className: classes, ...props, children })
130
164
  );
131
165
  }
132
166
 
133
167
  // src/ScrollArea.tsx
134
168
  import { ScrollArea as BaseScrollArea } from "@base-ui/react/scroll-area";
135
- import { jsx as jsx3, jsxs } from "react/jsx-runtime";
169
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
136
170
  var BAR = "z-10 flex touch-none select-none rounded-full opacity-0 transition-opacity delay-300 data-[hovering]:opacity-100 data-[hovering]:delay-0 data-[scrolling]:opacity-100 data-[scrolling]:delay-0";
137
171
  var THUMB = "rounded-full bg-border-strong";
138
172
  function ScrollArea({ orientation = "vertical", className, viewportClassName, contentClassName, viewportRef, onScroll, children }) {
139
173
  const vertical = orientation !== "horizontal";
140
174
  const horizontal = orientation !== "vertical";
141
175
  return /* @__PURE__ */ jsxs(BaseScrollArea.Root, { className: cn("relative min-h-0 min-w-0", className), children: [
142
- /* @__PURE__ */ jsx3(
176
+ /* @__PURE__ */ jsx4(
143
177
  BaseScrollArea.Viewport,
144
178
  {
145
179
  ref: viewportRef,
@@ -148,35 +182,114 @@ function ScrollArea({ orientation = "vertical", className, viewportClassName, co
148
182
  "h-full w-full outline-none data-[has-overflow-x]:overscroll-x-contain data-[has-overflow-y]:overscroll-y-contain",
149
183
  viewportClassName
150
184
  ),
151
- children: /* @__PURE__ */ jsx3(BaseScrollArea.Content, { className: contentClassName, style: horizontal ? void 0 : { minWidth: 0 }, children })
185
+ children: /* @__PURE__ */ jsx4(BaseScrollArea.Content, { className: contentClassName, style: horizontal ? void 0 : { minWidth: 0 }, children })
152
186
  }
153
187
  ),
154
- vertical && /* @__PURE__ */ jsx3(BaseScrollArea.Scrollbar, { orientation: "vertical", className: cn(BAR, "w-1.5 justify-center py-0.5 pr-0.5 data-[has-overflow-y]:opacity-100"), children: /* @__PURE__ */ jsx3(BaseScrollArea.Thumb, { className: cn(THUMB, "w-full") }) }),
155
- horizontal && /* @__PURE__ */ jsx3(BaseScrollArea.Scrollbar, { orientation: "horizontal", className: cn(BAR, "h-1.5 flex-col justify-center px-0.5 pb-0.5 data-[has-overflow-x]:opacity-100"), children: /* @__PURE__ */ jsx3(BaseScrollArea.Thumb, { className: cn(THUMB, "h-full") }) }),
156
- vertical && horizontal && /* @__PURE__ */ jsx3(BaseScrollArea.Corner, {})
188
+ vertical && /* @__PURE__ */ jsx4(BaseScrollArea.Scrollbar, { orientation: "vertical", className: cn(BAR, "w-1.5 justify-center py-0.5 pr-0.5 data-[has-overflow-y]:opacity-100"), children: /* @__PURE__ */ jsx4(BaseScrollArea.Thumb, { className: cn(THUMB, "w-full") }) }),
189
+ horizontal && /* @__PURE__ */ jsx4(BaseScrollArea.Scrollbar, { orientation: "horizontal", className: cn(BAR, "h-1.5 flex-col justify-center px-0.5 pb-0.5 data-[has-overflow-x]:opacity-100"), children: /* @__PURE__ */ jsx4(BaseScrollArea.Thumb, { className: cn(THUMB, "h-full") }) }),
190
+ vertical && horizontal && /* @__PURE__ */ jsx4(BaseScrollArea.Corner, {})
157
191
  ] });
158
192
  }
159
193
 
160
194
  // src/Sidebar.tsx
161
- import { createContext, useContext } from "react";
162
- import { jsx as jsx4 } from "react/jsx-runtime";
163
- var SidebarOnGround = createContext(false);
195
+ import { createContext as createContext2, useContext as useContext2 } from "react";
196
+ import { jsx as jsx5 } from "react/jsx-runtime";
197
+ var SidebarOnGround = createContext2(false);
164
198
  function Sidebar({ "aria-label": ariaLabel = "Workspace", children, className }) {
165
- const onGround = useContext(SidebarOnGround);
166
- return /* @__PURE__ */ jsx4(
199
+ const onGround = useContext2(SidebarOnGround);
200
+ return /* @__PURE__ */ jsx5(
167
201
  "nav",
168
202
  {
169
203
  "aria-label": ariaLabel,
170
204
  className: cn("flex w-60 shrink-0 flex-col", !onGround && "border-r border-border-default bg-bg-surface", className),
171
- children: /* @__PURE__ */ jsx4(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex flex-col gap-0.5 px-2.5 py-3", children })
205
+ children: /* @__PURE__ */ jsx5(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex flex-col gap-0.5 px-2.5 py-3", children })
172
206
  }
173
207
  );
174
208
  }
175
209
 
176
210
  // src/TopBar.tsx
177
- import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
178
- function TopBar({ variant = "solid", menu, logo, search, right, className }) {
211
+ import { useEffect, useRef } from "react";
212
+ import { Button as BaseButton } from "@base-ui/react/button";
213
+
214
+ // src/looks.ts
215
+ var FIELD_BOX_CLASSES = "bg-bg-field border border-border-field shadow-field hover:border-border-strong group-hover/field:border-border-strong focus:border-border-focus group-hover/field:focus:border-border-focus rounded-lg";
216
+ var FIELD_TEXT_CLASSES = "text-text-primary placeholder:text-text-muted";
217
+ var FIELD_DISABLED_CLASSES = "disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-field group-hover/field:disabled:border-border-field";
218
+ var FIELD_FOCUS_RING_CLASSES = "signal:transition-shadow signal:focus:shadow-focus-ring";
219
+ var FIELD_SIZE_CLASSES = {
220
+ default: "px-3 py-2 text-input-value",
221
+ small: "h-6 min-h-6 px-2 text-caption"
222
+ };
223
+ var FIELD_SHELL_CLASSES = "bg-bg-field border border-border-field shadow-field hover:border-border-strong group-hover/field:border-border-strong rounded-lg transition-colors";
224
+ var FLOATING_SURFACE_CLASSES = "rounded-lg border border-border-default bg-bg-elevated shadow-lg";
225
+ var COUNT_TEXT_CLASSES = "font-mono text-caption tabular-nums text-text-muted";
226
+ var CHIP_TEXT_CLASSES = "text-chip signal:font-mono signal:text-small signal:font-semibold signal:tabular-nums";
227
+ var MONO_CAPTION_CLASSES = "text-caption text-text-secondary signal:font-mono signal:text-small";
228
+ var BARE_INPUT_CLASSES = "bg-transparent text-text-primary placeholder:text-text-muted outline-none";
229
+ var SIDEBAR_ROW_CLASSES = "rounded-lg transition-colors";
230
+ var SIDEBAR_ROW_TEXT_CLASSES = "text-text-secondary hover:text-text-primary";
231
+ var MUTED_CONTROL_CLASSES = "text-text-secondary hover:bg-bg-hover hover:text-text-primary";
232
+ var MENU_TRIGGER_CLASSES = "cursor-pointer rounded-md transition-colors hover:bg-bg-hover data-[popup-open]:bg-bg-hover";
233
+ var COLLAPSIBLE_PANEL_CLASSES = "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";
234
+
235
+ // src/Kbd.tsx
236
+ import { jsx as jsx6 } from "react/jsx-runtime";
237
+ function Kbd({ children, className, tone = "default" }) {
238
+ return /* @__PURE__ */ jsx6(
239
+ "kbd",
240
+ {
241
+ className: cn(
242
+ "inline-flex shrink-0 items-center justify-center whitespace-nowrap rounded-sm border border-border-strong bg-bg-inset px-1 py-px font-sans",
243
+ MONO_CAPTION_CLASSES,
244
+ "signal:border-b-2 signal:pt-[2px] signal:pb-px signal:bg-bg-wash",
245
+ "ship:border-b-2 ship:pt-[2px] ship:pb-px ship:bg-bg-wash ship:font-mono ship:text-small",
246
+ // Leaf sets its keys in mono, as Signal does (Katerina, 28 September): the type, not the key's shape.
247
+ "leaf:font-mono leaf:text-small",
248
+ tone === "tooltip" && "border-border-tooltip-key bg-bg-tooltip-key text-text-tooltip-key signal:bg-bg-tooltip-key ship:bg-bg-tooltip-key",
249
+ className
250
+ ),
251
+ children
252
+ }
253
+ );
254
+ }
255
+
256
+ // src/shortcuts.ts
257
+ function isApplePlatform() {
258
+ if (typeof navigator === "undefined") return false;
259
+ return /Mac|iPhone|iPad|iPod/.test(navigator.platform || navigator.userAgent || "");
260
+ }
261
+ function shortcutLabel(keys, apple = isApplePlatform()) {
262
+ return keys.split("-").map((part, i, all) => {
263
+ if (i === all.length - 1) return part.length === 1 ? part.toUpperCase() : part;
264
+ if (part === "Mod") return apple ? "Cmd" : "Ctrl";
265
+ return part;
266
+ }).join("+");
267
+ }
268
+
269
+ // src/TopBar.tsx
270
+ import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
271
+ function TopBar({ variant = "solid", menu, logo, search, onSearch, searchPlaceholder = "Search\u2026", right, className }) {
179
272
  const floating = variant === "floating";
273
+ const searchRef = useRef(onSearch);
274
+ useEffect(() => {
275
+ searchRef.current = onSearch;
276
+ });
277
+ const searches = onSearch !== void 0;
278
+ useEffect(() => {
279
+ if (!searches) return;
280
+ const onKey = (event) => {
281
+ if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
282
+ event.preventDefault();
283
+ searchRef.current?.();
284
+ }
285
+ };
286
+ window.addEventListener("keydown", onKey);
287
+ return () => window.removeEventListener("keydown", onKey);
288
+ }, [searches]);
289
+ const centre = search ?? (onSearch && /* @__PURE__ */ jsxs2(BaseButton, { type: "button", onClick: onSearch, className: cn("flex w-[290px] cursor-pointer items-center gap-2 px-3 py-2", FIELD_SHELL_CLASSES), children: [
290
+ /* @__PURE__ */ jsx7("span", { className: "min-w-0 flex-1 truncate text-left text-input-value text-text-muted", children: searchPlaceholder }),
291
+ /* @__PURE__ */ jsx7(Kbd, { children: shortcutLabel("Mod-K") })
292
+ ] }));
180
293
  return /* @__PURE__ */ jsxs2(
181
294
  "header",
182
295
  {
@@ -188,19 +301,19 @@ function TopBar({ variant = "solid", menu, logo, search, right, className }) {
188
301
  children: [
189
302
  (menu || logo) && /* @__PURE__ */ jsxs2("div", { className: cn("flex shrink-0 items-center gap-2", floating && "pointer-events-auto"), children: [
190
303
  menu,
191
- logo && /* @__PURE__ */ jsx5("div", { className: "flex items-center text-body-2-strong text-text-primary", children: logo })
304
+ logo && /* @__PURE__ */ jsx7("div", { className: "flex items-center text-body-2-strong text-text-primary", children: logo })
192
305
  ] }),
193
- /* @__PURE__ */ jsx5("div", { className: cn("flex min-w-0 flex-1 items-center justify-center", floating && "pointer-events-auto"), children: search }),
194
- /* @__PURE__ */ jsx5("div", { className: cn("flex shrink-0 items-center gap-[6px]", floating && "pointer-events-auto"), children: right })
306
+ /* @__PURE__ */ jsx7("div", { className: cn("flex min-w-0 flex-1 items-center justify-center", floating && "pointer-events-auto"), children: centre }),
307
+ /* @__PURE__ */ jsx7("div", { className: cn("flex shrink-0 items-center gap-[6px]", floating && "pointer-events-auto"), children: right })
195
308
  ]
196
309
  }
197
310
  );
198
311
  }
199
312
 
200
313
  // src/AppShell.tsx
201
- import { Fragment, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
202
- function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav, children }) {
203
- const bar = /* @__PURE__ */ jsx6(TopBar, { variant, menu, logo, search, right: identity });
314
+ import { Fragment, jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
315
+ function AppShell({ variant = "solid", menu, logo, search, onSearch, searchPlaceholder, identity, banner, nav, children }) {
316
+ const bar = /* @__PURE__ */ jsx8(TopBar, { variant, menu, logo, search, onSearch, searchPlaceholder, right: identity });
204
317
  const inset = variant === "inset";
205
318
  if (variant === "floating") {
206
319
  return (
@@ -220,7 +333,7 @@ function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav
220
333
  ),
221
334
  children: [
222
335
  banner,
223
- /* @__PURE__ */ jsx6("main", { className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden", children })
336
+ /* @__PURE__ */ jsx8("main", { className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden", children })
224
337
  ]
225
338
  }
226
339
  )
@@ -230,7 +343,7 @@ function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav
230
343
  }
231
344
  const column = /* @__PURE__ */ jsxs3(Fragment, { children: [
232
345
  banner,
233
- /* @__PURE__ */ jsx6(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex min-h-full flex-col", children: /* @__PURE__ */ jsx6("main", { className: "flex min-w-0 flex-1 flex-col", children }) })
346
+ /* @__PURE__ */ jsx8(ScrollArea, { className: "min-h-0 flex-1", contentClassName: "flex min-h-full flex-col", children: /* @__PURE__ */ jsx8("main", { className: "flex min-w-0 flex-1 flex-col", children }) })
234
347
  ] });
235
348
  return (
236
349
  /* `relative overflow-hidden` is the seal the floating manner already has
@@ -245,16 +358,16 @@ function AppShell({ variant = "solid", menu, logo, search, identity, banner, nav
245
358
  /* @__PURE__ */ jsxs3("div", { className: "relative flex h-full min-h-0 flex-col overflow-hidden bg-bg-base text-text-primary", children: [
246
359
  bar,
247
360
  /* @__PURE__ */ jsxs3("div", { className: "flex min-h-0 flex-1", children: [
248
- /* @__PURE__ */ jsx6(SidebarOnGround.Provider, { value: inset, children: nav }),
249
- inset ? /* @__PURE__ */ jsx6(Card, { fill: "surface", clip: true, className: "mb-4 mr-4 flex min-h-0 min-w-0 flex-1 flex-col", children: column }) : /* @__PURE__ */ jsx6("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: column })
361
+ /* @__PURE__ */ jsx8(SidebarOnGround.Provider, { value: inset, children: nav }),
362
+ inset ? /* @__PURE__ */ jsx8(Card, { fill: "surface", clip: true, className: "mb-4 mr-4 flex min-h-0 min-w-0 flex-1 flex-col", children: column }) : /* @__PURE__ */ jsx8("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: column })
250
363
  ] })
251
364
  ] })
252
365
  );
253
366
  }
254
367
 
255
368
  // src/AttachmentCard.tsx
256
- import { useEffect, useLayoutEffect, useRef as useRef2, useState } from "react";
257
- import { Button as BaseButton2 } from "@base-ui/react/button";
369
+ import { useEffect as useEffect2, useLayoutEffect, useRef as useRef3, useState } from "react";
370
+ import { Button as BaseButton3 } from "@base-ui/react/button";
258
371
  import {
259
372
  IconAlertCircle,
260
373
  IconAlertTriangle,
@@ -274,76 +387,32 @@ import {
274
387
  } from "@tabler/icons-react";
275
388
 
276
389
  // src/IconButton.tsx
277
- import { Button as BaseButton } from "@base-ui/react/button";
278
-
279
- // src/looks.ts
280
- var FIELD_BOX_CLASSES = "bg-bg-field border border-border-field shadow-field hover:border-border-strong group-hover/field:border-border-strong focus:border-border-focus group-hover/field:focus:border-border-focus rounded-lg";
281
- var FIELD_TEXT_CLASSES = "text-text-primary placeholder:text-text-muted";
282
- var FIELD_DISABLED_CLASSES = "disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled disabled:border-border-field group-hover/field:disabled:border-border-field";
283
- var FIELD_FOCUS_RING_CLASSES = "signal:transition-shadow signal:focus:shadow-focus-ring";
284
- var FIELD_SIZE_CLASSES = {
285
- default: "px-3 py-2 text-input-value",
286
- small: "h-6 min-h-6 px-2 text-caption"
287
- };
288
- var FIELD_SHELL_CLASSES = "bg-bg-field border border-border-field shadow-field hover:border-border-strong group-hover/field:border-border-strong rounded-lg transition-colors";
289
- var FLOATING_SURFACE_CLASSES = "rounded-lg border border-border-default bg-bg-elevated shadow-lg";
290
- var COUNT_TEXT_CLASSES = "font-mono text-caption tabular-nums text-text-muted";
291
- var CHIP_TEXT_CLASSES = "text-chip signal:font-mono signal:text-small signal:font-semibold signal:tabular-nums";
292
- var MONO_CAPTION_CLASSES = "text-caption text-text-secondary signal:font-mono signal:text-small";
293
- var BARE_INPUT_CLASSES = "bg-transparent text-text-primary placeholder:text-text-muted outline-none";
294
- var SIDEBAR_ROW_CLASSES = "rounded-lg transition-colors";
295
- var SIDEBAR_ROW_TEXT_CLASSES = "text-text-secondary hover:text-text-primary";
296
- var MUTED_CONTROL_CLASSES = "text-text-secondary hover:bg-bg-hover hover:text-text-primary";
297
- var MENU_TRIGGER_CLASSES = "cursor-pointer rounded-md transition-colors hover:bg-bg-hover data-[popup-open]:bg-bg-hover";
298
- var COLLAPSIBLE_PANEL_CLASSES = "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";
390
+ import { Button as BaseButton2 } from "@base-ui/react/button";
299
391
 
300
392
  // src/formBusy.ts
301
- import { createContext as createContext2, useContext as useContext2 } from "react";
302
- var FormBusyContext = createContext2(false);
393
+ import { createContext as createContext3, useContext as useContext3 } from "react";
394
+ var FormBusyContext = createContext3(false);
303
395
  function useFormBusy() {
304
- return useContext2(FormBusyContext);
396
+ return useContext3(FormBusyContext);
305
397
  }
306
398
 
307
399
  // src/Tooltip.tsx
308
400
  import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";
309
-
310
- // src/Kbd.tsx
311
- import { jsx as jsx7 } from "react/jsx-runtime";
312
- function Kbd({ children, className, tone = "default" }) {
313
- return /* @__PURE__ */ jsx7(
314
- "kbd",
315
- {
316
- className: cn(
317
- "inline-flex shrink-0 items-center justify-center whitespace-nowrap rounded-sm border border-border-strong bg-bg-inset px-1 py-px font-sans",
318
- MONO_CAPTION_CLASSES,
319
- "signal:border-b-2 signal:pt-[2px] signal:pb-px signal:bg-bg-wash",
320
- "ship:border-b-2 ship:pt-[2px] ship:pb-px ship:bg-bg-wash ship:font-mono ship:text-small",
321
- // Leaf sets its keys in mono, as Signal does (Katerina, 28 September): the type, not the key's shape.
322
- "leaf:font-mono leaf:text-small",
323
- tone === "tooltip" && "border-border-tooltip-key bg-bg-tooltip-key text-text-tooltip-key signal:bg-bg-tooltip-key ship:bg-bg-tooltip-key",
324
- className
325
- ),
326
- children
327
- }
328
- );
329
- }
330
-
331
- // src/Tooltip.tsx
332
- import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
401
+ import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
333
402
  var OPEN_DELAY = 300;
334
403
  function TooltipProvider({ delay = OPEN_DELAY, closeDelay, timeout, children }) {
335
- return /* @__PURE__ */ jsx8(BaseTooltip.Provider, { delay, closeDelay, timeout, children });
404
+ return /* @__PURE__ */ jsx9(BaseTooltip.Provider, { delay, closeDelay, timeout, children });
336
405
  }
337
406
  function Tooltip({ label, shortcut, className, ...props }) {
338
407
  return /* @__PURE__ */ jsxs4("div", { role: "tooltip", className: cn(FLOATING_SURFACE_CLASSES, "border-border-tooltip bg-bg-tooltip", "min-h-[30px] max-w-80 flex items-center justify-center gap-1.5 px-2 py-1", className), ...props, children: [
339
- /* @__PURE__ */ jsx8("span", { className: "min-w-0 text-caption text-text-tooltip break-words", children: label }),
340
- shortcut && /* @__PURE__ */ jsx8(Kbd, { tone: "tooltip", children: shortcut })
408
+ /* @__PURE__ */ jsx9("span", { className: "min-w-0 text-caption text-text-tooltip break-words", children: label }),
409
+ shortcut && /* @__PURE__ */ jsx9(Kbd, { tone: "tooltip", children: shortcut })
341
410
  ] });
342
411
  }
343
412
  var GAP = 6;
344
413
  var VIEWPORT_PAD = 8;
345
414
  function TooltipSurface({ label, shortcut, placement }) {
346
- return /* @__PURE__ */ jsx8(BaseTooltip.Portal, { children: /* @__PURE__ */ jsx8(
415
+ return /* @__PURE__ */ jsx9(BaseTooltip.Portal, { children: /* @__PURE__ */ jsx9(
347
416
  BaseTooltip.Positioner,
348
417
  {
349
418
  side: placement,
@@ -352,10 +421,10 @@ function TooltipSurface({ label, shortcut, placement }) {
352
421
  collisionPadding: VIEWPORT_PAD,
353
422
  positionMethod: "fixed",
354
423
  className: "pointer-events-none z-[9999]",
355
- children: /* @__PURE__ */ jsx8(
424
+ children: /* @__PURE__ */ jsx9(
356
425
  BaseTooltip.Popup,
357
426
  {
358
- render: /* @__PURE__ */ jsx8(Tooltip, { label, shortcut }),
427
+ render: /* @__PURE__ */ jsx9(Tooltip, { label, shortcut }),
359
428
  className: cn(
360
429
  "transition-[opacity,transform] duration-[120ms] ease-out motion-reduce:transition-none",
361
430
  "data-[ending-style]:duration-[80ms] data-[instant]:duration-0",
@@ -371,19 +440,19 @@ function TooltipSurface({ label, shortcut, placement }) {
371
440
  function WithTooltip({ label, shortcut, placement = "top", wrapperClassName, inline = false, children }) {
372
441
  const Wrapper = inline ? "span" : "div";
373
442
  return /* @__PURE__ */ jsxs4(BaseTooltip.Root, { disableHoverablePopup: true, children: [
374
- /* @__PURE__ */ jsx8(BaseTooltip.Trigger, { delay: OPEN_DELAY, render: /* @__PURE__ */ jsx8(Wrapper, { className: cn("inline-flex shrink-0", inline && "align-top", wrapperClassName) }), children }),
375
- /* @__PURE__ */ jsx8(TooltipSurface, { label, shortcut, placement })
443
+ /* @__PURE__ */ jsx9(BaseTooltip.Trigger, { delay: OPEN_DELAY, render: /* @__PURE__ */ jsx9(Wrapper, { className: cn("inline-flex shrink-0", inline && "align-top", wrapperClassName) }), children }),
444
+ /* @__PURE__ */ jsx9(TooltipSurface, { label, shortcut, placement })
376
445
  ] });
377
446
  }
378
447
  function TooltipTrigger({ label, shortcut, placement = "top", children }) {
379
448
  return /* @__PURE__ */ jsxs4(BaseTooltip.Root, { disableHoverablePopup: true, children: [
380
- /* @__PURE__ */ jsx8(BaseTooltip.Trigger, { delay: OPEN_DELAY, render: children }),
381
- /* @__PURE__ */ jsx8(TooltipSurface, { label, shortcut, placement })
449
+ /* @__PURE__ */ jsx9(BaseTooltip.Trigger, { delay: OPEN_DELAY, render: children }),
450
+ /* @__PURE__ */ jsx9(TooltipSurface, { label, shortcut, placement })
382
451
  ] });
383
452
  }
384
453
 
385
454
  // src/IconButton.tsx
386
- import { jsx as jsx9 } from "react/jsx-runtime";
455
+ import { jsx as jsx10 } from "react/jsx-runtime";
387
456
  function IconButton({
388
457
  variant = "muted",
389
458
  pressed,
@@ -400,6 +469,8 @@ function IconButton({
400
469
  ...props
401
470
  }) {
402
471
  const formBusy = useFormBusy();
472
+ const anchor = props;
473
+ const inApp = useInAppClick(href, anchor.onClick);
403
474
  const unusable = disabled || !!disabledReason || formBusy;
404
475
  const look = (off) => cn(
405
476
  // `shrink-0` stops a flex parent squashing the button; `self-center`
@@ -434,8 +505,8 @@ function IconButton({
434
505
  off && "cursor-not-allowed",
435
506
  className
436
507
  );
437
- const button = href && !unusable ? /* @__PURE__ */ jsx9("a", { href, className: look(false), ...props, children }) : /* @__PURE__ */ jsx9(
438
- BaseButton,
508
+ const button = href && !unusable ? /* @__PURE__ */ jsx10("a", { href, className: look(false), ...anchor, onClick: inApp, children }) : /* @__PURE__ */ jsx10(
509
+ BaseButton2,
439
510
  {
440
511
  type,
441
512
  disabled: unusable,
@@ -448,19 +519,19 @@ function IconButton({
448
519
  );
449
520
  const label = disabledReason ?? tooltip;
450
521
  if (label) {
451
- return /* @__PURE__ */ jsx9(TooltipTrigger, { label, shortcut: disabledReason ? void 0 : tooltipShortcut, placement: tooltipPlacement, children: button });
522
+ return /* @__PURE__ */ jsx10(TooltipTrigger, { label, shortcut: disabledReason ? void 0 : tooltipShortcut, placement: tooltipPlacement, children: button });
452
523
  }
453
524
  return button;
454
525
  }
455
526
 
456
527
  // src/Lightbox.tsx
457
- import { useRef } from "react";
528
+ import { useRef as useRef2 } from "react";
458
529
  import { Dialog } from "@base-ui/react/dialog";
459
530
  import { IconX } from "@tabler/icons-react";
460
- import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
531
+ import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
461
532
  function Lightbox({ src, alt, onClose, className }) {
462
- const popupRef = useRef(null);
463
- return /* @__PURE__ */ jsx10(
533
+ const popupRef = useRef2(null);
534
+ return /* @__PURE__ */ jsx11(
464
535
  Dialog.Root,
465
536
  {
466
537
  open: true,
@@ -468,7 +539,7 @@ function Lightbox({ src, alt, onClose, className }) {
468
539
  if (!open) onClose();
469
540
  },
470
541
  children: /* @__PURE__ */ jsxs5(Dialog.Portal, { children: [
471
- /* @__PURE__ */ jsx10(Dialog.Backdrop, { className: "fixed inset-0 z-40 bg-scrim-strong" }),
542
+ /* @__PURE__ */ jsx11(Dialog.Backdrop, { className: "fixed inset-0 z-40 bg-scrim-strong" }),
472
543
  /* @__PURE__ */ jsxs5(
473
544
  Dialog.Popup,
474
545
  {
@@ -478,7 +549,7 @@ function Lightbox({ src, alt, onClose, className }) {
478
549
  className: "fixed inset-0 z-50 flex items-center justify-center p-8 outline-none",
479
550
  onClick: onClose,
480
551
  children: [
481
- /* @__PURE__ */ jsx10(
552
+ /* @__PURE__ */ jsx11(
482
553
  "img",
483
554
  {
484
555
  src,
@@ -487,12 +558,12 @@ function Lightbox({ src, alt, onClose, className }) {
487
558
  className: cn("max-w-full max-h-full object-contain rounded-lg", className)
488
559
  }
489
560
  ),
490
- /* @__PURE__ */ jsx10(
561
+ /* @__PURE__ */ jsx11(
491
562
  Dialog.Close,
492
563
  {
493
564
  "aria-label": "Close",
494
565
  className: "absolute top-4 right-4 size-8 rounded-full bg-bg-tooltip border border-border-tooltip-key flex items-center justify-center text-text-tooltip-key hover:text-text-tooltip",
495
- children: /* @__PURE__ */ jsx10(IconX, { size: 16, stroke: 1.5 })
566
+ children: /* @__PURE__ */ jsx11(IconX, { size: 16, stroke: 1.5 })
496
567
  }
497
568
  )
498
569
  ]
@@ -504,7 +575,7 @@ function Lightbox({ src, alt, onClose, className }) {
504
575
  }
505
576
 
506
577
  // src/AttachmentCard.tsx
507
- import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
578
+ import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
508
579
  var ICON_BY_EXTENSION = {
509
580
  pdf: IconFileTypePdf,
510
581
  doc: IconFileTypeDocx,
@@ -538,10 +609,10 @@ var NAME_CLASSES = "text-caption font-medium text-text-primary truncate";
538
609
  var NOTE_CLASSES = "text-small tracking-wide leading-tight truncate";
539
610
  function TypeIcon({ name }) {
540
611
  const Icon = ICON_BY_EXTENSION[extensionOf(name)] ?? IconFile;
541
- return /* @__PURE__ */ jsx11(Icon, { size: 20, stroke: 1.5 });
612
+ return /* @__PURE__ */ jsx12(Icon, { size: 20, stroke: 1.5 });
542
613
  }
543
614
  function Truncating({ text, hint, className, wrapperClassName, placement }) {
544
- const ref = useRef2(null);
615
+ const ref = useRef3(null);
545
616
  const [cut, setCut] = useState(false);
546
617
  useLayoutEffect(() => {
547
618
  const el = ref.current;
@@ -560,15 +631,15 @@ function Truncating({ text, hint, className, wrapperClassName, placement }) {
560
631
  observer.disconnect();
561
632
  };
562
633
  }, [text, cut]);
563
- const line = /* @__PURE__ */ jsx11("span", { ref, className, children: text });
634
+ const line = /* @__PURE__ */ jsx12("span", { ref, className, children: text });
564
635
  if (!hint && !cut) return line;
565
- return /* @__PURE__ */ jsx11(WithTooltip, { label: hint ?? text, placement, wrapperClassName: cn("min-w-0 flex-col", wrapperClassName), children: line });
636
+ return /* @__PURE__ */ jsx12(WithTooltip, { label: hint ?? text, placement, wrapperClassName: cn("min-w-0 flex-col", wrapperClassName), children: line });
566
637
  }
567
638
  function useRemoteImage(url, fetchImage) {
568
639
  const [result, setResult] = useState({});
569
- const fetcher = useRef2(fetchImage);
640
+ const fetcher = useRef3(fetchImage);
570
641
  fetcher.current = fetchImage;
571
- useEffect(() => {
642
+ useEffect2(() => {
572
643
  if (!url || !fetcher.current) return;
573
644
  let live = true;
574
645
  fetcher.current(url).then(
@@ -641,7 +712,7 @@ function AttachmentCard({
641
712
  const full = useRemoteImage(opened ? remoteFullSrc : void 0, fetchImage);
642
713
  const openable = image && !!picture && !pending;
643
714
  const openPicture = onOpen ?? (openable ? () => setOpened(true) : void 0);
644
- const viewer = opened && picture ? /* @__PURE__ */ jsx11(Lightbox, { src: full.src ?? picture, alt: alt ?? name, onClose: () => setOpened(false) }) : null;
715
+ const viewer = opened && picture ? /* @__PURE__ */ jsx12(Lightbox, { src: full.src ?? picture, alt: alt ?? name, onClose: () => setOpened(false) }) : null;
645
716
  const saveHere = download ? () => {
646
717
  const source = remoteFullSrc ?? remoteSrc;
647
718
  if (source && fetchImage) {
@@ -670,10 +741,10 @@ function AttachmentCard({
670
741
  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),
671
742
  ...props,
672
743
  children: [
673
- /* @__PURE__ */ jsx11("div", { className: cn(TILE_CLASSES, "overflow-hidden"), children: state === "uploading" ? /* @__PURE__ */ jsx11(IconLoader2, { size: 16, stroke: 1.5, className: "animate-spin" }) : failed ? /* @__PURE__ */ jsx11(IconAlertCircle, { size: 16, stroke: 1.5, className: "text-error-default" }) : warning ? /* @__PURE__ */ jsx11(IconAlertTriangle, { size: 16, stroke: 1.5, className: "text-warning-default" }) : image && src ? /* @__PURE__ */ jsx11("img", { src, alt: name, className: "size-full object-cover" }) : /* @__PURE__ */ jsx11("span", { className: "text-menu font-semibold", children: typeLabelOf(name) }) }),
744
+ /* @__PURE__ */ jsx12("div", { className: cn(TILE_CLASSES, "overflow-hidden"), children: state === "uploading" ? /* @__PURE__ */ jsx12(IconLoader2, { size: 16, stroke: 1.5, className: "animate-spin" }) : failed ? /* @__PURE__ */ jsx12(IconAlertCircle, { size: 16, stroke: 1.5, className: "text-error-default" }) : warning ? /* @__PURE__ */ jsx12(IconAlertTriangle, { size: 16, stroke: 1.5, className: "text-warning-default" }) : image && src ? /* @__PURE__ */ jsx12("img", { src, alt: name, className: "size-full object-cover" }) : /* @__PURE__ */ jsx12("span", { className: "text-menu font-semibold", children: typeLabelOf(name) }) }),
674
745
  /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-[1px] min-w-0", children: [
675
- /* @__PURE__ */ jsx11(Truncating, { text: name, className: NAME_CLASSES, placement: onRemove ? "bottom" : void 0 }),
676
- /* @__PURE__ */ jsx11(
746
+ /* @__PURE__ */ jsx12(Truncating, { text: name, className: NAME_CLASSES, placement: onRemove ? "bottom" : void 0 }),
747
+ /* @__PURE__ */ jsx12(
677
748
  Truncating,
678
749
  {
679
750
  text: (failed || warning ? note : state === "uploading" ? note ?? "Uploading\u2026" : note ?? sizeText) ?? "",
@@ -682,8 +753,8 @@ function AttachmentCard({
682
753
  }
683
754
  )
684
755
  ] }),
685
- onRemove && /* @__PURE__ */ jsx11(
686
- BaseButton2,
756
+ onRemove && /* @__PURE__ */ jsx12(
757
+ BaseButton3,
687
758
  {
688
759
  type: "button",
689
760
  "aria-label": `Remove ${name}`,
@@ -692,7 +763,7 @@ function AttachmentCard({
692
763
  event.stopPropagation();
693
764
  onRemove();
694
765
  },
695
- children: /* @__PURE__ */ jsx11(IconX2, { size: 11, stroke: 1.75 })
766
+ children: /* @__PURE__ */ jsx12(IconX2, { size: 11, stroke: 1.75 })
696
767
  }
697
768
  )
698
769
  ]
@@ -702,7 +773,7 @@ function AttachmentCard({
702
773
  }
703
774
  const downloadControl = saving ? (
704
775
  // @estiva-escape(no-restyled-part): Download shows when its card is pointed at or focused, AttachmentCard's own action; IconButton has no reveal on its card's hover (UIG-9, Katerina 17 September)
705
- /* @__PURE__ */ jsx11(
776
+ /* @__PURE__ */ jsx12(
706
777
  IconButton,
707
778
  {
708
779
  variant: "muted",
@@ -713,7 +784,7 @@ function AttachmentCard({
713
784
  event.stopPropagation();
714
785
  saving();
715
786
  },
716
- children: /* @__PURE__ */ jsx11(IconDownload, { size: 16, stroke: 1.5 })
787
+ children: /* @__PURE__ */ jsx12(IconDownload, { size: 16, stroke: 1.5 })
717
788
  }
718
789
  )
719
790
  ) : null;
@@ -722,27 +793,27 @@ function AttachmentCard({
722
793
  // `role="status"`: a plain box may not carry a name (axe, aria-prohibited-attr), and a
723
794
  // status says what it is doing — loading — to a reader that cannot see the pulse.
724
795
  // @estiva-escape(no-restyled-part): the loading pulse is AttachmentCard's own state; Card has no loading state (UIG-9, Katerina 17 September)
725
- /* @__PURE__ */ jsx11(Card, { role: "status", fill: "inset", "aria-busy": "true", "aria-label": `Loading ${name}`, className: cn("w-[180px] h-28 animate-pulse", className), ...props, children: null })
796
+ /* @__PURE__ */ jsx12(Card, { role: "status", fill: "inset", "aria-busy": "true", "aria-label": `Loading ${name}`, className: cn("w-[180px] h-28 animate-pulse", className), ...props, children: null })
726
797
  );
727
798
  }
728
799
  if (drawnState === "unreadable") {
729
800
  return (
730
801
  // @estiva-escape(no-restyled-part): a file that could not be read is faded as well as dashed, AttachmentCard's own state; Card has no faded state (UIG-9, Katerina 17 September)
731
802
  /* @__PURE__ */ jsxs6(Card, { fill: "inset", unreadable: true, className: cn("flex items-center gap-2 w-[240px] p-1.5 opacity-70", className), ...props, children: [
732
- /* @__PURE__ */ jsx11("div", { className: TILE_CLASSES, children: /* @__PURE__ */ jsx11(TypeIcon, { name }) }),
803
+ /* @__PURE__ */ jsx12("div", { className: TILE_CLASSES, children: /* @__PURE__ */ jsx12(TypeIcon, { name }) }),
733
804
  /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-[1px] min-w-0 text-left", children: [
734
- /* @__PURE__ */ jsx11(Truncating, { text: name, className: NAME_CLASSES }),
735
- /* @__PURE__ */ jsx11("span", { className: cn(NOTE_CLASSES, "text-text-secondary"), children: note ?? "Could not be loaded" })
805
+ /* @__PURE__ */ jsx12(Truncating, { text: name, className: NAME_CLASSES }),
806
+ /* @__PURE__ */ jsx12("span", { className: cn(NOTE_CLASSES, "text-text-secondary"), children: note ?? "Could not be loaded" })
736
807
  ] })
737
808
  ] })
738
809
  );
739
810
  }
740
811
  if (image && picture) {
741
- const thumbnail = /* @__PURE__ */ jsx11("img", { src: picture, alt: alt ?? name, className: "w-full h-28 object-cover" });
812
+ const thumbnail = /* @__PURE__ */ jsx12("img", { src: picture, alt: alt ?? name, className: "w-full h-28 object-cover" });
742
813
  return /* @__PURE__ */ jsxs6(Fragment2, { children: [
743
814
  /* @__PURE__ */ jsxs6(Card, { fill: "inset", hover: "hairline", clip: true, className: cn("group relative flex flex-col w-[180px]", className), ...props, children: [
744
- openPicture ? /* @__PURE__ */ jsx11(
745
- BaseButton2,
815
+ openPicture ? /* @__PURE__ */ jsx12(
816
+ BaseButton3,
746
817
  {
747
818
  type: "button",
748
819
  className: "block w-full",
@@ -753,9 +824,9 @@ function AttachmentCard({
753
824
  },
754
825
  children: thumbnail
755
826
  }
756
- ) : /* @__PURE__ */ jsx11("div", { className: "block w-full", children: thumbnail }),
827
+ ) : /* @__PURE__ */ jsx12("div", { className: "block w-full", children: thumbnail }),
757
828
  /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1 pl-2 pr-1 py-1 min-w-0", children: [
758
- /* @__PURE__ */ jsx11(Truncating, { text: name, className: "flex-1 text-caption text-text-primary truncate", wrapperClassName: "flex-1" }),
829
+ /* @__PURE__ */ jsx12(Truncating, { text: name, className: "flex-1 text-caption text-text-primary truncate", wrapperClassName: "flex-1" }),
759
830
  downloadControl
760
831
  ] })
761
832
  ] }),
@@ -763,16 +834,16 @@ function AttachmentCard({
763
834
  ] });
764
835
  }
765
836
  const body = /* @__PURE__ */ jsxs6(Fragment2, { children: [
766
- /* @__PURE__ */ jsx11("div", { className: TILE_CLASSES, children: /* @__PURE__ */ jsx11(TypeIcon, { name }) }),
837
+ /* @__PURE__ */ jsx12("div", { className: TILE_CLASSES, children: /* @__PURE__ */ jsx12(TypeIcon, { name }) }),
767
838
  /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-[1px] min-w-0 text-left", children: [
768
- /* @__PURE__ */ jsx11(Truncating, { text: name, className: NAME_CLASSES }),
769
- /* @__PURE__ */ jsx11("span", { className: cn(NOTE_CLASSES, "text-text-secondary"), children: note ?? `${typeLabelOf(name)} \xB7 ${sizeText}` })
839
+ /* @__PURE__ */ jsx12(Truncating, { text: name, className: NAME_CLASSES }),
840
+ /* @__PURE__ */ jsx12("span", { className: cn(NOTE_CLASSES, "text-text-secondary"), children: note ?? `${typeLabelOf(name)} \xB7 ${sizeText}` })
770
841
  ] })
771
842
  ] });
772
843
  return (
773
844
  // @estiva-escape(no-restyled-part): a file that cannot be opened is faded, AttachmentCard's own state; Card has no faded state (UIG-9, Katerina 17 September)
774
845
  /* @__PURE__ */ jsxs6(Card, { fill: "inset", hover: address ? "hairline" : "none", className: cn("group flex items-center gap-2 w-[240px] p-1.5 pr-1", !address && "opacity-70", className), ...props, children: [
775
- address ? /* @__PURE__ */ jsx11(Link, { href: address, external: true, variant: "plain", className: "flex items-center gap-2 min-w-0 flex-1", onClick: (event) => event.stopPropagation(), children: body }) : /* @__PURE__ */ jsx11("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: body }),
846
+ address ? /* @__PURE__ */ jsx12(Link, { href: address, external: true, variant: "plain", className: "flex items-center gap-2 min-w-0 flex-1", onClick: (event) => event.stopPropagation(), children: body }) : /* @__PURE__ */ jsx12("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: body }),
776
847
  downloadControl
777
848
  ] })
778
849
  );
@@ -781,7 +852,7 @@ function AttachmentCard({
781
852
  // src/Avatar.tsx
782
853
  import { Avatar as BaseAvatar } from "@base-ui/react/avatar";
783
854
  import { IconUserFilled } from "@tabler/icons-react";
784
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
855
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
785
856
  var HUES = ["#56c8ff", "#ff8f6b", "#4ade8c", "#b18cff", "#ffc94d", "#ff7eb0", "#7ea8ff", "#5fdfd6"];
786
857
  var hueFor = (key) => {
787
858
  let h = 0;
@@ -795,27 +866,29 @@ var initialsFor = (name) => {
795
866
  };
796
867
  function Avatar({ src, name, alt = "", size = 36, label: spoken, className }) {
797
868
  const label = name || alt;
869
+ const pictureFor = usePictureFor();
870
+ const picture = src ?? (label && pictureFor ? pictureFor(label) ?? void 0 : void 0);
798
871
  return /* @__PURE__ */ jsxs7(
799
872
  BaseAvatar.Root,
800
873
  {
801
- render: /* @__PURE__ */ jsx12("div", {}),
874
+ render: /* @__PURE__ */ jsx13("div", {}),
802
875
  ...spoken ? { role: "img", "aria-label": spoken } : { "aria-hidden": true },
803
876
  className: cn("rounded-sm overflow-hidden shrink-0 bg-bg-inset", className),
804
877
  style: { width: size, height: size },
805
878
  children: [
806
- src && /* @__PURE__ */ jsx12(
879
+ picture && /* @__PURE__ */ jsx13(
807
880
  BaseAvatar.Image,
808
881
  {
809
- src,
882
+ src: picture,
810
883
  alt: "",
811
884
  keepMounted: true,
812
885
  className: "w-full h-full object-cover data-[error]:hidden"
813
886
  }
814
887
  ),
815
- label ? /* @__PURE__ */ jsx12(
888
+ label ? /* @__PURE__ */ jsx13(
816
889
  BaseAvatar.Fallback,
817
890
  {
818
- render: /* @__PURE__ */ jsx12("div", {}),
891
+ render: /* @__PURE__ */ jsx13("div", {}),
819
892
  className: "w-full h-full flex items-center justify-center font-semibold leading-none",
820
893
  style: {
821
894
  /* eslint-disable no-restricted-syntax -- @estiva-escape: the per-person palette (the note at
@@ -829,32 +902,32 @@ function Avatar({ src, name, alt = "", size = 36, label: spoken, className }) {
829
902
  background: `linear-gradient(160deg, color-mix(in srgb, ${hueFor(label)} 92%, #fff) 0%, color-mix(in srgb, ${hueFor(label)} 70%, #0b0d11) 100%)`
830
903
  /* eslint-enable no-restricted-syntax */
831
904
  },
832
- children: /* @__PURE__ */ jsx12("span", { className: "[text-box:trim-both_cap_alphabetic]", children: initialsFor(label) })
905
+ children: /* @__PURE__ */ jsx13("span", { className: "[text-box:trim-both_cap_alphabetic]", children: initialsFor(label) })
833
906
  }
834
- ) : /* @__PURE__ */ jsx12(BaseAvatar.Fallback, { render: /* @__PURE__ */ jsx12("div", {}), className: "w-full h-full bg-accent-muted flex items-center justify-center text-text-muted", children: /* @__PURE__ */ jsx12(IconUserFilled, { size: Math.round(size * 0.5) }) })
907
+ ) : /* @__PURE__ */ jsx13(BaseAvatar.Fallback, { render: /* @__PURE__ */ jsx13("div", {}), className: "w-full h-full bg-accent-muted flex items-center justify-center text-text-muted", children: /* @__PURE__ */ jsx13(IconUserFilled, { size: Math.round(size * 0.5) }) })
835
908
  ]
836
909
  }
837
910
  );
838
911
  }
839
912
 
840
913
  // src/AvatarGroup.tsx
841
- import { jsx as jsx13 } from "react/jsx-runtime";
914
+ import { jsx as jsx14 } from "react/jsx-runtime";
842
915
  function AvatarGroup({ members, size = 24 }) {
843
916
  const visible = members.slice(0, 3);
844
917
  const overlap = Math.round(size / 3);
845
918
  const ring = size / 12;
846
- return /* @__PURE__ */ jsx13("div", { className: "flex items-center", style: { paddingRight: overlap }, children: visible.map((member, i) => (
919
+ return /* @__PURE__ */ jsx14("div", { className: "flex items-center", style: { paddingRight: overlap }, children: visible.map((member, i) => (
847
920
  /*
848
921
  The wrapper carries the overlap and the ring; the face carries
849
922
  neither. It must never clip — see the note at the top of the file —
850
923
  so it has the avatar's own radius and no overflow of its own.
851
924
  */
852
- /* @__PURE__ */ jsx13(
925
+ /* @__PURE__ */ jsx14(
853
926
  "span",
854
927
  {
855
928
  className: "relative flex rounded-sm",
856
929
  style: { marginRight: -overlap, boxShadow: `0 0 0 ${ring}px var(--bg-surface)` },
857
- children: /* @__PURE__ */ jsx13(Avatar, { size, name: member.name, src: member.picture, label: member.name })
930
+ children: /* @__PURE__ */ jsx14(Avatar, { size, name: member.name, src: member.picture, label: member.name })
858
931
  },
859
932
  i
860
933
  )
@@ -862,8 +935,8 @@ function AvatarGroup({ members, size = 24 }) {
862
935
  }
863
936
 
864
937
  // src/Button.tsx
865
- import { Button as BaseButton3 } from "@base-ui/react/button";
866
- import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
938
+ import { Button as BaseButton4 } from "@base-ui/react/button";
939
+ import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
867
940
  function Button({
868
941
  variant = "muted",
869
942
  size = "default",
@@ -878,7 +951,7 @@ function Button({
878
951
  const hasLeadingIcon = !!leadingIcon;
879
952
  const formBusy = useFormBusy();
880
953
  const button = /* @__PURE__ */ jsxs8(
881
- BaseButton3,
954
+ BaseButton4,
882
955
  {
883
956
  type,
884
957
  disabled: disabled || !!disabledReason || formBusy,
@@ -925,17 +998,17 @@ function Button({
925
998
  ]
926
999
  }
927
1000
  );
928
- return disabledReason ? /* @__PURE__ */ jsx14(TooltipTrigger, { label: disabledReason, children: button }) : button;
1001
+ return disabledReason ? /* @__PURE__ */ jsx15(TooltipTrigger, { label: disabledReason, children: button }) : button;
929
1002
  }
930
1003
 
931
1004
  // src/MembersPill.tsx
932
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1005
+ import { jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
933
1006
  function MembersPill({ members, count, onClick, className }) {
934
1007
  const total = count ?? members.length;
935
1008
  if (total === 0) return null;
936
1009
  return /* @__PURE__ */ jsxs9(Button, { variant: "outlined", "aria-label": `${total} ${total === 1 ? "member" : "members"}`, disabled: !onClick, onClick, className: cn("gap-2 pl-[3px] pr-2", className), children: [
937
- /* @__PURE__ */ jsx15(AvatarGroup, { members }),
938
- /* @__PURE__ */ jsx15("span", { className: cn(MONO_CAPTION_CLASSES, "signal:tabular-nums"), children: total })
1010
+ /* @__PURE__ */ jsx16(AvatarGroup, { members }),
1011
+ /* @__PURE__ */ jsx16("span", { className: cn(MONO_CAPTION_CLASSES, "signal:tabular-nums"), children: total })
939
1012
  ] });
940
1013
  }
941
1014
 
@@ -944,7 +1017,7 @@ import { useId, useState as useState3 } from "react";
944
1017
  import { IconArrowLeft, IconUserMinus, IconUserPlus } from "@tabler/icons-react";
945
1018
 
946
1019
  // src/Chip.tsx
947
- import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
1020
+ import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
948
1021
  var typeStyles = {
949
1022
  neutral: "bg-bg-inset text-text-primary",
950
1023
  brand: "bg-accent-muted text-accent-text signal:border signal:border-accent-outline",
@@ -954,9 +1027,10 @@ var typeStyles = {
954
1027
  error: "bg-error-muted text-error-default signal:border signal:border-error-outline"
955
1028
  };
956
1029
  function Chip({ type = "neutral", label, leadingIcon, trailingIcon, href, onClick, className }) {
1030
+ const inApp = useInAppClick(href, onClick);
957
1031
  const classes = 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);
958
1032
  const inside = /* @__PURE__ */ jsxs10(Fragment3, { children: [
959
- leadingIcon && /* @__PURE__ */ jsx16("span", { className: "flex size-3 shrink-0 items-center justify-center", children: leadingIcon }),
1033
+ leadingIcon && /* @__PURE__ */ jsx17("span", { className: "flex size-3 shrink-0 items-center justify-center", children: leadingIcon }),
960
1034
  label && // A chip given a `max-w-*` cuts a long label with an ellipsis instead
961
1035
  // of growing past it — Ship's project chip on an issue row
962
1036
  // (2026-09-09). Clipped sideways only: `overflow-x-clip`, not
@@ -965,31 +1039,31 @@ function Chip({ type = "neutral", label, leadingIcon, trailingIcon, href, onClic
965
1039
  // the screenshot diff caught every descender cut off. `clip` is the
966
1040
  // one overflow that leaves the other axis visible. A chip with no cap
967
1041
  // draws exactly as before.
968
- /* @__PURE__ */ jsx16("span", { className: cn("min-w-0 overflow-x-clip text-ellipsis whitespace-nowrap signal:tracking-wide", CHIP_TEXT_CLASSES), children: label }),
969
- trailingIcon && /* @__PURE__ */ jsx16("span", { className: "flex size-3 shrink-0 items-center justify-center", children: trailingIcon })
1042
+ /* @__PURE__ */ jsx17("span", { className: cn("min-w-0 overflow-x-clip text-ellipsis whitespace-nowrap signal:tracking-wide", CHIP_TEXT_CLASSES), children: label }),
1043
+ trailingIcon && /* @__PURE__ */ jsx17("span", { className: "flex size-3 shrink-0 items-center justify-center", children: trailingIcon })
970
1044
  ] });
971
- if (href) return /* @__PURE__ */ jsx16("a", { href, onClick, className: cn("relative", classes), children: inside });
972
- return /* @__PURE__ */ jsx16("div", { className: classes, children: inside });
1045
+ if (href) return /* @__PURE__ */ jsx17("a", { href, onClick: inApp, className: cn("relative", classes), children: inside });
1046
+ return /* @__PURE__ */ jsx17("div", { className: classes, children: inside });
973
1047
  }
974
1048
 
975
1049
  // src/ChipInput.tsx
976
- import { useMemo, useState as useState2 } from "react";
977
- import { Button as BaseButton4 } from "@base-ui/react/button";
1050
+ import { useMemo as useMemo2, useState as useState2 } from "react";
1051
+ import { Button as BaseButton5 } from "@base-ui/react/button";
978
1052
  import { Combobox } from "@base-ui/react/combobox";
979
1053
  import { IconX as IconX3 } from "@tabler/icons-react";
980
1054
 
981
1055
  // src/Menu.tsx
982
- import { createContext as createContext4, useContext as useContext4 } from "react";
1056
+ import { createContext as createContext5, useContext as useContext5 } from "react";
983
1057
  import { IconChevronRight } from "@tabler/icons-react";
984
1058
  import { Menu as BaseMenu } from "@base-ui/react/menu";
985
1059
 
986
1060
  // src/Divider.tsx
987
- import { createContext as createContext3, useContext as useContext3 } from "react";
1061
+ import { createContext as createContext4, useContext as useContext4 } from "react";
988
1062
  import { Separator } from "@base-ui/react/separator";
989
- import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
990
- var DividerInPanel = createContext3(false);
1063
+ import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
1064
+ var DividerInPanel = createContext4(false);
991
1065
  function Divider({ orientation = "horizontal", label, tone = "default", className }) {
992
- const inset = useContext3(DividerInPanel) ? "mx-0" : "mx-3";
1066
+ const inset = useContext4(DividerInPanel) ? "mx-0" : "mx-3";
993
1067
  if (label && orientation === "horizontal") {
994
1068
  const line = tone === "warning" ? "bg-warning-muted" : "bg-border-subtle";
995
1069
  return /* @__PURE__ */ jsxs11(
@@ -999,14 +1073,14 @@ function Divider({ orientation = "horizontal", label, tone = "default", classNam
999
1073
  "aria-label": label,
1000
1074
  className: cn("flex shrink-0 items-center gap-2", inset, className),
1001
1075
  children: [
1002
- /* @__PURE__ */ jsx17("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
1003
- /* @__PURE__ */ jsx17("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
1004
- /* @__PURE__ */ jsx17("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
1076
+ /* @__PURE__ */ jsx18("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) }),
1077
+ /* @__PURE__ */ jsx18("span", { className: cn("shrink-0 text-caption", tone === "warning" ? "text-warning-default" : "text-text-muted"), children: label }),
1078
+ /* @__PURE__ */ jsx18("span", { "aria-hidden": "true", className: cn("h-px flex-1", line) })
1005
1079
  ]
1006
1080
  }
1007
1081
  );
1008
1082
  }
1009
- return /* @__PURE__ */ jsx17(
1083
+ return /* @__PURE__ */ jsx18(
1010
1084
  Separator,
1011
1085
  {
1012
1086
  orientation,
@@ -1022,7 +1096,7 @@ function triggerDisabled(trigger) {
1022
1096
  }
1023
1097
 
1024
1098
  // src/SectionLabel.tsx
1025
- import { jsx as jsx18 } from "react/jsx-runtime";
1099
+ import { jsx as jsx19 } from "react/jsx-runtime";
1026
1100
  function SectionLabel({
1027
1101
  children,
1028
1102
  tone = "primary",
@@ -1030,7 +1104,7 @@ function SectionLabel({
1030
1104
  folds = false,
1031
1105
  className
1032
1106
  }) {
1033
- return /* @__PURE__ */ jsx18(
1107
+ return /* @__PURE__ */ jsx19(
1034
1108
  "span",
1035
1109
  {
1036
1110
  className: cn(
@@ -1051,10 +1125,10 @@ function SectionLabel({
1051
1125
  }
1052
1126
 
1053
1127
  // src/Menu.tsx
1054
- import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
1055
- var MenuContext = createContext4(null);
1128
+ import { Fragment as Fragment4, jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
1129
+ var MenuContext = createContext5(null);
1056
1130
  function MenuPanel({ children, className, ...props }) {
1057
- return /* @__PURE__ */ jsx19(
1131
+ return /* @__PURE__ */ jsx20(
1058
1132
  "div",
1059
1133
  {
1060
1134
  className: cn(
@@ -1094,7 +1168,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
1094
1168
  actionsRef,
1095
1169
  modal: false,
1096
1170
  children: [
1097
- /* @__PURE__ */ jsx19(
1171
+ /* @__PURE__ */ jsx20(
1098
1172
  BaseMenu.Trigger,
1099
1173
  {
1100
1174
  render: trigger,
@@ -1104,7 +1178,7 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
1104
1178
  closeDelay: HOVER_CLOSE_DELAY
1105
1179
  }
1106
1180
  ),
1107
- /* @__PURE__ */ jsx19(BaseMenu.Portal, { children: /* @__PURE__ */ jsx19(
1181
+ /* @__PURE__ */ jsx20(BaseMenu.Portal, { children: /* @__PURE__ */ jsx20(
1108
1182
  BaseMenu.Positioner,
1109
1183
  {
1110
1184
  side: "bottom",
@@ -1112,13 +1186,13 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
1112
1186
  sideOffset: GAP2,
1113
1187
  collisionPadding: VIEWPORT_PAD2,
1114
1188
  className: "z-50 data-[anchor-hidden]:hidden",
1115
- children: /* @__PURE__ */ jsx19(
1189
+ children: /* @__PURE__ */ jsx20(
1116
1190
  BaseMenu.Popup,
1117
1191
  {
1118
1192
  "data-interactive": true,
1119
1193
  className: cn("min-w-[180px] outline-none p-0", className),
1120
- render: /* @__PURE__ */ jsx19(MenuPanel, {}),
1121
- children: /* @__PURE__ */ jsx19(ScrollArea, { viewportClassName: "max-h-[var(--available-height)]", contentClassName: cn("flex flex-col gap-0.5 p-2", contentClassName), children: /* @__PURE__ */ jsx19(MenuContext.Provider, { value: { openOnHover }, children: /* @__PURE__ */ jsx19(DividerInPanel.Provider, { value: true, children }) }) })
1194
+ render: /* @__PURE__ */ jsx20(MenuPanel, {}),
1195
+ children: /* @__PURE__ */ jsx20(ScrollArea, { viewportClassName: "max-h-[var(--available-height)]", contentClassName: cn("flex flex-col gap-0.5 p-2", contentClassName), children: /* @__PURE__ */ jsx20(MenuContext.Provider, { value: { openOnHover }, children: /* @__PURE__ */ jsx20(DividerInPanel.Provider, { value: true, children }) }) })
1122
1196
  }
1123
1197
  )
1124
1198
  }
@@ -1128,26 +1202,26 @@ function Menu({ trigger, align = "left", openOnHover = false, open, onOpenChange
1128
1202
  );
1129
1203
  }
1130
1204
  function MenuSub({ label, leading, selected, children, className }) {
1131
- const menu = useContext4(MenuContext);
1205
+ const menu = useContext5(MenuContext);
1132
1206
  if (!isProduction() && menu?.openOnHover) {
1133
1207
  console.error(
1134
1208
  '[@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".'
1135
1209
  );
1136
1210
  }
1137
1211
  return /* @__PURE__ */ jsxs12(BaseMenu.SubmenuRoot, { children: [
1138
- /* @__PURE__ */ jsx19(
1212
+ /* @__PURE__ */ jsx20(
1139
1213
  BaseMenu.SubmenuTrigger,
1140
1214
  {
1141
1215
  openOnHover: true,
1142
1216
  delay: 0,
1143
1217
  closeDelay: 150,
1144
1218
  nativeButton: true,
1145
- render: /* @__PURE__ */ jsx19("button", { type: "button" }),
1219
+ render: /* @__PURE__ */ jsx20("button", { type: "button" }),
1146
1220
  className: menuItemClassName({ size: "default", selected }),
1147
- children: /* @__PURE__ */ jsx19(MenuItemBody, { label, leading, submenu: true })
1221
+ children: /* @__PURE__ */ jsx20(MenuItemBody, { label, leading, submenu: true })
1148
1222
  }
1149
1223
  ),
1150
- /* @__PURE__ */ jsx19(BaseMenu.Portal, { children: /* @__PURE__ */ jsx19(
1224
+ /* @__PURE__ */ jsx20(BaseMenu.Portal, { children: /* @__PURE__ */ jsx20(
1151
1225
  BaseMenu.Positioner,
1152
1226
  {
1153
1227
  side: "inline-end",
@@ -1155,7 +1229,7 @@ function MenuSub({ label, leading, selected, children, className }) {
1155
1229
  sideOffset: GAP2,
1156
1230
  collisionPadding: VIEWPORT_PAD2,
1157
1231
  className: "z-50 data-[anchor-hidden]:hidden",
1158
- children: /* @__PURE__ */ jsx19(BaseMenu.Popup, { className: cn("w-[160px]", className), "data-interactive": true, render: /* @__PURE__ */ jsx19(MenuPanel, {}), children })
1232
+ children: /* @__PURE__ */ jsx20(BaseMenu.Popup, { className: cn("w-[160px]", className), "data-interactive": true, render: /* @__PURE__ */ jsx20(MenuPanel, {}), children })
1159
1233
  }
1160
1234
  ) })
1161
1235
  ] });
@@ -1190,25 +1264,25 @@ function menuItemClassName({ size, selected, className }) {
1190
1264
  );
1191
1265
  }
1192
1266
  function MenuItemBody({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected }) {
1193
- const edge = trailing ?? (shortcut ? /* @__PURE__ */ jsx19(Kbd, { children: shortcut }) : submenu ? /* @__PURE__ */ jsx19(IconChevronRight, { size: 16, stroke: 1.5, className: "shrink-0 text-text-muted" }) : null);
1267
+ const edge = trailing ?? (shortcut ? /* @__PURE__ */ jsx20(Kbd, { children: shortcut }) : submenu ? /* @__PURE__ */ jsx20(IconChevronRight, { size: 16, stroke: 1.5, className: "shrink-0 text-text-muted" }) : null);
1194
1268
  return /* @__PURE__ */ jsxs12(Fragment4, { children: [
1195
- leading && /* @__PURE__ */ jsx19("span", { className: "flex shrink-0 items-center", children: leading }),
1269
+ leading && /* @__PURE__ */ jsx20("span", { className: "flex shrink-0 items-center", children: leading }),
1196
1270
  children ?? /* @__PURE__ */ jsxs12("span", { className: cn("flex min-w-0 flex-1 flex-col", size === "tall" && "gap-[2px]"), children: [
1197
- /* @__PURE__ */ jsx19("span", { className: cn("truncate text-body-2", destructive ? "text-error-default" : "text-text-primary"), children: label }),
1198
- description && /* @__PURE__ */ jsx19("span", { className: "truncate text-caption text-text-secondary", children: description })
1271
+ /* @__PURE__ */ jsx20("span", { className: cn("truncate text-body-2", destructive ? "text-error-default" : "text-text-primary"), children: label }),
1272
+ description && /* @__PURE__ */ jsx20("span", { className: "truncate text-caption text-text-secondary", children: description })
1199
1273
  ] }),
1200
1274
  (edge || hint) && // One grid cell holding both, right-aligned: the slot is as wide as
1201
1275
  // the wider of the two and never changes, so revealing the hint moves
1202
1276
  // nothing. No transition here either — the hint switches on the same
1203
1277
  // :hover / `selected` as the fill, in the same frame.
1204
1278
  /* @__PURE__ */ jsxs12("span", { className: "grid shrink-0 items-center justify-items-end [&>*]:col-start-1 [&>*]:row-start-1", children: [
1205
- edge && /* @__PURE__ */ jsx19("span", { className: cn("flex items-center", hint && "group-hover:opacity-0 group-data-[highlighted]:opacity-0", hint && selected && "opacity-0"), children: edge }),
1206
- hint && /* @__PURE__ */ jsx19("span", { className: cn("flex items-center opacity-0 group-hover:opacity-100 group-data-[highlighted]:opacity-100", selected && "opacity-100"), children: hint })
1279
+ edge && /* @__PURE__ */ jsx20("span", { className: cn("flex items-center", hint && "group-hover:opacity-0 group-data-[highlighted]:opacity-0", hint && selected && "opacity-0"), children: edge }),
1280
+ hint && /* @__PURE__ */ jsx20("span", { className: cn("flex items-center opacity-0 group-hover:opacity-100 group-data-[highlighted]:opacity-100", selected && "opacity-100"), children: hint })
1207
1281
  ] })
1208
1282
  ] });
1209
1283
  }
1210
1284
  function MenuItem({ label, children, size = "default", description, leading, trailing, hint, shortcut, submenu, destructive, selected, className, ...props }) {
1211
- const body = /* @__PURE__ */ jsx19(
1285
+ const body = /* @__PURE__ */ jsx20(
1212
1286
  MenuItemBody,
1213
1287
  {
1214
1288
  label,
@@ -1225,14 +1299,14 @@ function MenuItem({ label, children, size = "default", description, leading, tra
1225
1299
  }
1226
1300
  );
1227
1301
  const rowClassName = menuItemClassName({ size, selected, className });
1228
- if (!useContext4(MenuContext)) {
1229
- return /* @__PURE__ */ jsx19("button", { type: "button", className: rowClassName, ...props, children: body });
1302
+ if (!useContext5(MenuContext)) {
1303
+ return /* @__PURE__ */ jsx20("button", { type: "button", className: rowClassName, ...props, children: body });
1230
1304
  }
1231
- return /* @__PURE__ */ jsx19(
1305
+ return /* @__PURE__ */ jsx20(
1232
1306
  BaseMenu.Item,
1233
1307
  {
1234
1308
  nativeButton: true,
1235
- render: /* @__PURE__ */ jsx19("button", { type: "button" }),
1309
+ render: /* @__PURE__ */ jsx20("button", { type: "button" }),
1236
1310
  className: rowClassName,
1237
1311
  ...props,
1238
1312
  children: body
@@ -1241,13 +1315,13 @@ function MenuItem({ label, children, size = "default", description, leading, tra
1241
1315
  }
1242
1316
  function EnterHint({ target }) {
1243
1317
  return /* @__PURE__ */ jsxs12("span", { className: "flex shrink-0 items-center gap-1.5 text-text-muted", children: [
1244
- /* @__PURE__ */ jsx19(Kbd, { children: "\u21A9 Enter" }),
1245
- target && /* @__PURE__ */ jsx19("span", { className: "text-menu signal:font-mono signal:text-small signal:tracking-wider leaf:font-mono leaf:text-small leaf:tracking-wider", children: target })
1318
+ /* @__PURE__ */ jsx20(Kbd, { children: "\u21A9 Enter" }),
1319
+ target && /* @__PURE__ */ jsx20("span", { className: "text-menu signal:font-mono signal:text-small signal:tracking-wider leaf:font-mono leaf:text-small leaf:tracking-wider", children: target })
1246
1320
  ] });
1247
1321
  }
1248
1322
  function MenuSection({ label, children, className }) {
1249
- const inMenu = useContext4(MenuContext) !== null;
1250
- const heading = /* @__PURE__ */ jsx19("div", { className: cn("flex h-8 items-center px-2", className), children: /* @__PURE__ */ jsx19(SectionLabel, { tone: "secondary", children: label }) });
1323
+ const inMenu = useContext5(MenuContext) !== null;
1324
+ const heading = /* @__PURE__ */ jsx20("div", { className: cn("flex h-8 items-center px-2", className), children: /* @__PURE__ */ jsx20(SectionLabel, { tone: "secondary", children: label }) });
1251
1325
  if (!inMenu) {
1252
1326
  return /* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-0.5", children: [
1253
1327
  heading,
@@ -1255,19 +1329,19 @@ function MenuSection({ label, children, className }) {
1255
1329
  ] });
1256
1330
  }
1257
1331
  return /* @__PURE__ */ jsxs12(BaseMenu.Group, { className: "flex flex-col gap-0.5", children: [
1258
- /* @__PURE__ */ jsx19(BaseMenu.GroupLabel, { render: heading }),
1332
+ /* @__PURE__ */ jsx20(BaseMenu.GroupLabel, { render: heading }),
1259
1333
  children
1260
1334
  ] });
1261
1335
  }
1262
1336
  function MenuSeparator() {
1263
- return /* @__PURE__ */ jsx19(Divider, { className: "my-1" });
1337
+ return /* @__PURE__ */ jsx20(Divider, { className: "my-1" });
1264
1338
  }
1265
1339
  function MenuRow({ children, className }) {
1266
- return /* @__PURE__ */ jsx19("div", { className: cn("flex items-center gap-2 px-2 py-1.5", className), children });
1340
+ return /* @__PURE__ */ jsx20("div", { className: cn("flex items-center gap-2 px-2 py-1.5", className), children });
1267
1341
  }
1268
1342
 
1269
1343
  // src/ChipInput.tsx
1270
- import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
1344
+ import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
1271
1345
  var CHIP_BOX = (
1272
1346
  // Curved, not a pill (Katerina, 2026-09-01): the Avatar keeps its own
1273
1347
  // rounded-sm corners — never a forced circle — and the chip's corner
@@ -1279,10 +1353,10 @@ var CHIP_REMOVE = "size-4 flex items-center justify-center rounded-full hover:bg
1279
1353
  var chipPadding = (leading, removable) => cn(leading ? "pl-[2px]" : "pl-2", removable ? "pr-1" : "pr-2");
1280
1354
  function InputChip({ label, leading, onRemove, removeLabel, truncate, className }) {
1281
1355
  return /* @__PURE__ */ jsxs13("div", { className: cn(CHIP_BOX, chipPadding(!!leading, !!onRemove), className), children: [
1282
- leading && /* @__PURE__ */ jsx20("span", { className: "flex shrink-0 items-center", children: leading }),
1283
- /* @__PURE__ */ jsx20("span", { className: cn(CHIP_LABEL, truncate && "min-w-0 truncate"), children: label }),
1284
- onRemove && /* @__PURE__ */ jsx20(
1285
- BaseButton4,
1356
+ leading && /* @__PURE__ */ jsx21("span", { className: "flex shrink-0 items-center", children: leading }),
1357
+ /* @__PURE__ */ jsx21("span", { className: cn(CHIP_LABEL, truncate && "min-w-0 truncate"), children: label }),
1358
+ onRemove && /* @__PURE__ */ jsx21(
1359
+ BaseButton5,
1286
1360
  {
1287
1361
  type: "button",
1288
1362
  onClick: (e) => {
@@ -1291,7 +1365,7 @@ function InputChip({ label, leading, onRemove, removeLabel, truncate, className
1291
1365
  },
1292
1366
  className: cn(CHIP_REMOVE, truncate && "shrink-0"),
1293
1367
  "aria-label": removeLabel ?? `Remove ${label}`,
1294
- children: /* @__PURE__ */ jsx20(IconX3, { size: 10, stroke: 1.5 })
1368
+ children: /* @__PURE__ */ jsx21(IconX3, { size: 10, stroke: 1.5 })
1295
1369
  }
1296
1370
  )
1297
1371
  ] });
@@ -1309,12 +1383,12 @@ function ChipInput({
1309
1383
  }) {
1310
1384
  const [query, setQuery] = useState2("");
1311
1385
  const [box, setBox] = useState2(null);
1312
- const available = useMemo(() => {
1386
+ const available = useMemo2(() => {
1313
1387
  const chosen = new Set(value.map((o) => o.id));
1314
1388
  const excluded = new Set(excludeIds);
1315
1389
  return options.filter((o) => !chosen.has(o.id) && !excluded.has(o.id));
1316
1390
  }, [options, value, excludeIds]);
1317
- const filter = useMemo(
1391
+ const filter = useMemo2(
1318
1392
  () => (item, q) => {
1319
1393
  const needle = q.trim().toLowerCase();
1320
1394
  if (!needle) return true;
@@ -1363,11 +1437,11 @@ function ChipInput({
1363
1437
  children: [
1364
1438
  /* @__PURE__ */ jsxs13(Combobox.Chips, { ref: setBox, className: cn(FIELD_SHELL_CLASSES, "focus-within:border-border-focus focus-within:hover:border-border-focus group-hover/field:focus-within:border-border-focus px-3 py-1.5 flex flex-wrap items-center gap-1.5 min-h-[38px] cursor-text signal:transition-shadow signal:focus-within:shadow-focus-ring"), children: [
1365
1439
  value.map((option) => /* @__PURE__ */ jsxs13(Combobox.Chip, { className: cn(CHIP_BOX, chipPadding(!!chipLeading, true)), children: [
1366
- chipLeading && /* @__PURE__ */ jsx20("span", { className: "flex shrink-0 items-center", children: chipLeading(option) }),
1367
- /* @__PURE__ */ jsx20("span", { className: CHIP_LABEL, children: option.label }),
1368
- /* @__PURE__ */ jsx20(Combobox.ChipRemove, { className: CHIP_REMOVE, "aria-label": `Remove ${option.label}`, children: /* @__PURE__ */ jsx20(IconX3, { size: 10, stroke: 1.5 }) })
1440
+ chipLeading && /* @__PURE__ */ jsx21("span", { className: "flex shrink-0 items-center", children: chipLeading(option) }),
1441
+ /* @__PURE__ */ jsx21("span", { className: CHIP_LABEL, children: option.label }),
1442
+ /* @__PURE__ */ jsx21(Combobox.ChipRemove, { className: CHIP_REMOVE, "aria-label": `Remove ${option.label}`, children: /* @__PURE__ */ jsx21(IconX3, { size: 10, stroke: 1.5 }) })
1369
1443
  ] }, option.id)),
1370
- /* @__PURE__ */ jsx20(
1444
+ /* @__PURE__ */ jsx21(
1371
1445
  Combobox.Input,
1372
1446
  {
1373
1447
  autoFocus,
@@ -1379,18 +1453,18 @@ function ChipInput({
1379
1453
  }
1380
1454
  )
1381
1455
  ] }),
1382
- /* @__PURE__ */ jsx20(Combobox.Portal, { children: /* @__PURE__ */ jsx20(
1456
+ /* @__PURE__ */ jsx21(Combobox.Portal, { children: /* @__PURE__ */ jsx21(
1383
1457
  Combobox.Positioner,
1384
1458
  {
1385
1459
  anchor: box,
1386
1460
  sideOffset: GAP3,
1387
1461
  collisionPadding: VIEWPORT_PAD3,
1388
1462
  className: "z-50 data-[anchor-hidden]:hidden",
1389
- children: /* @__PURE__ */ jsx20(Combobox.Popup, { className: "w-[var(--anchor-width)] p-0", render: /* @__PURE__ */ jsx20(MenuPanel, {}), children: /* @__PURE__ */ jsx20(ScrollArea, { viewportClassName: "max-h-[240px]", contentClassName: "flex flex-col p-2", children: /* @__PURE__ */ jsx20(Combobox.List, { className: "flex flex-col gap-0.5", children: (option) => /* @__PURE__ */ jsx20(
1463
+ children: /* @__PURE__ */ jsx21(Combobox.Popup, { className: "w-[var(--anchor-width)] p-0", render: /* @__PURE__ */ jsx21(MenuPanel, {}), children: /* @__PURE__ */ jsx21(ScrollArea, { viewportClassName: "max-h-[240px]", contentClassName: "flex flex-col p-2", children: /* @__PURE__ */ jsx21(Combobox.List, { className: "flex flex-col gap-0.5", children: (option) => /* @__PURE__ */ jsx21(
1390
1464
  Combobox.Item,
1391
1465
  {
1392
1466
  value: option,
1393
- render: /* @__PURE__ */ jsx20(
1467
+ render: /* @__PURE__ */ jsx21(
1394
1468
  MenuItem,
1395
1469
  {
1396
1470
  size: "tall",
@@ -1412,20 +1486,20 @@ var GAP3 = 4;
1412
1486
  var VIEWPORT_PAD3 = 8;
1413
1487
 
1414
1488
  // src/DialogShell.tsx
1415
- import { useRef as useRef3 } from "react";
1489
+ import { useRef as useRef4 } from "react";
1416
1490
  import { Dialog as Dialog2 } from "@base-ui/react/dialog";
1417
1491
  import { AlertDialog } from "@base-ui/react/alert-dialog";
1418
1492
  import { IconX as IconX4 } from "@tabler/icons-react";
1419
1493
 
1420
1494
  // src/ContainerHeader.tsx
1421
1495
  import { IconChevronDown } from "@tabler/icons-react";
1422
- import { Button as BaseButton5 } from "@base-ui/react/button";
1423
- import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
1496
+ import { Button as BaseButton6 } from "@base-ui/react/button";
1497
+ import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
1424
1498
  function ContainerHeader({ title, chevron = false, titleMenu, actions, className }) {
1425
1499
  const text = typeof title === "string";
1426
1500
  const name = /* @__PURE__ */ jsxs14("div", { className: cn("flex items-center gap-1", text ? "shrink-0" : "min-w-0 flex-1"), children: [
1427
- text ? /* @__PURE__ */ jsx21("span", { className: "whitespace-nowrap text-body-2-strong text-text-primary", children: title }) : /* @__PURE__ */ jsx21("div", { className: "min-w-0 flex-1", children: title }),
1428
- (chevron || titleMenu != null) && /* @__PURE__ */ jsx21(IconChevronDown, { size: 12, stroke: 1.5, className: "shrink-0 text-text-secondary" })
1501
+ text ? /* @__PURE__ */ jsx22("span", { className: "whitespace-nowrap text-body-2-strong text-text-primary", children: title }) : /* @__PURE__ */ jsx22("div", { className: "min-w-0 flex-1", children: title }),
1502
+ (chevron || titleMenu != null) && /* @__PURE__ */ jsx22(IconChevronDown, { size: 12, stroke: 1.5, className: "shrink-0 text-text-secondary" })
1429
1503
  ] });
1430
1504
  return (
1431
1505
  // The title 16px in, where the column's content starts (Katerina, 7 October; it was 20px).
@@ -1434,24 +1508,24 @@ function ContainerHeader({ title, chevron = false, titleMenu, actions, className
1434
1508
  // are, and the fill is inside the bar — a negative margin had it clipped
1435
1509
  // (Katerina, 5 October).
1436
1510
  /* @__PURE__ */ jsxs14("div", { className: cn("flex h-12 shrink-0 items-center justify-between overflow-hidden border-b border-border-subtle py-2 pr-4", titleMenu != null ? "pl-2.5" : "pl-4", className), children: [
1437
- /* @__PURE__ */ jsx21("div", { className: cn("flex items-center gap-2 overflow-hidden", text ? "shrink-0" : "min-w-0 flex-1"), children: titleMenu != null ? /* @__PURE__ */ jsx21(
1511
+ /* @__PURE__ */ jsx22("div", { className: cn("flex items-center gap-2 overflow-hidden", text ? "shrink-0" : "min-w-0 flex-1"), children: titleMenu != null ? /* @__PURE__ */ jsx22(
1438
1512
  Menu,
1439
1513
  {
1440
- trigger: /* @__PURE__ */ jsx21(BaseButton5, { type: "button", className: cn("flex min-w-0 items-center px-1.5 py-1", MENU_TRIGGER_CLASSES), children: name }),
1514
+ trigger: /* @__PURE__ */ jsx22(BaseButton6, { type: "button", className: cn("flex min-w-0 items-center px-1.5 py-1", MENU_TRIGGER_CLASSES), children: name }),
1441
1515
  children: titleMenu
1442
1516
  }
1443
1517
  ) : name }),
1444
- actions && /* @__PURE__ */ jsx21("div", { className: "flex shrink-0 items-center justify-end gap-3", children: /* @__PURE__ */ jsx21("div", { className: "flex shrink-0 items-center gap-1", children: actions }) })
1518
+ actions && /* @__PURE__ */ jsx22("div", { className: "flex shrink-0 items-center justify-end gap-3", children: /* @__PURE__ */ jsx22("div", { className: "flex shrink-0 items-center gap-1", children: actions }) })
1445
1519
  ] })
1446
1520
  );
1447
1521
  }
1448
1522
 
1449
1523
  // src/DialogShell.tsx
1450
- import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
1524
+ import { jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
1451
1525
  function DialogShell({ title, onClose, headerContent, footer, children, bodyClassName, bodyMaxHeight, width = 502, alert = false }) {
1452
1526
  const Parts = alert ? AlertDialog : Dialog2;
1453
- const popupRef = useRef3(null);
1454
- return /* @__PURE__ */ jsx22(
1527
+ const popupRef = useRef4(null);
1528
+ return /* @__PURE__ */ jsx23(
1455
1529
  Parts.Root,
1456
1530
  {
1457
1531
  open: true,
@@ -1459,8 +1533,8 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
1459
1533
  if (!open) onClose();
1460
1534
  },
1461
1535
  children: /* @__PURE__ */ jsxs15(Parts.Portal, { children: [
1462
- /* @__PURE__ */ jsx22(Parts.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
1463
- /* @__PURE__ */ jsx22("div", { className: "fixed inset-0 z-50 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs15(
1536
+ /* @__PURE__ */ jsx23(Parts.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
1537
+ /* @__PURE__ */ jsx23("div", { className: "fixed inset-0 z-50 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs15(
1464
1538
  Parts.Popup,
1465
1539
  {
1466
1540
  ref: popupRef,
@@ -1469,11 +1543,11 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
1469
1543
  className: "bg-bg-elevated border border-border-subtle rounded-lg shadow-lg pointer-events-auto flex flex-col overflow-hidden outline-none",
1470
1544
  style: { width },
1471
1545
  children: [
1472
- /* @__PURE__ */ jsx22(
1546
+ /* @__PURE__ */ jsx23(
1473
1547
  ContainerHeader,
1474
1548
  {
1475
1549
  className: "pl-5",
1476
- title: headerContent ?? /* @__PURE__ */ jsx22(Parts.Title, { className: "block truncate text-h4 text-text-primary", render: /* @__PURE__ */ jsx22("span", {}), children: title }),
1550
+ title: headerContent ?? /* @__PURE__ */ jsx23(Parts.Title, { className: "block truncate text-h4 text-text-primary", render: /* @__PURE__ */ jsx23("span", {}), children: title }),
1477
1551
  actions: (
1478
1552
  /*
1479
1553
  The ✕ IS the `Close` part now, rather than a button that calls
@@ -1487,10 +1561,10 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
1487
1561
  so the ✕, Escape and the outside press are one path with one
1488
1562
  reason attached, instead of one of the three going around.
1489
1563
  */
1490
- /* @__PURE__ */ jsx22(
1564
+ /* @__PURE__ */ jsx23(
1491
1565
  Parts.Close,
1492
1566
  {
1493
- render: /* @__PURE__ */ jsx22(IconButton, { tooltip: "Close", "aria-label": "Close", children: /* @__PURE__ */ jsx22(IconX4, { size: 16, stroke: 1.5 }) })
1567
+ render: /* @__PURE__ */ jsx23(IconButton, { tooltip: "Close", "aria-label": "Close", children: /* @__PURE__ */ jsx23(IconX4, { size: 16, stroke: 1.5 }) })
1494
1568
  }
1495
1569
  )
1496
1570
  )
@@ -1498,9 +1572,9 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
1498
1572
  ),
1499
1573
  bodyMaxHeight ? (
1500
1574
  // The line above the footer on a box of the shell's own, not pushed into ScrollArea (UIG-9).
1501
- /* @__PURE__ */ jsx22("div", { className: cn(footer != null && "border-b border-border-subtle"), children: /* @__PURE__ */ jsx22(ScrollArea, { viewportClassName: bodyMaxHeight, contentClassName: cn("pl-5 pr-4 py-4", bodyClassName), children }) })
1502
- ) : /* @__PURE__ */ jsx22("div", { className: cn("pl-5 pr-4 py-4", footer != null && "border-b border-border-subtle", bodyClassName), children }),
1503
- footer != null && /* @__PURE__ */ jsx22("div", { className: "h-12 flex items-center justify-end gap-2 pl-5 pr-4 shrink-0", children: footer })
1575
+ /* @__PURE__ */ jsx23("div", { className: cn(footer != null && "border-b border-border-subtle"), children: /* @__PURE__ */ jsx23(ScrollArea, { viewportClassName: bodyMaxHeight, contentClassName: cn("pl-5 pr-4 py-4", bodyClassName), children }) })
1576
+ ) : /* @__PURE__ */ jsx23("div", { className: cn("pl-5 pr-4 py-4", footer != null && "border-b border-border-subtle", bodyClassName), children }),
1577
+ footer != null && /* @__PURE__ */ jsx23("div", { className: "h-12 flex items-center justify-end gap-2 pl-5 pr-4 shrink-0", children: footer })
1504
1578
  ]
1505
1579
  }
1506
1580
  ) })
@@ -1512,7 +1586,7 @@ function DialogShell({ title, onClose, headerContent, footer, children, bodyClas
1512
1586
  // src/Field.tsx
1513
1587
  import { cloneElement, isValidElement } from "react";
1514
1588
  import { Field as BaseField } from "@base-ui/react/field";
1515
- import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
1589
+ import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
1516
1590
  var LINE_STYLES = {
1517
1591
  helper: "text-caption text-text-muted",
1518
1592
  warning: "text-caption text-warning-default",
@@ -1529,24 +1603,24 @@ function Field({ label, required = false, helper, error, children }) {
1529
1603
  /* @__PURE__ */ jsxs16(BaseField.Root, { invalid: !!error, className: "group/field flex flex-col gap-2", children: [
1530
1604
  /* @__PURE__ */ jsxs16(BaseField.Label, { className: cn("text-input-label text-text-primary", required && "flex items-center"), children: [
1531
1605
  label,
1532
- required && /* @__PURE__ */ jsx23("span", { "aria-hidden": "true", className: "text-error-default ml-0.5", children: "*" })
1606
+ required && /* @__PURE__ */ jsx24("span", { "aria-hidden": "true", className: "text-error-default ml-0.5", children: "*" })
1533
1607
  ] }),
1534
1608
  /* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-1.5", children: [
1535
1609
  control,
1536
- error != null ? /* @__PURE__ */ jsx23(BaseField.Error, { match: true, className: LINE_STYLES.error, children: error }) : helper != null ? /* @__PURE__ */ jsx23(BaseField.Description, { className: LINE_STYLES.helper, children: helper }) : null
1610
+ 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
1537
1611
  ] })
1538
1612
  ] })
1539
1613
  );
1540
1614
  }
1541
1615
  function FieldLine({ tone = "helper", children, className }) {
1542
- return /* @__PURE__ */ jsx23("p", { role: tone === "error" ? "alert" : "status", className: cn(LINE_STYLES[tone], className), children });
1616
+ return /* @__PURE__ */ jsx24("p", { role: tone === "error" ? "alert" : "status", className: cn(LINE_STYLES[tone], className), children });
1543
1617
  }
1544
1618
 
1545
1619
  // src/Form.tsx
1546
- import { useLayoutEffect as useLayoutEffect2, useRef as useRef4 } from "react";
1620
+ import { useLayoutEffect as useLayoutEffect2, useRef as useRef5 } from "react";
1547
1621
  import { Fieldset } from "@base-ui/react/fieldset";
1548
1622
  import { Form as BaseForm } from "@base-ui/react/form";
1549
- import { jsx as jsx24 } from "react/jsx-runtime";
1623
+ import { jsx as jsx25 } from "react/jsx-runtime";
1550
1624
  var FIELDS_CLASSES = "flex flex-col gap-6";
1551
1625
  var CONTROL = 'input:not([type="hidden"]), textarea, select, button, [role="checkbox"], [role="combobox"], [tabindex]:not([tabindex="-1"])';
1552
1626
  var ONE_LINE = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
@@ -1564,12 +1638,12 @@ function firstInvalid(form) {
1564
1638
  function Form({ onSubmit, busy: ownBusy = false, enterSends = true, layout = "fields", className, children, ...props }) {
1565
1639
  const outerBusy = useFormBusy();
1566
1640
  const busy = ownBusy || outerBusy;
1567
- const form = useRef4(null);
1568
- const busyNow = useRef4(busy);
1641
+ const form = useRef5(null);
1642
+ const busyNow = useRef5(busy);
1569
1643
  busyNow.current = busy;
1570
- const sender = useRef4(null);
1571
- const holding = useRef4(false);
1572
- const lastInside = useRef4(null);
1644
+ const sender = useRef5(null);
1645
+ const holding = useRef5(false);
1646
+ const lastInside = useRef5(null);
1573
1647
  useLayoutEffect2(() => {
1574
1648
  const element = form.current;
1575
1649
  if (!element) return;
@@ -1606,7 +1680,7 @@ function Form({ onSubmit, busy: ownBusy = false, enterSends = true, layout = "fi
1606
1680
  const oneLine = ONE_LINE.has((target.getAttribute("type") ?? "").toLowerCase()) && target.getAttribute("role") !== "combobox";
1607
1681
  if (enterSends && oneLine) form.current?.requestSubmit();
1608
1682
  };
1609
- return /* @__PURE__ */ jsx24(
1683
+ return /* @__PURE__ */ jsx25(
1610
1684
  BaseForm,
1611
1685
  {
1612
1686
  ref: form,
@@ -1629,13 +1703,13 @@ function Form({ onSubmit, busy: ownBusy = false, enterSends = true, layout = "fi
1629
1703
  if (busyNow.current) return;
1630
1704
  void onSubmit();
1631
1705
  },
1632
- children: /* @__PURE__ */ jsx24(Fieldset.Root, { disabled: busy, className: "contents", children: /* @__PURE__ */ jsx24(FormBusyContext.Provider, { value: busy, children }) })
1706
+ children: /* @__PURE__ */ jsx25(Fieldset.Root, { disabled: busy, className: "contents", children: /* @__PURE__ */ jsx25(FormBusyContext.Provider, { value: busy, children }) })
1633
1707
  }
1634
1708
  );
1635
1709
  }
1636
1710
 
1637
1711
  // src/MembersDialog.tsx
1638
- import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
1712
+ import { Fragment as Fragment5, jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
1639
1713
  var LEADING_CLASSES = "size-8 rounded-md bg-accent-muted flex items-center justify-center shrink-0 text-accent-primary";
1640
1714
  function MembersDialog({ members, count, self, candidates = [], onAdd, note, initialView = "list", onClose }) {
1641
1715
  const [view, setView] = useState3(onAdd ? initialView : "list");
@@ -1658,21 +1732,21 @@ function MembersDialog({ members, count, self, candidates = [], onAdd, note, ini
1658
1732
  setView("list");
1659
1733
  };
1660
1734
  if (view === "add" && onAdd) {
1661
- return /* @__PURE__ */ jsx25(
1735
+ return /* @__PURE__ */ jsx26(
1662
1736
  DialogShell,
1663
1737
  {
1664
1738
  title: "Add members",
1665
1739
  onClose,
1666
1740
  headerContent: /* @__PURE__ */ jsxs17("div", { className: "flex min-w-0 items-center gap-2", children: [
1667
- /* @__PURE__ */ jsx25(IconButton, { tooltip: "Back to members", "aria-label": "Back to members", className: "-ml-2", onClick: () => setView("list"), children: /* @__PURE__ */ jsx25(IconArrowLeft, { size: 16, stroke: 1.5 }) }),
1668
- /* @__PURE__ */ jsx25("span", { className: "truncate text-h4 text-text-primary", children: "Add members" })
1741
+ /* @__PURE__ */ jsx26(IconButton, { tooltip: "Back to members", "aria-label": "Back to members", className: "-ml-2", onClick: () => setView("list"), children: /* @__PURE__ */ jsx26(IconArrowLeft, { size: 16, stroke: 1.5 }) }),
1742
+ /* @__PURE__ */ jsx26("span", { className: "truncate text-h4 text-text-primary", children: "Add members" })
1669
1743
  ] }),
1670
1744
  bodyClassName: "flex flex-col gap-6",
1671
1745
  footer: /* @__PURE__ */ jsxs17(Fragment5, { children: [
1672
- /* @__PURE__ */ jsx25(Button, { variant: "muted", onClick: onClose, children: "Cancel" }),
1673
- /* @__PURE__ */ jsx25(Button, { variant: "primary", type: "submit", form: formId, disabled: chosen.length === 0, children: "Invite" })
1746
+ /* @__PURE__ */ jsx26(Button, { variant: "muted", onClick: onClose, children: "Cancel" }),
1747
+ /* @__PURE__ */ jsx26(Button, { variant: "primary", type: "submit", form: formId, disabled: chosen.length === 0, children: "Invite" })
1674
1748
  ] }),
1675
- children: /* @__PURE__ */ jsx25(Form, { id: formId, onSubmit: add, children: /* @__PURE__ */ jsx25(Field, { label: "Invite people", required: true, children: /* @__PURE__ */ jsx25(
1749
+ children: /* @__PURE__ */ jsx26(Form, { id: formId, onSubmit: add, children: /* @__PURE__ */ jsx26(Field, { label: "Invite people", required: true, children: /* @__PURE__ */ jsx26(
1676
1750
  ChipInput,
1677
1751
  {
1678
1752
  value: chosen,
@@ -1680,8 +1754,8 @@ function MembersDialog({ members, count, self, candidates = [], onAdd, note, ini
1680
1754
  options: candidates,
1681
1755
  placeholder: "Search people...",
1682
1756
  excludeIds: members.map((m) => m.id),
1683
- chipLeading: (o) => /* @__PURE__ */ jsx25(Avatar, { name: o.label, src: o.picture, size: 16 }),
1684
- rowLeading: (o) => /* @__PURE__ */ jsx25(Avatar, { name: o.label, src: o.picture, size: 32 }),
1757
+ chipLeading: (o) => /* @__PURE__ */ jsx26(Avatar, { name: o.label, src: o.picture, size: 16 }),
1758
+ rowLeading: (o) => /* @__PURE__ */ jsx26(Avatar, { name: o.label, src: o.picture, size: 32 }),
1685
1759
  autoFocus: true
1686
1760
  }
1687
1761
  ) }) })
@@ -1694,43 +1768,43 @@ function MembersDialog({ members, count, self, candidates = [], onAdd, note, ini
1694
1768
  title: "Members",
1695
1769
  onClose,
1696
1770
  headerContent: /* @__PURE__ */ jsxs17("div", { className: "flex min-w-0 items-center gap-2", children: [
1697
- /* @__PURE__ */ jsx25("span", { className: "truncate text-h4 text-text-primary", children: "Members" }),
1698
- /* @__PURE__ */ jsx25(Chip, { label: String(count ?? members.length) })
1771
+ /* @__PURE__ */ jsx26("span", { className: "truncate text-h4 text-text-primary", children: "Members" }),
1772
+ /* @__PURE__ */ jsx26(Chip, { label: String(count ?? members.length) })
1699
1773
  ] }),
1700
1774
  bodyMaxHeight: "max-h-[400px]",
1701
1775
  bodyClassName: "p-0 py-2",
1702
1776
  children: [
1703
1777
  (self || onAdd) && /* @__PURE__ */ jsxs17("div", { className: "flex flex-col px-2", children: [
1704
- self && /* @__PURE__ */ jsx25(
1778
+ self && /* @__PURE__ */ jsx26(
1705
1779
  MenuItem,
1706
1780
  {
1707
1781
  size: "tall",
1708
1782
  className: "py-2",
1709
1783
  disabled: toggling,
1710
1784
  onClick: () => void toggle(),
1711
- leading: /* @__PURE__ */ jsx25("span", { className: LEADING_CLASSES, children: self.action === "join" ? /* @__PURE__ */ jsx25(IconUserPlus, { size: 16, stroke: 1.5 }) : /* @__PURE__ */ jsx25(IconUserMinus, { size: 16, stroke: 1.5 }) }),
1785
+ leading: /* @__PURE__ */ jsx26("span", { className: LEADING_CLASSES, children: self.action === "join" ? /* @__PURE__ */ jsx26(IconUserPlus, { size: 16, stroke: 1.5 }) : /* @__PURE__ */ jsx26(IconUserMinus, { size: 16, stroke: 1.5 }) }),
1712
1786
  label: self.action === "join" ? "Join" : "Leave"
1713
1787
  }
1714
1788
  ),
1715
- onAdd && /* @__PURE__ */ jsx25(
1789
+ onAdd && /* @__PURE__ */ jsx26(
1716
1790
  MenuItem,
1717
1791
  {
1718
1792
  size: "tall",
1719
1793
  className: "py-2",
1720
1794
  onClick: () => setView("add"),
1721
- leading: /* @__PURE__ */ jsx25("span", { className: LEADING_CLASSES, children: /* @__PURE__ */ jsx25(IconUserPlus, { size: 16, stroke: 1.5 }) }),
1795
+ leading: /* @__PURE__ */ jsx26("span", { className: LEADING_CLASSES, children: /* @__PURE__ */ jsx26(IconUserPlus, { size: 16, stroke: 1.5 }) }),
1722
1796
  label: "Add members"
1723
1797
  }
1724
1798
  )
1725
1799
  ] }),
1726
1800
  members.map((member) => /* @__PURE__ */ jsxs17("div", { className: "flex h-12 items-center gap-3 px-5", children: [
1727
- /* @__PURE__ */ jsx25(Avatar, { size: 32, name: member.name, src: member.picture }),
1801
+ /* @__PURE__ */ jsx26(Avatar, { size: 32, name: member.name, src: member.picture }),
1728
1802
  /* @__PURE__ */ jsxs17("div", { className: "flex min-w-0 flex-1 flex-col justify-center gap-[2px]", children: [
1729
- /* @__PURE__ */ jsx25("div", { className: "truncate text-body-2 text-text-primary", children: member.name }),
1730
- member.caption && /* @__PURE__ */ jsx25("div", { className: "truncate text-caption text-text-secondary", children: member.caption })
1803
+ /* @__PURE__ */ jsx26("div", { className: "truncate text-body-2 text-text-primary", children: member.name }),
1804
+ member.caption && /* @__PURE__ */ jsx26("div", { className: "truncate text-caption text-text-secondary", children: member.caption })
1731
1805
  ] })
1732
1806
  ] }, member.id)),
1733
- note && /* @__PURE__ */ jsx25("div", { className: "px-5 pb-2 pt-3 text-caption text-text-secondary", children: note })
1807
+ note && /* @__PURE__ */ jsx26("div", { className: "px-5 pb-2 pt-3 text-caption text-text-secondary", children: note })
1734
1808
  ]
1735
1809
  }
1736
1810
  );
@@ -1738,7 +1812,7 @@ function MembersDialog({ members, count, self, candidates = [], onAdd, note, ini
1738
1812
 
1739
1813
  // src/Banner.tsx
1740
1814
  import { IconX as IconX5 } from "@tabler/icons-react";
1741
- import { jsx as jsx26, jsxs as jsxs18 } from "react/jsx-runtime";
1815
+ import { jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
1742
1816
  var TONE_STYLES = {
1743
1817
  ok: "bg-success-muted text-success-default",
1744
1818
  error: "bg-error-muted text-error-default",
@@ -1748,21 +1822,21 @@ var TONE_STYLES = {
1748
1822
  function Banner({ tone, children, icon, action, onDismiss, dismissLabel = "Dismiss", className }) {
1749
1823
  const role = tone === "error" ? "alert" : "status";
1750
1824
  if (!onDismiss && !icon && !action) {
1751
- return /* @__PURE__ */ jsx26("div", { role, className: cn("px-4 py-2 text-body-2", TONE_STYLES[tone], className), children });
1825
+ return /* @__PURE__ */ jsx27("div", { role, className: cn("px-4 py-2 text-body-2", TONE_STYLES[tone], className), children });
1752
1826
  }
1753
1827
  const oneLine = Boolean(icon || action);
1754
1828
  return /* @__PURE__ */ jsxs18("div", { role, className: cn("flex items-center gap-3 px-4 py-2 text-body-2", TONE_STYLES[tone], className), children: [
1755
- icon && /* @__PURE__ */ jsx26("span", { className: "flex shrink-0", children: icon }),
1756
- /* @__PURE__ */ jsx26("span", { className: cn("min-w-0 flex-1", oneLine && "truncate"), children }),
1757
- action && /* @__PURE__ */ jsx26(Button, { variant: "muted", size: "small", className: "shrink-0", onClick: action.onClick, children: action.label }),
1758
- onDismiss && /* @__PURE__ */ jsx26(IconButton, { variant: "current", "aria-label": dismissLabel, onClick: onDismiss, className: "-mr-1 shrink-0", children: /* @__PURE__ */ jsx26(IconX5, { size: 16, stroke: 1.5 }) })
1829
+ icon && /* @__PURE__ */ jsx27("span", { className: "flex shrink-0", children: icon }),
1830
+ /* @__PURE__ */ jsx27("span", { className: cn("min-w-0 flex-1", oneLine && "truncate"), children }),
1831
+ action && /* @__PURE__ */ jsx27(Button, { variant: "muted", size: "small", className: "shrink-0", onClick: action.onClick, children: action.label }),
1832
+ onDismiss && /* @__PURE__ */ jsx27(IconButton, { variant: "current", "aria-label": dismissLabel, onClick: onDismiss, className: "-mr-1 shrink-0", children: /* @__PURE__ */ jsx27(IconX5, { size: 16, stroke: 1.5 }) })
1759
1833
  ] });
1760
1834
  }
1761
1835
 
1762
1836
  // src/BlockHandle.tsx
1763
- import { useCallback, useEffect as useEffect2, useRef as useRef5, useState as useState4 } from "react";
1837
+ import { useCallback, useEffect as useEffect3, useRef as useRef6, useState as useState4 } from "react";
1764
1838
  import { IconGripVertical } from "@tabler/icons-react";
1765
- import { jsx as jsx27, jsxs as jsxs19 } from "react/jsx-runtime";
1839
+ import { jsx as jsx28, jsxs as jsxs19 } from "react/jsx-runtime";
1766
1840
  function readId(element) {
1767
1841
  const own = element.getAttribute("data-block-id") ?? element.querySelector("[data-block-id]")?.getAttribute("data-block-id");
1768
1842
  return own || void 0;
@@ -1788,8 +1862,8 @@ function firstLineOffset(element) {
1788
1862
  return inset + (line - HANDLE) / 2;
1789
1863
  }
1790
1864
  function BlockHandle({ actions, editing, children, className }) {
1791
- const frame = useRef5(null);
1792
- const content = useRef5(null);
1865
+ const frame = useRef6(null);
1866
+ const content = useRef6(null);
1793
1867
  const [block, setBlock] = useState4(null);
1794
1868
  const [top, setTop] = useState4(0);
1795
1869
  const [open, setOpen] = useState4(false);
@@ -1802,7 +1876,7 @@ function BlockHandle({ actions, editing, children, className }) {
1802
1876
  },
1803
1877
  [editing]
1804
1878
  );
1805
- useEffect2(() => {
1879
+ useEffect3(() => {
1806
1880
  if (!editing) return;
1807
1881
  return editing.onChange(() => {
1808
1882
  if (!open) setBlock(null);
@@ -1810,7 +1884,7 @@ function BlockHandle({ actions, editing, children, className }) {
1810
1884
  }, [editing, open]);
1811
1885
  const rows = editing && block ? editing.rows(block) : null;
1812
1886
  const own = actions && block ? actions(block) : null;
1813
- const dragging = useRef5(false);
1887
+ const dragging = useRef6(false);
1814
1888
  const [line, setLine] = useState4(null);
1815
1889
  const inGutter = (e) => dragging.current && !!editing && !!content.current && !content.current.contains(e.target);
1816
1890
  const landing = (y) => {
@@ -1855,16 +1929,16 @@ function BlockHandle({ actions, editing, children, className }) {
1855
1929
  if (!frame.current?.contains(e.relatedTarget)) setLine(null);
1856
1930
  },
1857
1931
  children: [
1858
- /* @__PURE__ */ jsx27("div", { ref: content, children }),
1859
- /* @__PURE__ */ jsx27("div", { "aria-hidden": true, className: "absolute inset-y-0 -left-7 w-7" }),
1860
- line !== null && /* @__PURE__ */ jsx27("div", { "aria-hidden": true, className: "pointer-events-none absolute inset-x-0 h-px bg-accent-primary", style: { top: line } }),
1932
+ /* @__PURE__ */ jsx28("div", { ref: content, children }),
1933
+ /* @__PURE__ */ jsx28("div", { "aria-hidden": true, className: "absolute inset-y-0 -left-7 w-7" }),
1934
+ line !== null && /* @__PURE__ */ jsx28("div", { "aria-hidden": true, className: "pointer-events-none absolute inset-x-0 h-px bg-accent-primary", style: { top: line } }),
1861
1935
  block && (rows || own) && // The top is the block's, measured: it depends on the document, not on a size of ours.
1862
- /* @__PURE__ */ jsx27("div", { className: cn("absolute -left-7", rows && "cursor-grab active:cursor-grabbing"), style: { top }, children: /* @__PURE__ */ jsxs19(
1936
+ /* @__PURE__ */ jsx28("div", { className: cn("absolute -left-7", rows && "cursor-grab active:cursor-grabbing"), style: { top }, children: /* @__PURE__ */ jsxs19(
1863
1937
  Menu,
1864
1938
  {
1865
1939
  open,
1866
1940
  onOpenChange: setOpen,
1867
- trigger: /* @__PURE__ */ jsx27(
1941
+ trigger: /* @__PURE__ */ jsx28(
1868
1942
  IconButton,
1869
1943
  {
1870
1944
  "aria-label": "Block menu",
@@ -1885,12 +1959,12 @@ function BlockHandle({ actions, editing, children, className }) {
1885
1959
  endDrag();
1886
1960
  setBlock(null);
1887
1961
  },
1888
- children: /* @__PURE__ */ jsx27(IconGripVertical, { size: 16, stroke: 1.5 })
1962
+ children: /* @__PURE__ */ jsx28(IconGripVertical, { size: 16, stroke: 1.5 })
1889
1963
  }
1890
1964
  ),
1891
1965
  children: [
1892
1966
  rows,
1893
- rows && own && /* @__PURE__ */ jsx27(MenuSeparator, {}),
1967
+ rows && own && /* @__PURE__ */ jsx28(MenuSeparator, {}),
1894
1968
  own
1895
1969
  ]
1896
1970
  }
@@ -1904,7 +1978,7 @@ function BlockHandle({ actions, editing, children, className }) {
1904
1978
  import { Checkbox as BaseCheckbox } from "@base-ui/react/checkbox";
1905
1979
  import { Field as BaseField2 } from "@base-ui/react/field";
1906
1980
  import { IconCheck } from "@tabler/icons-react";
1907
- import { jsx as jsx28, jsxs as jsxs20 } from "react/jsx-runtime";
1981
+ import { jsx as jsx29, jsxs as jsxs20 } from "react/jsx-runtime";
1908
1982
  function squareClasses(checked, disabled, interactive, className) {
1909
1983
  return cn(
1910
1984
  "inline-flex items-center justify-center size-4 shrink-0 rounded-sm border transition-colors",
@@ -1921,14 +1995,14 @@ function Checkbox({ checked, onChange, disabled: ownDisabled = false, label, row
1921
1995
  const formBusy = useFormBusy();
1922
1996
  const disabled = ownDisabled || formBusy;
1923
1997
  if (!onChange) {
1924
- const picture = /* @__PURE__ */ jsx28("span", { "aria-hidden": "true", className: squareClasses(checked, disabled, false, className), children: /* @__PURE__ */ jsx28("span", { className: tickClasses(checked), children: /* @__PURE__ */ jsx28(IconCheck, { size: 12, stroke: 3 }) }) });
1998
+ const picture = /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", className: squareClasses(checked, disabled, false, className), children: /* @__PURE__ */ jsx29("span", { className: tickClasses(checked), children: /* @__PURE__ */ jsx29(IconCheck, { size: 12, stroke: 3 }) }) });
1925
1999
  if (label === void 0) return picture;
1926
2000
  return /* @__PURE__ */ jsxs20("span", { className: "flex items-center gap-2", children: [
1927
2001
  picture,
1928
- /* @__PURE__ */ jsx28("span", { className: WORDS_CLASSES, children: label })
2002
+ /* @__PURE__ */ jsx29("span", { className: WORDS_CLASSES, children: label })
1929
2003
  ] });
1930
2004
  }
1931
- const box = /* @__PURE__ */ jsx28(
2005
+ const box = /* @__PURE__ */ jsx29(
1932
2006
  BaseCheckbox.Root,
1933
2007
  {
1934
2008
  checked,
@@ -1938,31 +2012,31 @@ function Checkbox({ checked, onChange, disabled: ownDisabled = false, label, row
1938
2012
  onCheckedChange: (next) => onChange(next),
1939
2013
  onClick: (e) => e.stopPropagation(),
1940
2014
  className: (state) => squareClasses(state.checked, state.disabled, true, className),
1941
- children: /* @__PURE__ */ jsx28(BaseCheckbox.Indicator, { keepMounted: true, className: (state) => tickClasses(state.checked), children: /* @__PURE__ */ jsx28(IconCheck, { size: 12, stroke: 3 }) })
2015
+ children: /* @__PURE__ */ jsx29(BaseCheckbox.Indicator, { keepMounted: true, className: (state) => tickClasses(state.checked), children: /* @__PURE__ */ jsx29(IconCheck, { size: 12, stroke: 3 }) })
1942
2016
  }
1943
2017
  );
1944
2018
  if (label === void 0) return box;
1945
2019
  if (row) {
1946
- return /* @__PURE__ */ jsx28(BaseField2.Root, { disabled, children: /* @__PURE__ */ jsxs20(BaseField2.Label, { className: cn(ROW_CLASSES, checked && "bg-bg-selected", !disabled && "cursor-pointer hover:bg-bg-hover"), children: [
2020
+ return /* @__PURE__ */ jsx29(BaseField2.Root, { disabled, children: /* @__PURE__ */ jsxs20(BaseField2.Label, { className: cn(ROW_CLASSES, checked && "bg-bg-selected", !disabled && "cursor-pointer hover:bg-bg-hover"), children: [
1947
2021
  leading,
1948
- /* @__PURE__ */ jsx28("span", { className: cn("flex-1 min-w-0 truncate", WORDS_CLASSES), children: label }),
2022
+ /* @__PURE__ */ jsx29("span", { className: cn("flex-1 min-w-0 truncate", WORDS_CLASSES), children: label }),
1949
2023
  box
1950
2024
  ] }) });
1951
2025
  }
1952
- return /* @__PURE__ */ jsx28(BaseField2.Root, { disabled, children: /* @__PURE__ */ jsxs20(BaseField2.Label, { className: cn("flex items-center gap-2", !disabled && "cursor-pointer"), children: [
2026
+ return /* @__PURE__ */ jsx29(BaseField2.Root, { disabled, children: /* @__PURE__ */ jsxs20(BaseField2.Label, { className: cn("flex items-center gap-2", !disabled && "cursor-pointer"), children: [
1953
2027
  box,
1954
- /* @__PURE__ */ jsx28("span", { className: WORDS_CLASSES, children: label })
2028
+ /* @__PURE__ */ jsx29("span", { className: WORDS_CLASSES, children: label })
1955
2029
  ] }) });
1956
2030
  }
1957
2031
 
1958
2032
  // src/CommandPalette.tsx
1959
2033
  import {
1960
- createContext as createContext5,
1961
- useContext as useContext5,
1962
- useEffect as useEffect3,
2034
+ createContext as createContext6,
2035
+ useContext as useContext6,
2036
+ useEffect as useEffect4,
1963
2037
  useLayoutEffect as useLayoutEffect3,
1964
- useMemo as useMemo2,
1965
- useRef as useRef6,
2038
+ useMemo as useMemo3,
2039
+ useRef as useRef7,
1966
2040
  useState as useState5
1967
2041
  } from "react";
1968
2042
  import { Dialog as Dialog3 } from "@base-ui/react/dialog";
@@ -1971,39 +2045,39 @@ import { IconLoader2 as IconLoader22, IconSearch } from "@tabler/icons-react";
1971
2045
 
1972
2046
  // src/EmptyState.tsx
1973
2047
  import { IconMessage2 } from "@tabler/icons-react";
1974
- import { jsx as jsx29, jsxs as jsxs21 } from "react/jsx-runtime";
2048
+ import { jsx as jsx30, jsxs as jsxs21 } from "react/jsx-runtime";
1975
2049
  function EmptyState({ icon, message, scope = "page", action, className }) {
1976
2050
  if (scope === "section") {
1977
- return /* @__PURE__ */ jsx29("p", { className: cn("text-caption text-text-muted", className), children: message });
2051
+ return /* @__PURE__ */ jsx30("p", { className: cn("text-caption text-text-muted", className), children: message });
1978
2052
  }
1979
2053
  return /* @__PURE__ */ jsxs21("div", { className: cn("flex flex-1 flex-col items-center justify-center gap-2", className), children: [
1980
- /* @__PURE__ */ jsx29("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx29(IconMessage2, { size: 16, stroke: 1.5 }) }),
1981
- /* @__PURE__ */ jsx29("p", { className: "text-body-2 text-text-secondary text-center", children: message }),
1982
- action && /* @__PURE__ */ jsx29(Button, { variant: "outlined", className: "mt-2", onClick: action.onClick, children: action.label })
2054
+ /* @__PURE__ */ jsx30("span", { className: "text-text-secondary", children: icon ?? /* @__PURE__ */ jsx30(IconMessage2, { size: 16, stroke: 1.5 }) }),
2055
+ /* @__PURE__ */ jsx30("p", { className: "text-body-2 text-text-secondary text-center", children: message }),
2056
+ action && /* @__PURE__ */ jsx30(Button, { variant: "outlined", className: "mt-2", onClick: action.onClick, children: action.label })
1983
2057
  ] });
1984
2058
  }
1985
2059
 
1986
2060
  // src/Skeleton.tsx
1987
- import { jsx as jsx30, jsxs as jsxs22 } from "react/jsx-runtime";
2061
+ import { jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
1988
2062
  function SkeletonBar({ className, style }) {
1989
- return /* @__PURE__ */ jsx30("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
2063
+ return /* @__PURE__ */ jsx31("div", { className: cn("bg-bg-inset rounded-sm animate-pulse", className), style });
1990
2064
  }
1991
2065
  var ROW_BAR_WIDTHS = [150, 100, 170, 120, 90, 140, 110, 160];
1992
2066
  function SkeletonRow({ barWidth = 130 }) {
1993
2067
  return /* @__PURE__ */ jsxs22("div", { className: "flex shrink-0 items-center gap-2 px-2 h-[32px] rounded-lg", children: [
1994
- /* @__PURE__ */ jsx30(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
1995
- /* @__PURE__ */ jsx30(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
2068
+ /* @__PURE__ */ jsx31(SkeletonBar, { className: "w-4 h-4 shrink-0" }),
2069
+ /* @__PURE__ */ jsx31(SkeletonBar, { className: "h-3.5", style: { width: barWidth } })
1996
2070
  ] });
1997
2071
  }
1998
2072
  function SkeletonList({ rows = 8, className }) {
1999
- return /* @__PURE__ */ jsx30("div", { className: cn("flex flex-col gap-0.5 animate-skeleton-in", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx30(SkeletonRow, { barWidth: ROW_BAR_WIDTHS[i % ROW_BAR_WIDTHS.length] }, i)) });
2073
+ return /* @__PURE__ */ jsx31("div", { className: cn("flex flex-col gap-0.5 animate-skeleton-in", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx31(SkeletonRow, { barWidth: ROW_BAR_WIDTHS[i % ROW_BAR_WIDTHS.length] }, i)) });
2000
2074
  }
2001
2075
 
2002
2076
  // src/CommandPalette.tsx
2003
- import { Fragment as Fragment6, jsx as jsx31, jsxs as jsxs23 } from "react/jsx-runtime";
2004
- var PaletteContext = createContext5(null);
2077
+ import { Fragment as Fragment6, jsx as jsx32, jsxs as jsxs23 } from "react/jsx-runtime";
2078
+ var PaletteContext = createContext6(null);
2005
2079
  function usePalette(part) {
2006
- const palette = useContext5(PaletteContext);
2080
+ const palette = useContext6(PaletteContext);
2007
2081
  if (!palette) throw new Error(`[@estiva-app/ui] ${part} must be inside a CommandPalette.`);
2008
2082
  return palette;
2009
2083
  }
@@ -2015,8 +2089,8 @@ function firstControl(popup) {
2015
2089
  return popup.querySelector("[data-command-palette-fields]")?.querySelector(CONTROL2) ?? null;
2016
2090
  }
2017
2091
  function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", children }) {
2018
- const popupRef = useRef6(null);
2019
- useEffect3(() => {
2092
+ const popupRef = useRef7(null);
2093
+ useEffect4(() => {
2020
2094
  if (!open) return;
2021
2095
  const frame = requestAnimationFrame(() => {
2022
2096
  const popup = popupRef.current;
@@ -2025,10 +2099,10 @@ function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", chi
2025
2099
  });
2026
2100
  return () => cancelAnimationFrame(frame);
2027
2101
  });
2028
- const context = useMemo2(() => ({ where, modKey, popupRef }), [where, modKey]);
2029
- return /* @__PURE__ */ jsx31(Dialog3.Root, { open, onOpenChange: (next) => onOpenChange(next), children: /* @__PURE__ */ jsxs23(Dialog3.Portal, { children: [
2030
- /* @__PURE__ */ jsx31(Dialog3.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
2031
- /* @__PURE__ */ jsx31(Dialog3.Viewport, { className: "fixed inset-0 z-50 flex items-start justify-center pt-[16vh]", children: /* @__PURE__ */ jsx31(
2102
+ const context = useMemo3(() => ({ where, modKey, popupRef }), [where, modKey]);
2103
+ return /* @__PURE__ */ jsx32(Dialog3.Root, { open, onOpenChange: (next) => onOpenChange(next), children: /* @__PURE__ */ jsxs23(Dialog3.Portal, { children: [
2104
+ /* @__PURE__ */ jsx32(Dialog3.Backdrop, { className: "fixed inset-0 z-40 bg-scrim" }),
2105
+ /* @__PURE__ */ jsx32(Dialog3.Viewport, { className: "fixed inset-0 z-50 flex items-start justify-center pt-[16vh]", children: /* @__PURE__ */ jsx32(
2032
2106
  Dialog3.Popup,
2033
2107
  {
2034
2108
  ref: popupRef,
@@ -2038,13 +2112,13 @@ function CommandPalette({ open, onOpenChange, label, where, modKey = "Ctrl", chi
2038
2112
  if (e.target === popupRef.current) firstControl(popupRef.current)?.focus();
2039
2113
  },
2040
2114
  className: "flex w-[658px] max-w-[calc(100vw-32px)] flex-col overflow-hidden rounded-lg border border-border-default bg-bg-elevated shadow-lg outline-none",
2041
- children: /* @__PURE__ */ jsx31(PaletteContext.Provider, { value: context, children })
2115
+ children: /* @__PURE__ */ jsx32(PaletteContext.Provider, { value: context, children })
2042
2116
  }
2043
2117
  ) })
2044
2118
  ] }) });
2045
2119
  }
2046
2120
  function LevelChip({ chip, onBack }) {
2047
- return /* @__PURE__ */ jsx31(InputChip, { label: chip.label, leading: chip.leading, onRemove: onBack, removeLabel: `Leave ${chip.label}`, truncate: true, className: "max-w-[272px] shrink-0" });
2121
+ return /* @__PURE__ */ jsx32(InputChip, { label: chip.label, leading: chip.leading, onRemove: onBack, removeLabel: `Leave ${chip.label}`, truncate: true, className: "max-w-[272px] shrink-0" });
2048
2122
  }
2049
2123
  function useBack(chip, popupRef) {
2050
2124
  return () => {
@@ -2056,9 +2130,9 @@ function useBack(chip, popupRef) {
2056
2130
  function Footer({ keys }) {
2057
2131
  const { where } = usePalette("The footer");
2058
2132
  return /* @__PURE__ */ jsxs23("div", { className: cn("flex h-9 shrink-0 items-center gap-4 border-t border-border-subtle px-5", MONO_CAPTION_CLASSES, "signal:text-text-muted leaf:font-mono leaf:text-small"), children: [
2059
- /* @__PURE__ */ jsx31("span", { className: "min-w-0 flex-1 truncate", children: where }),
2133
+ /* @__PURE__ */ jsx32("span", { className: "min-w-0 flex-1 truncate", children: where }),
2060
2134
  keys.map(([key, word]) => /* @__PURE__ */ jsxs23("span", { className: "flex shrink-0 items-center gap-1.5", children: [
2061
- /* @__PURE__ */ jsx31(Kbd, { children: key }),
2135
+ /* @__PURE__ */ jsx32(Kbd, { children: key }),
2062
2136
  " ",
2063
2137
  word
2064
2138
  ] }, key))
@@ -2068,14 +2142,14 @@ var lowerFirst = (s) => s.charAt(0).toLowerCase() + s.slice(1);
2068
2142
  function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip, pending, notes = [], empty, children }) {
2069
2143
  const { modKey, popupRef } = usePalette("CommandPaletteSearch");
2070
2144
  const back = useBack(chip, popupRef);
2071
- const items = useMemo2(() => groups.filter((g) => g.rows.length > 0).map((g) => ({ value: g.label, items: g.rows })), [groups]);
2145
+ const items = useMemo3(() => groups.filter((g) => g.rows.length > 0).map((g) => ({ value: g.label, items: g.rows })), [groups]);
2072
2146
  const rows = items.flatMap((g) => g.items);
2073
2147
  const [litId, setLitId] = useState5();
2074
2148
  const lit = litId === void 0 ? void 0 : rows.find((r) => r.id === litId);
2075
- const inputRef = useRef6(null);
2076
- const reported = useRef6({});
2077
- const settled = useRef6(null);
2078
- const moved = useRef6(false);
2149
+ const inputRef = useRef7(null);
2150
+ const reported = useRef7({});
2151
+ const settled = useRef7(null);
2152
+ const moved = useRef7(false);
2079
2153
  useLayoutEffect3(() => {
2080
2154
  const before = settled.current;
2081
2155
  const now = reported.current;
@@ -2159,9 +2233,9 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
2159
2233
  },
2160
2234
  children: [
2161
2235
  /* @__PURE__ */ jsxs23("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
2162
- /* @__PURE__ */ jsx31(IconSearch, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" }),
2163
- chip && /* @__PURE__ */ jsx31(LevelChip, { chip, onBack: back }),
2164
- /* @__PURE__ */ jsx31(
2236
+ /* @__PURE__ */ jsx32(IconSearch, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" }),
2237
+ chip && /* @__PURE__ */ jsx32(LevelChip, { chip, onBack: back }),
2238
+ /* @__PURE__ */ jsx32(
2165
2239
  Autocomplete.Input,
2166
2240
  {
2167
2241
  ref: inputRef,
@@ -2174,42 +2248,42 @@ function CommandPaletteSearch({ query, onQueryChange, placeholder, groups, chip,
2174
2248
  )
2175
2249
  ] }),
2176
2250
  /* @__PURE__ */ jsxs23(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col p-2", children: [
2177
- children != null && /* @__PURE__ */ jsx31("div", { className: "flex flex-col gap-2 px-3 pb-2 pt-3", children }),
2178
- /* @__PURE__ */ jsx31(Autocomplete.List, { className: "flex flex-col", children: (group) => /* @__PURE__ */ jsxs23(Autocomplete.Group, { items: group.items, className: "flex flex-col gap-0.5", children: [
2179
- /* @__PURE__ */ jsx31(Autocomplete.GroupLabel, { className: "flex h-7 shrink-0 items-center px-3", children: /* @__PURE__ */ jsx31(SectionLabel, { tone: "secondary", children: group.value }) }),
2180
- /* @__PURE__ */ jsx31(Autocomplete.Collection, { children: (row) => (
2251
+ children != null && /* @__PURE__ */ jsx32("div", { className: "flex flex-col gap-2 px-3 pb-2 pt-3", children }),
2252
+ /* @__PURE__ */ jsx32(Autocomplete.List, { className: "flex flex-col", children: (group) => /* @__PURE__ */ jsxs23(Autocomplete.Group, { items: group.items, className: "flex flex-col gap-0.5", children: [
2253
+ /* @__PURE__ */ jsx32(Autocomplete.GroupLabel, { className: "flex h-7 shrink-0 items-center px-3", children: /* @__PURE__ */ jsx32(SectionLabel, { tone: "secondary", children: group.value }) }),
2254
+ /* @__PURE__ */ jsx32(Autocomplete.Collection, { children: (row) => (
2181
2255
  /* The menu row, as the list's own option — the way Select
2182
2256
  puts it on `Select.Item`. One row, two parts. */
2183
- /* @__PURE__ */ jsx31(Autocomplete.Item, { value: row, onClick: () => row.onSelect(), className: menuItemClassName({ size: "tall" }), children: /* @__PURE__ */ jsx31(
2257
+ /* @__PURE__ */ jsx32(Autocomplete.Item, { value: row, onClick: () => row.onSelect(), className: menuItemClassName({ size: "tall" }), children: /* @__PURE__ */ jsx32(
2184
2258
  MenuItemBody,
2185
2259
  {
2186
2260
  size: "tall",
2187
2261
  label: row.label,
2188
2262
  description: row.description,
2189
- leading: /* @__PURE__ */ jsx31(RowLeading, { row }),
2263
+ leading: /* @__PURE__ */ jsx32(RowLeading, { row }),
2190
2264
  submenu: !!row.onGoIn,
2191
- hint: row.onGoIn ? /* @__PURE__ */ jsx31(Kbd, { children: "Tab" }) : /* @__PURE__ */ jsx31(EnterHint, {})
2265
+ hint: row.onGoIn ? /* @__PURE__ */ jsx32(Kbd, { children: "Tab" }) : /* @__PURE__ */ jsx32(EnterHint, {})
2192
2266
  }
2193
2267
  ) }, row.id)
2194
2268
  ) })
2195
2269
  ] }, group.value) }),
2196
- /* @__PURE__ */ jsx31(Autocomplete.Status, { className: "flex items-center gap-2 px-3 [&:not(:empty)]:h-8", children: pending && /* @__PURE__ */ jsxs23(Fragment6, { children: [
2197
- /* @__PURE__ */ jsx31(IconLoader22, { size: 12, stroke: 1.5, className: "shrink-0 animate-spin text-text-muted" }),
2198
- /* @__PURE__ */ jsx31("span", { className: "text-caption text-text-muted", children: pending })
2270
+ /* @__PURE__ */ jsx32(Autocomplete.Status, { className: "flex items-center gap-2 px-3 [&:not(:empty)]:h-8", children: pending && /* @__PURE__ */ jsxs23(Fragment6, { children: [
2271
+ /* @__PURE__ */ jsx32(IconLoader22, { size: 12, stroke: 1.5, className: "shrink-0 animate-spin text-text-muted" }),
2272
+ /* @__PURE__ */ jsx32("span", { className: "text-caption text-text-muted", children: pending })
2199
2273
  ] }) }),
2200
- notes.map((note) => /* @__PURE__ */ jsx31("div", { className: "flex min-h-8 items-center px-3", children: /* @__PURE__ */ jsx31(FieldLine, { children: note }) }, note)),
2201
- /* @__PURE__ */ jsx31(Autocomplete.Empty, { className: "flex items-center px-3 [&:not(:empty)]:min-h-10", children: empty && /* @__PURE__ */ jsx31(EmptyState, { scope: "section", message: empty }) })
2274
+ notes.map((note) => /* @__PURE__ */ jsx32("div", { className: "flex min-h-8 items-center px-3", children: /* @__PURE__ */ jsx32(FieldLine, { children: note }) }, note)),
2275
+ /* @__PURE__ */ jsx32(Autocomplete.Empty, { className: "flex items-center px-3 [&:not(:empty)]:min-h-10", children: empty && /* @__PURE__ */ jsx32(EmptyState, { scope: "section", message: empty }) })
2202
2276
  ] }),
2203
- /* @__PURE__ */ jsx31(Footer, { keys })
2277
+ /* @__PURE__ */ jsx32(Footer, { keys })
2204
2278
  ]
2205
2279
  }
2206
2280
  );
2207
2281
  }
2208
2282
  function RowLeading({ row }) {
2209
2283
  if (row.icon != null) {
2210
- return /* @__PURE__ */ jsx31("span", { className: "flex size-8 items-center justify-center rounded-sm bg-bg-inset text-text-secondary", children: row.icon });
2284
+ return /* @__PURE__ */ jsx32("span", { className: "flex size-8 items-center justify-center rounded-sm bg-bg-inset text-text-secondary", children: row.icon });
2211
2285
  }
2212
- return /* @__PURE__ */ jsx31("span", { className: "flex size-8 items-center justify-center", children: row.leading });
2286
+ return /* @__PURE__ */ jsx32("span", { className: "flex size-8 items-center justify-center", children: row.leading });
2213
2287
  }
2214
2288
  var TEXT_TYPES = /* @__PURE__ */ new Set(["", "text", "search", "email", "url", "tel", "password", "number"]);
2215
2289
  function isTextField(el) {
@@ -2219,9 +2293,9 @@ function isTextField(el) {
2219
2293
  function CommandPaletteForm({ chip, icon, submitLabel, onSubmit, submitWaits, working, error, children }) {
2220
2294
  const { modKey, popupRef } = usePalette("CommandPaletteForm");
2221
2295
  const back = useBack(chip, popupRef);
2222
- const frameRef = useRef6(null);
2296
+ const frameRef = useRef7(null);
2223
2297
  const busy = !!working;
2224
- const busyRef = useRef6(busy);
2298
+ const busyRef = useRef7(busy);
2225
2299
  busyRef.current = busy;
2226
2300
  const firstInvalid2 = () => frameRef.current?.querySelector("[data-invalid]")?.querySelector(CONTROL2) ?? null;
2227
2301
  const submit = () => {
@@ -2253,50 +2327,50 @@ function CommandPaletteForm({ chip, icon, submitLabel, onSubmit, submitWaits, wo
2253
2327
  ];
2254
2328
  return /* @__PURE__ */ jsxs23("div", { ref: frameRef, tabIndex: -1, onKeyDown, onFocus: measure, onBlur: measure, onInput: measure, className: "flex min-h-0 flex-col outline-none", children: [
2255
2329
  /* @__PURE__ */ jsxs23("div", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border-subtle px-5", children: [
2256
- icon != null && /* @__PURE__ */ jsx31("span", { className: "flex shrink-0 items-center text-text-secondary", children: icon }),
2257
- /* @__PURE__ */ jsx31(LevelChip, { chip, onBack: back })
2330
+ icon != null && /* @__PURE__ */ jsx32("span", { className: "flex shrink-0 items-center text-text-secondary", children: icon }),
2331
+ /* @__PURE__ */ jsx32(LevelChip, { chip, onBack: back })
2258
2332
  ] }),
2259
2333
  /* @__PURE__ */ jsxs23(Form, { "data-command-palette-fields": "", busy, enterSends: false, onSubmit: submit, layout: "free", className: "flex min-h-0 flex-col", children: [
2260
- /* @__PURE__ */ jsx31(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col px-5 py-4", children: /* @__PURE__ */ jsx31("div", { className: FIELDS_CLASSES, children }) }),
2334
+ /* @__PURE__ */ jsx32(ScrollArea, { viewportClassName: "max-h-[420px]", contentClassName: "flex flex-col px-5 py-4", children: /* @__PURE__ */ jsx32("div", { className: FIELDS_CLASSES, children }) }),
2261
2335
  /* @__PURE__ */ jsxs23("div", { className: "flex shrink-0 items-center gap-3 px-5 pb-4", children: [
2262
- /* @__PURE__ */ jsx31("div", { className: "min-w-0 flex-1", children: working ? /* @__PURE__ */ jsx31(FieldLine, { children: working.line }) : error ? /* @__PURE__ */ jsx31(FieldLine, { tone: "error", children: error }) : null }),
2263
- /* @__PURE__ */ jsx31(
2336
+ /* @__PURE__ */ jsx32("div", { className: "min-w-0 flex-1", children: working ? /* @__PURE__ */ jsx32(FieldLine, { children: working.line }) : error ? /* @__PURE__ */ jsx32(FieldLine, { tone: "error", children: error }) : null }),
2337
+ /* @__PURE__ */ jsx32(
2264
2338
  Button,
2265
2339
  {
2266
2340
  type: "submit",
2267
2341
  variant: "primary",
2268
2342
  disabled: busy,
2269
2343
  disabledReason: busy ? void 0 : submitWaits,
2270
- leadingIcon: busy ? /* @__PURE__ */ jsx31(IconLoader22, { size: 16, stroke: 1.5, className: "animate-spin" }) : void 0,
2344
+ leadingIcon: busy ? /* @__PURE__ */ jsx32(IconLoader22, { size: 16, stroke: 1.5, className: "animate-spin" }) : void 0,
2271
2345
  children: working ? working.button : submitLabel
2272
2346
  }
2273
2347
  )
2274
2348
  ] })
2275
2349
  ] }),
2276
- /* @__PURE__ */ jsx31(Footer, { keys })
2350
+ /* @__PURE__ */ jsx32(Footer, { keys })
2277
2351
  ] });
2278
2352
  }
2279
2353
  var BAR_WIDTHS = ["w-4/5", "w-3/5", "w-2/3"];
2280
2354
  function CommandPaletteWorking({ children, bars = 2 }) {
2281
2355
  return /* @__PURE__ */ jsxs23("div", { role: "status", className: "flex flex-col gap-2", children: [
2282
2356
  /* @__PURE__ */ jsxs23("span", { className: "flex items-center gap-2 text-caption text-text-secondary", children: [
2283
- /* @__PURE__ */ jsx31(IconLoader22, { size: 14, stroke: 1.5, className: "shrink-0 animate-spin" }),
2357
+ /* @__PURE__ */ jsx32(IconLoader22, { size: 14, stroke: 1.5, className: "shrink-0 animate-spin" }),
2284
2358
  children
2285
2359
  ] }),
2286
- BAR_WIDTHS.slice(0, bars).map((width) => /* @__PURE__ */ jsx31(SkeletonBar, { className: cn("h-3", width) }, width))
2360
+ BAR_WIDTHS.slice(0, bars).map((width) => /* @__PURE__ */ jsx32(SkeletonBar, { className: cn("h-3", width) }, width))
2287
2361
  ] });
2288
2362
  }
2289
2363
  function CommandPaletteAnswer({ children, note }) {
2290
2364
  const paragraphs = children.split(/\n\s*\n/).filter((p) => p.trim() !== "");
2291
2365
  return /* @__PURE__ */ jsxs23("div", { className: "flex flex-col gap-2", children: [
2292
- paragraphs.map((paragraph, i) => /* @__PURE__ */ jsx31("p", { className: "whitespace-pre-wrap text-body-2 text-text-primary", children: paragraph.split(/\s*(\[\d+\])/).map(
2293
- (part, j) => /^\[\d+\]$/.test(part) ? /* @__PURE__ */ jsx31("sup", { className: "ml-0.5 font-mono text-small text-accent-text", children: part.slice(1, -1) }, j) : part
2366
+ paragraphs.map((paragraph, i) => /* @__PURE__ */ jsx32("p", { className: "whitespace-pre-wrap text-body-2 text-text-primary", children: paragraph.split(/\s*(\[\d+\])/).map(
2367
+ (part, j) => /^\[\d+\]$/.test(part) ? /* @__PURE__ */ jsx32("sup", { className: "ml-0.5 font-mono text-small text-accent-text", children: part.slice(1, -1) }, j) : part
2294
2368
  ) }, i)),
2295
- note && /* @__PURE__ */ jsx31(FieldLine, { children: note })
2369
+ note && /* @__PURE__ */ jsx32(FieldLine, { children: note })
2296
2370
  ] });
2297
2371
  }
2298
2372
  function CommandPaletteQuote({ children }) {
2299
- return /* @__PURE__ */ jsx31("p", { className: "whitespace-pre-wrap border-l-2 border-border-default pl-3 text-body-2 text-text-primary", children });
2373
+ return /* @__PURE__ */ jsx32("p", { className: "whitespace-pre-wrap border-l-2 border-border-default pl-3 text-body-2 text-text-primary", children });
2300
2374
  }
2301
2375
  function CommandPaletteProposal({ source, mark, children }) {
2302
2376
  return /* @__PURE__ */ jsxs23(Card, { fill: "surface", className: "flex flex-col gap-1 p-3", children: [
@@ -2304,12 +2378,12 @@ function CommandPaletteProposal({ source, mark, children }) {
2304
2378
  mark,
2305
2379
  source
2306
2380
  ] }),
2307
- /* @__PURE__ */ jsx31("span", { className: "text-body-2 text-text-primary", children })
2381
+ /* @__PURE__ */ jsx32("span", { className: "text-body-2 text-text-primary", children })
2308
2382
  ] });
2309
2383
  }
2310
2384
 
2311
2385
  // src/InlineChip.tsx
2312
- import { Fragment as Fragment7, jsx as jsx32, jsxs as jsxs24 } from "react/jsx-runtime";
2386
+ import { Fragment as Fragment7, jsx as jsx33, jsxs as jsxs24 } from "react/jsx-runtime";
2313
2387
  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";
2314
2388
  var INLINE_CHIP_TONE_CLASSES = {
2315
2389
  /** A thing or a place — anything that is not a person. */
@@ -2331,19 +2405,20 @@ function inlineChipClassName(tone, className) {
2331
2405
  return cn(INLINE_CHIP_CLASSES, INLINE_CHIP_TONE_CLASSES[tone], className);
2332
2406
  }
2333
2407
  function InlineChip({ tone = "neutral", icon, href, className, children, ...props }) {
2408
+ const inApp = useInAppClick(href, props.onClick);
2334
2409
  const body = /* @__PURE__ */ jsxs24(Fragment7, { children: [
2335
- icon && /* @__PURE__ */ jsx32("span", { className: "flex size-4 shrink-0 items-center justify-center text-text-secondary", children: icon }),
2410
+ icon && /* @__PURE__ */ jsx33("span", { className: "flex size-4 shrink-0 items-center justify-center text-text-secondary", children: icon }),
2336
2411
  children
2337
2412
  ] });
2338
2413
  const classes = inlineChipClassName(tone, className);
2339
2414
  if (href === void 0) {
2340
- return /* @__PURE__ */ jsx32("span", { className: classes, ...props, children: body });
2415
+ return /* @__PURE__ */ jsx33("span", { className: classes, ...props, children: body });
2341
2416
  }
2342
- return /* @__PURE__ */ jsx32("a", { href, className: classes, ...props, children: body });
2417
+ return /* @__PURE__ */ jsx33("a", { href, className: classes, ...props, onClick: inApp, children: body });
2343
2418
  }
2344
2419
 
2345
2420
  // src/RichText.tsx
2346
- import { Fragment as Fragment8, jsx as jsx33, jsxs as jsxs25 } from "react/jsx-runtime";
2421
+ import { Fragment as Fragment8, jsx as jsx34, jsxs as jsxs25 } from "react/jsx-runtime";
2347
2422
  var RICH_TEXT_CLASSES = {
2348
2423
  base: "flex flex-col gap-1 break-words text-text-secondary",
2349
2424
  /* A heading binds to what follows it: 12px above (8 and the 4px gap), 8px below (4 and the gap); two headings in a row, 12px apart. Level 3 keeps the text's colour, one step lower. */
@@ -2375,35 +2450,35 @@ function textWithLinks(text, renderText) {
2375
2450
  return parts.map((part, i) => {
2376
2451
  const written = part.match(WRITTEN_LINK);
2377
2452
  if (written) {
2378
- return /* @__PURE__ */ jsx33("span", { className: "break-words", children: /* @__PURE__ */ jsx33(Link, { href: written[2], external: true, onClick: keepToLink, children: written[1] }) }, i);
2453
+ return /* @__PURE__ */ jsx34("span", { className: "break-words", children: /* @__PURE__ */ jsx34(Link, { href: written[2], external: true, onClick: keepToLink, children: written[1] }) }, i);
2379
2454
  }
2380
2455
  const bare = i % 2 === 1 ? part.match(BARE_LINK) : null;
2381
2456
  if (bare) {
2382
2457
  return (
2383
2458
  // An address has no spaces to wrap at, so it may break anywhere.
2384
2459
  /* @__PURE__ */ jsxs25("span", { className: "break-all", children: [
2385
- /* @__PURE__ */ jsx33(Link, { href: bare[1], external: true, onClick: keepToLink, children: bare[1] }),
2460
+ /* @__PURE__ */ jsx34(Link, { href: bare[1], external: true, onClick: keepToLink, children: bare[1] }),
2386
2461
  bare[2]
2387
2462
  ] }, i)
2388
2463
  );
2389
2464
  }
2390
- return part ? /* @__PURE__ */ jsx33("span", { children: renderText(part) }, i) : null;
2465
+ return part ? /* @__PURE__ */ jsx34("span", { children: renderText(part) }, i) : null;
2391
2466
  });
2392
2467
  }
2393
2468
  function Runs({ runs, draw }) {
2394
- return /* @__PURE__ */ jsx33(Fragment8, { children: (runs ?? []).map((run, i) => {
2395
- if (run.reference) return /* @__PURE__ */ jsx33("span", { children: draw.renderReference(run.reference, run) }, i);
2469
+ return /* @__PURE__ */ jsx34(Fragment8, { children: (runs ?? []).map((run, i) => {
2470
+ if (run.reference) return /* @__PURE__ */ jsx34("span", { children: draw.renderReference(run.reference, run) }, i);
2396
2471
  if (run.marks.includes("code")) {
2397
- return /* @__PURE__ */ jsx33("code", { children: run.text }, i);
2472
+ return /* @__PURE__ */ jsx34("code", { children: run.text }, i);
2398
2473
  }
2399
2474
  let node = run.text.split("\n").map((line, j) => /* @__PURE__ */ jsxs25("span", { children: [
2400
- j > 0 && /* @__PURE__ */ jsx33("br", {}),
2475
+ j > 0 && /* @__PURE__ */ jsx34("br", {}),
2401
2476
  textWithLinks(line, draw.renderText)
2402
2477
  ] }, j));
2403
- if (run.marks.includes("underline")) node = /* @__PURE__ */ jsx33("u", { children: node });
2404
- if (run.marks.includes("italic")) node = /* @__PURE__ */ jsx33("em", { children: node });
2405
- if (run.marks.includes("bold")) node = /* @__PURE__ */ jsx33("strong", { children: node });
2406
- return /* @__PURE__ */ jsx33("span", { children: node }, i);
2478
+ if (run.marks.includes("underline")) node = /* @__PURE__ */ jsx34("u", { children: node });
2479
+ if (run.marks.includes("italic")) node = /* @__PURE__ */ jsx34("em", { children: node });
2480
+ if (run.marks.includes("bold")) node = /* @__PURE__ */ jsx34("strong", { children: node });
2481
+ return /* @__PURE__ */ jsx34("span", { children: node }, i);
2407
2482
  }) });
2408
2483
  }
2409
2484
  var named = (block) => block.typeName ?? block.type;
@@ -2421,8 +2496,8 @@ function Table({ block, draw }) {
2421
2496
  colSpan: colspan && colspan > 1 ? colspan : void 0,
2422
2497
  rowSpan: rowspan && rowspan > 1 ? rowspan : void 0,
2423
2498
  children: [
2424
- (cell.children ?? []).map((child, j) => /* @__PURE__ */ jsx33(Runs, { runs: child.inline, draw }, j)),
2425
- /* @__PURE__ */ jsx33(Runs, { runs: cell.inline, draw })
2499
+ (cell.children ?? []).map((child, j) => /* @__PURE__ */ jsx34(Runs, { runs: child.inline, draw }, j)),
2500
+ /* @__PURE__ */ jsx34(Runs, { runs: cell.inline, draw })
2426
2501
  ]
2427
2502
  },
2428
2503
  cell.id ?? i
@@ -2431,42 +2506,42 @@ function Table({ block, draw }) {
2431
2506
  const first = rows[0].children ?? [];
2432
2507
  const headerRow = first.length > 0 && first.every((cell) => named(cell) === "tableHeader");
2433
2508
  return /* @__PURE__ */ jsxs25("table", { "data-block-id": block.id, children: [
2434
- headerRow && /* @__PURE__ */ jsx33("thead", { children: /* @__PURE__ */ jsx33("tr", { "data-block-id": rows[0].id, children: cells(rows[0]) }) }),
2435
- /* @__PURE__ */ jsx33("tbody", { children: (headerRow ? rows.slice(1) : rows).map((row, i) => /* @__PURE__ */ jsx33("tr", { "data-block-id": row.id, children: cells(row) }, row.id ?? i)) })
2509
+ headerRow && /* @__PURE__ */ jsx34("thead", { children: /* @__PURE__ */ jsx34("tr", { "data-block-id": rows[0].id, children: cells(rows[0]) }) }),
2510
+ /* @__PURE__ */ jsx34("tbody", { children: (headerRow ? rows.slice(1) : rows).map((row, i) => /* @__PURE__ */ jsx34("tr", { "data-block-id": row.id, children: cells(row) }, row.id ?? i)) })
2436
2511
  ] });
2437
2512
  }
2438
2513
  function Block({ block, draw }) {
2439
2514
  const own = draw.renderBlock?.(block);
2440
2515
  if (own !== void 0) return own;
2441
- const runs = /* @__PURE__ */ jsx33(Runs, { runs: block.inline, draw });
2516
+ const runs = /* @__PURE__ */ jsx34(Runs, { runs: block.inline, draw });
2442
2517
  switch (block.type) {
2443
2518
  case "heading": {
2444
- if (block.level === 1) return /* @__PURE__ */ jsx33("h1", { "data-block-id": block.id, children: runs });
2445
- if (block.level === 3) return /* @__PURE__ */ jsx33("h3", { "data-block-id": block.id, children: runs });
2446
- return /* @__PURE__ */ jsx33("h2", { "data-block-id": block.id, children: runs });
2519
+ if (block.level === 1) return /* @__PURE__ */ jsx34("h1", { "data-block-id": block.id, children: runs });
2520
+ if (block.level === 3) return /* @__PURE__ */ jsx34("h3", { "data-block-id": block.id, children: runs });
2521
+ return /* @__PURE__ */ jsx34("h2", { "data-block-id": block.id, children: runs });
2447
2522
  }
2448
2523
  case "paragraph":
2449
- return /* @__PURE__ */ jsx33("p", { "data-block-id": block.id, children: runs });
2524
+ return /* @__PURE__ */ jsx34("p", { "data-block-id": block.id, children: runs });
2450
2525
  case "bulletList":
2451
2526
  case "orderedList": {
2452
- const items = (block.children ?? []).map((item, i) => /* @__PURE__ */ jsx33("li", { "data-block-id": item.id, children: /* @__PURE__ */ jsx33(Runs, { runs: item.inline, draw }) }, item.id ?? i));
2453
- return block.type === "bulletList" ? /* @__PURE__ */ jsx33("ul", { "data-block-id": block.id, children: items }) : /* @__PURE__ */ jsx33("ol", { "data-block-id": block.id, start: block.start, children: items });
2527
+ const items = (block.children ?? []).map((item, i) => /* @__PURE__ */ jsx34("li", { "data-block-id": item.id, children: /* @__PURE__ */ jsx34(Runs, { runs: item.inline, draw }) }, item.id ?? i));
2528
+ return block.type === "bulletList" ? /* @__PURE__ */ jsx34("ul", { "data-block-id": block.id, children: items }) : /* @__PURE__ */ jsx34("ol", { "data-block-id": block.id, start: block.start, children: items });
2454
2529
  }
2455
2530
  case "blockquote":
2456
- return /* @__PURE__ */ jsx33("blockquote", { "data-block-id": block.id, children: runs });
2531
+ return /* @__PURE__ */ jsx34("blockquote", { "data-block-id": block.id, children: runs });
2457
2532
  case "codeBlock":
2458
- return /* @__PURE__ */ jsx33("pre", { "data-block-id": block.id, "data-language": block.language, children: /* @__PURE__ */ jsx33("code", { children: (block.inline ?? []).map((run) => run.text).join("") }) });
2533
+ return /* @__PURE__ */ jsx34("pre", { "data-block-id": block.id, "data-language": block.language, children: /* @__PURE__ */ jsx34("code", { children: (block.inline ?? []).map((run) => run.text).join("") }) });
2459
2534
  case "horizontalRule":
2460
- return /* @__PURE__ */ jsx33("hr", { "data-block-id": block.id });
2535
+ return /* @__PURE__ */ jsx34("hr", { "data-block-id": block.id });
2461
2536
  case "table": {
2462
- const table = /* @__PURE__ */ jsx33(Table, { block, draw });
2537
+ const table = /* @__PURE__ */ jsx34(Table, { block, draw });
2463
2538
  if ((block.children ?? []).some((row) => named(row) === "tableRow")) return table;
2464
2539
  break;
2465
2540
  }
2466
2541
  }
2467
2542
  return /* @__PURE__ */ jsxs25("div", { "data-block-id": block.id, "data-block-type": named(block), children: [
2468
2543
  runs,
2469
- (block.children ?? []).map((child, i) => /* @__PURE__ */ jsx33(Block, { block: child, draw }, child.id ?? i))
2544
+ (block.children ?? []).map((child, i) => /* @__PURE__ */ jsx34(Block, { block: child, draw }, child.id ?? i))
2470
2545
  ] });
2471
2546
  }
2472
2547
  function RichText({
@@ -2478,34 +2553,34 @@ function RichText({
2478
2553
  }) {
2479
2554
  if (blocks.length === 0) return null;
2480
2555
  const draw = { renderText, renderReference, renderBlock };
2481
- return /* @__PURE__ */ jsx33("div", { "data-rich-text": true, className: richTextClassName(size), children: blocks.map((block, i) => /* @__PURE__ */ jsx33(Block, { block, draw }, block.id ?? i)) });
2556
+ return /* @__PURE__ */ jsx34("div", { "data-rich-text": true, className: richTextClassName(size), children: blocks.map((block, i) => /* @__PURE__ */ jsx34(Block, { block, draw }, block.id ?? i)) });
2482
2557
  }
2483
2558
 
2484
2559
  // src/IdentityMenu.tsx
2485
- import { useCallback as useCallback2, useRef as useRef7 } from "react";
2560
+ import { useCallback as useCallback2, useRef as useRef8 } from "react";
2486
2561
 
2487
2562
  // src/Person.tsx
2488
- import { jsx as jsx34, jsxs as jsxs26 } from "react/jsx-runtime";
2563
+ import { jsx as jsx35, jsxs as jsxs26 } from "react/jsx-runtime";
2489
2564
  function Person({ name, picture, fallback = "\u2014", size = 20, className }) {
2490
2565
  return (
2491
2566
  // gap-2: the face-to-name distance is one rule (8px) wherever a person
2492
2567
  // appears — Katerina, 2026-09-01, set on Person so PersonTrigger and every
2493
2568
  // row agree by construction.
2494
2569
  /* @__PURE__ */ jsxs26("span", { className: cn("flex min-w-0 items-center gap-2", className), children: [
2495
- /* @__PURE__ */ jsx34(Avatar, { name, src: picture, size }),
2496
- /* @__PURE__ */ jsx34("span", { className: cn("truncate", !name && "text-text-muted"), children: name ?? fallback })
2570
+ /* @__PURE__ */ jsx35(Avatar, { name, src: picture, size }),
2571
+ /* @__PURE__ */ jsx35("span", { className: cn("truncate", !name && "text-text-muted"), children: name ?? fallback })
2497
2572
  ] })
2498
2573
  );
2499
2574
  }
2500
2575
 
2501
2576
  // src/PersonTrigger.tsx
2502
- import { Button as BaseButton6 } from "@base-ui/react/button";
2577
+ import { Button as BaseButton7 } from "@base-ui/react/button";
2503
2578
  import { IconChevronDown as IconChevronDown2 } from "@tabler/icons-react";
2504
- import { jsx as jsx35, jsxs as jsxs27 } from "react/jsx-runtime";
2579
+ import { jsx as jsx36, jsxs as jsxs27 } from "react/jsx-runtime";
2505
2580
  function PersonTrigger({ name, picture, fallback, size, open = false, compact = false, className, ...props }) {
2506
2581
  if (compact) {
2507
- return /* @__PURE__ */ jsx35(
2508
- BaseButton6,
2582
+ return /* @__PURE__ */ jsx36(
2583
+ BaseButton7,
2509
2584
  {
2510
2585
  type: "button",
2511
2586
  "aria-haspopup": "menu",
@@ -2513,14 +2588,14 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
2513
2588
  "aria-label": props["aria-label"] ?? name ?? fallback,
2514
2589
  className: cn("cursor-pointer rounded-full", className),
2515
2590
  ...props,
2516
- children: /* @__PURE__ */ jsx35(Avatar, { name, src: picture, size: size ?? 36 })
2591
+ children: /* @__PURE__ */ jsx36(Avatar, { name, src: picture, size: size ?? 36 })
2517
2592
  }
2518
2593
  );
2519
2594
  }
2520
2595
  return (
2521
2596
  // @estiva-escape(no-copied-look): N5 (Katerina, 24 September: record only): a row that fills on hover, as NavItem also does
2522
2597
  /* @__PURE__ */ jsxs27(
2523
- BaseButton6,
2598
+ BaseButton7,
2524
2599
  {
2525
2600
  type: "button",
2526
2601
  "aria-haspopup": "menu",
@@ -2537,8 +2612,8 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
2537
2612
  ),
2538
2613
  ...props,
2539
2614
  children: [
2540
- /* @__PURE__ */ jsx35(Person, { name, picture, fallback, size: size ?? 22 }),
2541
- /* @__PURE__ */ jsx35(IconChevronDown2, { size: 14, stroke: 1.5, className: "shrink-0 text-text-muted" })
2615
+ /* @__PURE__ */ jsx36(Person, { name, picture, fallback, size: size ?? 22 }),
2616
+ /* @__PURE__ */ jsx36(IconChevronDown2, { size: 14, stroke: 1.5, className: "shrink-0 text-text-muted" })
2542
2617
  ]
2543
2618
  }
2544
2619
  )
@@ -2546,10 +2621,10 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
2546
2621
  }
2547
2622
 
2548
2623
  // src/IdentityMenu.tsx
2549
- import { Fragment as Fragment9, jsx as jsx36, jsxs as jsxs28 } from "react/jsx-runtime";
2624
+ import { Fragment as Fragment9, jsx as jsx37, jsxs as jsxs28 } from "react/jsx-runtime";
2550
2625
  function IdentityPanel({ className, onClose = () => {
2551
2626
  }, ...rest }) {
2552
- return /* @__PURE__ */ jsx36(MenuPanel, { className: cn("w-72", className), children: /* @__PURE__ */ jsx36(IdentityRows, { ...rest, onClose }) });
2627
+ return /* @__PURE__ */ jsx37(MenuPanel, { className: cn("w-72", className), children: /* @__PURE__ */ jsx37(IdentityRows, { ...rest, onClose }) });
2553
2628
  }
2554
2629
  function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, onClose, children }) {
2555
2630
  const act = (action) => () => {
@@ -2559,51 +2634,51 @@ function IdentityRows({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, on
2559
2634
  const appRows = typeof children === "function" ? children(onClose) : children;
2560
2635
  return /* @__PURE__ */ jsxs28(Fragment9, { children: [
2561
2636
  /* @__PURE__ */ jsxs28(MenuSection, { label: signedIn ? "Signed in as" : "Acting as", children: [
2562
- /* @__PURE__ */ jsx36(MenuRow, { children: /* @__PURE__ */ jsx36("div", { className: "flex min-w-0 text-body-2-strong", children: /* @__PURE__ */ jsx36(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28 }) }) }),
2563
- /* @__PURE__ */ jsx36(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." }),
2637
+ /* @__PURE__ */ jsx37(MenuRow, { children: /* @__PURE__ */ jsx37("div", { className: "flex min-w-0 text-body-2-strong", children: /* @__PURE__ */ jsx37(Person, { name: me.name, picture: me.picture, fallback: "Anonymous", size: 28 }) }) }),
2638
+ /* @__PURE__ */ jsx37(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." }),
2564
2639
  me.email && /* @__PURE__ */ jsxs28(Note, { children: [
2565
2640
  me.email,
2566
2641
  " \xB7 known to Estiva, never published to the relay"
2567
2642
  ] })
2568
2643
  ] }),
2569
2644
  relayUrl && /* @__PURE__ */ jsxs28(Fragment9, { children: [
2570
- /* @__PURE__ */ jsx36(Divider, { className: "mx-0 my-2" }),
2645
+ /* @__PURE__ */ jsx37(Divider, { className: "mx-0 my-2" }),
2571
2646
  /* @__PURE__ */ jsxs28(MenuSection, { label: "Workspace", children: [
2572
- /* @__PURE__ */ jsx36(MenuRow, { children: /* @__PURE__ */ jsx36("span", { className: "break-all font-mono text-caption text-text-primary", children: relayUrl }) }),
2573
- /* @__PURE__ */ jsx36(Note, { children: "Everyone on this relay shares this workspace, in every app." })
2647
+ /* @__PURE__ */ jsx37(MenuRow, { children: /* @__PURE__ */ jsx37("span", { className: "break-all font-mono text-caption text-text-primary", children: relayUrl }) }),
2648
+ /* @__PURE__ */ jsx37(Note, { children: "Everyone on this relay shares this workspace, in every app." })
2574
2649
  ] })
2575
2650
  ] }),
2576
2651
  appRows && /* @__PURE__ */ jsxs28(Fragment9, { children: [
2577
- /* @__PURE__ */ jsx36(Divider, { className: "mx-0 my-2" }),
2652
+ /* @__PURE__ */ jsx37(Divider, { className: "mx-0 my-2" }),
2578
2653
  appRows
2579
2654
  ] }),
2580
- signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */ jsx36(Divider, { className: "mx-0 my-2" }) : null,
2581
- signedIn && idBase && /* @__PURE__ */ jsx36(
2655
+ signedIn && idBase || onCopyKey || idBase && onSignOut ? /* @__PURE__ */ jsx37(Divider, { className: "mx-0 my-2" }) : null,
2656
+ signedIn && idBase && /* @__PURE__ */ jsx37(
2582
2657
  MenuItem,
2583
2658
  {
2584
2659
  label: "Edit your profile in Estiva ID",
2585
2660
  onClick: act(() => window.open(idBase, "_blank", "noopener,noreferrer"))
2586
2661
  }
2587
2662
  ),
2588
- onCopyKey && /* @__PURE__ */ jsx36(MenuItem, { label: "Copy public key", onClick: act(onCopyKey) }),
2589
- idBase && onSignOut && /* @__PURE__ */ jsx36(MenuItem, { label: "Sign out", onClick: act(onSignOut) })
2663
+ onCopyKey && /* @__PURE__ */ jsx37(MenuItem, { label: "Copy public key", onClick: act(onCopyKey) }),
2664
+ idBase && onSignOut && /* @__PURE__ */ jsx37(MenuItem, { label: "Sign out", onClick: act(onSignOut) })
2590
2665
  ] });
2591
2666
  }
2592
2667
  function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, compact = false, className, children }) {
2593
- const actions = useRef7(null);
2668
+ const actions = useRef8(null);
2594
2669
  const close = useCallback2(() => actions.current?.close(), []);
2595
2670
  return (
2596
2671
  /* The wrapper carries the caller's `className` and nothing else. It used
2597
2672
  to be `relative`, because the panel was positioned against it; the panel
2598
2673
  hangs from the trigger and portals now, so a positioning context here
2599
2674
  would only be a lie about what this box does. */
2600
- /* @__PURE__ */ jsx36("div", { className, children: /* @__PURE__ */ jsx36(
2675
+ /* @__PURE__ */ jsx37("div", { className, children: /* @__PURE__ */ jsx37(
2601
2676
  Menu,
2602
2677
  {
2603
2678
  align: "right",
2604
2679
  actionsRef: actions,
2605
2680
  className: "w-72",
2606
- trigger: /* @__PURE__ */ jsx36(
2681
+ trigger: /* @__PURE__ */ jsx37(
2607
2682
  PersonTrigger,
2608
2683
  {
2609
2684
  name: me.name,
@@ -2614,7 +2689,7 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
2614
2689
  "aria-label": compact ? "Account menu" : void 0
2615
2690
  }
2616
2691
  ),
2617
- children: /* @__PURE__ */ jsx36(
2692
+ children: /* @__PURE__ */ jsx37(
2618
2693
  IdentityRows,
2619
2694
  {
2620
2695
  me,
@@ -2632,14 +2707,14 @@ function IdentityMenu({ me, signedIn, relayUrl, idBase, onCopyKey, onSignOut, co
2632
2707
  );
2633
2708
  }
2634
2709
  function Note({ children }) {
2635
- return /* @__PURE__ */ jsx36("span", { className: "px-2 pb-1.5 text-caption text-text-secondary", children });
2710
+ return /* @__PURE__ */ jsx37("span", { className: "px-2 pb-1.5 text-caption text-text-secondary", children });
2636
2711
  }
2637
2712
 
2638
2713
  // src/FilePicker.tsx
2639
2714
  import { forwardRef } from "react";
2640
- import { jsx as jsx37 } from "react/jsx-runtime";
2715
+ import { jsx as jsx38 } from "react/jsx-runtime";
2641
2716
  var FilePicker = forwardRef(function FilePicker2({ onPick, ...props }, ref) {
2642
- return /* @__PURE__ */ jsx37(
2717
+ return /* @__PURE__ */ jsx38(
2643
2718
  "input",
2644
2719
  {
2645
2720
  ref,
@@ -2660,7 +2735,7 @@ var FilePicker = forwardRef(function FilePicker2({ onPick, ...props }, ref) {
2660
2735
  // src/Select.tsx
2661
2736
  import { IconCheck as IconCheck2, IconChevronDown as IconChevronDown3 } from "@tabler/icons-react";
2662
2737
  import { Select as BaseSelect } from "@base-ui/react/select";
2663
- import { jsx as jsx38, jsxs as jsxs29 } from "react/jsx-runtime";
2738
+ import { jsx as jsx39, jsxs as jsxs29 } from "react/jsx-runtime";
2664
2739
  var GAP4 = 4;
2665
2740
  var VIEWPORT_PAD4 = 8;
2666
2741
  function Select({ value, onChange, options, size = "default", ariaLabel, placeholder = "Select\u2026", disabled, disabledReason, className, ...aria }) {
@@ -2702,13 +2777,13 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
2702
2777
  ),
2703
2778
  children: [
2704
2779
  /* @__PURE__ */ jsxs29("span", { className: cn("flex min-w-0 items-center gap-2", !selected && "text-text-muted"), children: [
2705
- selected?.leading && /* @__PURE__ */ jsx38("span", { className: "flex shrink-0 items-center", children: selected.leading }),
2706
- /* @__PURE__ */ jsx38(BaseSelect.Value, { className: "truncate", children: () => selected?.label ?? placeholder })
2780
+ selected?.leading && /* @__PURE__ */ jsx39("span", { className: "flex shrink-0 items-center", children: selected.leading }),
2781
+ /* @__PURE__ */ jsx39(BaseSelect.Value, { className: "truncate", children: () => selected?.label ?? placeholder })
2707
2782
  ] }),
2708
- /* @__PURE__ */ jsx38(
2783
+ /* @__PURE__ */ jsx39(
2709
2784
  BaseSelect.Icon,
2710
2785
  {
2711
- render: /* @__PURE__ */ jsx38(IconChevronDown3, { size: size === "small" ? 14 : 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
2786
+ render: /* @__PURE__ */ jsx39(IconChevronDown3, { size: size === "small" ? 14 : 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
2712
2787
  }
2713
2788
  )
2714
2789
  ]
@@ -2727,8 +2802,8 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
2727
2802
  disabled: disabled && !held,
2728
2803
  modal: false,
2729
2804
  children: [
2730
- held ? /* @__PURE__ */ jsx38(TooltipTrigger, { label: disabledReason ?? "", children: trigger }) : trigger,
2731
- /* @__PURE__ */ jsx38(BaseSelect.Portal, { children: /* @__PURE__ */ jsx38(
2805
+ held ? /* @__PURE__ */ jsx39(TooltipTrigger, { label: disabledReason ?? "", children: trigger }) : trigger,
2806
+ /* @__PURE__ */ jsx39(BaseSelect.Portal, { children: /* @__PURE__ */ jsx39(
2732
2807
  BaseSelect.Positioner,
2733
2808
  {
2734
2809
  side: "bottom",
@@ -2737,25 +2812,25 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
2737
2812
  collisionPadding: VIEWPORT_PAD4,
2738
2813
  alignItemWithTrigger: false,
2739
2814
  className: "z-50 data-[anchor-hidden]:hidden",
2740
- children: /* @__PURE__ */ jsx38(
2815
+ children: /* @__PURE__ */ jsx39(
2741
2816
  BaseSelect.Popup,
2742
2817
  {
2743
- render: /* @__PURE__ */ jsx38(MenuPanel, {}),
2818
+ render: /* @__PURE__ */ jsx39(MenuPanel, {}),
2744
2819
  className: "min-w-[var(--anchor-width)] p-0",
2745
- children: /* @__PURE__ */ jsx38(ScrollArea, { viewportClassName: "max-h-[min(288px,var(--available-height))]", contentClassName: "flex flex-col gap-0.5 p-2", children: options.map((option) => /* @__PURE__ */ jsxs29(
2820
+ children: /* @__PURE__ */ jsx39(ScrollArea, { viewportClassName: "max-h-[min(288px,var(--available-height))]", contentClassName: "flex flex-col gap-0.5 p-2", children: options.map((option) => /* @__PURE__ */ jsxs29(
2746
2821
  BaseSelect.Item,
2747
2822
  {
2748
2823
  value: option.value,
2749
2824
  className: cn(menuItemClassName({ size: "default" }), "justify-between data-[selected]:font-medium"),
2750
2825
  children: [
2751
2826
  /* @__PURE__ */ jsxs29("span", { className: "flex min-w-0 items-center gap-2", children: [
2752
- option.leading && /* @__PURE__ */ jsx38("span", { className: "flex shrink-0 items-center", children: option.leading }),
2753
- /* @__PURE__ */ jsx38(BaseSelect.ItemText, { className: "truncate text-body-2 text-text-primary", children: option.label })
2827
+ option.leading && /* @__PURE__ */ jsx39("span", { className: "flex shrink-0 items-center", children: option.leading }),
2828
+ /* @__PURE__ */ jsx39(BaseSelect.ItemText, { className: "truncate text-body-2 text-text-primary", children: option.label })
2754
2829
  ] }),
2755
- /* @__PURE__ */ jsx38(
2830
+ /* @__PURE__ */ jsx39(
2756
2831
  BaseSelect.ItemIndicator,
2757
2832
  {
2758
- render: /* @__PURE__ */ jsx38(IconCheck2, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
2833
+ render: /* @__PURE__ */ jsx39(IconCheck2, { size: 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
2759
2834
  }
2760
2835
  )
2761
2836
  ]
@@ -2774,9 +2849,9 @@ function Select({ value, onChange, options, size = "default", ariaLabel, placeho
2774
2849
  // src/TextInput.tsx
2775
2850
  import { forwardRef as forwardRef2 } from "react";
2776
2851
  import { Input } from "@base-ui/react/input";
2777
- import { jsx as jsx39 } from "react/jsx-runtime";
2852
+ import { jsx as jsx40 } from "react/jsx-runtime";
2778
2853
  var TextInput = forwardRef2(function TextInput2({ className, type = "text", size = "default", ...props }, ref) {
2779
- return /* @__PURE__ */ jsx39(
2854
+ return /* @__PURE__ */ jsx40(
2780
2855
  Input,
2781
2856
  {
2782
2857
  ref,
@@ -2802,13 +2877,13 @@ var TextInput = forwardRef2(function TextInput2({ className, type = "text", size
2802
2877
  // src/Textarea.tsx
2803
2878
  import { forwardRef as forwardRef3 } from "react";
2804
2879
  import { Field as BaseField3 } from "@base-ui/react/field";
2805
- import { jsx as jsx40 } from "react/jsx-runtime";
2880
+ import { jsx as jsx41 } from "react/jsx-runtime";
2806
2881
  var Textarea = forwardRef3(function Textarea2({ className, ...props }, ref) {
2807
- return /* @__PURE__ */ jsx40(
2882
+ return /* @__PURE__ */ jsx41(
2808
2883
  BaseField3.Control,
2809
2884
  {
2810
2885
  ref,
2811
- render: /* @__PURE__ */ jsx40("textarea", {}),
2886
+ render: /* @__PURE__ */ jsx41("textarea", {}),
2812
2887
  className: cn(
2813
2888
  // The border strengthens on hover, as Select's and ChipInput's do (Katerina, 16 September:
2814
2889
  // "aren't there hover states in text input and text area?"). Focus comes after hover in
@@ -2828,7 +2903,7 @@ var Textarea = forwardRef3(function Textarea2({ className, ...props }, ref) {
2828
2903
 
2829
2904
  // src/ConfirmDialog.tsx
2830
2905
  import { useState as useState6 } from "react";
2831
- import { Fragment as Fragment10, jsx as jsx41, jsxs as jsxs30 } from "react/jsx-runtime";
2906
+ import { Fragment as Fragment10, jsx as jsx42, jsxs as jsxs30 } from "react/jsx-runtime";
2832
2907
  function ConfirmDialog({ title, children, confirmLabel, destructive = false, onConfirm, onClose }) {
2833
2908
  const [busy, setBusy] = useState6(false);
2834
2909
  const confirm = async () => {
@@ -2840,32 +2915,32 @@ function ConfirmDialog({ title, children, confirmLabel, destructive = false, onC
2840
2915
  setBusy(false);
2841
2916
  }
2842
2917
  };
2843
- return /* @__PURE__ */ jsx41(
2918
+ return /* @__PURE__ */ jsx42(
2844
2919
  DialogShell,
2845
2920
  {
2846
2921
  alert: true,
2847
2922
  title,
2848
2923
  onClose,
2849
2924
  footer: /* @__PURE__ */ jsxs30(Fragment10, { children: [
2850
- /* @__PURE__ */ jsx41(Button, { variant: "muted", onClick: onClose, disabled: busy, children: "Cancel" }),
2851
- /* @__PURE__ */ jsx41(Button, { variant: destructive ? "destructive" : "primary", onClick: () => void confirm(), disabled: busy, children: confirmLabel })
2925
+ /* @__PURE__ */ jsx42(Button, { variant: "muted", onClick: onClose, disabled: busy, children: "Cancel" }),
2926
+ /* @__PURE__ */ jsx42(Button, { variant: destructive ? "destructive" : "primary", onClick: () => void confirm(), disabled: busy, children: confirmLabel })
2852
2927
  ] }),
2853
- children: /* @__PURE__ */ jsx41("div", { className: "flex flex-col gap-3 text-body-2 text-text-primary", children })
2928
+ children: /* @__PURE__ */ jsx42("div", { className: "flex flex-col gap-3 text-body-2 text-text-primary", children })
2854
2929
  }
2855
2930
  );
2856
2931
  }
2857
2932
 
2858
2933
  // src/EditableText.tsx
2859
- import { useEffect as useEffect4, useRef as useRef8, useState as useState7 } from "react";
2934
+ import { useEffect as useEffect5, useRef as useRef9, useState as useState7 } from "react";
2860
2935
  import { Field as BaseField4 } from "@base-ui/react/field";
2861
2936
  import { Input as Input2 } from "@base-ui/react/input";
2862
- import { jsx as jsx42 } from "react/jsx-runtime";
2937
+ import { jsx as jsx43 } from "react/jsx-runtime";
2863
2938
  function EditableText({ value, display, displayNode, placeholder, onCommit, multiline = false, className, label, readOnly = false }) {
2864
2939
  const [editing, setEditing] = useState7(false);
2865
2940
  const [draft, setDraft] = useState7(value);
2866
2941
  const [busy, setBusy] = useState7(false);
2867
- const fieldRef = useRef8(null);
2868
- useEffect4(() => {
2942
+ const fieldRef = useRef9(null);
2943
+ useEffect5(() => {
2869
2944
  if (editing) {
2870
2945
  fieldRef.current?.focus();
2871
2946
  fieldRef.current?.select();
@@ -2917,7 +2992,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
2917
2992
  written and never read. Read-only, this is a line of text: whatever
2918
2993
  names the region around it (a `Field`, a `Property`) names this too.
2919
2994
  */
2920
- /* @__PURE__ */ jsx42(
2995
+ /* @__PURE__ */ jsx43(
2921
2996
  "div",
2922
2997
  {
2923
2998
  className: cn("w-full px-2 py-1", multiline && !displayNode && "whitespace-pre-wrap", display ?? value ? "text-text-primary" : "text-text-muted", className),
@@ -2927,11 +3002,11 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
2927
3002
  );
2928
3003
  }
2929
3004
  if (editing) {
2930
- return multiline ? /* @__PURE__ */ jsx42(
3005
+ return multiline ? /* @__PURE__ */ jsx43(
2931
3006
  BaseField4.Control,
2932
3007
  {
2933
3008
  ref: fieldRef,
2934
- render: /* @__PURE__ */ jsx42("textarea", { rows: 4 }),
3009
+ render: /* @__PURE__ */ jsx43("textarea", { rows: 4 }),
2935
3010
  "aria-label": label,
2936
3011
  value: draft,
2937
3012
  disabled: busy,
@@ -2940,7 +3015,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
2940
3015
  onBlur: () => void commit(),
2941
3016
  className: fieldClass
2942
3017
  }
2943
- ) : /* @__PURE__ */ jsx42(
3018
+ ) : /* @__PURE__ */ jsx43(
2944
3019
  Input2,
2945
3020
  {
2946
3021
  ref: fieldRef,
@@ -2954,7 +3029,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
2954
3029
  }
2955
3030
  );
2956
3031
  }
2957
- return /* @__PURE__ */ jsx42(
3032
+ return /* @__PURE__ */ jsx43(
2958
3033
  "button",
2959
3034
  {
2960
3035
  type: "button",
@@ -2974,7 +3049,7 @@ function EditableText({ value, display, displayNode, placeholder, onCommit, mult
2974
3049
  // src/ErrorBoundary.tsx
2975
3050
  import { Component } from "react";
2976
3051
  import { IconAlertTriangle as IconAlertTriangle2 } from "@tabler/icons-react";
2977
- import { jsx as jsx43 } from "react/jsx-runtime";
3052
+ import { jsx as jsx44 } from "react/jsx-runtime";
2978
3053
  var ErrorBoundary = class extends Component {
2979
3054
  state = { hasError: false };
2980
3055
  static getDerivedStateFromError() {
@@ -2985,22 +3060,22 @@ var ErrorBoundary = class extends Component {
2985
3060
  }
2986
3061
  render() {
2987
3062
  if (!this.state.hasError) return this.props.children;
2988
- const message = /* @__PURE__ */ jsx43(
3063
+ const message = /* @__PURE__ */ jsx44(
2989
3064
  EmptyState,
2990
3065
  {
2991
- icon: /* @__PURE__ */ jsx43(IconAlertTriangle2, { size: 16, stroke: 1.5 }),
3066
+ icon: /* @__PURE__ */ jsx44(IconAlertTriangle2, { size: 16, stroke: 1.5 }),
2992
3067
  message: `Something went wrong${this.props.label ? ` in the ${this.props.label}` : ""}. Your data is safe \u2014 try again.`,
2993
3068
  action: { label: "Try again", onClick: () => this.setState({ hasError: false }) }
2994
3069
  }
2995
3070
  );
2996
3071
  if (this.props.frame) return this.props.frame(message);
2997
- return this.props.fallbackClassName ? /* @__PURE__ */ jsx43("div", { className: this.props.fallbackClassName, children: message }) : message;
3072
+ return this.props.fallbackClassName ? /* @__PURE__ */ jsx44("div", { className: this.props.fallbackClassName, children: message }) : message;
2998
3073
  }
2999
3074
  };
3000
3075
 
3001
3076
  // src/ProgressBar.tsx
3002
3077
  import { Progress } from "@base-ui/react/progress";
3003
- import { jsx as jsx44 } from "react/jsx-runtime";
3078
+ import { jsx as jsx45 } from "react/jsx-runtime";
3004
3079
  var TRACK_CLASSES = {
3005
3080
  default: "h-1.5 w-full overflow-hidden rounded-full bg-bg-inset",
3006
3081
  // 4px, Katerina's ruling of 14 September; Peek's own bar is 3px until it takes this one.
@@ -3013,16 +3088,16 @@ var INDICATOR_CLASSES = {
3013
3088
  function ProgressBar({ value, max, label, variant = "default", className }) {
3014
3089
  return (
3015
3090
  // `max={0}` needs no guard: Base UI reads the 0/0 share as an empty bar.
3016
- /* @__PURE__ */ jsx44(Progress.Root, { value, max, "aria-label": label, className, children: /* @__PURE__ */ jsx44(Progress.Track, { className: TRACK_CLASSES[variant], children: /* @__PURE__ */ jsx44(Progress.Indicator, { className: INDICATOR_CLASSES[variant] }) }) })
3091
+ /* @__PURE__ */ jsx45(Progress.Root, { value, max, "aria-label": label, className, children: /* @__PURE__ */ jsx45(Progress.Track, { className: TRACK_CLASSES[variant], children: /* @__PURE__ */ jsx45(Progress.Indicator, { className: INDICATOR_CLASSES[variant] }) }) })
3017
3092
  );
3018
3093
  }
3019
3094
 
3020
3095
  // src/Breadcrumb.tsx
3021
- import { Fragment as Fragment11, useCallback as useCallback3, useLayoutEffect as useLayoutEffect4, useRef as useRef9, useState as useState8 } from "react";
3022
- import { jsx as jsx45, jsxs as jsxs31 } from "react/jsx-runtime";
3096
+ import { Fragment as Fragment11, useCallback as useCallback3, useLayoutEffect as useLayoutEffect4, useRef as useRef10, useState as useState8 } from "react";
3097
+ import { jsx as jsx46, jsxs as jsxs31 } from "react/jsx-runtime";
3023
3098
  function Breadcrumb({ items, className }) {
3024
- const navRef = useRef9(null);
3025
- const labelRefs = useRef9([]);
3099
+ const navRef = useRef10(null);
3100
+ const labelRefs = useRef10([]);
3026
3101
  const [truncated, setTruncated] = useState8(/* @__PURE__ */ new Set());
3027
3102
  const measure = useCallback3(() => {
3028
3103
  const next = /* @__PURE__ */ new Set();
@@ -3039,7 +3114,7 @@ function Breadcrumb({ items, className }) {
3039
3114
  observer.observe(nav);
3040
3115
  return () => observer.disconnect();
3041
3116
  }, [measure, items]);
3042
- return /* @__PURE__ */ jsx45("nav", { ref: navRef, "aria-label": "Breadcrumb", className: cn("flex min-w-0 items-center gap-1.5 text-body-2", className), children: items.map((item, index) => {
3117
+ return /* @__PURE__ */ jsx46("nav", { ref: navRef, "aria-label": "Breadcrumb", className: cn("flex min-w-0 items-center gap-1.5 text-body-2", className), children: items.map((item, index) => {
3043
3118
  const last = index === items.length - 1;
3044
3119
  const tone = item.muted || last && item.mono ? "text-text-muted" : last ? "text-text-primary" : "text-text-secondary";
3045
3120
  const text = cn(
@@ -3060,16 +3135,16 @@ function Breadcrumb({ items, className }) {
3060
3135
  // on a box around it, which the link takes them from, rather than
3061
3136
  // pushed into it (UIG-9); the link is still the one element that
3062
3137
  // truncates and is measured.
3063
- /* @__PURE__ */ jsx45("span", { className: cn("flex min-w-0", item.mono && "shrink-0 font-mono text-caption", tone, "hover:text-text-primary"), children: /* @__PURE__ */ jsx45(Link, { ref: setLabelRef, variant: "plain", truncate: true, href: item.href, onClick: item.onClick, children: item.label }) })
3064
- ) : /* @__PURE__ */ jsx45("span", { ref: setLabelRef, className: text, "aria-current": last ? "page" : void 0, children: item.label });
3138
+ /* @__PURE__ */ jsx46("span", { className: cn("flex min-w-0", item.mono && "shrink-0 font-mono text-caption", tone, "hover:text-text-primary"), children: /* @__PURE__ */ jsx46(Link, { ref: setLabelRef, variant: "plain", truncate: true, href: item.href, onClick: item.onClick, children: item.label }) })
3139
+ ) : /* @__PURE__ */ jsx46("span", { ref: setLabelRef, className: text, "aria-current": last ? "page" : void 0, children: item.label });
3065
3140
  return /* @__PURE__ */ jsxs31(Fragment11, { children: [
3066
- index > 0 && /* @__PURE__ */ jsx45("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
3067
- item.icon && /* @__PURE__ */ jsx45("span", { "aria-hidden": "true", className: cn("flex shrink-0", tone), children: item.icon }),
3141
+ index > 0 && /* @__PURE__ */ jsx46("span", { "aria-hidden": "true", className: "shrink-0 text-text-muted", children: "/" }),
3142
+ item.icon && /* @__PURE__ */ jsx46("span", { "aria-hidden": "true", className: cn("flex shrink-0", tone), children: item.icon }),
3068
3143
  truncated.has(index) ? (
3069
3144
  // `min-w-0 shrink` undoes the wrapper's own shrink-0 — the crumb
3070
3145
  // must keep truncating inside it, or wrapping it would widen the
3071
3146
  // trail and the tooltip would never be needed again.
3072
- /* @__PURE__ */ jsx45(WithTooltip, { label: item.label, wrapperClassName: "min-w-0 shrink", children: crumb })
3147
+ /* @__PURE__ */ jsx46(WithTooltip, { label: item.label, wrapperClassName: "min-w-0 shrink", children: crumb })
3073
3148
  ) : crumb
3074
3149
  ] }, `${item.label}-${index}`);
3075
3150
  }) });
@@ -3081,13 +3156,13 @@ import { Collapsible } from "@base-ui/react/collapsible";
3081
3156
  import { IconAlertSquareRounded, IconChevronRight as IconChevronRight2, IconDotsVertical } from "@tabler/icons-react";
3082
3157
 
3083
3158
  // src/UnreadDot.tsx
3084
- import { jsx as jsx46 } from "react/jsx-runtime";
3159
+ import { jsx as jsx47 } from "react/jsx-runtime";
3085
3160
  function UnreadDot({ className }) {
3086
- return /* @__PURE__ */ jsx46("div", { className: cn("flex h-6 w-6 shrink-0 items-center justify-center", className), "data-unread": true, children: /* @__PURE__ */ jsx46("div", { className: "h-1.5 w-1.5 rounded-full bg-accent-primary" }) });
3161
+ return /* @__PURE__ */ jsx47("div", { className: cn("flex h-6 w-6 shrink-0 items-center justify-center", className), "data-unread": true, children: /* @__PURE__ */ jsx47("div", { className: "h-1.5 w-1.5 rounded-full bg-accent-primary" }) });
3087
3162
  }
3088
3163
 
3089
3164
  // src/NavItem.tsx
3090
- import { jsx as jsx47, jsxs as jsxs32 } from "react/jsx-runtime";
3165
+ import { jsx as jsx48, jsxs as jsxs32 } from "react/jsx-runtime";
3091
3166
  function NavItem({
3092
3167
  label,
3093
3168
  href,
@@ -3105,8 +3180,10 @@ function NavItem({
3105
3180
  open: openProp,
3106
3181
  onOpenChange,
3107
3182
  className,
3183
+ onClick,
3108
3184
  ...props
3109
3185
  }) {
3186
+ const inApp = useInAppClick(href, onClick);
3110
3187
  const [openState, setOpenState] = useState9(defaultOpen);
3111
3188
  const panelId = useId2();
3112
3189
  const hasRows = children != null && children !== false;
@@ -3116,7 +3193,7 @@ function NavItem({
3116
3193
  onOpenChange?.(next);
3117
3194
  };
3118
3195
  const besides = menu != null || hasRows;
3119
- const mark = unread ? urgent ? /* @__PURE__ */ jsx47(UrgentMark, {}) : /* @__PURE__ */ jsx47(UnreadDot, {}) : null;
3196
+ const mark = unread ? urgent ? /* @__PURE__ */ jsx48(UrgentMark, {}) : /* @__PURE__ */ jsx48(UnreadDot, {}) : null;
3120
3197
  const stepsAside = menu != null && "transition-opacity group-hover/nav:opacity-0 group-has-[:focus-visible]/nav:opacity-0 group-has-[[data-nav-menu]_[aria-expanded=true]]/nav:opacity-0 [@media(hover:none)]:opacity-0";
3121
3198
  const row = /* @__PURE__ */ jsxs32(
3122
3199
  "a",
@@ -3138,8 +3215,9 @@ function NavItem({
3138
3215
  className
3139
3216
  ),
3140
3217
  ...props,
3218
+ onClick: inApp,
3141
3219
  children: [
3142
- (icon || hasRows) && /* @__PURE__ */ jsx47(
3220
+ (icon || hasRows) && /* @__PURE__ */ jsx48(
3143
3221
  "span",
3144
3222
  {
3145
3223
  className: cn(
@@ -3150,10 +3228,10 @@ function NavItem({
3150
3228
  children: icon
3151
3229
  }
3152
3230
  ),
3153
- /* @__PURE__ */ jsx47("span", { className: cn("flex-1 truncate", unread && "font-medium"), children: label }),
3231
+ /* @__PURE__ */ jsx48("span", { className: cn("flex-1 truncate", unread && "font-medium"), children: label }),
3154
3232
  hint != null && // Takes room only while it shows, so the label gives way to it.
3155
- /* @__PURE__ */ jsx47("span", { className: "hidden shrink-0 items-center group-hover/nav:flex group-has-[:focus-visible]/nav:flex", children: hint }),
3156
- count ? /* @__PURE__ */ jsx47(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx47(
3233
+ /* @__PURE__ */ jsx48("span", { className: "hidden shrink-0 items-center group-hover/nav:flex group-has-[:focus-visible]/nav:flex", children: hint }),
3234
+ count ? /* @__PURE__ */ jsx48(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx48(
3157
3235
  "span",
3158
3236
  {
3159
3237
  className: cn(
@@ -3169,7 +3247,7 @@ function NavItem({
3169
3247
  // `-mr-1`: the 24px slot's dot then sits on the axis of a count and
3170
3248
  // of the ⋮ (8px from the edge to the 16px box), one column with a
3171
3249
  // folder heading's dot and ⋮ (Katerina, 5 October).
3172
- /* @__PURE__ */ jsx47("span", { className: cn("-mr-1 flex shrink-0", stepsAside), children: mark })
3250
+ /* @__PURE__ */ jsx48("span", { className: cn("-mr-1 flex shrink-0", stepsAside), children: mark })
3173
3251
  ) : menu != null && !count ? (
3174
3252
  // Nothing at the right, but a menu: no room is kept at rest, so the
3175
3253
  // label has the row's whole width; while the ⋮ shows, its 24px slot
@@ -3177,7 +3255,7 @@ function NavItem({
3177
3255
  // `-mr-1`: the ⋮ sits at `right-1`, 4px into the row's padding, so the
3178
3256
  // slot does too — at the padding's edge it kept 4px the ⋮ never
3179
3257
  // covers, and the label stopped 12px short of the button, not 8.
3180
- /* @__PURE__ */ jsx47("span", { "aria-hidden": "true", className: "-mr-1 hidden w-6 shrink-0 group-hover/nav:block group-has-[:focus-visible]/nav:block group-has-[[data-nav-menu]_[aria-expanded=true]]/nav:block [@media(hover:none)]:block" })
3258
+ /* @__PURE__ */ jsx48("span", { "aria-hidden": "true", className: "-mr-1 hidden w-6 shrink-0 group-hover/nav:block group-has-[:focus-visible]/nav:block group-has-[[data-nav-menu]_[aria-expanded=true]]/nav:block [@media(hover:none)]:block" })
3181
3259
  ) : null
3182
3260
  ]
3183
3261
  }
@@ -3188,7 +3266,7 @@ function NavItem({
3188
3266
  row,
3189
3267
  hasRows && // `left-1`: the 24px button's 16px arrow then sits where the icon
3190
3268
  // sits (the row's px-2), so the icon turns into the arrow in place.
3191
- /* @__PURE__ */ jsx47("div", { className: "absolute inset-y-0 left-1 flex items-center opacity-0 transition-opacity group-hover/nav:opacity-100 group-has-[:focus-visible]/nav:opacity-100", children: /* @__PURE__ */ jsx47(
3269
+ /* @__PURE__ */ jsx48("div", { className: "absolute inset-y-0 left-1 flex items-center opacity-0 transition-opacity group-hover/nav:opacity-100 group-has-[:focus-visible]/nav:opacity-100", children: /* @__PURE__ */ jsx48(
3192
3270
  IconButton,
3193
3271
  {
3194
3272
  tooltip: open ? "Collapse" : "Expand",
@@ -3196,7 +3274,7 @@ function NavItem({
3196
3274
  "aria-expanded": open,
3197
3275
  "aria-controls": panelId,
3198
3276
  onClick: () => setOpen(!open),
3199
- children: /* @__PURE__ */ jsx47(IconChevronRight2, { size: 16, stroke: 1.5, className: cn("transition-transform duration-150", open && "rotate-90") })
3277
+ children: /* @__PURE__ */ jsx48(IconChevronRight2, { size: 16, stroke: 1.5, className: cn("transition-transform duration-150", open && "rotate-90") })
3200
3278
  }
3201
3279
  ) }),
3202
3280
  menu != null && // `right-1`: the 24px button's 16px icon ends 8px from the row's
@@ -3207,11 +3285,11 @@ function NavItem({
3207
3285
  // right of the slot's centre.
3208
3286
  // On a screen with no hover it always shows: nothing there can point
3209
3287
  // at the row, and the menu has no other way in.
3210
- /* @__PURE__ */ jsx47("div", { "data-nav-menu": true, className: cn("absolute inset-y-0 right-1 flex items-center", "opacity-0 transition-opacity group-hover/nav:opacity-100 group-has-[:focus-visible]/nav:opacity-100 has-[[aria-expanded=true]]:opacity-100 [@media(hover:none)]:opacity-100"), children: /* @__PURE__ */ jsx47(
3288
+ /* @__PURE__ */ jsx48("div", { "data-nav-menu": true, className: cn("absolute inset-y-0 right-1 flex items-center", "opacity-0 transition-opacity group-hover/nav:opacity-100 group-has-[:focus-visible]/nav:opacity-100 has-[[aria-expanded=true]]:opacity-100 [@media(hover:none)]:opacity-100"), children: /* @__PURE__ */ jsx48(
3211
3289
  Menu,
3212
3290
  {
3213
3291
  align: "right",
3214
- trigger: /* @__PURE__ */ jsx47(IconButton, { tooltip: "More options", "aria-label": name, children: /* @__PURE__ */ jsx47(IconDotsVertical, { size: 16, stroke: 1.5 }) }),
3292
+ trigger: /* @__PURE__ */ jsx48(IconButton, { tooltip: "More options", "aria-label": name, children: /* @__PURE__ */ jsx48(IconDotsVertical, { size: 16, stroke: 1.5 }) }),
3215
3293
  children: menu
3216
3294
  }
3217
3295
  ) })
@@ -3219,23 +3297,23 @@ function NavItem({
3219
3297
  if (!hasRows) return line;
3220
3298
  return /* @__PURE__ */ jsxs32(Collapsible.Root, { open, onOpenChange: setOpen, className: "flex shrink-0 flex-col", children: [
3221
3299
  line,
3222
- /* @__PURE__ */ jsx47(
3300
+ /* @__PURE__ */ jsx48(
3223
3301
  Collapsible.Panel,
3224
3302
  {
3225
3303
  id: panelId,
3226
3304
  hiddenUntilFound: true,
3227
3305
  className: COLLAPSIBLE_PANEL_CLASSES,
3228
- children: /* @__PURE__ */ jsx47("div", { className: "flex flex-col gap-0.5 pt-0.5 pl-6", children })
3306
+ children: /* @__PURE__ */ jsx48("div", { className: "flex flex-col gap-0.5 pt-0.5 pl-6", children })
3229
3307
  }
3230
3308
  )
3231
3309
  ] });
3232
3310
  }
3233
3311
  function UrgentMark() {
3234
- return /* @__PURE__ */ jsx47("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center", "data-urgent": true, children: /* @__PURE__ */ jsx47("div", { className: "flex items-center rounded-full bg-warning-muted p-0.5 signal:shadow-glow-warning", children: /* @__PURE__ */ jsx47(IconAlertSquareRounded, { size: 12, stroke: 2.5, className: "text-warning-default" }) }) });
3312
+ return /* @__PURE__ */ jsx48("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center", "data-urgent": true, children: /* @__PURE__ */ jsx48("div", { className: "flex items-center rounded-full bg-warning-muted p-0.5 signal:shadow-glow-warning", children: /* @__PURE__ */ jsx48(IconAlertSquareRounded, { size: 12, stroke: 2.5, className: "text-warning-default" }) }) });
3235
3313
  }
3236
3314
 
3237
3315
  // src/NavTree.tsx
3238
- import { useEffect as useEffect5, useRef as useRef10 } from "react";
3316
+ import { useEffect as useEffect6, useRef as useRef11 } from "react";
3239
3317
 
3240
3318
  // src/CollapsibleSection.tsx
3241
3319
  import { useState as useState10 } from "react";
@@ -3244,14 +3322,14 @@ import { Collapsible as Collapsible2 } from "@base-ui/react/collapsible";
3244
3322
  // src/SectionHeader.tsx
3245
3323
  import { IconChevronRight as IconChevronRight3, IconDotsVertical as IconDotsVertical2 } from "@tabler/icons-react";
3246
3324
  import { useRender } from "@base-ui/react/use-render";
3247
- import { Fragment as Fragment12, jsx as jsx48, jsxs as jsxs33 } from "react/jsx-runtime";
3325
+ import { Fragment as Fragment12, jsx as jsx49, jsxs as jsxs33 } from "react/jsx-runtime";
3248
3326
  function SectionHeader({ title, chevron = false, icon, isExpanded = true, onToggle, trailing, count, actions, menu, menuLabel, showActions = "hover", hover = "fill", look = "heading", render, className }) {
3249
3327
  const row = look === "row";
3250
3328
  const acts = actions && actions.length > 0 || menu != null;
3251
3329
  const trailingClasses = !acts ? "has-[[data-unread]]:-mr-1" : showActions === "hover" && "has-[[data-unread]]:pointer-events-none has-[[data-unread]]:absolute has-[[data-unread]]:inset-y-0 has-[[data-unread]]:right-1 has-[[data-unread]]:w-6 has-[[data-unread]]:justify-center has-[[data-unread]]:transition-opacity group-hover:has-[[data-unread]]:opacity-0 group-has-[:focus-visible]:has-[[data-unread]]:opacity-0 group-has-[[data-section-menu]_[aria-expanded=true]]:has-[[data-unread]]:opacity-0 [@media(hover:none)]:has-[[data-unread]]:opacity-0";
3252
3330
  const reveal = showActions === "hover" && "opacity-0 transition-opacity group-hover:opacity-100 group-has-[:focus-visible]:opacity-100 has-[[aria-expanded=true]]:opacity-100 [@media(hover:none)]:opacity-100";
3253
3331
  const titleElement = useRender({
3254
- render: render ?? (chevron ? /* @__PURE__ */ jsx48("button", { type: "button", onClick: onToggle, "aria-expanded": isExpanded }) : /* @__PURE__ */ jsx48("span", {})),
3332
+ render: render ?? (chevron ? /* @__PURE__ */ jsx49("button", { type: "button", onClick: onToggle, "aria-expanded": isExpanded }) : /* @__PURE__ */ jsx49("span", {})),
3255
3333
  props: {
3256
3334
  // `text-left`: a button centres its text. `h-full` and `flex-1`: the
3257
3335
  // whole row up to the actions is the hit target, as it was when the
@@ -3260,8 +3338,8 @@ function SectionHeader({ title, chevron = false, icon, isExpanded = true, onTogg
3260
3338
  className: cn("flex h-full min-w-0 flex-1 items-center text-left", row || chevron || icon != null ? "gap-2" : "gap-1"),
3261
3339
  children: /* @__PURE__ */ jsxs33(Fragment12, { children: [
3262
3340
  icon != null ? /* @__PURE__ */ jsxs33("span", { className: "relative flex size-4 shrink-0 items-center justify-center text-text-secondary", children: [
3263
- /* @__PURE__ */ jsx48("span", { className: cn("flex", chevron && "transition-opacity group-hover:opacity-0 group-has-[:focus-visible]:opacity-0"), children: icon }),
3264
- chevron && /* @__PURE__ */ jsx48(
3341
+ /* @__PURE__ */ jsx49("span", { className: cn("flex", chevron && "transition-opacity group-hover:opacity-0 group-has-[:focus-visible]:opacity-0"), children: icon }),
3342
+ chevron && /* @__PURE__ */ jsx49(
3265
3343
  IconChevronRight3,
3266
3344
  {
3267
3345
  size: 16,
@@ -3269,7 +3347,7 @@ function SectionHeader({ title, chevron = false, icon, isExpanded = true, onTogg
3269
3347
  className: cn("absolute opacity-0 transition-[opacity,transform] duration-150 group-hover:opacity-100 group-has-[:focus-visible]:opacity-100", isExpanded && "rotate-90")
3270
3348
  }
3271
3349
  )
3272
- ] }) : chevron && /* @__PURE__ */ jsx48(
3350
+ ] }) : chevron && /* @__PURE__ */ jsx49(
3273
3351
  IconChevronRight3,
3274
3352
  {
3275
3353
  size: 16,
@@ -3277,11 +3355,11 @@ function SectionHeader({ title, chevron = false, icon, isExpanded = true, onTogg
3277
3355
  className: cn("shrink-0 transition-transform duration-150", !row && "text-text-secondary", isExpanded && "rotate-90")
3278
3356
  }
3279
3357
  ),
3280
- look === "quiet" ? /* @__PURE__ */ jsx48("span", { className: "min-w-0 truncate text-caption text-text-muted", children: title }) : row ? (
3358
+ look === "quiet" ? /* @__PURE__ */ jsx49("span", { className: "min-w-0 truncate text-caption text-text-muted", children: title }) : row ? (
3281
3359
  // A row's words: NavItem's size and colour, brightening under the pointer with the row.
3282
- /* @__PURE__ */ jsx48("span", { className: "min-w-0 flex-1 truncate text-body-2", children: title })
3283
- ) : /* @__PURE__ */ jsx48(SectionLabel, { folds: chevron, children: title }),
3284
- count != null && /* @__PURE__ */ jsx48("span", { className: cn("ml-1 shrink-0", COUNT_TEXT_CLASSES), children: count })
3360
+ /* @__PURE__ */ jsx49("span", { className: "min-w-0 flex-1 truncate text-body-2", children: title })
3361
+ ) : /* @__PURE__ */ jsx49(SectionLabel, { folds: chevron, children: title }),
3362
+ count != null && /* @__PURE__ */ jsx49("span", { className: cn("ml-1 shrink-0", COUNT_TEXT_CLASSES), children: count })
3285
3363
  ] })
3286
3364
  }
3287
3365
  });
@@ -3306,18 +3384,18 @@ function SectionHeader({ title, chevron = false, icon, isExpanded = true, onTogg
3306
3384
  ),
3307
3385
  children: [
3308
3386
  titleElement,
3309
- trailing != null && /* @__PURE__ */ jsx48("div", { className: cn("flex shrink-0 items-center", trailingClasses), children: trailing }),
3310
- acts && /* @__PURE__ */ jsx48(
3387
+ trailing != null && /* @__PURE__ */ jsx49("div", { className: cn("flex shrink-0 items-center", trailingClasses), children: trailing }),
3388
+ acts && /* @__PURE__ */ jsx49(
3311
3389
  "div",
3312
3390
  {
3313
3391
  className: "-mr-1 flex shrink-0 items-center",
3314
3392
  children: /* @__PURE__ */ jsxs33("div", { className: cn("flex items-center gap-1", reveal), children: [
3315
- actions?.map((action) => /* @__PURE__ */ jsx48(IconButton, { tooltip: action.tooltip, "aria-label": action.tooltip, onClick: action.onClick, children: action.icon }, action.tooltip)),
3316
- menu != null && /* @__PURE__ */ jsx48("div", { "data-section-menu": true, className: "flex items-center", children: /* @__PURE__ */ jsx48(
3393
+ actions?.map((action) => /* @__PURE__ */ jsx49(IconButton, { tooltip: action.tooltip, "aria-label": action.tooltip, onClick: action.onClick, children: action.icon }, action.tooltip)),
3394
+ menu != null && /* @__PURE__ */ jsx49("div", { "data-section-menu": true, className: "flex items-center", children: /* @__PURE__ */ jsx49(
3317
3395
  Menu,
3318
3396
  {
3319
3397
  align: "right",
3320
- trigger: /* @__PURE__ */ jsx48(IconButton, { tooltip: "More options", "aria-label": menuLabel ?? `More options for ${title}`, children: /* @__PURE__ */ jsx48(IconDotsVertical2, { size: 16, stroke: 1.5 }) }),
3398
+ trigger: /* @__PURE__ */ jsx49(IconButton, { tooltip: "More options", "aria-label": menuLabel ?? `More options for ${title}`, children: /* @__PURE__ */ jsx49(IconDotsVertical2, { size: 16, stroke: 1.5 }) }),
3321
3399
  children: menu
3322
3400
  }
3323
3401
  ) })
@@ -3330,7 +3408,7 @@ function SectionHeader({ title, chevron = false, icon, isExpanded = true, onTogg
3330
3408
  }
3331
3409
 
3332
3410
  // src/CollapsibleSection.tsx
3333
- import { jsx as jsx49, jsxs as jsxs34 } from "react/jsx-runtime";
3411
+ import { jsx as jsx50, jsxs as jsxs34 } from "react/jsx-runtime";
3334
3412
  var OPEN = "open";
3335
3413
  var CLOSED = "closed";
3336
3414
  function readStored(key) {
@@ -3358,30 +3436,30 @@ function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenC
3358
3436
  onOpenChange?.(next);
3359
3437
  };
3360
3438
  return /* @__PURE__ */ jsxs34(Collapsible2.Root, { open, onOpenChange: setOpen, className: cn("flex flex-col", className), children: [
3361
- /* @__PURE__ */ jsx49(SectionHeader, { title, chevron: true, icon, isExpanded: open, trailing, actions, menu, menuLabel, showActions, look, className: "shrink-0", render: /* @__PURE__ */ jsx49(Collapsible2.Trigger, {}) }),
3362
- /* @__PURE__ */ jsx49(
3439
+ /* @__PURE__ */ jsx50(SectionHeader, { title, chevron: true, icon, isExpanded: open, trailing, actions, menu, menuLabel, showActions, look, className: "shrink-0", render: /* @__PURE__ */ jsx50(Collapsible2.Trigger, {}) }),
3440
+ /* @__PURE__ */ jsx50(
3363
3441
  Collapsible2.Panel,
3364
3442
  {
3365
3443
  hiddenUntilFound: true,
3366
3444
  className: COLLAPSIBLE_PANEL_CLASSES,
3367
- children: /* @__PURE__ */ jsx49("div", { className: cn("flex flex-col pt-0.5", (look === "row" || indent) && "pl-6", contentClassName), children })
3445
+ children: /* @__PURE__ */ jsx50("div", { className: cn("flex flex-col pt-0.5", (look === "row" || indent) && "pl-6", contentClassName), children })
3368
3446
  }
3369
3447
  )
3370
3448
  ] });
3371
3449
  }
3372
3450
 
3373
3451
  // src/NavTree.tsx
3374
- import { Fragment as Fragment13, jsx as jsx50, jsxs as jsxs35 } from "react/jsx-runtime";
3452
+ import { Fragment as Fragment13, jsx as jsx51, jsxs as jsxs35 } from "react/jsx-runtime";
3375
3453
  var NAV_TREE_INTENT_MS = 150;
3376
3454
  function holds(nodes, id) {
3377
3455
  return !!nodes && id !== void 0 && nodes.some((node) => node.id === id || holds(node.children ?? null, id));
3378
3456
  }
3379
3457
  function Line({ message }) {
3380
- return /* @__PURE__ */ jsx50("div", { className: "px-2 py-1", children: /* @__PURE__ */ jsx50(EmptyState, { scope: "section", message }) });
3458
+ return /* @__PURE__ */ jsx51("div", { className: "px-2 py-1", children: /* @__PURE__ */ jsx51(EmptyState, { scope: "section", message }) });
3381
3459
  }
3382
3460
  function Row({ node, selected, onSelect }) {
3383
- const under = node.childrenMessage !== void 0 ? /* @__PURE__ */ jsx50(Line, { message: node.childrenMessage }) : node.children?.length ? node.children.map((child) => /* @__PURE__ */ jsx50(Row, { node: child, selected, onSelect }, child.id)) : node.children === null || node.hasChildren && node.children === void 0 ? /* @__PURE__ */ jsx50(SkeletonList, { rows: 2 }) : void 0;
3384
- return /* @__PURE__ */ jsx50(
3461
+ const under = node.childrenMessage !== void 0 ? /* @__PURE__ */ jsx51(Line, { message: node.childrenMessage }) : node.children?.length ? node.children.map((child) => /* @__PURE__ */ jsx51(Row, { node: child, selected, onSelect }, child.id)) : node.children === null || node.hasChildren && node.children === void 0 ? /* @__PURE__ */ jsx51(SkeletonList, { rows: 2 }) : void 0;
3462
+ return /* @__PURE__ */ jsx51(
3385
3463
  NavItem,
3386
3464
  {
3387
3465
  href: node.href,
@@ -3403,7 +3481,7 @@ function Row({ node, selected, onSelect }) {
3403
3481
  );
3404
3482
  }
3405
3483
  function Group({ group, selected, onSelect, storageKey }) {
3406
- return /* @__PURE__ */ jsx50(
3484
+ return /* @__PURE__ */ jsx51(
3407
3485
  NavTreeSection,
3408
3486
  {
3409
3487
  id: group.id,
@@ -3419,15 +3497,15 @@ function Group({ group, selected, onSelect, storageKey }) {
3419
3497
  onOpenChange: group.onOpenChange,
3420
3498
  storageKey: storageKey ? `${storageKey}.${group.id}` : void 0,
3421
3499
  onIntent: group.onIntent,
3422
- children: group.nodes?.map((node) => /* @__PURE__ */ jsx50(Row, { node, selected, onSelect }, node.id))
3500
+ children: group.nodes?.map((node) => /* @__PURE__ */ jsx51(Row, { node, selected, onSelect }, node.id))
3423
3501
  }
3424
3502
  );
3425
3503
  }
3426
3504
  function NavTreeSection({ id, title, message, loading = false, trailing, actions, menu, icon, defaultOpen = true, open, onOpenChange, storageKey, onIntent, children }) {
3427
- const timer = useRef10(void 0);
3428
- useEffect5(() => () => clearTimeout(timer.current), []);
3505
+ const timer = useRef11(void 0);
3506
+ useEffect6(() => () => clearTimeout(timer.current), []);
3429
3507
  const intent = onIntent;
3430
- return /* @__PURE__ */ jsx50(
3508
+ return /* @__PURE__ */ jsx51(
3431
3509
  "div",
3432
3510
  {
3433
3511
  className: "shrink-0 [&+&]:mt-1",
@@ -3438,7 +3516,7 @@ function NavTreeSection({ id, title, message, loading = false, trailing, actions
3438
3516
  } : void 0,
3439
3517
  onPointerLeave: intent ? () => clearTimeout(timer.current) : void 0,
3440
3518
  onFocus: intent,
3441
- children: /* @__PURE__ */ jsx50(
3519
+ children: /* @__PURE__ */ jsx51(
3442
3520
  CollapsibleSection,
3443
3521
  {
3444
3522
  title,
@@ -3453,7 +3531,7 @@ function NavTreeSection({ id, title, message, loading = false, trailing, actions
3453
3531
  icon,
3454
3532
  className: "shrink-0",
3455
3533
  contentClassName: "gap-0.5",
3456
- children: message !== void 0 ? /* @__PURE__ */ jsx50(Line, { message }) : loading ? /* @__PURE__ */ jsx50(SkeletonList, { rows: 3 }) : children
3534
+ children: message !== void 0 ? /* @__PURE__ */ jsx51(Line, { message }) : loading ? /* @__PURE__ */ jsx51(SkeletonList, { rows: 3 }) : children
3457
3535
  }
3458
3536
  )
3459
3537
  }
@@ -3461,22 +3539,22 @@ function NavTreeSection({ id, title, message, loading = false, trailing, actions
3461
3539
  }
3462
3540
  function NavTree({ title, titleActions, groups, children, selected, onSelect, emptyMessage = "", storageKey }) {
3463
3541
  return /* @__PURE__ */ jsxs35(Fragment13, { children: [
3464
- title && /* @__PURE__ */ jsx50(SectionHeader, { title, look: "quiet", showActions: "always", actions: titleActions, className: "mt-4 shrink-0" }),
3465
- groups === void 0 ? children : groups === null ? /* @__PURE__ */ jsx50(SkeletonList, { rows: 5 }) : groups.length === 0 ? (
3542
+ title && /* @__PURE__ */ jsx51(SectionHeader, { title, look: "quiet", showActions: "always", actions: titleActions, className: "mt-4 shrink-0" }),
3543
+ groups === void 0 ? children : groups === null ? /* @__PURE__ */ jsx51(SkeletonList, { rows: 5 }) : groups.length === 0 ? (
3466
3544
  // No words, no line: an app that says nothing when it has no groups.
3467
- emptyMessage ? /* @__PURE__ */ jsx50(Line, { message: emptyMessage }) : null
3468
- ) : groups.map((group) => /* @__PURE__ */ jsx50(Group, { group, selected, onSelect, storageKey }, group.id))
3545
+ emptyMessage ? /* @__PURE__ */ jsx51(Line, { message: emptyMessage }) : null
3546
+ ) : groups.map((group) => /* @__PURE__ */ jsx51(Group, { group, selected, onSelect, storageKey }, group.id))
3469
3547
  ] });
3470
3548
  }
3471
3549
 
3472
3550
  // src/Popover.tsx
3473
- import { useMemo as useMemo3 } from "react";
3551
+ import { useMemo as useMemo4 } from "react";
3474
3552
  import { Popover as BasePopover } from "@base-ui/react/popover";
3475
- import { jsx as jsx51, jsxs as jsxs36 } from "react/jsx-runtime";
3553
+ import { jsx as jsx52, jsxs as jsxs36 } from "react/jsx-runtime";
3476
3554
  var GAP5 = 4;
3477
3555
  var VIEWPORT_PAD5 = 8;
3478
3556
  function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpenChange, finalFocus, actionsRef, ariaLabel, children, className, contentClassName, maxHeight }) {
3479
- const anchorTarget = useMemo3(() => {
3557
+ const anchorTarget = useMemo4(() => {
3480
3558
  if (!anchor) return void 0;
3481
3559
  if (anchor instanceof Element) return anchor;
3482
3560
  return { getBoundingClientRect: () => anchor };
@@ -3489,8 +3567,8 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
3489
3567
  actionsRef,
3490
3568
  modal: false,
3491
3569
  children: [
3492
- trigger && /* @__PURE__ */ jsx51(BasePopover.Trigger, { render: trigger, disabled: triggerDisabled(trigger) }),
3493
- /* @__PURE__ */ jsx51(BasePopover.Portal, { children: /* @__PURE__ */ jsx51(
3570
+ trigger && /* @__PURE__ */ jsx52(BasePopover.Trigger, { render: trigger, disabled: triggerDisabled(trigger) }),
3571
+ /* @__PURE__ */ jsx52(BasePopover.Portal, { children: /* @__PURE__ */ jsx52(
3494
3572
  BasePopover.Positioner,
3495
3573
  {
3496
3574
  anchor: anchorTarget,
@@ -3499,20 +3577,20 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
3499
3577
  sideOffset: GAP5,
3500
3578
  collisionPadding: VIEWPORT_PAD5,
3501
3579
  className: "z-50 data-[anchor-hidden]:hidden",
3502
- children: /* @__PURE__ */ jsx51(
3580
+ children: /* @__PURE__ */ jsx52(
3503
3581
  BasePopover.Popup,
3504
3582
  {
3505
3583
  "aria-label": ariaLabel,
3506
3584
  initialFocus: trigger ? void 0 : false,
3507
3585
  finalFocus,
3508
3586
  className: cn("min-w-[180px] outline-none p-0", className),
3509
- render: /* @__PURE__ */ jsx51(MenuPanel, {}),
3510
- children: /* @__PURE__ */ jsx51(
3587
+ render: /* @__PURE__ */ jsx52(MenuPanel, {}),
3588
+ children: /* @__PURE__ */ jsx52(
3511
3589
  ScrollArea,
3512
3590
  {
3513
3591
  viewportClassName: maxHeight ?? "max-h-[var(--available-height)]",
3514
3592
  contentClassName: cn("flex flex-col p-2", contentClassName),
3515
- children: /* @__PURE__ */ jsx51(DividerInPanel.Provider, { value: true, children })
3593
+ children: /* @__PURE__ */ jsx52(DividerInPanel.Provider, { value: true, children })
3516
3594
  }
3517
3595
  )
3518
3596
  }
@@ -3525,18 +3603,18 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
3525
3603
  }
3526
3604
 
3527
3605
  // src/SuggestionMenu.tsx
3528
- import { useCallback as useCallback4, useEffect as useEffect6, useId as useId3, useImperativeHandle, useMemo as useMemo4, useRef as useRef11, useState as useState11 } from "react";
3529
- import { jsx as jsx52, jsxs as jsxs37 } from "react/jsx-runtime";
3606
+ import { useCallback as useCallback4, useEffect as useEffect7, useId as useId3, useImperativeHandle, useMemo as useMemo5, useRef as useRef12, useState as useState11 } from "react";
3607
+ import { jsx as jsx53, jsxs as jsxs37 } from "react/jsx-runtime";
3530
3608
  function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sections, itemKey, row, onSelect, handle }) {
3531
- const shown = useMemo4(() => sections.filter((section) => section.items.length > 0), [sections]);
3532
- const items = useMemo4(() => shown.flatMap((section) => section.items), [shown]);
3609
+ const shown = useMemo5(() => sections.filter((section) => section.items.length > 0), [sections]);
3610
+ const items = useMemo5(() => shown.flatMap((section) => section.items), [shown]);
3533
3611
  const keys = items.map(itemKey).join("\n");
3534
3612
  const [highlight, setHighlight] = useState11(0);
3535
3613
  const base = useId3();
3536
3614
  const listboxId = `${base}-list`;
3537
- const chosen = useRef11(null);
3538
- useEffect6(() => void (chosen.current = highlight > 0 ? keys.split("\n")[highlight] ?? null : null), [highlight]);
3539
- useEffect6(() => {
3615
+ const chosen = useRef12(null);
3616
+ useEffect7(() => void (chosen.current = highlight > 0 ? keys.split("\n")[highlight] ?? null : null), [highlight]);
3617
+ useEffect7(() => {
3540
3618
  const at = chosen.current ? keys.split("\n").indexOf(chosen.current) : -1;
3541
3619
  setHighlight(at > 0 ? at : 0);
3542
3620
  }, [keys]);
@@ -3561,7 +3639,7 @@ function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sect
3561
3639
  }
3562
3640
  }), [items, highlight, onSelect]);
3563
3641
  const open = rect !== null && items.length > 0;
3564
- useEffect6(() => {
3642
+ useEffect7(() => {
3565
3643
  if (!editorElement || !open) return;
3566
3644
  editorElement.setAttribute("aria-autocomplete", "list");
3567
3645
  editorElement.setAttribute("aria-haspopup", "listbox");
@@ -3570,7 +3648,7 @@ function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sect
3570
3648
  for (const name of ["aria-autocomplete", "aria-haspopup", "aria-controls", "aria-activedescendant"]) editorElement.removeAttribute(name);
3571
3649
  };
3572
3650
  }, [editorElement, open, listboxId]);
3573
- useEffect6(() => {
3651
+ useEffect7(() => {
3574
3652
  if (!editorElement || !open) return;
3575
3653
  editorElement.setAttribute("aria-activedescendant", `${base}-${highlight}`);
3576
3654
  }, [editorElement, open, base, highlight]);
@@ -3591,7 +3669,7 @@ function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sect
3591
3669
  const { label, description, leading, shortcut, hint, size } = row(item);
3592
3670
  return (
3593
3671
  // A row of a list the editor drives from its caret: focus stays in the text, so the row is no Tab stop.
3594
- /* @__PURE__ */ jsx52(
3672
+ /* @__PURE__ */ jsx53(
3595
3673
  MenuItem,
3596
3674
  {
3597
3675
  role: "option",
@@ -3618,19 +3696,19 @@ function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sect
3618
3696
  };
3619
3697
  return (
3620
3698
  // finalFocus={false}: focus never left the text, and a list that closes because focus moved elsewhere must not pull it back (71a4577b).
3621
- /* @__PURE__ */ jsx52(Popover, { anchor: rect, open: rect !== null, side: "top", align: "left", className: width, maxHeight, ariaLabel, finalFocus: false, children: /* @__PURE__ */ jsx52("div", { ref: keepFocus, id: listboxId, role: "listbox", "aria-label": ariaLabel, className: "flex flex-col gap-0.5", children: shown.map((section, i) => /* @__PURE__ */ jsxs37("div", { className: "contents", children: [
3622
- i > 0 && /* @__PURE__ */ jsx52(MenuSeparator, {}),
3623
- section.label ? /* @__PURE__ */ jsx52("div", { role: "group", "aria-label": section.label, children: /* @__PURE__ */ jsx52(MenuSection, { label: section.label, className: section.className, children: section.items.map(drawRow) }) }) : section.items.map(drawRow)
3699
+ /* @__PURE__ */ jsx53(Popover, { anchor: rect, open: rect !== null, side: "top", align: "left", className: width, maxHeight, ariaLabel, finalFocus: false, children: /* @__PURE__ */ jsx53("div", { ref: keepFocus, id: listboxId, role: "listbox", "aria-label": ariaLabel, className: "flex flex-col gap-0.5", children: shown.map((section, i) => /* @__PURE__ */ jsxs37("div", { className: "contents", children: [
3700
+ i > 0 && /* @__PURE__ */ jsx53(MenuSeparator, {}),
3701
+ section.label ? /* @__PURE__ */ jsx53("div", { role: "group", "aria-label": section.label, children: /* @__PURE__ */ jsx53(MenuSection, { label: section.label, className: section.className, children: section.items.map(drawRow) }) }) : section.items.map(drawRow)
3624
3702
  ] }, section.label ?? i)) }) })
3625
3703
  );
3626
3704
  }
3627
3705
 
3628
3706
  // src/ShowMore.tsx
3629
- import { useLayoutEffect as useLayoutEffect5, useRef as useRef12, useState as useState12 } from "react";
3630
- import { jsx as jsx53, jsxs as jsxs38 } from "react/jsx-runtime";
3707
+ import { useLayoutEffect as useLayoutEffect5, useRef as useRef13, useState as useState12 } from "react";
3708
+ import { jsx as jsx54, jsxs as jsxs38 } from "react/jsx-runtime";
3631
3709
  var FADE_CLASSES = { surface: "from-bg-surface", inset: "from-bg-inset" };
3632
3710
  function ShowMore({ children, maxHeight = 96, surface = "surface", className }) {
3633
- const box = useRef12(null);
3711
+ const box = useRef13(null);
3634
3712
  const [open, setOpen] = useState12(false);
3635
3713
  const [overflows, setOverflows] = useState12(false);
3636
3714
  useLayoutEffect5(() => {
@@ -3647,18 +3725,18 @@ function ShowMore({ children, maxHeight = 96, surface = "surface", className })
3647
3725
  return /* @__PURE__ */ jsxs38("div", { className: cn("flex flex-col items-start", className), children: [
3648
3726
  /* @__PURE__ */ jsxs38("div", { ref: box, className: cn("relative w-full", cut && "overflow-hidden"), style: cut ? { maxHeight } : void 0, onFocus: cut ? () => setOpen(true) : void 0, children: [
3649
3727
  children,
3650
- cut && /* @__PURE__ */ jsx53("div", { "aria-hidden": true, className: cn("pointer-events-none absolute inset-x-0 bottom-0 h-10 bg-gradient-to-t to-transparent", FADE_CLASSES[surface]) })
3728
+ cut && /* @__PURE__ */ jsx54("div", { "aria-hidden": true, className: cn("pointer-events-none absolute inset-x-0 bottom-0 h-10 bg-gradient-to-t to-transparent", FADE_CLASSES[surface]) })
3651
3729
  ] }),
3652
3730
  overflows && // `-ml-1.5`: the small button's own 6px inset, so its words start where the content's do.
3653
- /* @__PURE__ */ jsx53(Button, { variant: "muted", size: "small", className: "-ml-1.5 mt-1", "aria-expanded": open, onClick: () => setOpen((o) => !o), children: open ? "Show less" : "Show more" })
3731
+ /* @__PURE__ */ jsx54(Button, { variant: "muted", size: "small", className: "-ml-1.5 mt-1", "aria-expanded": open, onClick: () => setOpen((o) => !o), children: open ? "Show less" : "Show more" })
3654
3732
  ] });
3655
3733
  }
3656
3734
 
3657
3735
  // src/Toolbar.tsx
3658
3736
  import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar";
3659
- import { jsx as jsx54 } from "react/jsx-runtime";
3737
+ import { jsx as jsx55 } from "react/jsx-runtime";
3660
3738
  function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocus = true, surface = true, children, className }) {
3661
- const strip = /* @__PURE__ */ jsx54(
3739
+ const strip = /* @__PURE__ */ jsx55(
3662
3740
  BaseToolbar.Root,
3663
3741
  {
3664
3742
  "aria-label": ariaLabel,
@@ -3669,27 +3747,27 @@ function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocu
3669
3747
  }
3670
3748
  );
3671
3749
  if (!surface) return strip;
3672
- return /* @__PURE__ */ jsx54(MenuPanel, { className: "w-fit p-1", children: strip });
3750
+ return /* @__PURE__ */ jsx55(MenuPanel, { className: "w-fit p-1", children: strip });
3673
3751
  }
3674
3752
  function ToolbarButton({ ref, disabled, disabledReason, ...props }) {
3675
- return /* @__PURE__ */ jsx54(
3753
+ return /* @__PURE__ */ jsx55(
3676
3754
  BaseToolbar.Button,
3677
3755
  {
3678
3756
  ref,
3679
3757
  disabled: disabled || !!disabledReason,
3680
3758
  focusableWhenDisabled: true,
3681
- render: /* @__PURE__ */ jsx54(IconButton, { disabled, disabledReason, ...props })
3759
+ render: /* @__PURE__ */ jsx55(IconButton, { disabled, disabledReason, ...props })
3682
3760
  }
3683
3761
  );
3684
3762
  }
3685
3763
  function ToolbarLink({ ref, href, ...props }) {
3686
- return /* @__PURE__ */ jsx54(BaseToolbar.Link, { ref, render: /* @__PURE__ */ jsx54(IconButton, { href, ...props }) });
3764
+ return /* @__PURE__ */ jsx55(BaseToolbar.Link, { ref, render: /* @__PURE__ */ jsx55(IconButton, { href, ...props }) });
3687
3765
  }
3688
3766
  function ToolbarInput({ size, ...props }) {
3689
- return /* @__PURE__ */ jsx54(BaseToolbar.Input, { render: /* @__PURE__ */ jsx54(TextInput, { size }), ...props });
3767
+ return /* @__PURE__ */ jsx55(BaseToolbar.Input, { render: /* @__PURE__ */ jsx55(TextInput, { size }), ...props });
3690
3768
  }
3691
3769
  function ToolbarSeparator({ className }) {
3692
- return /* @__PURE__ */ jsx54(
3770
+ return /* @__PURE__ */ jsx55(
3693
3771
  BaseToolbar.Separator,
3694
3772
  {
3695
3773
  orientation: "vertical",
@@ -3699,9 +3777,9 @@ function ToolbarSeparator({ className }) {
3699
3777
  }
3700
3778
 
3701
3779
  // src/ReactionPicker.tsx
3702
- import { jsx as jsx55 } from "react/jsx-runtime";
3780
+ import { jsx as jsx56 } from "react/jsx-runtime";
3703
3781
  function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reactions", surface = true, className }) {
3704
- return /* @__PURE__ */ jsx55(Toolbar, { "aria-label": ariaLabel, surface, className: cn("gap-0.5", className), children: options.map((option) => (
3782
+ return /* @__PURE__ */ jsx56(Toolbar, { "aria-label": ariaLabel, surface, className: cn("gap-0.5", className), children: options.map((option) => (
3705
3783
  /*
3706
3784
  A `ToolbarButton`, not a button in a tooltip wrapper. The wrapper
3707
3785
  would become the toolbar's item and the button inside it would never
@@ -3711,14 +3789,14 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
3711
3789
  The tooltip names it for a pointer, `aria-label` for everything else,
3712
3790
  and both say the meaning rather than the glyph.
3713
3791
  */
3714
- /* @__PURE__ */ jsx55(
3792
+ /* @__PURE__ */ jsx56(
3715
3793
  ToolbarButton,
3716
3794
  {
3717
3795
  "aria-label": option.label,
3718
3796
  tooltip: option.label,
3719
3797
  onClick: () => onSelect(option.emoji),
3720
3798
  className: "size-7",
3721
- children: /* @__PURE__ */ jsx55("span", { "aria-hidden": "true", className: "text-h3 leading-none", children: option.emoji })
3799
+ children: /* @__PURE__ */ jsx56("span", { "aria-hidden": "true", className: "text-h3 leading-none", children: option.emoji })
3722
3800
  },
3723
3801
  option.emoji
3724
3802
  )
@@ -3727,23 +3805,23 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
3727
3805
 
3728
3806
  // src/PreviewCard.tsx
3729
3807
  import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card";
3730
- import { jsx as jsx56, jsxs as jsxs39 } from "react/jsx-runtime";
3808
+ import { jsx as jsx57, jsxs as jsxs39 } from "react/jsx-runtime";
3731
3809
  var GAP6 = 12;
3732
3810
  var VIEWPORT_PAD6 = 8;
3733
3811
  var OPEN_DELAY2 = 350;
3734
3812
  var CLOSE_DELAY = 200;
3735
3813
  function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, closeDelay = CLOSE_DELAY, className, contentClassName, wrapperClassName }) {
3736
3814
  return /* @__PURE__ */ jsxs39(BasePreviewCard.Root, { children: [
3737
- /* @__PURE__ */ jsx56(
3815
+ /* @__PURE__ */ jsx57(
3738
3816
  BasePreviewCard.Trigger,
3739
3817
  {
3740
3818
  delay,
3741
3819
  closeDelay,
3742
- render: /* @__PURE__ */ jsx56("span", { className: cn("inline-flex", wrapperClassName) }),
3820
+ render: /* @__PURE__ */ jsx57("span", { className: cn("inline-flex", wrapperClassName) }),
3743
3821
  children
3744
3822
  }
3745
3823
  ),
3746
- /* @__PURE__ */ jsx56(BasePreviewCard.Portal, { children: /* @__PURE__ */ jsx56(
3824
+ /* @__PURE__ */ jsx57(BasePreviewCard.Portal, { children: /* @__PURE__ */ jsx57(
3747
3825
  BasePreviewCard.Positioner,
3748
3826
  {
3749
3827
  side,
@@ -3751,12 +3829,12 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
3751
3829
  sideOffset: GAP6,
3752
3830
  collisionPadding: VIEWPORT_PAD6,
3753
3831
  className: "z-50 data-[anchor-hidden]:hidden",
3754
- children: /* @__PURE__ */ jsx56(
3832
+ children: /* @__PURE__ */ jsx57(
3755
3833
  BasePreviewCard.Popup,
3756
3834
  {
3757
3835
  className: cn("w-[360px] p-0 outline-none", className),
3758
- render: /* @__PURE__ */ jsx56(MenuPanel, {}),
3759
- children: /* @__PURE__ */ jsx56(ScrollArea, { viewportClassName: "max-h-[min(300px,var(--available-height))]", contentClassName: cn("flex flex-col gap-3 p-3", contentClassName), children: content })
3836
+ render: /* @__PURE__ */ jsx57(MenuPanel, {}),
3837
+ children: /* @__PURE__ */ jsx57(ScrollArea, { viewportClassName: "max-h-[min(300px,var(--available-height))]", contentClassName: cn("flex flex-col gap-3 p-3", contentClassName), children: content })
3760
3838
  }
3761
3839
  )
3762
3840
  }
@@ -3765,14 +3843,15 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
3765
3843
  }
3766
3844
 
3767
3845
  // src/Rail.tsx
3768
- import { jsx as jsx57 } from "react/jsx-runtime";
3846
+ import { jsx as jsx58 } from "react/jsx-runtime";
3769
3847
  function Rail({ "aria-label": ariaLabel = "Navigation", children, className }) {
3770
- return /* @__PURE__ */ jsx57("nav", { "aria-label": ariaLabel, className: cn("flex w-16 shrink-0 flex-col items-start gap-2 px-2 py-3", className), children });
3848
+ return /* @__PURE__ */ jsx58("nav", { "aria-label": ariaLabel, className: cn("flex w-16 shrink-0 flex-col items-start gap-2 px-2 py-3", className), children });
3771
3849
  }
3772
3850
 
3773
3851
  // src/RailItem.tsx
3774
- import { jsx as jsx58, jsxs as jsxs40 } from "react/jsx-runtime";
3775
- function RailItem({ href, icon, label, active = false, className, ...props }) {
3852
+ import { jsx as jsx59, jsxs as jsxs40 } from "react/jsx-runtime";
3853
+ function RailItem({ href, icon, label, active = false, className, onClick, ...props }) {
3854
+ const inApp = useInAppClick(href, onClick);
3776
3855
  return /* @__PURE__ */ jsxs40(
3777
3856
  "a",
3778
3857
  {
@@ -3780,15 +3859,16 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
3780
3859
  "aria-current": active ? "page" : void 0,
3781
3860
  className: cn("group flex h-12 w-full shrink-0 flex-col items-center gap-0.5 px-2 py-0.5", className),
3782
3861
  ...props,
3862
+ onClick: inApp,
3783
3863
  children: [
3784
- /* @__PURE__ */ jsx58(
3864
+ /* @__PURE__ */ jsx59(
3785
3865
  "div",
3786
3866
  {
3787
3867
  className: cn(
3788
3868
  "flex items-center justify-center rounded-lg p-2 transition-colors",
3789
3869
  active ? "bg-bg-selected" : "group-hover:bg-bg-hover"
3790
3870
  ),
3791
- children: /* @__PURE__ */ jsx58(
3871
+ children: /* @__PURE__ */ jsx59(
3792
3872
  "span",
3793
3873
  {
3794
3874
  className: cn(
@@ -3800,14 +3880,14 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
3800
3880
  )
3801
3881
  }
3802
3882
  ),
3803
- /* @__PURE__ */ jsx58("span", { className: cn("text-center text-menu", active ? "text-text-primary" : "text-text-secondary"), children: label })
3883
+ /* @__PURE__ */ jsx59("span", { className: cn("text-center text-menu", active ? "text-text-primary" : "text-text-secondary"), children: label })
3804
3884
  ]
3805
3885
  }
3806
3886
  );
3807
3887
  }
3808
3888
 
3809
3889
  // src/Property.tsx
3810
- import { jsx as jsx59, jsxs as jsxs41 } from "react/jsx-runtime";
3890
+ import { jsx as jsx60, jsxs as jsxs41 } from "react/jsx-runtime";
3811
3891
  var VALUE_CLASSES = "contents";
3812
3892
  function Property({ label, layout = "row", children, className }) {
3813
3893
  if (layout === "stacked") {
@@ -3816,20 +3896,20 @@ function Property({ label, layout = "row", children, className }) {
3816
3896
  // Peek's topic-details sections already sit at 12px, Ship's rail was
3817
3897
  // 6px, and unifying means the bigger, calmer one.
3818
3898
  /* @__PURE__ */ jsxs41("dl", { className: cn("flex flex-col gap-3", className), children: [
3819
- /* @__PURE__ */ jsx59("dt", { className: "text-menu uppercase tracking-widest text-text-secondary", children: label }),
3820
- /* @__PURE__ */ jsx59("dd", { className: VALUE_CLASSES, children })
3899
+ /* @__PURE__ */ jsx60("dt", { className: "text-menu uppercase tracking-widest text-text-secondary", children: label }),
3900
+ /* @__PURE__ */ jsx60("dd", { className: VALUE_CLASSES, children })
3821
3901
  ] })
3822
3902
  );
3823
3903
  }
3824
3904
  return /* @__PURE__ */ jsxs41("dl", { className: cn("flex items-center gap-2", className), children: [
3825
- /* @__PURE__ */ jsx59("dt", { className: "w-[68px] shrink-0 text-caption text-text-secondary", children: label }),
3826
- /* @__PURE__ */ jsx59("dd", { className: VALUE_CLASSES, children })
3905
+ /* @__PURE__ */ jsx60("dt", { className: "w-[68px] shrink-0 text-caption text-text-secondary", children: label }),
3906
+ /* @__PURE__ */ jsx60("dd", { className: VALUE_CLASSES, children })
3827
3907
  ] });
3828
3908
  }
3829
3909
 
3830
3910
  // src/Reaction.tsx
3831
3911
  import { Toggle } from "@base-ui/react/toggle";
3832
- import { jsx as jsx60, jsxs as jsxs42 } from "react/jsx-runtime";
3912
+ import { jsx as jsx61, jsxs as jsxs42 } from "react/jsx-runtime";
3833
3913
  function Reaction({ emoji, count, pressed = false, className, ...props }) {
3834
3914
  return (
3835
3915
  // @estiva-escape(no-copied-look): W1 (Katerina, 24 September: leave alone): a reaction pill shares four words with a field's box by coincidence
@@ -3855,8 +3935,8 @@ function Reaction({ emoji, count, pressed = false, className, ...props }) {
3855
3935
  ),
3856
3936
  ...props,
3857
3937
  children: [
3858
- /* @__PURE__ */ jsx60("span", { "aria-hidden": "true", className: "shrink-0 text-body-1 leading-none", children: emoji }),
3859
- /* @__PURE__ */ jsx60("span", { className: CHIP_TEXT_CLASSES, children: count })
3938
+ /* @__PURE__ */ jsx61("span", { "aria-hidden": "true", className: "shrink-0 text-body-1 leading-none", children: emoji }),
3939
+ /* @__PURE__ */ jsx61("span", { className: CHIP_TEXT_CLASSES, children: count })
3860
3940
  ]
3861
3941
  }
3862
3942
  )
@@ -3866,7 +3946,7 @@ function Reaction({ emoji, count, pressed = false, className, ...props }) {
3866
3946
  // src/SearchInput.tsx
3867
3947
  import "react";
3868
3948
  import { Input as Input3 } from "@base-ui/react/input";
3869
- import { jsx as jsx61, jsxs as jsxs43 } from "react/jsx-runtime";
3949
+ import { jsx as jsx62, jsxs as jsxs43 } from "react/jsx-runtime";
3870
3950
  function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...props }) {
3871
3951
  return /* @__PURE__ */ jsxs43(
3872
3952
  "div",
@@ -3880,7 +3960,7 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
3880
3960
  className
3881
3961
  ),
3882
3962
  children: [
3883
- /* @__PURE__ */ jsx61(
3963
+ /* @__PURE__ */ jsx62(
3884
3964
  Input3,
3885
3965
  {
3886
3966
  className: cn("flex-1 min-w-0 text-input-value", BARE_INPUT_CLASSES),
@@ -3888,40 +3968,40 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
3888
3968
  ...props
3889
3969
  }
3890
3970
  ),
3891
- shortcut && /* @__PURE__ */ jsx61(Kbd, { children: shortcut })
3971
+ shortcut && /* @__PURE__ */ jsx62(Kbd, { children: shortcut })
3892
3972
  ]
3893
3973
  }
3894
3974
  );
3895
3975
  }
3896
3976
 
3897
3977
  // src/Panel.tsx
3898
- import { jsx as jsx62, jsxs as jsxs44 } from "react/jsx-runtime";
3978
+ import { jsx as jsx63, jsxs as jsxs44 } from "react/jsx-runtime";
3899
3979
  function Frame({ title, chevron = false, actions, children, footer, bodyClassName, bodyRef, onBodyScroll, className, broken = false }) {
3900
3980
  return /* @__PURE__ */ jsxs44("div", { className: cn("flex h-full min-h-0 flex-1 flex-col", className), children: [
3901
- /* @__PURE__ */ jsx62(ContainerHeader, { title, chevron, actions }),
3981
+ /* @__PURE__ */ jsx63(ContainerHeader, { title, chevron, actions }),
3902
3982
  broken ? (
3903
3983
  // The message takes the room the body had and centres itself in it.
3904
- /* @__PURE__ */ jsx62("div", { className: "flex min-h-0 flex-1 flex-col px-4", children })
3905
- ) : /* @__PURE__ */ jsx62(ScrollArea, { className: "min-h-0 flex-1", contentClassName: bodyClassName, viewportRef: bodyRef, onScroll: onBodyScroll, children }),
3906
- !broken && footer && /* @__PURE__ */ jsx62("div", { className: "shrink-0", children: footer })
3984
+ /* @__PURE__ */ jsx63("div", { className: "flex min-h-0 flex-1 flex-col px-4", children })
3985
+ ) : /* @__PURE__ */ jsx63(ScrollArea, { className: "min-h-0 flex-1", contentClassName: bodyClassName, viewportRef: bodyRef, onScroll: onBodyScroll, children }),
3986
+ !broken && footer && /* @__PURE__ */ jsx63("div", { className: "shrink-0", children: footer })
3907
3987
  ] });
3908
3988
  }
3909
3989
  function Panel(props) {
3910
- return /* @__PURE__ */ jsx62(
3990
+ return /* @__PURE__ */ jsx63(
3911
3991
  ErrorBoundary,
3912
3992
  {
3913
3993
  label: "panel",
3914
3994
  frame: (message) => (
3915
3995
  // Only the name comes back with the message: the actions and the footer may be what threw.
3916
- /* @__PURE__ */ jsx62(Frame, { title: props.title, chevron: props.chevron, className: props.className, broken: true, children: message })
3996
+ /* @__PURE__ */ jsx63(Frame, { title: props.title, chevron: props.chevron, className: props.className, broken: true, children: message })
3917
3997
  ),
3918
- children: /* @__PURE__ */ jsx62(Frame, { ...props })
3998
+ children: /* @__PURE__ */ jsx63(Frame, { ...props })
3919
3999
  }
3920
4000
  );
3921
4001
  }
3922
4002
 
3923
4003
  // src/ListColumn.tsx
3924
- import { jsx as jsx63, jsxs as jsxs45 } from "react/jsx-runtime";
4004
+ import { jsx as jsx64, jsxs as jsxs45 } from "react/jsx-runtime";
3925
4005
  function Column({ title, chevron = false, titleMenu, actions, above, collapsed = false, children, className, broken = false }) {
3926
4006
  return /* @__PURE__ */ jsxs45(
3927
4007
  "div",
@@ -3934,35 +4014,35 @@ function Column({ title, chevron = false, titleMenu, actions, above, collapsed =
3934
4014
  ),
3935
4015
  "data-collapsed": collapsed || void 0,
3936
4016
  children: [
3937
- /* @__PURE__ */ jsx63(ContainerHeader, { title, chevron, titleMenu, actions }),
4017
+ /* @__PURE__ */ jsx64(ContainerHeader, { title, chevron, titleMenu, actions }),
3938
4018
  above,
3939
4019
  broken ? (
3940
4020
  // The message takes the room the list had and centres itself in it (Katerina, 19 September).
3941
- /* @__PURE__ */ jsx63("div", { className: "flex min-h-0 flex-1 flex-col px-3", children })
3942
- ) : /* @__PURE__ */ jsx63(ScrollArea, { className: "flex-1", contentClassName: "flex flex-col gap-0.5 px-3 pt-4 pb-3", children })
4021
+ /* @__PURE__ */ jsx64("div", { className: "flex min-h-0 flex-1 flex-col px-3", children })
4022
+ ) : /* @__PURE__ */ jsx64(ScrollArea, { className: "flex-1", contentClassName: "flex flex-col gap-0.5 px-3 pt-4 pb-3", children })
3943
4023
  ]
3944
4024
  }
3945
4025
  );
3946
4026
  }
3947
4027
  function ListColumn(props) {
3948
- return /* @__PURE__ */ jsx63(
4028
+ return /* @__PURE__ */ jsx64(
3949
4029
  ErrorBoundary,
3950
4030
  {
3951
4031
  label: "list panel",
3952
4032
  frame: (message) => (
3953
4033
  // Only the name comes back with the message: the actions and the row above may be what threw.
3954
- /* @__PURE__ */ jsx63(Column, { title: props.title, chevron: props.chevron, collapsed: props.collapsed, className: props.className, broken: true, children: message })
4034
+ /* @__PURE__ */ jsx64(Column, { title: props.title, chevron: props.chevron, collapsed: props.collapsed, className: props.className, broken: true, children: message })
3955
4035
  ),
3956
- children: /* @__PURE__ */ jsx63(Column, { ...props })
4036
+ children: /* @__PURE__ */ jsx64(Column, { ...props })
3957
4037
  }
3958
4038
  );
3959
4039
  }
3960
4040
 
3961
4041
  // src/Tabs.tsx
3962
4042
  import { Tabs as BaseTabs } from "@base-ui/react/tabs";
3963
- import { Fragment as Fragment14, jsx as jsx64, jsxs as jsxs46 } from "react/jsx-runtime";
4043
+ import { Fragment as Fragment14, jsx as jsx65, jsxs as jsxs46 } from "react/jsx-runtime";
3964
4044
  function Tabs({ tabs, active, onChange, size = "default", className, ...aria }) {
3965
- return /* @__PURE__ */ jsx64(
4045
+ return /* @__PURE__ */ jsx65(
3966
4046
  BaseTabs.Root,
3967
4047
  {
3968
4048
  value: active,
@@ -3970,7 +4050,7 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
3970
4050
  if (details.reason === "none") onChange(value);
3971
4051
  },
3972
4052
  className,
3973
- children: /* @__PURE__ */ jsx64(
4053
+ children: /* @__PURE__ */ jsx65(
3974
4054
  BaseTabs.List,
3975
4055
  {
3976
4056
  activateOnFocus: true,
@@ -3992,11 +4072,11 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
3992
4072
  tab.icon,
3993
4073
  /* @__PURE__ */ jsxs46("span", { className: "flex items-baseline", children: [
3994
4074
  tab.label,
3995
- tab.count !== void 0 ? /* @__PURE__ */ jsx64("span", { className: "ml-2.5 font-mono text-caption tabular-nums text-text-secondary", children: tab.count }) : null
4075
+ tab.count !== void 0 ? /* @__PURE__ */ jsx65("span", { className: "ml-2.5 font-mono text-caption tabular-nums text-text-secondary", children: tab.count }) : null
3996
4076
  ] }),
3997
4077
  tab.unread ? /* @__PURE__ */ jsxs46(Fragment14, { children: [
3998
- /* @__PURE__ */ jsx64(UnreadDot, { className: "h-auto w-auto" }),
3999
- /* @__PURE__ */ jsx64("span", { className: "sr-only", children: "new" })
4078
+ /* @__PURE__ */ jsx65(UnreadDot, { className: "h-auto w-auto" }),
4079
+ /* @__PURE__ */ jsx65("span", { className: "sr-only", children: "new" })
4000
4080
  ] }) : null
4001
4081
  ]
4002
4082
  },
@@ -4009,10 +4089,10 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
4009
4089
  }
4010
4090
 
4011
4091
  // src/Toast.tsx
4012
- import { createContext as createContext6, useContext as useContext6, useMemo as useMemo5 } from "react";
4092
+ import { createContext as createContext7, useContext as useContext7, useMemo as useMemo6 } from "react";
4013
4093
  import { Toast as BaseToast } from "@base-ui/react/toast";
4014
4094
  import { IconAlertCircle as IconAlertCircle2, IconCircleCheck, IconCircleX } from "@tabler/icons-react";
4015
- import { jsx as jsx65, jsxs as jsxs47 } from "react/jsx-runtime";
4095
+ import { jsx as jsx66, jsxs as jsxs47 } from "react/jsx-runtime";
4016
4096
  var SURFACE_STYLES = {
4017
4097
  success: "bg-success-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md",
4018
4098
  brand: "bg-accent-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md",
@@ -4048,23 +4128,23 @@ var pillClassName = (type, hasAction, className) => cn(
4048
4128
  );
4049
4129
  function LeadingIcon({ type }) {
4050
4130
  const Icon = ICONS[type];
4051
- return /* @__PURE__ */ jsx65(Icon, { size: 16, stroke: 1.5, className: cn("text-text-primary shrink-0", ICON_STYLES[type]) });
4131
+ return /* @__PURE__ */ jsx66(Icon, { size: 16, stroke: 1.5, className: cn("text-text-primary shrink-0", ICON_STYLES[type]) });
4052
4132
  }
4053
4133
  function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAction, className }) {
4054
4134
  const hasAction = !!(actionLabel && onAction);
4055
4135
  return /* @__PURE__ */ jsxs47("div", { className: pillClassName(type, hasAction, className), children: [
4056
4136
  /* @__PURE__ */ jsxs47("div", { className: "flex items-center gap-2 shrink-0", children: [
4057
- leadingIcon && /* @__PURE__ */ jsx65(LeadingIcon, { type }),
4058
- /* @__PURE__ */ jsx65("span", { className: LABEL_CLASSES, children: label })
4137
+ leadingIcon && /* @__PURE__ */ jsx66(LeadingIcon, { type }),
4138
+ /* @__PURE__ */ jsx66("span", { className: LABEL_CLASSES, children: label })
4059
4139
  ] }),
4060
- hasAction && /* @__PURE__ */ jsx65(Button, { variant: "outlined", size: "small", onClick: onAction, children: actionLabel })
4140
+ hasAction && /* @__PURE__ */ jsx66(Button, { variant: "outlined", size: "small", onClick: onAction, children: actionLabel })
4061
4141
  ] });
4062
4142
  }
4063
- var ToastContext = createContext6(null);
4143
+ var ToastContext = createContext7(null);
4064
4144
  var VISIBLE_TOASTS = 3;
4065
4145
  function ToastProvider({ children }) {
4066
- const manager = useMemo5(() => BaseToast.createToastManager(), []);
4067
- const value = useMemo5(
4146
+ const manager = useMemo6(() => BaseToast.createToastManager(), []);
4147
+ const value = useMemo6(
4068
4148
  () => ({
4069
4149
  showToast: ({ label, type = "neutral", leadingIcon = true, actionLabel, onAction, durationMs = 5e3 }) => manager.add({
4070
4150
  title: label,
@@ -4078,9 +4158,9 @@ function ToastProvider({ children }) {
4078
4158
  }),
4079
4159
  [manager]
4080
4160
  );
4081
- return /* @__PURE__ */ jsx65(ToastContext.Provider, { value, children: /* @__PURE__ */ jsxs47(BaseToast.Provider, { toastManager: manager, limit: VISIBLE_TOASTS, children: [
4161
+ return /* @__PURE__ */ jsx66(ToastContext.Provider, { value, children: /* @__PURE__ */ jsxs47(BaseToast.Provider, { toastManager: manager, limit: VISIBLE_TOASTS, children: [
4082
4162
  children,
4083
- /* @__PURE__ */ jsx65(BaseToast.Portal, { children: /* @__PURE__ */ jsx65(BaseToast.Viewport, { className: "fixed bottom-4 left-4 z-[100] flex flex-col-reverse items-start gap-2 pointer-events-none", children: /* @__PURE__ */ jsx65(ToastList, {}) }) })
4163
+ /* @__PURE__ */ jsx66(BaseToast.Portal, { children: /* @__PURE__ */ jsx66(BaseToast.Viewport, { className: "fixed bottom-4 left-4 z-[100] flex flex-col-reverse items-start gap-2 pointer-events-none", children: /* @__PURE__ */ jsx66(ToastList, {}) }) })
4084
4164
  ] }) });
4085
4165
  }
4086
4166
  function ToastList() {
@@ -4096,17 +4176,17 @@ function ToastList() {
4096
4176
  className: pillClassName(type, !!actionLabel, "pointer-events-auto data-[limited]:hidden"),
4097
4177
  children: [
4098
4178
  /* @__PURE__ */ jsxs47("div", { className: "flex items-center gap-2 shrink-0", children: [
4099
- leadingIcon && /* @__PURE__ */ jsx65(LeadingIcon, { type }),
4100
- /* @__PURE__ */ jsx65(BaseToast.Title, { render: /* @__PURE__ */ jsx65("span", {}), className: LABEL_CLASSES })
4179
+ leadingIcon && /* @__PURE__ */ jsx66(LeadingIcon, { type }),
4180
+ /* @__PURE__ */ jsx66(BaseToast.Title, { render: /* @__PURE__ */ jsx66("span", {}), className: LABEL_CLASSES })
4101
4181
  ] }),
4102
- actionLabel && /* @__PURE__ */ jsx65(
4182
+ actionLabel && /* @__PURE__ */ jsx66(
4103
4183
  BaseToast.Action,
4104
4184
  {
4105
4185
  onClick: () => {
4106
4186
  onAction?.();
4107
4187
  close(toast.id);
4108
4188
  },
4109
- render: /* @__PURE__ */ jsx65(Button, { variant: "outlined", size: "small", children: actionLabel })
4189
+ render: /* @__PURE__ */ jsx66(Button, { variant: "outlined", size: "small", children: actionLabel })
4110
4190
  }
4111
4191
  )
4112
4192
  ]
@@ -4116,24 +4196,12 @@ function ToastList() {
4116
4196
  });
4117
4197
  }
4118
4198
  function useToast() {
4119
- const ctx = useContext6(ToastContext);
4199
+ const ctx = useContext7(ToastContext);
4120
4200
  if (!ctx) throw new Error("useToast must be used within ToastProvider");
4121
4201
  return ctx;
4122
4202
  }
4123
-
4124
- // src/shortcuts.ts
4125
- function isApplePlatform() {
4126
- if (typeof navigator === "undefined") return false;
4127
- return /Mac|iPhone|iPad|iPod/.test(navigator.platform || navigator.userAgent || "");
4128
- }
4129
- function shortcutLabel(keys, apple = isApplePlatform()) {
4130
- return keys.split("-").map((part, i, all) => {
4131
- if (i === all.length - 1) return part.length === 1 ? part.toUpperCase() : part;
4132
- if (part === "Mod") return apple ? "Cmd" : "Ctrl";
4133
- return part;
4134
- }).join("+");
4135
- }
4136
4203
  export {
4204
+ AppProvider,
4137
4205
  AppShell,
4138
4206
  AttachmentCard,
4139
4207
  Avatar,