Types

Every other public type, grouped as the contracts define them, with the page that uses it.

On this page

The package exports its TypeScript contracts from the root: import type { … } from '@cloudlet/toast'. The types of the factory, the controller and the Toaster are on their own pages; this page covers the rest, grouped as in the contracts, and links each type to the page where it is used. Core types take a Slot parameter for rich content; the React… aliases at the end fix it to ReactNode.

Identity

Handles and tokens are capabilities minted by the controller. They are never built by hand, compared across controllers or stored across reloads.

TypeDefinitionDescription
NotificationHandle{ id, controller, generation }One appearance of a notification, returned by show and track. Pass it to update and dismiss. Not a serializable ID: keep the id string for that.
ControllerIdentityopaque stringWhich controller minted a handle; ControllerSnapshot.controller.
Generationopaque stringWhich appearance of an ID a handle belongs to; a reused ID gets a new generation.
OperationAttemptTokenopaque stringOne attempt of a tracked operation; see track.
ActionAttemptTokenopaque stringOne run of a command action; see PrimaryAction.
Unsubscribe() => voidReturned by subscribe and onEvent. Calling it again is harmless.
HandleRejection'invalid-handle' | 'foreign-controller' | 'stale-handle'Why a handle was refused; part of MutationRejection and FocusResult.
InputIssue{ path: string; message: string }One invalid field of a rejected show, update or track.

Notifications

TypeDefinitionUsed on
NotificationKind'info' | 'success' | 'loading' | 'warning' | 'error'show, Notifications & time
Priority'normal' | 'high'show, track: record metadata that does not reorder the stack.
AnnouncementPriority'polite' | 'assertive' | 'off'show, Labels & announcements
Durationnumber | nullshow: readable milliseconds ≥ 0, or null to stay until closed.
Attention'auto' | 'open' | 'stack'show, Positioning & offsets
NotificationContenttitle, description?, icon?, progress?, action?, announcementPriority?, duration?, attention?What a notification shows; the content of track's pending, success, error and cancelled.
NotificationSpecNotificationContent and id?, kind?, priority?, dedupeKey?, onClose?show
NotificationPatchthe changeable fields, null removesupdate
AdmissionResult, AdmissionRejectioncreated, deduplicated or rejectedshow
OperationAdmissionResultAdmissionResult without deduplicatedOperationHandle.admission
OverflowSnapshot{ count, pending }onOverflow, ControllerSnapshot.overflow

Description

Description<Slot>, the text under the title:

VariantFieldsDescription
{ kind: 'text' }text: stringPlain text; may be empty.
{ kind: 'rich' }content: Slot, announcement: stringYour own non-interactive content (a ReactNode), and the non-empty text screen readers hear instead of it. Buttons and links belong in the action.

Progress

Progress, a ring around the icon:

VariantFieldsDescription
{ kind: 'indeterminate' }label?: stringWork of unknown length.
{ kind: 'determinate' }value: number, label?: stringvalue is finite, from 0 to 1; out-of-range values are rejected, not clamped. label names the progress for assistive technology.

PrimaryAction

PrimaryAction is a CommandAction or a NavigationAction; a notification has at most one. Operations & cancellation shows both.

CommandAction runs your function:

PropTypeDefaultDescription
kind'command'—Required.
labelstring—Required, non-empty. The button text.
run(context: ActionContext) => unknown—Required. May return a value, nothing or a promise. While it runs the button is pending and a second press is refused; success closes the notification (action-success), failure keeps it with a message and allows another try.
errorMessage(error: unknown) => stringmessages.actionErrorTurns a failure into the message shown on the card.

ActionContext is passed to run: handle, the notification's NotificationHandle, and token, the ActionAttemptToken of this run.

NavigationAction is a real link:

PropTypeDefaultDescription
kind'link'—Required.
labelstring—Required, non-empty. The link text.
hrefstring—Required. Relative and fragment URLs, http:, https:, mailto: and tel:; other schemes are rejected.
target'_self' | '_blank' | '_parent' | '_top'—Where it opens. _blank always gets noopener.
relstring—Your rel; noopener is added to it, never replacing it.

Following the link closes the notification with the reason navigation; modifier keys and new tabs behave as for any link.

CloseReason

CloseNotice is what onClose receives: handle and reason, a CloseReason:

ReasonClosed by
'timeout'Its readable time ran out.
'programmatic'dismiss(handle).
'close-button'The user pressed close.
'swipe'The user swiped the pill away.
'action-success'Its command action succeeded.
'navigation'Its link was followed.
'clear'clear().
'dispose'dispose().

Operations

TypeDefinitionUsed on
OperationSource<T>PromiseLike<T> | OperationFactory<T>track
OperationFactory<T, Signal>(context: OperationContext<Signal>) => T | PromiseLike<T>track: called once per attempt.
OperationContext<Signal>{ signal, token, attempt }The factory's argument: this attempt's signal, its OperationAttemptToken and its number from 1.
OperationStatus'pending' | 'fulfilled' | 'rejected' | 'cancelled'OperationSnapshot
OperationSnapshotthe current attempt's stateOperationHandle.getSnapshot
OperationAttempt<T>{ token, attempt, result }Returned for each new attempt by retry and restart.
OperationHandle<T>the first attempt plus commandstrack
AttemptStartResult<T>, CancelResultresults of retry/restart and cancelOperationHandle
TrackOptions<T, Slot, Signal>the options of tracktrack

CancellationSignal is the minimal abort port the core needs, so it runs without the DOM. A native AbortSignal implements it, and the React controller gives factories a real AbortSignal.

MemberTypeDescription
abortedbooleanCancellation was requested.
reasonunknownThe reason passed to cancel.
throwIfAborted() => voidThrows the reason if aborted.
addEventListener(type: 'abort', listener, options?) => voidListens for the request; { once: true } is supported.
removeEventListener(type: 'abort', listener) => voidStops listening.

Snapshots

TypeDefinitionUsed on
ControllerSnapshotthe whole stategetSnapshot
IslandSnapshot{ open, reason, current }ControllerSnapshot.island; reason and current are null exactly when closed.
IslandReason'user' | 'attention'Whether the user opened the Island or a notification needing attention did.
NotificationLocation'stack' | 'current'current is the one presented notification: the pill, or the Island's slide.

NotificationSnapshot

One notification in ControllerSnapshot.notifications, also passed to the announcement formatters.

FieldTypeDescription
handleNotificationHandleIts handle.
kindNotificationKindIts current kind.
contentNotificationContentWhat it shows.
priorityPriorityIts metadata priority.
occurrencesnumber1, plus each deduplicated repeat.
locationNotificationLocation'current' when presented, otherwise 'stack'.
remainingMsnumber | nullReadable time left when the snapshot was taken (it does not tick); null when it stays until closed.
pauseReasonsreadonly PauseReason[]Why its time is not running; empty while it runs.
operationOperationSnapshot | nullThe tracked operation, or null for a plain notification.
actionActionSnapshotThe state of its command action.

ActionSnapshot is { status: 'idle' }, { status: 'pending', token } while a command runs, or { status: 'failed', token, message } after it failed.

PauseReason, the reasons a notification's time stands still; time runs only when there are none:

ReasonMeaning
'inactive'It is not the presented notification.
'no-host'No Toaster is attached.
'presentation-pending'It is about to be shown and is not readable yet.
'hover'The pointer is over the notifications.
'focus'Keyboard focus is inside the notifications.
'gesture'A swipe is in progress.
'action-pending'Its command action is running.
'content-transition'Its content is being swapped on screen.
'island'It is the Island's slide and the user opened the Island, or it asks for action.
'document-hidden'The tab is hidden.
'window-blur'The window lost focus.

Events

TypeDefinitionUsed on
SemanticEventEventBase and one variant per typeonEvent
EventBase{ controller, sequence, at }The fields every event has.
Diagnostic{ code, source, message, handle?, error? }onDiagnostic, the diagnostic event
DiagnosticCode'invalid-input' | 'second-host' | …onDiagnostic

Controller

TypeUsed on
CloudletController<Slot, Signal>Controller: the generic controller.
NotificationController<Slot>Controller: the controller without track.
ControllerOptions, FallbackMessagescreateCloudlet
MutationResult, MutationRejectionupdate, dismiss, acknowledgeOverflow
ClearResultclear
FocusTarget, FocusResultrequestFocus

React

The React entry fixes Slot to ReactNode and Signal to AbortSignal:

TypeEqualsUsed on
ReactCloudletControllerCloudletController<ReactNode, AbortSignal>createCloudlet, useCloudlet, useOptionalCloudlet
ReactNotificationSpecNotificationSpec<ReactNode>show
ReactNotificationPatchNotificationPatch<ReactNode>update
ReactTrackOptions<T>TrackOptions<T, ReactNode, AbortSignal>track
ReactOperationFactory<T>OperationFactory<T, AbortSignal>track
ReactOperationContextOperationContext<AbortSignal>track
CreateCloudlet(options?: ControllerOptions) => ReactCloudletControllercreateCloudlet
CloudletProviderComponent, UseCloudlet, UseOptionalCloudlet, ToasterComponentthe signatures of the two components and the two hooksToaster props
ToasterProps, ToasterOffsets, EdgeInsets, ToasterAttention, ToasterMotion, CloudletPartthe Toaster's propsToaster props
CloudletMotionConstants, CloudletMotionOverrides, CloudletSpring, CloudletTimedSpringthe motion debugging channelToasterMotion
CloudletLabels, AnnouncementFormattersthe Toaster's textsLabels & announcements
CloudletProviderPropsthe provider's propsCloudletProvider