@botiverse/raft-ui 0.26.0 → 0.28.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/CHANGELOG.md CHANGED
@@ -1,3 +1,43 @@
1
+ ## [0.28.0](https://github.com/botiverse/raft-design/compare/v0.27.0...v0.28.0) (2026-10-23)
2
+
3
+ ### Design System
4
+
5
+ - **Toasts: one at a time, no Dismiss, above the composer on a phone**: a toast shows alone; a new one replaces it at once and the replaced one is closed, not queued. It has no Dismiss: it closes by itself after 5 seconds, or 8 with an action or as an error, and can be swiped away or closed with Esc. It stays at the bottom center: at the bottom of the window on a desktop, and on a phone just above the composer, the tab bar or the keyboard, which the app sets with `--toast-viewport-bottom`. ([#675](https://github.com/botiverse/raft-design/pull/675))
6
+ - Why: stacked toasts and a × on each one asked people to manage messages that were only receipts; at the very bottom of a phone a toast sat under the composer and the keyboard (decided with stdrc).
7
+ - Affects: a rule for products; raft-ui's Toast defaults.
8
+ - Docs: https://raft-design.botiverse.build/components/toast/#where-it-appears
9
+
10
+ - **Pull to refresh looks like Android's own on Android**: on Android web the indicator is Material 3's: a small disc with a shadow slides down over the list, which stays still; inside, a progress arc with an arrowhead grows with the pull, faint until the pull is armed and faint again when it is pulled back (disarmed); while refreshing the arc turns; at the end the disc scales away. iOS and everything else keep the Spinner. The disc is the one round surface besides switches, radios and grab handles, and its turning arc the one other looping animation. ([#765](https://github.com/botiverse/raft-design/pull/765))
11
+ - Why: a pull on Android should look the way it does in every Android app (decided by stdrc); armed and disarmed now look different.
12
+ - Affects: `PullToRefresh` (wip) on Android; shape, motion and navigation rules record the exception.
13
+ - Docs: https://raft-design.botiverse.build/components/pull-to-refresh/#on-android
14
+
15
+ ### Changed
16
+
17
+ - **Toast defaults** ([#675](https://github.com/botiverse/raft-design/pull/675)):
18
+ - `limit` is 1 (was 3); a newer toast replaces the older and closes it.
19
+ - The command API shows `ToastClose` only with `dismissible: true`.
20
+ - `actionTimeout` (8s) applies to toasts with an action and to errors; `timeout` stays 5s.
21
+ - Bottom placements sit 16px above `max(var(--toast-viewport-bottom, 0px), env(safe-area-inset-bottom))`; `top-center` takes `--toast-viewport-top`. A toast swipes away toward the edge it came from.
22
+ - Migration: an app that passed its own `placement` or drew its own close can drop them; set `--toast-viewport-bottom` on a phone (from `visualViewport` while the keyboard is up on iOS).
23
+
24
+ ## [0.27.0](https://github.com/botiverse/raft-design/compare/v0.26.0...v0.27.0) (2026-10-23)
25
+
26
+ ### Design System
27
+
28
+ - **Refreshing a snapshot page by pulling**: on a phone, a page that shows a snapshot and doesn't update itself (Saved, search results, a conversation's files, the lists in Settings) refreshes when pulled down past 100px; while it refreshes the indicator holds at 60px, and it snaps back in 300ms without overshoot. Pages fed by realtime updates (conversations, Home, Activity, Tasks, Members, Computers) are never pulled: they stay current on their own. On iOS a pull that passed the trigger stays armed; on Android, as in Material 3, pulling back above it takes it back, and crossing it gives a short vibration. The indicator is the Spinner on every platform. Every such page also reloads when it is opened, so the gesture is never the only way. `PullToRefresh` is experimental, from `@botiverse/raft-ui/wip`. ([#743](https://github.com/botiverse/raft-design/pull/743))
29
+ - Why: on a phone there was no way to ask a snapshot page for what is new without leaving it; the numbers match Raft's iOS app so the two feel the same.
30
+ - Affects: a rule for products; raft-ui adds `PullToRefresh` (wip).
31
+ - Docs: https://raft-design.botiverse.build/patterns/navigation/#refreshing
32
+ - **A right panel grows until the area left of it is 360px**: a thread, a profile or task side panel and the side cards have no fixed maximum width (640px, 720px before); they grow until the area beside them is down to its 360px minimum. ([#759](https://github.com/botiverse/raft-design/pull/759))
33
+ - Why: a fixed maximum stopped them at about half of a 1280px to 1440px window, though people wanted three quarters while they worked in them.
34
+ - Affects: a rule for products.
35
+ - Docs: https://raft-design.botiverse.build/foundations/spacing/
36
+ - **Dragging past the end snaps**: dragging the sidebar 40px past its minimum collapses it, and dragging a thread 40px past where the conversation is down to 360px puts it in focus mode, during the drag; dragging back undoes it, and the width before the snap comes back. ([#761](https://github.com/botiverse/raft-design/pull/761))
37
+ - Why: the jump is how people know they went past the end; 40px keeps a drag that only reaches it from snapping by accident.
38
+ - Affects: a rule for products.
39
+ - Docs: https://raft-design.botiverse.build/components/resizable/#dragging-past-the-end
40
+
1
41
  ## [0.26.0](https://github.com/botiverse/raft-design/compare/v0.25.0...v0.26.0) (2026-10-23)
2
42
 
3
43
  ### Design System
@@ -5521,6 +5521,14 @@ function Skeleton({ variant = "block", className, ...props }) {
5521
5521
  });
5522
5522
  }
5523
5523
  //#endregion
5524
+ //#region src/components/virtual-list/hooks/use-latest-ref.ts
5525
+ /** A ref whose `current` is the value of the latest render. */
5526
+ function useLatestRef(value) {
5527
+ const ref = useRef(value);
5528
+ ref.current = value;
5529
+ return ref;
5530
+ }
5531
+ //#endregion
5524
5532
  //#region src/components/inbox-item/inbox-item.recipe.ts
5525
5533
  const inboxItem = tv$1({
5526
5534
  slots: {
@@ -5930,4 +5938,4 @@ function InboxItemActions({ className, render, reveal, ...props }) {
5930
5938
  });
5931
5939
  }
5932
5940
  //#endregion
5933
- export { MessageMultiSelect as $, PopoverTitle as $n, ListRowTitle as $r, MessageItemAvatarSlot as $t, MessageQuotedPreview as A, textLinkVariants as Ai, MobileNavServerItem as An, PanelBody as Ar, MessageItemReadReceipt as At, MessageQuotedPreviewLoading as B, useTheme as Bi, MobileNavServerPopoverRowLabel as Bn, ScrollAreaThumb as Br, MessageItemMeta as Bt, MessageListJumpPillDismiss as C, DialogSurface as Ci, PreviewCardHeader as Cn, DropdownMenuShortcut as Cr, MessageReactionTooltipMeta as Ct, MessageListHistoryLimited as D, panelToggleAction as Di, PreviewCardSeparator as Dn, Kbd as Dr, MessageReactionTooltipSeparator as Dt, MessageListEndFade as E, PanelAction as Ei, PreviewCardPortal as En, DropdownMenuTrigger as Er, MessageReactionTooltipNames as Et, MessageQuotedPreviewAuthorMeta as F, defaultNativeButton as Fi, MobileNavServerPopoverGroup as Fn, PanelSection as Fr, MessageItemDelegatedBy as Ft, MessageEmbed as G, controlIconInset as Gi, PopoverBody as Gn, ListRow as Gr, MessageItemTime as Gt, MessageQuotedPreviewThread as H, tv$1 as Hi, PopoverActions as Hn, Checkbox$1 as Hr, MessageItemSenderBadges as Ht, MessageQuotedPreviewAuthorName as I, OverlayLayerProvider as Ii, MobileNavServerPopoverList as In, ScrollArea$1 as Ir, MessageItemDelegatedByButton as It, MessageEmbedHeader as J, decisionWidth as Ji, PopoverDescription as Jn, ListRowChevron as Jr, MessageItemContent as Jt, MessageEmbedContent as K, headEdgePull as Ki, PopoverClose as Kn, ListRowBody as Kr, MessageItemAttachments as Kt, MessageQuotedPreviewChannel as L, useParentOverlayKind as Li, MobileNavServerPopoverRow as Ln, ScrollAreaContent as Lr, MessageItemDelegatedByName as Lt, MessageQuotedPreviewAttachments as M, Button$1 as Mi, MobileNavServerPopoverContent as Mn, PanelHeaderRoot as Mr, MessageItemToolbar as Mt, MessageQuotedPreviewAuthor as N, buttonVariants as Ni, MobileNavServerPopoverDestination as Nn, PanelScrollContent as Nr, MessageItemToolbarButton as Nt, MessageListNotice as O, TextLink as Oi, PreviewCardTitle as On, KbdGroup as Or, MessageItemBadge as Ot, MessageQuotedPreviewAuthorDelegatedBy as P, Spinner as Pi, MobileNavServerPopoverDestinations as Pn, PanelScrollViewport as Pr, MessageItemDelegatedAvatar as Pt, MessageTextSelectionToolbarSeparator as Q, PopoverSeparator as Qn, ListRowMeta as Qr, MessageItemSearchMatch as Qt, MessageQuotedPreviewContent as R, withOverlayLayer as Ri, MobileNavServerPopoverRowBody as Rn, ScrollAreaCorner as Rr, MessageItemHeader as Rt, MessageListJumpPill as S, DialogSheetBack as Si, PreviewCardFooter as Sn, DropdownMenuSeparator as Sr, MessageReactionTooltipContent as St, MessageListDateDivider as T, DialogTrigger as Ti, PreviewCardPopup as Tn, DropdownMenuSubmenuTrigger as Tr, MessageReactionTooltipNameText as Tt, MessageQuotedPreviewTimestamp as U, stackedActions as Ui, PopoverArrow as Un, CheckboxIndicator as Ur, MessageItemSenderButton as Ut, MessageQuotedPreviewText as V, ThemeStateContext as Vi, Popover$1 as Vn, ScrollAreaViewport as Vr, MessageItemSender as Vt, MessageQuotedPreviewUnavailable as W, useStackedActions as Wi, PopoverBackdrop as Wn, PRESENCE_COLOR as Wr, MessageItemSenderGroup as Wt, MessageTextSelectionToolbar as X, PopoverPopup as Xn, ListRowGroup as Xr, MessageItemEmbedded as Xt, messageEmbed as Y, PopoverHeader as Yn, ListRowDescription as Yr, MessageItemEdited as Yt, MessageTextSelectionToolbarButton as Z, PopoverPortal as Zn, ListRowIcon as Zr, MessageItemFooter as Zt, InboxItemTrailing as _, DialogFooterNote as _i, PreviewCardArrow as _n, DropdownMenuPopup as _r, MessageReactionGlyph as _t, InboxItemContext as a, TooltipProvider as ai, AvatarBadge as an, MobileNavLabel as ar, MessageReferenceIndicator as at, Skeleton as b, DialogOverlay as bi, PreviewCardDescription as bn, DropdownMenuRadioItem as br, MessageReactionQuickButton as bt, InboxItemLeading as c, DialogCommit as ci, AvatarGroupCount as cn, DropdownMenuCheckboxItem as cr, MessageReferenceReadMark as ct, InboxItemMetadata as d, Dialog$1 as di, measureContent as dn, DropdownMenuFooter as dr, MessageReferenceUnavailable as dt, ListRowTop as ei, MessageItemContinuationTime as en, PopoverTrigger as er, MessageMultiSelectCheckbox as et, InboxItemSelection as f, DialogBody as fi, measureElement as fn, DropdownMenuItem as fr, inlineChip as ft, InboxItemTitle as g, DialogFooter as gi, PreviewCardActions as gn, DropdownMenuLinkItem as gr, MessageReactionErrorIndicator as gt, InboxItemTimestamp as h, DialogDescription as hi, PreviewCard$1 as hn, DropdownMenuLabel as hr, MessageReactionCount as ht, InboxItemContent as i, TooltipPortal as ii, Avatar$1 as in, MobileNavItem as ir, MessageReferenceIcon as it, MessageQuotedPreviewAttachment as j, DialogSheetReset as ji, MobileNavServerPopover as jn, PanelFooter as jr, MessageItemSavedIndicator as jt, MessageList as k, TextLinkExternalIcon as ki, PreviewCardTrigger as kn, Panel as kr, MessageItemBadgeSeparator as kt, InboxItemMarks as l, DialogSheetContent as li, AvatarImage as ln, DropdownMenuCheckboxItemIndicator as lr, MessageReferenceSuffix as lt, InboxItemSubtitle as m, DialogContent as mi, readNow as mn, DropdownMenuItemLabel as mr, MessageReactionChip as mt, InboxItemActions as n, Tooltip$1 as ni, MessageItem as nn, useHoldThenMoveTouchSensor as nr, MessageMultiSelectToolbarActions as nt, InboxItemHeading as o, TooltipTrigger as oi, AvatarFallback as on, MobileNavRoot as or, MessageReferenceLabel as ot, InboxItemSender as p, DialogClose as pi, observeTruncation as pn, DropdownMenuItemCount as pr, MessageReactionAddButton as pt, MessageEmbedFooter as q, headEdges as qi, PopoverContent as qn, ListRowBottom as qr, MessageItemBody as qt, InboxItemBody as r, TooltipContent as ri, searchHit as rn, useMouseOnlyPointerSensor as rr, MessageReferenceChip as rt, InboxItemHoverTarget as s, Badge as si, AvatarGroup as sn, DropdownMenu as sr, MessageReferencePending as st, InboxItem as t, ListRowValue as ti, MessageItemGutter as tn, PopoverViewport as tr, MessageMultiSelectToolbar as tt, InboxItemMessage as u, useMobileViewport as ui, useOverflowTitle as un, DropdownMenuContent as ur, MessageReferenceText as ut, InboxItemTrigger as v, DialogHeader as vi, PreviewCardBody as vn, DropdownMenuPortal as vr, MessageReactionPickerContent as vt, MessageListJumpPillGroup as w, DialogTitle as wi, PreviewCardMeta as wn, DropdownMenuSubmenu as wr, MessageReactionTooltipName as wt, MessageListJumpControls as x, DialogPortal as xi, PreviewCardEyebrow as xn, DropdownMenuRadioItemIndicator as xr, MessageReactionQuickRow as xt, inboxItem as y, DialogNav as yi, PreviewCardContent as yn, DropdownMenuRadioGroup as yr, MessageReactionPickerStatic as yt, MessageQuotedPreviewHeader as z, useThemeScopeProps as zi, MobileNavServerPopoverRowDescription as zn, ScrollAreaScrollbar as zr, MessageItemInlineStatus as zt };
5941
+ export { MessageTextSelectionToolbarSeparator as $, PopoverSeparator as $n, ListRowMeta as $r, MessageItemSearchMatch as $t, MessageList as A, TextLinkExternalIcon as Ai, PreviewCardTrigger as An, Panel as Ar, MessageItemBadgeSeparator as At, MessageQuotedPreviewHeader as B, useThemeScopeProps as Bi, MobileNavServerPopoverRowDescription as Bn, ScrollAreaScrollbar as Br, MessageItemInlineStatus as Bt, MessageListJumpPill as C, DialogSheetBack as Ci, PreviewCardFooter as Cn, DropdownMenuSeparator as Cr, MessageReactionTooltipContent as Ct, MessageListEndFade as D, PanelAction as Di, PreviewCardPortal as Dn, DropdownMenuTrigger as Dr, MessageReactionTooltipNames as Dt, MessageListDateDivider as E, DialogTrigger as Ei, PreviewCardPopup as En, DropdownMenuSubmenuTrigger as Er, MessageReactionTooltipNameText as Et, MessageQuotedPreviewAuthorDelegatedBy as F, Spinner as Fi, MobileNavServerPopoverDestinations as Fn, PanelScrollViewport as Fr, MessageItemDelegatedAvatar as Ft, MessageQuotedPreviewUnavailable as G, useStackedActions as Gi, PopoverBackdrop as Gn, PRESENCE_COLOR as Gr, MessageItemSenderGroup as Gt, MessageQuotedPreviewText as H, ThemeStateContext as Hi, Popover$1 as Hn, ScrollAreaViewport as Hr, MessageItemSender as Ht, MessageQuotedPreviewAuthorMeta as I, defaultNativeButton as Ii, MobileNavServerPopoverGroup as In, PanelSection as Ir, MessageItemDelegatedBy as It, MessageEmbedFooter as J, headEdges as Ji, PopoverContent as Jn, ListRowBottom as Jr, MessageItemBody as Jt, MessageEmbed as K, controlIconInset as Ki, PopoverBody as Kn, ListRow as Kr, MessageItemTime as Kt, MessageQuotedPreviewAuthorName as L, OverlayLayerProvider as Li, MobileNavServerPopoverList as Ln, ScrollArea$1 as Lr, MessageItemDelegatedByButton as Lt, MessageQuotedPreviewAttachment as M, DialogSheetReset as Mi, MobileNavServerPopover as Mn, PanelFooter as Mr, MessageItemSavedIndicator as Mt, MessageQuotedPreviewAttachments as N, Button$1 as Ni, MobileNavServerPopoverContent as Nn, PanelHeaderRoot as Nr, MessageItemToolbar as Nt, MessageListHistoryLimited as O, panelToggleAction as Oi, PreviewCardSeparator as On, Kbd as Or, MessageReactionTooltipSeparator as Ot, MessageQuotedPreviewAuthor as P, buttonVariants as Pi, MobileNavServerPopoverDestination as Pn, PanelScrollContent as Pr, MessageItemToolbarButton as Pt, MessageTextSelectionToolbarButton as Q, PopoverPortal as Qn, ListRowIcon as Qr, MessageItemFooter as Qt, MessageQuotedPreviewChannel as R, useParentOverlayKind as Ri, MobileNavServerPopoverRow as Rn, ScrollAreaContent as Rr, MessageItemDelegatedByName as Rt, MessageListJumpControls as S, DialogPortal as Si, PreviewCardEyebrow as Sn, DropdownMenuRadioItemIndicator as Sr, MessageReactionQuickRow as St, MessageListJumpPillGroup as T, DialogTitle as Ti, PreviewCardMeta as Tn, DropdownMenuSubmenu as Tr, MessageReactionTooltipName as Tt, MessageQuotedPreviewThread as U, tv$1 as Ui, PopoverActions as Un, Checkbox$1 as Ur, MessageItemSenderBadges as Ut, MessageQuotedPreviewLoading as V, useTheme as Vi, MobileNavServerPopoverRowLabel as Vn, ScrollAreaThumb as Vr, MessageItemMeta as Vt, MessageQuotedPreviewTimestamp as W, stackedActions as Wi, PopoverArrow as Wn, CheckboxIndicator as Wr, MessageItemSenderButton as Wt, messageEmbed as X, PopoverHeader as Xn, ListRowDescription as Xr, MessageItemEdited as Xt, MessageEmbedHeader as Y, decisionWidth as Yi, PopoverDescription as Yn, ListRowChevron as Yr, MessageItemContent as Yt, MessageTextSelectionToolbar as Z, PopoverPopup as Zn, ListRowGroup as Zr, MessageItemEmbedded as Zt, InboxItemTrailing as _, DialogFooter as _i, PreviewCardActions as _n, DropdownMenuLinkItem as _r, MessageReactionErrorIndicator as _t, InboxItemContext as a, TooltipPortal as ai, Avatar$1 as an, MobileNavItem as ar, MessageReferenceIcon as at, useLatestRef as b, DialogNav as bi, PreviewCardContent as bn, DropdownMenuRadioGroup as br, MessageReactionPickerStatic as bt, InboxItemLeading as c, Badge as ci, AvatarGroup as cn, DropdownMenu as cr, MessageReferencePending as ct, InboxItemMetadata as d, useMobileViewport as di, useOverflowTitle as dn, DropdownMenuContent as dr, MessageReferenceText as dt, ListRowTitle as ei, MessageItemAvatarSlot as en, PopoverTitle as er, MessageMultiSelect as et, InboxItemSelection as f, Dialog$1 as fi, measureContent as fn, DropdownMenuFooter as fr, MessageReferenceUnavailable as ft, InboxItemTitle as g, DialogDescription as gi, PreviewCard$1 as gn, DropdownMenuLabel as gr, MessageReactionCount as gt, InboxItemTimestamp as h, DialogContent as hi, readNow as hn, DropdownMenuItemLabel as hr, MessageReactionChip as ht, InboxItemContent as i, TooltipContent as ii, searchHit as in, useMouseOnlyPointerSensor as ir, MessageReferenceChip as it, MessageQuotedPreview as j, textLinkVariants as ji, MobileNavServerItem as jn, PanelBody as jr, MessageItemReadReceipt as jt, MessageListNotice as k, TextLink as ki, PreviewCardTitle as kn, KbdGroup as kr, MessageItemBadge as kt, InboxItemMarks as l, DialogCommit as li, AvatarGroupCount as ln, DropdownMenuCheckboxItem as lr, MessageReferenceReadMark as lt, InboxItemSubtitle as m, DialogClose as mi, observeTruncation as mn, DropdownMenuItemCount as mr, MessageReactionAddButton as mt, InboxItemActions as n, ListRowValue as ni, MessageItemGutter as nn, PopoverViewport as nr, MessageMultiSelectToolbar as nt, InboxItemHeading as o, TooltipProvider as oi, AvatarBadge as on, MobileNavLabel as or, MessageReferenceIndicator as ot, InboxItemSender as p, DialogBody as pi, measureElement as pn, DropdownMenuItem as pr, inlineChip as pt, MessageEmbedContent as q, headEdgePull as qi, PopoverClose as qn, ListRowBody as qr, MessageItemAttachments as qt, InboxItemBody as r, Tooltip$1 as ri, MessageItem as rn, useHoldThenMoveTouchSensor as rr, MessageMultiSelectToolbarActions as rt, InboxItemHoverTarget as s, TooltipTrigger as si, AvatarFallback as sn, MobileNavRoot as sr, MessageReferenceLabel as st, InboxItem as t, ListRowTop as ti, MessageItemContinuationTime as tn, PopoverTrigger as tr, MessageMultiSelectCheckbox as tt, InboxItemMessage as u, DialogSheetContent as ui, AvatarImage as un, DropdownMenuCheckboxItemIndicator as ur, MessageReferenceSuffix as ut, InboxItemTrigger as v, DialogFooterNote as vi, PreviewCardArrow as vn, DropdownMenuPopup as vr, MessageReactionGlyph as vt, MessageListJumpPillDismiss as w, DialogSurface as wi, PreviewCardHeader as wn, DropdownMenuShortcut as wr, MessageReactionTooltipMeta as wt, Skeleton as x, DialogOverlay as xi, PreviewCardDescription as xn, DropdownMenuRadioItem as xr, MessageReactionQuickButton as xt, inboxItem as y, DialogHeader as yi, PreviewCardBody as yn, DropdownMenuPortal as yr, MessageReactionPickerContent as yt, MessageQuotedPreviewContent as z, withOverlayLayer as zi, MobileNavServerPopoverRowBody as zn, ScrollAreaCorner as zr, MessageItemHeader as zt };
package/dist/index.d.mts CHANGED
@@ -3291,16 +3291,16 @@ export declare function NotificationCenterEmptyState(props: NotificationCenterEm
3291
3291
  declare const toastStyles: import("tailwind-variants/lite").TVReturnType<{
3292
3292
  placement: {
3293
3293
  "bottom-center": {
3294
- viewport: string;
3294
+ viewport: string[];
3295
3295
  };
3296
3296
  "bottom-right": {
3297
- viewport: string;
3297
+ viewport: string[];
3298
3298
  };
3299
3299
  "top-center": {
3300
- viewport: string;
3300
+ viewport: string[];
3301
3301
  };
3302
3302
  "top-right": {
3303
- viewport: string;
3303
+ viewport: string[];
3304
3304
  };
3305
3305
  none: {
3306
3306
  viewport: string;
@@ -3338,16 +3338,16 @@ declare const toastStyles: import("tailwind-variants/lite").TVReturnType<{
3338
3338
  }, undefined, {
3339
3339
  placement: {
3340
3340
  "bottom-center": {
3341
- viewport: string;
3341
+ viewport: string[];
3342
3342
  };
3343
3343
  "bottom-right": {
3344
- viewport: string;
3344
+ viewport: string[];
3345
3345
  };
3346
3346
  "top-center": {
3347
- viewport: string;
3347
+ viewport: string[];
3348
3348
  };
3349
3349
  "top-right": {
3350
- viewport: string;
3350
+ viewport: string[];
3351
3351
  };
3352
3352
  none: {
3353
3353
  viewport: string;
@@ -3385,16 +3385,16 @@ declare const toastStyles: import("tailwind-variants/lite").TVReturnType<{
3385
3385
  }, import("tailwind-variants/lite").TVReturnTypeLike<{
3386
3386
  placement: {
3387
3387
  "bottom-center": {
3388
- viewport: string;
3388
+ viewport: string[];
3389
3389
  };
3390
3390
  "bottom-right": {
3391
- viewport: string;
3391
+ viewport: string[];
3392
3392
  };
3393
3393
  "top-center": {
3394
- viewport: string;
3394
+ viewport: string[];
3395
3395
  };
3396
3396
  "top-right": {
3397
- viewport: string;
3397
+ viewport: string[];
3398
3398
  };
3399
3399
  none: {
3400
3400
  viewport: string;
@@ -3448,6 +3448,10 @@ type ToastCommandOptions<Data extends object = ToastData> = Omit<Partial<ToastOb
3448
3448
  onClick?: ComponentPropsWithRef<"button">["onClick"];
3449
3449
  };
3450
3450
  contentClassName?: string;
3451
+ /**
3452
+ * Show `ToastClose` (Dismiss). Defaults to `false`: every toast closes by
3453
+ * itself, swipes away and closes with Esc.
3454
+ */
3451
3455
  dismissible?: boolean;
3452
3456
  /** Show the intent's icon in `ToastIcon`. Defaults to `true`. */
3453
3457
  icon?: boolean;
@@ -3472,13 +3476,19 @@ export declare const toast: {
3472
3476
  dismiss(id?: string): void;
3473
3477
  };
3474
3478
  type ToastProviderProps = Toast.Provider.Props & {
3479
+ /**
3480
+ * How long a toast from the `toast` command API stays when it has an action
3481
+ * or is an `error`, in ms. Defaults to 8000, or to `timeout` when that is
3482
+ * longer, and to 0 when `timeout` is 0.
3483
+ */
3484
+ actionTimeout?: number;
3475
3485
  portalContainer?: Toast.Portal.Props["container"];
3476
3486
  renderViewport?: boolean;
3477
3487
  viewportClassName?: string;
3478
3488
  viewportPlacement?: ToastViewportProps["placement"];
3479
3489
  viewportStrategy?: ToastViewportProps["strategy"];
3480
3490
  };
3481
- export declare function ToastProvider({ children, portalContainer, renderViewport, toastManager, timeout, viewportClassName, viewportPlacement, viewportStrategy, ...props }: ToastProviderProps): import("react").JSX.Element;
3491
+ export declare function ToastProvider({ actionTimeout, children, limit, portalContainer, renderViewport, toastManager, timeout, viewportClassName, viewportPlacement, viewportStrategy, ...props }: ToastProviderProps): import("react").JSX.Element;
3482
3492
  type ToastPortalProps = Toast.Portal.Props;
3483
3493
  export declare function ToastPortal(props: ToastPortalProps): import("react").JSX.Element;
3484
3494
  type ToastViewportProps = StyledProps<Toast.Viewport.Props> & Pick<VariantProps<typeof toastStyles>, "placement" | "strategy">;
@@ -3486,7 +3496,13 @@ export declare function ToastViewport({ placement, strategy, className, ...props
3486
3496
  type ToastPositionerProps = StyledProps<Toast.Positioner.Props>;
3487
3497
  export declare function ToastPositioner({ className, ...props }: ToastPositionerProps): import("react").JSX.Element;
3488
3498
  type ToastRootProps = StyledProps<Toast.Root.Props> & Pick<VariantProps<typeof toastStyles>, "layout">;
3489
- export declare function ToastRoot({ layout, className, toast: toastObject, ...props }: ToastRootProps): import("react").JSX.Element;
3499
+ /**
3500
+ * A toast pushed past the provider's `limit` by a newer one is closed, not
3501
+ * held back: toasts replace each other and never queue, so an older toast
3502
+ * can't come back when the newer one goes. Its swipe direction follows the
3503
+ * viewport's edge unless `swipeDirection` is passed.
3504
+ */
3505
+ export declare function ToastRoot({ layout, className, swipeDirection, toast: toastObject, ...props }: ToastRootProps): import("react").JSX.Element;
3490
3506
  type ToastContentProps = StyledProps<Toast.Content.Props> & {
3491
3507
  ref?: Ref<HTMLDivElement>;
3492
3508
  };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { cn } from "./cn.mjs";
2
- import { $ as MessageMultiSelect, $n as PopoverTitle, $r as ListRowTitle, $t as MessageItemAvatarSlot, A as MessageQuotedPreview, Ai as textLinkVariants, Ar as PanelBody, At as MessageItemReadReceipt, B as MessageQuotedPreviewLoading, Bi as useTheme, Br as ScrollAreaThumb, Bt as MessageItemMeta, Ci as DialogSurface, Cn as PreviewCardHeader, Cr as DropdownMenuShortcut, Ct as MessageReactionTooltipMeta, D as MessageListHistoryLimited, Di as panelToggleAction, Dn as PreviewCardSeparator, Dr as Kbd, Dt as MessageReactionTooltipSeparator, E as MessageListEndFade, Ei as PanelAction, En as PreviewCardPortal, Er as DropdownMenuTrigger, Et as MessageReactionTooltipNames, F as MessageQuotedPreviewAuthorMeta, Fi as defaultNativeButton, Fr as PanelSection, G as MessageEmbed, Gi as controlIconInset, Gr as ListRow, Gt as MessageItemTime, H as MessageQuotedPreviewThread, Hi as tv, Hr as Checkbox, Ht as MessageItemSenderBadges, I as MessageQuotedPreviewAuthorName, Ir as ScrollArea, J as MessageEmbedHeader, Ji as decisionWidth, Jn as PopoverDescription, Jr as ListRowChevron, Jt as MessageItemContent, K as MessageEmbedContent, Ki as headEdgePull, Kn as PopoverClose, Kr as ListRowBody, Kt as MessageItemAttachments, L as MessageQuotedPreviewChannel, Li as useParentOverlayKind, Lr as ScrollAreaContent, M as MessageQuotedPreviewAttachments, Mi as Button, Mr as PanelHeaderRoot, Mt as MessageItemToolbar, N as MessageQuotedPreviewAuthor, Ni as buttonVariants, Nr as PanelScrollContent, Nt as MessageItemToolbarButton, O as MessageListNotice, Oi as TextLink, On as PreviewCardTitle, Or as KbdGroup, Ot as MessageItemBadge, Pi as Spinner, Pr as PanelScrollViewport, Q as MessageTextSelectionToolbarSeparator, Qn as PopoverSeparator, Qr as ListRowMeta, Qt as MessageItemSearchMatch, R as MessageQuotedPreviewContent, Ri as withOverlayLayer, Rr as ScrollAreaCorner, Rt as MessageItemHeader, Sr as DropdownMenuSeparator, St as MessageReactionTooltipContent, T as MessageListDateDivider, Ti as DialogTrigger, Tn as PreviewCardPopup, Tr as DropdownMenuSubmenuTrigger, Tt as MessageReactionTooltipNameText, U as MessageQuotedPreviewTimestamp, Ui as stackedActions, Un as PopoverArrow, Ur as CheckboxIndicator, Ut as MessageItemSenderButton, V as MessageQuotedPreviewText, Vi as ThemeStateContext, Vn as Popover, Vr as ScrollAreaViewport, Vt as MessageItemSender, W as MessageQuotedPreviewUnavailable, Wi as useStackedActions, Wn as PopoverBackdrop, Wr as PRESENCE_COLOR, Wt as MessageItemSenderGroup, X as MessageTextSelectionToolbar, Xn as PopoverPopup, Xr as ListRowGroup, Xt as MessageItemEmbedded, Y as messageEmbed, Yn as PopoverHeader, Yr as ListRowDescription, Yt as MessageItemEdited, Z as MessageTextSelectionToolbarButton, Zn as PopoverPortal, Zr as ListRowIcon, Zt as MessageItemFooter, _ as InboxItemTrailing, _n as PreviewCardArrow, _r as DropdownMenuPopup, _t as MessageReactionGlyph, a as InboxItemContext, ai as TooltipProvider, an as AvatarBadge, ar as MobileNavLabel, at as MessageReferenceIndicator, b as Skeleton, bi as DialogOverlay, bn as PreviewCardDescription, br as DropdownMenuRadioItem, bt as MessageReactionQuickButton, c as InboxItemLeading, cn as AvatarGroupCount, cr as DropdownMenuCheckboxItem, d as InboxItemMetadata, di as Dialog, dr as DropdownMenuFooter, dt as MessageReferenceUnavailable, ei as ListRowTop, en as MessageItemContinuationTime, er as PopoverTrigger, et as MessageMultiSelectCheckbox, f as InboxItemSelection, fi as DialogBody, fr as DropdownMenuItem, ft as inlineChip, g as InboxItemTitle, gi as DialogFooter, gt as MessageReactionErrorIndicator, h as InboxItemTimestamp, hi as DialogDescription, hn as PreviewCard, hr as DropdownMenuLabel, ht as MessageReactionCount, i as InboxItemContent, ii as TooltipPortal, in as Avatar, ir as MobileNavItem, j as MessageQuotedPreviewAttachment, ji as DialogSheetReset, jr as PanelFooter, jt as MessageItemSavedIndicator, k as MessageList, ki as TextLinkExternalIcon, kn as PreviewCardTrigger, kr as Panel, kt as MessageItemBadgeSeparator, l as InboxItemMarks, ln as AvatarImage, lr as DropdownMenuCheckboxItemIndicator, lt as MessageReferenceSuffix, m as InboxItemSubtitle, mi as DialogContent, mr as DropdownMenuItemLabel, mt as MessageReactionChip, n as InboxItemActions, ni as Tooltip, nn as MessageItem, nr as useHoldThenMoveTouchSensor, nt as MessageMultiSelectToolbarActions, o as InboxItemHeading, oi as TooltipTrigger, on as AvatarFallback, or as MobileNavRoot, ot as MessageReferenceLabel, p as InboxItemSender, pi as DialogClose, pr as DropdownMenuItemCount, pt as MessageReactionAddButton, q as MessageEmbedFooter, qi as headEdges, qn as PopoverContent, qr as ListRowBottom, qt as MessageItemBody, r as InboxItemBody, ri as TooltipContent, rn as searchHit, rr as useMouseOnlyPointerSensor, rt as MessageReferenceChip, s as InboxItemHoverTarget, si as Badge, sn as AvatarGroup, sr as DropdownMenu, st as MessageReferencePending, t as InboxItem, ti as ListRowValue, tn as MessageItemGutter, tr as PopoverViewport, tt as MessageMultiSelectToolbar, u as InboxItemMessage, ui as useMobileViewport, un as useOverflowTitle, ur as DropdownMenuContent, ut as MessageReferenceText, v as InboxItemTrigger, vi as DialogHeader, vr as DropdownMenuPortal, vt as MessageReactionPickerContent, wi as DialogTitle, wr as DropdownMenuSubmenu, wt as MessageReactionTooltipName, xi as DialogPortal, xr as DropdownMenuRadioItemIndicator, xt as MessageReactionQuickRow, yi as DialogNav, yn as PreviewCardContent, yr as DropdownMenuRadioGroup, yt as MessageReactionPickerStatic, z as MessageQuotedPreviewHeader, zi as useThemeScopeProps, zr as ScrollAreaScrollbar, zt as MessageItemInlineStatus } from "./inbox-item-Cgf9IT7y.mjs";
2
+ import { $ as MessageTextSelectionToolbarSeparator, $n as PopoverSeparator, $r as ListRowMeta, $t as MessageItemSearchMatch, A as MessageList, Ai as TextLinkExternalIcon, An as PreviewCardTrigger, Ar as Panel, At as MessageItemBadgeSeparator, B as MessageQuotedPreviewHeader, Bi as useThemeScopeProps, Br as ScrollAreaScrollbar, Bt as MessageItemInlineStatus, Cr as DropdownMenuSeparator, Ct as MessageReactionTooltipContent, D as MessageListEndFade, Di as PanelAction, Dn as PreviewCardPortal, Dr as DropdownMenuTrigger, Dt as MessageReactionTooltipNames, E as MessageListDateDivider, Ei as DialogTrigger, En as PreviewCardPopup, Er as DropdownMenuSubmenuTrigger, Et as MessageReactionTooltipNameText, Fi as Spinner, Fr as PanelScrollViewport, G as MessageQuotedPreviewUnavailable, Gi as useStackedActions, Gn as PopoverBackdrop, Gr as PRESENCE_COLOR, Gt as MessageItemSenderGroup, H as MessageQuotedPreviewText, Hi as ThemeStateContext, Hn as Popover, Hr as ScrollAreaViewport, Ht as MessageItemSender, I as MessageQuotedPreviewAuthorMeta, Ii as defaultNativeButton, Ir as PanelSection, J as MessageEmbedFooter, Ji as headEdges, Jn as PopoverContent, Jr as ListRowBottom, Jt as MessageItemBody, K as MessageEmbed, Ki as controlIconInset, Kr as ListRow, Kt as MessageItemTime, L as MessageQuotedPreviewAuthorName, Lr as ScrollArea, M as MessageQuotedPreviewAttachment, Mi as DialogSheetReset, Mr as PanelFooter, Mt as MessageItemSavedIndicator, N as MessageQuotedPreviewAttachments, Ni as Button, Nr as PanelHeaderRoot, Nt as MessageItemToolbar, O as MessageListHistoryLimited, Oi as panelToggleAction, On as PreviewCardSeparator, Or as Kbd, Ot as MessageReactionTooltipSeparator, P as MessageQuotedPreviewAuthor, Pi as buttonVariants, Pr as PanelScrollContent, Pt as MessageItemToolbarButton, Q as MessageTextSelectionToolbarButton, Qn as PopoverPortal, Qr as ListRowIcon, Qt as MessageItemFooter, R as MessageQuotedPreviewChannel, Ri as useParentOverlayKind, Rr as ScrollAreaContent, Si as DialogPortal, Sr as DropdownMenuRadioItemIndicator, St as MessageReactionQuickRow, Ti as DialogTitle, Tr as DropdownMenuSubmenu, Tt as MessageReactionTooltipName, U as MessageQuotedPreviewThread, Ui as tv, Ur as Checkbox, Ut as MessageItemSenderBadges, V as MessageQuotedPreviewLoading, Vi as useTheme, Vr as ScrollAreaThumb, Vt as MessageItemMeta, W as MessageQuotedPreviewTimestamp, Wi as stackedActions, Wn as PopoverArrow, Wr as CheckboxIndicator, Wt as MessageItemSenderButton, X as messageEmbed, Xn as PopoverHeader, Xr as ListRowDescription, Xt as MessageItemEdited, Y as MessageEmbedHeader, Yi as decisionWidth, Yn as PopoverDescription, Yr as ListRowChevron, Yt as MessageItemContent, Z as MessageTextSelectionToolbar, Zn as PopoverPopup, Zr as ListRowGroup, Zt as MessageItemEmbedded, _ as InboxItemTrailing, _i as DialogFooter, _t as MessageReactionErrorIndicator, a as InboxItemContext, ai as TooltipPortal, an as Avatar, ar as MobileNavItem, b as useLatestRef, bi as DialogNav, bn as PreviewCardContent, br as DropdownMenuRadioGroup, bt as MessageReactionPickerStatic, c as InboxItemLeading, ci as Badge, cn as AvatarGroup, cr as DropdownMenu, ct as MessageReferencePending, d as InboxItemMetadata, di as useMobileViewport, dn as useOverflowTitle, dr as DropdownMenuContent, dt as MessageReferenceText, ei as ListRowTitle, en as MessageItemAvatarSlot, er as PopoverTitle, et as MessageMultiSelect, f as InboxItemSelection, fi as Dialog, fr as DropdownMenuFooter, ft as MessageReferenceUnavailable, g as InboxItemTitle, gi as DialogDescription, gn as PreviewCard, gr as DropdownMenuLabel, gt as MessageReactionCount, h as InboxItemTimestamp, hi as DialogContent, hr as DropdownMenuItemLabel, ht as MessageReactionChip, i as InboxItemContent, ii as TooltipContent, in as searchHit, ir as useMouseOnlyPointerSensor, it as MessageReferenceChip, j as MessageQuotedPreview, ji as textLinkVariants, jr as PanelBody, jt as MessageItemReadReceipt, k as MessageListNotice, ki as TextLink, kn as PreviewCardTitle, kr as KbdGroup, kt as MessageItemBadge, l as InboxItemMarks, ln as AvatarGroupCount, lr as DropdownMenuCheckboxItem, m as InboxItemSubtitle, mi as DialogClose, mr as DropdownMenuItemCount, mt as MessageReactionAddButton, n as InboxItemActions, ni as ListRowValue, nn as MessageItemGutter, nr as PopoverViewport, nt as MessageMultiSelectToolbar, o as InboxItemHeading, oi as TooltipProvider, on as AvatarBadge, or as MobileNavLabel, ot as MessageReferenceIndicator, p as InboxItemSender, pi as DialogBody, pr as DropdownMenuItem, pt as inlineChip, q as MessageEmbedContent, qi as headEdgePull, qn as PopoverClose, qr as ListRowBody, qt as MessageItemAttachments, r as InboxItemBody, ri as Tooltip, rn as MessageItem, rr as useHoldThenMoveTouchSensor, rt as MessageMultiSelectToolbarActions, s as InboxItemHoverTarget, si as TooltipTrigger, sn as AvatarFallback, sr as MobileNavRoot, st as MessageReferenceLabel, t as InboxItem, ti as ListRowTop, tn as MessageItemContinuationTime, tr as PopoverTrigger, tt as MessageMultiSelectCheckbox, u as InboxItemMessage, un as AvatarImage, ur as DropdownMenuCheckboxItemIndicator, ut as MessageReferenceSuffix, v as InboxItemTrigger, vn as PreviewCardArrow, vr as DropdownMenuPopup, vt as MessageReactionGlyph, wi as DialogSurface, wn as PreviewCardHeader, wr as DropdownMenuShortcut, wt as MessageReactionTooltipMeta, x as Skeleton, xi as DialogOverlay, xn as PreviewCardDescription, xr as DropdownMenuRadioItem, xt as MessageReactionQuickButton, yi as DialogHeader, yr as DropdownMenuPortal, yt as MessageReactionPickerContent, z as MessageQuotedPreviewContent, zi as withOverlayLayer, zr as ScrollAreaCorner, zt as MessageItemHeader } from "./inbox-item-CfS34Ssw.mjs";
3
3
  import { Dialog as Dialog$1 } from "@base-ui/react/dialog";
4
4
  import { AlertTriangle, Bell, Check, CheckCircle2, ChevronDown, ChevronLeft, ChevronRight, CircleCheck, Copy, FileText, Image, Info, TriangleAlert, Upload, X, Zap } from "lucide-react";
5
5
  import { Children, cloneElement, createContext, createElement, isValidElement, use, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
@@ -10143,10 +10143,10 @@ const toastStyles = tv({
10143
10143
  },
10144
10144
  variants: {
10145
10145
  placement: {
10146
- "bottom-center": { viewport: "bottom-4 left-1/2 -translate-x-1/2" },
10147
- "bottom-right": { viewport: "right-4 bottom-4" },
10148
- "top-center": { viewport: "top-4 left-1/2 -translate-x-1/2" },
10149
- "top-right": { viewport: "top-4 right-4" },
10146
+ "bottom-center": { viewport: ["bottom-[calc(max(var(--toast-viewport-bottom,0px),env(safe-area-inset-bottom))+1rem)]", "left-1/2 -translate-x-1/2"] },
10147
+ "bottom-right": { viewport: ["bottom-[calc(max(var(--toast-viewport-bottom,0px),env(safe-area-inset-bottom))+1rem)]", "right-4"] },
10148
+ "top-center": { viewport: ["top-[calc(max(var(--toast-viewport-top,0px),env(safe-area-inset-top))+1rem)]", "left-1/2 -translate-x-1/2"] },
10149
+ "top-right": { viewport: ["top-[calc(max(var(--toast-viewport-top,0px),env(safe-area-inset-top))+1rem)]", "right-4"] },
10150
10150
  none: { viewport: "contents" }
10151
10151
  },
10152
10152
  strategy: {
@@ -10215,7 +10215,22 @@ const toastProgressStyle = /* @__PURE__ */ jsx("style", {
10215
10215
  `
10216
10216
  });
10217
10217
  const DEFAULT_TOAST_TIMEOUT_MS = 5e3;
10218
+ const DEFAULT_TOAST_ACTION_TIMEOUT_MS = 8e3;
10218
10219
  const ToastProviderConfigContext = createContext({ timeout: DEFAULT_TOAST_TIMEOUT_MS });
10220
+ const ToastPlacementContext = createContext(void 0);
10221
+ const SWIPE_DIRECTION_BY_EDGE = {
10222
+ top: ["up"],
10223
+ bottom: ["down", "right"]
10224
+ };
10225
+ function getSwipeDirection(placement) {
10226
+ if (placement?.startsWith("top-")) return [...SWIPE_DIRECTION_BY_EDGE.top];
10227
+ if (placement?.startsWith("bottom-")) return [...SWIPE_DIRECTION_BY_EDGE.bottom];
10228
+ }
10229
+ function resolveActionTimeout(timeout, actionTimeout) {
10230
+ if (actionTimeout !== void 0) return actionTimeout;
10231
+ return timeout > 0 ? Math.max(timeout, DEFAULT_TOAST_ACTION_TIMEOUT_MS) : 0;
10232
+ }
10233
+ const defaultManagerTiming = { actionTimeout: DEFAULT_TOAST_ACTION_TIMEOUT_MS };
10219
10234
  const toastAction = tv({ slots: {
10220
10235
  root: [
10221
10236
  "relative order-2 inline-flex shrink-0 items-center justify-center whitespace-nowrap select-none",
@@ -10236,9 +10251,11 @@ const createToastManager = Toast.createToastManager;
10236
10251
  const useToastManager = Toast.useToastManager;
10237
10252
  const defaultToastManager = createToastManager();
10238
10253
  function addDefaultToast(intent, title, options = {}) {
10239
- const { action, contentClassName, dismissible, icon, leading, priority, progress, ...toastOptions } = options;
10254
+ const { action, contentClassName, dismissible, icon, leading, priority, progress, timeout, ...toastOptions } = options;
10255
+ const needsTimeToAct = Boolean(action) || intent === "error";
10240
10256
  return defaultToastManager.add({
10241
10257
  ...toastOptions,
10258
+ timeout: timeout ?? (needsTimeToAct ? defaultManagerTiming.actionTimeout : void 0),
10242
10259
  actionProps: action ? {
10243
10260
  children: action.label,
10244
10261
  onClick: action.onClick
@@ -10281,13 +10298,22 @@ function getToastTone(type) {
10281
10298
  if (type === "success" || type === "warning" || type === "error") return type;
10282
10299
  return "info";
10283
10300
  }
10284
- function ToastProvider({ children, portalContainer, renderViewport = true, toastManager = defaultToastManager, timeout = DEFAULT_TOAST_TIMEOUT_MS, viewportClassName, viewportPlacement = "bottom-center", viewportStrategy = "fixed", ...props }) {
10301
+ function ToastProvider({ actionTimeout, children, limit = 1, portalContainer, renderViewport = true, toastManager = defaultToastManager, timeout = DEFAULT_TOAST_TIMEOUT_MS, viewportClassName, viewportPlacement = "bottom-center", viewportStrategy = "fixed", ...props }) {
10285
10302
  const config = useMemo(() => ({ timeout }), [timeout]);
10303
+ const resolvedActionTimeout = resolveActionTimeout(timeout, actionTimeout);
10304
+ useLayoutEffect(() => {
10305
+ if (toastManager !== defaultToastManager) return;
10306
+ defaultManagerTiming.actionTimeout = resolvedActionTimeout;
10307
+ return () => {
10308
+ defaultManagerTiming.actionTimeout = DEFAULT_TOAST_ACTION_TIMEOUT_MS;
10309
+ };
10310
+ }, [resolvedActionTimeout, toastManager]);
10286
10311
  return /* @__PURE__ */ jsx(ToastProviderConfigContext.Provider, {
10287
10312
  value: config,
10288
10313
  children: /* @__PURE__ */ jsxs(Toast.Provider, {
10289
10314
  toastManager,
10290
10315
  timeout,
10316
+ limit,
10291
10317
  ...props,
10292
10318
  children: [children, renderViewport ? /* @__PURE__ */ jsx(DefaultToastLayer, {
10293
10319
  placement: viewportPlacement,
@@ -10309,11 +10335,14 @@ function ToastViewport({ placement = "bottom-center", strategy = "fixed", classN
10309
10335
  placement,
10310
10336
  strategy
10311
10337
  });
10312
- return /* @__PURE__ */ jsx(Toast.Viewport, {
10313
- "data-slot": "toast-viewport",
10314
- "data-toast-placement": placement,
10315
- className: viewport({ className }),
10316
- ...props
10338
+ return /* @__PURE__ */ jsx(ToastPlacementContext.Provider, {
10339
+ value: placement,
10340
+ children: /* @__PURE__ */ jsx(Toast.Viewport, {
10341
+ "data-slot": "toast-viewport",
10342
+ "data-toast-placement": placement,
10343
+ className: viewport({ className }),
10344
+ ...props
10345
+ })
10317
10346
  });
10318
10347
  }
10319
10348
  function ToastPositioner({ className, ...props }) {
@@ -10324,11 +10353,28 @@ function ToastPositioner({ className, ...props }) {
10324
10353
  ...props
10325
10354
  });
10326
10355
  }
10327
- function ToastRoot({ layout = "stacked", className, toast: toastObject, ...props }) {
10356
+ /**
10357
+ * A toast pushed past the provider's `limit` by a newer one is closed, not
10358
+ * held back: toasts replace each other and never queue, so an older toast
10359
+ * can't come back when the newer one goes. Its swipe direction follows the
10360
+ * viewport's edge unless `swipeDirection` is passed.
10361
+ */
10362
+ function ToastRoot({ layout = "stacked", className, swipeDirection, toast: toastObject, ...props }) {
10328
10363
  const { root } = toastStyles({ layout });
10364
+ const placement = useContext(ToastPlacementContext);
10365
+ const { close } = useToastManager();
10366
+ const replaced = toastObject.limited === true && toastObject.transitionStatus !== "ending";
10367
+ useLayoutEffect(() => {
10368
+ if (replaced) close(toastObject.id);
10369
+ }, [
10370
+ close,
10371
+ replaced,
10372
+ toastObject.id
10373
+ ]);
10329
10374
  return /* @__PURE__ */ jsx(Toast.Root, {
10330
10375
  "data-slot": "toast",
10331
10376
  "data-toast-type": toastObject.type ?? "info",
10377
+ swipeDirection: swipeDirection ?? getSwipeDirection(placement),
10332
10378
  toast: toastObject,
10333
10379
  className: root({ className }),
10334
10380
  ...props
@@ -10504,29 +10550,24 @@ function DefaultToastLayer({ placement, portalContainer, strategy, viewportClass
10504
10550
  placement,
10505
10551
  strategy,
10506
10552
  className: viewportClassName,
10507
- children: /* @__PURE__ */ jsx(DefaultToastList, { placement })
10553
+ children: /* @__PURE__ */ jsx(DefaultToastList, {})
10508
10554
  })
10509
10555
  });
10510
10556
  }
10511
- function DefaultToastList({ placement }) {
10557
+ function DefaultToastList() {
10512
10558
  const { toasts } = useToastManager();
10513
- return toasts.map((toastObject) => /* @__PURE__ */ jsx(DefaultToastItem, {
10514
- placement,
10515
- toast: toastObject
10516
- }, toastObject.id));
10559
+ return toasts.map((toastObject) => /* @__PURE__ */ jsx(DefaultToastItem, { toast: toastObject }, toastObject.id));
10517
10560
  }
10518
- const TOP_SWIPE_DIRECTION = ["up", "right"];
10519
- function DefaultToastItem({ placement, toast: toastObject }) {
10561
+ function DefaultToastItem({ toast: toastObject }) {
10520
10562
  const { timeout } = useContext(ToastProviderConfigContext);
10521
10563
  const showDescription = Boolean(toastObject.description);
10522
10564
  const showAction = Boolean(toastObject.actionProps?.children);
10523
- const showClose = toastObject.data?.hasClose !== false;
10565
+ const showClose = toastObject.data?.hasClose === true;
10524
10566
  const showIcon = hasLeading(toastObject) || toastObject.data?.hasIcon !== false;
10525
10567
  const progressDuration = toastObject.timeout ?? timeout;
10526
10568
  const showProgress = toastObject.data?.hasProgress === true && toastObject.type !== "loading" && progressDuration > 0;
10527
10569
  return /* @__PURE__ */ jsx(ToastRoot, {
10528
10570
  toast: toastObject,
10529
- swipeDirection: placement.startsWith("top-") ? TOP_SWIPE_DIRECTION : void 0,
10530
10571
  children: /* @__PURE__ */ jsxs(ToastContent, {
10531
10572
  className: toastObject.data?.contentClassName,
10532
10573
  children: [
@@ -12973,14 +13014,6 @@ function useEventCallback(fn) {
12973
13014
  return useCallback((...args) => fnRef.current(...args), []);
12974
13015
  }
12975
13016
  //#endregion
12976
- //#region src/components/virtual-list/hooks/use-latest-ref.ts
12977
- /** A ref whose `current` is the value of the latest render. */
12978
- function useLatestRef(value) {
12979
- const ref = useRef(value);
12980
- ref.current = value;
12981
- return ref;
12982
- }
12983
- //#endregion
12984
13017
  //#region src/components/virtual-list/hooks/use-layout-effect-with-previous.ts
12985
13018
  /**
12986
13019
  * `useLayoutEffect(() => fn(previousDeps), deps)`: the layout-effect form of useMemoWithPrevious;
package/dist/wip.d.mts CHANGED
@@ -604,4 +604,106 @@ export declare function OverlayLayerProvider({ kind, modal, children }: OverlayL
604
604
  */
605
605
  export declare function useParentOverlayKind(): OverlayLayerKind | null;
606
606
  //#endregion
607
- export { Dialog as AnnouncementDialog, DialogClose as AnnouncementDialogClose, DialogTrigger as AnnouncementDialogTrigger, type ComboboxSelectGroup, type ComboboxSelectMessages, type ComboboxSelectOption, type ComboboxSelectProps, type ComboboxSelectSelection, type ComboboxSelectValue, type CommentCardMetaProps, type CommentCardProps, type CommentCardQuoteProps, type CommentCardTriggerProps, type CommentEntryAuthorProps, type CommentEntryBodyProps, type CommentEntryHeaderProps, type CommentEntryProps, type CommentEntryTimeProps, type CommentMarginItemProps, type CommentMarginLayout, type CommentMarginLayoutItem, type CommentMarginLayoutOptions, type CommentMarginProps, type CommentMarkerProps, DialogCommit, type DialogCommitProps, DialogFooterNote, type DialogFooterNoteProps, DialogSheetBack, type DialogSheetBackProps, DialogSheetContent, type DialogSheetContentProps, DropdownMenuLinkItem, type DropdownMenuLinkItemProps, type EllipsisProps, type EllipsisState, type EllipsisToggleProps, type HoldThenMoveOptions, type InboxItemLeadingBadgeProps, type InboxItemSkeletonListProps, type InboxItemSkeletonProps, type ListRowSkeletonProps, MessageItemDelegatedAvatar, type MessageItemDelegatedAvatarProps, MessageItemDelegatedBy, MessageItemDelegatedByButton, type MessageItemDelegatedByButtonProps, MessageItemDelegatedByName, type MessageItemDelegatedByNameProps, type MessageItemDelegatedByProps, MessageListJumpControls, type MessageListJumpControlsProps, MessageListJumpPill, MessageListJumpPillDismiss, type MessageListJumpPillDismissProps, MessageListJumpPillGroup, type MessageListJumpPillGroupProps, type MessageListJumpPillProps, MessageQuotedPreviewAuthorDelegatedBy, type MessageQuotedPreviewAuthorDelegatedByProps, MessageReferenceIcon, type MessageReferenceIconProps, MessageReferenceReadMark, type MessageReferenceReadMarkProps, type MeterHeaderProps, type MeterIndicatorProps, type MeterLabelProps, type MeterProps, type MeterTrackProps, type MeterValueProps, MobileNavServerItem, type MobileNavServerItemProps, MobileNavServerPopover, MobileNavServerPopoverContent, type MobileNavServerPopoverContentProps, MobileNavServerPopoverDestination, type MobileNavServerPopoverDestinationProps, MobileNavServerPopoverDestinations, type MobileNavServerPopoverDestinationsProps, MobileNavServerPopoverGroup, type MobileNavServerPopoverGroupProps, MobileNavServerPopoverList, type MobileNavServerPopoverListProps, type MobileNavServerPopoverProps, MobileNavServerPopoverRow, MobileNavServerPopoverRowBody, type MobileNavServerPopoverRowBodyProps, MobileNavServerPopoverRowDescription, type MobileNavServerPopoverRowDescriptionProps, MobileNavServerPopoverRowLabel, type MobileNavServerPopoverRowLabelProps, type MobileNavServerPopoverRowProps, type OverlayLayerKind, type OverlayLayerProviderProps, PopoverActions, type PopoverActionsProps, PopoverBody, type PopoverBodyProps, PreviewCardActions, type PreviewCardActionsProps, PreviewCardBody, type PreviewCardBodyProps, PreviewCardEyebrow, type PreviewCardEyebrowProps, PreviewCardFooter, type PreviewCardFooterProps, PreviewCardMeta, type PreviewCardMetaProps, type UseCommentMarginFitsOptions };
607
+ //#region src/components/pull-to-refresh/pull-to-refresh-gesture.d.ts
608
+ /**
609
+ * The pull-to-refresh gesture as a pure state machine (pull-to-refresh.md,
610
+ * "Behavior"). `usePullToRefresh` feeds it the scroller's touch events; this
611
+ * file owns every decision, so the rules can be tested without a DOM.
612
+ */
613
+ /** How far the indicator has to be pulled, after damping, for a release to refresh. */
614
+ export declare const PULL_TO_REFRESH_THRESHOLD = 100;
615
+ /**
616
+ * The furthest the indicator follows the finger. 40px past the threshold is
617
+ * enough to show the pull is armed and still going; any further and a long
618
+ * drag would push the list off a small phone's screen.
619
+ */
620
+ export declare const PULL_TO_REFRESH_MAX_DISTANCE = 140;
621
+ /** The indicator's height while the refresh runs. */
622
+ export declare const PULL_TO_REFRESH_HOLD_DISTANCE = 60;
623
+ /**
624
+ * The rubber band: the indicator moves this fraction of the finger's travel,
625
+ * so it lags and the pull reads as resistance. 0.55 is iOS's own
626
+ * scroll-view constant.
627
+ */
628
+ export declare const PULL_TO_REFRESH_DAMPING = 0.55;
629
+ /**
630
+ * How long the indicator takes to go back, to the hold height or to 0, once
631
+ * the finger lifts or the refresh ends: ease-out (`ease-slide`), with no
632
+ * overshoot. Instant with reduced motion.
633
+ */
634
+ export declare const PULL_TO_REFRESH_SNAP_BACK_MS = 300;
635
+ type PullToRefreshState = "idle" | "pulling" | "refreshing";
636
+ //#endregion
637
+ //#region src/components/pull-to-refresh/use-pull-to-refresh.d.ts
638
+ /** A primary pointer that is a finger: the only input pull to refresh answers. */
639
+ export declare const PULL_TO_REFRESH_POINTER_QUERY = "(pointer: coarse)";
640
+ /**
641
+ * How the pull looks. `default` (iOS and every other touch screen), as in
642
+ * the iOS app: the content moves down with the pull and the indicator sits in
643
+ * the space it opens. `android` follows Material 3: the indicator travels
644
+ * down over the content, which stays still, arming the pull gives a short
645
+ * vibration, and moving back above the threshold disarms it (no latch).
646
+ */
647
+ type PullToRefreshPlatform = "default" | "android";
648
+ type UsePullToRefreshOptions = {
649
+ /**
650
+ * Reload the page's snapshot. The indicator holds until the promise
651
+ * settles. Handle a failure here (keep the content, show the same toast as
652
+ * a failed first load): a rejection only ends the refresh.
653
+ */
654
+ onRefresh: () => Promise<unknown>;
655
+ /** Turn the gesture off, such as while the first load is still running or a search is empty. */
656
+ disabled?: boolean;
657
+ /** Pull distance, after damping, that arms the refresh. Default 100px. */
658
+ threshold?: number;
659
+ /** The furthest the indicator follows the finger. Default 140px. */
660
+ maxDistance?: number;
661
+ /** The indicator's height while refreshing. Default 60px. */
662
+ holdDistance?: number;
663
+ /** Override the detected platform, such as in a preview. */
664
+ platform?: PullToRefreshPlatform;
665
+ };
666
+ type PullToRefresh = {
667
+ /** `idle`, `pulling` while a finger pulls the indicator down, `refreshing` until `onRefresh` settles. */
668
+ state: PullToRefreshState;
669
+ /** The indicator's height in px. */
670
+ distance: number;
671
+ /** How far towards the threshold the pull is, from 0 to 1; 1 once armed and while refreshing. */
672
+ progress: number;
673
+ /** Which platform's look the indicator takes. */
674
+ platform: PullToRefreshPlatform;
675
+ };
676
+ /**
677
+ * Pull to refresh for a scroll container on a touch screen
678
+ * (pull-to-refresh.md). Pulling down from the top of `scrollRef` past the
679
+ * threshold calls `onRefresh`; render a `PullToRefreshIndicator` with the
680
+ * result as the scroller's first child.
681
+ *
682
+ * On Android it takes Material 3's look (`PullToRefreshPlatform`). It does
683
+ * nothing on a fine pointer. While it is on, the scroller gets
684
+ * `overscroll-behavior-y: contain`, so a browser tab's own pull to reload
685
+ * doesn't run as well. `scrollRef` is read when the hook turns on; a
686
+ * scroller that is replaced later needs the hook remounted (a `key`).
687
+ */
688
+ export declare function usePullToRefresh(scrollRef: RefObject<HTMLElement | null>, { onRefresh, disabled, threshold, maxDistance, holdDistance, platform: platformOverride }: UsePullToRefreshOptions): PullToRefresh;
689
+ //#endregion
690
+ //#region src/components/pull-to-refresh/pull-to-refresh-indicator.d.ts
691
+ type PullToRefreshIndicatorProps = Omit<ComponentProps<"div">, "children"> & {
692
+ /** The result of `usePullToRefresh`. */
693
+ pull: PullToRefresh;
694
+ /**
695
+ * What a screen reader announces when the refresh starts, such as
696
+ * "Refreshing…". Product copy, so it comes from the consumer.
697
+ */
698
+ label: string;
699
+ };
700
+ /**
701
+ * The pull's indicator. Render it as the scroller's first child: by default
702
+ * it is the space the pull opens, with the DS Spinner in it, so the content
703
+ * moves down with the pull; on Android it is Material 3's own indicator, a
704
+ * disc with a progress arc that travels down over the content. It holds a
705
+ * polite live region that announces `label` while refreshing.
706
+ */
707
+ export declare function PullToRefreshIndicator({ pull, label, className, style, ...props }: PullToRefreshIndicatorProps): import("react").JSX.Element;
708
+ //#endregion
709
+ export { Dialog as AnnouncementDialog, DialogClose as AnnouncementDialogClose, DialogTrigger as AnnouncementDialogTrigger, type ComboboxSelectGroup, type ComboboxSelectMessages, type ComboboxSelectOption, type ComboboxSelectProps, type ComboboxSelectSelection, type ComboboxSelectValue, type CommentCardMetaProps, type CommentCardProps, type CommentCardQuoteProps, type CommentCardTriggerProps, type CommentEntryAuthorProps, type CommentEntryBodyProps, type CommentEntryHeaderProps, type CommentEntryProps, type CommentEntryTimeProps, type CommentMarginItemProps, type CommentMarginLayout, type CommentMarginLayoutItem, type CommentMarginLayoutOptions, type CommentMarginProps, type CommentMarkerProps, DialogCommit, type DialogCommitProps, DialogFooterNote, type DialogFooterNoteProps, DialogSheetBack, type DialogSheetBackProps, DialogSheetContent, type DialogSheetContentProps, DropdownMenuLinkItem, type DropdownMenuLinkItemProps, type EllipsisProps, type EllipsisState, type EllipsisToggleProps, type HoldThenMoveOptions, type InboxItemLeadingBadgeProps, type InboxItemSkeletonListProps, type InboxItemSkeletonProps, type ListRowSkeletonProps, MessageItemDelegatedAvatar, type MessageItemDelegatedAvatarProps, MessageItemDelegatedBy, MessageItemDelegatedByButton, type MessageItemDelegatedByButtonProps, MessageItemDelegatedByName, type MessageItemDelegatedByNameProps, type MessageItemDelegatedByProps, MessageListJumpControls, type MessageListJumpControlsProps, MessageListJumpPill, MessageListJumpPillDismiss, type MessageListJumpPillDismissProps, MessageListJumpPillGroup, type MessageListJumpPillGroupProps, type MessageListJumpPillProps, MessageQuotedPreviewAuthorDelegatedBy, type MessageQuotedPreviewAuthorDelegatedByProps, MessageReferenceIcon, type MessageReferenceIconProps, MessageReferenceReadMark, type MessageReferenceReadMarkProps, type MeterHeaderProps, type MeterIndicatorProps, type MeterLabelProps, type MeterProps, type MeterTrackProps, type MeterValueProps, MobileNavServerItem, type MobileNavServerItemProps, MobileNavServerPopover, MobileNavServerPopoverContent, type MobileNavServerPopoverContentProps, MobileNavServerPopoverDestination, type MobileNavServerPopoverDestinationProps, MobileNavServerPopoverDestinations, type MobileNavServerPopoverDestinationsProps, MobileNavServerPopoverGroup, type MobileNavServerPopoverGroupProps, MobileNavServerPopoverList, type MobileNavServerPopoverListProps, type MobileNavServerPopoverProps, MobileNavServerPopoverRow, MobileNavServerPopoverRowBody, type MobileNavServerPopoverRowBodyProps, MobileNavServerPopoverRowDescription, type MobileNavServerPopoverRowDescriptionProps, MobileNavServerPopoverRowLabel, type MobileNavServerPopoverRowLabelProps, type MobileNavServerPopoverRowProps, type OverlayLayerKind, type OverlayLayerProviderProps, PopoverActions, type PopoverActionsProps, PopoverBody, type PopoverBodyProps, PreviewCardActions, type PreviewCardActionsProps, PreviewCardBody, type PreviewCardBodyProps, PreviewCardEyebrow, type PreviewCardEyebrowProps, PreviewCardFooter, type PreviewCardFooterProps, PreviewCardMeta, type PreviewCardMetaProps, type PullToRefresh, type PullToRefreshIndicatorProps, type PullToRefreshPlatform, type PullToRefreshState, type UseCommentMarginFitsOptions, type UsePullToRefreshOptions };
package/dist/wip.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { $r as ListRowTitle, An as MobileNavServerItem, Bi as useTheme, Bn as MobileNavServerPopoverRowLabel, C as MessageListJumpPillDismiss, Fi as defaultNativeButton, Fn as MobileNavServerPopoverGroup, Ft as MessageItemDelegatedBy, Gn as PopoverBody, Gr as ListRow, Hi as tv, Hn as PopoverActions, Ii as OverlayLayerProvider, In as MobileNavServerPopoverList, It as MessageItemDelegatedByButton, Kr as ListRowBody, Li as useParentOverlayKind, Ln as MobileNavServerPopoverRow, Lt as MessageItemDelegatedByName, Mi as Button$1, Mn as MobileNavServerPopoverContent, Nn as MobileNavServerPopoverDestination, Oi as TextLink, P as MessageQuotedPreviewAuthorDelegatedBy, Pn as MobileNavServerPopoverDestinations, Pt as MessageItemDelegatedAvatar, Qr as ListRowMeta, Rn as MobileNavServerPopoverRowBody, S as MessageListJumpPill, Si as DialogSheetBack, Sn as PreviewCardFooter, Ti as DialogTrigger, Yr as ListRowDescription, _ as InboxItemTrailing, _i as DialogFooterNote, a as InboxItemContext, b as Skeleton, c as InboxItemLeading, ci as DialogCommit, ct as MessageReferenceReadMark, di as Dialog, dn as measureContent, ei as ListRowTop, fn as measureElement, g as InboxItemTitle, gn as PreviewCardActions, gr as DropdownMenuLinkItem, h as InboxItemTimestamp, i as InboxItemContent, it as MessageReferenceIcon, jn as MobileNavServerPopover, li as DialogSheetContent, mi as DialogContent, mn as readNow, ni as Tooltip, nr as useHoldThenMoveTouchSensor, o as InboxItemHeading, oi as TooltipTrigger, pi as DialogClose, pn as observeTruncation, qr as ListRowBottom, r as InboxItemBody, ri as TooltipContent, t as InboxItem, un as useOverflowTitle, vn as PreviewCardBody, w as MessageListJumpPillGroup, wi as DialogTitle, wn as PreviewCardMeta, x as MessageListJumpControls, xn as PreviewCardEyebrow, y as inboxItem, zi as useThemeScopeProps, zn as MobileNavServerPopoverRowDescription } from "./inbox-item-Cgf9IT7y.mjs";
1
+ import { $r as ListRowMeta, Bi as useThemeScopeProps, Bn as MobileNavServerPopoverRowDescription, C as MessageListJumpPill, Ci as DialogSheetBack, Cn as PreviewCardFooter, Ei as DialogTrigger, F as MessageQuotedPreviewAuthorDelegatedBy, Fi as Spinner, Fn as MobileNavServerPopoverDestinations, Ft as MessageItemDelegatedAvatar, Ii as defaultNativeButton, In as MobileNavServerPopoverGroup, It as MessageItemDelegatedBy, Jr as ListRowBottom, Kn as PopoverBody, Kr as ListRow, Li as OverlayLayerProvider, Ln as MobileNavServerPopoverList, Lt as MessageItemDelegatedByButton, Mn as MobileNavServerPopover, Ni as Button$1, Nn as MobileNavServerPopoverContent, Pn as MobileNavServerPopoverDestination, Ri as useParentOverlayKind, Rn as MobileNavServerPopoverRow, Rt as MessageItemDelegatedByName, S as MessageListJumpControls, Sn as PreviewCardEyebrow, T as MessageListJumpPillGroup, Ti as DialogTitle, Tn as PreviewCardMeta, Ui as tv, Un as PopoverActions, Vi as useTheme, Vn as MobileNavServerPopoverRowLabel, Xr as ListRowDescription, _ as InboxItemTrailing, _n as PreviewCardActions, _r as DropdownMenuLinkItem, a as InboxItemContext, at as MessageReferenceIcon, b as useLatestRef, c as InboxItemLeading, dn as useOverflowTitle, ei as ListRowTitle, fi as Dialog, fn as measureContent, g as InboxItemTitle, h as InboxItemTimestamp, hi as DialogContent, hn as readNow, i as InboxItemContent, ii as TooltipContent, jn as MobileNavServerItem, ki as TextLink, li as DialogCommit, lt as MessageReferenceReadMark, mi as DialogClose, mn as observeTruncation, o as InboxItemHeading, pn as measureElement, qr as ListRowBody, r as InboxItemBody, ri as Tooltip, rr as useHoldThenMoveTouchSensor, si as TooltipTrigger, t as InboxItem, ti as ListRowTop, ui as DialogSheetContent, vi as DialogFooterNote, w as MessageListJumpPillDismiss, x as Skeleton, y as inboxItem, yn as PreviewCardBody, zn as MobileNavServerPopoverRowBody } from "./inbox-item-CfS34Ssw.mjs";
2
2
  import { Check, ChevronDown, LoaderCircle, Plus, X } from "lucide-react";
3
3
  import { createContext, use, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
4
4
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -1750,4 +1750,581 @@ function MeterIndicator({ className, ...props }) {
1750
1750
  });
1751
1751
  }
1752
1752
  //#endregion
1753
- export { Dialog as AnnouncementDialog, AnnouncementDialogAction, AnnouncementDialogBody, DialogClose as AnnouncementDialogClose, AnnouncementDialogContent, AnnouncementDialogFooter, AnnouncementDialogHeader, AnnouncementDialogLabel, AnnouncementDialogPicture, AnnouncementDialogSecondaryAction, AnnouncementDialogText, AnnouncementDialogTitle, DialogTrigger as AnnouncementDialogTrigger, COMMENT_HIGHLIGHT, COMMENT_HIGHLIGHT_ACTIVE, ComboboxSelect, CommentCard, CommentCardMeta, CommentCardQuote, CommentCardTrigger, CommentEntry, CommentEntryAuthor, CommentEntryBody, CommentEntryHeader, CommentEntryTime, CommentMargin, CommentMarginItem, CommentMarker, DialogCommit, DialogFooterNote, DialogSheetBack, DialogSheetContent, DropdownMenuLinkItem, Ellipsis, EllipsisToggle, InboxItemLeadingBadge, InboxItemSkeleton, InboxItemSkeletonList, ListRowSkeleton, MessageItemDelegatedAvatar, MessageItemDelegatedBy, MessageItemDelegatedByButton, MessageItemDelegatedByName, MessageListJumpControls, MessageListJumpPill, MessageListJumpPillDismiss, MessageListJumpPillGroup, MessageQuotedPreviewAuthorDelegatedBy, MessageReferenceIcon, MessageReferenceReadMark, Meter, MeterHeader, MeterIndicator, MeterLabel, MeterTrack, MeterValue, MobileNavServerItem, MobileNavServerPopover, MobileNavServerPopoverContent, MobileNavServerPopoverDestination, MobileNavServerPopoverDestinations, MobileNavServerPopoverGroup, MobileNavServerPopoverList, MobileNavServerPopoverRow, MobileNavServerPopoverRowBody, MobileNavServerPopoverRowDescription, MobileNavServerPopoverRowLabel, OverlayLayerProvider, PopoverActions, PopoverBody, PreviewCardActions, PreviewCardBody, PreviewCardEyebrow, PreviewCardFooter, PreviewCardMeta, resolveCommentMarginLayout, setCommentHighlights, useCommentMarginFits, useHoldThenMoveTouchSensor, useParentOverlayKind, useTruncated };
1753
+ //#region src/components/pull-to-refresh/pull-to-refresh-gesture.ts
1754
+ /**
1755
+ * The pull-to-refresh gesture as a pure state machine (pull-to-refresh.md,
1756
+ * "Behavior"). `usePullToRefresh` feeds it the scroller's touch events; this
1757
+ * file owns every decision, so the rules can be tested without a DOM.
1758
+ */
1759
+ /** How far the indicator has to be pulled, after damping, for a release to refresh. */
1760
+ const PULL_TO_REFRESH_THRESHOLD = 100;
1761
+ /**
1762
+ * The furthest the indicator follows the finger. 40px past the threshold is
1763
+ * enough to show the pull is armed and still going; any further and a long
1764
+ * drag would push the list off a small phone's screen.
1765
+ */
1766
+ const PULL_TO_REFRESH_MAX_DISTANCE = 140;
1767
+ /** The indicator's height while the refresh runs. */
1768
+ const PULL_TO_REFRESH_HOLD_DISTANCE = 60;
1769
+ /**
1770
+ * The rubber band: the indicator moves this fraction of the finger's travel,
1771
+ * so it lags and the pull reads as resistance. 0.55 is iOS's own
1772
+ * scroll-view constant.
1773
+ */
1774
+ const PULL_TO_REFRESH_DAMPING = .55;
1775
+ /**
1776
+ * How long the indicator takes to go back, to the hold height or to 0, once
1777
+ * the finger lifts or the refresh ends: ease-out (`ease-slide`), with no
1778
+ * overshoot. Instant with reduced motion.
1779
+ */
1780
+ const PULL_TO_REFRESH_SNAP_BACK_MS = 300;
1781
+ /** A finger held this long before it pulls is a long press (a menu, a drag), not a pull. */
1782
+ const PULL_TO_REFRESH_LONG_PRESS_MS = 500;
1783
+ /** How far the finger may drift while it could still be a long press. */
1784
+ const PULL_TO_REFRESH_TOLERANCE = 10;
1785
+ /** Where a touch must not start a pull: text entry, and anything the consumer marks. */
1786
+ const PULL_TO_REFRESH_IGNORE_SELECTOR = [
1787
+ "input",
1788
+ "textarea",
1789
+ "select",
1790
+ "[contenteditable=\"\"]",
1791
+ "[contenteditable=\"true\"]",
1792
+ "[contenteditable=\"plaintext-only\"]",
1793
+ "[data-pull-to-refresh-ignore]"
1794
+ ].join(", ");
1795
+ const DEFAULT_PULL_GESTURE_CONFIG = {
1796
+ threshold: 100,
1797
+ maxDistance: 140,
1798
+ holdDistance: 60,
1799
+ latch: true
1800
+ };
1801
+ const IDLE_PULL_GESTURE = {
1802
+ phase: "idle",
1803
+ startX: 0,
1804
+ startY: 0,
1805
+ distance: 0,
1806
+ armed: false
1807
+ };
1808
+ /** How far the indicator is for a finger that has travelled `delta` px down. */
1809
+ function pullDistance(delta, maxDistance = 140) {
1810
+ if (delta <= 0) return 0;
1811
+ return Math.min(maxDistance, delta * PULL_TO_REFRESH_DAMPING);
1812
+ }
1813
+ /** How far towards the threshold the pull is, from 0 to 1. */
1814
+ function pullProgress(distance, threshold = 100) {
1815
+ if (threshold <= 0) return 1;
1816
+ return Math.min(1, Math.max(0, distance / threshold));
1817
+ }
1818
+ /**
1819
+ * Which of the spinner's 4 pixels is lit while pulling, clockwise from the
1820
+ * top left: one step per quarter of the threshold, the last from the
1821
+ * threshold on (the same walk as the native apps' indicator).
1822
+ */
1823
+ function pullStep(progress) {
1824
+ return Math.min(3, Math.floor(Math.max(0, progress) * 4));
1825
+ }
1826
+ /** The state the indicator shows for a gesture. */
1827
+ function pullState(gesture) {
1828
+ if (gesture.phase === "refreshing") return "refreshing";
1829
+ if (gesture.phase !== "pulling") return "idle";
1830
+ return gesture.distance > 0 || gesture.armed ? "pulling" : "idle";
1831
+ }
1832
+ function step(gesture, preventDefault = false, refresh = false, armed = false) {
1833
+ return {
1834
+ gesture,
1835
+ preventDefault,
1836
+ refresh,
1837
+ armed
1838
+ };
1839
+ }
1840
+ /** The next gesture for an event. */
1841
+ function stepPullGesture(gesture, event, config = DEFAULT_PULL_GESTURE_CONFIG) {
1842
+ if (gesture.phase === "refreshing") return step(event.type === "settle" ? IDLE_PULL_GESTURE : gesture);
1843
+ switch (event.type) {
1844
+ case "start":
1845
+ if (event.fingers !== 1 || !event.atTop || event.ignored) return step(IDLE_PULL_GESTURE);
1846
+ return step({
1847
+ ...IDLE_PULL_GESTURE,
1848
+ phase: "tracking",
1849
+ startX: event.x,
1850
+ startY: event.y
1851
+ });
1852
+ case "move": {
1853
+ if (gesture.phase === "idle") return step(gesture);
1854
+ if (event.fingers !== 1) return step(IDLE_PULL_GESTURE);
1855
+ if (!event.atTop && !gesture.armed) return step(IDLE_PULL_GESTURE);
1856
+ const dx = event.x - gesture.startX;
1857
+ const dy = event.y - gesture.startY;
1858
+ if (gesture.phase === "tracking") {
1859
+ if (Math.abs(dx) > PULL_TO_REFRESH_TOLERANCE && Math.abs(dx) > dy) return step(IDLE_PULL_GESTURE);
1860
+ if (dy < -6) return step(IDLE_PULL_GESTURE);
1861
+ if (dy <= 6) return step(gesture);
1862
+ }
1863
+ const distance = pullDistance(dy, config.maxDistance);
1864
+ const armed = config.latch && gesture.armed || distance >= config.threshold;
1865
+ return step({
1866
+ ...gesture,
1867
+ phase: "pulling",
1868
+ distance,
1869
+ armed
1870
+ }, armed || dy > 6, false, armed && !gesture.armed);
1871
+ }
1872
+ case "hold": return step(gesture.phase === "tracking" ? IDLE_PULL_GESTURE : gesture);
1873
+ case "end":
1874
+ if (gesture.phase === "pulling" && gesture.armed) return step({
1875
+ ...gesture,
1876
+ phase: "refreshing",
1877
+ distance: config.holdDistance
1878
+ }, false, true);
1879
+ return step(IDLE_PULL_GESTURE);
1880
+ case "cancel":
1881
+ case "settle": return step(IDLE_PULL_GESTURE);
1882
+ }
1883
+ }
1884
+ //#endregion
1885
+ //#region src/components/pull-to-refresh/use-pull-to-refresh.ts
1886
+ /** A primary pointer that is a finger: the only input pull to refresh answers. */
1887
+ const PULL_TO_REFRESH_POINTER_QUERY = "(pointer: coarse)";
1888
+ /** The one platform check: Android, by its user agent (Client Hints first). */
1889
+ function detectPullToRefreshPlatform() {
1890
+ if (typeof navigator === "undefined") return "default";
1891
+ const hints = navigator.userAgentData;
1892
+ if (hints?.platform) return hints.platform === "Android" ? "android" : "default";
1893
+ return /\bAndroid\b/i.test(navigator.userAgent) ? "android" : "default";
1894
+ }
1895
+ function hapticTick() {
1896
+ if (typeof navigator !== "undefined" && typeof navigator.vibrate === "function") navigator.vibrate(10);
1897
+ }
1898
+ const subscribeNever = () => () => void 0;
1899
+ const defaultSnapshot = () => "default";
1900
+ function subscribeCoarse(onChange) {
1901
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return () => void 0;
1902
+ const media = window.matchMedia(PULL_TO_REFRESH_POINTER_QUERY);
1903
+ media.addEventListener("change", onChange);
1904
+ return () => media.removeEventListener("change", onChange);
1905
+ }
1906
+ function coarseSnapshot() {
1907
+ return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(pointer: coarse)").matches;
1908
+ }
1909
+ function ignoredTarget(target) {
1910
+ return target instanceof Element && target.closest(PULL_TO_REFRESH_IGNORE_SELECTOR) !== null;
1911
+ }
1912
+ /**
1913
+ * Pull to refresh for a scroll container on a touch screen
1914
+ * (pull-to-refresh.md). Pulling down from the top of `scrollRef` past the
1915
+ * threshold calls `onRefresh`; render a `PullToRefreshIndicator` with the
1916
+ * result as the scroller's first child.
1917
+ *
1918
+ * On Android it takes Material 3's look (`PullToRefreshPlatform`). It does
1919
+ * nothing on a fine pointer. While it is on, the scroller gets
1920
+ * `overscroll-behavior-y: contain`, so a browser tab's own pull to reload
1921
+ * doesn't run as well. `scrollRef` is read when the hook turns on; a
1922
+ * scroller that is replaced later needs the hook remounted (a `key`).
1923
+ */
1924
+ function usePullToRefresh(scrollRef, { onRefresh, disabled = false, threshold = DEFAULT_PULL_GESTURE_CONFIG.threshold, maxDistance = DEFAULT_PULL_GESTURE_CONFIG.maxDistance, holdDistance = DEFAULT_PULL_GESTURE_CONFIG.holdDistance, platform: platformOverride }) {
1925
+ const coarse = useSyncExternalStore(subscribeCoarse, coarseSnapshot, () => false);
1926
+ const detected = useSyncExternalStore(subscribeNever, detectPullToRefreshPlatform, defaultSnapshot);
1927
+ const platform = platformOverride ?? detected;
1928
+ const enabled = coarse && !disabled;
1929
+ const [gesture, setGesture] = useState(IDLE_PULL_GESTURE);
1930
+ const gestureRef = useRef(IDLE_PULL_GESTURE);
1931
+ const onRefreshRef = useLatestRef(onRefresh);
1932
+ useEffect(() => {
1933
+ const element = scrollRef.current;
1934
+ if (!enabled || !element) return;
1935
+ const config = {
1936
+ threshold,
1937
+ maxDistance,
1938
+ holdDistance,
1939
+ latch: platform !== "android"
1940
+ };
1941
+ let holdTimer;
1942
+ let live = true;
1943
+ const dispatch = (event, native) => {
1944
+ const next = stepPullGesture(gestureRef.current, event, config);
1945
+ if (next.preventDefault && native?.cancelable) native.preventDefault();
1946
+ if (next.gesture !== gestureRef.current) {
1947
+ gestureRef.current = next.gesture;
1948
+ setGesture(next.gesture);
1949
+ }
1950
+ if (next.gesture.phase !== "tracking") clearTimeout(holdTimer);
1951
+ if (next.armed && platform === "android") hapticTick();
1952
+ if (next.refresh) {
1953
+ const settle = () => {
1954
+ if (live) dispatch({ type: "settle" });
1955
+ };
1956
+ let result;
1957
+ try {
1958
+ result = Promise.resolve(onRefreshRef.current());
1959
+ } catch (error) {
1960
+ result = Promise.reject(error);
1961
+ }
1962
+ result.then(settle, settle);
1963
+ }
1964
+ };
1965
+ const atTop = () => element.scrollTop <= 0;
1966
+ const onTouchStart = (event) => {
1967
+ const touch = event.touches[0];
1968
+ dispatch({
1969
+ type: "start",
1970
+ x: touch?.clientX ?? 0,
1971
+ y: touch?.clientY ?? 0,
1972
+ fingers: event.touches.length,
1973
+ atTop: atTop(),
1974
+ ignored: ignoredTarget(event.target)
1975
+ });
1976
+ if (gestureRef.current.phase === "tracking") {
1977
+ clearTimeout(holdTimer);
1978
+ holdTimer = setTimeout(() => dispatch({ type: "hold" }), PULL_TO_REFRESH_LONG_PRESS_MS);
1979
+ }
1980
+ };
1981
+ const onTouchMove = (event) => {
1982
+ if (event.defaultPrevented && gestureRef.current.phase === "tracking") {
1983
+ dispatch({ type: "cancel" });
1984
+ return;
1985
+ }
1986
+ const touch = event.touches[0];
1987
+ dispatch({
1988
+ type: "move",
1989
+ x: touch?.clientX ?? 0,
1990
+ y: touch?.clientY ?? 0,
1991
+ fingers: event.touches.length,
1992
+ atTop: atTop()
1993
+ }, event);
1994
+ };
1995
+ const onTouchEnd = () => dispatch({ type: "end" });
1996
+ const onCancel = () => dispatch({ type: "cancel" });
1997
+ const previousOverscroll = element.style.overscrollBehaviorY;
1998
+ element.style.overscrollBehaviorY = "contain";
1999
+ element.addEventListener("touchstart", onTouchStart, { passive: true });
2000
+ element.addEventListener("touchmove", onTouchMove, { passive: false });
2001
+ element.addEventListener("touchend", onTouchEnd, { passive: true });
2002
+ element.addEventListener("touchcancel", onCancel, { passive: true });
2003
+ element.addEventListener("contextmenu", onCancel);
2004
+ element.addEventListener("dragstart", onCancel);
2005
+ return () => {
2006
+ live = false;
2007
+ clearTimeout(holdTimer);
2008
+ element.style.overscrollBehaviorY = previousOverscroll;
2009
+ element.removeEventListener("touchstart", onTouchStart);
2010
+ element.removeEventListener("touchmove", onTouchMove);
2011
+ element.removeEventListener("touchend", onTouchEnd);
2012
+ element.removeEventListener("touchcancel", onCancel);
2013
+ element.removeEventListener("contextmenu", onCancel);
2014
+ element.removeEventListener("dragstart", onCancel);
2015
+ gestureRef.current = IDLE_PULL_GESTURE;
2016
+ setGesture(IDLE_PULL_GESTURE);
2017
+ };
2018
+ }, [
2019
+ enabled,
2020
+ scrollRef,
2021
+ onRefreshRef,
2022
+ threshold,
2023
+ maxDistance,
2024
+ holdDistance,
2025
+ platform
2026
+ ]);
2027
+ const state = pullState(gesture);
2028
+ const distance = state === "idle" ? 0 : gesture.distance;
2029
+ return {
2030
+ state,
2031
+ distance,
2032
+ progress: state === "refreshing" || gesture.armed ? 1 : pullProgress(distance, threshold),
2033
+ platform
2034
+ };
2035
+ }
2036
+ //#endregion
2037
+ //#region src/components/pull-to-refresh/pull-to-refresh-material-progress.tsx
2038
+ /**
2039
+ * Android's own pull-to-refresh progress, drawn as Material 3 draws it
2040
+ * (Compose's `PullToRefreshDefaults.Indicator`, the one Chrome on Android
2041
+ * shows too): a 2.5px arc of radius 7.5px in a 40px disc. While pulling the
2042
+ * arc grows to 0.8 of the circle and turns a little with the pull, with an
2043
+ * arrowhead at its end, at 0.3 opacity until the pull is armed and fully
2044
+ * opaque from then on. While refreshing it is Material's indeterminate arc,
2045
+ * which grows and shrinks as it turns. Internal: `PullToRefreshIndicator`
2046
+ * renders it on Android.
2047
+ */
2048
+ /** The disc's centre, in its 40px box. */
2049
+ const CENTER = 20;
2050
+ const MATERIAL_ARC_RADIUS = 7.5;
2051
+ const MATERIAL_STROKE_WIDTH = 2.5;
2052
+ const ARROW_WIDTH = 10;
2053
+ const ARROW_HEIGHT = 5;
2054
+ /** The longest the arc gets while pulling, as a share of the circle. */
2055
+ const MATERIAL_MAX_ARC = .8;
2056
+ const CIRCUMFERENCE = 2 * Math.PI * MATERIAL_ARC_RADIUS;
2057
+ /**
2058
+ * The arc for a pull's progress (0 to 1), as Material computes it: nothing
2059
+ * for the first 40%, then the arc grows to `MATERIAL_MAX_ARC` of the circle
2060
+ * and its start turns from -45° to +27° (12 o'clock is -90°), and the
2061
+ * arrowhead grows with it.
2062
+ */
2063
+ function materialArc(progress) {
2064
+ const adjusted = Math.max(Math.min(1, progress) - .4, 0) * 5 / 3;
2065
+ const rotation = (-.25 + .4 * adjusted) * .5;
2066
+ return {
2067
+ startAngle: rotation * 360,
2068
+ endAngle: (rotation + adjusted * MATERIAL_MAX_ARC) * 360,
2069
+ arrowScale: Math.min(1, adjusted)
2070
+ };
2071
+ }
2072
+ const point = (degrees) => {
2073
+ const radians = degrees * Math.PI / 180;
2074
+ return `${CENTER + MATERIAL_ARC_RADIUS * Math.cos(radians)} ${CENTER + MATERIAL_ARC_RADIUS * Math.sin(radians)}`;
2075
+ };
2076
+ /** An SVG path for the arc, clockwise from `startAngle` to `endAngle`. */
2077
+ function arcPath({ startAngle, endAngle }) {
2078
+ const sweep = endAngle - startAngle;
2079
+ if (sweep <= .01) return "";
2080
+ const large = sweep > 180 ? 1 : 0;
2081
+ return `M ${point(startAngle)} A ${MATERIAL_ARC_RADIUS} ${MATERIAL_ARC_RADIUS} 0 ${large} 1 ${point(endAngle)}`;
2082
+ }
2083
+ /**
2084
+ * The arrowhead: a triangle whose base straddles the arc at 3 o'clock and
2085
+ * whose tip points clockwise, turned to the arc's end.
2086
+ */
2087
+ function arrowPoints(scale) {
2088
+ const half = ARROW_WIDTH * scale / 2;
2089
+ const base = 17.5;
2090
+ const x = 27.5;
2091
+ return `${x - half},${base} ${x + half},${base} ${x},${base + ARROW_HEIGHT * scale}`;
2092
+ }
2093
+ const MATERIAL_STYLE = `
2094
+ @keyframes raft-ptr-material-rotate {
2095
+ to {
2096
+ transform: rotate(360deg);
2097
+ }
2098
+ }
2099
+
2100
+ @keyframes raft-ptr-material-dash {
2101
+ 0% {
2102
+ stroke-dasharray: 0.4 ${CIRCUMFERENCE};
2103
+ stroke-dashoffset: 0;
2104
+ }
2105
+ 50% {
2106
+ stroke-dasharray: ${CIRCUMFERENCE * .7} ${CIRCUMFERENCE};
2107
+ stroke-dashoffset: ${-CIRCUMFERENCE * .1};
2108
+ }
2109
+ 100% {
2110
+ stroke-dasharray: ${CIRCUMFERENCE * .7} ${CIRCUMFERENCE};
2111
+ stroke-dashoffset: ${-CIRCUMFERENCE * .99};
2112
+ }
2113
+ }
2114
+
2115
+ [data-slot="pull-to-refresh-material-progress"][data-state="refreshing"] {
2116
+ animation: raft-ptr-material-rotate 1.4s linear infinite;
2117
+ }
2118
+
2119
+ [data-slot="pull-to-refresh-material-progress"][data-state="refreshing"] [data-material-indeterminate] {
2120
+ animation: raft-ptr-material-dash 1.4s ease-in-out infinite;
2121
+ }
2122
+
2123
+ @media (prefers-reduced-motion: reduce) {
2124
+ [data-slot="pull-to-refresh-material-progress"][data-state="refreshing"],
2125
+ [data-slot="pull-to-refresh-material-progress"][data-state="refreshing"] [data-material-indeterminate] {
2126
+ animation: none;
2127
+ }
2128
+
2129
+ [data-slot="pull-to-refresh-material-progress"][data-state="refreshing"] [data-material-indeterminate] {
2130
+ stroke-dasharray: ${CIRCUMFERENCE * .75} ${CIRCUMFERENCE};
2131
+ }
2132
+ }
2133
+ `;
2134
+ const materialStyle = /* @__PURE__ */ jsx("style", {
2135
+ href: "raft-ui-pull-to-refresh-material",
2136
+ precedence: "default",
2137
+ children: MATERIAL_STYLE
2138
+ });
2139
+ const materialProgress = tv({ slots: {
2140
+ root: ["size-10 shrink-0 overflow-visible", "text-info-strong"],
2141
+ determinate: ["transition-opacity duration-150 ease-out motion-reduce:transition-none", "opacity-30 data-armed:opacity-100"],
2142
+ arc: ["fill-none stroke-current [stroke-linecap:butt]"],
2143
+ arrow: ["fill-current"],
2144
+ indeterminate: ["fill-none stroke-current [stroke-linecap:round]"]
2145
+ } });
2146
+ function PullToRefreshMaterialProgress({ state, progress }) {
2147
+ const { root, determinate, arc, arrow, indeterminate } = materialProgress();
2148
+ const refreshing = state === "refreshing";
2149
+ const armed = progress >= 1;
2150
+ const values = materialArc(refreshing ? 1 : progress);
2151
+ return /* @__PURE__ */ jsxs("svg", {
2152
+ "data-slot": "pull-to-refresh-material-progress",
2153
+ "data-state": state,
2154
+ "data-armed": !refreshing && armed ? "" : void 0,
2155
+ viewBox: "0 0 40 40",
2156
+ "aria-hidden": "true",
2157
+ className: root(),
2158
+ children: [materialStyle, refreshing ? /* @__PURE__ */ jsx("circle", {
2159
+ "data-material-indeterminate": "",
2160
+ cx: CENTER,
2161
+ cy: CENTER,
2162
+ r: MATERIAL_ARC_RADIUS,
2163
+ strokeWidth: MATERIAL_STROKE_WIDTH,
2164
+ transform: `rotate(-90 ${CENTER} ${CENTER})`,
2165
+ className: indeterminate()
2166
+ }) : /* @__PURE__ */ jsxs("g", {
2167
+ "data-armed": armed ? "" : void 0,
2168
+ className: determinate(),
2169
+ children: [/* @__PURE__ */ jsx("path", {
2170
+ "data-material-arc": "",
2171
+ d: arcPath(values),
2172
+ strokeWidth: MATERIAL_STROKE_WIDTH,
2173
+ className: arc()
2174
+ }), values.arrowScale > 0 && /* @__PURE__ */ jsx("polygon", {
2175
+ "data-material-arrow": "",
2176
+ points: arrowPoints(values.arrowScale),
2177
+ transform: `rotate(${values.endAngle - 2.5} ${CENTER} ${CENTER})`,
2178
+ className: arrow()
2179
+ })]
2180
+ })]
2181
+ });
2182
+ }
2183
+ //#endregion
2184
+ //#region src/components/pull-to-refresh/pull-to-refresh-indicator.tsx
2185
+ const pullStepStyle = /* @__PURE__ */ jsx("style", {
2186
+ href: "raft-ui-pull-to-refresh",
2187
+ precedence: "default",
2188
+ children: `
2189
+ [data-slot="pull-to-refresh-indicator"][data-pull-step] [data-spinner-pixel],
2190
+ [data-slot="pull-to-refresh-indicator"][data-state="idle"] [data-spinner-pixel] {
2191
+ animation: none;
2192
+ opacity: 0.2;
2193
+ }
2194
+
2195
+ [data-slot="pull-to-refresh-indicator"][data-pull-step="0"] [data-spinner-pixel]:nth-child(1),
2196
+ [data-slot="pull-to-refresh-indicator"][data-pull-step="1"] [data-spinner-pixel]:nth-child(2),
2197
+ [data-slot="pull-to-refresh-indicator"][data-pull-step="2"] [data-spinner-pixel]:nth-child(4),
2198
+ [data-slot="pull-to-refresh-indicator"][data-pull-step="3"] [data-spinner-pixel]:nth-child(3) {
2199
+ opacity: 1;
2200
+ }
2201
+ `
2202
+ });
2203
+ const SNAP_BACK = ["duration-300 ease-slide motion-reduce:transition-none", "data-[state=pulling]:transition-none"];
2204
+ const pullToRefreshIndicator = tv({
2205
+ slots: {
2206
+ root: ["flex w-full shrink-0 justify-center", "text-foreground-icon"],
2207
+ surface: ["flex items-center justify-center"],
2208
+ spinner: [
2209
+ "transition-opacity duration-300 ease-slide motion-reduce:transition-none",
2210
+ "in-data-[state=pulling]:transition-none",
2211
+ "in-data-[state=pulling]:opacity-(--pull-progress) in-data-[state=idle]:opacity-0"
2212
+ ],
2213
+ status: ["sr-only"]
2214
+ },
2215
+ variants: { platform: {
2216
+ default: {
2217
+ root: [
2218
+ "relative items-center overflow-hidden",
2219
+ "transition-[height]",
2220
+ ...SNAP_BACK
2221
+ ],
2222
+ surface: ["size-full"]
2223
+ },
2224
+ android: {
2225
+ root: ["sticky top-0 z-10 h-0 overflow-visible"],
2226
+ surface: [
2227
+ "absolute inset-x-0 top-0 mx-auto size-10 rounded-full bg-layer-popover shadow-float",
2228
+ "translate-y-[calc(var(--pull-distance)-100%)]",
2229
+ "transition-[translate,opacity,scale]",
2230
+ ...SNAP_BACK,
2231
+ "data-[state=idle]:opacity-0",
2232
+ "data-[exit=finish]:scale-0 data-[exit=finish]:duration-150 data-[exit=finish]:ease-out"
2233
+ ]
2234
+ }
2235
+ } },
2236
+ defaultVariants: { platform: "default" }
2237
+ });
2238
+ /**
2239
+ * How the Android disc leaves once idle: `finish` when a refresh has just
2240
+ * ended (it scales down where it held), `cancel` otherwise (it slides back
2241
+ * up). The finish keeps the distance it held, so it doesn't also slide.
2242
+ * `gone` once the scale-down has ended: the disc stays scaled away and its
2243
+ * arc stops turning.
2244
+ */
2245
+ function useAndroidExit(state, distance) {
2246
+ const [previous, setPrevious] = useState(state);
2247
+ const [exit, setExit] = useState({
2248
+ kind: "cancel",
2249
+ distance: 0
2250
+ });
2251
+ const [held, setHeld] = useState(distance);
2252
+ if (state !== previous) {
2253
+ setPrevious(state);
2254
+ if (state === "idle") setExit(previous === "refreshing" ? {
2255
+ kind: "finish",
2256
+ distance: held
2257
+ } : {
2258
+ kind: "cancel",
2259
+ distance: 0
2260
+ });
2261
+ }
2262
+ if (state === "refreshing" && distance !== held) setHeld(distance);
2263
+ const settle = () => {
2264
+ if (exit.kind === "finish") setExit({
2265
+ ...exit,
2266
+ kind: "gone"
2267
+ });
2268
+ };
2269
+ return {
2270
+ ...exit,
2271
+ settle
2272
+ };
2273
+ }
2274
+ /**
2275
+ * The pull's indicator. Render it as the scroller's first child: by default
2276
+ * it is the space the pull opens, with the DS Spinner in it, so the content
2277
+ * moves down with the pull; on Android it is Material 3's own indicator, a
2278
+ * disc with a progress arc that travels down over the content. It holds a
2279
+ * polite live region that announces `label` while refreshing.
2280
+ */
2281
+ function PullToRefreshIndicator({ pull, label, className, style, ...props }) {
2282
+ const { state, distance, progress, platform } = pull;
2283
+ const { root, surface, spinner, status } = pullToRefreshIndicator({ platform });
2284
+ const android = platform === "android";
2285
+ const exit = useAndroidExit(state, distance);
2286
+ const finishing = android && state === "idle" && exit.kind !== "cancel";
2287
+ return /* @__PURE__ */ jsxs("div", {
2288
+ "data-slot": "pull-to-refresh-indicator",
2289
+ "data-state": state,
2290
+ "data-platform": platform,
2291
+ "data-pull-step": !android && state === "pulling" ? pullStep(progress) : void 0,
2292
+ className: root({ className }),
2293
+ style: {
2294
+ ...style,
2295
+ height: android ? void 0 : distance,
2296
+ ["--pull-progress"]: progress,
2297
+ ["--pull-distance"]: `${finishing ? exit.distance : distance}px`
2298
+ },
2299
+ ...props,
2300
+ children: [
2301
+ !android && pullStepStyle,
2302
+ /* @__PURE__ */ jsx("div", {
2303
+ "data-slot": "pull-to-refresh-surface",
2304
+ "data-state": state,
2305
+ "data-exit": finishing ? "finish" : void 0,
2306
+ className: surface(),
2307
+ onTransitionEnd: (event) => {
2308
+ if (event.target === event.currentTarget && event.propertyName === "scale") exit.settle();
2309
+ },
2310
+ children: android ? /* @__PURE__ */ jsx(PullToRefreshMaterialProgress, {
2311
+ state: finishing && exit.kind === "finish" ? "refreshing" : state,
2312
+ progress
2313
+ }) : /* @__PURE__ */ jsx(Spinner, {
2314
+ "aria-hidden": "true",
2315
+ role: "presentation",
2316
+ "aria-label": void 0,
2317
+ className: spinner()
2318
+ })
2319
+ }),
2320
+ /* @__PURE__ */ jsx("span", {
2321
+ role: "status",
2322
+ "aria-live": "polite",
2323
+ className: status(),
2324
+ children: state === "refreshing" ? label : ""
2325
+ })
2326
+ ]
2327
+ });
2328
+ }
2329
+ //#endregion
2330
+ export { Dialog as AnnouncementDialog, AnnouncementDialogAction, AnnouncementDialogBody, DialogClose as AnnouncementDialogClose, AnnouncementDialogContent, AnnouncementDialogFooter, AnnouncementDialogHeader, AnnouncementDialogLabel, AnnouncementDialogPicture, AnnouncementDialogSecondaryAction, AnnouncementDialogText, AnnouncementDialogTitle, DialogTrigger as AnnouncementDialogTrigger, COMMENT_HIGHLIGHT, COMMENT_HIGHLIGHT_ACTIVE, ComboboxSelect, CommentCard, CommentCardMeta, CommentCardQuote, CommentCardTrigger, CommentEntry, CommentEntryAuthor, CommentEntryBody, CommentEntryHeader, CommentEntryTime, CommentMargin, CommentMarginItem, CommentMarker, DialogCommit, DialogFooterNote, DialogSheetBack, DialogSheetContent, DropdownMenuLinkItem, Ellipsis, EllipsisToggle, InboxItemLeadingBadge, InboxItemSkeleton, InboxItemSkeletonList, ListRowSkeleton, MessageItemDelegatedAvatar, MessageItemDelegatedBy, MessageItemDelegatedByButton, MessageItemDelegatedByName, MessageListJumpControls, MessageListJumpPill, MessageListJumpPillDismiss, MessageListJumpPillGroup, MessageQuotedPreviewAuthorDelegatedBy, MessageReferenceIcon, MessageReferenceReadMark, Meter, MeterHeader, MeterIndicator, MeterLabel, MeterTrack, MeterValue, MobileNavServerItem, MobileNavServerPopover, MobileNavServerPopoverContent, MobileNavServerPopoverDestination, MobileNavServerPopoverDestinations, MobileNavServerPopoverGroup, MobileNavServerPopoverList, MobileNavServerPopoverRow, MobileNavServerPopoverRowBody, MobileNavServerPopoverRowDescription, MobileNavServerPopoverRowLabel, OverlayLayerProvider, PULL_TO_REFRESH_DAMPING, PULL_TO_REFRESH_HOLD_DISTANCE, PULL_TO_REFRESH_MAX_DISTANCE, PULL_TO_REFRESH_POINTER_QUERY, PULL_TO_REFRESH_SNAP_BACK_MS, PULL_TO_REFRESH_THRESHOLD, PopoverActions, PopoverBody, PreviewCardActions, PreviewCardBody, PreviewCardEyebrow, PreviewCardFooter, PreviewCardMeta, PullToRefreshIndicator, resolveCommentMarginLayout, setCommentHighlights, useCommentMarginFits, useHoldThenMoveTouchSensor, useParentOverlayKind, usePullToRefresh, useTruncated };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botiverse/raft-ui",
3
- "version": "0.26.0",
3
+ "version": "0.28.0",
4
4
  "description": "React components and CSS foundations for the Raft Design System.",
5
5
  "keywords": [
6
6
  "agent-skills",