@ailuracode/alpine-toast 0.1.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,8 +1,22 @@
1
- import AlpineType from 'alpinejs';
1
+ import { SingletonScope, Alpine, Unsubscribe, PluginCallback, BaseController } from '@ailuracode/alpine-core';
2
+ export { Unsubscribe } from '@ailuracode/alpine-core';
3
+ import { Alpine as Alpine$1 } from 'alpinejs';
4
+
5
+ /**
6
+ * Public type contracts for `@ailuracode/alpine-toast`.
7
+ *
8
+ * Per `.cursor/rules/formatting.mdc`, every public type
9
+ * lives in a `types.ts` module so consumers can import them without pulling
10
+ * the implementation. The shape IS the contract — changes to a field name
11
+ * or type are breaking changes.
12
+ */
2
13
 
3
14
  /** Built-in Alpine store key for the toast queue. */
4
15
  declare const TOAST_STORE_KEY: "toast";
16
+ /** Built-in `$toast` magic key registered by {@link toastPlugin}. */
17
+ declare const TOAST_MAGIC_KEY: "toast";
5
18
  type ToastStoreKey = typeof TOAST_STORE_KEY;
19
+ type ToastMagicKey = typeof TOAST_MAGIC_KEY;
6
20
  /** Built-in position used when none is provided. Map to CSS in your UI layer. */
7
21
  type DefaultToastPosition = "bottom-right";
8
22
  /** Union of `bottom-right` plus developer-defined positions from plugin options. */
@@ -76,6 +90,14 @@ interface ToastPluginOptions<TVariants extends readonly string[] = readonly [],
76
90
  listenToWindowEvents?: boolean;
77
91
  /** Internal store key. Default: `"toast"`. */
78
92
  storeKey?: ToastStoreKey;
93
+ /**
94
+ * `$toast` magic key the Alpine plugin registers under. Defaults to
95
+ * {@link TOAST_MAGIC_KEY}. Set when the host already owns a `toast`
96
+ * magic or another toolkit plugin would collide on that name — the
97
+ * rename avoids the collision without touching the controller.
98
+ * Ignored by the standalone `createToastController` helper.
99
+ */
100
+ magicKey?: string;
79
101
  }
80
102
  interface ToastPromiseMessages<T = unknown, TVariant extends string = string, TContent = unknown> {
81
103
  loading?: string;
@@ -155,25 +177,154 @@ type ResolvedToastPluginConfig<TVariants extends readonly string[] = readonly []
155
177
  maxVisible: number;
156
178
  listenToWindowEvents: boolean;
157
179
  storeKey: ToastStoreKey;
180
+ magicKey: string;
158
181
  variants: TVariants;
159
182
  positions: TPositions;
160
183
  promise: ResolvedPromiseConfig<TVariants>;
161
184
  };
162
-
163
- /** Resolves plugin options with defaults and queue limit rules. */
164
- declare function resolveToastPluginConfig<const TVariants extends readonly string[] = readonly [], const TPositions extends readonly string[] = readonly []>(options?: ToastPluginOptions<TVariants, TPositions>): ResolvedToastPluginConfig<TVariants, TPositions>;
165
- /** Builds typed toast plugin options with inferred variant and position literals. */
166
- declare function toastOptions<const TVariants extends readonly string[] = readonly [], const TPositions extends readonly string[] = readonly [], TContent = unknown>(options: ToastPluginOptions<TVariants, TPositions, TContent>): ToastPluginOptions<TVariants, TPositions, TContent>;
167
- /** Declares toast variant names with full literal inference. */
168
- declare function toastVariants<const T extends readonly string[]>(variants: T): T;
169
- /** Declares toast position names with full literal inference. */
170
- declare function toastPositions<const T extends readonly string[]>(positions: T): T;
171
-
172
- /** Variant names that cannot override core `$toast` methods. */
173
- declare const RESERVED_TOAST_MAGIC_KEYS: Set<string>;
174
- /** Builds the callable `$toast` magic API backed by the internal toast store. */
175
- declare function createToastMagic<const TVariants extends readonly string[], const TPositions extends readonly string[] = readonly [], TContent = unknown>(config: ResolvedToastPluginConfig<TVariants, TPositions>, getStore: () => ToastStore<TVariants, TPositions, TContent>): ToastMagic<TVariants, TPositions, TContent>;
176
-
185
+ /**
186
+ * Source of a toast transition informs subscribers why a change
187
+ * happened. Single source of truth for the `change` event's `source`
188
+ * field; adding a new member ripples through every consumer so
189
+ * exhaustiveness is enforced by TypeScript.
190
+ *
191
+ * Public: branching on `detail.source` is a contract.
192
+ */
193
+ type ToastChangeSource = "initialization" | "push" | "pushUnique" | "update" | "dismiss" | "dismissAt" | "dismissAll";
194
+ /**
195
+ * Structured payload delivered to subscribers on every transition.
196
+ *
197
+ * - `source` discriminates the kind of transition.
198
+ * - `items` is the full snapshot Alpine's reactive proxy mirrors
199
+ * the array reference (replacing, not mutating in place) so
200
+ * template `x-for` loops see the new contents.
201
+ */
202
+ interface ToastChangeDetail<TVariants extends readonly string[] = readonly [], TPositions extends readonly string[] = readonly [], TContent = unknown> {
203
+ readonly source: ToastChangeSource;
204
+ readonly items: ToastItem<TVariants, TPositions, TContent>[];
205
+ }
206
+ /** Options accepted by {@link createToastController}. */
207
+ interface CreateToastControllerOptions<TPositions extends readonly string[] = readonly [], _TContent = unknown> {
208
+ /**
209
+ * Stable identifier exposed via {@link ToastController.id}. When
210
+ * omitted, the controller generates one from the controller name.
211
+ * Tests typically pin this for deterministic assertions.
212
+ */
213
+ readonly id?: string;
214
+ /** Default position for new toasts when payload omits it. */
215
+ readonly defaultPosition?: ToastPosition<TPositions>;
216
+ /** Declared positions — each gets its own stack. */
217
+ readonly positions?: TPositions;
218
+ /** Default auto-dismiss duration in milliseconds. */
219
+ readonly defaultDuration?: number;
220
+ /** Maximum toasts in the queue. `0` = unlimited. */
221
+ readonly maxToasts?: number;
222
+ /** Maximum toasts shown at once. Defaults to `maxToasts`. */
223
+ readonly maxVisible?: number;
224
+ /** Listen for `toast` window events. Default: `true`. */
225
+ readonly listenToWindowEvents?: boolean;
226
+ /** Internal store key. Default: `"toast"`. */
227
+ readonly storeKey?: ToastStoreKey;
228
+ /**
229
+ * Reactive store accessor — maintained for backwards compatibility
230
+ * with the pre-controller architecture. The auto-dismiss timer
231
+ * routes through this accessor when provided, so callers can wrap
232
+ * the store in a proxy and observe timer-fired dismissals.
233
+ */
234
+ readonly getStore?: () => ToastStore<readonly [], TPositions, unknown>;
235
+ /**
236
+ * Singleton scope for this controller. Defaults to the active
237
+ * `document`, an ambient `runWithSingletonScope()` context, or —
238
+ * in SSR — must be provided explicitly as a plain object.
239
+ */
240
+ readonly scope?: SingletonScope;
241
+ }
242
+ /**
243
+ * Public, framework-agnostic manager returned by {@link createToastController}.
244
+ *
245
+ * Reads flow through getters; mutations go through the manager so
246
+ * subscriptions and the in-place snapshot stay consistent.
247
+ *
248
+ * The Alpine integration subscribes to the `change` event and
249
+ * mirrors the snapshot into the reactive store so bindings re-render
250
+ * automatically. Standalone consumers can wire their own adapter via
251
+ * `manager.on("change", detail => ...)`.
252
+ */
253
+ interface ToastManager<TVariants extends readonly string[] = readonly [], TPositions extends readonly string[] = readonly [], TContent = unknown> {
254
+ /** Default position for new toasts when payload omits it. */
255
+ readonly defaultPosition: ToastPosition<TPositions>;
256
+ /** Declared positions with an independent stack each. */
257
+ readonly stackPositions: readonly ToastPosition<TPositions>[];
258
+ /** Maximum toasts in the queue. `0` = unlimited. */
259
+ readonly maxToasts: number;
260
+ /** Maximum toasts shown at once. */
261
+ readonly maxVisible: number;
262
+ /** Live snapshot of every toast (newest first). */
263
+ readonly items: ToastItem<TVariants, TPositions, TContent>[];
264
+ /** Pushes a new toast and returns its id. */
265
+ push(payload?: ToastPayload<TVariants, TPositions, TContent>): string;
266
+ /**
267
+ * Dismisses every active toast with the same `key`, then pushes.
268
+ * Useful for undo flows and single-slot notices.
269
+ */
270
+ pushUnique(key: string, payload?: ToastPayload<TVariants, TPositions, TContent>): string;
271
+ /** Patches a toast in place by id. Resets the auto-dismiss timer if `duration` changes. */
272
+ update(id: string, payload?: Partial<ToastPayload<TVariants, TPositions, TContent>>): void;
273
+ /** Marks a toast as removed; purge happens after a short delay. */
274
+ dismiss(id: string): void;
275
+ /** Marks every toast at `position` as removed. */
276
+ dismissAt(position: ToastPosition<TPositions>): void;
277
+ /** Marks every toast as removed. */
278
+ dismissAll(): void;
279
+ /** Toasts at `position`, newest first (includes exiting `removed` items). */
280
+ itemsAt(position: ToastPosition<TPositions>): ToastItem<TVariants, TPositions, TContent>[];
281
+ /** Timed stack at `position` (includes exiting `removed` items). */
282
+ timedItemsAt(position: ToastPosition<TPositions>): ToastItem<TVariants, TPositions, TContent>[];
283
+ /** Persistent stack at `position` (includes exiting `removed` items). */
284
+ persistentItemsAt(position: ToastPosition<TPositions>): ToastItem<TVariants, TPositions, TContent>[];
285
+ /** Active timed toasts only — preferred for `x-for` render lists. */
286
+ activeTimedItemsAt(position: ToastPosition<TPositions>): ToastItem<TVariants, TPositions, TContent>[];
287
+ /** Active persistent toasts only — preferred for `x-for` render lists. */
288
+ activePersistentItemsAt(position: ToastPosition<TPositions>): ToastItem<TVariants, TPositions, TContent>[];
289
+ /** Whether the timed toast at `index` (within `timedItemsAt`) should render. */
290
+ isVisibleAt(position: ToastPosition<TPositions>, index: number): boolean;
291
+ /**
292
+ * Subscribes to a `change` event. Returns an unsubscribe function.
293
+ * The detail payload carries `source` and `items` (full snapshot).
294
+ */
295
+ on(event: "change", listener: (detail: ToastChangeDetail<TVariants, TPositions, TContent>) => void): Unsubscribe;
296
+ /** Tears down listeners and timers. Idempotent. */
297
+ destroy(): void;
298
+ }
299
+ /**
300
+ * Typed view of `Alpine` the toast plugin uses internally.
301
+ *
302
+ * Built from the toolkit's {@link Alpine} generic with the `toast`
303
+ * store mapped to its concrete {@link ToastStore} shape. A real
304
+ * `Alpine` runtime is assignable to `ToastAlpine` without a cast
305
+ * because the toolkit's `Alpine<Stores>` only adds overloads.
306
+ *
307
+ * The optional `cleanup?` member mirrors theme/lang/scroll's
308
+ * integrations so `controller.destroy()` can be forwarded through
309
+ * Alpine's lifecycle when available.
310
+ */
311
+ type ToastAlpine = Alpine<{
312
+ toast: ToastStore;
313
+ }> & {
314
+ /** Forwarded through Alpine's cleanup mechanism when available. */
315
+ cleanup?(callback: () => void): void;
316
+ };
317
+ /**
318
+ * `Alpine.plugin()` callback signature.
319
+ *
320
+ * Typed against the base {@link AlpineBase} via the toolkit's
321
+ * {@link PluginCallback} generic, which keeps this alias structurally
322
+ * assignable to `Base.PluginCallback`. The plugin narrows the
323
+ * runtime instance to {@link ToastAlpine} inside the function body
324
+ * for typed access to the `"toast"` store / magic.
325
+ */
326
+ type ToastPluginCallback = PluginCallback<Alpine$1>;
327
+ /** Backwards-compat alias for {@link CreateToastControllerOptions}. */
177
328
  interface CreateToastStoreOptions<TPositions extends readonly string[] = readonly []> {
178
329
  defaultPosition?: ToastPosition<TPositions>;
179
330
  /** Declared positions — each gets its own stack. */
@@ -184,6 +335,203 @@ interface CreateToastStoreOptions<TPositions extends readonly string[] = readonl
184
335
  /** Reactive store accessor — required for Alpine auto-dismiss timers. */
185
336
  getStore?: () => ToastStore<readonly [], TPositions, unknown>;
186
337
  }
338
+
339
+ /**
340
+ * Strongly-typed event map for the toast controller.
341
+ *
342
+ * Per the toolkit convention (see `@ailuracode/alpine-theme` and
343
+ * `@ailuracode/alpine-lang`), the event map is the small surface
344
+ * this module owns; the detail types live in `./types.ts` so the
345
+ * manager interface in that module can reference them without an
346
+ * `events.ts ↔ types.ts` import cycle.
347
+ *
348
+ * The controller emits a single `change` event after every state
349
+ * mutation (push, update, dismiss, dismissAt, dismissAll,
350
+ * pushUnique). The Alpine adapter subscribes to this one event and
351
+ * mirrors the `items` snapshot into the reactive store proxy.
352
+ *
353
+ * `source` discriminates the kind of transition so subscribers can
354
+ * branch on intent (e.g. animations might react differently to
355
+ * `push` vs `dismiss`).
356
+ *
357
+ * The event map is parameterized by `TPositions` and `TContent` so
358
+ * `BaseController.emit` infers the right `ToastChangeDetail` shape
359
+ * for each generic instantiation of the controller.
360
+ */
361
+
362
+ /**
363
+ * Event map consumed by `BaseController<ToastEvents>`. Single-key
364
+ * contract: every transition emits `change` with the same
365
+ * {@link ToastChangeDetail} payload.
366
+ */
367
+ interface ToastEvents<TPositions extends readonly string[] = readonly [], TContent = unknown> extends Record<string, unknown> {
368
+ change: ToastChangeDetail<readonly [], TPositions, TContent>;
369
+ }
370
+ /**
371
+ * Subscriber callback for the `change` event. Hardcoded to the
372
+ * listener signature `(detail: ToastChangeDetail) => void` rather
373
+ * than indexed via `ToastEvents['change']` because that indexer
374
+ * returns the *payload* type, not the *callback* type. Keeping it
375
+ * explicit avoids the silent payload-vs-callback swap.
376
+ */
377
+ type ToastListener<TPositions extends readonly string[] = readonly [], TContent = unknown> = (detail: ToastChangeDetail<readonly [], TPositions, TContent>) => void;
378
+
379
+ /**
380
+ * Toast controller — the framework-agnostic core of
381
+ * `@ailuracode/alpine-toast`. Owns every piece of toast queue
382
+ * state and is the single source of truth for the
383
+ * `items` array, the auto-dismiss timers, and the position /
384
+ * variant filtering logic.
385
+ *
386
+ * Responsibilities:
387
+ *
388
+ * 1. **State** — owns `items`, `defaultPosition`, `stackPositions`,
389
+ * `maxToasts`, `maxVisible`. Mutations always produce a fresh
390
+ * `items` array (immutable replacement) so Alpine's reactive
391
+ * proxy can observe the change.
392
+ * 2. **Timers** — schedules auto-dismiss timers per timed toast.
393
+ * Timers are tracked internally and cleared on `destroy()`
394
+ * via `registerCleanup()` so the BaseController lifecycle
395
+ * covers them.
396
+ * 3. **Queue limits** — enforces `maxToasts` per (position, stack)
397
+ * pair on every `push` / `update` (when position or duration
398
+ * flips between timed ↔ persistent).
399
+ * 4. **Subscriptions** — typed `on('change', listener)` from the
400
+ * inherited bus, with the toast-level detail shape (`source`
401
+ * discriminator + full `items` snapshot).
402
+ *
403
+ * Construction rules:
404
+ *
405
+ * - The constructor MUST NOT touch `window`, `document`, or timers.
406
+ * Browser-side wiring (the window `toast` event listener) lives
407
+ * in `mount()`.
408
+ * - The factory `createToastController()` auto-mounts so callers
409
+ * receive a fully-initialized instance.
410
+ * - `destroy()` MUST be idempotent and MUST clear every pending
411
+ * timer.
412
+ */
413
+
414
+ /**
415
+ * Public entrypoint — builds and mounts a fully-initialized
416
+ * {@link ToastController}. The constructor stays pure; the factory
417
+ * wires the browser-touching `mount()` step.
418
+ *
419
+ * Singleton guarantee: at most one live `ToastController` per
420
+ * document. Repeated calls return the existing instance; the
421
+ * controller's `destroy()` releases the slot so the next call
422
+ * builds a fresh one. Direct `new ToastController(...)` is still
423
+ * supported for tests and advanced consumers — only the
424
+ * `createToastController()` factory enforces uniqueness.
425
+ */
426
+ declare function createToastController<const TPositions extends readonly string[] = readonly [], TContent = unknown>(options?: CreateToastControllerOptions<TPositions, TContent>): ToastController<TPositions, TContent>;
427
+ /**
428
+ * Headless controller for `@ailuracode/alpine-toast`. Owns every
429
+ * piece of toast queue state. The Alpine integration in
430
+ * `plugin.ts` subscribes to the controller's `change` event and
431
+ * mirrors the snapshot into the reactive store so bindings
432
+ * re-render automatically.
433
+ *
434
+ * Standalone consumers (non-Alpine) can `createToastController()`
435
+ * directly and wire their own adapter via
436
+ * `manager.on("change", detail => ...)`.
437
+ */
438
+ declare class ToastController<const TPositions extends readonly string[] = readonly [], TContent = unknown> extends BaseController<ToastEvents<TPositions, TContent>> {
439
+ #private;
440
+ constructor(options: CreateToastControllerOptions<TPositions, TContent>);
441
+ /**
442
+ * Tears down every side effect. Idempotent. `super.destroy()` runs
443
+ * the registered cleanups (currently just the window listener)
444
+ * first; the timer cleanup runs as a final step. Also releases
445
+ * the singleton slot so the next `createToastController()` call
446
+ * builds a fresh controller.
447
+ */
448
+ destroy(): void;
449
+ /**
450
+ * Starts the controller's side effects. The constructor leaves
451
+ * `#items` empty; `mount()` registers the `toast` window event
452
+ * listener (when enabled) and emits the initialization event.
453
+ *
454
+ * Calling `mount()` more than once is a no-op — `BaseController`
455
+ * guards the phase. Calling it after `destroy()` throws.
456
+ */
457
+ mount(): void;
458
+ get defaultPosition(): ToastPosition<TPositions>;
459
+ get stackPositions(): readonly ToastPosition<TPositions>[];
460
+ get maxToasts(): number;
461
+ get maxVisible(): number;
462
+ get items(): ToastItem<readonly [], TPositions, TContent>[];
463
+ push(payload?: ToastPayload<readonly [], TPositions, TContent>): string;
464
+ pushUnique(key: string, payload?: ToastPayload<readonly [], TPositions, TContent>): string;
465
+ update(id: string, payload?: Partial<ToastPayload<readonly [], TPositions, TContent>>): void;
466
+ dismiss(id: string): void;
467
+ dismissAt(position: ToastPosition<TPositions>): void;
468
+ dismissAll(): void;
469
+ itemsAt(position: ToastPosition<TPositions>): ToastItem<readonly [], TPositions, TContent>[];
470
+ timedItemsAt(position: ToastPosition<TPositions>): ToastItem<readonly [], TPositions, TContent>[];
471
+ persistentItemsAt(position: ToastPosition<TPositions>): ToastItem<readonly [], TPositions, TContent>[];
472
+ activeTimedItemsAt(position: ToastPosition<TPositions>): ToastItem<readonly [], TPositions, TContent>[];
473
+ activePersistentItemsAt(position: ToastPosition<TPositions>): ToastItem<readonly [], TPositions, TContent>[];
474
+ isVisibleAt(position: ToastPosition<TPositions>, index: number): boolean;
475
+ /**
476
+ * Public escape hatch for callers (mainly the magic's `fromPayload`)
477
+ * that need to push a toast from a raw `ToastEventPayload` shape.
478
+ */
479
+ fromPayload(payload?: ToastPayload<readonly [], TPositions, TContent>): string;
480
+ }
481
+ /**
482
+ * Wraps a {@link ToastController} in the {@link ToastStore} surface.
483
+ * The store's reads delegate to the controller; mutations go
484
+ * through the controller's semantic commands.
485
+ *
486
+ * The wrapper subscribes to the controller's `change` event so its
487
+ * own `items` property stays in sync with the controller's queue —
488
+ * that subscription is what keeps standalone consumers (`store.items`
489
+ * reads in tests, scripts) up to date. Alpine consumers also benefit
490
+ * because the wrapper's `items` is a regular settable property,
491
+ * which means Alpine's reactive proxy can intercept assignments
492
+ * through its SET trap and trigger template re-renders.
493
+ *
494
+ * The Alpine adapter (`plugin.ts`) registers its own subscription
495
+ * that mirrors changes into the proxy via the SET trap — that is
496
+ * what triggers Alpine's reactivity. The wrapper's own subscription
497
+ * keeps `store.items` fresh in standalone use and provides a
498
+ * redundant but safe update path in Alpine use (Alpine's SET trap
499
+ * still fires because the proxy's cached value lags the target's
500
+ * direct mutation).
501
+ *
502
+ * `destroy()` unsubscribes the internal listener AND forwards to
503
+ * the controller's destroy so callers have one entry point.
504
+ *
505
+ * Used both by `toastPlugin` (to register with Alpine) and by the
506
+ * standalone {@link createToastStore} factory.
507
+ */
508
+ declare function wrapToastStore<const TPositions extends readonly string[] = readonly [], TContent = unknown>(controller: ToastController<TPositions, TContent>): ToastStore<readonly [], TPositions, TContent>;
509
+ /**
510
+ * Standalone factory — creates a fresh (non-singleton)
511
+ * {@link ToastController} and returns the {@link ToastStore}
512
+ * surface. Useful for tests, scripts, and non-Alpine consumers
513
+ * that need a one-off queue.
514
+ *
515
+ * Each call returns a NEW controller; for the document-level
516
+ * singleton pattern, use {@link createToastController} instead.
517
+ */
518
+ declare function createToastStore<const TPositions extends readonly string[] = readonly [], TContent = unknown>(options?: CreateToastControllerOptions<TPositions, TContent>): ToastStore<readonly [], TPositions, TContent>;
519
+ /**
520
+ * Timed duration for `$toast.promise` loading state.
521
+ * Stays in the timed stack; the timer is replaced when the promise
522
+ * settles. Exported from `./index.ts` so consumers can compare
523
+ * against the sentinel without importing the controller module.
524
+ */
525
+ declare const PROMISE_LOADING_DURATION = 3600000;
526
+ /** Canonical persistent value — `0` is normalized to `false`. */
527
+ declare function normalizeToastDuration(duration: ToastDuration): ToastDuration;
528
+ /** Resolves payload duration — `false` / `0` persist; `undefined` uses the default. */
529
+ declare function resolveToastDuration(duration: ToastDuration | undefined, defaultDuration: number): ToastDuration;
530
+ /** Whether the toast should schedule an auto-dismiss timer. */
531
+ declare function shouldAutoDismiss(duration: ToastDuration): duration is number;
532
+ /** Persistent toasts (`duration: false` / `0`) use a separate UI stack from timed toasts. */
533
+ declare function isPersistentDuration(duration: ToastDuration): boolean;
534
+ /** Resolves `maxToasts` / `maxVisible` with the standard clamp rule. */
187
535
  declare function resolveToastLimits(options?: {
188
536
  maxToasts?: number;
189
537
  maxVisible?: number;
@@ -193,33 +541,53 @@ declare function resolveToastLimits(options?: {
193
541
  };
194
542
  /** Unique stack keys: built-in default plus configured positions. */
195
543
  declare function resolveStackPositions<TPositions extends readonly string[]>(defaultPosition: ToastPosition<TPositions>, positions?: TPositions): readonly ToastPosition<TPositions>[];
196
- /** Canonical persistent value — `0` is normalized to `false`. */
197
- declare function normalizeToastDuration(duration: ToastDuration): ToastDuration;
198
- /** Resolves payload duration — `false` / `0` persist; `undefined` uses the default. */
199
- declare function resolveToastDuration(duration: ToastDuration | undefined, defaultDuration: number): ToastDuration;
200
- /** Whether the toast should schedule an auto-dismiss timer. */
201
- declare function shouldAutoDismiss(duration: ToastDuration): duration is number;
202
- /** Persistent toasts (`duration: false` / `0`) use a separate UI stack from timed toasts. */
203
- declare function isPersistentDuration(duration: ToastDuration): boolean;
544
+
204
545
  /**
205
- * Timed duration for `$toast.promise` loading state.
206
- * Stays in the timed stack; the timer is replaced when the promise settles.
546
+ * Alpine.js integration for `@ailuracode/alpine-toast`.
547
+ *
548
+ * Thin adapter that wires {@link ToastController} into `$store.toast`
549
+ * and the `$toast` magic. Every command forwards to the controller
550
+ * (see `AGENTS.md` for the integration contract).
207
551
  */
208
- declare const PROMISE_LOADING_DURATION = 3600000;
209
- /** Creates the internal reactive toast queue consumed by `$toast` and UI integrators. */
210
- declare function createToastStore<const TPositions extends readonly string[] = readonly [], TContent = unknown>(options?: CreateToastStoreOptions<TPositions>): ToastStore<readonly [], TPositions, TContent>;
211
552
 
212
- /** Alpine.js toast plugin. Registers magic `$toast` with an internal reactive queue. CSS-framework agnostic — no markup or styles. */
213
- declare function toastPlugin<const TVariants extends readonly string[] = readonly [], const TPositions extends readonly string[] = readonly [], TContent = unknown>(optionsOrAlpine?: ToastPluginOptions<TVariants, TPositions, TContent> | AlpineType.Alpine): undefined | ((Alpine: AlpineType.Alpine) => void);
214
- declare global {
215
- namespace Alpine {
216
- interface Stores {
217
- toast: ToastStore;
218
- }
219
- interface Magics<T> {
220
- $toast: ToastMagic;
221
- }
222
- }
223
- }
553
+ /** Variant names that cannot override core `$toast` methods. */
554
+ declare const RESERVED_TOAST_MAGIC_KEYS: Set<string>;
555
+ /** Resolves plugin options with defaults and queue limit rules. */
556
+ declare function resolveToastPluginConfig<const TVariants extends readonly string[] = readonly [], const TPositions extends readonly string[] = readonly []>(options?: ToastPluginOptions<TVariants, TPositions>): ResolvedToastPluginConfig<TVariants, TPositions>;
557
+ /** Builds typed toast plugin options with inferred variant and position literals. */
558
+ declare function toastOptions<const TVariants extends readonly string[] = readonly [], const TPositions extends readonly string[] = readonly [], TContent = unknown>(options: ToastPluginOptions<TVariants, TPositions, TContent>): ToastPluginOptions<TVariants, TPositions, TContent>;
559
+ /** Declares toast variant names with full literal inference. */
560
+ declare function toastVariants<const T extends readonly string[]>(variants: T): T;
561
+ /** Declares toast position names with full literal inference. */
562
+ declare function toastPositions<const T extends readonly string[]>(positions: T): T;
563
+ /**
564
+ * Plugin factory — returns the `Alpine.plugin()` callback. Pass
565
+ * {@link ToastPluginOptions} to configure {@link ToastController},
566
+ * or `{}` for the package defaults. See `AGENTS.md` for the
567
+ * integration contract.
568
+ */
569
+ declare function toastPlugin<const TVariants extends readonly string[] = readonly [], const TPositions extends readonly string[] = readonly [], TContent = unknown>(options?: ToastPluginOptions<TVariants, TPositions, TContent>): ToastPluginCallback;
570
+ /**
571
+ * Wraps a {@link ToastController} in the {@link ToastStore} surface
572
+ * that Alpine consumers (templates, `$store.toast.*` references)
573
+ * see. The store's reads delegate to the controller; mutations go
574
+ * through the controller's semantic commands.
575
+ *
576
+ * The store is intentionally a thin object literal — every field is
577
+ * a direct getter into the controller, and every method is a one-line
578
+ * delegation. Splitting helpers would add indirection without buying
579
+ * anything because the controller already exposes the entire surface.
580
+ *
581
+ * The implementation lives in `./controller.ts` (see
582
+ * {@link wrapToastStore}) so both `toastPlugin` and the standalone
583
+ * `createToastStore` factory can share it.
584
+ */
585
+ /**
586
+ * Builds the callable `$toast` magic API. The magic delegates every
587
+ * command to the store accessor passed in by the caller — typically
588
+ * `() => Alpine.store("toast")` so the magic stays reactive, but
589
+ * tests inject their own store.
590
+ */
591
+ declare function createToastMagic<const TVariants extends readonly string[], const TPositions extends readonly string[] = readonly [], TContent = unknown>(config: ResolvedToastPluginConfig<TVariants, TPositions>, getStore: () => ToastStore<TVariants, TPositions, TContent>): ToastMagic<TVariants, TPositions, TContent>;
224
592
 
225
- export { type DefaultToastPosition, type DefaultToastVariant, PROMISE_LOADING_DURATION, RESERVED_TOAST_MAGIC_KEYS, type ResolvedPromiseConfig, type ResolvedToastPluginConfig, TOAST_STORE_KEY, type ToastAction, type ToastDuration, type ToastEventPayload, type ToastItem, type ToastMagic, type ToastPayload, type ToastPayloadWithoutVariant, type ToastPluginOptions, type ToastPosition, type ToastPromiseInput, type ToastPromiseMessages, type ToastPromiseOptions, type ToastStore, type ToastStoreKey, type ToastVariant, type ToastVariantMethods, createToastMagic, createToastStore, toastPlugin as default, isPersistentDuration, normalizeToastDuration, resolveStackPositions, resolveToastDuration, resolveToastLimits, resolveToastPluginConfig, shouldAutoDismiss, toastOptions, toastPositions, toastVariants };
593
+ export { type CreateToastControllerOptions, type CreateToastStoreOptions, type DefaultToastPosition, type DefaultToastVariant, PROMISE_LOADING_DURATION, RESERVED_TOAST_MAGIC_KEYS, type ResolvedPromiseConfig, type ResolvedToastPluginConfig, TOAST_MAGIC_KEY, TOAST_STORE_KEY, type ToastAction, type ToastAlpine, type ToastChangeDetail, type ToastChangeSource, ToastController, type ToastDuration, type ToastEventPayload, type ToastEvents, type ToastItem, type ToastListener, type ToastMagic, type ToastMagicKey, type ToastManager, type ToastPayload, type ToastPayloadWithoutVariant, type ToastPluginCallback, type ToastPluginOptions, type ToastPosition, type ToastPromiseInput, type ToastPromiseMessages, type ToastPromiseOptions, type ToastStore, type ToastStoreKey, type ToastVariant, type ToastVariantMethods, createToastController, createToastMagic, createToastStore, toastPlugin as default, isPersistentDuration, normalizeToastDuration, resolveStackPositions, resolveToastDuration, resolveToastLimits, resolveToastPluginConfig, shouldAutoDismiss, toastOptions, toastPlugin, toastPositions, toastVariants, wrapToastStore };