@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.
56 lines (55 loc) • 2.54 kB
TypeScript
import { CardEnvelope, CardPolicy, CardResolution } from './card-contract';
/** The minimal toast surface this helper needs. Inject a real adapter (e.g. one
* backed by `kai-toast-region`) — this module never imports the toast itself. */
export interface RecoveryToast {
show(opts: {
message: string;
action?: {
label: string;
onClick: () => void;
};
durationMs?: number;
}): {
dismiss(): void;
};
}
/** Context handed to a custom `isReopenable` predicate. */
export interface ReopenEnv {
cardId: string;
/** The card's current resolution at reopen time (should be `dismissed`). */
resolution: CardResolution | undefined;
/** `Date.now()` at reopen time (injected for testability). */
now: number;
}
export interface DismissRecoveryOptions {
/** Read the current cards array. */
get: () => CardEnvelope[];
/** Write the next cards array (a NEW reference). */
set: (next: CardEnvelope[]) => void;
/** Optional injected toast adapter for the "Dismissed · Undo" affordance. */
toast?: RecoveryToast;
/** Override the default re-openable rule. Return false to expire instead. */
isReopenable?: (env: ReopenEnv) => boolean;
/** A dismissed card older than this (ms since `dismissed.at`) is no longer
* re-openable (→ expired). Omit/Infinity = never stale. */
staleAfterMs?: number;
/** Auto-dismiss the Undo toast after this long. Default 6000ms. */
undoMs?: number;
/** Injected clock (defaults to Date.now); keeps the helper testable. */
now?: () => number;
}
/** Default re-openable rule: a card can come back unless it carries a terminal
* resolution OR it has gone stale (`staleAfterMs` elapsed since `dismissed.at`).
* A `dismissed` card with no/invalid `at` is always re-openable. */
export declare function defaultIsReopenable(env: ReopenEnv, staleAfterMs?: number): boolean;
/**
* Build the `{ onDismiss, onReopen }` policy handlers for the card dismiss/recovery
* flow over a host store (`get`/`set`).
*
* - `onDismiss(cardId)` — stamps `{ kind:'dismissed', at }` immutably and, when a
* `toast` is injected, shows "Dismissed" with an Undo that restores the card's
* prior resolution (live again when there was none).
* - `onReopen(cardId)` — clears the resolution (live) when `isReopenable`, else
* stamps `{ kind:'expired', at }`.
*/
export declare function dismissRecovery(opts: DismissRecoveryOptions): Pick<CardPolicy, 'onDismiss' | 'onReopen'>;