@forgeroute/ui 0.4.69 → 0.4.71
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/fesm2022/forgeroute-ui-pdf.mjs +2 -0
- package/fesm2022/forgeroute-ui-pdf.mjs.map +1 -1
- package/fesm2022/forgeroute-ui-stripe.mjs +1 -0
- package/fesm2022/forgeroute-ui-stripe.mjs.map +1 -1
- package/fesm2022/forgeroute-ui.mjs +691 -53
- package/fesm2022/forgeroute-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/src/_animations.scss +7 -4
- package/types/forgeroute-ui-messaging.d.ts +4 -4
- package/types/forgeroute-ui-stripe.d.ts +1 -1
- package/types/forgeroute-ui.d.ts +268 -9
package/package.json
CHANGED
package/src/_animations.scss
CHANGED
|
@@ -7,8 +7,11 @@
|
|
|
7
7
|
to { opacity: 1; }
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
// Entrance of the table header and rows: slides up only, it never fades. The header holds the tabs, search and buttons and the rows hold the
|
|
11
|
+
// cell text, so while they fade in (opacity 0 to 1) an accessibility audit run right after render measures half-transparent text and reports a
|
|
12
|
+
// colour-contrast failure that is gone 300ms later. Moving without changing opacity keeps every pixel of text at full contrast at all times.
|
|
13
|
+
@keyframes slideUp {
|
|
14
|
+
from { transform: translateY(6px); }
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
@keyframes dotPulse {
|
|
@@ -25,13 +28,13 @@
|
|
|
25
28
|
// Applied automatically by ui-data-table (rows and cards).
|
|
26
29
|
// The stagger is capped at 8 steps (240ms) so a 50-row page never starts its last row ~1.5s late.
|
|
27
30
|
.alive-row {
|
|
28
|
-
animation:
|
|
31
|
+
animation: slideUp .3s ease backwards;
|
|
29
32
|
animation-delay: calc(min(var(--i, 0), 8) * 30ms);
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
// ── Page/toolbar header ──
|
|
33
36
|
.alive-header {
|
|
34
|
-
animation:
|
|
37
|
+
animation: slideUp .3s ease both;
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
// ── Detail page cards ──
|
|
@@ -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<"" | "
|
|
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<"
|
|
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<"
|
|
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<"
|
|
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<"
|
|
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). */
|
package/types/forgeroute-ui.d.ts
CHANGED
|
@@ -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";
|
|
@@ -1801,6 +1801,10 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
|
|
|
1801
1801
|
/** State for the built-in single-row delete confirmation modal. */
|
|
1802
1802
|
protected readonly _rowDeleteTarget: import("@angular/core").WritableSignal<T | null>;
|
|
1803
1803
|
protected readonly _rowDeleting: import("@angular/core").WritableSignal<boolean>;
|
|
1804
|
+
/** Ids the built-in delete confirm dialog is described by (aria-describedby): its message and the "what will happen" list. */
|
|
1805
|
+
private readonly _confirmUid;
|
|
1806
|
+
protected readonly _confirmMsgId: string;
|
|
1807
|
+
protected readonly _confirmDetailsId: string;
|
|
1804
1808
|
protected readonly _rowDeleteConfig: import("@angular/core").WritableSignal<{
|
|
1805
1809
|
title: string;
|
|
1806
1810
|
message: string;
|
|
@@ -2261,6 +2265,12 @@ export declare class ModalComponent implements OnInit, OnDestroy {
|
|
|
2261
2265
|
readonly open: import("@angular/core").InputSignal<boolean>;
|
|
2262
2266
|
readonly title: import("@angular/core").InputSignal<string>;
|
|
2263
2267
|
readonly description: import("@angular/core").InputSignal<string>;
|
|
2268
|
+
/**
|
|
2269
|
+
* Id(s) of the element(s) inside the dialog that describe it (space-separated, as `aria-describedby` takes them), e.g. the confirm message
|
|
2270
|
+
* paragraph. Screen readers read them after the title when the dialog opens. When it is not set and `description` is, the dialog is described
|
|
2271
|
+
* by that description line; with neither, no `aria-describedby` is rendered (the body of a form dialog is not a description).
|
|
2272
|
+
*/
|
|
2273
|
+
readonly describedBy: import("@angular/core").InputSignal<string | null>;
|
|
2264
2274
|
readonly maxWidth: import("@angular/core").InputSignal<string>;
|
|
2265
2275
|
readonly bodyOverflow: import("@angular/core").InputSignal<"hidden" | "auto" | "visible">;
|
|
2266
2276
|
/** `data-testid` of the dialog element itself (the host `<ui-modal>` is always in the page, the dialog only while open). None when empty. */
|
|
@@ -2295,6 +2305,8 @@ export declare class ModalComponent implements OnInit, OnDestroy {
|
|
|
2295
2305
|
readonly returnFocusTo: import("@angular/core").InputSignal<HTMLElement | null>;
|
|
2296
2306
|
protected readonly kiosk: import("@angular/core").Signal<boolean>;
|
|
2297
2307
|
protected readonly titleId: string;
|
|
2308
|
+
protected readonly descId: string;
|
|
2309
|
+
protected readonly describedById: import("@angular/core").Signal<string | null>;
|
|
2298
2310
|
private readonly el;
|
|
2299
2311
|
private readonly ren;
|
|
2300
2312
|
private readonly doc;
|
|
@@ -2332,6 +2344,11 @@ export declare class ModalComponent implements OnInit, OnDestroy {
|
|
|
2332
2344
|
"required": false;
|
|
2333
2345
|
"isSignal": true;
|
|
2334
2346
|
};
|
|
2347
|
+
"describedBy": {
|
|
2348
|
+
"alias": "describedBy";
|
|
2349
|
+
"required": false;
|
|
2350
|
+
"isSignal": true;
|
|
2351
|
+
};
|
|
2335
2352
|
"maxWidth": {
|
|
2336
2353
|
"alias": "maxWidth";
|
|
2337
2354
|
"required": false;
|
|
@@ -2387,6 +2404,54 @@ export declare class ModalComponent implements OnInit, OnDestroy {
|
|
|
2387
2404
|
}, never, ["[modal-header-end]", "*", "[modal-footer-left]", "[modal-footer-center]", "[modal-footer-right]"], true, never>;
|
|
2388
2405
|
}
|
|
2389
2406
|
export type ToastType = 'success' | 'error' | 'info';
|
|
2407
|
+
/** A button on a toast (e.g. "View Contact", "Call Back"). */
|
|
2408
|
+
export interface ToastAction {
|
|
2409
|
+
/** Identifies the button in `onAction` and in the `(action)` output; also the test id suffix (`toast-action-<id>`). */
|
|
2410
|
+
id: string;
|
|
2411
|
+
label: string;
|
|
2412
|
+
/** Look of the button. Default `secondary`. */
|
|
2413
|
+
variant?: 'primary' | 'secondary' | 'danger';
|
|
2414
|
+
disabled?: boolean;
|
|
2415
|
+
/** Keep the toast open after this button is used. Default `false`: using a button closes the toast. */
|
|
2416
|
+
keepOpen?: boolean;
|
|
2417
|
+
}
|
|
2418
|
+
/** What `(action)` / `ToastService.action$` emit when a toast button is used. */
|
|
2419
|
+
export interface ToastActionEvent {
|
|
2420
|
+
/** The `id` of the button. */
|
|
2421
|
+
id: string;
|
|
2422
|
+
/** The `key` of the toast it belongs to, when the toast had one. */
|
|
2423
|
+
key?: string;
|
|
2424
|
+
}
|
|
2425
|
+
/**
|
|
2426
|
+
* Per-message options for `show()` / `success()` / `info()` / `error()` / `notify()`. Every field is optional; a call without any of them is a plain
|
|
2427
|
+
* toast exactly as before.
|
|
2428
|
+
*/
|
|
2429
|
+
export interface ToastOptions {
|
|
2430
|
+
/** Only `notify()` reads this (`show` / `success` / `info` / `error` fix their own type). Default `success`. */
|
|
2431
|
+
type?: ToastType;
|
|
2432
|
+
/** How long it stays, in ms. Default: 3000 (4000 for errors). */
|
|
2433
|
+
duration?: number;
|
|
2434
|
+
/** A bold first line above the message. */
|
|
2435
|
+
title?: string;
|
|
2436
|
+
/** Buttons under the message. */
|
|
2437
|
+
actions?: readonly ToastAction[];
|
|
2438
|
+
/** Show "Dismissing in Ns" and a shrinking bar for this toast. Default: the outlet's / app's `countdown` setting (off). */
|
|
2439
|
+
countdown?: boolean;
|
|
2440
|
+
/** When another toast is showing, wait for it to finish instead of replacing it. Default: the outlet's / app's `queue` setting (off). */
|
|
2441
|
+
queue?: boolean;
|
|
2442
|
+
/** 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). */
|
|
2443
|
+
key?: string;
|
|
2444
|
+
/** Called with the `id` of a button when it is used (before the toast closes). */
|
|
2445
|
+
onAction?: (actionId: string) => void;
|
|
2446
|
+
}
|
|
2447
|
+
/** What is known about the toast on screen beyond its message and type; `null` for a plain toast. */
|
|
2448
|
+
export interface ToastDetails {
|
|
2449
|
+
title?: string;
|
|
2450
|
+
actions: readonly ToastAction[];
|
|
2451
|
+
countdown: boolean;
|
|
2452
|
+
key?: string;
|
|
2453
|
+
onAction?: (actionId: string) => void;
|
|
2454
|
+
}
|
|
2390
2455
|
export declare class ToastService implements OnDestroy {
|
|
2391
2456
|
readonly message: import("@angular/core").WritableSignal<string | null>;
|
|
2392
2457
|
readonly type: import("@angular/core").WritableSignal<ToastType>;
|
|
@@ -2402,18 +2467,42 @@ export declare class ToastService implements OnDestroy {
|
|
|
2402
2467
|
* Set once per app with `provideForgerouteToast({ persistentLiveRegion: true })`, or per outlet with `<ui-toast [persistentLiveRegion]="true" />`.
|
|
2403
2468
|
*/
|
|
2404
2469
|
readonly persistentLiveRegion: import("@angular/core").WritableSignal<boolean>;
|
|
2470
|
+
/** The title, buttons, countdown flag, key and callback of the toast on screen; `null` for a plain toast or none. */
|
|
2471
|
+
readonly details: import("@angular/core").WritableSignal<ToastDetails | null>;
|
|
2472
|
+
/** How many toasts are waiting behind the one on screen (queue mode). */
|
|
2473
|
+
readonly queuedCount: import("@angular/core").WritableSignal<number>;
|
|
2474
|
+
/** 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" />`. */
|
|
2475
|
+
readonly queueDefault: import("@angular/core").WritableSignal<boolean>;
|
|
2476
|
+
/** Default for `ToastOptions.countdown`. Set with `provideForgerouteToast({ countdown: true })` or `<ui-toast [countdown]="true" />`. */
|
|
2477
|
+
readonly countdownDefault: import("@angular/core").WritableSignal<boolean>;
|
|
2478
|
+
/** Most toasts that may wait; further ones are dropped. Default 20. Set with `provideForgerouteToast({ maxQueued })` or `<ui-toast [maxQueued]="n" />`. */
|
|
2479
|
+
readonly maxQueued: import("@angular/core").WritableSignal<number>;
|
|
2480
|
+
/** Time left of the toast on screen, in ms; only kept up to date for a toast with a countdown. */
|
|
2481
|
+
readonly remainingMs: import("@angular/core").WritableSignal<number>;
|
|
2482
|
+
/** The full time the toast on screen was given, in ms (the denominator of the countdown bar). */
|
|
2483
|
+
readonly totalMs: import("@angular/core").WritableSignal<number>;
|
|
2484
|
+
/** Emits when a toast button is used. */
|
|
2485
|
+
readonly action$: Subject<ToastActionEvent>;
|
|
2405
2486
|
private _timer;
|
|
2487
|
+
private _ticker;
|
|
2488
|
+
private _advanceTimer;
|
|
2406
2489
|
private _deadline;
|
|
2407
2490
|
private _remaining;
|
|
2408
2491
|
private _paused;
|
|
2409
|
-
|
|
2492
|
+
private _queue;
|
|
2493
|
+
/** Green success toast. `durationOrOptions` is the time in ms (default 3000) or a {@link ToastOptions} object. */
|
|
2494
|
+
show(msg: string, durationOrOptions?: number | ToastOptions): void;
|
|
2410
2495
|
/** Green success toast, the explicit name for `show()` (same type, same 3000ms default, same behaviour). */
|
|
2411
|
-
success(msg: string,
|
|
2496
|
+
success(msg: string, durationOrOptions?: number | ToastOptions): void;
|
|
2412
2497
|
/** Neutral (blue) toast for a result that is neither a success nor a failure, e.g. "No changes to save.". */
|
|
2413
|
-
info(msg: string,
|
|
2414
|
-
error(msg: string,
|
|
2415
|
-
/**
|
|
2498
|
+
info(msg: string, durationOrOptions?: number | ToastOptions): void;
|
|
2499
|
+
error(msg: string, durationOrOptions?: number | ToastOptions): void;
|
|
2500
|
+
/** A toast whose type comes from `options.type` (default `success`); the same as the named methods otherwise. */
|
|
2501
|
+
notify(msg: string, options?: ToastOptions): void;
|
|
2502
|
+
/** Removes the current toast now (close button / Escape); the next waiting one, if any, follows. Safe when nothing is showing. */
|
|
2416
2503
|
dismiss(): void;
|
|
2504
|
+
/** 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. */
|
|
2505
|
+
runAction(id: string): void;
|
|
2417
2506
|
/** 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
2507
|
pause(): void;
|
|
2419
2508
|
/** Continues after `pause()`; the toast gets at least 1000ms more so it can be read. No-op when not paused. */
|
|
@@ -2421,8 +2510,14 @@ export declare class ToastService implements OnDestroy {
|
|
|
2421
2510
|
/** The root injector is destroyed (app teardown, TestBed reset): no timer may outlive it. */
|
|
2422
2511
|
ngOnDestroy(): void;
|
|
2423
2512
|
private _clearTimer;
|
|
2513
|
+
private _clearTicker;
|
|
2514
|
+
private _clearAdvance;
|
|
2515
|
+
/** 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
2516
|
private _start;
|
|
2425
|
-
|
|
2517
|
+
/** 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. */
|
|
2518
|
+
private _finish;
|
|
2519
|
+
private _enter;
|
|
2520
|
+
private _present;
|
|
2426
2521
|
static ɵfac: i0.ɵɵFactoryDeclaration<ToastService, never>;
|
|
2427
2522
|
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
2428
2523
|
}
|
|
@@ -2448,6 +2543,28 @@ export declare class ToastComponent {
|
|
|
2448
2543
|
*/
|
|
2449
2544
|
readonly persistentLiveRegion: import("@angular/core").InputSignal<boolean | null>;
|
|
2450
2545
|
protected readonly persistent: import("@angular/core").Signal<boolean>;
|
|
2546
|
+
/**
|
|
2547
|
+
* Outlet-wide defaults for the optional parts of a toast (a message's own options win). `null` (default) leaves the app / service setting alone
|
|
2548
|
+
* (`provideForgerouteToast`, itself off); a value is applied while this is the live outlet.
|
|
2549
|
+
*
|
|
2550
|
+
* - `queue`: a toast that arrives while another is showing waits for it instead of replacing it.
|
|
2551
|
+
* - `countdown`: show "Dismissing in Ns" and a shrinking bar on every toast.
|
|
2552
|
+
* - `maxQueued`: how many may wait (default 20).
|
|
2553
|
+
*/
|
|
2554
|
+
readonly queue: import("@angular/core").InputSignal<boolean | null>;
|
|
2555
|
+
readonly countdown: import("@angular/core").InputSignal<boolean | null>;
|
|
2556
|
+
readonly maxQueued: import("@angular/core").InputSignal<number | null>;
|
|
2557
|
+
/** Wording of the countdown line; `{n}` is the seconds left. */
|
|
2558
|
+
readonly countdownLabel: import("@angular/core").InputSignal<string>;
|
|
2559
|
+
/** Wording of the chip that says how many toasts are waiting; `{n}` is the count. */
|
|
2560
|
+
readonly queueLabel: import("@angular/core").InputSignal<string>;
|
|
2561
|
+
/** A toast button was used (also after its own `onAction`). */
|
|
2562
|
+
readonly action: import("@angular/core").OutputEmitterRef<ToastActionEvent>;
|
|
2563
|
+
protected readonly isRich: import("@angular/core").Signal<boolean>;
|
|
2564
|
+
protected readonly countdownPct: import("@angular/core").Signal<number>;
|
|
2565
|
+
protected readonly countdownText: import("@angular/core").Signal<string>;
|
|
2566
|
+
protected readonly queueText: import("@angular/core").Signal<string>;
|
|
2567
|
+
protected onAction(id: string): void;
|
|
2451
2568
|
/**
|
|
2452
2569
|
* Message that was already on screen when this instance took over from a destroyed host. While it is
|
|
2453
2570
|
* unchanged the toast renders without the entry animation and without live-region roles, so the
|
|
@@ -2478,7 +2595,34 @@ export declare class ToastComponent {
|
|
|
2478
2595
|
"required": false;
|
|
2479
2596
|
"isSignal": true;
|
|
2480
2597
|
};
|
|
2481
|
-
|
|
2598
|
+
"queue": {
|
|
2599
|
+
"alias": "queue";
|
|
2600
|
+
"required": false;
|
|
2601
|
+
"isSignal": true;
|
|
2602
|
+
};
|
|
2603
|
+
"countdown": {
|
|
2604
|
+
"alias": "countdown";
|
|
2605
|
+
"required": false;
|
|
2606
|
+
"isSignal": true;
|
|
2607
|
+
};
|
|
2608
|
+
"maxQueued": {
|
|
2609
|
+
"alias": "maxQueued";
|
|
2610
|
+
"required": false;
|
|
2611
|
+
"isSignal": true;
|
|
2612
|
+
};
|
|
2613
|
+
"countdownLabel": {
|
|
2614
|
+
"alias": "countdownLabel";
|
|
2615
|
+
"required": false;
|
|
2616
|
+
"isSignal": true;
|
|
2617
|
+
};
|
|
2618
|
+
"queueLabel": {
|
|
2619
|
+
"alias": "queueLabel";
|
|
2620
|
+
"required": false;
|
|
2621
|
+
"isSignal": true;
|
|
2622
|
+
};
|
|
2623
|
+
}, {
|
|
2624
|
+
"action": "action";
|
|
2625
|
+
}, never, never, true, never>;
|
|
2482
2626
|
}
|
|
2483
2627
|
export type ProgressBarVariant = 'blue' | 'green' | 'amber' | 'red' | 'slate';
|
|
2484
2628
|
/**
|
|
@@ -4816,6 +4960,11 @@ export declare class ConfirmService {
|
|
|
4816
4960
|
export declare class ConfirmOutletComponent implements OnInit, OnDestroy {
|
|
4817
4961
|
protected readonly svc: ConfirmService;
|
|
4818
4962
|
protected readonly _isPrimary: import("@angular/core").Signal<boolean>;
|
|
4963
|
+
/** Unique per outlet: the dialog is described by the message and, when there is one, the "what will happen" list (aria-describedby). */
|
|
4964
|
+
private readonly _uid;
|
|
4965
|
+
protected readonly msgId: string;
|
|
4966
|
+
protected readonly detailsId: string;
|
|
4967
|
+
protected readonly _describedBy: import("@angular/core").Signal<string>;
|
|
4819
4968
|
ngOnInit(): void;
|
|
4820
4969
|
ngOnDestroy(): void;
|
|
4821
4970
|
static ɵfac: i0.ɵɵFactoryDeclaration<ConfirmOutletComponent, never>;
|
|
@@ -7344,6 +7493,7 @@ export declare class NotesComponent {
|
|
|
7344
7493
|
* providers: [provideForgerouteToast()]
|
|
7345
7494
|
* providers: [provideForgerouteToast({ dismissible: true })] // every toast also gets a close button (default: none)
|
|
7346
7495
|
* providers: [provideForgerouteToast({ persistentLiveRegion: true })] // always-present live regions: reliable announcements in VoiceOver / Safari
|
|
7496
|
+
* 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
7497
|
*
|
|
7348
7498
|
* 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
7499
|
* message renders and is announced once. Nothing happens on the server. The outlet is destroyed with the app.
|
|
@@ -7351,6 +7501,9 @@ export declare class NotesComponent {
|
|
|
7351
7501
|
export declare function provideForgerouteToast(options?: {
|
|
7352
7502
|
dismissible?: boolean;
|
|
7353
7503
|
persistentLiveRegion?: boolean;
|
|
7504
|
+
queue?: boolean;
|
|
7505
|
+
countdown?: boolean;
|
|
7506
|
+
maxQueued?: number;
|
|
7354
7507
|
}): EnvironmentProviders;
|
|
7355
7508
|
/** Payload of `(reorder)`. Apply it with `reorderItems(items, order)` or take the ready-made `items`. */
|
|
7356
7509
|
export interface ListReorderEvent<T = unknown> {
|
|
@@ -13562,6 +13715,30 @@ export interface ConversationMessage {
|
|
|
13562
13715
|
sender?: string | null;
|
|
13563
13716
|
/** A link-style button under the text, e.g. "View transaction"; clicking it emits `(messageAction)` with this message. */
|
|
13564
13717
|
action?: ConversationMessageAction | null;
|
|
13718
|
+
/** A record the message points at (a job, an estimate…), shown as a chip under the text; a chip with a `url` is a link. */
|
|
13719
|
+
link?: ConversationLink | null;
|
|
13720
|
+
}
|
|
13721
|
+
/** A record linked to a message (see `ConversationMessage.link`, `[(link)]` and `ConversationSendEvent.link`). */
|
|
13722
|
+
export interface ConversationLink {
|
|
13723
|
+
/** What kind of record it is (`JOB`, `ESTIMATE`…): the host's own code, handed back unchanged. */
|
|
13724
|
+
type: string;
|
|
13725
|
+
/** The record's id. */
|
|
13726
|
+
id: string;
|
|
13727
|
+
/** What the chip says, e.g. "Johnson Roof — Alice". */
|
|
13728
|
+
label: string;
|
|
13729
|
+
/** Where the chip goes when it is clicked; none = a plain chip. Only used on messages, not in the composer. */
|
|
13730
|
+
url?: string | null;
|
|
13731
|
+
}
|
|
13732
|
+
/** One section of the "Link a record" picker: the records of one kind. */
|
|
13733
|
+
export interface ConversationLinkGroup {
|
|
13734
|
+
/** The kind, copied to `ConversationLink.type` of every pick from this section. */
|
|
13735
|
+
type: string;
|
|
13736
|
+
/** The section heading, e.g. "Jobs". */
|
|
13737
|
+
label: string;
|
|
13738
|
+
items: ReadonlyArray<{
|
|
13739
|
+
id: string;
|
|
13740
|
+
label: string;
|
|
13741
|
+
}>;
|
|
13565
13742
|
}
|
|
13566
13743
|
/** The button a message can carry (see `ConversationMessage.action`). */
|
|
13567
13744
|
export interface ConversationMessageAction {
|
|
@@ -13579,6 +13756,8 @@ export interface ConversationSendEvent {
|
|
|
13579
13756
|
text: string;
|
|
13580
13757
|
/** Only with `[richText]="true"`: the formatted message as sanitised HTML (bold, italic, underline, links, lists). */
|
|
13581
13758
|
html?: string;
|
|
13759
|
+
/** Only when a record is linked (`[(link)]`): the chosen record. The key is absent otherwise. */
|
|
13760
|
+
link?: ConversationLink;
|
|
13582
13761
|
}
|
|
13583
13762
|
/** A message with the date separator that goes above it ('' when it shares the day of the previous message). */
|
|
13584
13763
|
export interface ConversationMessageRow {
|
|
@@ -13790,6 +13969,24 @@ export declare class ConversationsComponent {
|
|
|
13790
13969
|
/** Files accepted by the attach picker (type and size already checked against `acceptedFiles` / `maxFileSize`). */
|
|
13791
13970
|
readonly filesSelected: import("@angular/core").OutputEmitterRef<File[]>;
|
|
13792
13971
|
readonly attachmentRemove: import("@angular/core").OutputEmitterRef<void>;
|
|
13972
|
+
/**
|
|
13973
|
+
* Link a record to a message (opt-in): `null` (default) = no link button, no picker, nothing changes. A list (even an empty one) turns on a "Link a record"
|
|
13974
|
+
* button in the composer that opens a searchable picker of these sections; the pick becomes `[(link)]`, shows as a removable chip above the composer, and
|
|
13975
|
+
* goes out with `(send)` as `link`. Load the sections when `(linkPickerOpened)` fires and show `[linkLoading]` meanwhile.
|
|
13976
|
+
*/
|
|
13977
|
+
readonly linkGroups: import("@angular/core").InputSignal<readonly ConversationLinkGroup[] | null>;
|
|
13978
|
+
readonly linkLoading: import("@angular/core").InputSignal<boolean>;
|
|
13979
|
+
/** The record linked to the message being written. Cleared by the host after a send, like `[(draft)]`; the chip's × clears it too. */
|
|
13980
|
+
readonly link: import("@angular/core").ModelSignal<ConversationLink | null>;
|
|
13981
|
+
readonly linkLabel: import("@angular/core").InputSignal<string>;
|
|
13982
|
+
readonly linkPickerTitle: import("@angular/core").InputSignal<string>;
|
|
13983
|
+
readonly linkSearchPlaceholder: import("@angular/core").InputSignal<string>;
|
|
13984
|
+
readonly linkSearchLabel: import("@angular/core").InputSignal<string>;
|
|
13985
|
+
readonly linkEmptyText: import("@angular/core").InputSignal<string>;
|
|
13986
|
+
readonly linkLoadingText: import("@angular/core").InputSignal<string>;
|
|
13987
|
+
readonly removeLinkLabel: import("@angular/core").InputSignal<string>;
|
|
13988
|
+
/** The "Link a record" button opened the picker: load the sections now. */
|
|
13989
|
+
readonly linkPickerOpened: import("@angular/core").OutputEmitterRef<void>;
|
|
13793
13990
|
/** An image in a bubble was clicked: the host opens it (usually in a new tab). */
|
|
13794
13991
|
readonly mediaOpen: import("@angular/core").OutputEmitterRef<string>;
|
|
13795
13992
|
/** The link-style button of a message (`ConversationMessage.action`) was clicked. */
|
|
@@ -13818,8 +14015,12 @@ export declare class ConversationsComponent {
|
|
|
13818
14015
|
protected readonly emptyText: import("@angular/core").Signal<string>;
|
|
13819
14016
|
protected readonly messageRows: import("@angular/core").Signal<import("@forgeroute/ui").ConversationMessageRow[]>;
|
|
13820
14017
|
protected readonly contextVisible: import("@angular/core").Signal<boolean>;
|
|
13821
|
-
/** Something to send (text or a
|
|
14018
|
+
/** Something to send (text, a file or a linked record), the composer is open and no request is running. */
|
|
13822
14019
|
readonly canSend: import("@angular/core").Signal<boolean>;
|
|
14020
|
+
protected readonly pickerOpen: import("@angular/core").WritableSignal<boolean>;
|
|
14021
|
+
protected readonly linkQuery: import("@angular/core").WritableSignal<string>;
|
|
14022
|
+
/** The picker's sections narrowed by the search (case-insensitive, on the record label); a section with no match is left out. */
|
|
14023
|
+
protected readonly visibleLinkGroups: import("@angular/core").Signal<ConversationLinkGroup[]>;
|
|
13823
14024
|
/** The composer's formatted content. `draft` is always its plain text, so a host that reads or sets `[(draft)]` never sees markup. */
|
|
13824
14025
|
protected readonly editorHtml: import("@angular/core").WritableSignal<string>;
|
|
13825
14026
|
protected readonly richHide: RichTextOption[];
|
|
@@ -13838,6 +14039,12 @@ export declare class ConversationsComponent {
|
|
|
13838
14039
|
protected onComposeKeydown(event: KeyboardEvent): void;
|
|
13839
14040
|
protected onEditorChange(html: string): void;
|
|
13840
14041
|
protected sendMessage(): void;
|
|
14042
|
+
protected openLinkPicker(): void;
|
|
14043
|
+
protected closeLinkPicker(): void;
|
|
14044
|
+
protected pickLink(group: ConversationLinkGroup, item: {
|
|
14045
|
+
id: string;
|
|
14046
|
+
label: string;
|
|
14047
|
+
}): void;
|
|
13841
14048
|
private clock;
|
|
13842
14049
|
private singleColumn;
|
|
13843
14050
|
private scrollToBottom;
|
|
@@ -14268,6 +14475,56 @@ export declare class ConversationsComponent {
|
|
|
14268
14475
|
"required": false;
|
|
14269
14476
|
"isSignal": true;
|
|
14270
14477
|
};
|
|
14478
|
+
"linkGroups": {
|
|
14479
|
+
"alias": "linkGroups";
|
|
14480
|
+
"required": false;
|
|
14481
|
+
"isSignal": true;
|
|
14482
|
+
};
|
|
14483
|
+
"linkLoading": {
|
|
14484
|
+
"alias": "linkLoading";
|
|
14485
|
+
"required": false;
|
|
14486
|
+
"isSignal": true;
|
|
14487
|
+
};
|
|
14488
|
+
"link": {
|
|
14489
|
+
"alias": "link";
|
|
14490
|
+
"required": false;
|
|
14491
|
+
"isSignal": true;
|
|
14492
|
+
};
|
|
14493
|
+
"linkLabel": {
|
|
14494
|
+
"alias": "linkLabel";
|
|
14495
|
+
"required": false;
|
|
14496
|
+
"isSignal": true;
|
|
14497
|
+
};
|
|
14498
|
+
"linkPickerTitle": {
|
|
14499
|
+
"alias": "linkPickerTitle";
|
|
14500
|
+
"required": false;
|
|
14501
|
+
"isSignal": true;
|
|
14502
|
+
};
|
|
14503
|
+
"linkSearchPlaceholder": {
|
|
14504
|
+
"alias": "linkSearchPlaceholder";
|
|
14505
|
+
"required": false;
|
|
14506
|
+
"isSignal": true;
|
|
14507
|
+
};
|
|
14508
|
+
"linkSearchLabel": {
|
|
14509
|
+
"alias": "linkSearchLabel";
|
|
14510
|
+
"required": false;
|
|
14511
|
+
"isSignal": true;
|
|
14512
|
+
};
|
|
14513
|
+
"linkEmptyText": {
|
|
14514
|
+
"alias": "linkEmptyText";
|
|
14515
|
+
"required": false;
|
|
14516
|
+
"isSignal": true;
|
|
14517
|
+
};
|
|
14518
|
+
"linkLoadingText": {
|
|
14519
|
+
"alias": "linkLoadingText";
|
|
14520
|
+
"required": false;
|
|
14521
|
+
"isSignal": true;
|
|
14522
|
+
};
|
|
14523
|
+
"removeLinkLabel": {
|
|
14524
|
+
"alias": "removeLinkLabel";
|
|
14525
|
+
"required": false;
|
|
14526
|
+
"isSignal": true;
|
|
14527
|
+
};
|
|
14271
14528
|
}, {
|
|
14272
14529
|
"searchText": "searchTextChange";
|
|
14273
14530
|
"contextOpen": "contextOpenChange";
|
|
@@ -14285,6 +14542,8 @@ export declare class ConversationsComponent {
|
|
|
14285
14542
|
"send": "send";
|
|
14286
14543
|
"filesSelected": "filesSelected";
|
|
14287
14544
|
"attachmentRemove": "attachmentRemove";
|
|
14545
|
+
"link": "linkChange";
|
|
14546
|
+
"linkPickerOpened": "linkPickerOpened";
|
|
14288
14547
|
"mediaOpen": "mediaOpen";
|
|
14289
14548
|
"messageAction": "messageAction";
|
|
14290
14549
|
"loadEarlier": "loadEarlier";
|