@kitn.ai/ui
Version:
Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. Authored in SolidJS.
119 lines (118 loc) • 5.44 kB
TypeScript
import { ToastPosition } from '../components/toast';
export type ToastVariant = 'neutral' | 'success' | 'warning' | 'error' | 'info';
/** Visual treatment: `'pill'` (default, compact single-line) or `'card'` (richer
* rounded card with an optional description line). */
export type ToastAppearance = 'pill' | 'card';
export interface ToastConfig {
stack?: 'expanded' | 'collapsed';
position?: ToastPosition;
max?: number;
/** Default appearance for imperatively-raised toasts. Defaults to `'pill'`. */
appearance?: ToastAppearance;
/** Default high-contrast inverse treatment for imperatively-raised toasts.
* Defaults to `false`. */
inverse?: boolean;
}
/**
* Configure the imperative `toast()` singleton — call once at app start.
* `toast.success('…')` has no element to set a prop on, so this is how you opt
* the auto-mounted region into collapsed stacking / a position / a max. Updates
* any already-mounted regions too, so call order doesn't matter.
*/
export declare function configureToasts(config: ToastConfig): void;
/** An action button rendered inside the toast. Returning `false` from
* `onAction` keeps the toast open (e.g. to show a follow-up); any other
* return value dismisses it. */
export interface ToastAction {
label: string;
onAction: () => void | false;
}
export interface ToastItem {
id: string;
message: string;
variant?: ToastVariant;
/** Visual treatment: `'pill'` (default, compact single-line) or `'card'` (richer
* rounded card with an optional description line). */
appearance?: ToastAppearance;
/** High-contrast inverse surface — works on either appearance, popping in light
* AND dark. Defaults to `false`. */
inverse?: boolean;
/** Secondary line shown below the message in the `'card'` appearance. The
* `'pill'` appearance ignores it. */
description?: string;
action?: ToastAction;
/** Auto-dismiss delay in ms. `0` = sticky (never auto-dismisses). When an
* `action` is present the effective floor is 4000ms so it stays long enough
* to act on. Defaults to 2000ms. */
duration?: number;
/** Whether the × close affordance is shown. Defaults to `true`. */
dismissible?: boolean;
/** Container to scope this toast WITHIN — it floats anchored to that element's
* bounds instead of the viewport. Omit for a global, viewport-anchored toast.
* The chat targets itself by default so its copy/feedback toasts stay in-chat. */
target?: HTMLElement;
}
/** Options accepted by `toast()` — everything but the message. Pass `id` to
* update an existing toast in place. */
export interface ToastOptions {
id?: string;
variant?: ToastVariant;
/** Visual treatment: `'pill'` (default) or `'card'`. Falls back to the value set
* via `configureToasts`, then `'pill'`. */
appearance?: ToastAppearance;
/** High-contrast inverse surface. Falls back to `configureToasts`, then `false`. */
inverse?: boolean;
/** Secondary line shown below the message in the `'card'` appearance. */
description?: string;
action?: ToastAction;
duration?: number;
dismissible?: boolean;
/** Scope this toast to a container's bounds (e.g. a chat) instead of the
* viewport. Omit for a global, viewport-anchored toast. */
target?: HTMLElement;
}
/** Handle returned from `toast()` for imperative control. */
export interface ToastHandle {
id: string;
dismiss: () => void;
update: (patch: Partial<Omit<ToastItem, 'id'>>) => void;
}
/** Default auto-dismiss delay. Long enough to read + reach before it leaves. */
export declare const DEFAULT_TOAST_DURATION = 5000;
/** Minimum auto-dismiss delay when the toast carries an action (e.g. Undo) — it
* has to stay up long enough to actually act on. */
export declare const ACTION_TOAST_FLOOR = 7000;
/** The live toast list (reactive). The region facade binds to this. */
export declare function getToasts(): ToastItem[];
/** Resolve the effective duration, applying the action floor. */
declare function resolveDuration(item: Pick<ToastItem, 'duration' | 'action'>): number;
export declare function ensureMounted(target?: HTMLElement | null): HTMLElement | undefined;
/** Test-only: whether `ensureMounted` has run. */
export declare function isToastRegionMounted(): boolean;
export interface ToastFn {
(message: string, opts?: ToastOptions): ToastHandle;
/** Raise a success (green check) toast. */
success: (message: string, opts?: ToastOptions) => ToastHandle;
/** Raise a warning (amber) toast — e.g. an agent needs your input. */
warning: (message: string, opts?: ToastOptions) => ToastHandle;
/** Raise an error (destructive/red) toast — e.g. an agent failed. */
error: (message: string, opts?: ToastOptions) => ToastHandle;
/** Raise an info (blue) toast. */
info: (message: string, opts?: ToastOptions) => ToastHandle;
/** Dismiss a toast by id. */
dismiss: (id: string) => void;
/** Dismiss every active toast. */
clear: () => void;
}
/**
* Raise a transient toast. Returns a `{ id, dismiss, update }` handle.
*
* ```ts
* toast('Copied to clipboard');
* toast.success('Saved');
* const t = toast('Working…', { duration: 0 });
* t.update({ message: 'Done', variant: 'success', duration: 2000 });
* ```
*/
export declare const toast: ToastFn;
export { resolveDuration };