@forgeroute/ui 0.4.60 → 0.4.61

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.60",
3
+ "version": "0.4.61",
4
4
  "peerDependencies": {
5
5
  "@angular/common": ">=22.0.0",
6
6
  "@angular/core": ">=22.0.0",
@@ -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<"hidden" | "visible" | "auto">;
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<"metadata" | "none" | "auto">;
2685
+ readonly preload: import("@angular/core").InputSignal<"none" | "auto" | "metadata">;
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>;
@@ -2936,7 +2936,7 @@ export declare class CheckboxComponent implements ControlValueAccessor, Validato
2936
2936
  * clicking it still toggles the box - e.g. a product name that is both the heading of its card and the label of its checkbox.
2937
2937
  * Default null: plain label text, exactly as before. Single mode only.
2938
2938
  */
2939
- readonly headingLevel: import("@angular/core").InputSignal<2 | 1 | 6 | 3 | 4 | 5 | null>;
2939
+ readonly headingLevel: import("@angular/core").InputSignal<1 | 2 | 3 | 4 | 5 | 6 | null>;
2940
2940
  readonly indeterminate: import("@angular/core").InputSignal<boolean>;
2941
2941
  readonly checked: import("@angular/core").ModelSignal<boolean>;
2942
2942
  /**
@@ -3847,7 +3847,7 @@ export declare class PhoneNumberPickerComponent {
3847
3847
  protected readonly modeCtl: FormControl<string>;
3848
3848
  protected readonly zipCtl: FormControl<string>;
3849
3849
  protected readonly areaCtl: FormControl<string>;
3850
- protected readonly step: import("@angular/core").WritableSignal<2 | 1 | 3>;
3850
+ protected readonly step: import("@angular/core").WritableSignal<1 | 2 | 3>;
3851
3851
  protected readonly mode: import("@angular/core").WritableSignal<PhoneNumberSearchMode>;
3852
3852
  private readonly _zip;
3853
3853
  private readonly _area;
@@ -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" | "primary" | "secondary" | "danger" | "warning" | "ghost" | "ghost-start" | "tab" | "icon" | "icon-danger">;
3966
+ readonly variant: import("@angular/core").InputSignal<"primary" | "secondary" | "danger" | "warning" | "link" | "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. */
@@ -4948,7 +4948,7 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
4948
4948
  readonly passwordRequirements: import("@angular/core").InputSignal<boolean>;
4949
4949
  /** Rules for `passwordRequirements`; default = the library's five rules (8+ characters, upper, lower, digit, special). */
4950
4950
  readonly passwordRules: import("@angular/core").InputSignal<readonly PasswordRule[] | undefined>;
4951
- readonly type: import("@angular/core").InputSignal<"number" | "tel" | "text" | "email" | "password" | "url">;
4951
+ readonly type: import("@angular/core").InputSignal<"number" | "text" | "email" | "tel" | "password" | "url">;
4952
4952
  readonly maxlength: import("@angular/core").InputSignal<number | undefined>;
4953
4953
  readonly required: import("@angular/core").InputSignal<boolean>;
4954
4954
  readonly autocomplete: import("@angular/core").InputSignal<string>;
@@ -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<"" | "tel" | "search" | "text" | "none" | "email" | "url" | "decimal" | "numeric">;
4960
+ readonly inputmode: import("@angular/core").InputSignal<"" | "none" | "text" | "search" | "email" | "tel" | "url" | "decimal" | "numeric">;
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. */
@@ -5023,7 +5023,7 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
5023
5023
  protected readonly _stepAttr: import("@angular/core").Signal<string | null>;
5024
5024
  protected readonly _revealable: import("@angular/core").Signal<boolean>;
5025
5025
  protected readonly _shown: import("@angular/core").WritableSignal<boolean>;
5026
- protected readonly _inputType: import("@angular/core").Signal<"number" | "tel" | "text" | "email" | "password" | "url">;
5026
+ protected readonly _inputType: import("@angular/core").Signal<"number" | "text" | "email" | "tel" | "password" | "url">;
5027
5027
  protected readonly _eyePath: string;
5028
5028
  protected readonly _eyeOffPath: string;
5029
5029
  protected readonly _showRequirements: import("@angular/core").Signal<boolean>;
@@ -6424,7 +6424,7 @@ export declare class DropdownComponent {
6424
6424
  readonly loader: import("@angular/core").InputSignal<(() => Promise<DropdownItem[]>) | null>;
6425
6425
  readonly active: import("@angular/core").InputSignal<boolean>;
6426
6426
  readonly activeValue: import("@angular/core").InputSignal<string>;
6427
- readonly variant: import("@angular/core").InputSignal<"button" | "badge">;
6427
+ readonly variant: import("@angular/core").InputSignal<"badge" | "button">;
6428
6428
  readonly menuWidth: import("@angular/core").InputSignal<string>;
6429
6429
  /**
6430
6430
  * Fixed width of the trigger as a CSS length (e.g. `'280px'`). Empty (default) = the trigger is as wide as its label. When set, the trigger keeps that
@@ -6728,7 +6728,7 @@ export declare class FormSectionComponent {
6728
6728
  }, {}, never, ["*"], true, never>;
6729
6729
  }
6730
6730
  export declare class FormRowComponent {
6731
- readonly cols: import("@angular/core").InputSignal<2 | 1 | 3 | 4>;
6731
+ readonly cols: import("@angular/core").InputSignal<1 | 2 | 3 | 4>;
6732
6732
  static ɵfac: i0.ɵɵFactoryDeclaration<FormRowComponent, never>;
6733
6733
  static ɵcmp: i0.ɵɵComponentDeclaration<FormRowComponent, "ui-form-row", never, {
6734
6734
  "cols": {
@@ -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<"" | 2 | "2" | "3" | 3 | "all">;
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, {
@@ -9045,10 +9045,10 @@ export declare function resolvePreset(key: DatePreset, today: Date): DateRange;
9045
9045
  * `textColor highlight` | `align` | `bulletList numberedList indent outdent` | `clearFormat`.
9046
9046
  * `align` is the three alignment buttons (left, center, right) as one option.
9047
9047
  */
9048
- export type RichTextOption = 'bold' | 'italic' | 'underline' | 'strikethrough' | 'heading' | 'fontSize' | 'fontFamily' | 'textColor' | 'highlight' | 'align' | 'bulletList' | 'numberedList' | 'indent' | 'outdent' | 'clearFormat';
9048
+ export type RichTextOption = 'bold' | 'italic' | 'underline' | 'strikethrough' | 'link' | 'heading' | 'fontSize' | 'fontFamily' | 'textColor' | 'highlight' | 'align' | 'bulletList' | 'numberedList' | 'indent' | 'outdent' | 'clearFormat';
9049
9049
  /** All option keys, in toolbar order. */
9050
9050
  export declare const RICH_TEXT_OPTIONS: readonly RichTextOption[];
9051
- type MenuId = 'heading' | 'size' | 'font';
9051
+ type MenuId = 'heading' | 'size' | 'font' | 'link';
9052
9052
  export declare class RichTextEditorComponent implements ControlValueAccessor {
9053
9053
  readonly label: import("@angular/core").InputSignal<string>;
9054
9054
  /** Accessible name for an editor with no visible label. */
@@ -9099,6 +9099,10 @@ export declare class RichTextEditorComponent implements ControlValueAccessor {
9099
9099
  protected readonly activeFont: import("@angular/core").WritableSignal<string>;
9100
9100
  protected readonly active: import("@angular/core").WritableSignal<Record<string, boolean>>;
9101
9101
  protected readonly empty: import("@angular/core").WritableSignal<boolean>;
9102
+ protected readonly linkUrl: import("@angular/core").WritableSignal<string>;
9103
+ protected readonly linkError: import("@angular/core").WritableSignal<string>;
9104
+ protected readonly hasLink: import("@angular/core").WritableSignal<boolean>;
9105
+ protected readonly _linkId: string;
9102
9106
  private readonly hidden;
9103
9107
  /** Group id → at least one of its controls is shown. */
9104
9108
  private readonly groupVisible;
@@ -9134,6 +9138,12 @@ export declare class RichTextEditorComponent implements ControlValueAccessor {
9134
9138
  protected selectHeading(tag: string, label: string): void;
9135
9139
  protected selectSize(value: string, label: string): void;
9136
9140
  protected selectFont(value: string, label: string): void;
9141
+ /** The `<a>` the saved (or current) selection sits in, if any. */
9142
+ private _anchorAtSelection;
9143
+ protected toggleLink(): void;
9144
+ protected closeLink(): void;
9145
+ protected applyLink(): void;
9146
+ protected removeLink(): void;
9137
9147
  protected exec(command: string): void;
9138
9148
  protected execWithArg(command: string, value: string): void;
9139
9149
  static ɵfac: i0.ɵɵFactoryDeclaration<RichTextEditorComponent, never>;
@@ -9800,7 +9810,7 @@ export declare class DetailCardComponent {
9800
9810
  /** true (default) = the title is displayed in capitals (CSS only); false = shown as written. The text, aria-label and heading name are never changed. */
9801
9811
  readonly uppercaseTitle: import("@angular/core").InputSignal<boolean>;
9802
9812
  /** 1-6 makes the title a real heading for screen readers (role=heading, aria-level); null keeps it plain text. */
9803
- readonly headingLevel: import("@angular/core").InputSignal<2 | 1 | 6 | 3 | 4 | 5 | null>;
9813
+ readonly headingLevel: import("@angular/core").InputSignal<1 | 2 | 3 | 4 | 5 | 6 | null>;
9804
9814
  /** Optional id for the title text; the card is then labelled by it. Without it the title is the card's aria-label. */
9805
9815
  readonly titleId: import("@angular/core").InputSignal<string>;
9806
9816
  /** Accessible name of the card when the header gives none (no header, or no title). A visible title wins; blank = no name. */
@@ -12243,7 +12253,7 @@ export declare class SetupWizardComponent {
12243
12253
  protected customHintId(): string;
12244
12254
  protected readonly importBlocked: import("@angular/core").Signal<boolean>;
12245
12255
  /** The step's own two parts (`splitLayout`) show as two tabs, one card at a time; this is the open one (it starts on the app's part on every visit). */
12246
- protected readonly splitTab: import("@angular/core").WritableSignal<"extra" | "main">;
12256
+ protected readonly splitTab: import("@angular/core").WritableSignal<"main" | "extra">;
12247
12257
  protected readonly splitTabs: import("@angular/core").Signal<{
12248
12258
  key: string;
12249
12259
  label: string;
@@ -13204,6 +13214,8 @@ export interface ConversationMessage {
13204
13214
  id: string;
13205
13215
  direction: ConversationMessageDirection;
13206
13216
  body?: string | null;
13217
+ /** Formatted text (bold, links, lists) of a message written in the rich composer: shown instead of `body`, after the library's allow-list sanitiser. Keep `body` as its plain text. */
13218
+ bodyHtml?: string | null;
13207
13219
  /** ISO instant. Drives the time under the bubble and the date separators. */
13208
13220
  sentAt: string;
13209
13221
  /** Outbound only: `sent` (✓), `delivered` (✓✓), `failed`, `scheduled`. Other values show nothing. */
@@ -13226,7 +13238,10 @@ export interface ConversationAttachment {
13226
13238
  }
13227
13239
  /** What `(send)` reports. */
13228
13240
  export interface ConversationSendEvent {
13241
+ /** The message as plain text (trimmed). With `[richText]`, the text of the formatted message. */
13229
13242
  text: string;
13243
+ /** With `[richText]`: the formatted message as sanitised HTML (bold, italic, underline, links, lists). Absent for a plain-text composer. */
13244
+ html?: string;
13230
13245
  }
13231
13246
  /** A message with the date separator that goes above it ('' when it shares the day of the previous message). */
13232
13247
  export interface ConversationMessageRow {
@@ -13255,6 +13270,24 @@ export declare function groupMessagesByDay(messages: readonly ConversationMessag
13255
13270
  export declare function conversationMessageStatusLabel(status: string | null | undefined): string;
13256
13271
  /** The mark shown beside an outbound message: ticks for sent / delivered, the word for the rest. */
13257
13272
  export declare function conversationMessageStatusMark(status: string | null | undefined): string;
13273
+ /**
13274
+ * The plain text of formatted composer HTML, the way it reads: paragraphs, list items and line breaks become line breaks, everything else
13275
+ * is its text. Runs on an inert document, so nothing in `html` is executed. Trimmed; '' for nothing.
13276
+ */
13277
+ export declare function conversationHtmlToText(html: string | null | undefined): string;
13278
+ /** A message's formatted text. Its own (unencapsulated) component so the styles reach the markup that `innerHTML` creates. */
13279
+ export declare class ConversationRichBodyComponent {
13280
+ readonly html: import("@angular/core").InputSignal<string>;
13281
+ protected readonly safe: import("@angular/core").Signal<string>;
13282
+ static ɵfac: i0.ɵɵFactoryDeclaration<ConversationRichBodyComponent, never>;
13283
+ static ɵcmp: i0.ɵɵComponentDeclaration<ConversationRichBodyComponent, "ui-conversation-rich-body", never, {
13284
+ "html": {
13285
+ "alias": "html";
13286
+ "required": false;
13287
+ "isSignal": true;
13288
+ };
13289
+ }, {}, never, never, true, never>;
13290
+ }
13258
13291
  /**
13259
13292
  * The text-message inbox: a conversation list (search, filter tabs, pagination) on the left, the open thread (header, messages with date
13260
13293
  * 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.
@@ -13281,7 +13314,7 @@ export declare function conversationMessageStatusMark(status: string | null | un
13281
13314
  * Test ids: conversations, conv-search, conv-filters, new-message-btn, conv-loading, conv-error, conv-retry, conv-empty, conv-item, conv-unread,
13282
13315
  * conv-arrow, 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,
13283
13316
  * messages, messages-loading, messages-empty, message, msg-status, attach-btn, attach-input, attachment-preview, attachment-remove,
13284
- * compose-input, send-btn, compose-opted-out, compose-loading-contact, context-panel, context-close.
13317
+ * msg-rich-body, compose-input, send-btn, compose-opted-out, compose-loading-contact, context-panel, context-close.
13285
13318
  */
13286
13319
  export declare class ConversationsComponent {
13287
13320
  readonly conversations: import("@angular/core").InputSignal<readonly ConversationItem[]>;
@@ -13322,6 +13355,8 @@ export declare class ConversationsComponent {
13322
13355
  readonly allowDelete: import("@angular/core").InputSignal<boolean>;
13323
13356
  /** The arrow at the end of each conversation row, drawn inside the row so its highlight covers it. Default false (hidden); `true` where the arrow helps (rows that open a thread on a phone). */
13324
13357
  readonly showRowArrow: import("@angular/core").InputSignal<boolean>;
13358
+ /** Rows open their conversation on click / Enter (pointer cursor, hover tint, focusable) and the thread has a Back button. `false` for a host with one conversation that is always open: nothing to click, no Back. */
13359
+ readonly selectable: import("@angular/core").InputSignal<boolean>;
13325
13360
  readonly newLabel: import("@angular/core").InputSignal<string>;
13326
13361
  readonly newTooltip: import("@angular/core").InputSignal<string>;
13327
13362
  readonly deleteRowLabel: import("@angular/core").InputSignal<string>;
@@ -13378,6 +13413,8 @@ export declare class ConversationsComponent {
13378
13413
  readonly composerError: import("@angular/core").InputSignal<string>;
13379
13414
  /** Longest message the box accepts (1600 = the SMS provider's limit for one send). */
13380
13415
  readonly maxLength: import("@angular/core").InputSignal<number>;
13416
+ /** The composer is the library's rich text editor (bold, italic, underline, links, lists) and `[(draft)]` holds its HTML; `(send)` reports `text` and `html`. Messages show their `bodyHtml`. Default false: a plain text box. */
13417
+ readonly richText: import("@angular/core").InputSignal<boolean>;
13381
13418
  readonly attachment: import("@angular/core").InputSignal<ConversationAttachment | null>;
13382
13419
  readonly uploading: import("@angular/core").InputSignal<boolean>;
13383
13420
  readonly attachEnabled: import("@angular/core").InputSignal<boolean>;
@@ -13441,6 +13478,9 @@ export declare class ConversationsComponent {
13441
13478
  protected readonly contextVisible: import("@angular/core").Signal<boolean>;
13442
13479
  /** Something to send (text or a file), the composer is open and no request is running. */
13443
13480
  readonly canSend: import("@angular/core").Signal<boolean>;
13481
+ /** The draft as plain text: the draft itself, or the text of its HTML in the rich composer. */
13482
+ protected readonly draftText: import("@angular/core").Signal<string>;
13483
+ protected readonly richHide: RichTextOption[];
13444
13484
  constructor();
13445
13485
  protected relativeTime(iso: string | null | undefined): string;
13446
13486
  protected preview(text: string | null | undefined): string;
@@ -13600,6 +13640,11 @@ export declare class ConversationsComponent {
13600
13640
  "required": false;
13601
13641
  "isSignal": true;
13602
13642
  };
13643
+ "selectable": {
13644
+ "alias": "selectable";
13645
+ "required": false;
13646
+ "isSignal": true;
13647
+ };
13603
13648
  "newLabel": {
13604
13649
  "alias": "newLabel";
13605
13650
  "required": false;
@@ -13805,6 +13850,11 @@ export declare class ConversationsComponent {
13805
13850
  "required": false;
13806
13851
  "isSignal": true;
13807
13852
  };
13853
+ "richText": {
13854
+ "alias": "richText";
13855
+ "required": false;
13856
+ "isSignal": true;
13857
+ };
13808
13858
  "attachment": {
13809
13859
  "alias": "attachment";
13810
13860
  "required": false;