@forgeroute/ui 0.4.69 → 0.4.70

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgeroute/ui",
3
- "version": "0.4.69",
3
+ "version": "0.4.70",
4
4
  "peerDependencies": {
5
5
  "@angular/common": ">=22.0.0",
6
6
  "@angular/core": ">=22.0.0",
@@ -115,7 +115,7 @@ export declare class TemplatePickerComponent {
115
115
  private readonly host;
116
116
  private readonly search$;
117
117
  /** Filter results to a specific channel: 'email', 'text', or omit for all. */
118
- readonly channel: import("@angular/core").InputSignal<"" | "text" | "email">;
118
+ readonly channel: import("@angular/core").InputSignal<"" | "email" | "text">;
119
119
  readonly selectedId: import("@angular/core").InputSignal<string | null>;
120
120
  readonly label: import("@angular/core").InputSignal<string>;
121
121
  /** Shows the red required asterisk (same as the library inputs) — e.g. when a template must be picked to send. */
@@ -543,7 +543,7 @@ export declare class DocumentSendOptionsComponent implements UiFieldValidity {
543
543
  /** API root from FORGEROUTE_CONFIG (e.g. a cross-origin prod API); falls back to same-origin `/api`. */
544
544
  private readonly apiBase;
545
545
  /** `email` → purpose select + attachment allowed; `text` → link only (purpose fixed to e-signature). */
546
- readonly channel: import("@angular/core").InputSignal<"text" | "email">;
546
+ readonly channel: import("@angular/core").InputSignal<"email" | "text">;
547
547
  readonly label: import("@angular/core").InputSignal<string>;
548
548
  /** When true, at least one document must be chosen. The message forms leave it false: documents are optional there. */
549
549
  readonly required: import("@angular/core").InputSignal<boolean>;
@@ -608,7 +608,7 @@ export declare class DocumentSendOptionsComponent implements UiFieldValidity {
608
608
  /** Roles of documents whose row had no `signerRoles` and that the host resolves (`signers().resolveRoles`). */
609
609
  readonly roleStates: import("@angular/core").WritableSignal<Record<string, RoleState>>;
610
610
  /** The envelope's documents: `loading` / `error` while the panel reads them (`loadDocuments`), `ready` once known. */
611
- readonly envelopeStatus: import("@angular/core").WritableSignal<"error" | "loading" | "ready" | "idle">;
611
+ readonly envelopeStatus: import("@angular/core").WritableSignal<"idle" | "loading" | "ready" | "error">;
612
612
  private envelopeSub;
613
613
  private readonly roleSubs;
614
614
  /** The sender opened the collapsed "Signing options" line. */
@@ -1997,7 +1997,7 @@ export declare class SendMessagePanelComponent {
1997
1997
  readonly activeContact: import("@angular/core").WritableSignal<MessageContact | null>;
1998
1998
  /** What the sender should know about the picked contact before sending (why a channel is missing, what to add). */
1999
1999
  readonly contactNotices: import("@angular/core").Signal<string[]>;
2000
- readonly channel: import("@angular/core").WritableSignal<"text" | "email">;
2000
+ readonly channel: import("@angular/core").WritableSignal<"email" | "text">;
2001
2001
  readonly valid: import("@angular/core").WritableSignal<boolean>;
2002
2002
  /** Bumped on every fresh open / new contact — re-creates the email and text forms so no draft carries over. */
2003
2003
  readonly formEpoch: import("@angular/core").WritableSignal<number>;
@@ -1300,7 +1300,7 @@ export declare class StripeConnectComponent {
1300
1300
  readonly navigateTab: import("@angular/core").InputSignal<((url: string) => void) | null>;
1301
1301
  protected readonly visible: import("@angular/core").Signal<boolean>;
1302
1302
  /** Which screen the card shows. */
1303
- protected readonly state: import("@angular/core").Signal<"complete" | "verifying" | "incomplete" | "none">;
1303
+ protected readonly state: import("@angular/core").Signal<"none" | "complete" | "verifying" | "incomplete">;
1304
1304
  /** What the persistent status region says: the current state, plus "Loading." while a request runs. Empty while nothing is shown. */
1305
1305
  protected readonly liveText: import("@angular/core").Signal<string>;
1306
1306
  /** The user pressed a button that started a request: when the screen then changes, focus moves to the new screen (the pressed button is gone). */
@@ -1,7 +1,7 @@
1
1
  import * as i0 from "@angular/core";
2
2
  import { EnvironmentProviders, InjectionToken, OnDestroy, OnInit, Signal, TemplateRef, WritableSignal } from "@angular/core";
3
3
  import { UrlTree } from "@angular/router";
4
- import { Observable } from "rxjs";
4
+ import { Observable, Subject } from "rxjs";
5
5
  import { AbstractControl, ControlValueAccessor, FormControl, ValidationErrors, Validator, ValidatorFn } from "@angular/forms";
6
6
  import { HttpInterceptorFn } from "@angular/common/http";
7
7
  import { SafeHtml } from "@angular/platform-browser";
@@ -2387,6 +2387,54 @@ export declare class ModalComponent implements OnInit, OnDestroy {
2387
2387
  }, never, ["[modal-header-end]", "*", "[modal-footer-left]", "[modal-footer-center]", "[modal-footer-right]"], true, never>;
2388
2388
  }
2389
2389
  export type ToastType = 'success' | 'error' | 'info';
2390
+ /** A button on a toast (e.g. "View Contact", "Call Back"). */
2391
+ export interface ToastAction {
2392
+ /** Identifies the button in `onAction` and in the `(action)` output; also the test id suffix (`toast-action-<id>`). */
2393
+ id: string;
2394
+ label: string;
2395
+ /** Look of the button. Default `secondary`. */
2396
+ variant?: 'primary' | 'secondary' | 'danger';
2397
+ disabled?: boolean;
2398
+ /** Keep the toast open after this button is used. Default `false`: using a button closes the toast. */
2399
+ keepOpen?: boolean;
2400
+ }
2401
+ /** What `(action)` / `ToastService.action$` emit when a toast button is used. */
2402
+ export interface ToastActionEvent {
2403
+ /** The `id` of the button. */
2404
+ id: string;
2405
+ /** The `key` of the toast it belongs to, when the toast had one. */
2406
+ key?: string;
2407
+ }
2408
+ /**
2409
+ * Per-message options for `show()` / `success()` / `info()` / `error()` / `notify()`. Every field is optional; a call without any of them is a plain
2410
+ * toast exactly as before.
2411
+ */
2412
+ export interface ToastOptions {
2413
+ /** Only `notify()` reads this (`show` / `success` / `info` / `error` fix their own type). Default `success`. */
2414
+ type?: ToastType;
2415
+ /** How long it stays, in ms. Default: 3000 (4000 for errors). */
2416
+ duration?: number;
2417
+ /** A bold first line above the message. */
2418
+ title?: string;
2419
+ /** Buttons under the message. */
2420
+ actions?: readonly ToastAction[];
2421
+ /** Show "Dismissing in Ns" and a shrinking bar for this toast. Default: the outlet's / app's `countdown` setting (off). */
2422
+ countdown?: boolean;
2423
+ /** When another toast is showing, wait for it to finish instead of replacing it. Default: the outlet's / app's `queue` setting (off). */
2424
+ queue?: boolean;
2425
+ /** Identifies the toast: while one with the same key is showing or waiting, another one with that key is not added again (e.g. one per call id). */
2426
+ key?: string;
2427
+ /** Called with the `id` of a button when it is used (before the toast closes). */
2428
+ onAction?: (actionId: string) => void;
2429
+ }
2430
+ /** What is known about the toast on screen beyond its message and type; `null` for a plain toast. */
2431
+ export interface ToastDetails {
2432
+ title?: string;
2433
+ actions: readonly ToastAction[];
2434
+ countdown: boolean;
2435
+ key?: string;
2436
+ onAction?: (actionId: string) => void;
2437
+ }
2390
2438
  export declare class ToastService implements OnDestroy {
2391
2439
  readonly message: import("@angular/core").WritableSignal<string | null>;
2392
2440
  readonly type: import("@angular/core").WritableSignal<ToastType>;
@@ -2402,18 +2450,42 @@ export declare class ToastService implements OnDestroy {
2402
2450
  * Set once per app with `provideForgerouteToast({ persistentLiveRegion: true })`, or per outlet with `<ui-toast [persistentLiveRegion]="true" />`.
2403
2451
  */
2404
2452
  readonly persistentLiveRegion: import("@angular/core").WritableSignal<boolean>;
2453
+ /** The title, buttons, countdown flag, key and callback of the toast on screen; `null` for a plain toast or none. */
2454
+ readonly details: import("@angular/core").WritableSignal<ToastDetails | null>;
2455
+ /** How many toasts are waiting behind the one on screen (queue mode). */
2456
+ readonly queuedCount: import("@angular/core").WritableSignal<number>;
2457
+ /** Default for `ToastOptions.queue`: new toasts wait for the one on screen instead of replacing it. Set with `provideForgerouteToast({ queue: true })` or `<ui-toast [queue]="true" />`. */
2458
+ readonly queueDefault: import("@angular/core").WritableSignal<boolean>;
2459
+ /** Default for `ToastOptions.countdown`. Set with `provideForgerouteToast({ countdown: true })` or `<ui-toast [countdown]="true" />`. */
2460
+ readonly countdownDefault: import("@angular/core").WritableSignal<boolean>;
2461
+ /** Most toasts that may wait; further ones are dropped. Default 20. Set with `provideForgerouteToast({ maxQueued })` or `<ui-toast [maxQueued]="n" />`. */
2462
+ readonly maxQueued: import("@angular/core").WritableSignal<number>;
2463
+ /** Time left of the toast on screen, in ms; only kept up to date for a toast with a countdown. */
2464
+ readonly remainingMs: import("@angular/core").WritableSignal<number>;
2465
+ /** The full time the toast on screen was given, in ms (the denominator of the countdown bar). */
2466
+ readonly totalMs: import("@angular/core").WritableSignal<number>;
2467
+ /** Emits when a toast button is used. */
2468
+ readonly action$: Subject<ToastActionEvent>;
2405
2469
  private _timer;
2470
+ private _ticker;
2471
+ private _advanceTimer;
2406
2472
  private _deadline;
2407
2473
  private _remaining;
2408
2474
  private _paused;
2409
- show(msg: string, duration?: number): void;
2475
+ private _queue;
2476
+ /** Green success toast. `durationOrOptions` is the time in ms (default 3000) or a {@link ToastOptions} object. */
2477
+ show(msg: string, durationOrOptions?: number | ToastOptions): void;
2410
2478
  /** Green success toast, the explicit name for `show()` (same type, same 3000ms default, same behaviour). */
2411
- success(msg: string, duration?: number): void;
2479
+ success(msg: string, durationOrOptions?: number | ToastOptions): void;
2412
2480
  /** Neutral (blue) toast for a result that is neither a success nor a failure, e.g. "No changes to save.". */
2413
- info(msg: string, duration?: number): void;
2414
- error(msg: string, duration?: number): void;
2415
- /** Removes the current toast now (close button / Escape). Safe when nothing is showing. */
2481
+ info(msg: string, durationOrOptions?: number | ToastOptions): void;
2482
+ error(msg: string, durationOrOptions?: number | ToastOptions): void;
2483
+ /** A toast whose type comes from `options.type` (default `success`); the same as the named methods otherwise. */
2484
+ notify(msg: string, options?: ToastOptions): void;
2485
+ /** Removes the current toast now (close button / Escape); the next waiting one, if any, follows. Safe when nothing is showing. */
2416
2486
  dismiss(): void;
2487
+ /** Uses the button `id` of the toast on screen: calls its `onAction`, emits `action$`, and closes the toast unless the button has `keepOpen`. No-op for an unknown or disabled button. */
2488
+ runAction(id: string): void;
2417
2489
  /** Holds the countdown while the pointer or keyboard focus is on the toast (WCAG 2.2.1). No-op when nothing is counting down. */
2418
2490
  pause(): void;
2419
2491
  /** Continues after `pause()`; the toast gets at least 1000ms more so it can be read. No-op when not paused. */
@@ -2421,8 +2493,14 @@ export declare class ToastService implements OnDestroy {
2421
2493
  /** The root injector is destroyed (app teardown, TestBed reset): no timer may outlive it. */
2422
2494
  ngOnDestroy(): void;
2423
2495
  private _clearTimer;
2496
+ private _clearTicker;
2497
+ private _clearAdvance;
2498
+ /** Starts the expiry timer (and the countdown ticker for a toast with a countdown). `fresh` = a new toast, not a resume after a pause. */
2424
2499
  private _start;
2425
- private _display;
2500
+ /** The toast on screen is over (expired, dismissed or its button used): clear it and bring in the next waiting one after a short gap. */
2501
+ private _finish;
2502
+ private _enter;
2503
+ private _present;
2426
2504
  static ɵfac: i0.ɵɵFactoryDeclaration<ToastService, never>;
2427
2505
  static ɵprov: i0.ɵɵInjectableDeclaration<any>;
2428
2506
  }
@@ -2448,6 +2526,28 @@ export declare class ToastComponent {
2448
2526
  */
2449
2527
  readonly persistentLiveRegion: import("@angular/core").InputSignal<boolean | null>;
2450
2528
  protected readonly persistent: import("@angular/core").Signal<boolean>;
2529
+ /**
2530
+ * Outlet-wide defaults for the optional parts of a toast (a message's own options win). `null` (default) leaves the app / service setting alone
2531
+ * (`provideForgerouteToast`, itself off); a value is applied while this is the live outlet.
2532
+ *
2533
+ * - `queue`: a toast that arrives while another is showing waits for it instead of replacing it.
2534
+ * - `countdown`: show "Dismissing in Ns" and a shrinking bar on every toast.
2535
+ * - `maxQueued`: how many may wait (default 20).
2536
+ */
2537
+ readonly queue: import("@angular/core").InputSignal<boolean | null>;
2538
+ readonly countdown: import("@angular/core").InputSignal<boolean | null>;
2539
+ readonly maxQueued: import("@angular/core").InputSignal<number | null>;
2540
+ /** Wording of the countdown line; `{n}` is the seconds left. */
2541
+ readonly countdownLabel: import("@angular/core").InputSignal<string>;
2542
+ /** Wording of the chip that says how many toasts are waiting; `{n}` is the count. */
2543
+ readonly queueLabel: import("@angular/core").InputSignal<string>;
2544
+ /** A toast button was used (also after its own `onAction`). */
2545
+ readonly action: import("@angular/core").OutputEmitterRef<ToastActionEvent>;
2546
+ protected readonly isRich: import("@angular/core").Signal<boolean>;
2547
+ protected readonly countdownPct: import("@angular/core").Signal<number>;
2548
+ protected readonly countdownText: import("@angular/core").Signal<string>;
2549
+ protected readonly queueText: import("@angular/core").Signal<string>;
2550
+ protected onAction(id: string): void;
2451
2551
  /**
2452
2552
  * Message that was already on screen when this instance took over from a destroyed host. While it is
2453
2553
  * unchanged the toast renders without the entry animation and without live-region roles, so the
@@ -2478,7 +2578,34 @@ export declare class ToastComponent {
2478
2578
  "required": false;
2479
2579
  "isSignal": true;
2480
2580
  };
2481
- }, {}, never, never, true, never>;
2581
+ "queue": {
2582
+ "alias": "queue";
2583
+ "required": false;
2584
+ "isSignal": true;
2585
+ };
2586
+ "countdown": {
2587
+ "alias": "countdown";
2588
+ "required": false;
2589
+ "isSignal": true;
2590
+ };
2591
+ "maxQueued": {
2592
+ "alias": "maxQueued";
2593
+ "required": false;
2594
+ "isSignal": true;
2595
+ };
2596
+ "countdownLabel": {
2597
+ "alias": "countdownLabel";
2598
+ "required": false;
2599
+ "isSignal": true;
2600
+ };
2601
+ "queueLabel": {
2602
+ "alias": "queueLabel";
2603
+ "required": false;
2604
+ "isSignal": true;
2605
+ };
2606
+ }, {
2607
+ "action": "action";
2608
+ }, never, never, true, never>;
2482
2609
  }
2483
2610
  export type ProgressBarVariant = 'blue' | 'green' | 'amber' | 'red' | 'slate';
2484
2611
  /**
@@ -7344,6 +7471,7 @@ export declare class NotesComponent {
7344
7471
  * providers: [provideForgerouteToast()]
7345
7472
  * providers: [provideForgerouteToast({ dismissible: true })] // every toast also gets a close button (default: none)
7346
7473
  * providers: [provideForgerouteToast({ persistentLiveRegion: true })] // always-present live regions: reliable announcements in VoiceOver / Safari
7474
+ * providers: [provideForgerouteToast({ queue: true, countdown: true, maxQueued: 10 })] // toasts wait for each other and show a countdown (defaults; a message's own options win)
7347
7475
  *
7348
7476
  * It is created first, so it is the registry's host and any other `<ui-toast>` (a table's own, a shell's) stays silent: each
7349
7477
  * message renders and is announced once. Nothing happens on the server. The outlet is destroyed with the app.
@@ -7351,6 +7479,9 @@ export declare class NotesComponent {
7351
7479
  export declare function provideForgerouteToast(options?: {
7352
7480
  dismissible?: boolean;
7353
7481
  persistentLiveRegion?: boolean;
7482
+ queue?: boolean;
7483
+ countdown?: boolean;
7484
+ maxQueued?: number;
7354
7485
  }): EnvironmentProviders;
7355
7486
  /** Payload of `(reorder)`. Apply it with `reorderItems(items, order)` or take the ready-made `items`. */
7356
7487
  export interface ListReorderEvent<T = unknown> {