@arbidocs/react 0.3.185 → 0.4.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 (41) hide show
  1. package/dist/{chunk-YJAYST7S.js → chunk-3CLGHHME.js} +880 -240
  2. package/dist/chunk-3CLGHHME.js.map +1 -0
  3. package/dist/chunk-6ALMBER7.js +176 -0
  4. package/dist/chunk-6ALMBER7.js.map +1 -0
  5. package/dist/chunk-BXP6S34V.cjs +284 -0
  6. package/dist/chunk-BXP6S34V.cjs.map +1 -0
  7. package/dist/chunk-EJ2BMHYK.js +272 -0
  8. package/dist/chunk-EJ2BMHYK.js.map +1 -0
  9. package/dist/{chunk-IZPXHVPJ.cjs → chunk-OU2QLIKS.cjs} +969 -344
  10. package/dist/chunk-OU2QLIKS.cjs.map +1 -0
  11. package/dist/chunk-RZQACYNQ.cjs +218 -0
  12. package/dist/chunk-RZQACYNQ.cjs.map +1 -0
  13. package/dist/{index-4WwLZsQO.d.cts → index-CcbVSNSP.d.cts} +40 -2
  14. package/dist/{index-4WwLZsQO.d.ts → index-CcbVSNSP.d.ts} +40 -2
  15. package/dist/index.cjs +589 -1070
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +11 -155
  18. package/dist/index.d.ts +11 -155
  19. package/dist/index.js +223 -725
  20. package/dist/index.js.map +1 -1
  21. package/dist/shell/index.cjs +13 -4
  22. package/dist/shell/index.d.cts +1 -1
  23. package/dist/shell/index.d.ts +1 -1
  24. package/dist/shell/index.js +2 -1
  25. package/dist/ui/index.cjs +211 -190
  26. package/dist/ui/index.d.cts +204 -3
  27. package/dist/ui/index.d.ts +204 -3
  28. package/dist/ui/index.js +2 -1
  29. package/dist/viewers/index.cjs +327 -76
  30. package/dist/viewers/index.cjs.map +1 -1
  31. package/dist/viewers/index.d.cts +90 -4
  32. package/dist/viewers/index.d.ts +90 -4
  33. package/dist/viewers/index.js +316 -78
  34. package/dist/viewers/index.js.map +1 -1
  35. package/package.json +4 -3
  36. package/dist/chunk-3MLQUKT4.cjs +0 -97
  37. package/dist/chunk-3MLQUKT4.cjs.map +0 -1
  38. package/dist/chunk-IZPXHVPJ.cjs.map +0 -1
  39. package/dist/chunk-J3XEKOV5.js +0 -87
  40. package/dist/chunk-J3XEKOV5.js.map +0 -1
  41. package/dist/chunk-YJAYST7S.js.map +0 -1
@@ -1,12 +1,11 @@
1
- import { clsx } from 'clsx';
2
- import { twMerge } from 'tailwind-merge';
1
+ import { cn, getCollisionPadding, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuItem, DropdownMenuSeparator } from './chunk-6ALMBER7.js';
3
2
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
3
  import * as React2 from 'react';
5
- import React2__default, { createContext, forwardRef, memo, useMemo, useContext, useState, useRef, useEffect, useCallback, useId } from 'react';
4
+ import React2__default, { createContext, forwardRef, memo, useMemo, useContext, useState, useRef, useEffect, useCallback, useId, Fragment as Fragment$1 } from 'react';
6
5
  import Markdown from 'react-markdown';
7
6
  import remarkGfm from 'remark-gfm';
8
7
  import rehypeRaw from 'rehype-raw';
9
- import { Circle, Check, X, ChevronRight, ChevronDown, ChevronUp, Search, MessageCircleMore, Loader2, Square, Mic, MoreVertical, Copy, MessageSquareLock, Info, FileQuestion, BookOpen, Upload, LogOut, LayoutGrid, Bell, MessageSquare, CircleUserRound, Wrench, CreditCard, ClipboardList, UserPlus, UserStar, Settings2, Users, User, NotebookPen, NotebookText, StickyNote, FolderPlus, Hash, EyeOff, Eye, CaptionsOff, FolderOpen, MessageSquareMore, MessageSquarePlus, MessageSquareText, MessageSquareOff, MessagesSquare, Columns3Cog, SquarePlus, SquareM, ChevronsDown, Bot, Calendar, Folder, List, SquareCheckBig, Minus, Plus } from 'lucide-react';
8
+ import { Circle, Check, X, ChevronDown, ChevronUp, Search, MessageCircleMore, Loader2, Square, Mic, MoreVertical, Copy, MessageSquareLock, Info, FileQuestion, BookOpen, Upload, LogOut, LayoutGrid, Bell, MessageSquare, CircleUserRound, Wrench, CreditCard, ClipboardList, UserPlus, UserStar, Settings2, Users, User, NotebookPen, NotebookText, StickyNote, FolderPlus, Hash, EyeOff, Eye, CaptionsOff, FolderOpen, MessageSquareMore, MessageSquarePlus, MessageSquareText, MessageSquareOff, MessagesSquare, Columns3Cog, SquarePlus, SquareM, ChevronsDown, Bot, Calendar, Folder, List, SquareCheckBig, ChevronsUpDown, Minus, Plus, AlertTriangle, FileX, SkipForward, XCircle, CheckCircle } from 'lucide-react';
10
9
  import { createPortal } from 'react-dom';
11
10
  import * as AvatarPrimitive from '@radix-ui/react-avatar';
12
11
  import { cva } from 'class-variance-authority';
@@ -15,7 +14,6 @@ import * as HoverCardPrimitive from '@radix-ui/react-hover-card';
15
14
  import * as SeparatorPrimitive from '@radix-ui/react-separator';
16
15
  import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
17
16
  import * as ProgressPrimitive from '@radix-ui/react-progress';
18
- import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
19
17
  import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
20
18
  import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
21
19
  import * as SwitchPrimitives from '@radix-ui/react-switch';
@@ -25,14 +23,9 @@ import * as TogglePrimitive from '@radix-ui/react-toggle';
25
23
  import * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group';
26
24
  import * as DialogPrimitive from '@radix-ui/react-dialog';
27
25
  import * as PopoverPrimitive from '@radix-ui/react-popover';
28
- import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
29
26
  import * as SelectPrimitive from '@radix-ui/react-select';
30
27
  import { Command as Command$1 } from 'cmdk';
31
28
 
32
- // src/lib/utils.ts
33
- function cn(...inputs) {
34
- return twMerge(clsx(inputs));
35
- }
36
29
  var markdownBaseComponents = {
37
30
  h1: ({ children, ...props }) => /* @__PURE__ */ jsx("h1", { className: "text-lg font-semibold", "data-testid": "markdown-heading-1", ...props, children }),
38
31
  h2: ({ children, ...props }) => /* @__PURE__ */ jsx("h2", { className: "font-semibold text-base", "data-testid": "markdown-heading-2", ...props, children }),
@@ -266,39 +259,74 @@ function Tooltip({ children, delayDuration }) {
266
259
  timer.current = null;
267
260
  }
268
261
  };
262
+ const suppressed = React2.useRef(false);
269
263
  const show = React2.useCallback(() => {
270
264
  clearTimer();
265
+ if (suppressed.current) return;
271
266
  timer.current = setTimeout(() => setOpen(true), delay);
272
267
  }, [delay]);
273
268
  const hide = React2.useCallback(() => {
274
269
  clearTimer();
275
270
  setOpen(false);
276
271
  }, []);
272
+ const suppress = React2.useCallback(() => {
273
+ suppressed.current = true;
274
+ clearTimer();
275
+ setOpen(false);
276
+ }, []);
277
+ const release = React2.useCallback(() => {
278
+ suppressed.current = false;
279
+ }, []);
277
280
  const setTrigger = React2.useCallback((el) => {
278
281
  triggerRef.current = el;
279
282
  }, []);
280
283
  React2.useEffect(() => () => clearTimer(), []);
281
284
  const value = React2.useMemo(
282
- () => ({ open, show, hide, setTrigger, triggerRef, contentId }),
283
- [open, show, hide, setTrigger, contentId]
285
+ () => ({ open, show, hide, suppress, release, setTrigger, triggerRef, contentId }),
286
+ [open, show, hide, suppress, release, setTrigger, contentId]
284
287
  );
285
288
  return /* @__PURE__ */ jsx(TooltipContext.Provider, { value, children });
286
289
  }
290
+ function isKeyboardFocus(target) {
291
+ try {
292
+ return target.matches(":focus-visible");
293
+ } catch {
294
+ return true;
295
+ }
296
+ }
297
+ function showsOwnText(el) {
298
+ if (!el) return false;
299
+ const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
300
+ let visible = "";
301
+ for (let node = walker.nextNode(); node; node = walker.nextNode()) {
302
+ if (node.parentElement?.closest(".sr-only")) continue;
303
+ visible += node.textContent ?? "";
304
+ }
305
+ return /\p{L}{2,}/u.test(visible);
306
+ }
287
307
  function TooltipTrigger({ asChild, children, ...props }) {
288
308
  const ctx = React2.useContext(TooltipContext);
289
309
  if (!ctx) return /* @__PURE__ */ jsx(Fragment, { children });
290
310
  const triggerHandlers = {
291
311
  onPointerEnter: (e) => {
292
312
  props.onPointerEnter?.(e);
313
+ if (e.pointerType === "touch") return;
314
+ if (showsOwnText(e.currentTarget)) return;
293
315
  ctx.show();
294
316
  },
295
317
  onPointerLeave: (e) => {
296
318
  props.onPointerLeave?.(e);
319
+ ctx.release();
297
320
  ctx.hide();
298
321
  },
322
+ onPointerDown: (e) => {
323
+ props.onPointerDown?.(e);
324
+ (asChild && React2.isValidElement(children) ? children.props.onPointerDown : void 0)?.(e);
325
+ ctx.suppress();
326
+ },
299
327
  onFocus: (e) => {
300
328
  props.onFocus?.(e);
301
- ctx.show();
329
+ if (isKeyboardFocus(e.target) && !showsOwnText(e.currentTarget)) ctx.show();
302
330
  },
303
331
  onBlur: (e) => {
304
332
  props.onBlur?.(e);
@@ -333,7 +361,7 @@ var TRANSFORM_BY_SIDE = {
333
361
  right: "translate(0, -50%)"
334
362
  };
335
363
  var TooltipContent = React2.forwardRef(
336
- ({ className, side = "top", sideOffset = 4, style, ...props }, ref) => {
364
+ ({ className, side = "top", sideOffset = 4, collisionPadding = 8, style, ...props }, ref) => {
337
365
  const ctx = React2.useContext(TooltipContext);
338
366
  const innerRef = React2.useRef(null);
339
367
  const [coords, setCoords] = React2.useState(null);
@@ -353,12 +381,16 @@ var TooltipContent = React2.forwardRef(
353
381
  else if (s === "bottom" && r.bottom + sideOffset + ch > vh) s = "top";
354
382
  else if (s === "left" && r.left - sideOffset - cw < 0) s = "right";
355
383
  else if (s === "right" && r.right + sideOffset + cw > vw) s = "left";
384
+ const PAD = collisionPadding;
385
+ const clamp = (value, half, max) => Math.min(Math.max(value, PAD + half), Math.max(PAD + half, max - PAD - half));
386
+ const rawTop = s === "top" ? r.top - sideOffset : s === "bottom" ? r.bottom + sideOffset : r.top + r.height / 2;
387
+ const rawLeft = s === "left" ? r.left - sideOffset : s === "right" ? r.right + sideOffset : r.left + r.width / 2;
356
388
  setCoords({
357
- top: s === "top" ? r.top - sideOffset : s === "bottom" ? r.bottom + sideOffset : r.top + r.height / 2,
358
- left: s === "left" ? r.left - sideOffset : s === "right" ? r.right + sideOffset : r.left + r.width / 2,
389
+ top: s === "left" || s === "right" ? clamp(rawTop, ch / 2, vh) : rawTop,
390
+ left: s === "top" || s === "bottom" ? clamp(rawLeft, cw / 2, vw) : rawLeft,
359
391
  transform: TRANSFORM_BY_SIDE[s]
360
392
  });
361
- }, [ctx?.open, side, sideOffset, ctx?.triggerRef]);
393
+ }, [ctx?.open, side, sideOffset, collisionPadding, ctx?.triggerRef]);
362
394
  if (!ctx?.open) return null;
363
395
  const setRefs = (node) => {
364
396
  innerRef.current = node;
@@ -378,7 +410,7 @@ var TooltipContent = React2.forwardRef(
378
410
  // The `tooltip-content` hook is kept last-but-one so a host stylesheet
379
411
  // can still restyle every tooltip in one place (the ARBI app does, with
380
412
  // `!important` rules that win over these defaults).
381
- "pointer-events-none max-w-[300px] break-words rounded-md border border-border bg-popover px-3 py-2 text-sm font-normal text-popover-foreground shadow-lg",
413
+ "pointer-events-none w-max max-w-[300px] break-words rounded-md border border-border bg-popover px-3 py-2 text-sm font-normal text-popover-foreground shadow-lg",
382
414
  "tooltip-content",
383
415
  className
384
416
  ),
@@ -433,6 +465,7 @@ function IconToggle({
433
465
  "aria-pressed": isMixed ? "mixed" : isActive,
434
466
  className: `
435
467
  group/toggle relative inline-flex items-center h-4 w-8 rounded-full
468
+ pointer-coarse:after:absolute pointer-coarse:after:left-1/2 pointer-coarse:after:top-1/2 pointer-coarse:after:size-11 pointer-coarse:after:-translate-x-1/2 pointer-coarse:after:-translate-y-1/2 pointer-coarse:after:content-['']
436
469
  transition-colors cursor-pointer
437
470
  disabled:opacity-50 disabled:cursor-not-allowed
438
471
  ${isActive ? bgColorClass : isMixed ? "bg-gray-400" : "bg-muted"}
@@ -530,23 +563,28 @@ function Badge({ className, variant, ...props }) {
530
563
  return /* @__PURE__ */ jsx("div", { className: cn(badgeVariants({ variant }), className), ...props });
531
564
  }
532
565
  var buttonVariants = cva(
533
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-base font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
566
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
534
567
  {
535
568
  variants: {
569
+ // One filled primary per view; everything else is tonal, hairline or ghost. No
570
+ // static shadows: separation is tone, and shadows are reserved for floating layers.
536
571
  variant: {
537
- default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
538
- accent: "bg-ai-accent text-ai-accent-foreground shadow hover:bg-ai-accent/90",
539
- destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
540
- outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
541
- secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
542
- ghost: "hover:bg-accent hover:text-accent-foreground",
572
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
573
+ accent: "bg-ai-accent text-ai-accent-foreground hover:bg-ai-accent/90",
574
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
575
+ outline: "border border-border bg-background hover:bg-muted",
576
+ secondary: "bg-muted text-foreground hover:bg-muted/70",
577
+ ghost: "hover:bg-muted",
543
578
  link: "text-primary underline-offset-4 hover:underline"
544
579
  },
580
+ // Touch screens get a 44px target (coarse pointers only), mouse keeps the compact 36px.
581
+ // `!` so the floor also wins over a caller's compact `h-7` or a container's
582
+ // `[&_button]:h-7` rule: a compact toolbar on a phone must still be tappable.
545
583
  size: {
546
- default: "h-9 px-4 py-2",
547
- sm: "h-8 rounded-md px-3",
548
- lg: "h-10 rounded-md px-8",
549
- icon: "h-9 w-9"
584
+ default: "h-9 px-4 py-2 pointer-coarse:h-11!",
585
+ sm: "h-8 rounded-md px-3 pointer-coarse:h-11! pointer-coarse:min-w-11",
586
+ lg: "h-10 rounded-md px-8 pointer-coarse:h-12!",
587
+ icon: "h-9 w-9 pointer-coarse:h-11! pointer-coarse:w-11!"
550
588
  }
551
589
  },
552
590
  defaultVariants: {
@@ -570,8 +608,9 @@ var HoverCardContent = React2.forwardRef(({ className, align = "center", sideOff
570
608
  ref,
571
609
  align,
572
610
  sideOffset,
611
+ collisionPadding: getCollisionPadding(),
573
612
  className: cn(
574
- "z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-hover-card-content-transform-origin]",
613
+ "z-50 w-64 max-w-[calc(100vw-1rem)] rounded-md border bg-popover p-4 text-popover-foreground shadow-lg outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-hover-card-content-transform-origin]",
575
614
  className
576
615
  ),
577
616
  ...props
@@ -992,7 +1031,7 @@ var Input = React2.forwardRef(
992
1031
  type,
993
1032
  "data-slot": "input",
994
1033
  className: cn(
995
- "flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground/60 focus-visible:outline-none focus-visible:border-ring/50 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1034
+ "flex h-9 pointer-coarse:h-11 w-full rounded-md border border-input bg-background px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground/60 focus-visible:outline-none focus-visible:border-ring/50 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
996
1035
  showDictate && "pr-9",
997
1036
  className
998
1037
  ),
@@ -1132,36 +1171,6 @@ var Progress = React2.forwardRef(({ className, value, ...props }, ref) => /* @__
1132
1171
  }
1133
1172
  ));
1134
1173
  Progress.displayName = ProgressPrimitive.Root.displayName;
1135
- var ScrollArea = React2.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
1136
- ScrollAreaPrimitive.Root,
1137
- {
1138
- ref,
1139
- className: cn("relative overflow-hidden", className),
1140
- ...props,
1141
- children: [
1142
- /* @__PURE__ */ jsx(ScrollAreaPrimitive.Viewport, { className: "h-full w-full rounded-[inherit]", children }),
1143
- /* @__PURE__ */ jsx(ScrollBar, {}),
1144
- /* @__PURE__ */ jsx(ScrollAreaPrimitive.Corner, {})
1145
- ]
1146
- }
1147
- ));
1148
- ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
1149
- var ScrollBar = React2.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsx(
1150
- ScrollAreaPrimitive.ScrollAreaScrollbar,
1151
- {
1152
- ref,
1153
- orientation,
1154
- className: cn(
1155
- "flex touch-none select-none transition-colors",
1156
- orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent p-[1px]",
1157
- orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent p-[1px]",
1158
- className
1159
- ),
1160
- ...props,
1161
- children: /* @__PURE__ */ jsx(ScrollAreaPrimitive.ScrollAreaThumb, { className: "relative flex-1 rounded-full bg-border" })
1162
- }
1163
- ));
1164
- ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
1165
1174
  var RadioGroup = React2.forwardRef(({ className, ...props }, ref) => {
1166
1175
  return /* @__PURE__ */ jsx(RadioGroupPrimitive.Root, { className: cn("grid gap-2", className), ...props, ref });
1167
1176
  });
@@ -1172,7 +1181,7 @@ var RadioGroupItem = React2.forwardRef(({ className, ...props }, ref) => {
1172
1181
  {
1173
1182
  ref,
1174
1183
  className: cn(
1175
- "aspect-square h-4 w-4 rounded-full border border-primary text-primary focus:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
1184
+ "relative aspect-square h-4 w-4 rounded-full border border-primary text-primary after:absolute after:left-1/2 after:top-1/2 after:hidden after:size-11 after:-translate-x-1/2 after:-translate-y-1/2 after:content-[''] pointer-coarse:after:block focus:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
1176
1185
  className
1177
1186
  ),
1178
1187
  ...props,
@@ -1186,7 +1195,7 @@ var Checkbox = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__
1186
1195
  {
1187
1196
  ref,
1188
1197
  className: cn(
1189
- "peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
1198
+ "peer relative h-4 w-4 shrink-0 rounded-sm border border-muted-foreground/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground after:absolute after:left-1/2 after:top-1/2 after:hidden after:size-11 after:-translate-x-1/2 after:-translate-y-1/2 after:content-[''] pointer-coarse:after:block",
1190
1199
  className
1191
1200
  ),
1192
1201
  ...props,
@@ -1198,7 +1207,7 @@ var Switch = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
1198
1207
  SwitchPrimitives.Root,
1199
1208
  {
1200
1209
  className: cn(
1201
- "peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
1210
+ "peer relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input dark:data-[state=unchecked]:bg-muted-foreground/45 after:absolute after:left-1/2 after:top-1/2 after:hidden after:size-11 after:-translate-x-1/2 after:-translate-y-1/2 after:content-[''] pointer-coarse:after:block",
1202
1211
  className
1203
1212
  ),
1204
1213
  ...props,
@@ -1220,7 +1229,7 @@ var TabsList = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__
1220
1229
  {
1221
1230
  ref,
1222
1231
  className: cn(
1223
- "inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
1232
+ "inline-flex h-9 pointer-coarse:h-auto items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
1224
1233
  className
1225
1234
  ),
1226
1235
  ...props
@@ -1232,7 +1241,7 @@ var TabsTrigger = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE
1232
1241
  {
1233
1242
  ref,
1234
1243
  className: cn(
1235
- "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow",
1244
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm pointer-coarse:min-h-11 font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow",
1236
1245
  className
1237
1246
  ),
1238
1247
  ...props
@@ -1336,9 +1345,9 @@ var toggleVariants = cva(
1336
1345
  outline: "border border-input bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground"
1337
1346
  },
1338
1347
  size: {
1339
- default: "h-9 px-2 min-w-9",
1340
- sm: "h-8 px-1.5 min-w-8",
1341
- lg: "h-10 px-2.5 min-w-10"
1348
+ default: "h-9 px-2 min-w-9 pointer-coarse:h-11 pointer-coarse:min-w-11",
1349
+ sm: "h-8 px-1.5 min-w-8 pointer-coarse:h-11 pointer-coarse:min-w-11",
1350
+ lg: "h-10 px-2.5 min-w-10 pointer-coarse:h-11 pointer-coarse:min-w-11"
1342
1351
  }
1343
1352
  },
1344
1353
  defaultVariants: {
@@ -1412,45 +1421,61 @@ var DialogOverlay = React2.forwardRef(({ className, ...props }, ref) => /* @__PU
1412
1421
  }
1413
1422
  ));
1414
1423
  DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
1415
- var DialogContent = React2.forwardRef(({ className, children, hideCloseButton, onInteractOutside, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
1416
- /* @__PURE__ */ jsx(DialogOverlay, {}),
1417
- /* @__PURE__ */ jsxs(
1418
- DialogPrimitive.Content,
1419
- {
1420
- ref,
1421
- onInteractOutside: (event) => {
1422
- if (isToastInteraction(event)) event.preventDefault();
1423
- onInteractOutside?.(event);
1424
- },
1425
- className: cn(
1426
- "fixed left-[50%] top-[50%] z-50 grid w-[calc(100%-2rem)] max-w-lg max-h-[90vh] translate-x-[-50%] translate-y-[-50%] gap-4 overflow-y-auto border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 rounded-md",
1427
- className
1428
- ),
1429
- ...props,
1430
- children: [
1431
- children,
1432
- !hideCloseButton && /* @__PURE__ */ jsxs(
1433
- DialogPrimitive.Close,
1434
- {
1435
- className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",
1436
- "data-testid": "dialog-close-button",
1437
- children: [
1438
- /* @__PURE__ */ jsx(X, { className: "h-4 w-4" }),
1439
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close dialog" })
1440
- ]
1441
- }
1442
- )
1443
- ]
1444
- }
1445
- )
1446
- ] }));
1424
+ var PHONE_PRESENTATION = {
1425
+ center: "",
1426
+ sheet: "max-sm:top-auto max-sm:bottom-0 max-sm:left-0 max-sm:w-full max-sm:max-w-full max-sm:border-x-0 max-sm:border-b-0 max-sm:translate-x-0 max-sm:translate-y-0 max-sm:rounded-b-none max-sm:rounded-t-xl max-sm:pb-[max(1.5rem,env(safe-area-inset-bottom))] max-sm:max-h-[calc(100dvh-env(safe-area-inset-top,0px)-2.5rem)] max-sm:data-[state=open]:slide-in-from-bottom-10 max-sm:data-[state=open]:zoom-in-100 max-sm:data-[state=closed]:zoom-out-100",
1427
+ full: "max-sm:top-auto max-sm:bottom-0 max-sm:left-0 max-sm:border-x-0 max-sm:border-b-0 max-sm:h-[calc(100dvh-env(safe-area-inset-top,0px)-1rem)] max-sm:w-full max-sm:max-w-full max-sm:translate-x-0 max-sm:translate-y-0 max-sm:rounded-b-none max-sm:rounded-t-xl max-sm:pb-[max(1.5rem,env(safe-area-inset-bottom))] max-sm:max-h-none max-sm:data-[state=open]:slide-in-from-bottom-10 max-sm:data-[state=open]:zoom-in-100 max-sm:data-[state=closed]:zoom-out-100"
1428
+ };
1429
+ var DialogContent = React2.forwardRef(
1430
+ ({ className, children, hideCloseButton, presentation = "center", onInteractOutside, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
1431
+ /* @__PURE__ */ jsx(DialogOverlay, {}),
1432
+ /* @__PURE__ */ jsxs(
1433
+ DialogPrimitive.Content,
1434
+ {
1435
+ ref,
1436
+ "data-slot": "dialog-content",
1437
+ "data-presentation": presentation,
1438
+ onInteractOutside: (event) => {
1439
+ if (isToastInteraction(event)) event.preventDefault();
1440
+ onInteractOutside?.(event);
1441
+ },
1442
+ className: cn(
1443
+ // Always inside the viewport: width and height are capped by the DYNAMIC viewport (mobile
1444
+ // browser chrome) and the notch / home-indicator insets; the content scrolls inside.
1445
+ "fixed left-[50%] top-[50%] z-50 grid w-[calc(100%-2rem-env(safe-area-inset-left,0px)-env(safe-area-inset-right,0px))] max-w-lg max-h-[calc(min(100dvh,100svh,100vh)-2rem-env(safe-area-inset-top,0px)-env(safe-area-inset-bottom,0px))] translate-x-[-50%] translate-y-[-50%] will-change-transform grid-cols-[minmax(0,1fr)] gap-4 overflow-x-hidden overflow-y-auto overscroll-contain border bg-background p-6 shadow-xl duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 rounded-md",
1446
+ PHONE_PRESENTATION[presentation],
1447
+ className
1448
+ ),
1449
+ ...props,
1450
+ children: [
1451
+ children,
1452
+ !hideCloseButton && /* @__PURE__ */ jsxs(
1453
+ DialogPrimitive.Close,
1454
+ {
1455
+ className: "fixed right-4 top-4 z-20 inline-flex items-center justify-center rounded-sm pointer-coarse:right-2 pointer-coarse:top-2 pointer-coarse:size-11 opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",
1456
+ "data-testid": "dialog-close-button",
1457
+ children: [
1458
+ /* @__PURE__ */ jsx(X, { className: "h-4 w-4" }),
1459
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close dialog" })
1460
+ ]
1461
+ }
1462
+ )
1463
+ ]
1464
+ }
1465
+ )
1466
+ ] })
1467
+ );
1447
1468
  DialogContent.displayName = DialogPrimitive.Content.displayName;
1448
- var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
1469
+ var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn("flex min-w-0 flex-col space-y-1.5 pr-8 text-left", className), ...props });
1449
1470
  DialogHeader.displayName = "DialogHeader";
1450
1471
  var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx(
1451
1472
  "div",
1452
1473
  {
1453
- className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
1474
+ className: cn(
1475
+ // Sticks to the bottom of a scrolling dialog so the actions stay reachable.
1476
+ "sticky bottom-0 z-10 -mx-6 -mb-6 flex flex-col-reverse gap-2 bg-background px-6 pb-6 pt-3 sm:flex-row sm:justify-end",
1477
+ className
1478
+ ),
1454
1479
  ...props
1455
1480
  }
1456
1481
  );
@@ -1459,7 +1484,7 @@ var DialogTitle = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE
1459
1484
  DialogPrimitive.Title,
1460
1485
  {
1461
1486
  ref,
1462
- className: cn("text-lg font-semibold leading-none tracking-tight", className),
1487
+ className: cn("break-words text-lg font-semibold leading-tight tracking-tight", className),
1463
1488
  ...props
1464
1489
  }
1465
1490
  ));
@@ -1482,131 +1507,273 @@ var PopoverContent = React2.forwardRef(({ className, align = "center", sideOffse
1482
1507
  ref,
1483
1508
  align,
1484
1509
  sideOffset,
1510
+ collisionPadding: getCollisionPadding(),
1485
1511
  className: cn(
1486
- "z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-popover-content-transform-origin]",
1512
+ "z-50 w-72 max-w-[calc(100vw-1rem)] max-h-[var(--radix-popover-content-available-height)] overflow-y-auto overscroll-contain rounded-md border bg-popover p-4 text-popover-foreground shadow-lg outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-popover-content-transform-origin]",
1487
1513
  className
1488
1514
  ),
1489
1515
  ...props
1490
1516
  }
1491
1517
  ) }));
1492
1518
  PopoverContent.displayName = PopoverPrimitive.Content.displayName;
1493
- var DropdownMenu = DropdownMenuPrimitive.Root;
1494
- var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
1495
- var DropdownMenuGroup = DropdownMenuPrimitive.Group;
1496
- var DropdownMenuPortal = DropdownMenuPrimitive.Portal;
1497
- var DropdownMenuSub = DropdownMenuPrimitive.Sub;
1498
- var DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
1499
- var DropdownMenuSubTrigger = React2.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs(
1500
- DropdownMenuPrimitive.SubTrigger,
1501
- {
1502
- ref,
1503
- className: cn(
1504
- "flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
1505
- inset && "pl-8",
1506
- className
1507
- ),
1508
- ...props,
1509
- children: [
1510
- children,
1511
- /* @__PURE__ */ jsx(ChevronRight, { className: "ml-auto" })
1512
- ]
1513
- }
1514
- ));
1515
- DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
1516
- var DropdownMenuSubContent = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1517
- DropdownMenuPrimitive.SubContent,
1518
- {
1519
- ref,
1520
- className: cn(
1521
- "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
1522
- className
1523
- ),
1524
- ...props
1525
- }
1526
- ));
1527
- DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
1528
- var DropdownMenuContent = React2.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
1529
- DropdownMenuPrimitive.Content,
1530
- {
1531
- ref,
1532
- sideOffset,
1533
- className: cn(
1534
- "z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
1535
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
1536
- className
1537
- ),
1538
- ...props
1539
- }
1540
- ) }));
1541
- DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
1542
- var DropdownMenuItem = React2.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
1543
- DropdownMenuPrimitive.Item,
1544
- {
1545
- ref,
1546
- className: cn(
1547
- "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
1548
- inset && "pl-8",
1549
- className
1550
- ),
1551
- ...props
1552
- }
1553
- ));
1554
- DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
1555
- var DropdownMenuCheckboxItem = React2.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs(
1556
- DropdownMenuPrimitive.CheckboxItem,
1557
- {
1558
- ref,
1559
- className: cn(
1560
- "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
1561
- className
1562
- ),
1563
- checked,
1564
- ...props,
1565
- children: [
1566
- /* @__PURE__ */ jsx("span", { className: "absolute left-2 flex h-4 w-4 items-center justify-center rounded border border-border bg-popover", children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5 text-primary" }) }) }),
1567
- children
1568
- ]
1569
- }
1570
- ));
1571
- DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
1572
- var DropdownMenuRadioItem = React2.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
1573
- DropdownMenuPrimitive.RadioItem,
1574
- {
1575
- ref,
1576
- className: cn(
1577
- "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
1578
- className
1579
- ),
1580
- ...props,
1581
- children: [
1582
- /* @__PURE__ */ jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Circle, { className: "h-2 w-2 fill-current" }) }) }),
1583
- children
1584
- ]
1585
- }
1586
- ));
1587
- DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
1588
- var DropdownMenuLabel = React2.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
1589
- DropdownMenuPrimitive.Label,
1590
- {
1591
- ref,
1592
- className: cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className),
1593
- ...props
1519
+ var FINE_OPEN_DELAY = 350;
1520
+ var FINE_CLOSE_DELAY = 180;
1521
+ function isFocusVisible(el) {
1522
+ try {
1523
+ return el.matches(":focus-visible");
1524
+ } catch {
1525
+ return true;
1594
1526
  }
1595
- ));
1596
- DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
1597
- var DropdownMenuSeparator = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1598
- DropdownMenuPrimitive.Separator,
1599
- {
1600
- ref,
1601
- className: cn("-mx-1 my-1 h-px bg-muted", className),
1602
- ...props
1603
- }
1604
- ));
1605
- DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
1606
- var DropdownMenuShortcut = ({ className, ...props }) => {
1607
- return /* @__PURE__ */ jsx("span", { className: cn("ml-auto text-sm tracking-widest opacity-60", className), ...props });
1608
- };
1609
- DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
1527
+ }
1528
+ function isCoarse(pointerType) {
1529
+ if (pointerType === "touch" || pointerType === "pen") return true;
1530
+ if (pointerType === "mouse") return false;
1531
+ return typeof window !== "undefined" && !!window.matchMedia?.("(pointer: coarse)").matches;
1532
+ }
1533
+ function MarkMenu({
1534
+ as = "span",
1535
+ href,
1536
+ items,
1537
+ preview,
1538
+ menuLabel,
1539
+ shouldClickRunPrimary = true,
1540
+ openDelay = FINE_OPEN_DELAY,
1541
+ closeDelay = FINE_CLOSE_DELAY,
1542
+ testId,
1543
+ menuTestId,
1544
+ triggerRef: externalRef,
1545
+ className,
1546
+ children,
1547
+ onPointerDown,
1548
+ onPointerEnter,
1549
+ onPointerLeave,
1550
+ onFocus,
1551
+ onBlur,
1552
+ onKeyDown,
1553
+ ...rest
1554
+ }) {
1555
+ const [open, setOpen] = useState(false);
1556
+ const [side, setSide] = useState("bottom");
1557
+ const menuId = useId();
1558
+ const triggerRef = useRef(null);
1559
+ const contentRef = useRef(null);
1560
+ const timer = useRef(null);
1561
+ const mode = useRef("hover");
1562
+ const lastPointer = useRef("mouse");
1563
+ const focusFirstOnOpen = useRef(false);
1564
+ const isEmpty = items.length === 0 && !preview;
1565
+ const ordered = [...items].sort((a, b) => Number(!!b.primary) - Number(!!a.primary));
1566
+ const primary = ordered[0];
1567
+ const clearTimer = () => {
1568
+ if (timer.current) clearTimeout(timer.current);
1569
+ timer.current = null;
1570
+ };
1571
+ useEffect(() => clearTimer, []);
1572
+ const rows = () => Array.from(contentRef.current?.querySelectorAll('[role="menuitem"]') ?? []);
1573
+ const firstItem = () => rows()[0];
1574
+ const openWith = (next, focusFirst = false) => {
1575
+ clearTimer();
1576
+ mode.current = next;
1577
+ focusFirstOnOpen.current = focusFirst;
1578
+ setSide(next === "press" && isCoarse(lastPointer.current) ? "top" : "bottom");
1579
+ setOpen(true);
1580
+ if (focusFirst) {
1581
+ requestAnimationFrame(() => firstItem()?.focus());
1582
+ }
1583
+ };
1584
+ const close = (returnFocus = false) => {
1585
+ clearTimer();
1586
+ setOpen(false);
1587
+ if (returnFocus) triggerRef.current?.focus({ preventScroll: true });
1588
+ };
1589
+ const schedule = (action, delay) => {
1590
+ clearTimer();
1591
+ timer.current = setTimeout(action, delay);
1592
+ };
1593
+ const handlePointerDown = (e) => {
1594
+ lastPointer.current = e.pointerType;
1595
+ onPointerDown?.(e);
1596
+ };
1597
+ const handlePointerEnter = (e) => {
1598
+ onPointerEnter?.(e);
1599
+ if (isCoarse(e.pointerType) || isEmpty) return;
1600
+ lastPointer.current = e.pointerType;
1601
+ schedule(() => openWith("hover"), openDelay);
1602
+ };
1603
+ const handlePointerLeave = (e) => {
1604
+ onPointerLeave?.(e);
1605
+ if (isCoarse(e.pointerType)) return;
1606
+ if (!open) return clearTimer();
1607
+ if (mode.current === "hover") schedule(() => close(), closeDelay);
1608
+ };
1609
+ const handleFocus = (e) => {
1610
+ onFocus?.(e);
1611
+ if (isEmpty) return;
1612
+ if (isFocusVisible(e.currentTarget)) schedule(() => openWith("focus"), openDelay);
1613
+ };
1614
+ const handleBlur = (e) => {
1615
+ onBlur?.(e);
1616
+ const next = e.relatedTarget;
1617
+ if (next && contentRef.current?.contains(next)) return;
1618
+ if (mode.current === "focus" || mode.current === "key") schedule(() => close(), closeDelay);
1619
+ else clearTimer();
1620
+ };
1621
+ const handleKeyDown = (e) => {
1622
+ onKeyDown?.(e);
1623
+ lastPointer.current = "keyboard";
1624
+ if (e.defaultPrevented || isEmpty) return;
1625
+ if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
1626
+ e.preventDefault();
1627
+ openWith("key", true);
1628
+ } else if (e.key === "Escape" && open) {
1629
+ e.preventDefault();
1630
+ e.stopPropagation();
1631
+ close(true);
1632
+ }
1633
+ };
1634
+ const handleClick = (e) => {
1635
+ if (isEmpty) return;
1636
+ if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
1637
+ if (e.detail === 0 && lastPointer.current === "keyboard") {
1638
+ e.preventDefault();
1639
+ return;
1640
+ }
1641
+ if (isCoarse(lastPointer.current)) {
1642
+ e.preventDefault();
1643
+ if (open) close();
1644
+ else openWith("press");
1645
+ return;
1646
+ }
1647
+ if (shouldClickRunPrimary && primary?.onSelect) {
1648
+ e.preventDefault();
1649
+ close();
1650
+ primary.onSelect();
1651
+ }
1652
+ };
1653
+ const handleMenuKeyDown = (e) => {
1654
+ const list = rows();
1655
+ const index = list.indexOf(document.activeElement);
1656
+ let target;
1657
+ if (e.key === "ArrowDown") target = list[(index + 1) % list.length];
1658
+ else if (e.key === "ArrowUp") target = list[(index - 1 + list.length) % list.length];
1659
+ else if (e.key === "Home") target = list[0];
1660
+ else if (e.key === "End") target = list[list.length - 1];
1661
+ else if (e.key === "Escape") {
1662
+ e.preventDefault();
1663
+ e.stopPropagation();
1664
+ close(true);
1665
+ return;
1666
+ } else if (e.key === "Tab") {
1667
+ close();
1668
+ return;
1669
+ }
1670
+ if (target) {
1671
+ e.preventDefault();
1672
+ target.focus();
1673
+ }
1674
+ };
1675
+ const choose = (item) => {
1676
+ const wasKey = mode.current === "key";
1677
+ close(wasKey);
1678
+ item.onSelect?.();
1679
+ };
1680
+ const setTriggerRef = useCallback(
1681
+ (el) => {
1682
+ triggerRef.current = el;
1683
+ if (typeof externalRef === "function") externalRef(el);
1684
+ else if (externalRef) externalRef.current = el;
1685
+ },
1686
+ [externalRef]
1687
+ );
1688
+ const triggerProps = {
1689
+ ref: setTriggerRef,
1690
+ className,
1691
+ "data-testid": testId,
1692
+ "data-slot": "mark",
1693
+ "aria-haspopup": "true",
1694
+ "aria-expanded": open,
1695
+ "aria-controls": open ? menuId : void 0,
1696
+ onPointerDown: handlePointerDown,
1697
+ onPointerEnter: handlePointerEnter,
1698
+ onPointerLeave: handlePointerLeave,
1699
+ onFocus: handleFocus,
1700
+ onBlur: handleBlur,
1701
+ onKeyDown: handleKeyDown,
1702
+ onClick: handleClick,
1703
+ ...rest
1704
+ };
1705
+ return /* @__PURE__ */ jsxs(Popover, { open: open && !isEmpty, children: [
1706
+ /* @__PURE__ */ jsx(PopoverAnchor, { asChild: true, children: as === "a" ? /* @__PURE__ */ jsx("a", { href, ...triggerProps, children }) : /* @__PURE__ */ jsx("span", { role: "button", tabIndex: 0, ...triggerProps, children }) }),
1707
+ /* @__PURE__ */ jsxs(
1708
+ PopoverContent,
1709
+ {
1710
+ ref: contentRef,
1711
+ id: menuId,
1712
+ side,
1713
+ align: "start",
1714
+ sideOffset: 6,
1715
+ collisionPadding: 8,
1716
+ role: "group",
1717
+ "data-testid": menuTestId,
1718
+ "data-slot": "mark-menu",
1719
+ className: "w-auto min-w-[12rem] max-w-[min(22rem,calc(100vw-1rem))] p-1",
1720
+ onOpenAutoFocus: (e) => {
1721
+ e.preventDefault();
1722
+ if (focusFirstOnOpen.current) firstItem()?.focus();
1723
+ },
1724
+ onCloseAutoFocus: (e) => e.preventDefault(),
1725
+ onEscapeKeyDown: (e) => {
1726
+ e.preventDefault();
1727
+ close(true);
1728
+ },
1729
+ onInteractOutside: (e) => {
1730
+ if (triggerRef.current?.contains(e.target)) e.preventDefault();
1731
+ },
1732
+ onPointerDownOutside: () => close(),
1733
+ onPointerEnter: clearTimer,
1734
+ onPointerLeave: (e) => {
1735
+ if (!isCoarse(e.pointerType) && mode.current === "hover")
1736
+ schedule(() => close(), closeDelay);
1737
+ },
1738
+ children: [
1739
+ preview && /* @__PURE__ */ jsx("div", { className: "px-2 py-1.5 text-sm", children: preview }),
1740
+ ordered.length > 0 && /* @__PURE__ */ jsx("div", { role: "menu", "aria-label": menuLabel, onKeyDown: handleMenuKeyDown, children: ordered.map((item) => {
1741
+ const rowClass = cn(
1742
+ "flex w-full cursor-pointer items-center rounded-sm px-2 py-1.5 text-left text-sm outline-none transition-colors hover:bg-accent focus-visible:bg-accent pointer-coarse:min-h-11 pointer-coarse:px-3",
1743
+ item.primary && "font-medium pointer-coarse:text-base",
1744
+ item.destructive && "text-destructive"
1745
+ );
1746
+ return item.href && !item.onSelect ? /* @__PURE__ */ jsx(
1747
+ "a",
1748
+ {
1749
+ role: "menuitem",
1750
+ tabIndex: -1,
1751
+ href: item.href,
1752
+ className: rowClass,
1753
+ "data-testid": item.testId,
1754
+ onClick: () => close(),
1755
+ children: item.label
1756
+ },
1757
+ item.id
1758
+ ) : /* @__PURE__ */ jsx(
1759
+ "button",
1760
+ {
1761
+ type: "button",
1762
+ role: "menuitem",
1763
+ tabIndex: -1,
1764
+ className: rowClass,
1765
+ "data-testid": item.testId,
1766
+ onClick: () => choose(item),
1767
+ children: item.label
1768
+ },
1769
+ item.id
1770
+ );
1771
+ }) })
1772
+ ]
1773
+ }
1774
+ )
1775
+ ] });
1776
+ }
1610
1777
  var Select = SelectPrimitive.Root;
1611
1778
  var SelectGroup = SelectPrimitive.Group;
1612
1779
  var SelectValue = SelectPrimitive.Value;
@@ -1615,7 +1782,7 @@ var SelectTrigger = React2.forwardRef(({ className, children, ...props }, ref) =
1615
1782
  {
1616
1783
  ref,
1617
1784
  className: cn(
1618
- "flex h-9 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground/60 focus:outline-none focus-visible:border-ring/50 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
1785
+ "flex h-9 pointer-coarse:min-h-11 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground/60 focus:outline-none focus-visible:border-ring/50 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
1619
1786
  className
1620
1787
  ),
1621
1788
  ...props,
@@ -1651,11 +1818,12 @@ var SelectContent = React2.forwardRef(({ className, children, position = "popper
1651
1818
  {
1652
1819
  ref,
1653
1820
  className: cn(
1654
- "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
1821
+ "relative z-50 max-h-[min(24rem,var(--radix-select-content-available-height))] min-w-[8rem] max-w-[calc(100vw-1rem)] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
1655
1822
  position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
1656
1823
  className
1657
1824
  ),
1658
1825
  position,
1826
+ collisionPadding: getCollisionPadding(),
1659
1827
  ...props,
1660
1828
  children: [
1661
1829
  /* @__PURE__ */ jsx(SelectScrollUpButton, {}),
@@ -1688,7 +1856,7 @@ var SelectItem = React2.forwardRef(({ className, children, ...props }, ref) => /
1688
1856
  {
1689
1857
  ref,
1690
1858
  className: cn(
1691
- "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
1859
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 pointer-coarse:min-h-11 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
1692
1860
  className
1693
1861
  ),
1694
1862
  ...props,
@@ -1730,7 +1898,7 @@ var CommandInput = React2.forwardRef(({ className, ...props }, ref) => /* @__PUR
1730
1898
  {
1731
1899
  ref,
1732
1900
  className: cn(
1733
- "flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
1901
+ "flex h-10 pointer-coarse:h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
1734
1902
  className
1735
1903
  ),
1736
1904
  ...props
@@ -1742,7 +1910,7 @@ var CommandList = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE
1742
1910
  Command$1.List,
1743
1911
  {
1744
1912
  ref,
1745
- className: cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className),
1913
+ className: cn("max-h-[min(300px,50dvh)] overflow-y-auto overflow-x-hidden", className),
1746
1914
  ...props
1747
1915
  }
1748
1916
  ));
@@ -1775,7 +1943,7 @@ var CommandItem = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE
1775
1943
  {
1776
1944
  ref,
1777
1945
  className: cn(
1778
- "relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
1946
+ "relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 pointer-coarse:min-h-11 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
1779
1947
  className
1780
1948
  ),
1781
1949
  ...props
@@ -1858,7 +2026,7 @@ var EntityPill = forwardRef(function EntityPill2({
1858
2026
  "transition-all",
1859
2027
  className
1860
2028
  );
1861
- const interactiveClasses = "cursor-pointer hover:bg-muted/80";
2029
+ const interactiveClasses = "relative cursor-pointer hover:bg-muted/80 pointer-coarse:after:absolute pointer-coarse:after:inset-x-0 pointer-coarse:after:-inset-y-3 pointer-coarse:after:content-['']";
1862
2030
  const disabledClasses = "cursor-default opacity-60";
1863
2031
  const highlightClasses = "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground";
1864
2032
  const mainContent = /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -1902,6 +2070,10 @@ var EntityPill = forwardRef(function EntityPill2({
1902
2070
  /* @__PURE__ */ jsx(TooltipContent, { side, className: "p-2", children: tip })
1903
2071
  ] });
1904
2072
  const mainAreaClass = cn("inline-flex items-center gap-1", fullWidth && "min-w-0 flex-1");
2073
+ const mainAreaTouchClass = cn(
2074
+ mainAreaClass,
2075
+ (onClick || href) && !disabled && "relative pointer-coarse:after:absolute pointer-coarse:after:inset-x-0 pointer-coarse:after:-inset-y-3 pointer-coarse:after:content-['']"
2076
+ );
1905
2077
  if (onMoreClick || moreContent) {
1906
2078
  let mainArea;
1907
2079
  if (tooltipContent) {
@@ -1909,7 +2081,7 @@ var EntityPill = forwardRef(function EntityPill2({
1909
2081
  mainContent,
1910
2082
  tooltipContent,
1911
2083
  tooltipSide,
1912
- cn(mainAreaClass, disabled && "opacity-60"),
2084
+ cn(mainAreaTouchClass, disabled && "opacity-60"),
1913
2085
  {
1914
2086
  type: "button",
1915
2087
  onClick: href ? onClick : disabled ? void 0 : onClick,
@@ -1923,7 +2095,7 @@ var EntityPill = forwardRef(function EntityPill2({
1923
2095
  href,
1924
2096
  target: "_blank",
1925
2097
  rel: "noopener noreferrer",
1926
- className: mainAreaClass,
2098
+ className: mainAreaTouchClass,
1927
2099
  onClick,
1928
2100
  children: mainContent
1929
2101
  }
@@ -1935,12 +2107,15 @@ var EntityPill = forwardRef(function EntityPill2({
1935
2107
  type: "button",
1936
2108
  onClick: disabled ? void 0 : onClick,
1937
2109
  disabled,
1938
- className: cn("inline-flex items-center gap-1", disabled && "opacity-60"),
2110
+ className: cn(
2111
+ "relative inline-flex items-center gap-1 pointer-coarse:after:absolute pointer-coarse:after:inset-x-0 pointer-coarse:after:-inset-y-3 pointer-coarse:after:content-['']",
2112
+ disabled && "opacity-60"
2113
+ ),
1939
2114
  children: mainContent
1940
2115
  }
1941
2116
  );
1942
2117
  } else {
1943
- mainArea = /* @__PURE__ */ jsx("span", { className: mainAreaClass, children: mainContent });
2118
+ mainArea = /* @__PURE__ */ jsx("span", { className: mainAreaTouchClass, children: mainContent });
1944
2119
  }
1945
2120
  const moreArea = moreContent ? /* @__PURE__ */ jsx("span", { className: "flex-shrink-0 leading-none", children: moreContent }) : tooltipWrap(
1946
2121
  /* @__PURE__ */ jsx(MoreVertical, { className: "w-3.5 h-3.5" }),
@@ -1961,7 +2136,7 @@ var EntityPill = forwardRef(function EntityPill2({
1961
2136
  ref,
1962
2137
  className: cn(
1963
2138
  baseClasses,
1964
- (onClick || href) && !disabled && interactiveClasses,
2139
+ (onClick || href) && !disabled && "cursor-pointer hover:bg-muted/80",
1965
2140
  highlight && highlightClasses
1966
2141
  ),
1967
2142
  "data-testid": testId,
@@ -2168,6 +2343,79 @@ function TagEntity({
2168
2343
  }
2169
2344
  );
2170
2345
  }
2346
+ var TIERS = [
2347
+ { min: 0.7, tone: "bg-emerald-500", label: "High relevance" },
2348
+ { min: 0.4, tone: "bg-amber-500", label: "Medium relevance" },
2349
+ { min: -Infinity, tone: "bg-muted-foreground/40", label: "Low relevance" }
2350
+ ];
2351
+ function RelevanceDot({ score }) {
2352
+ if (score == null) return null;
2353
+ const tier = TIERS.find((t) => score >= t.min) ?? TIERS[TIERS.length - 1];
2354
+ return /* @__PURE__ */ jsx(
2355
+ "span",
2356
+ {
2357
+ role: "img",
2358
+ "aria-label": tier.label,
2359
+ title: `${tier.label} (${score.toFixed(2)})`,
2360
+ className: cn("size-1.5 shrink-0 rounded-full", tier.tone),
2361
+ "data-testid": "passage-relevance"
2362
+ }
2363
+ );
2364
+ }
2365
+ function PassageCard({
2366
+ header,
2367
+ score,
2368
+ headerRight,
2369
+ active,
2370
+ onClick,
2371
+ footer,
2372
+ className,
2373
+ children,
2374
+ "data-testid": testId
2375
+ }) {
2376
+ const body = /* @__PURE__ */ jsxs(Fragment, { children: [
2377
+ /* @__PURE__ */ jsxs("div", { className: "mb-1.5 flex items-center gap-2", children: [
2378
+ header,
2379
+ (score != null || headerRight) && /* @__PURE__ */ jsxs("div", { className: "ml-auto flex shrink-0 items-center gap-2", children: [
2380
+ /* @__PURE__ */ jsx(RelevanceDot, { score }),
2381
+ headerRight
2382
+ ] })
2383
+ ] }),
2384
+ /* @__PURE__ */ jsx("div", { className: "[&_mark]:rounded-sm [&_mark]:bg-ai-accent/20 [&_mark]:px-0.5 [&_mark]:font-medium [&_mark]:text-foreground", children })
2385
+ ] });
2386
+ return /* @__PURE__ */ jsxs(
2387
+ "div",
2388
+ {
2389
+ className: cn(
2390
+ "group rounded-lg border border-border bg-card p-3 text-left transition-colors",
2391
+ onClick && "hover:border-ai-accent/40 focus-within:ring-2 focus-within:ring-ai-accent/40",
2392
+ active && "border-ai-accent/60 ring-1 ring-ai-accent/30",
2393
+ className
2394
+ ),
2395
+ children: [
2396
+ onClick ? /* @__PURE__ */ jsx(
2397
+ "div",
2398
+ {
2399
+ role: "button",
2400
+ tabIndex: 0,
2401
+ onClick,
2402
+ onKeyDown: (e) => {
2403
+ if (e.key === "Enter" || e.key === " ") {
2404
+ e.preventDefault();
2405
+ onClick(e);
2406
+ }
2407
+ },
2408
+ "aria-current": active || void 0,
2409
+ "data-testid": testId,
2410
+ className: "cursor-pointer focus:outline-none",
2411
+ children: body
2412
+ }
2413
+ ) : /* @__PURE__ */ jsx("div", { "aria-current": active || void 0, "data-testid": testId, children: body }),
2414
+ footer
2415
+ ]
2416
+ }
2417
+ );
2418
+ }
2171
2419
 
2172
2420
  // src/icons/colors.ts
2173
2421
  var NEUTRAL_GRAY = "#64748b";
@@ -2522,7 +2770,8 @@ function DocumentEntity({
2522
2770
  tooltipContent,
2523
2771
  className,
2524
2772
  fullWidth,
2525
- noClamp
2773
+ noClamp,
2774
+ "data-testid": testId
2526
2775
  }) {
2527
2776
  const title = getDocumentTitle(doc);
2528
2777
  const ext = doc.file_name?.split(".").pop()?.toLowerCase();
@@ -2563,6 +2812,7 @@ function DocumentEntity({
2563
2812
  moreContent: actions,
2564
2813
  className,
2565
2814
  highlight: viewing,
2815
+ "data-testid": testId,
2566
2816
  tooltipContent: tooltipContent ?? defaultTooltip
2567
2817
  }
2568
2818
  );
@@ -2776,7 +3026,7 @@ var UserEntity = memo(function UserEntity2({
2776
3026
  ] });
2777
3027
  const rowClass = "group/pill inline-flex min-w-0 items-center gap-2";
2778
3028
  const clickable = interactive && !!onClick;
2779
- const clickableClass = "cursor-pointer rounded-md px-1 py-0.5 -mx-1 transition-colors hover:bg-muted/60";
3029
+ const clickableClass = "relative cursor-pointer rounded-md px-1 py-0.5 -mx-1 transition-colors hover:bg-muted/60 pointer-coarse:after:absolute pointer-coarse:after:inset-x-0 pointer-coarse:after:-inset-y-3 pointer-coarse:after:content-['']";
2780
3030
  if (resolvedTooltip) {
2781
3031
  return /* @__PURE__ */ jsxs(Tooltip, { children: [
2782
3032
  /* @__PURE__ */ jsx(
@@ -2809,7 +3059,14 @@ var UserEntity = memo(function UserEntity2({
2809
3059
  }
2810
3060
  if (showTooltip) {
2811
3061
  return /* @__PURE__ */ jsxs(Tooltip, { children: [
2812
- /* @__PURE__ */ jsx(TooltipTrigger, { onFocusCapture: (e) => e.stopPropagation(), className: "inline-flex", children: avatarElement }),
3062
+ /* @__PURE__ */ jsx(
3063
+ TooltipTrigger,
3064
+ {
3065
+ onFocusCapture: (e) => e.stopPropagation(),
3066
+ className: "touch-hit inline-flex",
3067
+ children: avatarElement
3068
+ }
3069
+ ),
2813
3070
  /* @__PURE__ */ jsx(TooltipContent, { className: "p-2", children: tooltipContent })
2814
3071
  ] });
2815
3072
  }
@@ -2822,7 +3079,7 @@ function AgentBadge({ className }) {
2822
3079
  "data-testid": "agent-badge",
2823
3080
  className: cn(
2824
3081
  "inline-flex shrink-0 items-center gap-1 rounded-full border border-ai-accent/50",
2825
- "bg-ai-accent-soft px-2 py-0.5 text-[11px] font-bold uppercase tracking-wider text-ai-accent",
3082
+ "bg-ai-accent-soft px-2 py-0.5 text-xs font-bold uppercase tracking-wider text-ai-accent",
2826
3083
  className
2827
3084
  ),
2828
3085
  children: [
@@ -3236,7 +3493,390 @@ var getWorkspaceColor = (workspaceId, useWorkspaceColors) => {
3236
3493
  if (!isValidId) return "hsl(var(--primary))";
3237
3494
  return getEntityColor2(workspaceId, "medium");
3238
3495
  };
3496
+ function nameInitials(name) {
3497
+ const parts = name.trim().split(/\s+/).filter(Boolean);
3498
+ if (!parts.length) return "?";
3499
+ return parts.slice(0, 2).map((p) => p[0]?.toUpperCase() ?? "").join("");
3500
+ }
3501
+ var STATUS_DOT = {
3502
+ online: "bg-emerald-500",
3503
+ busy: "bg-amber-500",
3504
+ offline: "bg-destructive"
3505
+ };
3506
+ function UserMenu({
3507
+ user,
3508
+ status,
3509
+ items = [],
3510
+ onLogout,
3511
+ logoutLabel = "Sign out",
3512
+ align = "end",
3513
+ side = "bottom",
3514
+ variant = "avatar",
3515
+ showChevron = true,
3516
+ classNames,
3517
+ testId = "user-menu",
3518
+ logoutTestId
3519
+ }) {
3520
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
3521
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
3522
+ "button",
3523
+ {
3524
+ type: "button",
3525
+ className: cn(
3526
+ "flex items-center gap-2 rounded-md transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
3527
+ variant === "account" ? "w-full min-w-0 p-1 text-left pointer-coarse:min-h-11" : "px-1.5 py-1 pointer-coarse:min-h-11 pointer-coarse:min-w-11 pointer-coarse:justify-center",
3528
+ classNames?.trigger
3529
+ ),
3530
+ "data-testid": testId,
3531
+ "data-variant": variant,
3532
+ "aria-label": variant === "avatar" ? "Account menu" : void 0,
3533
+ title: variant === "avatar" ? user.name : void 0,
3534
+ children: [
3535
+ /* @__PURE__ */ jsxs("span", { className: "relative", children: [
3536
+ /* @__PURE__ */ jsxs(Avatar, { className: "size-8", children: [
3537
+ user.picture ? /* @__PURE__ */ jsx(AvatarImage, { src: user.picture, alt: user.name }) : null,
3538
+ /* @__PURE__ */ jsx(
3539
+ AvatarFallback,
3540
+ {
3541
+ className: cn("bg-primary text-primary-foreground", classNames?.fallback),
3542
+ children: nameInitials(user.name)
3543
+ }
3544
+ )
3545
+ ] }),
3546
+ status && /* @__PURE__ */ jsx(
3547
+ "span",
3548
+ {
3549
+ className: cn(
3550
+ "absolute -bottom-0.5 -right-0.5 size-2.5 rounded-full border-2 border-background",
3551
+ STATUS_DOT[status.tone]
3552
+ ),
3553
+ title: status.detail ? `${status.label} \xB7 ${status.detail}` : status.label,
3554
+ "data-testid": status.testId ? `${status.testId}-dot` : void 0
3555
+ }
3556
+ )
3557
+ ] }),
3558
+ variant === "account" ? /* @__PURE__ */ jsxs(Fragment, { children: [
3559
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-sm font-medium text-foreground", children: user.name }),
3560
+ /* @__PURE__ */ jsx(ChevronsUpDown, { className: "mr-1 size-4 shrink-0 text-muted-foreground" })
3561
+ ] }) : showChevron && /* @__PURE__ */ jsx(ChevronDown, { className: "size-4 text-muted-foreground" })
3562
+ ]
3563
+ }
3564
+ ) }),
3565
+ /* @__PURE__ */ jsxs(
3566
+ DropdownMenuContent,
3567
+ {
3568
+ align,
3569
+ side,
3570
+ sideOffset: 8,
3571
+ collisionPadding: 12,
3572
+ className: "w-60 rounded-lg border-border/60 shadow-lg",
3573
+ "data-testid": "user-menu-panel",
3574
+ "data-topbar-popover": "",
3575
+ children: [
3576
+ /* @__PURE__ */ jsxs(DropdownMenuLabel, { className: "relative pr-8 pointer-coarse:pr-12", children: [
3577
+ /* @__PURE__ */ jsx(
3578
+ DropdownMenuItem,
3579
+ {
3580
+ className: "absolute right-1 top-1 flex size-6 items-center justify-center rounded-md p-0 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus:bg-accent pointer-coarse:right-0 pointer-coarse:top-0 pointer-coarse:size-11",
3581
+ "aria-label": "Close account menu",
3582
+ "data-testid": "user-menu-close",
3583
+ children: /* @__PURE__ */ jsx(X, { className: "size-3.5" })
3584
+ }
3585
+ ),
3586
+ /* @__PURE__ */ jsx("div", { className: "truncate font-medium text-foreground", title: user.name, children: user.name }),
3587
+ user.email && /* @__PURE__ */ jsx("div", { className: "truncate text-xs font-normal text-muted-foreground", title: user.email, children: user.email }),
3588
+ status && /* @__PURE__ */ jsxs(
3589
+ "div",
3590
+ {
3591
+ className: "mt-1 text-xs font-normal text-muted-foreground",
3592
+ "data-testid": status.testId,
3593
+ children: [
3594
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
3595
+ /* @__PURE__ */ jsx("span", { className: cn("size-2 shrink-0 rounded-full", STATUS_DOT[status.tone]) }),
3596
+ status.label
3597
+ ] }),
3598
+ status.detail && /* @__PURE__ */ jsx("div", { className: "mt-0.5 truncate pl-3.5 text-xs leading-tight text-muted-foreground/70", children: status.detail })
3599
+ ]
3600
+ }
3601
+ )
3602
+ ] }),
3603
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
3604
+ items.map((item) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
3605
+ item.separatorBefore && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
3606
+ /* @__PURE__ */ jsxs(
3607
+ DropdownMenuItem,
3608
+ {
3609
+ onClick: item.onSelect,
3610
+ "data-testid": item.testId,
3611
+ className: "pointer-coarse:min-h-11",
3612
+ ...item.checked !== void 0 ? { role: "menuitemcheckbox", "aria-checked": item.checked } : {},
3613
+ children: [
3614
+ item.icon && /* @__PURE__ */ jsxs("span", { className: "relative flex shrink-0", children: [
3615
+ /* @__PURE__ */ jsx(item.icon, { className: "size-4" }),
3616
+ item.dot && /* @__PURE__ */ jsx(
3617
+ "span",
3618
+ {
3619
+ className: "absolute -right-0.5 -top-0.5 size-2 rounded-full bg-primary ring-2 ring-popover",
3620
+ "aria-hidden": true
3621
+ }
3622
+ )
3623
+ ] }),
3624
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: item.label }),
3625
+ item.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-muted px-1.5 text-xs font-medium tabular-nums text-muted-foreground", children: item.badge }),
3626
+ item.checked !== void 0 && /* @__PURE__ */ jsx(
3627
+ "span",
3628
+ {
3629
+ "aria-hidden": true,
3630
+ className: cn(
3631
+ "flex h-4 w-7 shrink-0 items-center rounded-full p-0.5 transition-colors",
3632
+ item.checked ? "bg-primary" : "bg-border"
3633
+ ),
3634
+ children: /* @__PURE__ */ jsx(
3635
+ "span",
3636
+ {
3637
+ className: cn(
3638
+ "size-3 rounded-full bg-background transition-transform",
3639
+ item.checked && "translate-x-3"
3640
+ )
3641
+ }
3642
+ )
3643
+ }
3644
+ )
3645
+ ]
3646
+ }
3647
+ )
3648
+ ] }, item.label)),
3649
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
3650
+ /* @__PURE__ */ jsxs(
3651
+ DropdownMenuItem,
3652
+ {
3653
+ onClick: onLogout,
3654
+ "data-testid": logoutTestId ?? `${testId}-logout`,
3655
+ className: "pointer-coarse:min-h-11",
3656
+ children: [
3657
+ /* @__PURE__ */ jsx(LogOut, { className: "size-4" }),
3658
+ logoutLabel
3659
+ ]
3660
+ }
3661
+ )
3662
+ ]
3663
+ }
3664
+ )
3665
+ ] });
3666
+ }
3667
+ var ACTIVE_STATUSES = /* @__PURE__ */ new Set([
3668
+ "queued",
3669
+ "processing",
3670
+ "parsing",
3671
+ "encrypting",
3672
+ "indexing",
3673
+ "analysing"
3674
+ ]);
3675
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "skipped", "empty", "low-content"]);
3676
+ var STATUS_LABEL = {
3677
+ queued: "Queued",
3678
+ processing: "Processing",
3679
+ parsing: "Parsing",
3680
+ encrypting: "Encrypting",
3681
+ indexing: "Indexing",
3682
+ analysing: "Analysing"
3683
+ };
3684
+ var IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set(["jpg", "jpeg", "png", "gif", "bmp", "tiff", "tif", "webp"]);
3685
+ var VIDEO_EXTENSIONS2 = /* @__PURE__ */ new Set(["mp4", "mpeg", "mpg", "webm", "mov", "avi", "mkv"]);
3686
+ var AUDIO_EXTENSIONS2 = /* @__PURE__ */ new Set(["mp3", "wav", "m4a", "aac", "ogg", "flac"]);
3687
+ var EMAIL_EXTENSIONS2 = /* @__PURE__ */ new Set(["eml", "msg"]);
3688
+ function fileIcon(fileName, size) {
3689
+ const ext = fileName?.split(".").pop()?.toLowerCase();
3690
+ if (ext && VIDEO_EXTENSIONS2.has(ext)) return /* @__PURE__ */ jsx(VidIcon, { size });
3691
+ if (ext && AUDIO_EXTENSIONS2.has(ext)) return /* @__PURE__ */ jsx(AudIcon, { size });
3692
+ if (ext && IMAGE_EXTENSIONS2.has(ext)) return /* @__PURE__ */ jsx(ImgIcon, { size });
3693
+ if (ext && EMAIL_EXTENSIONS2.has(ext)) return /* @__PURE__ */ jsx(EmlIcon, { size });
3694
+ return /* @__PURE__ */ jsx(PdfIcon, { size });
3695
+ }
3696
+ function RenameField({
3697
+ seed,
3698
+ onCommit,
3699
+ onCancel,
3700
+ testId
3701
+ }) {
3702
+ const done = React2__default.useRef(false);
3703
+ const commit = (value) => {
3704
+ if (done.current) return;
3705
+ done.current = true;
3706
+ const trimmed = value.trim();
3707
+ if (trimmed && trimmed !== seed) onCommit(trimmed);
3708
+ else onCancel();
3709
+ };
3710
+ return /* @__PURE__ */ jsx(
3711
+ "input",
3712
+ {
3713
+ autoFocus: true,
3714
+ defaultValue: seed,
3715
+ "data-testid": testId,
3716
+ onFocus: (e) => e.currentTarget.select(),
3717
+ onClick: (e) => e.stopPropagation(),
3718
+ onKeyDown: (e) => {
3719
+ if (e.key === "Enter") {
3720
+ e.preventDefault();
3721
+ commit(e.currentTarget.value);
3722
+ } else if (e.key === "Escape") {
3723
+ e.preventDefault();
3724
+ done.current = true;
3725
+ onCancel();
3726
+ }
3727
+ },
3728
+ onBlur: (e) => commit(e.currentTarget.value),
3729
+ className: "w-full rounded border border-primary bg-background px-1 py-0.5 text-xs text-foreground outline-none"
3730
+ }
3731
+ );
3732
+ }
3733
+ function StatusMarker({ status, testId }) {
3734
+ let icon = null;
3735
+ let title = "";
3736
+ switch (status) {
3737
+ case "completed":
3738
+ icon = /* @__PURE__ */ jsx(CheckCircle, { className: "size-4 text-success", strokeWidth: 2.75 });
3739
+ title = "Ready";
3740
+ break;
3741
+ case "failed":
3742
+ icon = /* @__PURE__ */ jsx(XCircle, { className: "size-4 text-destructive", strokeWidth: 2.75 });
3743
+ title = "Failed";
3744
+ break;
3745
+ case "skipped":
3746
+ icon = /* @__PURE__ */ jsx(SkipForward, { className: "size-4 text-muted-foreground", strokeWidth: 2.75 });
3747
+ title = "Skipped";
3748
+ break;
3749
+ case "empty":
3750
+ icon = /* @__PURE__ */ jsx(FileX, { className: "size-4 text-warning", strokeWidth: 2.75 });
3751
+ title = "Empty \u2014 no extractable content";
3752
+ break;
3753
+ case "low-content":
3754
+ icon = /* @__PURE__ */ jsx(AlertTriangle, { className: "size-4 text-warning", strokeWidth: 2.75 });
3755
+ title = "Low content \u2014 minimal extractable content";
3756
+ break;
3757
+ default:
3758
+ return null;
3759
+ }
3760
+ return /* @__PURE__ */ jsx(
3761
+ "span",
3762
+ {
3763
+ title,
3764
+ "data-testid": testId,
3765
+ className: "flex size-6 items-center justify-center rounded-full bg-background shadow-sm",
3766
+ children: icon
3767
+ }
3768
+ );
3769
+ }
3770
+ function DocumentCard({
3771
+ doc,
3772
+ thumbnailUrl,
3773
+ status,
3774
+ selected = false,
3775
+ onToggleSelect,
3776
+ viewing = false,
3777
+ onOpen,
3778
+ actions,
3779
+ renaming = false,
3780
+ onCommitRename,
3781
+ onCancelRename,
3782
+ tooltipContent,
3783
+ marker,
3784
+ testId = "document-card",
3785
+ className
3786
+ }) {
3787
+ const normalised = (status ?? "").toLowerCase();
3788
+ const isProcessing = ACTIVE_STATUSES.has(normalised);
3789
+ const showStatusMarker = !isProcessing && TERMINAL_STATUSES.has(normalised);
3790
+ const [thumbFailed, setThumbFailed] = React2__default.useState(false);
3791
+ const [thumbLandscape, setThumbLandscape] = React2__default.useState(false);
3792
+ const showThumbnail = !!thumbnailUrl && !thumbFailed && !isProcessing;
3793
+ return /* @__PURE__ */ jsxs(
3794
+ "div",
3795
+ {
3796
+ "data-testid": testId,
3797
+ className: cn(
3798
+ // Square corners and a portrait-page aspect (height = 1.3 × width), so a
3799
+ // cover-page thumbnail reads edge-to-edge.
3800
+ "group relative aspect-[10/13] select-none overflow-hidden border bg-muted/20 transition",
3801
+ selected ? "border-primary bg-primary/10" : "border-border shadow-sm hover:border-border/80 hover:bg-muted/50",
3802
+ className
3803
+ ),
3804
+ children: [
3805
+ showThumbnail ? /* @__PURE__ */ jsx(
3806
+ "img",
3807
+ {
3808
+ src: thumbnailUrl,
3809
+ alt: "",
3810
+ loading: "lazy",
3811
+ draggable: false,
3812
+ onError: () => setThumbFailed(true),
3813
+ onLoad: (e) => setThumbLandscape(e.currentTarget.naturalWidth > e.currentTarget.naturalHeight),
3814
+ className: cn(
3815
+ "absolute inset-0 size-full bg-white",
3816
+ thumbLandscape ? "object-contain" : "object-cover object-top"
3817
+ )
3818
+ }
3819
+ ) : /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center text-muted-foreground", children: fileIcon(doc.file_name, 44) }),
3820
+ isProcessing && /* @__PURE__ */ jsxs(
3821
+ "div",
3822
+ {
3823
+ "data-testid": `${testId}-processing`,
3824
+ className: "absolute inset-0 z-10 flex flex-col items-center justify-center gap-1.5 bg-background/80 px-3",
3825
+ children: [
3826
+ /* @__PURE__ */ jsx("div", { className: "h-1.5 w-full overflow-hidden rounded-sm bg-muted", children: /* @__PURE__ */ jsx("div", { className: "h-full w-1/3 animate-pulse rounded-sm bg-primary" }) }),
3827
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-primary", children: STATUS_LABEL[normalised] ?? normalised })
3828
+ ]
3829
+ }
3830
+ ),
3831
+ onToggleSelect && /* @__PURE__ */ jsx(
3832
+ Checkbox,
3833
+ {
3834
+ checked: selected,
3835
+ onCheckedChange: () => onToggleSelect(),
3836
+ onClick: (e) => e.stopPropagation(),
3837
+ "aria-label": selected ? "Deselect" : "Select",
3838
+ "data-testid": `${testId}-select`,
3839
+ className: cn(
3840
+ "absolute left-1.5 top-1.5 z-20 size-6 rounded-none border-muted-foreground/60 bg-background shadow-sm transition",
3841
+ selected ? "opacity-100" : "opacity-40 group-hover:opacity-100"
3842
+ )
3843
+ }
3844
+ ),
3845
+ actions && /* @__PURE__ */ jsx("div", { className: "absolute right-1.5 top-1.5 z-20", children: actions }),
3846
+ /* @__PURE__ */ jsxs("div", { className: "absolute inset-x-1.5 bottom-1.5 z-20 flex flex-col gap-1", children: [
3847
+ (marker || showStatusMarker) && /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
3848
+ marker,
3849
+ showStatusMarker && /* @__PURE__ */ jsx("div", { className: "ml-auto flex", children: /* @__PURE__ */ jsx(StatusMarker, { status: normalised, testId: `${testId}-status` }) })
3850
+ ] }),
3851
+ renaming ? /* @__PURE__ */ jsx(
3852
+ RenameField,
3853
+ {
3854
+ seed: doc.doc_metadata?.title || doc.file_name || "",
3855
+ onCommit: (name) => onCommitRename?.(name),
3856
+ onCancel: () => onCancelRename?.(),
3857
+ testId: `${testId}-rename-input`
3858
+ }
3859
+ ) : /* @__PURE__ */ jsx(
3860
+ DocumentEntity,
3861
+ {
3862
+ doc,
3863
+ fullWidth: true,
3864
+ viewing,
3865
+ tooltipContent,
3866
+ labelClassName: "font-semibold",
3867
+ className: "w-full min-w-0 max-w-full bg-background/90 backdrop-blur-sm",
3868
+ onClick: (e) => {
3869
+ e.stopPropagation();
3870
+ onOpen?.();
3871
+ }
3872
+ }
3873
+ )
3874
+ ] })
3875
+ ]
3876
+ }
3877
+ );
3878
+ }
3239
3879
 
3240
- export { AgentBadge, AiMarkdown, ArbiBotHeadIcon, AudIcon, Avatar, AvatarFallback, AvatarImage, BASE_COLORS2 as BASE_COLORS, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DictateProvider, DocumentEntity, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, ENTITY_MAPPINGS, EmlIcon, EntityIcon, EntityPill, FILE_TYPE_COLORS, HoverCard, HoverCardContent, HoverCardTrigger, IconToggle, ImgIcon, InlineMicButton, Input, Label, MarkdownRenderer, MarkdownStreamingContext, MicRecordingOverlay, MicWaveformIndicator, NEUTRAL_GRAY2 as NEUTRAL_GRAY, PLACEHOLDER_COLOR, PdfIcon, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PresenceLabel, Progress, ProjectEntity, RadioGroup, RadioGroupItem, RagDot, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Slider, StatusPill, Switch, TAG_TYPE_ICONS, TAG_TYPE_LABELS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TagEntity, Textarea, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UserEntity, VISIBILITY_ICONS, VidIcon, VisibilityIcon, badgeVariants, buttonVariants, cardVariants, classifyMediaError, cn, configureEntityRegistry, configureRagLabels, configureStatusRegistry, formatElapsed, getDocIcon, getEntityColor2 as getEntityColor, getEntityColorStyles, getEntityIcon, getEntityLabel, getStatusVariant, getTagTypeIcon, getTagTypeLabel, getWorkspaceColor, markdownBaseComponents, splitMarkdownBlocks, toggleVariants, useAudioRecorder };
3241
- //# sourceMappingURL=chunk-YJAYST7S.js.map
3242
- //# sourceMappingURL=chunk-YJAYST7S.js.map
3880
+ export { AgentBadge, AiMarkdown, ArbiBotHeadIcon, AudIcon, Avatar, AvatarFallback, AvatarImage, BASE_COLORS2 as BASE_COLORS, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DictateProvider, DocumentCard, DocumentEntity, ENTITY_MAPPINGS, EmlIcon, EntityIcon, EntityPill, FILE_TYPE_COLORS, HoverCard, HoverCardContent, HoverCardTrigger, IconToggle, ImgIcon, InlineMicButton, Input, Label, MarkMenu, MarkdownRenderer, MarkdownStreamingContext, MicRecordingOverlay, MicWaveformIndicator, NEUTRAL_GRAY2 as NEUTRAL_GRAY, PLACEHOLDER_COLOR, PassageCard, PdfIcon, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PresenceLabel, Progress, ProjectEntity, RadioGroup, RadioGroupItem, RagDot, RelevanceDot, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Slider, StatusPill, Switch, TAG_TYPE_ICONS, TAG_TYPE_LABELS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TagEntity, Textarea, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UserEntity, UserMenu, VISIBILITY_ICONS, VidIcon, VisibilityIcon, badgeVariants, buttonVariants, cardVariants, classifyMediaError, configureEntityRegistry, configureRagLabels, configureStatusRegistry, formatElapsed, getDocIcon, getEntityColor2 as getEntityColor, getEntityColorStyles, getEntityIcon, getEntityLabel, getStatusVariant, getTagTypeIcon, getTagTypeLabel, getWorkspaceColor, markdownBaseComponents, splitMarkdownBlocks, toggleVariants, useAudioRecorder };
3881
+ //# sourceMappingURL=chunk-3CLGHHME.js.map
3882
+ //# sourceMappingURL=chunk-3CLGHHME.js.map