@botiverse/raft-ui 0.11.0 → 0.12.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.
package/dist/index.mjs CHANGED
@@ -1,18 +1,15 @@
1
1
  import { cn } from "./cn.mjs";
2
- import { A as buttonVariants, C as DialogNav, D as DialogTitle, E as DialogSurface, F as resolveThemeScopeProps, I as useThemeScopeProps, L as useTheme, M as defaultNativeButton, N as useParentOverlayKind, O as DialogTrigger, P as withOverlayLayer, R as ThemeStateContext, S as DialogHeader, T as DialogPortal, _ as DialogBody, a as DrawerContent, b as DialogDescription, c as DrawerHeader, d as DrawerTitle, f as DrawerTrigger, g as Dialog, h as panelHeader, i as DrawerClose, j as Spinner, k as Button, l as DrawerOverlay, m as panelHeadEdges, n as DrawerActions, o as DrawerDescription, p as panelHeadActions, r as DrawerBody, s as DrawerFooter, t as Drawer, u as DrawerPortal, v as DialogClose, w as DialogOverlay, x as DialogFooter, y as DialogContent, z as tv } from "./drawer-yZD16Ybl.mjs";
2
+ import { $ as MessageReactionTooltipNameText, $t as DropdownMenuShortcut, A as MessageTextSelectionToolbarButton, An as DialogClose, At as MessageItem, B as MessageReferenceUnavailable, Bn as DialogTrigger, Bt as DropdownMenuCheckboxItemIndicator, C as MessageQuotedPreviewUnavailable, Cn as TooltipContent, Ct as MessageItemEdited, D as MessageEmbedHeader, Dn as Badge, Dt as MessageItemAvatarSlot, E as MessageEmbedFooter, En as TooltipTrigger, Et as MessageItemSearchMatch, F as MessageReferenceChip, Fn as DialogNav, Ft as AvatarGroup, G as MessageReactionGlyph, Gn as useParentOverlayKind, Gt as DropdownMenuItemLabel, H as MessageReactionChip, Hn as buttonVariants, Ht as DropdownMenuFooter, I as MessageReferenceIndicator, In as DialogOverlay, It as AvatarGroupCount, J as MessageReactionQuickButton, Jn as useThemeScopeProps, Jt as DropdownMenuPortal, K as MessageReactionPickerContent, Kn as withOverlayLayer, Kt as DropdownMenuLabel, L as MessageReferenceLabel, Ln as DialogPortal, Lt as AvatarImage, M as MessageMultiSelect, Mn as DialogDescription, Mt as Avatar, N as MessageMultiSelectCheckbox, Nn as DialogFooter, Nt as AvatarBadge, O as messageEmbed, On as Dialog, Ot as MessageItemContinuationTime, P as MessageMultiSelectToolbar, Pn as DialogHeader, Pt as AvatarFallback, Q as MessageReactionTooltipName, Qt as DropdownMenuSeparator, R as MessageReferencePending, Rn as DialogSurface, Rt as DropdownMenu, S as MessageQuotedPreviewTimestamp, Sn as Tooltip, St as MessageItemContent, T as MessageEmbedContent, Tn as TooltipProvider, Tt as MessageItemFooter, U as MessageReactionCount, Un as Spinner, Ut as DropdownMenuItem, V as MessageReactionAddButton, Vn as Button, Vt as DropdownMenuContent, W as MessageReactionErrorIndicator, Wn as defaultNativeButton, Wt as DropdownMenuItemCount, X as MessageReactionTooltipContent, Xn as ThemeStateContext, Xt as DropdownMenuRadioItem, Y as MessageReactionQuickRow, Yn as useTheme, Yt as DropdownMenuRadioGroup, Z as MessageReactionTooltipMeta, Zn as tv, Zt as DropdownMenuRadioItemIndicator, _ as MessageQuotedPreviewContent, _n as ScrollAreaViewport, _t as MessageItemSenderButton, a as MessageListDateDivider, an as Panel, at as MessageItemSavedIndicator, b as MessageQuotedPreviewText, bn as CheckboxIndicator, bt as MessageItemAttachments, c as MessageList, cn as PanelHeaderRoot, d as MessageQuotedPreviewAttachments, dn as PanelSection, en as DropdownMenuSubmenu, et as MessageReactionTooltipNames, f as MessageQuotedPreviewAuthor, fn as ScrollArea, ft as MessageItemHeader, g as MessageQuotedPreviewChannel, gn as ScrollAreaThumb, gt as MessageItemSenderBadges, h as MessageQuotedPreviewAuthorName, hn as ScrollAreaScrollbar, ht as MessageItemSender, in as KbdGroup, it as MessageItemReadReceipt, j as MessageTextSelectionToolbarSeparator, jn as DialogContent, jt as searchHit, k as MessageTextSelectionToolbar, kn as DialogBody, kt as MessageItemGutter, l as MessageQuotedPreview, ln as PanelScrollContent, m as MessageQuotedPreviewAuthorMeta, mn as ScrollAreaCorner, mt as MessageItemMeta, nn as DropdownMenuTrigger, nt as MessageItemBadge, o as MessageListHistoryLimited, on as PanelBody, ot as MessageItemToolbar, pn as ScrollAreaContent, pt as MessageItemInlineStatus, q as MessageReactionPickerStatic, qn as resolveThemeScopeProps, qt as DropdownMenuPopup, rn as Kbd, rt as MessageItemBadgeSeparator, s as MessageListNotice, sn as PanelFooter, st as MessageItemToolbarButton, tn as DropdownMenuSubmenuTrigger, tt as MessageReactionTooltipSeparator, u as MessageQuotedPreviewAttachment, un as PanelScrollViewport, v as MessageQuotedPreviewHeader, vn as useMobileViewport, vt as MessageItemSenderGroup, w as MessageEmbed, wn as TooltipPortal, wt as MessageItemEmbedded, x as MessageQuotedPreviewThread, xn as PRESENCE_COLOR, xt as MessageItemBody, y as MessageQuotedPreviewLoading, yn as Checkbox, yt as MessageItemTime, z as MessageReferenceText, zn as DialogTitle, zt as DropdownMenuCheckboxItem } from "./message-list-CxawdwMF.mjs";
3
3
  import { Dialog as Dialog$1 } from "@base-ui/react/dialog";
4
- import { AlertTriangle, Bell, Check, CheckCircle2, ChevronDown, ChevronLeft, ChevronRight, Copy, FileText, Image, Info, Minus, Upload, X, Zap } from "lucide-react";
5
- import { Children, Fragment, cloneElement, createContext, createElement, isValidElement, use, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
4
+ import { AlertTriangle, Bell, Check, CheckCircle2, ChevronDown, ChevronLeft, ChevronRight, Copy, FileText, Image, Info, Upload, X, Zap } from "lucide-react";
5
+ import { Children, cloneElement, createContext, createElement, isValidElement, use, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
6
6
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
7
  import { Button as Button$1 } from "@base-ui/react/button";
8
8
  import { mergeProps } from "@base-ui/react/merge-props";
9
9
  import { useRender } from "@base-ui/react/use-render";
10
- import { Tooltip as Tooltip$1 } from "@base-ui/react/tooltip";
11
- import { Checkbox as Checkbox$1 } from "@base-ui/react/checkbox";
12
- import { ScrollArea as ScrollArea$1 } from "@base-ui/react/scroll-area";
10
+ import { Drawer as Drawer$1 } from "@base-ui/react/drawer";
13
11
  import { Collapsible } from "@base-ui/react/collapsible";
14
- import { Avatar as Avatar$1, ContextMenu as ContextMenu$1 } from "@base-ui/react";
15
- import { Menu } from "@base-ui/react/menu";
12
+ import { ContextMenu as ContextMenu$1 } from "@base-ui/react";
16
13
  import { useHotkey } from "@tanstack/react-hotkeys";
17
14
  import { Popover as Popover$1 } from "@base-ui/react/popover";
18
15
  import { PreviewCard as PreviewCard$1 } from "@base-ui/react/preview-card";
@@ -25,7 +22,6 @@ import { RadioGroup as RadioGroup$1 } from "@base-ui/react/radio-group";
25
22
  import { Switch as Switch$1 } from "@base-ui/react/switch";
26
23
  import { Toggle } from "@base-ui/react/toggle";
27
24
  import { ToggleGroup as ToggleGroup$1 } from "@base-ui/react/toggle-group";
28
- import { Toolbar } from "@base-ui/react/toolbar";
29
25
  import { Progress as Progress$1 } from "@base-ui/react/progress";
30
26
  import { DndContext, DragOverlay, KeyboardCode, KeyboardSensor, PointerSensor, TouchSensor, closestCenter, closestCorners, getFirstCollision, pointerWithin, useDraggable, useDroppable, useSensor, useSensors } from "@dnd-kit/core";
31
27
  import { SortableContext, arrayMove, defaultAnimateLayoutChanges, horizontalListSortingStrategy, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
@@ -173,185 +169,448 @@ function AlertDialogCancel({ className, variant, size, ...props }) {
173
169
  });
174
170
  }
175
171
  //#endregion
176
- //#region src/components/badge/badge.tsx
177
- const badge = tv({
178
- slots: { root: [
179
- "inline-flex h-[22px] w-fit min-w-0 max-w-full shrink-0 items-center gap-1 overflow-hidden whitespace-nowrap rounded-chip px-1.5",
180
- "font-sans text-caption font-semibold normal-case tracking-normal",
181
- "transition-[filter,opacity] duration-100",
182
- "[&_svg]:size-3.5 [&_svg]:shrink-0 [&_[data-slot='spinner']]:size-3 [&_[data-slot='spinner']]:text-xs",
183
- "disabled:cursor-not-allowed disabled:bg-fill-muted disabled:text-foreground-disabled disabled:opacity-100 disabled:inset-ring-0"
184
- ] },
172
+ //#region src/components/panel/panel-header.recipe.ts
173
+ /**
174
+ * Where a head's edge controls sit, shared by every head (panel, section,
175
+ * drawer, thread). Phone: a filled thing (a sticker, a pill) puts its shape
176
+ * on 16. A ghost button has no shape, so its empty 44px box overhangs, and
177
+ * the two edge buttons mirror each other: the last action (6px padding,
178
+ * `panelHeadActions`' -3px) and a leading Back (16px padding, -13px) both sit
179
+ * 3px from their edge. Their 22px icon frames are then 14px in and every
180
+ * glyph's centre 25px in, whatever the glyph (an arrow, a gear, a narrow ⋮);
181
+ * aligning ink instead would move each button by its glyph's own side
182
+ * bearing. A Button straight in the head (ghost ones are PanelActions) is a
183
+ * filled control, so its shape ends on the content edge: 20 / 16.
184
+ */
185
+ const panelHeadEdges = [
186
+ "pr-3 pl-5 max-md:pr-1.5 max-md:pl-4",
187
+ "max-md:[&>[data-slot=panel-action]:first-child]:-ml-[13px]",
188
+ "[&>[data-slot=button]:last-child]:mr-2 max-md:[&>[data-slot=button]:last-child]:mr-2.5"
189
+ ];
190
+ /**
191
+ * A head's trailing actions. The last glyph ends on the head's edge: 20px on
192
+ * desktop (12px of padding, 1px here, the 32px button's 7px glyph inset); on
193
+ * a phone 14px in (44px buttons, 11px inset), mirroring a leading Back. The
194
+ * margin and gap follow the button's size, not the layout: a touch screen
195
+ * from 768px has the desktop head with 44px buttons, so -3px puts its last
196
+ * glyph on 20px too.
197
+ */
198
+ const panelHeadActions = "flex shrink-0 items-center gap-0.5 mr-[-3px] md:pointer-fine:mr-px md:pointer-fine:gap-1";
199
+ /**
200
+ * `header` and `sectionHeader` share one bar, expressed through
201
+ * `compoundSlots`: a 56px row (the shell header height) with a seam under it.
202
+ * On a phone the section head sits on the frame.
203
+ */
204
+ const panelHeader = tv({
205
+ slots: {
206
+ header: [],
207
+ sectionHeader: [],
208
+ headerIcon: [
209
+ "flex size-[27px] shrink-0 items-center justify-center",
210
+ "rounded-sticker border-[1.5px] border-sticker-ink bg-brand text-sticker-ink ring-[1.5px] ring-sticker-edge",
211
+ "not-data-[icon-kind=avatar]:[&_svg]:size-3.5 not-data-[icon-kind=avatar]:[&_svg]:stroke-2",
212
+ "data-[icon-kind=avatar]:size-auto data-[icon-kind=avatar]:border-transparent data-[icon-kind=avatar]:bg-transparent"
213
+ ],
214
+ headerContent: "flex min-w-0 flex-1 flex-col justify-center",
215
+ heading: "flex min-w-0 items-center gap-2",
216
+ title: "truncate font-sans text-headline font-bold text-foreground",
217
+ meta: "min-w-0 truncate font-sans text-caption text-foreground-hint",
218
+ status: [
219
+ "inline-flex shrink-0 items-center gap-1 border-0 bg-transparent p-0",
220
+ "font-sans text-caption font-medium normal-case text-foreground-hint",
221
+ "[&_svg]:size-3.5 [&_svg]:shrink-0"
222
+ ],
223
+ activity: [
224
+ "inline-flex shrink-0 items-center gap-1.5",
225
+ "font-sans text-caption text-foreground-hint",
226
+ "[&_svg]:size-3.5 [&_svg]:shrink-0"
227
+ ],
228
+ actions: panelHeadActions
229
+ },
230
+ variants: { size: {
231
+ sm: {},
232
+ md: { meta: ["text-footnote"] }
233
+ } },
234
+ compoundSlots: [{
235
+ slots: ["header", "sectionHeader"],
236
+ class: [
237
+ "flex h-(--shell-header-height,56px) shrink-0 items-center gap-3 max-md:gap-2",
238
+ panelHeadEdges,
239
+ "border-b border-line-seam bg-layer-canvas text-foreground",
240
+ "max-md:sticky max-md:top-0 max-md:z-30"
241
+ ]
242
+ }, {
243
+ slots: ["sectionHeader"],
244
+ class: [
245
+ "max-md:bg-layer-frame max-md:text-foreground-on-frame",
246
+ "max-md:[&>[data-slot=panel-header-icon]]:hidden",
247
+ "max-md:**:data-[slot=panel-title]:text-foreground-on-frame",
248
+ "max-md:**:data-[slot=panel-meta]:text-foreground-on-frame-muted",
249
+ "max-md:**:data-[slot=panel-action]:text-foreground-on-frame",
250
+ "max-md:**:data-[slot=panel-action]:hover:bg-fill-frame-pressed max-md:**:data-[slot=panel-action]:active:bg-fill-frame-pressed"
251
+ ]
252
+ }]
253
+ });
254
+ //#endregion
255
+ //#region src/components/drawer/drawer.recipe.ts
256
+ const drawerMotion = tv({
257
+ slots: {
258
+ overlay: [
259
+ "opacity-[max(var(--drawer-overlay-min-opacity,0),calc(1-var(--drawer-swipe-progress)))]",
260
+ "transition-opacity duration-200 ease-slide",
261
+ "data-starting-style:opacity-0 data-ending-style:pointer-events-none data-ending-style:opacity-0 data-ending-style:duration-150",
262
+ "motion-reduce:transition-none"
263
+ ],
264
+ popup: [
265
+ "[--drawer-blur:2px] [--drawer-ease:var(--ease-slide)]",
266
+ "[--closed-transform:translate3d(var(--drawer-exit-x,0px),var(--drawer-exit-y,0px),0)]",
267
+ "[--drawer-stack-peek:16px] [--drawer-stack-step:0.05]",
268
+ "[--drawer-stack-progress:clamp(0,var(--drawer-swipe-progress),1)]",
269
+ "[--drawer-stack-offset:max(0px,calc((var(--nested-drawers)-var(--drawer-stack-progress))*var(--drawer-stack-peek)))]",
270
+ "[--drawer-stack-scale-base:calc(max(0,1-(var(--nested-drawers)*var(--drawer-stack-step))))]",
271
+ "[--drawer-stack-scale:clamp(0,calc(var(--drawer-stack-scale-base)+(var(--drawer-stack-step)*var(--drawer-stack-progress))),1)]",
272
+ "[--drawer-stack-shrink:calc(1-var(--drawer-stack-scale))]",
273
+ "[--drawer-stack-shrink-offset:calc(var(--drawer-stack-shrink)*var(--drawer-stack-size))]",
274
+ "origin-(--drawer-transform-origin)",
275
+ "transform-[translate3d(calc(var(--drawer-swipe-x,0px)+var(--drawer-stack-x,0px)),calc(var(--drawer-swipe-y,0px)+var(--drawer-stack-y,0px)),0)_scale(var(--drawer-stack-scale))]",
276
+ "opacity-100 blur-0",
277
+ "transition-[transform,height,opacity,filter] duration-240 ease-(--drawer-ease) will-change-transform",
278
+ "data-ending-style:duration-[calc(var(--drawer-swipe-strength,1)*180ms)]",
279
+ "data-starting-style:transform-(--closed-transform) data-starting-style:opacity-0 data-starting-style:blur-(--drawer-blur)",
280
+ "data-ending-style:transform-(--closed-transform) data-ending-style:opacity-0 data-ending-style:blur-(--drawer-blur)",
281
+ "data-swiping:duration-0 data-nested-drawer-swiping:duration-0 motion-reduce:transition-none"
282
+ ],
283
+ content: ["transition-opacity duration-150 ease-slide motion-reduce:transition-none", "group-data-nested-drawer-open/drawer-popup:opacity-0 group-data-nested-drawer-swiping/drawer-popup:opacity-100"],
284
+ swipeHandle: ["transition-opacity duration-150 motion-reduce:transition-none", "group-data-nested-drawer-open/drawer-popup:opacity-0 group-data-nested-drawer-swiping/drawer-popup:opacity-100"]
285
+ },
185
286
  variants: {
186
- appearance: {
187
- solid: { root: [
188
- "h-5 min-w-5 justify-center rounded-sticker",
189
- "font-bold tabular-nums",
190
- "text-sticker-ink inset-ring-[1.5px] inset-ring-sticker-ink ring-[1.5px] ring-sticker-edge",
191
- "[&_svg]:size-[13px]",
192
- "enabled:hover:press-overlay-sticker"
287
+ side: {
288
+ down: { popup: [
289
+ "[--drawer-exit-y:calc(100%+var(--drawer-inset)+2px)]",
290
+ "[--drawer-stack-y:calc(0px-var(--drawer-stack-offset)-var(--drawer-stack-shrink-offset))]",
291
+ "[--drawer-transform-origin:50%_100%]"
292
+ ] },
293
+ up: { popup: [
294
+ "[--drawer-exit-y:calc(-100%-var(--drawer-inset)-2px)]",
295
+ "[--drawer-stack-y:calc(var(--drawer-stack-offset)+var(--drawer-stack-shrink-offset))]",
296
+ "[--drawer-transform-origin:50%_0%]"
193
297
  ] },
194
- soft: { root: ["text-foreground", "enabled:hover:press-overlay"] },
195
- outline: { root: [
196
- "font-mono text-mono-meta font-normal",
197
- "bg-transparent text-foreground-muted inset-ring inset-ring-line-hairline",
198
- "enabled:hover:bg-fill-pressed"
298
+ left: { popup: [
299
+ "[--drawer-exit-x:calc(-100%-var(--drawer-inset)-2px)]",
300
+ "[--drawer-stack-x:calc(var(--drawer-stack-offset)+var(--drawer-stack-shrink-offset))]",
301
+ "[--drawer-transform-origin:0%_50%]"
302
+ ] },
303
+ right: { popup: [
304
+ "[--drawer-exit-x:calc(100%+var(--drawer-inset)+2px)]",
305
+ "[--drawer-stack-x:calc(0px-var(--drawer-stack-offset)-var(--drawer-stack-shrink-offset))]",
306
+ "[--drawer-transform-origin:100%_50%]"
199
307
  ] }
200
308
  },
201
- variant: {
202
- default: "",
203
- primary: "",
204
- information: "",
205
- muted: "",
206
- accent: "",
207
- success: "",
208
- warning: "",
209
- danger: ""
210
- }
211
- },
212
- defaultVariants: {
213
- appearance: "solid",
214
- variant: "default"
215
- },
216
- compoundVariants: [
217
- {
218
- appearance: "solid",
219
- variant: "default",
220
- class: { root: "bg-sticker-paper" }
221
- },
222
- {
223
- appearance: "solid",
224
- variant: "muted",
225
- class: { root: "bg-inactive" }
226
- },
227
- {
228
- appearance: "solid",
229
- variant: "primary",
230
- class: { root: "bg-brand" }
231
- },
232
- {
233
- appearance: "solid",
234
- variant: "information",
235
- class: { root: "bg-info" }
236
- },
237
- {
238
- appearance: "solid",
239
- variant: "accent",
240
- class: { root: "bg-attention font-mono text-mono-meta" }
241
- },
242
- {
243
- appearance: "solid",
244
- variant: "success",
245
- class: { root: "bg-success" }
246
- },
247
- {
248
- appearance: "solid",
249
- variant: "warning",
250
- class: { root: "bg-warning" }
251
- },
252
- {
253
- appearance: "solid",
254
- variant: "danger",
255
- class: { root: "bg-danger" }
256
- },
257
- {
258
- appearance: "soft",
259
- variant: "default",
260
- class: { root: "bg-fill-muted" }
261
- },
262
- {
263
- appearance: "soft",
264
- variant: "muted",
265
- class: { root: "bg-inactive-soft" }
266
- },
267
- {
268
- appearance: "soft",
269
- variant: "primary",
270
- class: { root: "bg-brand-soft" }
271
- },
272
- {
273
- appearance: "soft",
274
- variant: "information",
275
- class: { root: "bg-info-soft" }
276
- },
277
- {
278
- appearance: "soft",
279
- variant: "accent",
280
- class: { root: "bg-attention-soft" }
281
- },
282
- {
283
- appearance: "soft",
284
- variant: "success",
285
- class: { root: "bg-success-soft" }
286
- },
287
- {
288
- appearance: "soft",
289
- variant: "warning",
290
- class: { root: "bg-warning-soft" }
291
- },
292
- {
293
- appearance: "soft",
294
- variant: "danger",
295
- class: { root: "bg-danger-soft" }
296
- },
297
- {
298
- appearance: "outline",
299
- variant: "primary",
300
- class: { root: "text-brand-strong" }
301
- },
302
- {
303
- appearance: "outline",
304
- variant: "information",
305
- class: { root: "text-info-strong" }
306
- },
307
- {
308
- appearance: "outline",
309
- variant: "accent",
310
- class: { root: "text-attention-strong" }
309
+ axis: {
310
+ x: { popup: ["[--drawer-stack-size:100%]", "[--drawer-swipe-x:var(--drawer-swipe-movement-x)]"] },
311
+ y: { popup: ["[--drawer-stack-size:max(0px,var(--drawer-frontmost-height,var(--drawer-height)))]", "[--drawer-swipe-y:calc(var(--drawer-snap-point-offset,0px)+var(--drawer-swipe-movement-y))]"] }
311
312
  },
312
- {
313
- appearance: "outline",
314
- variant: "success",
315
- class: { root: "text-success-strong" }
313
+ snapPoints: { true: { overlay: ["[--drawer-overlay-min-opacity:0.5]"] } }
314
+ }
315
+ });
316
+ const drawer = tv({
317
+ extend: drawerMotion,
318
+ slots: {
319
+ overlay: [
320
+ "fixed inset-0 z-50 min-h-dvh select-none",
321
+ "supports-[-webkit-touch-callout:none]:absolute",
322
+ "bg-layer-backdrop"
323
+ ],
324
+ viewport: ["pointer-events-none fixed inset-0 z-50 select-none"],
325
+ popup: [
326
+ "group/drawer-popup pointer-events-auto fixed z-50 flex h-(--drawer-content-height) flex-col outline-none",
327
+ "[--drawer-inset:12px] [--drawer-content-height:var(--drawer-height,auto)]",
328
+ "data-nested-drawer-open:overflow-hidden",
329
+ "bg-layer-popover text-foreground",
330
+ "shadow-float ring-1 ring-line-seam"
331
+ ],
332
+ content: ["flex min-h-0 flex-1 flex-col rounded-[inherit] select-text", "group-data-swiping/drawer-popup:select-none"],
333
+ swipeHandle: [
334
+ "relative z-10 shrink-0 cursor-grab select-none active:cursor-grabbing",
335
+ "before:absolute before:content-['']",
336
+ "before:rounded-[1px] before:bg-line-seam"
337
+ ],
338
+ close: ["shrink-0"],
339
+ closeIcon: ["size-5.5"],
340
+ header: ["flex flex-col", "items-stretch gap-1 px-4 pt-4 pb-2 text-left"],
341
+ body: ["flex flex-1 flex-col", "items-stretch px-4 pt-2 pb-4 text-left"],
342
+ footer: ["mt-auto py-5", "px-4 pt-3 pb-4"],
343
+ actions: [
344
+ "flex w-full flex-col items-stretch",
345
+ "**:data-[slot=button]:w-full",
346
+ "gap-2"
347
+ ],
348
+ title: ["text-pretty text-foreground", "max-w-none text-left font-sans text-headline font-bold"],
349
+ description: ["text-pretty", "max-w-none text-left font-sans text-callout text-foreground-muted"]
350
+ },
351
+ variants: {
352
+ nested: {
353
+ false: {},
354
+ true: { overlay: ["bg-layer-backdrop-nested"] }
316
355
  },
317
- {
318
- appearance: "outline",
319
- variant: "warning",
320
- class: { root: "text-warning-strong" }
356
+ side: {
357
+ down: {
358
+ popup: [
359
+ "bottom-(--drawer-inset) min-h-64 max-h-[82vh]",
360
+ "rounded-t-dialog [--drawer-inset:0px]",
361
+ "pb-[env(safe-area-inset-bottom,0px)]"
362
+ ],
363
+ swipeHandle: ["before:top-3"]
364
+ },
365
+ up: {
366
+ popup: [
367
+ "top-(--drawer-inset) max-h-[80vh]",
368
+ "rounded-b-dialog [--drawer-inset:0px]",
369
+ "pt-[env(safe-area-inset-top,0px)]"
370
+ ],
371
+ swipeHandle: ["order-last", "before:bottom-3"]
372
+ },
373
+ left: {
374
+ popup: ["left-(--drawer-inset)"],
375
+ swipeHandle: ["order-last", "before:right-3"]
376
+ },
377
+ right: {
378
+ popup: ["right-(--drawer-inset)"],
379
+ swipeHandle: ["before:left-3"]
380
+ }
321
381
  },
322
- {
323
- appearance: "outline",
324
- variant: "danger",
325
- class: { root: "text-danger-strong" }
382
+ axis: {
383
+ x: {
384
+ popup: ["flex-row", "inset-y-0 w-full max-w-[420px] [--drawer-inset:0px]"],
385
+ swipeHandle: [
386
+ "my-auto h-16 w-11",
387
+ "before:top-1/2 before:-translate-y-1/2",
388
+ "before:w-1 before:h-9"
389
+ ],
390
+ header: [
391
+ "min-h-14 shrink-0 flex-row items-center justify-between gap-2 py-0 text-left",
392
+ "border-b border-line-seam",
393
+ panelHeadEdges
394
+ ],
395
+ body: ["items-stretch text-left", "min-h-0 overflow-y-auto px-5 py-4"],
396
+ footer: ["border-t border-line-seam px-5 py-3"],
397
+ title: ["min-w-0 max-w-none flex-1 text-left"],
398
+ description: ["max-w-none text-left"],
399
+ actions: ["flex-row flex-wrap justify-end", "**:data-[slot=button]:w-auto"]
400
+ },
401
+ y: {
402
+ popup: [
403
+ "data-nested-drawer-open:h-(--drawer-frontmost-height)",
404
+ "mx-auto md:max-w-md",
405
+ "inset-x-0"
406
+ ],
407
+ swipeHandle: [
408
+ "mx-auto w-16",
409
+ "before:left-1/2 before:-translate-x-1/2",
410
+ "h-4",
411
+ "before:top-1.5 before:h-1 before:w-9"
412
+ ]
413
+ }
326
414
  }
327
- ]
415
+ },
416
+ compoundVariants: [{
417
+ side: "down",
418
+ snapPoints: true,
419
+ class: { header: ["pt-2"] }
420
+ }, {
421
+ axis: "y",
422
+ snapPoints: true,
423
+ class: { popup: ["[--drawer-content-height:100dvh]"] }
424
+ }]
328
425
  });
329
- function BadgeRoot({ appearance, variant, className, render, ...props }) {
330
- const resolvedAppearance = appearance ?? "solid";
331
- const { root } = badge({
332
- appearance: resolvedAppearance,
333
- variant
426
+ //#endregion
427
+ //#region src/components/drawer/drawer.tsx
428
+ const DrawerConfigContext = createContext(null);
429
+ function useDrawerConfig() {
430
+ const context = useContext(DrawerConfigContext);
431
+ if (!context) throw new Error("Drawer parts must be used within Drawer.");
432
+ return context;
433
+ }
434
+ function Drawer({ modal = true, snapPoints, swipeDirection = "down", children, ...props }) {
435
+ const hasSnapPoints = snapPoints != null && snapPoints.length > 0;
436
+ const swipeAxis = swipeDirection === "down" || swipeDirection === "up" ? "y" : "x";
437
+ const contextValue = useMemo(() => ({
438
+ hasSnapPoints,
439
+ modal,
440
+ swipeAxis,
441
+ swipeDirection
442
+ }), [
443
+ hasSnapPoints,
444
+ modal,
445
+ swipeAxis,
446
+ swipeDirection
447
+ ]);
448
+ return /* @__PURE__ */ jsx(DrawerConfigContext.Provider, {
449
+ value: contextValue,
450
+ children: /* @__PURE__ */ jsx(Drawer$1.Root, {
451
+ modal,
452
+ snapPoints,
453
+ swipeDirection,
454
+ ...props,
455
+ children: withOverlayLayer("drawer", modal === true, children)
456
+ })
334
457
  });
335
- const defaultProps = { className: root({ className }) };
458
+ }
459
+ function DrawerTrigger(props) {
460
+ return /* @__PURE__ */ jsx(Drawer$1.Trigger, {
461
+ "data-slot": "drawer-trigger",
462
+ ...props
463
+ });
464
+ }
465
+ function DrawerPortal(props) {
466
+ return /* @__PURE__ */ jsx(Drawer$1.Portal, {
467
+ "data-slot": "drawer-portal",
468
+ ...useThemeScopeProps(props)
469
+ });
470
+ }
471
+ function DrawerOverlay({ className, ...props }) {
472
+ const { hasSnapPoints } = useDrawerConfig();
473
+ const nested = useParentOverlayKind() === "dialog";
474
+ const { overlay } = drawer({
475
+ snapPoints: hasSnapPoints,
476
+ nested
477
+ });
478
+ return /* @__PURE__ */ jsx(Drawer$1.Backdrop, {
479
+ "data-slot": "drawer-overlay",
480
+ "data-nested": nested ? "" : void 0,
481
+ forceRender: nested,
482
+ className: overlay({ className }),
483
+ ...props
484
+ });
485
+ }
486
+ function DrawerSwipeHandle() {
487
+ const { swipeAxis, swipeDirection } = useDrawerConfig();
488
+ const { swipeHandle } = drawer({
489
+ side: swipeDirection,
490
+ axis: swipeAxis
491
+ });
492
+ return /* @__PURE__ */ jsx("div", {
493
+ "data-slot": "drawer-swipe-handle",
494
+ "aria-hidden": "true",
495
+ className: swipeHandle()
496
+ });
497
+ }
498
+ function DrawerContent({ className, children, portalProps, ...props }) {
499
+ const { hasSnapPoints, modal, swipeAxis, swipeDirection } = useDrawerConfig();
500
+ const { content, popup, viewport } = drawer({
501
+ side: swipeDirection,
502
+ axis: swipeAxis,
503
+ snapPoints: hasSnapPoints
504
+ });
505
+ return /* @__PURE__ */ jsxs(DrawerPortal, {
506
+ ...portalProps,
507
+ children: [modal === true ? /* @__PURE__ */ jsx(DrawerOverlay, {}) : null, /* @__PURE__ */ jsx(Drawer$1.Viewport, {
508
+ "data-slot": "drawer-viewport",
509
+ className: cn(viewport(), modal === true && "pointer-events-auto"),
510
+ children: /* @__PURE__ */ jsxs(Drawer$1.Popup, {
511
+ "data-slot": "drawer-popup",
512
+ className: popup({ className }),
513
+ ...props,
514
+ children: [hasSnapPoints ? /* @__PURE__ */ jsx(DrawerSwipeHandle, {}) : null, /* @__PURE__ */ jsx(Drawer$1.Content, {
515
+ "data-slot": "drawer-content",
516
+ className: content(),
517
+ children
518
+ })]
519
+ })
520
+ })]
521
+ });
522
+ }
523
+ function DrawerClose({ className, variant, size, children, render, "aria-label": ariaLabel, ...props }) {
524
+ const { close, closeIcon } = drawer();
525
+ if (render) return /* @__PURE__ */ jsx(Drawer$1.Close, {
526
+ "data-slot": "drawer-close",
527
+ className,
528
+ render,
529
+ "aria-label": ariaLabel,
530
+ ...props,
531
+ children
532
+ });
533
+ return /* @__PURE__ */ jsx(Drawer$1.Close, {
534
+ "data-slot": "drawer-close",
535
+ render: /* @__PURE__ */ jsx(Button, {
536
+ variant: variant ?? "ghost",
537
+ size: size ?? "icon-lg",
538
+ "aria-label": ariaLabel ?? "Close"
539
+ }),
540
+ className: close({ className }),
541
+ ...props,
542
+ children: children ?? /* @__PURE__ */ jsx(X, { className: closeIcon() })
543
+ });
544
+ }
545
+ function DrawerHeader({ className, render, ...props }) {
546
+ const { hasSnapPoints, swipeAxis, swipeDirection } = useDrawerConfig();
547
+ const { header } = drawer({
548
+ side: swipeDirection,
549
+ axis: swipeAxis,
550
+ snapPoints: hasSnapPoints
551
+ });
552
+ const defaultProps = { className: header({ className }) };
336
553
  return useRender({
337
- defaultTagName: "span",
554
+ defaultTagName: "div",
338
555
  render,
339
556
  props: mergeProps(defaultProps, props),
340
- state: {
341
- slot: "badge",
342
- appearance: resolvedAppearance,
343
- variant
344
- }
557
+ state: { slot: "drawer-header" }
345
558
  });
346
559
  }
347
- function Experimental(props) {
348
- return /* @__PURE__ */ jsx(BadgeRoot, {
349
- variant: "success",
350
- ...props,
351
- children: "Experimental"
560
+ function DrawerFooter({ className, render, ...props }) {
561
+ const { swipeAxis } = useDrawerConfig();
562
+ const { footer } = drawer({ axis: swipeAxis });
563
+ const defaultProps = { className: footer({ className }) };
564
+ return useRender({
565
+ defaultTagName: "div",
566
+ render,
567
+ props: mergeProps(defaultProps, props),
568
+ state: { slot: "drawer-footer" }
569
+ });
570
+ }
571
+ function DrawerBody({ className, render, ...props }) {
572
+ const { swipeAxis } = useDrawerConfig();
573
+ const { body } = drawer({ axis: swipeAxis });
574
+ const defaultProps = { className: body({ className }) };
575
+ return useRender({
576
+ defaultTagName: "div",
577
+ render,
578
+ props: mergeProps(defaultProps, props),
579
+ state: { slot: "drawer-body" }
580
+ });
581
+ }
582
+ function DrawerActions({ className, render, children, ...props }) {
583
+ const swipeAxis = useContext(DrawerConfigContext)?.swipeAxis;
584
+ const { actions } = drawer({ axis: swipeAxis });
585
+ const defaultProps = {
586
+ className: actions({ className }),
587
+ children
588
+ };
589
+ return useRender({
590
+ defaultTagName: "div",
591
+ render,
592
+ props: mergeProps(defaultProps, props),
593
+ state: { slot: "drawer-actions" }
594
+ });
595
+ }
596
+ function DrawerTitle({ className, ...props }) {
597
+ const { swipeAxis } = useDrawerConfig();
598
+ const { title } = drawer({ axis: swipeAxis });
599
+ return /* @__PURE__ */ jsx(Drawer$1.Title, {
600
+ "data-slot": "drawer-title",
601
+ className: title({ className }),
602
+ ...props
603
+ });
604
+ }
605
+ function DrawerDescription({ className, ...props }) {
606
+ const { swipeAxis } = useDrawerConfig();
607
+ const { description } = drawer({ axis: swipeAxis });
608
+ return /* @__PURE__ */ jsx(Drawer$1.Description, {
609
+ "data-slot": "drawer-description",
610
+ className: description({ className }),
611
+ ...props
352
612
  });
353
613
  }
354
- const Badge = Object.assign(BadgeRoot, { Experimental });
355
614
  //#endregion
356
615
  //#region src/components/form-section/form-section.tsx
357
616
  const formSection = tv({ slots: {
@@ -430,215 +689,40 @@ function TextLink({ variant, className, render, ...props }) {
430
689
  });
431
690
  }
432
691
  //#endregion
433
- //#region src/components/tooltip/tooltip.tsx
434
- const tooltip = tv({
435
- slots: {
436
- trigger: ["select-none"],
437
- positioner: ["isolate z-50 pointer-events-none outline-none"],
438
- content: [
439
- "pointer-events-none relative inline-block max-w-[min(20rem,var(--available-width,20rem))] min-w-0 px-2.5 py-1",
440
- "origin-(--transform-origin) outline-none",
441
- "transition-[opacity,transform] duration-150 ease-[cubic-bezier(0.22,1,0.36,1)]",
442
- "data-starting-style:scale-[0.97] data-starting-style:opacity-0",
443
- "data-ending-style:scale-[0.99] data-ending-style:opacity-0",
444
- "data-instant:transition-none",
445
- "motion-reduce:transition-none",
446
- "rounded-chip bg-layer-hud text-foreground-on-hud",
447
- "font-sans font-medium",
448
- "shadow-float",
449
- "has-[[data-slot=kbd]]:py-1 has-[[data-slot=kbd]]:pr-2.5"
450
- ],
451
- body: [
452
- "block min-w-0 text-footnote whitespace-normal wrap-break-word",
453
- "**:data-[slot=kbd]:relative **:data-[slot=kbd]:z-10 [&_[data-slot=kbd]]:ml-1.5",
454
- "[&_[data-slot=kbd]]:h-4 [&_[data-slot=kbd]]:min-w-4 [&_[data-slot=kbd]]:px-1 [&_[data-slot=kbd]]:py-0",
455
- "**:data-[slot=kbd]:text-[12px] **:data-[slot=kbd]:leading-4 [&_[data-slot=kbd]]:font-normal"
456
- ],
457
- bodyIcon: ["shrink-0 [&>svg]:block [&>svg]:size-3.5 [&>svg]:shrink-0"],
458
- bodyText: ["min-w-0 flex-1"],
459
- arrow: [
460
- "pointer-events-none flex overflow-visible",
461
- "data-[side=top]:bottom-[-5px]",
462
- "data-[side=bottom]:top-[-5px] data-[side=bottom]:rotate-180",
463
- "data-[side=left]:right-[-8px] data-[side=left]:-rotate-90",
464
- "data-[side=right]:left-[-8px] data-[side=right]:rotate-90",
465
- "data-[side=inline-start]:right-[-8px] data-[side=inline-start]:-rotate-90",
466
- "data-[side=inline-end]:left-[-8px] data-[side=inline-end]:rotate-90"
467
- ]
468
- },
469
- variants: { hasLeadingIcon: {
470
- true: { body: ["flex items-center gap-x-1.5"] },
471
- false: {}
472
- } }
473
- });
474
- function TooltipProvider({ delay = 0, ...props }) {
475
- return /* @__PURE__ */ jsx(Tooltip$1.Provider, {
476
- delay,
477
- ...props
478
- });
692
+ //#region src/components/float-button/float-button.position.ts
693
+ function resolvePositionStyles(options) {
694
+ const { position, side, offset, style } = options;
695
+ if (!position && !side && offset === void 0) return style ?? {};
696
+ const resolvedPosition = position ?? "fixed";
697
+ if (resolvedPosition === "relative") return {
698
+ position: "relative",
699
+ ...style
700
+ };
701
+ const resolvedSide = side ?? "bottom-right";
702
+ const [offsetX, offsetY] = normalizeOffset(offset ?? 16);
703
+ const posStyles = { position: resolvedPosition };
704
+ if (resolvedSide === "bottom-right") {
705
+ posStyles.bottom = offsetY;
706
+ posStyles.right = offsetX;
707
+ } else if (resolvedSide === "bottom-left") {
708
+ posStyles.bottom = offsetY;
709
+ posStyles.left = offsetX;
710
+ } else if (resolvedSide === "top-right") {
711
+ posStyles.top = offsetY;
712
+ posStyles.right = offsetX;
713
+ } else if (resolvedSide === "top-left") {
714
+ posStyles.top = offsetY;
715
+ posStyles.left = offsetX;
716
+ }
717
+ return {
718
+ ...posStyles,
719
+ ...style
720
+ };
479
721
  }
480
- function Tooltip(props) {
481
- return /* @__PURE__ */ jsx(Tooltip$1.Root, { ...props });
482
- }
483
- function TooltipTrigger({ className, ...props }) {
484
- const { trigger } = tooltip();
485
- const childSlot = isValidElement(props.render) ? props.render.props["data-slot"] : void 0;
486
- const slot = props["data-slot"] ?? childSlot ?? "tooltip-trigger";
487
- return /* @__PURE__ */ jsx(Tooltip$1.Trigger, {
488
- "data-slot": slot,
489
- className: trigger({ className }),
490
- ...props
491
- });
492
- }
493
- function TooltipPortal(props) {
494
- return /* @__PURE__ */ jsx(Tooltip$1.Portal, {
495
- "data-slot": "tooltip-portal",
496
- ...useThemeScopeProps(props)
497
- });
498
- }
499
- function TooltipArrow({ className, ...props }) {
500
- const { arrow } = tooltip();
501
- return /* @__PURE__ */ jsx(Tooltip$1.Arrow, {
502
- "data-slot": "tooltip-arrow",
503
- className: arrow({ className }),
504
- ...props,
505
- children: /* @__PURE__ */ jsx(TooltipArrowSvg, {})
506
- });
507
- }
508
- function TooltipArrowSvg(props) {
509
- return /* @__PURE__ */ jsx("svg", {
510
- width: "12",
511
- height: "6",
512
- viewBox: "0 0 12 6",
513
- fill: "none",
514
- ...props,
515
- children: /* @__PURE__ */ jsx("path", {
516
- d: "M1 0H11L6 5.25Z",
517
- className: "fill-layer-hud"
518
- })
519
- });
520
- }
521
- function flattenTooltipChildren(children) {
522
- return Children.toArray(children).flatMap((child) => {
523
- if (isValidElement(child) && child.type === Fragment) return flattenTooltipChildren(child.props.children);
524
- return [child];
525
- });
526
- }
527
- function isTooltipLeadingIcon(child) {
528
- if (!isValidElement(child)) return false;
529
- if (child.props["data-slot"] === "kbd") return false;
530
- if (child.type === "svg") return true;
531
- return typeof child.type !== "string";
532
- }
533
- function partitionTooltipBodyChildren(children) {
534
- const items = flattenTooltipChildren(children);
535
- const icons = [];
536
- const rest = [];
537
- let seenNonIcon = false;
538
- for (const item of items) {
539
- if (!seenNonIcon && isTooltipLeadingIcon(item)) {
540
- icons.push(item);
541
- continue;
542
- }
543
- seenNonIcon = true;
544
- rest.push(item);
545
- }
546
- return {
547
- icons,
548
- rest
549
- };
550
- }
551
- function TooltipBodyContent({ children }) {
552
- const { icons, rest } = partitionTooltipBodyChildren(children);
553
- const { body, bodyIcon, bodyText } = tooltip({ hasLeadingIcon: icons.length > 0 });
554
- if (icons.length === 0) return /* @__PURE__ */ jsx("span", {
555
- "data-slot": "tooltip-body",
556
- className: body(),
557
- children
558
- });
559
- return /* @__PURE__ */ jsxs("span", {
560
- "data-slot": "tooltip-body",
561
- className: body(),
562
- children: [/* @__PURE__ */ jsx("span", {
563
- "data-slot": "tooltip-body-icon",
564
- className: bodyIcon(),
565
- children: icons
566
- }), /* @__PURE__ */ jsx("span", {
567
- "data-slot": "tooltip-body-text",
568
- className: bodyText(),
569
- children: rest
570
- })]
571
- });
572
- }
573
- const CONTENT_COLLISION_AVOIDANCE$1 = {
574
- side: "flip",
575
- align: "shift",
576
- fallbackAxisSide: "none"
577
- };
578
- function TooltipContent({ align = "center", alignOffset = 0, anchor, arrowPadding, collisionAvoidance = CONTENT_COLLISION_AVOIDANCE$1, collisionBoundary, collisionPadding, disableAnchorTracking = false, positionMethod = "fixed", side = "top", sideOffset, sticky, container, portalProps, className, children, ...props }) {
579
- const { positioner, content } = tooltip();
580
- const portalContainer = container !== void 0 ? container : portalProps?.container;
581
- return /* @__PURE__ */ jsx(TooltipPortal, {
582
- ...portalProps,
583
- container: portalContainer,
584
- children: /* @__PURE__ */ jsx(Tooltip$1.Positioner, {
585
- align,
586
- alignOffset,
587
- anchor,
588
- arrowPadding,
589
- collisionAvoidance,
590
- collisionBoundary,
591
- collisionPadding,
592
- disableAnchorTracking,
593
- positionMethod,
594
- side,
595
- sideOffset: sideOffset ?? 8,
596
- sticky,
597
- className: positioner(),
598
- children: /* @__PURE__ */ jsxs(Tooltip$1.Popup, {
599
- "data-slot": "tooltip-content",
600
- className: content({ className }),
601
- ...props,
602
- children: [/* @__PURE__ */ jsx(TooltipBodyContent, { children }), /* @__PURE__ */ jsx(TooltipArrow, {})]
603
- })
604
- })
605
- });
606
- }
607
- //#endregion
608
- //#region src/components/float-button/float-button.position.ts
609
- function resolvePositionStyles(options) {
610
- const { position, side, offset, style } = options;
611
- if (!position && !side && offset === void 0) return style ?? {};
612
- const resolvedPosition = position ?? "fixed";
613
- if (resolvedPosition === "relative") return {
614
- position: "relative",
615
- ...style
616
- };
617
- const resolvedSide = side ?? "bottom-right";
618
- const [offsetX, offsetY] = normalizeOffset(offset ?? 16);
619
- const posStyles = { position: resolvedPosition };
620
- if (resolvedSide === "bottom-right") {
621
- posStyles.bottom = offsetY;
622
- posStyles.right = offsetX;
623
- } else if (resolvedSide === "bottom-left") {
624
- posStyles.bottom = offsetY;
625
- posStyles.left = offsetX;
626
- } else if (resolvedSide === "top-right") {
627
- posStyles.top = offsetY;
628
- posStyles.right = offsetX;
629
- } else if (resolvedSide === "top-left") {
630
- posStyles.top = offsetY;
631
- posStyles.left = offsetX;
632
- }
633
- return {
634
- ...posStyles,
635
- ...style
636
- };
637
- }
638
- function normalizeOffset(offset) {
639
- if (Array.isArray(offset)) return [formatLength(offset[0]), formatLength(offset[1])];
640
- const formatted = formatLength(offset);
641
- return [formatted, formatted];
722
+ function normalizeOffset(offset) {
723
+ if (Array.isArray(offset)) return [formatLength(offset[0]), formatLength(offset[1])];
724
+ const formatted = formatLength(offset);
725
+ return [formatted, formatted];
642
726
  }
643
727
  function formatLength(val) {
644
728
  if (typeof val === "number") return `${val}px`;
@@ -1150,21 +1234,6 @@ function ListRowChevron({ className, render, ...props }) {
1150
1234
  });
1151
1235
  }
1152
1236
  //#endregion
1153
- //#region src/lib/presence.ts
1154
- /**
1155
- * The five status lights of the design system. Each colour is a fixed
1156
- * meaning: online green, busy (an agent at work) yellow, error orange,
1157
- * offline stone, an external agent cyan. One map, read by Status and by the
1158
- * avatar's dot through the same `--status-color`.
1159
- */
1160
- const PRESENCE_COLOR = {
1161
- online: "[--status-color:var(--presence-online)]",
1162
- busy: "[--status-color:var(--presence-busy)]",
1163
- error: "[--status-color:var(--presence-error)]",
1164
- offline: "[--status-color:var(--presence-offline)]",
1165
- external: "[--status-color:var(--presence-external)]"
1166
- };
1167
- //#endregion
1168
1237
  //#region src/components/status/status.tsx
1169
1238
  const status = tv({
1170
1239
  slots: { root: [
@@ -1579,182 +1648,6 @@ function CopyableCodeActionIcon({ copied }) {
1579
1648
  });
1580
1649
  }
1581
1650
  //#endregion
1582
- //#region src/components/checkbox/checkbox-indicator.tsx
1583
- const checkboxIndicator = tv({
1584
- slots: { root: [
1585
- "inline-flex size-5 shrink-0 items-center justify-center",
1586
- "rounded-sticker border-[1.5px] border-line-strong transition-colors",
1587
- "[&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5 [&_svg]:stroke-2"
1588
- ] },
1589
- variants: {
1590
- shape: {
1591
- square: "",
1592
- circle: { root: "rounded-full" }
1593
- },
1594
- checked: {
1595
- true: { root: "border-foreground bg-foreground text-foreground-inverse" },
1596
- false: { root: "bg-layer-card text-transparent" }
1597
- },
1598
- disabled: {
1599
- true: { root: "border-foreground-disabled bg-fill-muted" },
1600
- false: ""
1601
- },
1602
- previewOnHover: {
1603
- true: "",
1604
- false: ""
1605
- }
1606
- },
1607
- compoundVariants: [{
1608
- checked: false,
1609
- previewOnHover: true,
1610
- class: { root: "group-hover:text-foreground/20" }
1611
- }, {
1612
- checked: true,
1613
- disabled: true,
1614
- class: { root: "bg-foreground-disabled text-layer-card" }
1615
- }],
1616
- defaultVariants: {
1617
- shape: "square",
1618
- disabled: false,
1619
- previewOnHover: false
1620
- }
1621
- });
1622
- function CheckboxIndicator({ checked, mark = "check", shape, disabled, previewOnHover, className, ...props }) {
1623
- const { root } = checkboxIndicator({
1624
- shape,
1625
- checked,
1626
- disabled,
1627
- previewOnHover
1628
- });
1629
- const Icon = mark === "minus" ? Minus : Check;
1630
- return /* @__PURE__ */ jsx("span", {
1631
- ...props,
1632
- "data-slot": "checkbox-indicator-graphic",
1633
- "aria-hidden": true,
1634
- className: root({ className }),
1635
- children: (checked || previewOnHover) && /* @__PURE__ */ jsx(Icon, {})
1636
- });
1637
- }
1638
- //#endregion
1639
- //#region src/components/checkbox/checkbox.tsx
1640
- const checkbox = tv({ slots: {
1641
- root: [
1642
- "relative inline-flex size-5 shrink-0 touch-manipulation items-center justify-center outline-none",
1643
- "rounded-sticker focus-visible:shadow-focus",
1644
- "data-disabled:cursor-not-allowed",
1645
- "after:absolute after:-inset-x-3 after:-inset-y-2 after:content-['']"
1646
- ],
1647
- indicator: "pointer-events-none"
1648
- } });
1649
- function Checkbox({ shape = "square", className, ...props }) {
1650
- const { root, indicator } = checkbox();
1651
- const renderIndicator = useCallback((indicatorProps, state) => /* @__PURE__ */ jsx(CheckboxIndicator, {
1652
- ...indicatorProps,
1653
- checked: state.checked || state.indeterminate,
1654
- disabled: state.disabled,
1655
- mark: state.indeterminate ? "minus" : "check",
1656
- shape
1657
- }), [shape]);
1658
- return /* @__PURE__ */ jsx(Checkbox$1.Root, {
1659
- "data-slot": "checkbox",
1660
- className: root({ className }),
1661
- ...props,
1662
- children: /* @__PURE__ */ jsx(Checkbox$1.Indicator, {
1663
- keepMounted: true,
1664
- "data-slot": "checkbox-indicator",
1665
- className: indicator(),
1666
- render: renderIndicator
1667
- })
1668
- });
1669
- }
1670
- //#endregion
1671
- //#region src/lib/use-mobile-viewport.ts
1672
- const MOBILE_QUERY = "(max-width: 767px)";
1673
- function subscribeMobileViewport(onStoreChange) {
1674
- if (typeof window === "undefined") return () => void 0;
1675
- const media = window.matchMedia(MOBILE_QUERY);
1676
- media.addEventListener("change", onStoreChange);
1677
- return () => media.removeEventListener("change", onStoreChange);
1678
- }
1679
- function getMobileViewportSnapshot() {
1680
- return typeof window !== "undefined" && window.matchMedia(MOBILE_QUERY).matches;
1681
- }
1682
- function useMobileViewport() {
1683
- return useSyncExternalStore(subscribeMobileViewport, getMobileViewportSnapshot, () => false);
1684
- }
1685
- //#endregion
1686
- //#region src/components/scroll-area/scroll-area.recipe.ts
1687
- const scrollArea = tv({ slots: {
1688
- root: ["relative min-h-0"],
1689
- viewport: ["size-full min-h-0 overscroll-contain outline-none", "[overflow-anchor:auto] [-webkit-overflow-scrolling:touch]"],
1690
- content: ["min-h-full"],
1691
- scrollbar: [
1692
- "group/scroll-area-scrollbar z-50 flex touch-none select-none p-1",
1693
- "opacity-0 transition-opacity duration-150 pointer-events-none",
1694
- "data-scrolling:pointer-events-auto data-scrolling:opacity-100 data-scrolling:duration-0",
1695
- "data-[orientation=vertical]:w-3 data-[orientation=vertical]:justify-center",
1696
- "data-[orientation=horizontal]:h-3 data-[orientation=horizontal]:flex-col data-[orientation=horizontal]:justify-center"
1697
- ],
1698
- thumb: [
1699
- "relative",
1700
- "group-data-[orientation=vertical]/scroll-area-scrollbar:w-1.5",
1701
- "group-data-[orientation=horizontal]/scroll-area-scrollbar:h-1.5",
1702
- "rounded-[2px] bg-foreground/30 hover:bg-foreground/45"
1703
- ],
1704
- corner: ["bg-transparent"]
1705
- } });
1706
- //#endregion
1707
- //#region src/components/scroll-area/scroll-area.tsx
1708
- function ScrollArea({ className, ...props }) {
1709
- const { root } = scrollArea();
1710
- return /* @__PURE__ */ jsx(ScrollArea$1.Root, {
1711
- "data-slot": "scroll-area",
1712
- className: root({ className }),
1713
- ...props
1714
- });
1715
- }
1716
- function ScrollAreaViewport({ className, ...props }) {
1717
- const { viewport } = scrollArea();
1718
- return /* @__PURE__ */ jsx(ScrollArea$1.Viewport, {
1719
- "data-slot": "scroll-area-viewport",
1720
- className: viewport({ className }),
1721
- ...props
1722
- });
1723
- }
1724
- function ScrollAreaContent({ className, ...props }) {
1725
- const { content } = scrollArea();
1726
- return /* @__PURE__ */ jsx(ScrollArea$1.Content, {
1727
- "data-slot": "scroll-area-content",
1728
- className: content({ className }),
1729
- ...props
1730
- });
1731
- }
1732
- function ScrollAreaScrollbar({ className, orientation = "vertical", ...props }) {
1733
- const { scrollbar } = scrollArea();
1734
- return /* @__PURE__ */ jsx(ScrollArea$1.Scrollbar, {
1735
- "data-slot": "scroll-area-scrollbar",
1736
- orientation,
1737
- className: scrollbar({ className }),
1738
- ...props
1739
- });
1740
- }
1741
- function ScrollAreaThumb({ className, ...props }) {
1742
- const { thumb } = scrollArea();
1743
- return /* @__PURE__ */ jsx(ScrollArea$1.Thumb, {
1744
- "data-slot": "scroll-area-thumb",
1745
- className: thumb({ className }),
1746
- ...props
1747
- });
1748
- }
1749
- function ScrollAreaCorner({ className, ...props }) {
1750
- const { corner } = scrollArea();
1751
- return /* @__PURE__ */ jsx(ScrollArea$1.Corner, {
1752
- "data-slot": "scroll-area-corner",
1753
- className: corner({ className }),
1754
- ...props
1755
- });
1756
- }
1757
- //#endregion
1758
1651
  //#region src/components/sidebar/sidebar.recipe.ts
1759
1652
  const sidebarRecipe = tv({ slots: {
1760
1653
  sidebarRoot: [
@@ -2599,120 +2492,6 @@ function SidebarSectionControl({ className, render, size = "icon-sm", variant =
2599
2492
  }
2600
2493
  const SidebarControl = SidebarSectionControl;
2601
2494
  //#endregion
2602
- //#region src/components/panel/panel.recipe.ts
2603
- const panel = tv({
2604
- slots: {
2605
- root: ["[--panel-footer-clearance:10rem]", "bg-layer-canvas text-foreground"],
2606
- header: ["[@media(max-height:600px)]:h-12"],
2607
- body: ["relative min-h-0 flex-1 overflow-hidden"],
2608
- scrollViewport: ["h-full min-h-0 overflow-y-auto overscroll-contain", "[overflow-anchor:auto] [-webkit-overflow-scrolling:touch]"],
2609
- scrollContent: ["min-h-full"],
2610
- section: ["border-t px-5 py-4", "border-line-hairline"],
2611
- footer: [
2612
- "relative flex shrink-0 items-center pt-3",
2613
- "bg-layer-canvas",
2614
- "px-5 max-md:px-4",
2615
- "pb-[calc(env(safe-area-inset-bottom)+1rem)] max-md:pb-[calc(env(safe-area-inset-bottom)+0.5rem)]"
2616
- ]
2617
- },
2618
- variants: { edge: {
2619
- inset: { root: "group/panel-frame" },
2620
- attached: { root: ["group/panel-frame", "border-l border-line-seam max-md:border-l-0"] }
2621
- } }
2622
- });
2623
- //#endregion
2624
- //#region src/components/panel/panel.tsx
2625
- function Panel({ className, edge, render, ...props }) {
2626
- const { root } = panel({ edge });
2627
- const defaultProps = {
2628
- "data-edge": edge,
2629
- "data-slot": "panel",
2630
- className: root({ className })
2631
- };
2632
- return useRender({
2633
- defaultTagName: "section",
2634
- render,
2635
- props: mergeProps(defaultProps, props)
2636
- });
2637
- }
2638
- /**
2639
- * Bare header bar: fixed height and centered flex row, no border, fill, or padding.
2640
- * Shared base for `PanelHeader`, `PanelSectionHeader`, and panel-specific headers
2641
- * such as `ThreadPanelHeader` — it is not exclusive to `PanelHeader`.
2642
- */
2643
- function PanelHeaderRoot({ className, render, ...props }) {
2644
- const { header } = panel();
2645
- const defaultProps = {
2646
- "data-slot": "panel-header-root",
2647
- className: header({ className })
2648
- };
2649
- return useRender({
2650
- defaultTagName: "div",
2651
- render,
2652
- props: mergeProps(defaultProps, props)
2653
- });
2654
- }
2655
- function PanelBody({ className, render, ...props }) {
2656
- const { body } = panel();
2657
- const defaultProps = {
2658
- "data-slot": "panel-body",
2659
- className: body({ className })
2660
- };
2661
- return useRender({
2662
- defaultTagName: "div",
2663
- render,
2664
- props: mergeProps(defaultProps, props)
2665
- });
2666
- }
2667
- function PanelScrollViewport({ className, render, ...props }) {
2668
- const { scrollViewport } = panel();
2669
- const defaultProps = {
2670
- "data-slot": "panel-scroll-viewport",
2671
- className: scrollViewport({ className })
2672
- };
2673
- return useRender({
2674
- defaultTagName: "div",
2675
- render,
2676
- props: mergeProps(defaultProps, props)
2677
- });
2678
- }
2679
- function PanelScrollContent({ className, render, ...props }) {
2680
- const { scrollContent } = panel();
2681
- const defaultProps = {
2682
- "data-slot": "panel-scroll-content",
2683
- className: scrollContent({ className })
2684
- };
2685
- return useRender({
2686
- defaultTagName: "div",
2687
- render,
2688
- props: mergeProps(defaultProps, props)
2689
- });
2690
- }
2691
- function PanelSection({ className, render, ...props }) {
2692
- const { section } = panel();
2693
- const defaultProps = {
2694
- "data-slot": "panel-section",
2695
- className: section({ className })
2696
- };
2697
- return useRender({
2698
- defaultTagName: "section",
2699
- render,
2700
- props: mergeProps(defaultProps, props)
2701
- });
2702
- }
2703
- function PanelFooter({ className, render, ...props }) {
2704
- const { footer } = panel();
2705
- const defaultProps = {
2706
- "data-slot": "panel-footer",
2707
- className: footer({ className })
2708
- };
2709
- return useRender({
2710
- defaultTagName: "div",
2711
- render,
2712
- props: mergeProps(defaultProps, props)
2713
- });
2714
- }
2715
- //#endregion
2716
2495
  //#region src/components/conversation-panel/conversation-panel.recipe.ts
2717
2496
  const conversationPanel = tv({ slots: {
2718
2497
  root: ["flex h-full min-h-0 min-w-0 flex-1 flex-col", "bg-layer-canvas font-sans text-foreground"],
@@ -2836,37 +2615,6 @@ function ConversationPanelEmptyStateBrandMark({ className, render, ...props }) {
2836
2615
  });
2837
2616
  }
2838
2617
  //#endregion
2839
- //#region src/components/kbd/kbd.tsx
2840
- const kbd = tv({ slots: {
2841
- root: [
2842
- "pointer-events-none inline-flex w-fit shrink-0 items-center justify-center gap-1",
2843
- "whitespace-nowrap select-none",
2844
- "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-3",
2845
- "min-w-4 rounded-[3px] px-1",
2846
- "font-mono text-mono-meta font-normal text-foreground-hint",
2847
- "inset-ring inset-ring-line-hairline",
2848
- "in-data-[slot=tooltip-content]:text-foreground-on-hud/70",
2849
- "in-data-[slot=tooltip-content]:shadow-[inset_0_0_0_1px_color-mix(in_oklch,var(--foreground-on-hud)_70%,transparent)]"
2850
- ],
2851
- group: ["inline-flex items-center gap-1"]
2852
- } });
2853
- function Kbd({ className, ...props }) {
2854
- const { root } = kbd();
2855
- return /* @__PURE__ */ jsx("kbd", {
2856
- "data-slot": "kbd",
2857
- className: root({ className }),
2858
- ...props
2859
- });
2860
- }
2861
- function KbdGroup({ className, ...props }) {
2862
- const { group } = kbd();
2863
- return /* @__PURE__ */ jsx("span", {
2864
- "data-slot": "kbd-group",
2865
- className: group({ className }),
2866
- ...props
2867
- });
2868
- }
2869
- //#endregion
2870
2618
  //#region src/components/context-menu/context-menu.tsx
2871
2619
  const contextMenu = tv({ slots: {
2872
2620
  trigger: ["select-none"],
@@ -3126,288 +2874,6 @@ function ContextMenuCheckboxItemIndicator({ className, ...props }) {
3126
2874
  });
3127
2875
  }
3128
2876
  //#endregion
3129
- //#region src/components/dropdown-menu/dropdown-menu.tsx
3130
- const dropdownMenu = tv({ slots: {
3131
- trigger: ["select-none"],
3132
- positioner: ["isolate z-50 outline-none"],
3133
- content: [
3134
- "max-h-(--available-height) overflow-hidden",
3135
- "outline-none",
3136
- "flex min-w-60 flex-col gap-0 rounded-container bg-layer-popover p-1.5 text-foreground",
3137
- "shadow-float ring-1 ring-line-seam"
3138
- ],
3139
- item: [
3140
- "flex w-full cursor-default select-none items-center [@media(max-height:600px)]:py-1",
3141
- "text-left outline-none transition-colors",
3142
- "min-h-9 gap-2.5 rounded-control px-2.5 py-1.5",
3143
- "font-sans text-callout font-medium text-foreground",
3144
- "hover:bg-brand-soft data-highlighted:bg-brand-soft",
3145
- "data-checked:font-bold data-[selected]:font-bold data-[emphasis=strong]:font-bold",
3146
- "data-disabled:pointer-events-none data-disabled:text-foreground-disabled",
3147
- "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&>svg:not([class*='size-'])]:size-4",
3148
- "[&>svg]:text-foreground-muted data-disabled:[&>svg]:text-foreground-disabled"
3149
- ],
3150
- radioItem: [
3151
- "flex w-full cursor-default select-none items-center",
3152
- "text-left outline-none transition-colors",
3153
- "min-h-9 gap-2.5 rounded-control px-2.5 py-1.5",
3154
- "font-sans text-callout font-medium text-foreground",
3155
- "hover:bg-brand-soft data-highlighted:bg-brand-soft",
3156
- "data-checked:font-bold",
3157
- "data-disabled:pointer-events-none data-disabled:text-foreground-disabled",
3158
- "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&>svg:not([class*='size-'])]:size-4",
3159
- "[&>svg]:text-foreground-muted data-disabled:[&>svg]:text-foreground-disabled"
3160
- ],
3161
- submenuTrigger: [
3162
- "flex w-full cursor-default select-none items-center [@media(max-height:600px)]:py-1",
3163
- "text-left outline-none transition-colors",
3164
- "min-h-9 gap-2.5 rounded-control px-2.5 py-1.5",
3165
- "font-sans text-callout font-medium text-foreground",
3166
- "hover:bg-brand-soft data-highlighted:bg-brand-soft data-popup-open:bg-brand-soft",
3167
- "data-disabled:pointer-events-none data-disabled:text-foreground-disabled",
3168
- "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&>svg:not([class*='size-'])]:size-4",
3169
- "[&>svg]:text-foreground-muted data-disabled:[&>svg]:text-foreground-disabled"
3170
- ],
3171
- itemLabel: ["min-w-0 flex-1 truncate text-left"],
3172
- footer: ["px-3 py-2 text-xs text-foreground-muted tabular-nums"],
3173
- label: ["px-2.5 pt-2 pb-1", "font-sans text-caption font-bold text-foreground-hint"],
3174
- shortcut: [
3175
- "ml-auto",
3176
- "h-auto min-w-0 rounded-none bg-transparent p-0 shadow-none ring-0",
3177
- "font-mono text-mono-meta font-normal text-foreground-hint"
3178
- ],
3179
- itemCount: ["ml-auto inline-flex min-w-5 justify-center gap-0 px-1 tabular-nums"],
3180
- separator: ["-mx-1.5 my-1.5 h-px border-0 bg-line-hairline"],
3181
- indicator: ["pointer-events-none ml-auto flex shrink-0 items-center justify-center", "size-4 text-foreground [&_svg]:size-4"],
3182
- radioLabel: ["min-w-0 flex-1 truncate"]
3183
- } });
3184
- function DropdownMenu(props) {
3185
- return /* @__PURE__ */ jsx(Menu.Root, {
3186
- "data-slot": "dropdown-menu",
3187
- ...props
3188
- });
3189
- }
3190
- function DropdownMenuSubmenu(props) {
3191
- return /* @__PURE__ */ jsx(Menu.SubmenuRoot, {
3192
- "data-slot": "dropdown-menu-submenu",
3193
- ...props
3194
- });
3195
- }
3196
- function DropdownMenuTrigger({ className, render = /* @__PURE__ */ jsx(Button, {
3197
- variant: "outline",
3198
- size: "md"
3199
- }), ...props }) {
3200
- const { trigger } = dropdownMenu();
3201
- return /* @__PURE__ */ jsx(Menu.Trigger, {
3202
- "data-slot": "dropdown-menu-trigger",
3203
- render,
3204
- className: trigger({ className }),
3205
- ...props
3206
- });
3207
- }
3208
- function DropdownMenuPortal(props) {
3209
- return /* @__PURE__ */ jsx(Menu.Portal, {
3210
- "data-slot": "dropdown-menu-portal",
3211
- ...useThemeScopeProps(props)
3212
- });
3213
- }
3214
- function DropdownMenuPopup({ className, ...props }) {
3215
- const { content } = dropdownMenu();
3216
- return /* @__PURE__ */ jsx("div", {
3217
- "data-slot": "dropdown-menu-content",
3218
- className: content({ className }),
3219
- ...props
3220
- });
3221
- }
3222
- function DropdownMenuContent({ align = "start", alignOffset = 0, anchor, arrowPadding, collisionAvoidance, collisionBoundary, collisionPadding, disableAnchorTracking = false, positionMethod = "fixed", side = "bottom", sideOffset, sticky, portalProps, className, ...props }) {
3223
- const resolvedSideOffset = sideOffset ?? 6;
3224
- const { positioner, content } = dropdownMenu();
3225
- return /* @__PURE__ */ jsx(DropdownMenuPortal, {
3226
- ...portalProps,
3227
- children: /* @__PURE__ */ jsx(Menu.Positioner, {
3228
- align,
3229
- alignOffset,
3230
- anchor,
3231
- arrowPadding,
3232
- collisionAvoidance,
3233
- collisionBoundary,
3234
- collisionPadding,
3235
- disableAnchorTracking,
3236
- positionMethod,
3237
- side,
3238
- sideOffset: resolvedSideOffset,
3239
- sticky,
3240
- className: positioner(),
3241
- children: /* @__PURE__ */ jsx(Menu.Popup, {
3242
- "data-slot": "dropdown-menu-content",
3243
- className: content({ className }),
3244
- ...props
3245
- })
3246
- })
3247
- });
3248
- }
3249
- function DropdownMenuItem({ className, ...props }) {
3250
- const { item } = dropdownMenu();
3251
- return /* @__PURE__ */ jsx(Menu.Item, {
3252
- "data-slot": "dropdown-menu-item",
3253
- className: item({ className }),
3254
- ...props
3255
- });
3256
- }
3257
- function DropdownMenuItemLabel({ className, ...props }) {
3258
- const { itemLabel } = dropdownMenu();
3259
- return /* @__PURE__ */ jsx("span", {
3260
- "data-slot": "dropdown-menu-item-label",
3261
- className: itemLabel({ className }),
3262
- ...props
3263
- });
3264
- }
3265
- function DropdownMenuFooter({ className, ...props }) {
3266
- const { footer } = dropdownMenu();
3267
- return /* @__PURE__ */ jsx("div", {
3268
- "data-slot": "dropdown-menu-footer",
3269
- className: footer({ className }),
3270
- ...props
3271
- });
3272
- }
3273
- function DropdownMenuSubmenuTrigger({ children, className, ...props }) {
3274
- const { submenuTrigger, indicator } = dropdownMenu();
3275
- return /* @__PURE__ */ jsxs(Menu.SubmenuTrigger, {
3276
- "data-slot": "dropdown-menu-submenu-trigger",
3277
- className: submenuTrigger({ className }),
3278
- ...props,
3279
- children: [children, /* @__PURE__ */ jsx("span", {
3280
- className: indicator(),
3281
- "data-slot": "dropdown-menu-submenu-trigger-indicator",
3282
- "aria-hidden": "true",
3283
- children: /* @__PURE__ */ jsx(DropdownMenuSubmenuChevronIcon, {})
3284
- })]
3285
- });
3286
- }
3287
- function DropdownMenuLabel({ className, ...props }) {
3288
- const { label } = dropdownMenu();
3289
- return /* @__PURE__ */ jsx("div", {
3290
- "data-slot": "dropdown-menu-label",
3291
- className: label({ className }),
3292
- ...props
3293
- });
3294
- }
3295
- function DropdownMenuShortcut({ className, ...props }) {
3296
- const { shortcut } = dropdownMenu();
3297
- return /* @__PURE__ */ jsx(Kbd, {
3298
- "data-slot": "dropdown-menu-shortcut",
3299
- className: shortcut({ className }),
3300
- ...props
3301
- });
3302
- }
3303
- function DropdownMenuItemCount({ className, ...props }) {
3304
- const { itemCount } = dropdownMenu();
3305
- return /* @__PURE__ */ jsx(Badge, {
3306
- "data-slot": "dropdown-menu-item-count",
3307
- className: itemCount({ className }),
3308
- ...props
3309
- });
3310
- }
3311
- function DropdownMenuSeparator({ className, ...props }) {
3312
- const { separator } = dropdownMenu();
3313
- return /* @__PURE__ */ jsx(Menu.Separator, {
3314
- "data-slot": "dropdown-menu-separator",
3315
- className: separator({ className }),
3316
- ...props
3317
- });
3318
- }
3319
- function DropdownMenuSubmenuChevronIcon() {
3320
- return /* @__PURE__ */ jsx("svg", {
3321
- width: "12",
3322
- height: "12",
3323
- viewBox: "0 0 12 12",
3324
- "aria-hidden": true,
3325
- className: "size-3 shrink-0",
3326
- children: /* @__PURE__ */ jsx("g", {
3327
- fill: "none",
3328
- strokeLinecap: "round",
3329
- strokeLinejoin: "round",
3330
- strokeWidth: "1",
3331
- stroke: "currentColor",
3332
- children: /* @__PURE__ */ jsx("path", { d: "M4.25 2.5L7.75 6l-3.5 3.5" })
3333
- })
3334
- });
3335
- }
3336
- function DropdownMenuCheckIcon() {
3337
- return /* @__PURE__ */ jsx("svg", {
3338
- width: "12",
3339
- height: "12",
3340
- viewBox: "0 0 12 12",
3341
- "aria-hidden": true,
3342
- className: "size-3 shrink-0",
3343
- children: /* @__PURE__ */ jsx("g", {
3344
- fill: "none",
3345
- strokeLinecap: "round",
3346
- strokeLinejoin: "round",
3347
- strokeWidth: "1",
3348
- stroke: "currentColor",
3349
- children: /* @__PURE__ */ jsx("path", { d: "M1.75 6.41L4.4 9.25L10.25 2.99" })
3350
- })
3351
- });
3352
- }
3353
- function DropdownMenuRadioGroup({ ...props }) {
3354
- return /* @__PURE__ */ jsx(Menu.RadioGroup, {
3355
- "data-slot": "dropdown-menu-radio-group",
3356
- ...props
3357
- });
3358
- }
3359
- function DropdownMenuRadioItem({ className, children, ...props }) {
3360
- const { radioItem, radioLabel, indicator } = dropdownMenu();
3361
- return /* @__PURE__ */ jsxs(Menu.RadioItem, {
3362
- "data-slot": "dropdown-menu-radio-item",
3363
- className: radioItem({ className }),
3364
- ...props,
3365
- children: [renderRadioItemChildren(children, radioLabel()), /* @__PURE__ */ jsx("span", {
3366
- className: indicator(),
3367
- children: /* @__PURE__ */ jsx(Menu.RadioItemIndicator, { children: /* @__PURE__ */ jsx(DropdownMenuCheckIcon, {}) })
3368
- })]
3369
- });
3370
- }
3371
- function renderRadioItemChildren(children, className) {
3372
- if (typeof children === "string" || typeof children === "number") return /* @__PURE__ */ jsx("span", {
3373
- "data-slot": "dropdown-menu-radio-item-label",
3374
- className,
3375
- children
3376
- });
3377
- if (Array.isArray(children) && children.every((child) => typeof child === "string")) return /* @__PURE__ */ jsx("span", {
3378
- "data-slot": "dropdown-menu-radio-item-label",
3379
- className,
3380
- children
3381
- });
3382
- return children;
3383
- }
3384
- function DropdownMenuRadioItemIndicator({ className, ...props }) {
3385
- return /* @__PURE__ */ jsx(Menu.RadioItemIndicator, {
3386
- "data-slot": "dropdown-menu-radio-item-indicator",
3387
- className,
3388
- ...props
3389
- });
3390
- }
3391
- function DropdownMenuCheckboxItem({ className, children, ...props }) {
3392
- const { item, indicator } = dropdownMenu();
3393
- return /* @__PURE__ */ jsxs(Menu.CheckboxItem, {
3394
- "data-slot": "dropdown-menu-checkbox-item",
3395
- className: item({ className }),
3396
- ...props,
3397
- children: [children, /* @__PURE__ */ jsx("span", {
3398
- className: indicator(),
3399
- children: /* @__PURE__ */ jsx(Menu.CheckboxItemIndicator, { children: /* @__PURE__ */ jsx(DropdownMenuCheckIcon, {}) })
3400
- })]
3401
- });
3402
- }
3403
- function DropdownMenuCheckboxItemIndicator({ className, ...props }) {
3404
- return /* @__PURE__ */ jsx(Menu.CheckboxItemIndicator, {
3405
- "data-slot": "dropdown-menu-checkbox-item-indicator",
3406
- className,
3407
- ...props
3408
- });
3409
- }
3410
- //#endregion
3411
2877
  //#region src/components/lightbox/lightbox.tsx
3412
2878
  const lightbox = tv({ slots: {
3413
2879
  backdrop: ["fixed inset-0 z-70 bg-layer-backdrop data-closed:hidden"],
@@ -5647,317 +5113,53 @@ function DescriptionDetails({ className, render, ...props }) {
5647
5113
  });
5648
5114
  }
5649
5115
  //#endregion
5650
- //#region src/components/avatar/avatar.tsx
5651
- const avatar = tv({
5652
- slots: {
5653
- root: [
5654
- "group/avatar relative flex shrink-0 items-center justify-center select-none",
5655
- "rounded-sticker border-[1.5px] border-sticker-ink",
5656
- "text-sticker-ink shadow-[0_0_0_1.5px_var(--sticker-edge)]"
5657
- ],
5658
- image: ["size-full object-cover", "rounded-[2px]"],
5659
- fallback: [
5660
- "flex size-full items-center justify-center",
5661
- "[&>svg]:size-4",
5662
- "group-data-[size=lg]/avatar:[&>svg]:size-6",
5663
- "group-data-[size=md]/avatar:[&>svg]:size-4.5",
5664
- "group-data-[size=xs]/avatar:[&>svg]:size-3",
5665
- "overflow-hidden rounded-[2px]",
5666
- "font-sans text-[15px] leading-none font-bold tracking-[-0.01em] text-sticker-ink",
5667
- "group-data-[size=xl]/avatar:text-[40px]",
5668
- "group-data-[size=lg]/avatar:text-[22px]",
5669
- "group-data-[size=sm]/avatar:text-[13px]",
5670
- "group-data-[size=xs]/avatar:text-[11px]",
5671
- "group-data-[size=2xs]/avatar:text-[11px]",
5672
- "group-data-[size=3xs]/avatar:text-[8px]",
5673
- "group-data-[size=xl]/avatar:[&>svg]:size-12",
5674
- "group-data-[size=sm]/avatar:[&>svg]:size-3.5",
5675
- "group-data-[size=2xs]/avatar:[&>svg]:size-3",
5676
- "group-data-[size=3xs]/avatar:[&>svg]:size-2"
5677
- ],
5678
- badge: [
5679
- "absolute z-10 select-none",
5680
- "size-[11px] -right-1 -bottom-1 rounded-[2px]",
5681
- "outline-2 outline-solid outline-layer-canvas",
5682
- "group-data-[size=xl]/avatar:size-5 group-data-[size=xl]/avatar:-right-2 group-data-[size=xl]/avatar:-bottom-2",
5683
- "group-data-[size=lg]/avatar:size-3.5 group-data-[size=lg]/avatar:right-[-5px] group-data-[size=lg]/avatar:bottom-[-5px]",
5684
- "group-data-[size=md]/avatar:size-[11px]",
5685
- "group-data-[size=sm]/avatar:size-[9px] group-data-[size=sm]/avatar:right-[-3px] group-data-[size=sm]/avatar:bottom-[-3px]",
5686
- "group-data-[size=xs]/avatar:size-[7px] group-data-[size=xs]/avatar:-right-0.5 group-data-[size=xs]/avatar:-bottom-0.5",
5687
- "group-data-[size=2xs]/avatar:size-[7px] group-data-[size=2xs]/avatar:-right-0.5 group-data-[size=2xs]/avatar:-bottom-0.5",
5688
- "group-data-[size=3xs]/avatar:size-1.5 group-data-[size=3xs]/avatar:-right-0.5 group-data-[size=3xs]/avatar:-bottom-0.5"
5689
- ],
5690
- dot: [
5691
- "inline-flex items-center justify-center outline-2",
5692
- "[&>svg]:hidden",
5693
- "group-data-[size=xl]/avatar:[&>svg]:size-2 group-data-[size=xl]/avatar:[&>svg]:block",
5694
- "group-data-[size=lg]/avatar:[&>svg]:size-2 group-data-[size=lg]/avatar:[&>svg]:block",
5695
- "group-data-[size=md]/avatar:[&>svg]:size-1.5 group-data-[size=md]/avatar:[&>svg]:block",
5696
- "group-data-[size=xs]/avatar:outline group-data-[size=2xs]/avatar:outline group-data-[size=3xs]/avatar:outline",
5697
- "rounded-[2px] border-[1.5px] border-sticker-ink",
5698
- "bg-(--status-color) text-sticker-ink outline-layer-canvas",
5699
- "group-data-[size=xl]/avatar:border-2",
5700
- "group-data-[size=xs]/avatar:border group-data-[size=2xs]/avatar:border group-data-[size=3xs]/avatar:border"
5701
- ],
5702
- group: [
5703
- "group/avatar-group flex items-center",
5704
- "stack-x-[-5px]",
5705
- "*:data-[slot=avatar]:shadow-[0_0_0_1.5px_var(--sticker-edge),0_0_0_3px_var(--avatar-group-surface,var(--layer-canvas))]",
5706
- "*:data-[slot=avatar-group-count]:shadow-[0_0_0_1.5px_var(--sticker-edge),0_0_0_3px_var(--avatar-group-surface,var(--layer-canvas))]"
5707
- ]
5708
- },
5709
- variants: {
5710
- type: {
5711
- agent: { root: ["bg-inactive"] },
5712
- human: { root: ["bg-palette-lavender"] }
5713
- },
5714
- size: {
5715
- xl: { root: ["size-[99px] shadow-[0_0_0_1.5px_var(--sticker-edge),var(--elevation-sticker)]"] },
5716
- lg: { root: ["size-[51px]"] },
5717
- md: { root: ["size-[35px]"] },
5718
- sm: { root: ["size-[27px]"] },
5719
- xs: { root: ["size-[19px]"] },
5720
- "2xs": { root: ["size-[19px]"] },
5721
- "3xs": { root: "size-3.5" }
5722
- }
5723
- }
5724
- });
5725
- function Avatar({ size, type, className, children, ...props }) {
5726
- const { root } = avatar({
5727
- type,
5728
- size
5729
- });
5730
- return /* @__PURE__ */ jsx(Avatar$1.Root, {
5731
- "data-slot": "avatar",
5732
- "data-size": size,
5733
- className: root({ className }),
5734
- ...props,
5735
- children: children ?? /* @__PURE__ */ jsx(AvatarFallback, {})
5736
- });
5737
- }
5738
- function AvatarImage({ className, ...props }) {
5739
- const { image } = avatar();
5740
- return /* @__PURE__ */ jsx(Avatar$1.Image, {
5741
- "data-slot": "avatar-image",
5742
- className: image({ className }),
5743
- ...props
5744
- });
5745
- }
5746
- function AvatarFallbackIcon() {
5747
- return /* @__PURE__ */ jsx("svg", {
5748
- xmlns: "http://www.w3.org/2000/svg",
5749
- width: "18",
5750
- height: "18",
5751
- viewBox: "0 0 18 18",
5752
- "aria-hidden": "true",
5753
- focusable: "false",
5754
- children: /* @__PURE__ */ jsxs("g", {
5755
- fill: "none",
5756
- strokeLinecap: "round",
5757
- strokeLinejoin: "round",
5758
- strokeWidth: "1",
5759
- stroke: "currentColor",
5760
- children: [
5761
- /* @__PURE__ */ jsx("circle", {
5762
- cx: "9",
5763
- cy: "7.75",
5764
- r: "2"
5765
- }),
5766
- /* @__PURE__ */ jsx("path", { d: "M9,16.25c1.407,0,2.716-.407,3.827-1.101-.481-1.67-2.003-2.899-3.827-2.899s-3.347,1.229-3.827,2.899c1.112,.694,2.42,1.101,3.827,1.101Z" }),
5767
- /* @__PURE__ */ jsx("circle", {
5768
- cx: "1.889",
5769
- cy: "10.414",
5770
- r: ".75",
5771
- fill: "currentColor",
5772
- "data-stroke": "none",
5773
- stroke: "none"
5774
- }),
5775
- /* @__PURE__ */ jsx("circle", {
5776
- cx: "2.971",
5777
- cy: "4.972",
5778
- r: ".75",
5779
- fill: "currentColor",
5780
- "data-stroke": "none",
5781
- stroke: "none"
5782
- }),
5783
- /* @__PURE__ */ jsx("circle", {
5784
- cx: "2.972",
5785
- cy: "13.027",
5786
- r: ".75",
5787
- fill: "currentColor",
5788
- "data-stroke": "none",
5789
- stroke: "none"
5790
- }),
5791
- /* @__PURE__ */ jsx("circle", {
5792
- cx: "1.89",
5793
- cy: "7.586",
5794
- r: ".75",
5795
- fill: "currentColor",
5796
- "data-stroke": "none",
5797
- stroke: "none"
5798
- }),
5799
- /* @__PURE__ */ jsx("circle", {
5800
- cx: "4.973",
5801
- cy: "2.972",
5802
- r: ".75",
5803
- fill: "currentColor",
5804
- "data-stroke": "none",
5805
- stroke: "none"
5806
- }),
5807
- /* @__PURE__ */ jsx("circle", {
5808
- cx: "7.586",
5809
- cy: "1.889",
5810
- r: ".75",
5811
- fill: "currentColor",
5812
- "data-stroke": "none",
5813
- stroke: "none"
5814
- }),
5815
- /* @__PURE__ */ jsx("circle", {
5816
- cx: "15.029",
5817
- cy: "13.028",
5818
- r: ".75",
5819
- fill: "currentColor",
5820
- "data-stroke": "none",
5821
- stroke: "none"
5822
- }),
5823
- /* @__PURE__ */ jsx("circle", {
5824
- cx: "16.111",
5825
- cy: "7.586",
5826
- r: ".75",
5827
- fill: "currentColor",
5828
- "data-stroke": "none",
5829
- stroke: "none"
5830
- }),
5831
- /* @__PURE__ */ jsx("circle", {
5832
- cx: "13.028",
5833
- cy: "2.971",
5834
- r: ".75",
5835
- fill: "currentColor",
5836
- "data-stroke": "none",
5837
- stroke: "none"
5838
- }),
5839
- /* @__PURE__ */ jsx("circle", {
5840
- cx: "16.11",
5841
- cy: "10.414",
5842
- r: ".75",
5843
- fill: "currentColor",
5844
- "data-stroke": "none",
5845
- stroke: "none"
5846
- }),
5847
- /* @__PURE__ */ jsx("circle", {
5848
- cx: "15.028",
5849
- cy: "4.973",
5850
- r: ".75",
5851
- fill: "currentColor",
5852
- "data-stroke": "none",
5853
- stroke: "none"
5854
- }),
5855
- /* @__PURE__ */ jsx("circle", {
5856
- cx: "10.414",
5857
- cy: "1.89",
5858
- r: ".75",
5859
- fill: "currentColor",
5860
- "data-stroke": "none",
5861
- stroke: "none"
5862
- })
5863
- ]
5864
- })
5865
- });
5866
- }
5867
- function AvatarFallback({ className, children, ...props }) {
5868
- const { fallback } = avatar();
5869
- return /* @__PURE__ */ jsx(Avatar$1.Fallback, {
5870
- "data-slot": "avatar-fallback",
5871
- className: fallback({ className }),
5872
- ...props,
5873
- children: children ?? /* @__PURE__ */ jsx(AvatarFallbackIcon, {})
5874
- });
5875
- }
5876
- const toCssLength = (value) => typeof value === "number" ? `${value}px` : value;
5877
- function AvatarBadge({ className, render, offset, presence = "online", ...props }) {
5878
- const { badge, dot } = avatar();
5879
- const offsetStyle = offset ? {
5880
- top: toCssLength(offset[1]),
5881
- left: toCssLength(offset[0]),
5882
- right: "auto",
5883
- bottom: "auto",
5884
- translate: "-50% -50%"
5885
- } : void 0;
5886
- const defaultProps = {
5887
- className: badge({ className: render ? className : dot({ className: cn(PRESENCE_COLOR[presence], className) }) }),
5888
- style: offsetStyle
5889
- };
5890
- return useRender({
5891
- defaultTagName: "span",
5892
- render,
5893
- props: mergeProps(defaultProps, props),
5894
- state: { slot: "avatar-badge" }
5895
- });
5896
- }
5897
- function AvatarGroup({ className, ...props }) {
5898
- const { group } = avatar();
5899
- return /* @__PURE__ */ jsx("div", {
5900
- "data-slot": "avatar-group",
5901
- className: group({ className }),
5902
- ...props
5903
- });
5904
- }
5905
- function AvatarGroupCount({ size, className, ...props }) {
5906
- const { root } = avatar({ size });
5907
- return /* @__PURE__ */ jsx("span", {
5908
- "data-slot": "avatar-group-count",
5909
- className: root({ class: ["border-transparent bg-fill-muted font-mono text-mono-meta font-bold tabular-nums text-foreground-muted shadow-none", className] }),
5910
- ...props
5911
- });
5912
- }
5913
- //#endregion
5914
- //#region src/components/code-block/code-block.recipe.ts
5915
- const codeBlock = tv({ slots: {
5916
- root: [
5917
- "group/code-block relative my-2 min-w-0",
5918
- "[--code-block-header-height:--spacing(10)]",
5919
- "overflow-clip px-0 pb-0",
5920
- "rounded-container border border-line-hairline bg-layer-code text-foreground"
5921
- ],
5922
- header: [
5923
- "flex h-(--code-block-header-height) items-center",
5924
- "gap-2 border-b border-line-hairline pr-1 pl-3",
5925
- "font-mono text-mono-meta text-foreground-hint"
5926
- ],
5927
- title: ["min-w-0 flex-1 truncate font-mono", "text-mono-meta"],
5928
- actions: [
5929
- "ml-auto flex items-center gap-2",
5930
- "[[data-slot=code-block-body]>&]:absolute [[data-slot=code-block-body]>&]:top-2",
5931
- "[[data-slot=code-block-body]>&]:right-2 [[data-slot=code-block-body]>&]:z-10"
5932
- ],
5933
- corner: [
5934
- "pointer-events-none absolute z-20 size-1",
5935
- "data-[y=top]:top-0 data-[y=bottom]:bottom-0",
5936
- "data-[x=left]:left-0 data-[x=right]:right-0",
5937
- "hidden"
5938
- ],
5939
- body: [
5940
- "relative min-w-0 overflow-x-auto p-4 font-mono",
5941
- "px-3 py-2 text-mono-code text-foreground",
5942
- "[&_pre_span]:text-(--shiki-light,currentColor)",
5943
- "dark:[&_pre_span]:text-(--shiki-dark,currentColor)"
5944
- ],
5945
- action: [
5946
- "inline-flex shrink-0 items-center justify-center",
5947
- "transition-[color,background-color,opacity]",
5948
- "focus-visible:outline-none",
5949
- "size-8 rounded-control text-foreground",
5950
- "hover:bg-fill-pressed active:bg-fill-pressed",
5951
- "focus-visible:ring-0 focus-visible:shadow-focus",
5952
- "[&_svg:not([class*='size-'])]:size-4.5"
5953
- ]
5954
- } });
5955
- //#endregion
5956
- //#region src/components/code-block/code-block.tsx
5957
- const CORNERS = [
5958
- {
5959
- x: "left",
5960
- y: "top"
5116
+ //#region src/components/code-block/code-block.recipe.ts
5117
+ const codeBlock = tv({ slots: {
5118
+ root: [
5119
+ "group/code-block relative my-2 min-w-0",
5120
+ "[--code-block-header-height:--spacing(10)]",
5121
+ "overflow-clip px-0 pb-0",
5122
+ "rounded-container border border-line-hairline bg-layer-code text-foreground"
5123
+ ],
5124
+ header: [
5125
+ "flex h-(--code-block-header-height) items-center",
5126
+ "gap-2 border-b border-line-hairline pr-1 pl-3",
5127
+ "font-mono text-mono-meta text-foreground-hint"
5128
+ ],
5129
+ title: ["min-w-0 flex-1 truncate font-mono", "text-mono-meta"],
5130
+ actions: [
5131
+ "ml-auto flex items-center gap-2",
5132
+ "[[data-slot=code-block-body]>&]:absolute [[data-slot=code-block-body]>&]:top-2",
5133
+ "[[data-slot=code-block-body]>&]:right-2 [[data-slot=code-block-body]>&]:z-10"
5134
+ ],
5135
+ corner: [
5136
+ "pointer-events-none absolute z-20 size-1",
5137
+ "data-[y=top]:top-0 data-[y=bottom]:bottom-0",
5138
+ "data-[x=left]:left-0 data-[x=right]:right-0",
5139
+ "hidden"
5140
+ ],
5141
+ body: [
5142
+ "relative min-w-0 overflow-x-auto p-4 font-mono",
5143
+ "px-3 py-2 text-mono-code text-foreground",
5144
+ "[&_pre_span]:text-(--shiki-light,currentColor)",
5145
+ "dark:[&_pre_span]:text-(--shiki-dark,currentColor)"
5146
+ ],
5147
+ action: [
5148
+ "inline-flex shrink-0 items-center justify-center",
5149
+ "transition-[color,background-color,opacity]",
5150
+ "focus-visible:outline-none",
5151
+ "size-8 rounded-control text-foreground",
5152
+ "hover:bg-fill-pressed active:bg-fill-pressed",
5153
+ "focus-visible:ring-0 focus-visible:shadow-focus",
5154
+ "[&_svg:not([class*='size-'])]:size-4.5"
5155
+ ]
5156
+ } });
5157
+ //#endregion
5158
+ //#region src/components/code-block/code-block.tsx
5159
+ const CORNERS = [
5160
+ {
5161
+ x: "left",
5162
+ y: "top"
5961
5163
  },
5962
5164
  {
5963
5165
  x: "right",
@@ -6076,20 +5278,6 @@ function InlineCode({ className, appearance, ...props }) {
6076
5278
  });
6077
5279
  }
6078
5280
  //#endregion
6079
- //#region src/lib/search-hit.ts
6080
- /**
6081
- * The DS search hit: what you looked for is a small yellow sticker, like an @
6082
- * to you. Every place that marks a hit (message text, Markdown, search
6083
- * results) uses this. The hit keeps the surrounding font (`[font:inherit]`
6084
- * drops the browser's mark styling) but is always bold, which needs `!` to win
6085
- * over that shorthand.
6086
- */
6087
- const searchHit = [
6088
- "[font:inherit] font-bold!",
6089
- "rounded-sticker bg-brand px-[3px] box-decoration-clone",
6090
- "text-sticker-ink inset-ring-[1.5px] inset-ring-sticker-ink ring-[1.5px] ring-sticker-edge"
6091
- ];
6092
- //#endregion
6093
5281
  //#region src/components/markdown/markdown.recipe.ts
6094
5282
  const markdown = tv({
6095
5283
  slots: {
@@ -6255,906 +5443,59 @@ function MarkdownTableScroll({ className, ...props }) {
6255
5443
  ...props
6256
5444
  });
6257
5445
  }
6258
- function MarkdownTable({ className, ...props }) {
6259
- const { table } = markdown();
6260
- return /* @__PURE__ */ jsx("table", {
6261
- "data-slot": "markdown-table",
6262
- className: table({ className }),
6263
- ...props
6264
- });
6265
- }
6266
- function MarkdownTableRow({ className, ...props }) {
6267
- const { tableRow } = markdown();
6268
- return /* @__PURE__ */ jsx("tr", {
6269
- "data-slot": "markdown-table-row",
6270
- className: tableRow({ className }),
6271
- ...props
6272
- });
6273
- }
6274
- function MarkdownHeaderCell({ className, ...props }) {
6275
- const { headerCell } = markdown();
6276
- return /* @__PURE__ */ jsx("th", {
6277
- "data-slot": "markdown-header-cell",
6278
- className: headerCell({ className }),
6279
- ...props
6280
- });
6281
- }
6282
- function MarkdownCell({ className, ...props }) {
6283
- const { cell } = markdown();
6284
- return /* @__PURE__ */ jsx("td", {
6285
- "data-slot": "markdown-cell",
6286
- className: cell({ className }),
6287
- ...props
6288
- });
6289
- }
6290
- function MarkdownImage({ className, ...props }) {
6291
- const { image } = markdown();
6292
- return /* @__PURE__ */ jsx("img", {
6293
- "data-slot": "markdown-image",
6294
- className: image({ className }),
6295
- ...props
6296
- });
6297
- }
6298
- function MarkdownInlineCode({ className, ...props }) {
6299
- const { inlineCode } = markdown();
6300
- return /* @__PURE__ */ jsx(InlineCode, {
6301
- className: inlineCode({ className }),
6302
- ...props
6303
- });
6304
- }
6305
- /** Task-list checkbox. Markdown task items are display-only, so it defaults to read-only. */
6306
- function MarkdownCheckbox({ className, ...props }) {
6307
- const { checkbox } = markdown();
6308
- return /* @__PURE__ */ jsx(Checkbox, {
6309
- readOnly: true,
6310
- className: checkbox({ className }),
6311
- ...props
6312
- });
6313
- }
6314
- //#endregion
6315
- //#region src/components/message-item/message-item.recipe.ts
6316
- const sender = [
6317
- "min-w-0 truncate",
6318
- "text-subhead font-bold text-foreground",
6319
- "rounded-[2px] outline-none focus-visible:shadow-focus"
6320
- ];
6321
- const messageItem = tv({
6322
- slots: {
6323
- root: [
6324
- "group/message relative flex h-fit gap-3",
6325
- "hover:[--mi-toolbar-opacity:1] hover:[--mi-toolbar-pe:auto] focus-within:[--mi-toolbar-opacity:1] focus-within:[--mi-toolbar-pe:auto]",
6326
- "has-data-popup-open:[--mi-toolbar-opacity:1] has-data-popup-open:[--mi-toolbar-pe:auto]",
6327
- "min-h-0 px-2 py-1 border-t-8 border-transparent bg-clip-padding",
6328
- "hover:bg-fill-pressed data-popup-open:bg-fill-pressed has-data-popup-open:bg-fill-pressed",
6329
- "hover:[--mi-ct-color:var(--foreground-hint)] has-data-popup-open:[--mi-ct-color:var(--foreground-hint)]",
6330
- "has-data-[slot=message-item-search-match]:bg-info-soft has-data-[slot=message-item-search-match]:hover:bg-info-soft",
6331
- "has-[[data-slot=message-multi-select-checkbox][data-checked]]:bg-info-soft",
6332
- "has-[[data-slot=message-multi-select-checkbox][data-checked]]:hover:bg-info-soft"
6333
- ],
6334
- gutter: ["relative shrink-0 self-stretch", "w-[35px]"],
6335
- avatarSlot: [
6336
- "relative shrink-0 self-start",
6337
- "flex w-[35px] justify-center",
6338
- "[&_[data-slot=avatar][data-size=md]]:size-(--mi-avatar,35px)"
6339
- ],
6340
- continuationTime: [
6341
- "absolute right-0 select-none whitespace-nowrap tabular-nums",
6342
- "top-[calc((var(--text-body--line-height)-var(--text-mono-meta--line-height))/2)]",
6343
- "font-mono text-mono-meta",
6344
- "text-(--mi-ct-color,transparent)"
6345
- ],
6346
- content: ["min-w-0 flex-1", "text-body text-foreground"],
6347
- header: ["mb-px flex min-w-0 items-center gap-1.5 overflow-hidden", "pointer-fine:pe-(--mi-toolbar-reserve,6.5rem)"],
6348
- senderGroup: ["flex min-w-0 items-center gap-1.5 overflow-hidden", "*:data-[slot=message-item-meta]:basis-0 *:data-[slot=message-item-meta]:grow"],
6349
- sender,
6350
- senderButton: [
6351
- ...sender,
6352
- "cursor-pointer",
6353
- "decoration-[1.5px] underline-offset-[3px] hover:underline"
6354
- ],
6355
- senderBadges: ["inline-flex shrink-0 items-center gap-1"],
6356
- meta: ["min-w-0 truncate", "text-caption text-foreground-hint"],
6357
- time: ["shrink-0 whitespace-nowrap", "font-mono text-mono-meta tabular-nums text-foreground-hint"],
6358
- inlineStatus: ["shrink-0", "text-caption text-foreground-hint"],
6359
- edited: ["ms-1 whitespace-nowrap", "text-caption text-foreground-hint"],
6360
- body: [
6361
- "wrap-break-word select-text",
6362
- "**:select-text",
6363
- "text-body text-foreground",
6364
- "selection:bg-brand-soft"
6365
- ],
6366
- searchMatch: searchHit,
6367
- embedded: ["min-w-0", "mt-2"],
6368
- attachments: ["stack-y-2", "mt-2"],
6369
- footer: ["mt-1.5 flex flex-wrap items-center gap-1.5"],
6370
- toolbar: [
6371
- "absolute z-20 flex items-center",
6372
- "opacity-(--mi-toolbar-opacity,0)",
6373
- "[pointer-events:var(--mi-toolbar-pe,none)]",
6374
- "top-[-16px] right-3 gap-0.5 overflow-visible rounded-container p-0.5",
6375
- "bg-layer-popover ring-1 ring-line-seam ring-inset shadow-float"
6376
- ],
6377
- toolbarButton: [
6378
- "inline-flex shrink-0 items-center justify-center",
6379
- "[&_svg]:shrink-0",
6380
- "size-7 rounded-control border-0 bg-transparent p-0",
6381
- "text-foreground-muted hover:bg-fill-pressed active:bg-fill-pressed",
6382
- "data-popup-open:bg-fill-pressed data-active:text-foreground",
6383
- "outline-none focus-visible:shadow-focus",
6384
- "[&_svg]:size-4"
6385
- ]
6386
- },
6387
- variants: { compact: { true: { root: ["border-t-0"] } } }
6388
- });
6389
- //#endregion
6390
- //#region src/components/message-item/message-item-root.tsx
6391
- function MessageItem({ className, compact, render, ...props }) {
6392
- const { root } = messageItem({ compact });
6393
- const defaultProps = {
6394
- "data-message-item": "",
6395
- "data-compact": compact ? "true" : void 0,
6396
- className: root({ className })
6397
- };
6398
- return useRender({
6399
- defaultTagName: "div",
6400
- render,
6401
- props: mergeProps(defaultProps, props),
6402
- state: { slot: "message-item" }
6403
- });
6404
- }
6405
- //#endregion
6406
- //#region src/components/message-item/message-item-gutter.tsx
6407
- function MessageItemGutter({ className, render, ...props }) {
6408
- const { gutter } = messageItem();
6409
- const defaultProps = { className: gutter({ className }) };
6410
- return useRender({
6411
- defaultTagName: "div",
6412
- render,
6413
- props: mergeProps(defaultProps, props),
6414
- state: { slot: "message-item-gutter" }
6415
- });
6416
- }
6417
- function MessageItemAvatarSlot({ className, render, ...props }) {
6418
- const { avatarSlot } = messageItem();
6419
- const defaultProps = { className: avatarSlot({ className }) };
6420
- return useRender({
6421
- defaultTagName: "div",
6422
- render,
6423
- props: mergeProps(defaultProps, props),
6424
- state: { slot: "message-item-avatar-slot" }
6425
- });
6426
- }
6427
- /** Left-gutter hover clock for continuation rows, a `<time>`: pass the moment in `dateTime`. Show the hour and minute only, in the person's 12h/24h format, with no AM/PM (`6:35`, `18:35`). */
6428
- function MessageItemContinuationTime({ className, render, ...props }) {
6429
- const { continuationTime } = messageItem();
6430
- const defaultProps = { className: continuationTime({ className }) };
6431
- return useRender({
6432
- defaultTagName: "time",
6433
- render,
6434
- props: mergeProps(defaultProps, props),
6435
- state: { slot: "message-item-continuation-time" }
6436
- });
6437
- }
6438
- //#endregion
6439
- //#region src/components/message-item/message-item-content.tsx
6440
- function MessageItemContent({ className, render, ...props }) {
6441
- const { content } = messageItem();
6442
- const defaultProps = { className: content({ className }) };
6443
- return useRender({
6444
- defaultTagName: "div",
6445
- render,
6446
- props: mergeProps(defaultProps, props),
6447
- state: { slot: "message-item-content" }
6448
- });
6449
- }
6450
- function MessageItemBody({ className, render, ...props }) {
6451
- const { body } = messageItem();
6452
- const defaultProps = { className: body({ className }) };
6453
- return useRender({
6454
- defaultTagName: "div",
6455
- render,
6456
- props: mergeProps(defaultProps, props),
6457
- state: { slot: "message-item-body" }
6458
- });
6459
- }
6460
- /**
6461
- * The edited marker, inline at the end of the message text on every row, full
6462
- * or continuation. Put it inside the last paragraph so it follows the last
6463
- * word; pass the copy ("(edited)") as children and the edit time as its tooltip.
6464
- */
6465
- function MessageItemEdited({ className, render, ...props }) {
6466
- const { edited } = messageItem();
6467
- const defaultProps = { className: edited({ className }) };
6468
- return useRender({
6469
- defaultTagName: "span",
6470
- render,
6471
- props: mergeProps(defaultProps, props),
6472
- state: { slot: "message-item-edited" }
6473
- });
6474
- }
6475
- function MessageItemSearchMatch({ className, render, ...props }) {
6476
- const { searchMatch } = messageItem();
6477
- const defaultProps = { className: searchMatch({ className }) };
6478
- return useRender({
6479
- defaultTagName: "mark",
6480
- render,
6481
- props: mergeProps(defaultProps, props),
6482
- state: { slot: "message-item-search-match" }
6483
- });
6484
- }
6485
- function MessageItemEmbedded({ className, render, ...props }) {
6486
- const { embedded } = messageItem();
6487
- const defaultProps = { className: embedded({ className }) };
6488
- return useRender({
6489
- defaultTagName: "div",
6490
- render,
6491
- props: mergeProps(defaultProps, props),
6492
- state: { slot: "message-item-embedded" }
6493
- });
6494
- }
6495
- function MessageItemAttachments({ className, render, ...props }) {
6496
- const { attachments } = messageItem();
6497
- const defaultProps = { className: attachments({ className }) };
6498
- return useRender({
6499
- defaultTagName: "div",
6500
- render,
6501
- props: mergeProps(defaultProps, props),
6502
- state: { slot: "message-item-attachments" }
6503
- });
6504
- }
6505
- function MessageItemFooter({ className, render, ...props }) {
6506
- const { footer } = messageItem();
6507
- const defaultProps = { className: footer({ className }) };
6508
- return useRender({
6509
- defaultTagName: "div",
6510
- render,
6511
- props: mergeProps(defaultProps, props),
6512
- state: { slot: "message-item-footer" }
6513
- });
6514
- }
6515
- //#endregion
6516
- //#region src/components/message-item/message-item-header.tsx
6517
- function MessageItemHeader({ className, render, ...props }) {
6518
- const { header } = messageItem();
6519
- const defaultProps = { className: header({ className }) };
6520
- return useRender({
6521
- defaultTagName: "div",
6522
- render,
6523
- props: mergeProps(defaultProps, props),
6524
- state: { slot: "message-item-header" }
6525
- });
6526
- }
6527
- /**
6528
- * Holds the sender, its badges and its role, and decides who gives way when
6529
- * the header runs out of room: the role truncates first, then the name. The
6530
- * badges stay whole beside the name, and the time, outside the group, never
6531
- * truncates.
6532
- */
6533
- function MessageItemSenderGroup({ className, render, ...props }) {
6534
- const { senderGroup } = messageItem();
6535
- const defaultProps = { className: senderGroup({ className }) };
6536
- return useRender({
6537
- defaultTagName: "span",
6538
- render,
6539
- props: mergeProps(defaultProps, props),
6540
- state: { slot: "message-item-sender-group" }
6541
- });
6542
- }
6543
- function MessageItemSender({ className, render, ...props }) {
6544
- const { sender } = messageItem();
6545
- const defaultProps = { className: sender({ className }) };
6546
- return useRender({
6547
- defaultTagName: "span",
6548
- render,
6549
- props: mergeProps(defaultProps, props),
6550
- state: { slot: "message-item-sender" }
6551
- });
6552
- }
6553
- function MessageItemSenderButton({ className, render, ...props }) {
6554
- const { senderButton } = messageItem();
6555
- const defaultProps = {
6556
- type: "button",
6557
- className: senderButton({ className })
6558
- };
6559
- return useRender({
6560
- defaultTagName: "button",
6561
- render,
6562
- props: mergeProps(defaultProps, props),
6563
- state: { slot: "message-item-sender-button" }
6564
- });
6565
- }
6566
- function MessageItemSenderBadges({ className, render, ...props }) {
6567
- const { senderBadges } = messageItem();
6568
- const defaultProps = { className: senderBadges({ className }) };
6569
- return useRender({
6570
- defaultTagName: "span",
6571
- render,
6572
- props: mergeProps(defaultProps, props),
6573
- state: { slot: "message-item-sender-badges" }
6574
- });
6575
- }
6576
- function MessageItemMeta({ className, render, ...props }) {
6577
- const { meta } = messageItem();
6578
- const defaultProps = { className: meta({ className }) };
6579
- return useRender({
6580
- defaultTagName: "span",
6581
- render,
6582
- props: mergeProps(defaultProps, props),
6583
- state: { slot: "message-item-meta" }
6584
- });
6585
- }
6586
- /**
6587
- * The message's time, right after the sender. A `<time>`: pass the moment in
6588
- * `dateTime` (ISO 8601) and the full date and time as its tooltip.
6589
- */
6590
- function MessageItemTime({ className, render, ...props }) {
6591
- const { time } = messageItem();
6592
- const defaultProps = { className: time({ className }) };
6593
- return useRender({
6594
- defaultTagName: "time",
6595
- render,
6596
- props: mergeProps(defaultProps, props),
6597
- state: { slot: "message-item-time" }
6598
- });
6599
- }
6600
- function MessageItemInlineStatus({ className, render, ...props }) {
6601
- const { inlineStatus } = messageItem();
6602
- const defaultProps = { className: inlineStatus({ className }) };
6603
- return useRender({
6604
- defaultTagName: "span",
6605
- render,
6606
- props: mergeProps(defaultProps, props),
6607
- state: { slot: "message-item-inline-status" }
6608
- });
6609
- }
6610
- //#endregion
6611
- //#region src/components/message-item/message-item-toolbar.tsx
6612
- function MessageItemToolbar({ className, render, ...props }) {
6613
- const { toolbar } = messageItem();
6614
- const defaultProps = { className: toolbar({ className }) };
6615
- return useRender({
6616
- defaultTagName: "div",
6617
- render,
6618
- props: mergeProps(defaultProps, props),
6619
- state: { slot: "message-item-toolbar" }
6620
- });
6621
- }
6622
- function MessageItemToolbarButton({ active = false, className, render, ...props }) {
6623
- const { toolbarButton } = messageItem();
6624
- const defaultProps = {
6625
- type: "button",
6626
- "data-active": active ? "true" : void 0,
6627
- className: toolbarButton({ className })
6628
- };
6629
- return useRender({
6630
- defaultTagName: "button",
6631
- render,
6632
- props: mergeProps(defaultProps, props),
6633
- state: { slot: "message-item-toolbar-button" }
6634
- });
6635
- }
6636
- //#endregion
6637
- //#region src/components/message-item/message-footer.recipe.ts
6638
- const messageFooter = tv({
6639
- slots: {
6640
- savedIndicator: [
6641
- "inline-flex min-w-0 max-w-full items-center gap-1 overflow-hidden whitespace-nowrap select-none",
6642
- "[&_svg]:shrink-0",
6643
- "h-[22px] rounded-chip px-1.5",
6644
- "text-caption font-semibold text-foreground-muted",
6645
- "bg-fill-muted hover:press-overlay active:press-overlay",
6646
- "outline-none focus-visible:shadow-focus",
6647
- "[&_svg]:size-3.5 [&_svg]:text-foreground"
6648
- ],
6649
- readReceipt: [
6650
- "ml-auto inline-flex shrink-0 items-center gap-1 whitespace-nowrap",
6651
- "[&_svg]:shrink-0",
6652
- "h-[22px] font-mono text-mono-meta text-foreground-hint [&_svg]:size-3"
6653
- ],
6654
- badge: [
6655
- "inline-flex min-w-0 max-w-full items-center overflow-hidden whitespace-nowrap select-none",
6656
- "transition-colors [&_svg]:shrink-0",
6657
- "h-6 gap-1 rounded-chip border-0 px-2 shadow-none",
6658
- "text-footnote font-bold text-foreground-muted",
6659
- "bg-fill-muted hover:press-overlay active:press-overlay",
6660
- "[&_svg]:size-3.5"
6661
- ],
6662
- badgeSeparator: ["text-foreground/45"]
6663
- },
6664
- variants: {
6665
- badgeStatus: {
6666
- read: {},
6667
- unread: { badge: ["text-foreground"] }
6668
- },
6669
- iconOnly: {
6670
- true: { savedIndicator: [
6671
- "justify-center p-0",
6672
- "size-8 rounded-control bg-transparent",
6673
- "[&_svg]:size-[18px] [&_svg]:text-foreground-muted"
6674
- ] },
6675
- false: {}
6676
- }
6677
- },
6678
- defaultVariants: { iconOnly: false }
6679
- });
6680
- //#endregion
6681
- //#region src/components/message-item/message-footer.tsx
6682
- function MessageItemBadge({ className, status = "read", ...props }) {
6683
- const { badge } = messageFooter({ badgeStatus: status });
6684
- return /* @__PURE__ */ jsx(Badge, {
6685
- appearance: "soft",
6686
- "data-slot": "message-item-badge",
6687
- variant: "muted",
6688
- className: badge({ className }),
6689
- ...props
6690
- });
6691
- }
6692
- function MessageItemBadgeSeparator({ className, render, ...props }) {
6693
- const { badgeSeparator } = messageFooter();
6694
- const defaultProps = {
6695
- "aria-hidden": true,
6696
- className: badgeSeparator({ className })
6697
- };
6698
- return useRender({
6699
- defaultTagName: "span",
6700
- render,
6701
- props: mergeProps(defaultProps, props),
6702
- state: { slot: "message-item-badge-separator" }
6703
- });
6704
- }
6705
- function MessageItemSavedIndicator({ className, iconOnly = false, render, ...props }) {
6706
- const { savedIndicator } = messageFooter({ iconOnly });
6707
- const defaultProps = {
6708
- ...iconOnly ? { "data-icon-only": "" } : {},
6709
- className: savedIndicator({ className })
6710
- };
6711
- return useRender({
6712
- defaultTagName: "span",
6713
- render,
6714
- props: mergeProps(defaultProps, props),
6715
- state: { slot: "message-item-saved-indicator" }
6716
- });
6717
- }
6718
- function MessageItemReadReceipt({ className, render, ...props }) {
6719
- const { readReceipt } = messageFooter();
6720
- const defaultProps = { className: readReceipt({ className }) };
6721
- return useRender({
6722
- defaultTagName: "span",
6723
- render,
6724
- props: mergeProps(defaultProps, props),
6725
- state: { slot: "message-item-read-receipt" }
6726
- });
6727
- }
6728
- //#endregion
6729
- //#region src/components/message-item/message-reaction.recipe.ts
6730
- const reactionCountKeyframes = [
6731
- {
6732
- opacity: .7,
6733
- transform: "translateY(1px) scale(0.92)",
6734
- offset: 0
6735
- },
6736
- {
6737
- opacity: 1,
6738
- transform: "translateY(-1px) scale(1.16)",
6739
- offset: .45
6740
- },
6741
- {
6742
- opacity: 1,
6743
- transform: "translateY(0) scale(1)",
6744
- offset: 1
6745
- }
6746
- ];
6747
- const reactionCountTiming = {
6748
- duration: 180,
6749
- easing: "cubic-bezier(0.2, 0, 0.2, 1)"
6750
- };
6751
- const messageReaction = tv({ slots: {
6752
- chip: [
6753
- "inline-flex min-w-0 max-w-full items-center overflow-hidden whitespace-nowrap",
6754
- "transition-colors",
6755
- "h-6 gap-1 rounded-chip pr-2 pl-1.5 text-callout text-foreground",
6756
- "bg-fill-muted hover:press-overlay active:press-overlay",
6757
- "data-pressed:bg-attention-soft",
6758
- "has-data-[slot=message-reaction-error-indicator]:bg-warning-soft",
6759
- "outline-none focus-visible:shadow-focus",
6760
- "[&_[data-slot=message-reaction-glyph]>svg]:size-4"
6761
- ],
6762
- errorIndicator: ["sr-only"],
6763
- glyph: ["inline-flex items-center justify-center leading-none", "[&>svg]:size-[13px] [&>svg]:shrink-0"],
6764
- count: ["inline-block origin-center font-mono tabular-nums", "text-mono-meta font-bold"],
6765
- addButton: [
6766
- "inline-flex min-w-0 items-center justify-center",
6767
- "transition-colors",
6768
- "[&_svg]:shrink-0",
6769
- "h-6 rounded-chip px-1.5 [&_svg]:size-4",
6770
- "bg-fill-muted text-foreground-muted hover:press-overlay active:press-overlay",
6771
- "outline-none focus-visible:shadow-focus"
6772
- ],
6773
- quickRow: [
6774
- "flex shrink-0 items-center",
6775
- "justify-between gap-0.5 bg-layer-popover px-0.5 py-0.5",
6776
- "[&>[role=menuitem]]:size-9 [&>[role=menuitem]]:p-0 *:[[role=menuitem]]:justify-center"
6777
- ],
6778
- quickButton: [
6779
- "flex items-center justify-center",
6780
- "bg-transparent transition-colors",
6781
- "size-9 rounded-control p-0 text-xl leading-none text-foreground-muted",
6782
- "hover:bg-brand-soft data-highlighted:bg-brand-soft active:bg-brand-soft",
6783
- "outline-none focus-visible:shadow-focus"
6784
- ],
6785
- pickerContent: [
6786
- "inline-flex items-center",
6787
- "min-w-0 flex-row gap-0.5 p-1",
6788
- "[&>[role=menuitem]]:size-9 [&>[role=menuitem]]:p-0"
6789
- ],
6790
- pickerStatic: [
6791
- "inline-flex items-center",
6792
- "min-w-0 flex-row gap-0.5 rounded-container p-1",
6793
- "bg-layer-popover ring-1 ring-line-seam shadow-float outline-none"
6794
- ],
6795
- tooltip: ["inline-block max-w-[280px]", "px-2.5 py-1 text-footnote font-medium"],
6796
- tooltipNames: ["flex max-w-60 flex-wrap items-center gap-y-0.5"],
6797
- tooltipName: ["inline-flex min-w-0 items-baseline leading-5"],
6798
- tooltipNameText: ["max-w-28 truncate"],
6799
- tooltipSeparator: ["shrink-0", "text-foreground-on-hud/70"],
6800
- tooltipMeta: ["leading-5", "text-foreground-on-hud/70"]
6801
- } });
6802
- //#endregion
6803
- //#region src/components/message-item/message-reaction.tsx
6804
- function MessageReactionChip({ className, ...props }) {
6805
- const { chip } = messageReaction();
6806
- return /* @__PURE__ */ jsx(Toggle, {
6807
- ...props,
6808
- type: "button",
6809
- "data-slot": "message-reaction-chip",
6810
- className: chip({ className })
6811
- });
6812
- }
6813
- function MessageReactionErrorIndicator({ className, render, ...props }) {
6814
- const { errorIndicator } = messageReaction();
6815
- const defaultProps = {
6816
- className: errorIndicator({ className }),
6817
- role: "status"
6818
- };
6819
- return useRender({
6820
- defaultTagName: "span",
6821
- render,
6822
- props: mergeProps(defaultProps, props),
6823
- state: { slot: "message-reaction-error-indicator" }
6824
- });
6825
- }
6826
- function MessageReactionGlyph({ className, render, ...props }) {
6827
- const { glyph: glyphSlot } = messageReaction();
6828
- const defaultProps = { className: glyphSlot({ className }) };
6829
- return useRender({
6830
- defaultTagName: "span",
6831
- render,
6832
- props: mergeProps(defaultProps, props),
6833
- state: { slot: "message-reaction-glyph" }
6834
- });
6835
- }
6836
- function MessageReactionCount({ children, className, render, ...props }) {
6837
- const elementRef = useRef(null);
6838
- const value = typeof children === "number" && Number.isFinite(children) ? children : null;
6839
- const previousValue = useRef(value);
6840
- useEffect(() => {
6841
- const previous = previousValue.current;
6842
- previousValue.current = value;
6843
- if (value === null || previous === null || value === previous) return;
6844
- const element = elementRef.current;
6845
- const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
6846
- if (!element?.animate || reducedMotion.matches) return;
6847
- const animation = element.animate(reactionCountKeyframes, reactionCountTiming);
6848
- const handleMotionChange = () => {
6849
- if (reducedMotion.matches) animation.cancel();
6850
- };
6851
- reducedMotion.addEventListener("change", handleMotionChange);
6852
- return () => {
6853
- animation.cancel();
6854
- reducedMotion.removeEventListener("change", handleMotionChange);
6855
- };
6856
- }, [value]);
6857
- const { count } = messageReaction();
6858
- const defaultProps = {
6859
- className: count({ className }),
6860
- children,
6861
- ref: elementRef
6862
- };
6863
- return useRender({
6864
- defaultTagName: "span",
6865
- render,
6866
- props: mergeProps(defaultProps, props),
6867
- state: { slot: "message-reaction-count" }
6868
- });
6869
- }
6870
- function MessageReactionAddButton({ className, render, ...props }) {
6871
- const { addButton } = messageReaction();
6872
- const defaultProps = {
6873
- type: "button",
6874
- className: addButton({ className })
6875
- };
6876
- return useRender({
6877
- defaultTagName: "button",
6878
- render,
6879
- props: mergeProps(defaultProps, props),
6880
- state: { slot: "message-reaction-add-button" }
6881
- });
6882
- }
6883
- function MessageReactionQuickRow({ className, render, ...props }) {
6884
- const { quickRow } = messageReaction();
6885
- const defaultProps = { className: quickRow({ className }) };
6886
- return useRender({
6887
- defaultTagName: "div",
6888
- render,
6889
- props: mergeProps(defaultProps, props),
6890
- state: { slot: "message-reaction-quick-row" }
6891
- });
6892
- }
6893
- function MessageReactionQuickButton({ className, render, ...props }) {
6894
- const { quickButton } = messageReaction();
6895
- const defaultProps = {
6896
- type: "button",
6897
- className: quickButton({ className })
6898
- };
6899
- return useRender({
6900
- defaultTagName: "button",
6901
- render,
6902
- props: mergeProps(defaultProps, props),
6903
- state: { slot: "message-reaction-quick-button" }
6904
- });
6905
- }
6906
- function MessageReactionPickerStatic({ className, render, ...props }) {
6907
- const { pickerStatic } = messageReaction();
6908
- const defaultProps = { className: pickerStatic({ className }) };
6909
- return useRender({
6910
- defaultTagName: "div",
6911
- render,
6912
- props: mergeProps(defaultProps, props),
6913
- state: { slot: "message-reaction-picker-static" }
6914
- });
6915
- }
6916
- function MessageReactionPickerContent({ className, ...props }) {
6917
- const { pickerContent } = messageReaction();
6918
- return /* @__PURE__ */ jsx(DropdownMenuContent, {
6919
- "data-slot": "message-reaction-picker",
6920
- className: pickerContent({ className }),
6921
- ...props
6922
- });
6923
- }
6924
- function MessageReactionTooltipContent({ className, ...props }) {
6925
- const { tooltip } = messageReaction();
6926
- return /* @__PURE__ */ jsx(TooltipContent, {
6927
- className: tooltip({ className }),
6928
- ...props
6929
- });
6930
- }
6931
- function MessageReactionTooltipNames({ className, render, ...props }) {
6932
- const { tooltipNames } = messageReaction();
6933
- const defaultProps = { className: tooltipNames({ className }) };
6934
- return useRender({
6935
- defaultTagName: "span",
6936
- render,
6937
- props: mergeProps(defaultProps, props),
6938
- state: { slot: "message-reaction-tooltip-names" }
6939
- });
6940
- }
6941
- function MessageReactionTooltipName({ className, render, ...props }) {
6942
- const { tooltipName } = messageReaction();
6943
- const defaultProps = { className: tooltipName({ className }) };
6944
- return useRender({
6945
- defaultTagName: "span",
6946
- render,
6947
- props: mergeProps(defaultProps, props),
6948
- state: { slot: "message-reaction-tooltip-name" }
6949
- });
6950
- }
6951
- function MessageReactionTooltipNameText({ className, render, ...props }) {
6952
- const { tooltipNameText } = messageReaction();
6953
- const defaultProps = { className: tooltipNameText({ className }) };
6954
- return useRender({
6955
- defaultTagName: "span",
6956
- render,
6957
- props: mergeProps(defaultProps, props),
6958
- state: { slot: "message-reaction-tooltip-name-text" }
6959
- });
6960
- }
6961
- function MessageReactionTooltipSeparator({ className, render, ...props }) {
6962
- const { tooltipSeparator } = messageReaction();
6963
- const defaultProps = { className: tooltipSeparator({ className }) };
6964
- return useRender({
6965
- defaultTagName: "span",
6966
- render,
6967
- props: mergeProps(defaultProps, props),
6968
- state: { slot: "message-reaction-tooltip-separator" }
6969
- });
6970
- }
6971
- function MessageReactionTooltipMeta({ className, render, ...props }) {
6972
- const { tooltipMeta } = messageReaction();
6973
- const defaultProps = { className: tooltipMeta({ className }) };
6974
- return useRender({
6975
- defaultTagName: "span",
6976
- render,
6977
- props: mergeProps(defaultProps, props),
6978
- state: { slot: "message-reaction-tooltip-meta" }
6979
- });
6980
- }
6981
- //#endregion
6982
- //#region src/components/message-item/message-reference.recipe.ts
6983
- const chip = (fill) => [
6984
- "items-baseline gap-0.5 rounded-sticker px-1.5 py-px has-[>svg]:pl-[3px]",
6985
- "[font-size:0.875em] leading-5 font-semibold",
6986
- "[&_svg]:size-3.5 [&_svg]:text-foreground-muted",
6987
- fill
6988
- ];
6989
- const linkChip = (fill) => [...chip(fill), "text-foreground cursor-pointer hover:press-overlay active:press-overlay"];
6990
- const messageReference = tv({
6991
- slots: {
6992
- root: [
6993
- "inline-flex items-baseline gap-1",
6994
- "py-0 align-baseline",
6995
- "[font-size:inherit] leading-[1.2em]",
6996
- "max-w-full truncate select-text no-underline",
6997
- "outline-none focus-visible:shadow-focus",
6998
- "[&_svg]:size-[0.857em] [&_svg]:shrink-0 [&_svg]:self-center",
6999
- "has-[>[data-slot=message-reference-indicator]]:relative has-[>[data-slot=message-reference-indicator]]:mr-2",
7000
- "has-[>[data-slot=message-reference-indicator]]:inline-block",
7001
- "has-[>[data-slot=message-reference-indicator]]:overflow-visible"
7002
- ],
7003
- chipLabel: "min-w-0 truncate",
7004
- indicator: ["pointer-events-none absolute -right-1.5 top-0 inline-flex size-2 shrink-0 items-center justify-center", "*:data-[slot=status]:size-full"]
7005
- },
7006
- variants: { variant: {
7007
- primary: { root: [
7008
- "inline-flex cursor-pointer rounded-sticker px-[3px]",
7009
- "font-semibold text-sticker-ink no-underline",
7010
- "bg-brand inset-ring-[1.5px] inset-ring-sticker-ink ring-[1.5px] ring-sticker-edge",
7011
- "hover:press-overlay-sticker"
7012
- ] },
7013
- secondary: { root: ["inline cursor-pointer font-bold text-foreground", "decoration-foreground decoration-[1.5px] underline-offset-[3px] hover:underline"] },
7014
- accent: { root: linkChip("bg-attention-soft") },
7015
- muted: { root: linkChip("bg-inactive-soft") },
7016
- info: { root: linkChip("bg-info-soft") },
7017
- link: { root: linkChip("bg-info-soft") },
7018
- pending: { root: chip("cursor-wait bg-inactive-soft text-foreground-muted") },
7019
- unavailable: { root: chip("cursor-default bg-inactive-soft text-foreground-hint") }
7020
- } },
7021
- defaultVariants: { variant: "muted" }
7022
- });
7023
- //#endregion
7024
- //#region src/components/message-item/message-reference.tsx
7025
- function useReferenceRender(className, render, props) {
7026
- return useRender({
7027
- defaultTagName: "span",
7028
- render,
7029
- props: mergeProps({ className }, props),
7030
- state: { slot: "message-reference" }
7031
- });
7032
- }
7033
- function MessageReferenceText({ className, render, variant = "secondary", ...props }) {
7034
- const { root } = messageReference({ variant });
7035
- return useReferenceRender(root({ className }), render, props);
7036
- }
7037
- function MessageReferenceIndicator({ className, render, ...props }) {
7038
- const { indicator } = messageReference();
7039
- const defaultProps = { className: indicator({ className }) };
7040
- return useRender({
7041
- defaultTagName: "span",
7042
- render,
7043
- props: mergeProps(defaultProps, props),
7044
- state: { slot: "message-reference-indicator" }
7045
- });
7046
- }
7047
- function MessageReferenceChip({ className, render, variant = "muted", ...props }) {
7048
- const { root } = messageReference({ variant });
7049
- return useReferenceRender(root({ className }), render, props);
7050
- }
7051
- function MessageReferenceLabel({ className, render, ...props }) {
7052
- const { chipLabel } = messageReference();
7053
- const defaultProps = { className: chipLabel({ className }) };
7054
- return useRender({
7055
- defaultTagName: "span",
7056
- render,
7057
- props: mergeProps(defaultProps, props),
7058
- state: { slot: "message-reference-label" }
5446
+ function MarkdownTable({ className, ...props }) {
5447
+ const { table } = markdown();
5448
+ return /* @__PURE__ */ jsx("table", {
5449
+ "data-slot": "markdown-table",
5450
+ className: table({ className }),
5451
+ ...props
7059
5452
  });
7060
5453
  }
7061
- function MessageReferencePending({ className, render, ...props }) {
7062
- const { root } = messageReference({ variant: "pending" });
7063
- return useReferenceRender(root({ className }), render, props);
7064
- }
7065
- function MessageReferenceUnavailable({ className, render, ...props }) {
7066
- const { root } = messageReference({ variant: "unavailable" });
7067
- return useReferenceRender(root({ className }), render, props);
7068
- }
7069
- //#endregion
7070
- //#region src/components/message-item/message-multi-select.recipe.ts
7071
- const messageMultiSelect = tv({ slots: {
7072
- root: ["flex min-h-0 min-w-0 flex-1 flex-col"],
7073
- checkbox: [
7074
- "self-start",
7075
- "data-checked:shadow-none data-indeterminate:shadow-none",
7076
- "hover:data-checked:shadow-none hover:data-indeterminate:shadow-none",
7077
- "mt-2 rounded-sticker"
7078
- ],
7079
- toolbar: [
7080
- "flex items-center",
7081
- "gap-2 rounded-container px-2.5 py-2",
7082
- "bg-layer-popover ring-1 ring-line-seam shadow-float"
7083
- ]
7084
- } });
7085
- //#endregion
7086
- //#region src/components/message-item/message-multi-select.tsx
7087
- function MessageMultiSelect({ className, render, ...props }) {
7088
- const { root } = messageMultiSelect();
7089
- const defaultProps = { className: root({ className }) };
7090
- return useRender({
7091
- defaultTagName: "div",
7092
- render,
7093
- props: mergeProps(defaultProps, props),
7094
- state: { slot: "message-multi-select" }
5454
+ function MarkdownTableRow({ className, ...props }) {
5455
+ const { tableRow } = markdown();
5456
+ return /* @__PURE__ */ jsx("tr", {
5457
+ "data-slot": "markdown-table-row",
5458
+ className: tableRow({ className }),
5459
+ ...props
7095
5460
  });
7096
5461
  }
7097
- /** Shared select-mode toolbar shell. Consumers compose the count and actions as children. */
7098
- function MessageMultiSelectToolbar({ className, render, ...props }) {
7099
- const { toolbar } = messageMultiSelect();
7100
- const defaultProps = { className: toolbar({ className }) };
7101
- return useRender({
7102
- defaultTagName: "div",
7103
- render,
7104
- props: mergeProps(defaultProps, props),
7105
- state: { slot: "message-multi-select-toolbar" }
5462
+ function MarkdownHeaderCell({ className, ...props }) {
5463
+ const { headerCell } = markdown();
5464
+ return /* @__PURE__ */ jsx("th", {
5465
+ "data-slot": "markdown-header-cell",
5466
+ className: headerCell({ className }),
5467
+ ...props
7106
5468
  });
7107
5469
  }
7108
- function MessageMultiSelectCheckbox({ className, ...props }) {
7109
- const { checkbox } = messageMultiSelect();
7110
- return /* @__PURE__ */ jsx(Checkbox, {
7111
- "data-slot": "message-multi-select-checkbox",
7112
- className: checkbox({ className }),
7113
- shape: "square",
5470
+ function MarkdownCell({ className, ...props }) {
5471
+ const { cell } = markdown();
5472
+ return /* @__PURE__ */ jsx("td", {
5473
+ "data-slot": "markdown-cell",
5474
+ className: cell({ className }),
7114
5475
  ...props
7115
5476
  });
7116
5477
  }
7117
- //#endregion
7118
- //#region src/components/message-item/message-text-selection-toolbar.recipe.ts
7119
- const messageTextSelectionToolbar = tv({ slots: {
7120
- toolbar: [
7121
- "flex min-w-0 items-center select-none",
7122
- "gap-0.5 overflow-visible rounded-container p-0.5 text-control font-bold",
7123
- "bg-layer-popover ring-1 ring-line-seam ring-inset shadow-float"
7124
- ],
7125
- button: [
7126
- "flex shrink-0 items-center gap-1.5 outline-none transition-colors",
7127
- "h-7 rounded-control px-2.5 whitespace-nowrap text-foreground",
7128
- "hover:bg-fill-pressed active:bg-fill-pressed",
7129
- "focus-visible:shadow-focus",
7130
- "[&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-foreground-muted"
7131
- ],
7132
- separator: ["w-px shrink-0", "mx-0.5 h-5 bg-line-hairline"]
7133
- } });
7134
- //#endregion
7135
- //#region src/components/message-item/message-text-selection-toolbar.tsx
7136
- function MessageTextSelectionToolbar({ className, ...props }) {
7137
- const { toolbar } = messageTextSelectionToolbar();
7138
- return /* @__PURE__ */ jsx(Toolbar.Root, {
7139
- "data-slot": "message-text-selection-toolbar",
7140
- className: toolbar({ className }),
5478
+ function MarkdownImage({ className, ...props }) {
5479
+ const { image } = markdown();
5480
+ return /* @__PURE__ */ jsx("img", {
5481
+ "data-slot": "markdown-image",
5482
+ className: image({ className }),
7141
5483
  ...props
7142
5484
  });
7143
5485
  }
7144
- function MessageTextSelectionToolbarButton({ className, ...props }) {
7145
- const { button } = messageTextSelectionToolbar();
7146
- return /* @__PURE__ */ jsx(Toolbar.Button, {
7147
- "data-slot": "message-text-selection-toolbar-button",
7148
- type: "button",
7149
- className: button({ className }),
5486
+ function MarkdownInlineCode({ className, ...props }) {
5487
+ const { inlineCode } = markdown();
5488
+ return /* @__PURE__ */ jsx(InlineCode, {
5489
+ className: inlineCode({ className }),
7150
5490
  ...props
7151
5491
  });
7152
5492
  }
7153
- function MessageTextSelectionToolbarSeparator({ className, ...props }) {
7154
- const { separator } = messageTextSelectionToolbar();
7155
- return /* @__PURE__ */ jsx(Toolbar.Separator, {
7156
- "data-slot": "message-text-selection-toolbar-separator",
7157
- className: separator({ className }),
5493
+ /** Task-list checkbox. Markdown task items are display-only, so it defaults to read-only. */
5494
+ function MarkdownCheckbox({ className, ...props }) {
5495
+ const { checkbox } = markdown();
5496
+ return /* @__PURE__ */ jsx(Checkbox, {
5497
+ readOnly: true,
5498
+ className: checkbox({ className }),
7158
5499
  ...props
7159
5500
  });
7160
5501
  }
@@ -7399,211 +5740,6 @@ function SystemMessageGroupPanel({ className, render, ...props }) {
7399
5740
  });
7400
5741
  }
7401
5742
  //#endregion
7402
- //#region src/components/message-embed/message-embed.recipe.ts
7403
- const messageEmbed = tv({ slots: {
7404
- root: [
7405
- "group block min-w-0 text-left",
7406
- "rounded-container border border-line-hairline bg-layer-card",
7407
- "outline-none focus-visible:shadow-focus"
7408
- ],
7409
- header: ["min-w-0", "px-3 py-2"],
7410
- content: ["min-w-0"],
7411
- footer: ["min-w-0", "px-3 py-2"]
7412
- } });
7413
- //#endregion
7414
- //#region src/components/message-embed/message-embed.tsx
7415
- function MessageEmbed({ className, render, ...props }) {
7416
- const { root } = messageEmbed();
7417
- return useRender({
7418
- defaultTagName: "div",
7419
- render,
7420
- props: mergeProps({ className: root({ className }) }, props),
7421
- state: { slot: "message-embed" }
7422
- });
7423
- }
7424
- function MessageEmbedHeader({ className, render, ...props }) {
7425
- const { header } = messageEmbed();
7426
- return useRender({
7427
- defaultTagName: "div",
7428
- render,
7429
- props: mergeProps({ className: header({ className }) }, props),
7430
- state: { slot: "message-embed-header" }
7431
- });
7432
- }
7433
- function MessageEmbedContent({ className, render, ...props }) {
7434
- const { content } = messageEmbed();
7435
- return useRender({
7436
- defaultTagName: "div",
7437
- render,
7438
- props: mergeProps({ className: content({ className }) }, props),
7439
- state: { slot: "message-embed-content" }
7440
- });
7441
- }
7442
- function MessageEmbedFooter({ className, render, ...props }) {
7443
- const { footer } = messageEmbed();
7444
- return useRender({
7445
- defaultTagName: "div",
7446
- render,
7447
- props: mergeProps({ className: footer({ className }) }, props),
7448
- state: { slot: "message-embed-footer" }
7449
- });
7450
- }
7451
- //#endregion
7452
- //#region src/components/message-quoted-preview/message-quoted-preview.recipe.ts
7453
- const messageQuotedPreview = tv({ slots: {
7454
- root: [
7455
- "w-full",
7456
- "rounded-none border-0 border-l-2 border-line-seam bg-transparent pl-2.5",
7457
- "text-foreground-muted"
7458
- ],
7459
- content: ["min-w-0", "p-0"],
7460
- header: ["flex min-w-0 items-center", "gap-1.5 p-0 pb-0.5"],
7461
- channel: ["inline-flex items-center", "gap-1 text-footnote font-semibold text-foreground-hint [&_svg]:size-3.5"],
7462
- thread: ["inline-flex items-center", "gap-1 text-footnote font-semibold text-foreground-hint [&_svg]:size-3.5"],
7463
- author: ["inline-flex min-w-0 items-center", "gap-1.5"],
7464
- authorName: ["truncate", "text-footnote font-bold text-foreground-muted"],
7465
- authorMeta: ["truncate", "text-caption text-foreground-hint"],
7466
- timestamp: ["ml-auto shrink-0", "font-mono text-mono-meta tabular-nums text-foreground-hint"],
7467
- text: ["line-clamp-2", "text-callout text-foreground-muted"],
7468
- attachments: ["flex flex-wrap gap-1.5", "mt-1.5"],
7469
- attachment: [
7470
- "inline-flex items-center",
7471
- "h-[22px] gap-1 rounded-chip bg-fill-muted px-1.5",
7472
- "font-mono text-mono-meta text-foreground-muted [&_svg]:size-3.5"
7473
- ],
7474
- loading: ["w-full animate-pulse", "rounded-none border-0 border-l-2 border-line-seam bg-transparent pl-2.5"],
7475
- unavailable: [
7476
- "block w-full text-left",
7477
- "border-l-2 border-line-seam pl-2.5",
7478
- "text-callout text-foreground-hint",
7479
- "outline-none focus-visible:shadow-focus"
7480
- ]
7481
- } });
7482
- //#endregion
7483
- //#region src/components/message-quoted-preview/message-quoted-preview.tsx
7484
- function MessageQuotedPreview({ className, render, ...props }) {
7485
- const { root } = messageQuotedPreview();
7486
- return /* @__PURE__ */ jsx(MessageEmbed, {
7487
- className: root({ className }),
7488
- render,
7489
- ...props
7490
- });
7491
- }
7492
- function MessageQuotedPreviewContent({ className, render, ...props }) {
7493
- const { content } = messageQuotedPreview();
7494
- return /* @__PURE__ */ jsx(MessageEmbedContent, {
7495
- className: content({ className }),
7496
- render,
7497
- ...props
7498
- });
7499
- }
7500
- function MessageQuotedPreviewHeader({ className, render, ...props }) {
7501
- const { header } = messageQuotedPreview();
7502
- return /* @__PURE__ */ jsx(MessageEmbedHeader, {
7503
- className: header({ className }),
7504
- render,
7505
- ...props
7506
- });
7507
- }
7508
- function MessageQuotedPreviewChannel({ className, render, ...props }) {
7509
- const { channel } = messageQuotedPreview();
7510
- return useRender({
7511
- defaultTagName: "span",
7512
- render,
7513
- props: mergeProps({ className: channel({ className }) }, props),
7514
- state: { slot: "message-quoted-preview-channel" }
7515
- });
7516
- }
7517
- function MessageQuotedPreviewThread({ className, render, ...props }) {
7518
- const { thread } = messageQuotedPreview();
7519
- return useRender({
7520
- defaultTagName: "span",
7521
- render,
7522
- props: mergeProps({ className: thread({ className }) }, props),
7523
- state: { slot: "message-quoted-preview-thread" }
7524
- });
7525
- }
7526
- function MessageQuotedPreviewAuthor({ className, render, ...props }) {
7527
- const { author } = messageQuotedPreview();
7528
- return useRender({
7529
- defaultTagName: "span",
7530
- render,
7531
- props: mergeProps({ className: author({ className }) }, props),
7532
- state: { slot: "message-quoted-preview-author" }
7533
- });
7534
- }
7535
- function MessageQuotedPreviewAuthorName({ className, render, ...props }) {
7536
- const { authorName } = messageQuotedPreview();
7537
- return useRender({
7538
- defaultTagName: "span",
7539
- render,
7540
- props: mergeProps({ className: authorName({ className }) }, props),
7541
- state: { slot: "message-quoted-preview-author-name" }
7542
- });
7543
- }
7544
- function MessageQuotedPreviewAuthorMeta({ className, render, ...props }) {
7545
- const { authorMeta } = messageQuotedPreview();
7546
- return useRender({
7547
- defaultTagName: "span",
7548
- render,
7549
- props: mergeProps({ className: authorMeta({ className }) }, props),
7550
- state: { slot: "message-quoted-preview-author-meta" }
7551
- });
7552
- }
7553
- function MessageQuotedPreviewTimestamp({ className, render, ...props }) {
7554
- const { timestamp } = messageQuotedPreview();
7555
- return useRender({
7556
- defaultTagName: "span",
7557
- render,
7558
- props: mergeProps({ className: timestamp({ className }) }, props),
7559
- state: { slot: "message-quoted-preview-timestamp" }
7560
- });
7561
- }
7562
- function MessageQuotedPreviewText({ className, render, ...props }) {
7563
- const { text } = messageQuotedPreview();
7564
- return useRender({
7565
- defaultTagName: "div",
7566
- render,
7567
- props: mergeProps({ className: text({ className }) }, props),
7568
- state: { slot: "message-quoted-preview-text" }
7569
- });
7570
- }
7571
- function MessageQuotedPreviewAttachments({ className, render, ...props }) {
7572
- const { attachments } = messageQuotedPreview();
7573
- return useRender({
7574
- defaultTagName: "div",
7575
- render,
7576
- props: mergeProps({ className: attachments({ className }) }, props),
7577
- state: { slot: "message-quoted-preview-attachments" }
7578
- });
7579
- }
7580
- function MessageQuotedPreviewAttachment({ className, render, ...props }) {
7581
- const { attachment } = messageQuotedPreview();
7582
- return useRender({
7583
- defaultTagName: "span",
7584
- render,
7585
- props: mergeProps({ className: attachment({ className }) }, props),
7586
- state: { slot: "message-quoted-preview-attachment" }
7587
- });
7588
- }
7589
- function MessageQuotedPreviewLoading({ className, render, ...props }) {
7590
- const { loading } = messageQuotedPreview();
7591
- return /* @__PURE__ */ jsx(MessageEmbed, {
7592
- className: loading({ className }),
7593
- render,
7594
- ...props
7595
- });
7596
- }
7597
- function MessageQuotedPreviewUnavailable({ className, render, ...props }) {
7598
- const { unavailable } = messageQuotedPreview();
7599
- return useRender({
7600
- defaultTagName: "div",
7601
- render,
7602
- props: mergeProps({ className: unavailable({ className }) }, props),
7603
- state: { slot: "message-quoted-preview-unavailable" }
7604
- });
7605
- }
7606
- //#endregion
7607
5743
  //#region src/components/message-replies/message-replies.recipe.ts
7608
5744
  const messageReplies = tv({ slots: {
7609
5745
  root: [
@@ -9186,128 +7322,6 @@ function MessageItemTranslationRetryAction({ className, ...props }) {
9186
7322
  });
9187
7323
  }
9188
7324
  //#endregion
9189
- //#region src/components/message-list/message-list.recipe.ts
9190
- const messageList = tv({
9191
- slots: {
9192
- root: ["relative h-full min-h-0"],
9193
- viewport: ["min-w-0 overscroll-none"],
9194
- content: ["flex min-h-full w-full min-w-0 flex-col"],
9195
- dateDividerRoot: ["flex select-none items-center", "gap-2 px-4 py-3"],
9196
- dateDividerRule: ["flex-1", "min-w-3 border-t border-line-hairline"],
9197
- dateDividerChip: ["inline-flex items-center", "font-mono text-mono-meta whitespace-nowrap text-foreground-hint"],
9198
- notice: ["text-center", "pb-2 font-mono text-mono-meta"],
9199
- historyLimited: [
9200
- "inline-flex items-center",
9201
- "h-[22px] gap-1 rounded-chip px-1.5",
9202
- "font-mono text-mono-meta text-foreground-muted",
9203
- "inset-ring inset-ring-line-hairline",
9204
- "[&_svg]:size-3"
9205
- ]
9206
- },
9207
- variants: { tone: {
9208
- faint: { notice: ["text-foreground-hint"] },
9209
- muted: { notice: ["text-foreground-muted"] }
9210
- } },
9211
- defaultVariants: { tone: "faint" }
9212
- });
9213
- //#endregion
9214
- //#region src/components/message-list/message-list.tsx
9215
- const contentStyle = { minWidth: 0 };
9216
- function MessageList({ children, className, render, rootClassName, style, ...props }) {
9217
- const isMobile = useMobileViewport();
9218
- const { content, root, viewport } = messageList();
9219
- const viewportStyle = useMemo(() => ({
9220
- ...style,
9221
- overflowX: "hidden"
9222
- }), [style]);
9223
- if (isMobile) return /* @__PURE__ */ jsx("div", {
9224
- "data-slot": "message-list",
9225
- className: root({ className: rootClassName }),
9226
- children: /* @__PURE__ */ jsx(PanelScrollViewport, {
9227
- ...props,
9228
- render,
9229
- "data-slot": "message-list-viewport",
9230
- className: viewport({ className }),
9231
- style: viewportStyle,
9232
- children: /* @__PURE__ */ jsx("div", {
9233
- className: content(),
9234
- children
9235
- })
9236
- })
9237
- });
9238
- return /* @__PURE__ */ jsxs(ScrollArea, {
9239
- "data-slot": "message-list",
9240
- className: root({ className: rootClassName }),
9241
- children: [/* @__PURE__ */ jsx(ScrollAreaViewport, {
9242
- ...props,
9243
- render,
9244
- "data-slot": "message-list-viewport",
9245
- className: viewport({ className }),
9246
- style: viewportStyle,
9247
- children: /* @__PURE__ */ jsx(ScrollAreaContent, {
9248
- className: content(),
9249
- style: contentStyle,
9250
- children
9251
- })
9252
- }), /* @__PURE__ */ jsx(ScrollAreaScrollbar, {
9253
- className: "me-1.5 px-0 py-1",
9254
- children: /* @__PURE__ */ jsx(ScrollAreaThumb, {})
9255
- })]
9256
- });
9257
- }
9258
- //#endregion
9259
- //#region src/components/message-list/message-list-markers.tsx
9260
- function MessageListDateDivider({ children, className, render, ...props }) {
9261
- const { dateDividerRoot, dateDividerRule, dateDividerChip } = messageList();
9262
- const defaultProps = {
9263
- "data-slot": "message-list-date-divider",
9264
- className: dateDividerRoot({ className }),
9265
- children: /* @__PURE__ */ jsxs(Fragment$1, { children: [
9266
- /* @__PURE__ */ jsx("div", {
9267
- "aria-hidden": true,
9268
- className: dateDividerRule()
9269
- }),
9270
- /* @__PURE__ */ jsx("span", {
9271
- className: dateDividerChip(),
9272
- children
9273
- }),
9274
- /* @__PURE__ */ jsx("div", {
9275
- "aria-hidden": true,
9276
- className: dateDividerRule()
9277
- })
9278
- ] })
9279
- };
9280
- return useRender({
9281
- defaultTagName: "div",
9282
- render,
9283
- props: mergeProps(defaultProps, props)
9284
- });
9285
- }
9286
- function MessageListNotice({ className, render, tone = "faint", ...props }) {
9287
- const { notice } = messageList({ tone });
9288
- const defaultProps = {
9289
- "data-slot": "message-list-notice",
9290
- className: notice({ className })
9291
- };
9292
- return useRender({
9293
- defaultTagName: "div",
9294
- render,
9295
- props: mergeProps(defaultProps, props)
9296
- });
9297
- }
9298
- function MessageListHistoryLimited({ className, render, ...props }) {
9299
- const { historyLimited } = messageList();
9300
- const defaultProps = {
9301
- "data-slot": "message-list-history-limited",
9302
- className: historyLimited({ className })
9303
- };
9304
- return useRender({
9305
- defaultTagName: "span",
9306
- render,
9307
- props: mergeProps(defaultProps, props)
9308
- });
9309
- }
9310
- //#endregion
9311
7325
  //#region src/components/icon-tile/icon-tile.tsx
9312
7326
  const iconTile = tv({
9313
7327
  slots: { root: ["inline-flex shrink-0 items-center justify-center", "rounded-sticker [&_svg]:shrink-0"] },
@@ -12171,13 +10185,13 @@ const toastStyles = tv({
12171
10185
  "[&[data-has-icon][data-has-actions]]:grid-cols-[auto_minmax(0,1fr)_auto]"
12172
10186
  ],
12173
10187
  icon: [
12174
- "flex size-5 shrink-0 items-center justify-center",
10188
+ "flex h-lh w-5 shrink-0 items-center justify-center",
12175
10189
  "[&_svg]:shrink-0",
12176
10190
  "[&_svg]:size-4"
12177
10191
  ],
12178
10192
  body: ["min-w-0"],
12179
- title: ["m-0 truncate text-sm/5", "font-normal text-foreground-on-hud"],
12180
- description: ["m-0 text-sm/5", "text-foreground-on-hud/70"],
10193
+ title: ["m-0 truncate text-callout", "font-normal text-foreground-on-hud"],
10194
+ description: ["m-0 text-callout", "text-foreground-on-hud/70"],
12181
10195
  actions: ["flex items-center justify-end", "gap-4"],
12182
10196
  progress: [
12183
10197
  "pointer-events-none absolute h-[3px] origin-left",
@@ -16241,8 +14255,10 @@ function VirtualList(props) {
16241
14255
  if (!isReplay) {
16242
14256
  clearPendingScrollTask();
16243
14257
  if (behavior === "instant") {
14258
+ const item = items[index];
16244
14259
  pendingScrollTaskRef.current = {
16245
14260
  type: "index",
14261
+ key: item === void 0 ? void 0 : getKey(item),
16246
14262
  index,
16247
14263
  debounce: ensureVisibleOnly
16248
14264
  };
@@ -16382,11 +14398,13 @@ function VirtualList(props) {
16382
14398
  * `scrollTop` for the item from the DOM, set it, and update the range. If the range changes, the rows it
16383
14399
  * brings into view are rendered (in a microtask, still before the browser paints) and the next step runs
16384
14400
  * from the render callback (a layout effect) to measure them; the jump is done when a step finds the item
16385
- * mounted, no size changed and `scrollTop` already right. Bounded by `MAX_ALIGN_STEPS`.
14401
+ * mounted, no size changed and `scrollTop` already right. Bounded by `MAX_ALIGN_STEPS`. The item is
14402
+ * found by its key at every step: rows inserted above it in between move its index.
16386
14403
  */
16387
- const alignStep = useEventCallback((run, index, align, scrollMarginTop, scrollMarginBottom, remaining) => {
14404
+ const alignStep = useEventCallback((run, key, align, scrollMarginTop, scrollMarginBottom, remaining) => {
16388
14405
  const listEl = listElRef.current;
16389
- if (listEl == null || run !== alignRunRef.current || index >= items.length) return;
14406
+ const index = keyToIndexRef.current.get(key);
14407
+ if (listEl == null || run !== alignRunRef.current || index === void 0) return;
16390
14408
  const sizesChanged = measureMountedItems();
16391
14409
  const { top: itemTop, size: itemSize, measured } = getItemExtent(index);
16392
14410
  const viewportHeight = listEl.clientHeight;
@@ -16408,7 +14426,7 @@ function VirtualList(props) {
16408
14426
  viewportRef.current.scrollTop = listEl.scrollTop;
16409
14427
  if (!moved && !sizesChanged && measured || remaining <= 0) return;
16410
14428
  updateRange("listScroll", true, () => {
16411
- alignStep(run, index, align, scrollMarginTop, scrollMarginBottom, remaining - 1);
14429
+ alignStep(run, key, align, scrollMarginTop, scrollMarginBottom, remaining - 1);
16412
14430
  });
16413
14431
  });
16414
14432
  /**
@@ -16441,13 +14459,16 @@ function VirtualList(props) {
16441
14459
  });
16442
14460
  return;
16443
14461
  }
14462
+ const item = items[index];
14463
+ if (item === void 0) return;
14464
+ const key = getKey(item);
16444
14465
  const smooth = behavior === "smooth";
16445
14466
  if (!isReplay) {
16446
14467
  clearPendingScrollTask();
16447
14468
  if (!smooth) {
16448
14469
  pendingScrollTaskRef.current = {
16449
14470
  type: "align",
16450
- index,
14471
+ key,
16451
14472
  align,
16452
14473
  scrollMarginTop,
16453
14474
  scrollMarginBottom
@@ -16475,7 +14496,7 @@ function VirtualList(props) {
16475
14496
  updateRange("listScroll", true, null);
16476
14497
  return;
16477
14498
  }
16478
- alignStep(run, index, align, scrollMarginTop, scrollMarginBottom, MAX_ALIGN_STEPS);
14499
+ alignStep(run, key, align, scrollMarginTop, scrollMarginBottom, MAX_ALIGN_STEPS);
16479
14500
  });
16480
14501
  const scrollTo = useEventCallback((options, topIfNumber) => {
16481
14502
  if (typeof options == "number") {
@@ -16510,9 +14531,14 @@ function VirtualList(props) {
16510
14531
  if (task) {
16511
14532
  if (task.type === "top") scrollToPosition(0, 0, "instant");
16512
14533
  else if (task.type === "bottom") scrollToPosition(0, listElRef.current?.scrollHeight || 2e9, "instant");
16513
- else if (task.type === "index") scrollToIndex(task.index, "instant", task.debounce, true);
16514
- else if (task.type === "align") scrollToAligned(task.index, task.align, "instant", true, task.scrollMarginTop, task.scrollMarginBottom);
16515
- else if (task.type === "custom") task.task();
14534
+ else if (task.type === "index") {
14535
+ const index = task.key === void 0 ? task.index : keyToIndexRef.current.get(task.key);
14536
+ if (index !== void 0) scrollToIndex(index, "instant", task.debounce, true);
14537
+ } else if (task.type === "align") {
14538
+ const index = keyToIndexRef.current.get(task.key);
14539
+ if (index === void 0) return;
14540
+ scrollToAligned(index, task.align, "instant", true, task.scrollMarginTop, task.scrollMarginBottom);
14541
+ } else if (task.type === "custom") task.task();
16516
14542
  }
16517
14543
  });
16518
14544
  /**
@@ -16541,7 +14567,8 @@ function VirtualList(props) {
16541
14567
  rangeRef.current = renderedRange;
16542
14568
  const listEl = listElRef.current;
16543
14569
  const index = keyToIndexRef.current.get(anchor.key);
16544
- if (listEl == null || index === void 0 || pendingScrollTaskRef.current?.type !== void 0) return;
14570
+ const pendingType = pendingScrollTaskRef.current?.type;
14571
+ if (listEl == null || index === void 0 || pendingType !== void 0 && pendingType !== "index" && pendingType !== "align") return;
16545
14572
  applyLayoutStyles(startIndex);
16546
14573
  const diff = fenwickTree.sum(index) + anchor.delta + getRowsTop() - (listEl.scrollTop + compensationYRef.current);
16547
14574
  if (diff !== 0 && !addCompensation(diff)) listEl.scrollBy(0, diff);
@@ -16732,8 +14759,12 @@ function VirtualList(props) {
16732
14759
  });
16733
14760
  /**
16734
14761
  * Tracks the row holding focus: focusin finds the row the target is in (the visible-items element's
16735
- * child it is inside); focusout to outside the list releases it, and the range is updated so the row
16736
- * unmounts if it is out of the range.
14762
+ * child it is inside); focusout to an element outside the list releases it, and the range is updated so
14763
+ * the row unmounts if it is out of the range. A focusout to nowhere (`relatedTarget` null) does not
14764
+ * release it: switching to another window or tab fires one while the element keeps focus, and the row
14765
+ * must still be there when the person comes back. When focus did go to the page instead (a click on
14766
+ * nothing focusable), the next range update finds `document.activeElement` outside the list and
14767
+ * releases the row then.
16737
14768
  */
16738
14769
  const handleFocusIn = useEventCallback((event) => {
16739
14770
  const visibleItemsEl = getVisibleItemsEl();
@@ -16744,7 +14775,7 @@ function VirtualList(props) {
16744
14775
  const handleFocusOut = useEventCallback((event) => {
16745
14776
  const listEl = listElRef.current;
16746
14777
  const next = event.relatedTarget;
16747
- if (listEl === null || next instanceof Node && listEl.contains(next)) return;
14778
+ if (listEl === null || next === null || next instanceof Node && listEl.contains(next)) return;
16748
14779
  if (focusedKeyRef.current !== null) {
16749
14780
  focusedKeyRef.current = null;
16750
14781
  updateRange("listScroll", true, null);