@forgeroute/ui 0.4.77 → 0.4.79

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.77",
3
+ "version": "0.4.79",
4
4
  "peerDependencies": {
5
5
  "@angular/common": ">=22.0.0",
6
6
  "@angular/core": ">=22.0.0",
@@ -57,6 +57,10 @@
57
57
  "types": "./types/forgeroute-ui-messaging.d.ts",
58
58
  "default": "./fesm2022/forgeroute-ui-messaging.mjs"
59
59
  },
60
+ "./offline": {
61
+ "types": "./types/forgeroute-ui-offline.d.ts",
62
+ "default": "./fesm2022/forgeroute-ui-offline.mjs"
63
+ },
60
64
  "./pdf": {
61
65
  "types": "./types/forgeroute-ui-pdf.d.ts",
62
66
  "default": "./fesm2022/forgeroute-ui-pdf.mjs"
@@ -1,4 +1,5 @@
1
1
  import * as i0 from "@angular/core";
2
+ import { UiLabelsService } from "@forgeroute/ui";
2
3
  /**
3
4
  * A darker shade (each channel x 0.8) of a hex (`#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`) or comma-separated `rgb()` / `rgba()` colour,
4
5
  * returned as `rgb(r, g, b)` or `rgba(r, g, b, a)`. Returns `null` for anything else (named colours, `var(--x)`, `hsl()`, out-of-range
@@ -119,8 +120,9 @@ export declare class BarChartComponent {
119
120
  readonly valueFormat: import("@angular/core").InputSignal<BarChartValueFormat>;
120
121
  /** ISO 4217 currency code for `valueFormat="currency"` (default USD; an invalid code falls back to USD). */
121
122
  readonly currency: import("@angular/core").InputSignal<string>;
122
- /** BCP 47 locale for 'currency' / 'percent' (default en-US; an invalid tag falls back to en-US). */
123
- readonly locale: import("@angular/core").InputSignal<string>;
123
+ /** BCP 47 locale for 'currency' / 'percent'. `null` (default) = the app's active locale (`UiLabelsService.setLocale`, `en-US` until set); an invalid tag falls back to en-US. */
124
+ readonly locale: import("@angular/core").InputSignal<string | null>;
125
+ private readonly _ui;
124
126
  /** Fixed number of decimals for 'currency' / 'percent' (integer 0-6). null = the format's default. Ignored for 'number'. */
125
127
  readonly decimals: import("@angular/core").InputSignal<number | null>;
126
128
  /** Several series sharing `labels` (grouped side by side, or stacked). Non-empty = takes precedence over `values`, `color`, `hoverColor` and `colors`. Default: none (single series). */
@@ -257,8 +259,11 @@ interface PieSlice {
257
259
  percent: string;
258
260
  color: string;
259
261
  }
260
- /** "62.5%", "100%", "<0.1%" (a non-zero share that rounds to nothing). Rounded to 1 decimal. */
261
- declare function formatPercent(value: number, total: number): string;
262
+ /**
263
+ * "62.5%", "100%", "<0.1%" (a non-zero share that rounds to nothing). Rounded to 1 decimal, written with the decimal mark of `locale`
264
+ * (default: the app's active locale, so "62,5%" in a locale that uses a comma).
265
+ */
266
+ declare function formatPercent(value: number, total: number, locale?: string): string;
262
267
  /**
263
268
  * Pie or doughnut chart of one series (e.g. payments by method).
264
269
  *
@@ -277,6 +282,7 @@ declare function formatPercent(value: number, total: number): string;
277
282
  * - No click output: a slice is not keyboard reachable, so selecting is left to a list or table next to the chart.
278
283
  */
279
284
  export declare class PieChartComponent {
285
+ protected readonly ui: UiLabelsService;
280
286
  /** Slice names. */
281
287
  readonly labels: import("@angular/core").InputSignal<string[]>;
282
288
  /** Slice values, in the order of `labels`. */
@@ -1,3 +1,4 @@
1
+ import { UiLabelsService } from "@forgeroute/ui";
1
2
  import * as i0 from "@angular/core";
2
3
  interface StateView {
3
4
  id: string;
@@ -31,6 +32,7 @@ interface StateView {
31
32
  * Territories are not on the map.
32
33
  */
33
34
  export declare class UsStateMapComponent {
35
+ protected readonly labels: UiLabelsService;
34
36
  /** State abbreviation -> value. Keys are case-insensitive; unknown keys are ignored; numbers and numeric strings (`'5'`) are read as numbers, anything else (negative, NaN, Infinity, text, booleans, null) counts as 0; repeated keys (`tx` and `TX`) are added up. */
35
37
  readonly data: import("@angular/core").InputSignal<Record<string, number>>;
36
38
  /** Abbreviation of the selected state (orange outline, the others are dimmed). Unknown / null = none. */
@@ -50,7 +52,8 @@ export declare class UsStateMapComponent {
50
52
  /** Shows a row of buttons for the very small states (touch friendly, 44px). Off by default. */
51
53
  readonly showSmallStateButtons: import("@angular/core").InputSignal<boolean>;
52
54
  /** Accessible name of the whole map. */
53
- readonly ariaLabel: import("@angular/core").InputSignal<string>;
55
+ readonly ariaLabelInput: import("@angular/core").InputSignal<string | null>;
56
+ readonly ariaLabel: import("@angular/core").Signal<string>;
54
57
  /** CSS maximum width of the map (it always shrinks to its container). */
55
58
  readonly maxWidth: import("@angular/core").InputSignal<string>;
56
59
  /** Optional CSS height of the map, e.g. "420px". Empty = follows the width (aspect ratio of the map). */
@@ -141,7 +144,7 @@ export declare class UsStateMapComponent {
141
144
  "required": false;
142
145
  "isSignal": true;
143
146
  };
144
- "ariaLabel": {
147
+ "ariaLabelInput": {
145
148
  "alias": "ariaLabel";
146
149
  "required": false;
147
150
  "isSignal": true;
@@ -1,4 +1,4 @@
1
- import { ComboboxOption, ComboboxSelection, ContactLookup, PillTab, RadioOption, SelectOption, UiFieldValidity } from "@forgeroute/ui";
1
+ import { ComboboxOption, ComboboxSelection, ContactLookup, PillTab, RadioOption, SelectOption, UiFieldValidity, UiLabelsService } from "@forgeroute/ui";
2
2
  import * as i0 from "@angular/core";
3
3
  import { ChangeDetectorRef, OnInit } from "@angular/core";
4
4
  import { Observable, Subject } from "rxjs";
@@ -10,6 +10,7 @@ export interface VideoMessage {
10
10
  shareLink: string | null;
11
11
  }
12
12
  export declare class VideoPickerComponent implements UiFieldValidity {
13
+ protected readonly labels: UiLabelsService;
13
14
  readonly videoSelected: import("@angular/core").OutputEmitterRef<VideoMessage>;
14
15
  /** Optional visible label (names the search field and the selected-video group). Without it the field is named "Search videos". */
15
16
  readonly label: import("@angular/core").InputSignal<string>;
@@ -107,6 +108,7 @@ export interface TemplateItem {
107
108
  useAllYear?: boolean;
108
109
  }
109
110
  export declare class TemplatePickerComponent {
111
+ protected readonly labels: UiLabelsService;
110
112
  private readonly http;
111
113
  /** API root from FORGEROUTE_CONFIG (e.g. a cross-origin prod API); falls back to same-origin `/api`. */
112
114
  private readonly apiBase;
@@ -117,7 +119,8 @@ export declare class TemplatePickerComponent {
117
119
  /** Filter results to a specific channel: 'email', 'text', or omit for all. */
118
120
  readonly channel: import("@angular/core").InputSignal<"" | "email" | "text">;
119
121
  readonly selectedId: import("@angular/core").InputSignal<string | null>;
120
- readonly label: import("@angular/core").InputSignal<string>;
122
+ readonly labelInput: import("@angular/core").InputSignal<string | null>;
123
+ readonly label: import("@angular/core").Signal<string>;
121
124
  /** Shows the red required asterisk (same as the library inputs) — e.g. when a template must be picked to send. */
122
125
  readonly required: import("@angular/core").InputSignal<boolean>;
123
126
  /** Reveal the built-in "<label> is required." message now (e.g. after a failed Send click); otherwise it shows after the field was blurred. */
@@ -177,7 +180,7 @@ export declare class TemplatePickerComponent {
177
180
  onPreviewClick(tpl: TemplateItem): void;
178
181
  select(tpl: TemplateItem): void;
179
182
  preview(tpl: TemplateItem): void;
180
- private readonly sampleVars;
183
+ private get sampleVars();
181
184
  previewText(raw: string): string;
182
185
  isCurrentlyActive(tpl: TemplateItem): boolean;
183
186
  activeDateLabel(tpl: TemplateItem): string;
@@ -193,7 +196,7 @@ export declare class TemplatePickerComponent {
193
196
  "required": false;
194
197
  "isSignal": true;
195
198
  };
196
- "label": {
199
+ "labelInput": {
197
200
  "alias": "label";
198
201
  "required": false;
199
202
  "isSignal": true;
@@ -538,13 +541,15 @@ export declare const DOCUMENT_PURPOSE_OPTIONS: SelectOption[];
538
541
  * show only while `showErrors` is true.
539
542
  */
540
543
  export declare class DocumentSendOptionsComponent implements UiFieldValidity {
544
+ protected readonly labels: UiLabelsService;
541
545
  private readonly http;
542
546
  private readonly destroyRef;
543
547
  /** API root from FORGEROUTE_CONFIG (e.g. a cross-origin prod API); falls back to same-origin `/api`. */
544
548
  private readonly apiBase;
545
549
  /** `email` → purpose select + attachment allowed; `text` → link only (purpose fixed to e-signature). */
546
550
  readonly channel: import("@angular/core").InputSignal<"email" | "text">;
547
- readonly label: import("@angular/core").InputSignal<string>;
551
+ readonly labelInput: import("@angular/core").InputSignal<string | null>;
552
+ readonly label: import("@angular/core").Signal<string>;
548
553
  /** When true, at least one document must be chosen. The message forms leave it false: documents are optional there. */
549
554
  readonly required: import("@angular/core").InputSignal<boolean>;
550
555
  /** Shows the validation message (bind it to the host's "tried to submit" flag). */
@@ -596,7 +601,13 @@ export declare class DocumentSendOptionsComponent implements UiFieldValidity {
596
601
  readonly envelope: import("@angular/core").InputSignal<DocumentEnvelopeTarget | null>;
597
602
  /** The document list is fixed: an existing envelope's. */
598
603
  readonly locked: import("@angular/core").Signal<boolean>;
599
- protected readonly purposeOptions: import("@angular/core").Signal<SelectOption<string>[]>;
604
+ protected readonly purposeOptions: import("@angular/core").Signal<{
605
+ label: string;
606
+ value: string;
607
+ description?: string;
608
+ badge?: string;
609
+ disabled?: boolean;
610
+ }[]>;
600
611
  readonly search$: Subject<string>;
601
612
  readonly options: import("@angular/core").WritableSignal<ComboboxOption<DocumentOption>[]>;
602
613
  readonly loading: import("@angular/core").WritableSignal<boolean>;
@@ -616,13 +627,13 @@ export declare class DocumentSendOptionsComponent implements UiFieldValidity {
616
627
  readonly expiryDays: import("@angular/core").WritableSignal<string>;
617
628
  readonly reminderIntervalDays: import("@angular/core").WritableSignal<string>;
618
629
  readonly maxReminders: import("@angular/core").WritableSignal<string>;
619
- protected readonly providerOptions: RadioOption[];
630
+ protected readonly providerOptions: import("@angular/core").Signal<RadioOption[]>;
620
631
  /** The search box; cleared (and kept focused) after each pick so the next search starts empty. */
621
632
  private readonly combo;
622
633
  /** True when the last search request failed (shown inline instead of "No matching documents"). */
623
634
  readonly searchFailed: import("@angular/core").WritableSignal<boolean>;
624
635
  /** Shown through the combobox's own `error` input, so it is announced and tied to the search field natively (aria-describedby on the inner input). */
625
- protected readonly searchFailedMessage = "Couldn't search your documents. Check your connection and try again.";
636
+ protected get searchFailedMessage(): string;
626
637
  /**
627
638
  * False when the section can't be used: the text channel only sends an e-signature link, so an app whose `purposes` excludes
628
639
  * `ESIGN` has nothing to offer there. The section then shows a short note instead of a picker (it never silently sends another purpose).
@@ -643,9 +654,9 @@ export declare class DocumentSendOptionsComponent implements UiFieldValidity {
643
654
  /** Why an envelope cannot be sent ('' = it can): nothing to send, or a document that is no longer active. Shown under the section. */
644
655
  readonly envelopeProblem: import("@angular/core").Signal<string>;
645
656
  /** Why Send waits for the envelope's documents ('' when they are known). */
646
- readonly envelopeReadMessage: import("@angular/core").Signal<"" | "Reading the envelope's documents…" | "The documents of this envelope couldn't be read, so it can't be sent yet.">;
657
+ readonly envelopeReadMessage: import("@angular/core").Signal<string>;
647
658
  /** Why Send waits for the document's signers ('' when they are known). */
648
- readonly signerReadMessage: import("@angular/core").Signal<"" | "Reading the document's signers…" | "The signers of this document couldn't be read, so it can't be sent yet.">;
659
+ readonly signerReadMessage: import("@angular/core").Signal<string>;
649
660
  /** The collapsed line: "Signing options: expires in 7 days, reminders every 2 days, up to 3". */
650
661
  readonly signingSummary: import("@angular/core").Signal<string>;
651
662
  /** Open when the sender opened it, or while a value is broken (the error must be visible). */
@@ -693,7 +704,7 @@ export declare class DocumentSendOptionsComponent implements UiFieldValidity {
693
704
  "required": false;
694
705
  "isSignal": true;
695
706
  };
696
- "label": {
707
+ "labelInput": {
697
708
  "alias": "label";
698
709
  "required": false;
699
710
  "isSignal": true;
@@ -758,6 +769,15 @@ export declare class DocumentSendOptionsComponent implements UiFieldValidity {
758
769
  "invalidChange": "invalidChange";
759
770
  }, never, never, true, never>;
760
771
  }
772
+ /**
773
+ * The Spanish wordings of the two video lines, kept here (not imported from the Spanish dictionary) so the messaging entry point does not pull the whole
774
+ * 117 KB dictionary into apps that never use Spanish. They only exist so a line written in Spanish is recognised after a language switch.
775
+ * `video-link.spec.ts` asserts they equal `UI_LABELS_ES`, so they cannot drift.
776
+ */
777
+ declare const SPANISH_VIDEO_LINK_WORDS: {
778
+ readonly watchVideo: "Ver video";
779
+ readonly watchNamed: "Ver \"{{ title }}\": {{ link }}";
780
+ };
761
781
  /**
762
782
  * Video share-link helpers shared by every app (they replace the apps' own copies, e.g. real-estate `video-link.utils.ts`).
763
783
  *
@@ -796,7 +816,7 @@ declare function videoLinkWithDefaults(baseLink: string, defaults?: VideoDefault
796
816
  export declare function stripVideoLink(text: string): string;
797
817
  /** Appends a "🎬 Watch video: <link>" line to a message body (replacing one that is already there). */
798
818
  export declare function appendVideoLink(text: string, link: string): string;
799
- /** The line `ui-send-message-panel` puts in the message for an attached video: `Watch "<title>": <link>`. */
819
+ /** The line `ui-send-message-panel` puts in the message for an attached video: `Watch "<title>": <link>` (the active language's wording, `messagingVideoLink.watchNamed`). */
800
820
  export declare function videoMessageLine(title: string, link: string): string;
801
821
  /**
802
822
  * Puts `next` into `body` in place of `prev` (the line inserted earlier), so changing a video setting rewrites the link without
@@ -804,6 +824,8 @@ export declare function videoMessageLine(title: string, link: string): string;
804
824
  * - no `prev` yet → appended after a blank line (no separator for an empty body);
805
825
  * - `prev` is in the body → replaced in place; with an empty `next` it is removed together with its separator;
806
826
  * - `prev` was edited away by the sender → the body is left as the sender wrote it.
827
+ * `prev` also matches the same video line in another language (English / Spanish wording, or the "🎬 Watch video:" form), so a language
828
+ * switch between the two calls replaces the line instead of adding a second one.
807
829
  */
808
830
  export declare function applyVideoLine(body: string, prev: string, next: string): string;
809
831
  /** The `documents` key of `SendEmailPayload` / `SendTextPayload`: present only when at least one document was chosen. */
@@ -970,6 +992,7 @@ interface SendEmailPayload {
970
992
  */
971
993
  export declare function messagePreviewHtml(body: string): string;
972
994
  declare class SendEmailComponent implements OnInit {
995
+ protected readonly labels: UiLabelsService;
973
996
  private readonly destroyRef;
974
997
  private readonly http;
975
998
  /** API root from FORGEROUTE_CONFIG (e.g. a cross-origin prod API); falls back to same-origin `/api`. */
@@ -1002,7 +1025,8 @@ declare class SendEmailComponent implements OnInit {
1002
1025
  readonly sendFn: import("@angular/core").InputSignal<((payload: SendEmailPayload) => Observable<unknown>) | null>;
1003
1026
  /** Shows an "include receipt" checkbox; the choice is sent as `includeReceipt`. Off = payload has no such key. */
1004
1027
  readonly showReceiptOption: import("@angular/core").InputSignal<boolean>;
1005
- readonly receiptLabel: import("@angular/core").InputSignal<string>;
1028
+ readonly receiptLabelInput: import("@angular/core").InputSignal<string | null>;
1029
+ readonly receiptLabel: import("@angular/core").Signal<string>;
1006
1030
  /** Initial state of the receipt checkbox (and the state it returns to after a send). */
1007
1031
  readonly receiptDefault: import("@angular/core").InputSignal<boolean>;
1008
1032
  /** Shows the "Documents" section (search your documents, choose what the recipient does with them). Off = the form is unchanged. */
@@ -1074,7 +1098,7 @@ declare class SendEmailComponent implements OnInit {
1074
1098
  id: string;
1075
1099
  title: string;
1076
1100
  }>;
1077
- readonly EMAIL_DISABLED_MESSAGE = "Email sending is disabled, so this can't be sent. Enable it in Communication Settings.";
1101
+ get EMAIL_DISABLED_MESSAGE(): string;
1078
1102
  mode: 'compose' | 'template';
1079
1103
  subject: string;
1080
1104
  body: string;
@@ -1108,7 +1132,7 @@ declare class SendEmailComponent implements OnInit {
1108
1132
  /** Lines of the merge check ("These fields will be left empty: …"). */
1109
1133
  mergeWarnings: string[];
1110
1134
  readonly savingEmail: import("@angular/core").WritableSignal<boolean>;
1111
- readonly modeTabs: PillTab[];
1135
+ readonly modeTabs: import("@angular/core").Signal<PillTab[]>;
1112
1136
  /** Market values (`area`, `median_price`, `dom`, `new_listings`) — only the ones `/service-areas` returned. */
1113
1137
  private marketVars;
1114
1138
  ngOnInit(): void;
@@ -1290,7 +1314,7 @@ declare class SendEmailComponent implements OnInit {
1290
1314
  "required": false;
1291
1315
  "isSignal": true;
1292
1316
  };
1293
- "receiptLabel": {
1317
+ "receiptLabelInput": {
1294
1318
  "alias": "receiptLabel";
1295
1319
  "required": false;
1296
1320
  "isSignal": true;
@@ -1440,6 +1464,7 @@ interface SendInAppAttachment {
1440
1464
  * `richText`) and optional attachments (`allowAttachments`). No templates, video or scheduling, and it makes no request of its own: `sendFn` does the sending. Used by `<ui-send-message-panel recipientMode="in-app">`.
1441
1465
  */
1442
1466
  declare class SendInAppComponent implements OnInit {
1467
+ protected readonly labels: UiLabelsService;
1443
1468
  private readonly destroyRef;
1444
1469
  private readonly toast;
1445
1470
  private readonly cdr;
@@ -1564,6 +1589,7 @@ interface SendTextPayload {
1564
1589
  }
1565
1590
  declare function formatPhone(raw: string | null | undefined): string;
1566
1591
  declare class SendTextComponent implements OnInit {
1592
+ protected readonly labels: UiLabelsService;
1567
1593
  protected readonly formatPhone: typeof formatPhone;
1568
1594
  private readonly destroyRef;
1569
1595
  private readonly http;
@@ -1681,7 +1707,7 @@ declare class SendTextComponent implements OnInit {
1681
1707
  } | null>;
1682
1708
  readonly mediaUploading: import("@angular/core").WritableSignal<boolean>;
1683
1709
  readonly savingPhone: import("@angular/core").WritableSignal<boolean>;
1684
- readonly modeTabs: PillTab[];
1710
+ readonly modeTabs: import("@angular/core").Signal<PillTab[]>;
1685
1711
  /** Market values (`area`, `median_price`, `dom`, `new_listings`) — only the ones `/service-areas` returned. */
1686
1712
  private marketVars;
1687
1713
  ngOnInit(): void;
@@ -1928,6 +1954,7 @@ export interface BulkSentEvent {
1928
1954
  /** The hint under the bulk summary: personal tags are not resolved by the panel. */
1929
1955
  export declare const BULK_MERGE_TAG_HINT = "Personal details such as {{first_name}} are filled in for each recipient when sent.";
1930
1956
  export declare class SendMessagePanelComponent {
1957
+ protected readonly labels: UiLabelsService;
1931
1958
  readonly open: import("@angular/core").InputSignal<boolean>;
1932
1959
  readonly contact: import("@angular/core").InputSignal<MessageContact | null>;
1933
1960
  readonly loading: import("@angular/core").InputSignal<boolean>;
@@ -1948,14 +1975,15 @@ export declare class SendMessagePanelComponent {
1948
1975
  * `textEnabled` must already be known when the panel opens for `'text'` to take effect (bind `[recipients]` after async settings loaded, or re-open).
1949
1976
  */
1950
1977
  readonly initialChannel: import("@angular/core").InputSignal<"email" | "text" | null>;
1951
- /** Bulk mode: the plural noun in "To: 12 residents" (default `recipients`). */
1978
+ /** Bulk mode: the plural noun in "To: 12 residents" (default `recipients`, localized). */
1952
1979
  readonly recipientNoun: import("@angular/core").InputSignal<string>;
1953
1980
  /** Bulk mode: the singular noun used when exactly one is selected; empty = the plural without a trailing "s". */
1954
1981
  readonly recipientNounSingular: import("@angular/core").InputSignal<string>;
1955
1982
  /** Pass true when Twilio / SMS is enabled in the consuming app's settings. */
1956
1983
  readonly textEnabled: import("@angular/core").InputSignal<boolean>;
1957
1984
  /** Panel header. */
1958
- readonly title: import("@angular/core").InputSignal<string>;
1985
+ readonly titleInput: import("@angular/core").InputSignal<string | null>;
1986
+ readonly title: import("@angular/core").Signal<string>;
1959
1987
  /** Prefill for the email Subject / Message and the text Message in "Create Message" mode. */
1960
1988
  readonly defaultSubject: import("@angular/core").InputSignal<string>;
1961
1989
  readonly defaultBody: import("@angular/core").InputSignal<string>;
@@ -1970,7 +1998,8 @@ export declare class SendMessagePanelComponent {
1970
1998
  readonly sendText: import("@angular/core").InputSignal<((payload: SendTextPayload) => Observable<unknown>) | null>;
1971
1999
  /** Email tab only: shows an "include receipt" checkbox; the choice is sent as `SendEmailPayload.includeReceipt`. */
1972
2000
  readonly showReceiptOption: import("@angular/core").InputSignal<boolean>;
1973
- readonly receiptLabel: import("@angular/core").InputSignal<string>;
2001
+ readonly receiptLabelInput: import("@angular/core").InputSignal<string | null>;
2002
+ readonly receiptLabel: import("@angular/core").Signal<string>;
1974
2003
  readonly receiptDefault: import("@angular/core").InputSignal<boolean>;
1975
2004
  /**
1976
2005
  * Adds a "Documents" section to the email and text forms: the sender searches the company's documents and sends them
@@ -2005,8 +2034,7 @@ export declare class SendMessagePanelComponent {
2005
2034
  readonly showVideo: import("@angular/core").InputSignal<boolean>;
2006
2035
  /** In-app mode is for one contact: it is ignored in bulk mode. */
2007
2036
  protected readonly inApp: import("@angular/core").Signal<boolean>;
2008
- protected readonly BULK_NO_SEND_MESSAGE = "Sending to several recipients is not set up for this page, so nothing was sent.";
2009
- protected readonly BULK_MERGE_TAG_HINT = "Personal details such as {{first_name}} are filled in for each recipient when sent.";
2037
+ protected get BULK_MERGE_TAG_HINT(): string;
2010
2038
  /**
2011
2039
  * false hides Attach Files / Attach Image AND "Schedule for later" in both forms (a host `sendEmail` / `sendText` that can't deliver them).
2012
2040
  * It is the default for the two switches below, which override it one by one.
@@ -2102,6 +2130,7 @@ export declare class SendMessagePanelComponent {
2102
2130
  readonly sending: import("@angular/core").WritableSignal<boolean>;
2103
2131
  private submitSnapshot;
2104
2132
  protected readonly recipientWord: import("@angular/core").Signal<string>;
2133
+ /** Why recipients are skipped, worded for how many of them there are (a language with number agreement says "no tiene" for one, "no tienen" for several). */
2105
2134
  private skippedReason;
2106
2135
  private skippedNames;
2107
2136
  readonly skippedText: import("@angular/core").Signal<string>;
@@ -2126,7 +2155,8 @@ export declare class SendMessagePanelComponent {
2126
2155
  * function adds it to its request.
2127
2156
  */
2128
2157
  readonly showJobPicker: import("@angular/core").InputSignal<boolean>;
2129
- readonly jobLabel: import("@angular/core").InputSignal<string>;
2158
+ readonly jobLabelInput: import("@angular/core").InputSignal<string | null>;
2159
+ readonly jobLabel: import("@angular/core").Signal<string>;
2130
2160
  readonly jobHint: import("@angular/core").InputSignal<string>;
2131
2161
  /**
2132
2162
  * Looks jobs up for the Job field (the panel knows nothing about the app's API): called with the typed text (2+ characters,
@@ -2224,7 +2254,7 @@ export declare class SendMessagePanelComponent {
2224
2254
  "required": false;
2225
2255
  "isSignal": true;
2226
2256
  };
2227
- "title": {
2257
+ "titleInput": {
2228
2258
  "alias": "title";
2229
2259
  "required": false;
2230
2260
  "isSignal": true;
@@ -2264,7 +2294,7 @@ export declare class SendMessagePanelComponent {
2264
2294
  "required": false;
2265
2295
  "isSignal": true;
2266
2296
  };
2267
- "receiptLabel": {
2297
+ "receiptLabelInput": {
2268
2298
  "alias": "receiptLabel";
2269
2299
  "required": false;
2270
2300
  "isSignal": true;
@@ -2424,7 +2454,7 @@ export declare class SendMessagePanelComponent {
2424
2454
  "required": false;
2425
2455
  "isSignal": true;
2426
2456
  };
2427
- "jobLabel": {
2457
+ "jobLabelInput": {
2428
2458
  "alias": "jobLabel";
2429
2459
  "required": false;
2430
2460
  "isSignal": true;
@@ -2450,16 +2480,6 @@ export declare class SendMessagePanelComponent {
2450
2480
  "phoneAdded": "phoneAdded";
2451
2481
  }, never, never, true, never>;
2452
2482
  }
2453
- /**
2454
- * Merge-tag helpers shared by the email and text forms, so the Preview pane, the "View Send Preview" modal and the
2455
- * sent payload all come from the same values.
2456
- *
2457
- * Rules:
2458
- * - A tag is `{{key}}` (inner spaces allowed: `{{ key }}`); `key` is letters, digits, `_` and `.`.
2459
- * - A value counts only when it is non-blank: a blank contact field, market value or `context` entry never
2460
- * resolves a tag — the form asks for it instead.
2461
- * - Anything still shaped like `{{…}}` after merging blocks sending (the server answers such a body with a 400).
2462
- */
2463
2483
  /** Every distinct tag key in `text`, in order of first appearance. */
2464
2484
  declare function mergeTagKeys(text: string): string[];
2465
2485
  /** Replaces each tag that has a non-blank value in `values`; other tags are left as written. */
@@ -2497,6 +2517,7 @@ declare function formatVarLabel(key: string): string;
2497
2517
  * roles `<Name> is already <Role label>.` (unless the config allows it).
2498
2518
  */
2499
2519
  export declare class DocumentSignersComponent implements UiFieldValidity {
2520
+ protected readonly labels: UiLabelsService;
2500
2521
  /** The signer logic's conclusion for the chosen document(s) (`ui-document-send-options` value `signerInfo`). */
2501
2522
  readonly info: import("@angular/core").InputSignal<DocumentSignerInfo | null>;
2502
2523
  readonly config: import("@angular/core").InputSignal<DocumentSignersConfig | null>;