@forgeroute/ui 0.4.58 → 0.4.59

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.
@@ -1095,7 +1095,7 @@ export declare class SelectComponent implements ControlValueAccessor, Validator,
1095
1095
  readonly error: import("@angular/core").InputSignal<string>;
1096
1096
  /** Reveal the built-in error messages now (e.g. after a failed Save click), without waiting for blur. */
1097
1097
  readonly showErrors: import("@angular/core").InputSignal<boolean>;
1098
- readonly size: import("@angular/core").InputSignal<"sm" | "default">;
1098
+ readonly size: import("@angular/core").InputSignal<"default" | "sm">;
1099
1099
  readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
1100
1100
  private readonly _cvaDisabled;
1101
1101
  protected readonly disabled: import("@angular/core").Signal<boolean>;
@@ -2152,7 +2152,7 @@ export declare class SidePanelComponent implements OnDestroy {
2152
2152
  readonly cancelLabel: import("@angular/core").InputSignal<string>;
2153
2153
  /** Right-aligned primary action button label. Empty string = hidden. */
2154
2154
  readonly primaryLabel: import("@angular/core").InputSignal<string>;
2155
- readonly primaryVariant: import("@angular/core").InputSignal<"danger" | "warning" | "primary">;
2155
+ readonly primaryVariant: import("@angular/core").InputSignal<"primary" | "danger" | "warning">;
2156
2156
  readonly primaryLoading: import("@angular/core").InputSignal<boolean>;
2157
2157
  readonly primaryDisabled: import("@angular/core").InputSignal<boolean>;
2158
2158
  /** `data-testid` of the Cancel button; none when empty (default). */
@@ -2260,7 +2260,7 @@ export declare class ModalComponent implements OnInit, OnDestroy {
2260
2260
  readonly title: import("@angular/core").InputSignal<string>;
2261
2261
  readonly description: import("@angular/core").InputSignal<string>;
2262
2262
  readonly maxWidth: import("@angular/core").InputSignal<string>;
2263
- readonly bodyOverflow: import("@angular/core").InputSignal<"auto" | "hidden" | "visible">;
2263
+ readonly bodyOverflow: import("@angular/core").InputSignal<"hidden" | "auto" | "visible">;
2264
2264
  /** `data-testid` of the dialog element itself (the host `<ui-modal>` is always in the page, the dialog only while open). None when empty. */
2265
2265
  readonly dialogTestId: import("@angular/core").InputSignal<string>;
2266
2266
  /** Hides the header X button (e.g. while a request is running). Escape and a backdrop click still close unless `closable` is false. */
@@ -2682,7 +2682,7 @@ export declare class AudioPlayerComponent {
2682
2682
  /** Accessible name of the player. */
2683
2683
  readonly ariaLabel: import("@angular/core").InputSignal<string>;
2684
2684
  /** How much to load before play: 'metadata' (default), 'auto' or 'none'. */
2685
- readonly preload: import("@angular/core").InputSignal<"none" | "auto" | "metadata">;
2685
+ readonly preload: import("@angular/core").InputSignal<"metadata" | "none" | "auto">;
2686
2686
  /** Fires when the browser can't load or decode the source. */
2687
2687
  readonly playbackError: import("@angular/core").OutputEmitterRef<void>;
2688
2688
  protected readonly failed: import("@angular/core").WritableSignal<boolean>;
@@ -3963,7 +3963,7 @@ export declare class ButtonComponent {
3963
3963
  * `ghost-start`: a ghost button for list / section toggles - a full-width row with its content aligned to the start, transparent
3964
3964
  * background, hover tint and the normal focus ring. Pair it with `ariaExpanded` / `ariaPressed`; the label may contain a heading element.
3965
3965
  */
3966
- readonly variant: import("@angular/core").InputSignal<"link" | "danger" | "warning" | "primary" | "secondary" | "ghost" | "ghost-start" | "tab" | "icon" | "icon-danger">;
3966
+ readonly variant: import("@angular/core").InputSignal<"link" | "primary" | "secondary" | "danger" | "warning" | "ghost" | "ghost-start" | "tab" | "icon" | "icon-danger">;
3967
3967
  /** Renders an anchor to this route instead of a button (use with `variant="link"` for an inline text link). `['/settings']` or `'/settings'`. While `disabled` or `loading` it renders a non-clickable `<span role="link" aria-disabled>` with no href (like `href`). */
3968
3968
  readonly routerLink: import("@angular/core").InputSignal<string | readonly unknown[] | null>;
3969
3969
  /** Query params of the `routerLink` (e.g. `{ section: 'deal-defaults' }`). */
@@ -3984,7 +3984,7 @@ export declare class ButtonComponent {
3984
3984
  */
3985
3985
  readonly href: import("@angular/core").InputSignal<string | null>;
3986
3986
  /** Where to open the `href` (`_blank` = a new tab). */
3987
- readonly target: import("@angular/core").InputSignal<"_blank" | "_self" | "_parent" | "_top" | null>;
3987
+ readonly target: import("@angular/core").InputSignal<"_self" | "_blank" | "_parent" | "_top" | null>;
3988
3988
  /** `rel` of the `href` link. A `_blank` target always gets `noopener noreferrer` added. */
3989
3989
  readonly rel: import("@angular/core").InputSignal<string | null>;
3990
3990
  /** The href when it is allowed (http, https, mailto, tel, sms or a relative URL), else null. */
@@ -4008,7 +4008,7 @@ export declare class ButtonComponent {
4008
4008
  private readonly _narrow;
4009
4009
  readonly color: import("@angular/core").InputSignal<string | undefined>;
4010
4010
  readonly active: import("@angular/core").InputSignal<boolean>;
4011
- readonly size: import("@angular/core").InputSignal<"xs" | "sm" | "md" | "lg">;
4011
+ readonly size: import("@angular/core").InputSignal<"sm" | "md" | "lg" | "xs">;
4012
4012
  readonly type: import("@angular/core").InputSignal<"button" | "reset" | "submit">;
4013
4013
  readonly disabled: import("@angular/core").InputSignal<boolean>;
4014
4014
  readonly loading: import("@angular/core").InputSignal<boolean>;
@@ -4957,7 +4957,7 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
4957
4957
  * `search`, `text`, `none`). Empty (default) = the browser's default for the field, except `type="tel"`, which keeps `tel`.
4958
4958
  * It only picks the keyboard; it does not restrict what can be typed or pasted.
4959
4959
  */
4960
- readonly inputmode: import("@angular/core").InputSignal<"" | "none" | "search" | "text" | "email" | "tel" | "url" | "decimal" | "numeric">;
4960
+ readonly inputmode: import("@angular/core").InputSignal<"" | "search" | "text" | "numeric" | "none" | "email" | "tel" | "url" | "decimal">;
4961
4961
  readonly readonly: import("@angular/core").InputSignal<boolean>;
4962
4962
  readonly hint: import("@angular/core").InputSignal<string>;
4963
4963
  /** Id(s) of an external element that also describes this control (e.g. one shared error text for a group of fields). Space separated; MERGED after the control's own hint / error id in `aria-describedby`, never replacing it. Empty = unchanged. */
@@ -6745,7 +6745,7 @@ export declare class FormRowComponent {
6745
6745
  * child simply takes the full width. Keep a numeric span within the row's `cols` (use `all` for the whole row).
6746
6746
  */
6747
6747
  export declare class FormColSpanDirective {
6748
- readonly uiColSpan: import("@angular/core").InputSignal<"" | "all" | "2" | 2 | "3" | 3>;
6748
+ readonly uiColSpan: import("@angular/core").InputSignal<"" | 2 | 3 | "2" | "3" | "all">;
6749
6749
  protected readonly _class: import("@angular/core").Signal<string>;
6750
6750
  static ɵfac: i0.ɵɵFactoryDeclaration<FormColSpanDirective, never>;
6751
6751
  static ɵdir: i0.ɵɵDirectiveDeclaration<FormColSpanDirective, "[uiColSpan]", never, {
@@ -7862,9 +7862,9 @@ export declare class ChipGroupComponent {
7862
7862
  readonly spaceAbove: import("@angular/core").InputSignal<"none" | "sm" | "md">;
7863
7863
  /** Space below the chip group. */
7864
7864
  readonly spaceBelow: import("@angular/core").InputSignal<"none" | "sm" | "md">;
7865
- protected readonly _gap: import("@angular/core").Signal<"12px" | "6px" | "8px">;
7866
- protected readonly _spaceAbove: import("@angular/core").Signal<"12px" | "0" | "6px">;
7867
- protected readonly _spaceBelow: import("@angular/core").Signal<"12px" | "0" | "6px">;
7865
+ protected readonly _gap: import("@angular/core").Signal<"6px" | "12px" | "8px">;
7866
+ protected readonly _spaceAbove: import("@angular/core").Signal<"0" | "6px" | "12px">;
7867
+ protected readonly _spaceBelow: import("@angular/core").Signal<"0" | "6px" | "12px">;
7868
7868
  static ɵfac: i0.ɵɵFactoryDeclaration<ChipGroupComponent, never>;
7869
7869
  static ɵcmp: i0.ɵɵComponentDeclaration<ChipGroupComponent, "ui-chip-group", never, {
7870
7870
  "gap": {
@@ -9657,7 +9657,7 @@ export declare class PdfHotspotComponent {
9657
9657
  /** `ready`: clickable; `blocked`: disabled (a prerequisite is missing); `signed`: shows `image`. */
9658
9658
  readonly state: import("@angular/core").InputSignal<"ready" | "blocked" | "signed">;
9659
9659
  /** `warning` gives the ready state an amber look (e.g. for initials), default is blue. */
9660
- readonly tone: import("@angular/core").InputSignal<"warning" | "primary">;
9660
+ readonly tone: import("@angular/core").InputSignal<"primary" | "warning">;
9661
9661
  /** Text of the ready button (e.g. "Sign Here"). */
9662
9662
  readonly label: import("@angular/core").InputSignal<string>;
9663
9663
  /** Text of the blocked button (e.g. "Add signature above"). */
@@ -13166,4 +13166,720 @@ export declare class ReminderAlertsComponent {
13166
13166
  "hidden": "hidden";
13167
13167
  }, never, never, true, never>;
13168
13168
  }
13169
+ /** One row of the conversation list. The HOST maps its own record to this shape (phone formatting aside, the component shows the values as given). */
13170
+ export interface ConversationItem {
13171
+ id: string;
13172
+ /** Who the conversation is with; also the avatar initial and the thread heading. */
13173
+ name: string;
13174
+ /** Second line under the name, e.g. a phone number already formatted by the host (see `formatConversationPhone`). */
13175
+ subtitle?: string | null;
13176
+ /** ISO instant of the last message: shown as a short relative time ("5m", "2d", "Oct 12"). */
13177
+ lastMessageAt?: string | null;
13178
+ /** The last message's text; cut at 60 characters. Empty shows "No messages". */
13179
+ preview?: string | null;
13180
+ /** Unread messages; above 0 the row is highlighted and shows a count badge. */
13181
+ unreadCount?: number;
13182
+ /** A gray badge on the row, e.g. "Closed" or "Archived". Omit for an open conversation. */
13183
+ statusLabel?: string | null;
13184
+ }
13185
+ export type ConversationMessageDirection = 'inbound' | 'outbound';
13186
+ /** A file shown inside a message bubble. */
13187
+ export interface ConversationMedia {
13188
+ url: string;
13189
+ /** MIME type: `image/*` is shown as a picture, `video/*` as a player, anything else as a link. */
13190
+ type?: string | null;
13191
+ fileName?: string | null;
13192
+ }
13193
+ /** One message of the open thread. */
13194
+ export interface ConversationMessage {
13195
+ id: string;
13196
+ direction: ConversationMessageDirection;
13197
+ body?: string | null;
13198
+ /** ISO instant. Drives the time under the bubble and the date separators. */
13199
+ sentAt: string;
13200
+ /** Outbound only: `sent` (✓), `delivered` (✓✓), `failed`, `scheduled`. Other values show nothing. */
13201
+ status?: string | null;
13202
+ media?: ConversationMedia | null;
13203
+ /** Outbound only: who wrote it (e.g. the agent's name), shown before the time. Omit when the sender is always "You". */
13204
+ sender?: string | null;
13205
+ /** A link-style button under the text, e.g. "View transaction"; clicking it emits `(messageAction)` with this message. */
13206
+ action?: ConversationMessageAction | null;
13207
+ }
13208
+ /** The button a message can carry (see `ConversationMessage.action`). */
13209
+ export interface ConversationMessageAction {
13210
+ label: string;
13211
+ }
13212
+ /** The file waiting to be sent with the next message. */
13213
+ export interface ConversationAttachment {
13214
+ fileName: string;
13215
+ /** Shown as a thumbnail when set; otherwise the file name. */
13216
+ previewUrl?: string | null;
13217
+ }
13218
+ /** What `(send)` reports. */
13219
+ export interface ConversationSendEvent {
13220
+ text: string;
13221
+ }
13222
+ /** A message with the date separator that goes above it ('' when it shares the day of the previous message). */
13223
+ export interface ConversationMessageRow {
13224
+ message: ConversationMessage;
13225
+ separator: string;
13226
+ }
13227
+ /**
13228
+ * Pure display helpers of `ui-conversations` (no Angular). Dates are formatted with an explicit 'en-US' locale and are only ever
13229
+ * read from ISO strings, so Chrome, Edge, Firefox and Safari print the same text.
13230
+ */
13231
+ /** "(512) 555-0100"; "+1 (512) 555-0100" for an 11-digit number that starts with 1; anything else is returned as stored ('' for none). */
13232
+ export declare function formatConversationPhone(phone: string | null | undefined): string;
13233
+ /** The text cut at `len` characters with "..." ('' for none). */
13234
+ export declare function truncateConversationText(text: string | null | undefined, len: number): string;
13235
+ /** "now", "5m", "3h", "2d", then "Oct 12" (the list's time column). '' for a missing or unreadable date. */
13236
+ export declare function formatConversationTime(iso: string | null | undefined, now?: Date): string;
13237
+ /** "3:05 PM" (a message's time). '' for an unreadable date. */
13238
+ export declare function formatMessageTime(iso: string): string;
13239
+ /** "Today", "Yesterday" or "Oct 12, 2026" (the date separator in a thread). '' for an unreadable date (never "Invalid Date"). */
13240
+ export declare function conversationDateLabel(iso: string, now?: Date): string;
13241
+ /** First letter of the name, upper case, for the avatar ('?' for a blank name). */
13242
+ export declare function conversationInitial(name: string | null | undefined): string;
13243
+ /** Each message with the date separator that goes above it ('' when it shares the day of the previous message). */
13244
+ export declare function groupMessagesByDay(messages: readonly ConversationMessage[], now?: Date): ConversationMessageRow[];
13245
+ /** What the status mark beside an outbound message says to a screen reader ('' for a status that shows nothing). */
13246
+ export declare function conversationMessageStatusLabel(status: string | null | undefined): string;
13247
+ /** The mark shown beside an outbound message: ticks for sent / delivered, the word for the rest. */
13248
+ export declare function conversationMessageStatusMark(status: string | null | undefined): string;
13249
+ /**
13250
+ * The text-message inbox: a conversation list (search, filter tabs, pagination) on the left, the open thread (header, messages with date
13251
+ * separators and media, composer) in the middle and an optional contact panel on the right. On a phone the list and the thread take turns.
13252
+ *
13253
+ * <ui-conversations
13254
+ * [conversations]="rows()" [selected]="open()" [messages]="messages()" [loading]="loading()" [messagesLoading]="threadLoading()"
13255
+ * [filterTabs]="tabs" [filterCounts]="counts()" [activeFilter]="filter()" [page]="page()" [pageSize]="25" [totalItems]="total()"
13256
+ * [(draft)]="draft" [sending]="sending()" [canWrite]="canWrite()" [hasContext]="true" [(contextOpen)]="contextOpen"
13257
+ * (searchChange)="onSearch($event)" (filterChange)="filter.set($event)" (pageChange)="page.set($event)"
13258
+ * (selectConversation)="open.set($event)" (send)="onSend($event)" ...>
13259
+ * <div uiConversationsContext> ...contact details... </div>
13260
+ * </ui-conversations>
13261
+ *
13262
+ * The component keeps NO data and makes NO requests: the host loads, polls, sends, uploads, deletes and changes status, and passes the
13263
+ * results back in. It owns the layout, the keyboard / screen-reader behaviour, the scroll-to-latest rule (the thread follows new messages
13264
+ * only while the user is at its end), the focus moves of the one-column layout and the Enter-to-send rule (Shift+Enter is a new line; the
13265
+ * Enter that confirms an IME composition is not a send). `[canWrite]="false"` is the read-only view: no New / Delete / status / template
13266
+ * buttons and no composer.
13267
+ *
13268
+ * `[allowNew]="false"` / `[allowDelete]="false"` hide the New and Delete buttons for a host that cannot start or delete conversations while the composer
13269
+ * stays (a reply-only inbox such as Portal Messages). A message may carry a `sender` and an `action` link button (`(messageAction)`); a long thread
13270
+ * shows "Load earlier messages" while `[hasEarlier]` (`(loadEarlier)`); a failed thread load shows `[messagesError]` with Retry (`(messagesRetry)`).
13271
+ *
13272
+ * Test ids: conversations, conv-search, conv-filters, new-message-btn, conv-loading, conv-error, conv-retry, conv-empty, conv-item, conv-unread,
13273
+ * conv-delete-btn, thread-empty, thread-error, thread-retry, load-earlier, msg-sender, msg-action, back-to-list, thread-name, thread-phone, use-template-btn, context-toggle, status-btn, thread-delete-btn,
13274
+ * messages, messages-loading, messages-empty, message, msg-status, attach-btn, attach-input, attachment-preview, attachment-remove,
13275
+ * compose-input, send-btn, compose-opted-out, compose-loading-contact, context-panel, context-close.
13276
+ */
13277
+ export declare class ConversationsComponent {
13278
+ readonly conversations: import("@angular/core").InputSignal<readonly ConversationItem[]>;
13279
+ /** The open conversation (null = none: the empty thread shows, and on a phone the list). It need not be on the current list page. */
13280
+ readonly selected: import("@angular/core").InputSignal<ConversationItem | null>;
13281
+ readonly title: import("@angular/core").InputSignal<string>;
13282
+ readonly loading: import("@angular/core").InputSignal<boolean>;
13283
+ /** A failed list load: the message, with a Retry button. */
13284
+ readonly error: import("@angular/core").InputSignal<string | null>;
13285
+ /** The search text (two-way). The host usually reacts to `(searchChange)`, which fires after the search box's own debounce. */
13286
+ readonly searchText: import("@angular/core").ModelSignal<string>;
13287
+ readonly searchPlaceholder: import("@angular/core").InputSignal<string>;
13288
+ readonly searchAriaLabel: import("@angular/core").InputSignal<string>;
13289
+ /** Search and filter tabs are hidden until the host says the first load is done (they would flash while loading). */
13290
+ readonly showFilters: import("@angular/core").InputSignal<boolean>;
13291
+ /** Filter tabs; none = no filter row. The empty value `''` is the "All" tab. */
13292
+ readonly filterTabs: import("@angular/core").InputSignal<QuickFilterTab[]>;
13293
+ readonly filterCounts: import("@angular/core").InputSignal<Record<string, number>>;
13294
+ readonly activeFilter: import("@angular/core").InputSignal<string>;
13295
+ readonly filterAriaLabel: import("@angular/core").InputSignal<string>;
13296
+ /** 1-based page, page size and total of the list. */
13297
+ readonly page: import("@angular/core").InputSignal<number>;
13298
+ readonly pageSize: import("@angular/core").InputSignal<number>;
13299
+ readonly totalItems: import("@angular/core").InputSignal<number>;
13300
+ readonly paginationAriaLabel: import("@angular/core").InputSignal<string>;
13301
+ readonly listAriaLabel: import("@angular/core").InputSignal<string>;
13302
+ readonly loadingLabel: import("@angular/core").InputSignal<string>;
13303
+ readonly emptyTitle: import("@angular/core").InputSignal<string>;
13304
+ readonly emptyMessage: import("@angular/core").InputSignal<string>;
13305
+ /** The empty-list text for a read-only user (who has no + button). */
13306
+ readonly emptyReadOnlyMessage: import("@angular/core").InputSignal<string>;
13307
+ readonly filteredEmptyTitle: import("@angular/core").InputSignal<string>;
13308
+ readonly filteredEmptyMessage: import("@angular/core").InputSignal<string>;
13309
+ readonly noMessagesText: import("@angular/core").InputSignal<string>;
13310
+ /** Shows the + (New) button for a writer. `false` for a host that cannot start conversations. */
13311
+ readonly allowNew: import("@angular/core").InputSignal<boolean>;
13312
+ /** Shows the bins (row and thread header) for a writer. `false` for a host that cannot delete conversations. */
13313
+ readonly allowDelete: import("@angular/core").InputSignal<boolean>;
13314
+ readonly newLabel: import("@angular/core").InputSignal<string>;
13315
+ readonly newTooltip: import("@angular/core").InputSignal<string>;
13316
+ readonly deleteRowLabel: import("@angular/core").InputSignal<string>;
13317
+ readonly messages: import("@angular/core").InputSignal<readonly ConversationMessage[]>;
13318
+ readonly messagesLoading: import("@angular/core").InputSignal<boolean>;
13319
+ /** A failed thread load: the message, with a Retry button (`(messagesRetry)`). */
13320
+ readonly messagesError: import("@angular/core").InputSignal<string | null>;
13321
+ /** The loaded messages are only the newest ones: a "Load earlier messages" button shows above them. */
13322
+ readonly hasEarlier: import("@angular/core").InputSignal<boolean>;
13323
+ readonly loadingEarlier: import("@angular/core").InputSignal<boolean>;
13324
+ readonly loadEarlierLabel: import("@angular/core").InputSignal<string>;
13325
+ /** The thread header's Close / Reopen button: its label (also the tooltip); null = no button. */
13326
+ readonly statusActionLabel: import("@angular/core").InputSignal<string | null>;
13327
+ /** `close` (a check) or `reopen` (a circular arrow): which icon the status button shows. */
13328
+ readonly statusActionIcon: import("@angular/core").InputSignal<"close" | "reopen">;
13329
+ readonly statusChanging: import("@angular/core").InputSignal<boolean>;
13330
+ /** Shows the "Use a template" button (disabled with the composer). */
13331
+ readonly templatesEnabled: import("@angular/core").InputSignal<boolean>;
13332
+ readonly templateLabel: import("@angular/core").InputSignal<string>;
13333
+ readonly deleteThreadLabel: import("@angular/core").InputSignal<string>;
13334
+ readonly backLabel: import("@angular/core").InputSignal<string>;
13335
+ readonly threadAriaLabel: import("@angular/core").InputSignal<string>;
13336
+ readonly messagesAriaLabel: import("@angular/core").InputSignal<string>;
13337
+ readonly threadEmptyTitle: import("@angular/core").InputSignal<string>;
13338
+ readonly threadEmptyMessage: import("@angular/core").InputSignal<string>;
13339
+ readonly noMessagesWriteText: import("@angular/core").InputSignal<string>;
13340
+ readonly noMessagesReadText: import("@angular/core").InputSignal<string>;
13341
+ readonly youLabel: import("@angular/core").InputSignal<string>;
13342
+ readonly openMediaLabel: import("@angular/core").InputSignal<string>;
13343
+ readonly imageFallbackName: import("@angular/core").InputSignal<string>;
13344
+ readonly fileFallbackName: import("@angular/core").InputSignal<string>;
13345
+ /** Shows the contact-info toggle. The panel's content is the host's, projected with the `uiConversationsContext` attribute. */
13346
+ readonly hasContext: import("@angular/core").InputSignal<boolean>;
13347
+ /** The panel is open (two-way). It closes itself on Escape, the X and (one column) the backdrop, and when the conversation is closed. */
13348
+ readonly contextOpen: import("@angular/core").ModelSignal<boolean>;
13349
+ readonly contextTitle: import("@angular/core").InputSignal<string>;
13350
+ readonly showContextLabel: import("@angular/core").InputSignal<string>;
13351
+ readonly hideContextLabel: import("@angular/core").InputSignal<string>;
13352
+ readonly closeContextLabel: import("@angular/core").InputSignal<string>;
13353
+ /** Read-only view: no New / Delete / status / template buttons and no composer. */
13354
+ readonly canWrite: import("@angular/core").InputSignal<boolean>;
13355
+ /** The message being typed (two-way). The host clears it after a successful send. */
13356
+ readonly draft: import("@angular/core").ModelSignal<string>;
13357
+ readonly sending: import("@angular/core").InputSignal<boolean>;
13358
+ /** The composer is locked (e.g. the contact opted out): the box, attach and template buttons are disabled and nothing can be sent. */
13359
+ readonly composerDisabled: import("@angular/core").InputSignal<boolean>;
13360
+ /** A host-side reason nothing can be sent right now (e.g. the contact is still loading); the Send button is disabled. */
13361
+ readonly sendBlocked: import("@angular/core").InputSignal<boolean>;
13362
+ /** A warning under the composer, e.g. "This contact has opted out of text messages." */
13363
+ readonly composerNotice: import("@angular/core").InputSignal<string>;
13364
+ /** A polite status line under the composer (a live region), e.g. "Loading contact...". */
13365
+ readonly composerStatus: import("@angular/core").InputSignal<string>;
13366
+ /** An error on the message box. */
13367
+ readonly composerError: import("@angular/core").InputSignal<string>;
13368
+ /** Longest message the box accepts (1600 = the SMS provider's limit for one send). */
13369
+ readonly maxLength: import("@angular/core").InputSignal<number>;
13370
+ readonly attachment: import("@angular/core").InputSignal<ConversationAttachment | null>;
13371
+ readonly uploading: import("@angular/core").InputSignal<boolean>;
13372
+ readonly attachEnabled: import("@angular/core").InputSignal<boolean>;
13373
+ readonly acceptedFiles: import("@angular/core").InputSignal<string>;
13374
+ readonly maxFileSize: import("@angular/core").InputSignal<number | null>;
13375
+ readonly typeMessage: import("@angular/core").InputSignal<string>;
13376
+ readonly sizeMessage: import("@angular/core").InputSignal<string>;
13377
+ readonly composeLabel: import("@angular/core").InputSignal<string>;
13378
+ readonly composePlaceholder: import("@angular/core").InputSignal<string>;
13379
+ readonly sendLabel: import("@angular/core").InputSignal<string>;
13380
+ readonly attachLabel: import("@angular/core").InputSignal<string>;
13381
+ readonly removeAttachmentLabel: import("@angular/core").InputSignal<string>;
13382
+ readonly attachmentPreviewLabel: import("@angular/core").InputSignal<string>;
13383
+ /** "Now" for the relative times and date separators; null = the real clock. For tests and demos. */
13384
+ readonly now: import("@angular/core").InputSignal<Date | null>;
13385
+ readonly searchChange: import("@angular/core").OutputEmitterRef<string>;
13386
+ readonly filterChange: import("@angular/core").OutputEmitterRef<string>;
13387
+ readonly pageChange: import("@angular/core").OutputEmitterRef<number>;
13388
+ /** A row was clicked or opened with the keyboard. */
13389
+ readonly selectConversation: import("@angular/core").OutputEmitterRef<ConversationItem>;
13390
+ /** Back (one column): the host clears `selected`; the focus returns to the row that was open. */
13391
+ readonly back: import("@angular/core").OutputEmitterRef<void>;
13392
+ readonly newConversation: import("@angular/core").OutputEmitterRef<void>;
13393
+ readonly retry: import("@angular/core").OutputEmitterRef<void>;
13394
+ /** The bin on a row, or in the thread header. The host asks for confirmation. */
13395
+ readonly deleteConversation: import("@angular/core").OutputEmitterRef<ConversationItem>;
13396
+ /** The Close / Reopen button of the open conversation. */
13397
+ readonly statusChange: import("@angular/core").OutputEmitterRef<ConversationItem>;
13398
+ readonly templateRequest: import("@angular/core").OutputEmitterRef<void>;
13399
+ readonly send: import("@angular/core").OutputEmitterRef<ConversationSendEvent>;
13400
+ /** Files accepted by the attach picker (type and size already checked against `acceptedFiles` / `maxFileSize`). */
13401
+ readonly filesSelected: import("@angular/core").OutputEmitterRef<File[]>;
13402
+ readonly attachmentRemove: import("@angular/core").OutputEmitterRef<void>;
13403
+ /** An image in a bubble was clicked: the host opens it (usually in a new tab). */
13404
+ readonly mediaOpen: import("@angular/core").OutputEmitterRef<string>;
13405
+ /** The link-style button of a message (`ConversationMessage.action`) was clicked. */
13406
+ readonly messageAction: import("@angular/core").OutputEmitterRef<ConversationMessage>;
13407
+ /** "Load earlier messages": the host puts the older page above the loaded messages. */
13408
+ readonly loadEarlier: import("@angular/core").OutputEmitterRef<void>;
13409
+ /** Retry after a failed thread load. */
13410
+ readonly messagesRetry: import("@angular/core").OutputEmitterRef<void>;
13411
+ protected readonly titleId: string;
13412
+ protected readonly skeletonRows: number[];
13413
+ protected readonly skeletonBubbles: number[];
13414
+ protected readonly trackConversation: (c: ConversationItem) => string;
13415
+ protected readonly initial: typeof conversationInitial;
13416
+ protected readonly statusLabel: typeof conversationMessageStatusLabel;
13417
+ protected readonly statusMark: typeof conversationMessageStatusMark;
13418
+ private readonly injector;
13419
+ private readonly host;
13420
+ private readonly threadHeading;
13421
+ private readonly messagesEl;
13422
+ private readonly contextPanel;
13423
+ private readonly fileInput;
13424
+ /** True while the thread is scrolled to (or within NEAR_BOTTOM_PX of) its end; kept by the scroll handler. */
13425
+ private atBottom;
13426
+ private lastThreadId;
13427
+ protected readonly filtering: import("@angular/core").Signal<boolean>;
13428
+ protected readonly emptyText: import("@angular/core").Signal<string>;
13429
+ protected readonly messageRows: import("@angular/core").Signal<import("@forgeroute/ui").ConversationMessageRow[]>;
13430
+ protected readonly contextVisible: import("@angular/core").Signal<boolean>;
13431
+ /** Something to send (text or a file), the composer is open and no request is running. */
13432
+ readonly canSend: import("@angular/core").Signal<boolean>;
13433
+ constructor();
13434
+ protected relativeTime(iso: string | null | undefined): string;
13435
+ protected preview(text: string | null | undefined): string;
13436
+ protected time(message: ConversationMessage): string;
13437
+ /** A row was clicked or opened with the keyboard. */
13438
+ protected onRowOpen(conv: ConversationItem): void;
13439
+ protected onBack(): void;
13440
+ protected onMessagesScroll(): void;
13441
+ protected toggleContext(): void;
13442
+ /** Closes the contact panel; `restoreFocus` puts the focus back on the toggle that opened it. */
13443
+ protected closeContext(restoreFocus?: boolean): void;
13444
+ protected openFilePicker(): void;
13445
+ protected onComposeKeydown(event: KeyboardEvent): void;
13446
+ protected sendMessage(): void;
13447
+ private clock;
13448
+ private singleColumn;
13449
+ private scrollToBottom;
13450
+ static ɵfac: i0.ɵɵFactoryDeclaration<ConversationsComponent, never>;
13451
+ static ɵcmp: i0.ɵɵComponentDeclaration<ConversationsComponent, "ui-conversations", never, {
13452
+ "conversations": {
13453
+ "alias": "conversations";
13454
+ "required": false;
13455
+ "isSignal": true;
13456
+ };
13457
+ "selected": {
13458
+ "alias": "selected";
13459
+ "required": false;
13460
+ "isSignal": true;
13461
+ };
13462
+ "title": {
13463
+ "alias": "title";
13464
+ "required": false;
13465
+ "isSignal": true;
13466
+ };
13467
+ "loading": {
13468
+ "alias": "loading";
13469
+ "required": false;
13470
+ "isSignal": true;
13471
+ };
13472
+ "error": {
13473
+ "alias": "error";
13474
+ "required": false;
13475
+ "isSignal": true;
13476
+ };
13477
+ "searchText": {
13478
+ "alias": "searchText";
13479
+ "required": false;
13480
+ "isSignal": true;
13481
+ };
13482
+ "searchPlaceholder": {
13483
+ "alias": "searchPlaceholder";
13484
+ "required": false;
13485
+ "isSignal": true;
13486
+ };
13487
+ "searchAriaLabel": {
13488
+ "alias": "searchAriaLabel";
13489
+ "required": false;
13490
+ "isSignal": true;
13491
+ };
13492
+ "showFilters": {
13493
+ "alias": "showFilters";
13494
+ "required": false;
13495
+ "isSignal": true;
13496
+ };
13497
+ "filterTabs": {
13498
+ "alias": "filterTabs";
13499
+ "required": false;
13500
+ "isSignal": true;
13501
+ };
13502
+ "filterCounts": {
13503
+ "alias": "filterCounts";
13504
+ "required": false;
13505
+ "isSignal": true;
13506
+ };
13507
+ "activeFilter": {
13508
+ "alias": "activeFilter";
13509
+ "required": false;
13510
+ "isSignal": true;
13511
+ };
13512
+ "filterAriaLabel": {
13513
+ "alias": "filterAriaLabel";
13514
+ "required": false;
13515
+ "isSignal": true;
13516
+ };
13517
+ "page": {
13518
+ "alias": "page";
13519
+ "required": false;
13520
+ "isSignal": true;
13521
+ };
13522
+ "pageSize": {
13523
+ "alias": "pageSize";
13524
+ "required": false;
13525
+ "isSignal": true;
13526
+ };
13527
+ "totalItems": {
13528
+ "alias": "totalItems";
13529
+ "required": false;
13530
+ "isSignal": true;
13531
+ };
13532
+ "paginationAriaLabel": {
13533
+ "alias": "paginationAriaLabel";
13534
+ "required": false;
13535
+ "isSignal": true;
13536
+ };
13537
+ "listAriaLabel": {
13538
+ "alias": "listAriaLabel";
13539
+ "required": false;
13540
+ "isSignal": true;
13541
+ };
13542
+ "loadingLabel": {
13543
+ "alias": "loadingLabel";
13544
+ "required": false;
13545
+ "isSignal": true;
13546
+ };
13547
+ "emptyTitle": {
13548
+ "alias": "emptyTitle";
13549
+ "required": false;
13550
+ "isSignal": true;
13551
+ };
13552
+ "emptyMessage": {
13553
+ "alias": "emptyMessage";
13554
+ "required": false;
13555
+ "isSignal": true;
13556
+ };
13557
+ "emptyReadOnlyMessage": {
13558
+ "alias": "emptyReadOnlyMessage";
13559
+ "required": false;
13560
+ "isSignal": true;
13561
+ };
13562
+ "filteredEmptyTitle": {
13563
+ "alias": "filteredEmptyTitle";
13564
+ "required": false;
13565
+ "isSignal": true;
13566
+ };
13567
+ "filteredEmptyMessage": {
13568
+ "alias": "filteredEmptyMessage";
13569
+ "required": false;
13570
+ "isSignal": true;
13571
+ };
13572
+ "noMessagesText": {
13573
+ "alias": "noMessagesText";
13574
+ "required": false;
13575
+ "isSignal": true;
13576
+ };
13577
+ "allowNew": {
13578
+ "alias": "allowNew";
13579
+ "required": false;
13580
+ "isSignal": true;
13581
+ };
13582
+ "allowDelete": {
13583
+ "alias": "allowDelete";
13584
+ "required": false;
13585
+ "isSignal": true;
13586
+ };
13587
+ "newLabel": {
13588
+ "alias": "newLabel";
13589
+ "required": false;
13590
+ "isSignal": true;
13591
+ };
13592
+ "newTooltip": {
13593
+ "alias": "newTooltip";
13594
+ "required": false;
13595
+ "isSignal": true;
13596
+ };
13597
+ "deleteRowLabel": {
13598
+ "alias": "deleteRowLabel";
13599
+ "required": false;
13600
+ "isSignal": true;
13601
+ };
13602
+ "messages": {
13603
+ "alias": "messages";
13604
+ "required": false;
13605
+ "isSignal": true;
13606
+ };
13607
+ "messagesLoading": {
13608
+ "alias": "messagesLoading";
13609
+ "required": false;
13610
+ "isSignal": true;
13611
+ };
13612
+ "messagesError": {
13613
+ "alias": "messagesError";
13614
+ "required": false;
13615
+ "isSignal": true;
13616
+ };
13617
+ "hasEarlier": {
13618
+ "alias": "hasEarlier";
13619
+ "required": false;
13620
+ "isSignal": true;
13621
+ };
13622
+ "loadingEarlier": {
13623
+ "alias": "loadingEarlier";
13624
+ "required": false;
13625
+ "isSignal": true;
13626
+ };
13627
+ "loadEarlierLabel": {
13628
+ "alias": "loadEarlierLabel";
13629
+ "required": false;
13630
+ "isSignal": true;
13631
+ };
13632
+ "statusActionLabel": {
13633
+ "alias": "statusActionLabel";
13634
+ "required": false;
13635
+ "isSignal": true;
13636
+ };
13637
+ "statusActionIcon": {
13638
+ "alias": "statusActionIcon";
13639
+ "required": false;
13640
+ "isSignal": true;
13641
+ };
13642
+ "statusChanging": {
13643
+ "alias": "statusChanging";
13644
+ "required": false;
13645
+ "isSignal": true;
13646
+ };
13647
+ "templatesEnabled": {
13648
+ "alias": "templatesEnabled";
13649
+ "required": false;
13650
+ "isSignal": true;
13651
+ };
13652
+ "templateLabel": {
13653
+ "alias": "templateLabel";
13654
+ "required": false;
13655
+ "isSignal": true;
13656
+ };
13657
+ "deleteThreadLabel": {
13658
+ "alias": "deleteThreadLabel";
13659
+ "required": false;
13660
+ "isSignal": true;
13661
+ };
13662
+ "backLabel": {
13663
+ "alias": "backLabel";
13664
+ "required": false;
13665
+ "isSignal": true;
13666
+ };
13667
+ "threadAriaLabel": {
13668
+ "alias": "threadAriaLabel";
13669
+ "required": false;
13670
+ "isSignal": true;
13671
+ };
13672
+ "messagesAriaLabel": {
13673
+ "alias": "messagesAriaLabel";
13674
+ "required": false;
13675
+ "isSignal": true;
13676
+ };
13677
+ "threadEmptyTitle": {
13678
+ "alias": "threadEmptyTitle";
13679
+ "required": false;
13680
+ "isSignal": true;
13681
+ };
13682
+ "threadEmptyMessage": {
13683
+ "alias": "threadEmptyMessage";
13684
+ "required": false;
13685
+ "isSignal": true;
13686
+ };
13687
+ "noMessagesWriteText": {
13688
+ "alias": "noMessagesWriteText";
13689
+ "required": false;
13690
+ "isSignal": true;
13691
+ };
13692
+ "noMessagesReadText": {
13693
+ "alias": "noMessagesReadText";
13694
+ "required": false;
13695
+ "isSignal": true;
13696
+ };
13697
+ "youLabel": {
13698
+ "alias": "youLabel";
13699
+ "required": false;
13700
+ "isSignal": true;
13701
+ };
13702
+ "openMediaLabel": {
13703
+ "alias": "openMediaLabel";
13704
+ "required": false;
13705
+ "isSignal": true;
13706
+ };
13707
+ "imageFallbackName": {
13708
+ "alias": "imageFallbackName";
13709
+ "required": false;
13710
+ "isSignal": true;
13711
+ };
13712
+ "fileFallbackName": {
13713
+ "alias": "fileFallbackName";
13714
+ "required": false;
13715
+ "isSignal": true;
13716
+ };
13717
+ "hasContext": {
13718
+ "alias": "hasContext";
13719
+ "required": false;
13720
+ "isSignal": true;
13721
+ };
13722
+ "contextOpen": {
13723
+ "alias": "contextOpen";
13724
+ "required": false;
13725
+ "isSignal": true;
13726
+ };
13727
+ "contextTitle": {
13728
+ "alias": "contextTitle";
13729
+ "required": false;
13730
+ "isSignal": true;
13731
+ };
13732
+ "showContextLabel": {
13733
+ "alias": "showContextLabel";
13734
+ "required": false;
13735
+ "isSignal": true;
13736
+ };
13737
+ "hideContextLabel": {
13738
+ "alias": "hideContextLabel";
13739
+ "required": false;
13740
+ "isSignal": true;
13741
+ };
13742
+ "closeContextLabel": {
13743
+ "alias": "closeContextLabel";
13744
+ "required": false;
13745
+ "isSignal": true;
13746
+ };
13747
+ "canWrite": {
13748
+ "alias": "canWrite";
13749
+ "required": false;
13750
+ "isSignal": true;
13751
+ };
13752
+ "draft": {
13753
+ "alias": "draft";
13754
+ "required": false;
13755
+ "isSignal": true;
13756
+ };
13757
+ "sending": {
13758
+ "alias": "sending";
13759
+ "required": false;
13760
+ "isSignal": true;
13761
+ };
13762
+ "composerDisabled": {
13763
+ "alias": "composerDisabled";
13764
+ "required": false;
13765
+ "isSignal": true;
13766
+ };
13767
+ "sendBlocked": {
13768
+ "alias": "sendBlocked";
13769
+ "required": false;
13770
+ "isSignal": true;
13771
+ };
13772
+ "composerNotice": {
13773
+ "alias": "composerNotice";
13774
+ "required": false;
13775
+ "isSignal": true;
13776
+ };
13777
+ "composerStatus": {
13778
+ "alias": "composerStatus";
13779
+ "required": false;
13780
+ "isSignal": true;
13781
+ };
13782
+ "composerError": {
13783
+ "alias": "composerError";
13784
+ "required": false;
13785
+ "isSignal": true;
13786
+ };
13787
+ "maxLength": {
13788
+ "alias": "maxLength";
13789
+ "required": false;
13790
+ "isSignal": true;
13791
+ };
13792
+ "attachment": {
13793
+ "alias": "attachment";
13794
+ "required": false;
13795
+ "isSignal": true;
13796
+ };
13797
+ "uploading": {
13798
+ "alias": "uploading";
13799
+ "required": false;
13800
+ "isSignal": true;
13801
+ };
13802
+ "attachEnabled": {
13803
+ "alias": "attachEnabled";
13804
+ "required": false;
13805
+ "isSignal": true;
13806
+ };
13807
+ "acceptedFiles": {
13808
+ "alias": "acceptedFiles";
13809
+ "required": false;
13810
+ "isSignal": true;
13811
+ };
13812
+ "maxFileSize": {
13813
+ "alias": "maxFileSize";
13814
+ "required": false;
13815
+ "isSignal": true;
13816
+ };
13817
+ "typeMessage": {
13818
+ "alias": "typeMessage";
13819
+ "required": false;
13820
+ "isSignal": true;
13821
+ };
13822
+ "sizeMessage": {
13823
+ "alias": "sizeMessage";
13824
+ "required": false;
13825
+ "isSignal": true;
13826
+ };
13827
+ "composeLabel": {
13828
+ "alias": "composeLabel";
13829
+ "required": false;
13830
+ "isSignal": true;
13831
+ };
13832
+ "composePlaceholder": {
13833
+ "alias": "composePlaceholder";
13834
+ "required": false;
13835
+ "isSignal": true;
13836
+ };
13837
+ "sendLabel": {
13838
+ "alias": "sendLabel";
13839
+ "required": false;
13840
+ "isSignal": true;
13841
+ };
13842
+ "attachLabel": {
13843
+ "alias": "attachLabel";
13844
+ "required": false;
13845
+ "isSignal": true;
13846
+ };
13847
+ "removeAttachmentLabel": {
13848
+ "alias": "removeAttachmentLabel";
13849
+ "required": false;
13850
+ "isSignal": true;
13851
+ };
13852
+ "attachmentPreviewLabel": {
13853
+ "alias": "attachmentPreviewLabel";
13854
+ "required": false;
13855
+ "isSignal": true;
13856
+ };
13857
+ "now": {
13858
+ "alias": "now";
13859
+ "required": false;
13860
+ "isSignal": true;
13861
+ };
13862
+ }, {
13863
+ "searchText": "searchTextChange";
13864
+ "contextOpen": "contextOpenChange";
13865
+ "draft": "draftChange";
13866
+ "searchChange": "searchChange";
13867
+ "filterChange": "filterChange";
13868
+ "pageChange": "pageChange";
13869
+ "selectConversation": "selectConversation";
13870
+ "back": "back";
13871
+ "newConversation": "newConversation";
13872
+ "retry": "retry";
13873
+ "deleteConversation": "deleteConversation";
13874
+ "statusChange": "statusChange";
13875
+ "templateRequest": "templateRequest";
13876
+ "send": "send";
13877
+ "filesSelected": "filesSelected";
13878
+ "attachmentRemove": "attachmentRemove";
13879
+ "mediaOpen": "mediaOpen";
13880
+ "messageAction": "messageAction";
13881
+ "loadEarlier": "loadEarlier";
13882
+ "messagesRetry": "messagesRetry";
13883
+ }, never, ["[uiConversationsContext]"], true, never>;
13884
+ }
13169
13885
  export type { CalendarDay, CalendarRange, CalendarViewMode };