@forgeroute/ui 0.4.72 → 0.4.73

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from "@angular/core";
2
- import { EnvironmentProviders, InjectionToken, OnDestroy, OnInit, Signal, TemplateRef, WritableSignal } from "@angular/core";
2
+ import { AfterContentChecked, EnvironmentProviders, InjectionToken, OnDestroy, OnInit, Signal, TemplateRef, WritableSignal } from "@angular/core";
3
3
  import { UrlTree } from "@angular/router";
4
4
  import { Observable, Subject } from "rxjs";
5
5
  import { AbstractControl, ControlValueAccessor, FormControl, ValidationErrors, Validator, ValidatorFn } from "@angular/forms";
@@ -1133,6 +1133,13 @@ export declare class SelectComponent implements ControlValueAccessor, Validator,
1133
1133
  readonly label: import("@angular/core").InputSignal<string>;
1134
1134
  /** Accessible name for a select with no visible label (e.g. an inline row or table-cell select). */
1135
1135
  readonly ariaLabel: import("@angular/core").InputSignal<string>;
1136
+ /**
1137
+ * Compact, label-less look for a filter above KPI cards or in a toolbar (library source 2026-11-04, not yet published). `true` renders NO visible
1138
+ * label row (no gap above the field; the `*` marker goes with it) while `label` stays the select's accessible name through `aria-label` and still
1139
+ * words the built-in "<label> is required." message. An explicit `ariaLabel` wins over `label`. Default `false` = unchanged. Combine with
1140
+ * `size="sm"`. (`ariaLabel` alone, with no `label`, was already the way to name a label-less select in a table cell.)
1141
+ */
1142
+ readonly labelHidden: import("@angular/core").InputSignal<boolean>;
1136
1143
  /** Native `name` attribute placed on the inner `<select>` (e2e `[name=x]` selectors, autofill). None when empty. */
1137
1144
  readonly inputName: import("@angular/core").InputSignal<string>;
1138
1145
  readonly placeholder: import("@angular/core").InputSignal<string>;
@@ -1146,7 +1153,7 @@ export declare class SelectComponent implements ControlValueAccessor, Validator,
1146
1153
  readonly error: import("@angular/core").InputSignal<string>;
1147
1154
  /** Reveal the built-in error messages now (e.g. after a failed Save click), without waiting for blur. */
1148
1155
  readonly showErrors: import("@angular/core").InputSignal<boolean>;
1149
- readonly size: import("@angular/core").InputSignal<"default" | "sm">;
1156
+ readonly size: import("@angular/core").InputSignal<"sm" | "default">;
1150
1157
  readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
1151
1158
  private readonly _cvaDisabled;
1152
1159
  protected readonly disabled: import("@angular/core").Signal<boolean>;
@@ -1175,6 +1182,13 @@ export declare class SelectComponent implements ControlValueAccessor, Validator,
1175
1182
  validate(control: AbstractControl): ValidationErrors | null;
1176
1183
  registerOnValidatorChange(fn: () => void): void;
1177
1184
  protected readonly _selectId: string;
1185
+ private readonly _hostEl;
1186
+ /**
1187
+ * Library source 2026-11-04, not yet published. Puts the keyboard focus on the inner native `<select>` (`ref.focus()` via `viewChild`).
1188
+ * Same options as the DOM method (`{ preventScroll: true }`). Safe at any time: before the view exists, or on a disabled field, it does
1189
+ * nothing and never throws.
1190
+ */
1191
+ focus(options?: FocusOptions): void;
1178
1192
  private _onChange;
1179
1193
  private _warned;
1180
1194
  /** The comparison form of a key: in number mode a numeric text ('21.0', ' 21 ') becomes the canonical number text ('21'). */
@@ -1203,6 +1217,11 @@ export declare class SelectComponent implements ControlValueAccessor, Validator,
1203
1217
  "required": false;
1204
1218
  "isSignal": true;
1205
1219
  };
1220
+ "labelHidden": {
1221
+ "alias": "labelHidden";
1222
+ "required": false;
1223
+ "isSignal": true;
1224
+ };
1206
1225
  "inputName": {
1207
1226
  "alias": "inputName";
1208
1227
  "required": false;
@@ -1602,6 +1621,15 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
1602
1621
  */
1603
1622
  readonly bulkPanelClick: import("@angular/core").OutputEmitterRef<BulkPanelEvent<T>>;
1604
1623
  /** Emitted after a built-in single-row delete completes successfully. */
1624
+ /**
1625
+ * Emitted after every rows request that completes (a request superseded by a newer one emits nothing; first load, page, sort, search, tab, filter, `refresh()` ...): `{ ok: true, total }` when the rows
1626
+ * arrived (`total` = all matching rows), `{ ok: false, total }` when the request failed (the rows on screen are kept, `total` is the last known).
1627
+ * Lets a host refresh something that must follow the table (e.g. a failure banner above it).
1628
+ */
1629
+ readonly loaded: import("@angular/core").OutputEmitterRef<{
1630
+ ok: boolean;
1631
+ total: number;
1632
+ }>;
1605
1633
  readonly rowDeleted: import("@angular/core").OutputEmitterRef<T>;
1606
1634
  /**
1607
1635
  * Optional drag-and-drop ordering of the rows. Off by default; when `true` (and the user has full access) every row gets a grip
@@ -2193,6 +2221,7 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
2193
2221
  "tabChange": "tabChange";
2194
2222
  "bulkAction": "bulkAction";
2195
2223
  "bulkPanelClick": "bulkPanelClick";
2224
+ "loaded": "loaded";
2196
2225
  "rowDeleted": "rowDeleted";
2197
2226
  "rowReorder": "rowReorder";
2198
2227
  }, never, never, true, never>;
@@ -2228,7 +2257,7 @@ export declare class SidePanelComponent implements OnDestroy {
2228
2257
  readonly cancelLabel: import("@angular/core").InputSignal<string>;
2229
2258
  /** Right-aligned primary action button label. Empty string = hidden. */
2230
2259
  readonly primaryLabel: import("@angular/core").InputSignal<string>;
2231
- readonly primaryVariant: import("@angular/core").InputSignal<"warning" | "danger" | "primary">;
2260
+ readonly primaryVariant: import("@angular/core").InputSignal<"primary" | "danger" | "warning">;
2232
2261
  readonly primaryLoading: import("@angular/core").InputSignal<boolean>;
2233
2262
  readonly primaryDisabled: import("@angular/core").InputSignal<boolean>;
2234
2263
  /** `data-testid` of the Cancel button; none when empty (default). */
@@ -2243,6 +2272,15 @@ export declare class SidePanelComponent implements OnDestroy {
2243
2272
  readonly closed: import("@angular/core").OutputEmitterRef<void>;
2244
2273
  readonly primaryClick: import("@angular/core").OutputEmitterRef<void>;
2245
2274
  protected readonly titleId: string;
2275
+ /**
2276
+ * (library source 2026-11-04, not yet published) True while the scrollable body (`.sp-body`) is taller than the space it has.
2277
+ * Only then the body is a keyboard Tab stop (`tabindex="0"`, `role="group"`, named by the panel title via `aria-labelledby`)
2278
+ * so keyboard users can scroll it with the arrow keys / Space / PageUp / PageDown. While the content fits, the body carries
2279
+ * none of those attributes (unchanged markup). Kept current by a ResizeObserver + MutationObserver on the body.
2280
+ */
2281
+ readonly bodyScrollable: import("@angular/core").WritableSignal<boolean>;
2282
+ private readonly _bodyRef;
2283
+ private _bodyObservers;
2246
2284
  private readonly _el;
2247
2285
  private readonly _doc;
2248
2286
  private readonly _overlays;
@@ -2252,6 +2290,14 @@ export declare class SidePanelComponent implements OnDestroy {
2252
2290
  private _stopIframeKeys;
2253
2291
  private readonly _interaction;
2254
2292
  constructor();
2293
+ /**
2294
+ * Re-measures the body now (`scrollHeight` vs `clientHeight`, 1px tolerance for sub-pixel rounding) and updates
2295
+ * `bodyScrollable`. Called by the observers; also usable by a host that changes the body content in a way no observer sees.
2296
+ */
2297
+ refreshScrollable(): void;
2298
+ /** Starts observing the (new) body element, or stops observing when the body is gone (panel closed). */
2299
+ private _watchBody;
2300
+ private _stopWatchingBody;
2255
2301
  onKeydown(event: KeyboardEvent): void;
2256
2302
  /** A focus-guard sentinel received focus (Tab left the panel's tab order, e.g. out of an iframe): send it back inside. */
2257
2303
  protected onGuardFocus(which: 'start' | 'end', event?: FocusEvent): void;
@@ -2513,6 +2559,14 @@ export interface ToastOptions {
2513
2559
  key?: string;
2514
2560
  /** Called with the `id` of a button when it is used (before the toast closes). */
2515
2561
  onAction?: (actionId: string) => void;
2562
+ /**
2563
+ * (library source 2026-11-04, not yet published) Default `false` (unchanged). `true` = if a toast with the SAME message and the SAME type is on screen right
2564
+ * now, show this one as a fresh toast of its own: the toast element is re-created (so a screen reader announces the text again and the
2565
+ * entry animation replays), the dismiss timer restarts with this call's duration, and the title / buttons / countdown of this call replace
2566
+ * the old ones. Nothing is queued. If the message on screen is different (or nothing is showing) `repeat` changes nothing. Without
2567
+ * `repeat`, an identical message arriving while it is on screen only restarts the timer silently: it is not announced again.
2568
+ */
2569
+ repeat?: boolean;
2516
2570
  }
2517
2571
  /** What is known about the toast on screen beyond its message and type; `null` for a plain toast. */
2518
2572
  export interface ToastDetails {
@@ -2539,6 +2593,11 @@ export declare class ToastService implements OnDestroy {
2539
2593
  readonly persistentLiveRegion: import("@angular/core").WritableSignal<boolean>;
2540
2594
  /** The title, buttons, countdown flag, key and callback of the toast on screen; `null` for a plain toast or none. */
2541
2595
  readonly details: import("@angular/core").WritableSignal<ToastDetails | null>;
2596
+ /**
2597
+ * (library source 2026-11-04, not yet published) Counts the `repeat: true` re-presentations of an identical message. The outlet re-creates the toast
2598
+ * element whenever it changes, which is what makes a screen reader announce the same text again. Starts at 0 and only grows.
2599
+ */
2600
+ readonly repeatTick: import("@angular/core").WritableSignal<number>;
2542
2601
  /** How many toasts are waiting behind the one on screen (queue mode). */
2543
2602
  readonly queuedCount: import("@angular/core").WritableSignal<number>;
2544
2603
  /** Default for `ToastOptions.queue`: new toasts wait for the one on screen instead of replacing it. Set with `provideForgerouteToast({ queue: true })` or `<ui-toast [queue]="true" />`. */
@@ -2630,6 +2689,8 @@ export declare class ToastComponent {
2630
2689
  readonly queueLabel: import("@angular/core").InputSignal<string>;
2631
2690
  /** A toast button was used (also after its own `onAction`). */
2632
2691
  readonly action: import("@angular/core").OutputEmitterRef<ToastActionEvent>;
2692
+ /** One entry that changes with every `repeat: true` toast: the @for re-creates the toast element, so identical text is announced again. */
2693
+ protected readonly repeatKeys: import("@angular/core").Signal<number[]>;
2633
2694
  protected readonly isRich: import("@angular/core").Signal<boolean>;
2634
2695
  protected readonly countdownPct: import("@angular/core").Signal<number>;
2635
2696
  protected readonly countdownText: import("@angular/core").Signal<string>;
@@ -2642,6 +2703,7 @@ export declare class ToastComponent {
2642
2703
  */
2643
2704
  private readonly _adoptedMessage;
2644
2705
  protected readonly adopted: import("@angular/core").Signal<boolean>;
2706
+ private _lastRepeatTick;
2645
2707
  private _wasWaiting;
2646
2708
  private _hover;
2647
2709
  private _focus;
@@ -3154,7 +3216,7 @@ export declare class CheckboxComponent implements ControlValueAccessor, Validato
3154
3216
  * 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.
3155
3217
  * Default null: plain label text, exactly as before. Single mode only.
3156
3218
  */
3157
- readonly headingLevel: import("@angular/core").InputSignal<1 | 2 | 3 | 4 | 5 | 6 | null>;
3219
+ readonly headingLevel: import("@angular/core").InputSignal<2 | 1 | 5 | 3 | 4 | 6 | null>;
3158
3220
  readonly indeterminate: import("@angular/core").InputSignal<boolean>;
3159
3221
  readonly checked: import("@angular/core").ModelSignal<boolean>;
3160
3222
  /**
@@ -3378,6 +3440,8 @@ export declare class ToggleComponent implements ControlValueAccessor {
3378
3440
  readonly ariaLabel: import("@angular/core").InputSignal<string>;
3379
3441
  /** Id of another element that describes the switch (e.g. a description rendered elsewhere); announced after the hint. Absent when empty. */
3380
3442
  readonly ariaDescribedBy: import("@angular/core").InputSignal<string>;
3443
+ /** `data-testid` put on the inner `<input role="switch">` (the host keeps its own attributes), so e2e can target the switch directly. Absent when empty. */
3444
+ readonly inputTestId: import("@angular/core").InputSignal<string>;
3381
3445
  /** Whether the switch is on. Two-way: `[(checked)]`. */
3382
3446
  readonly checked: import("@angular/core").ModelSignal<boolean>;
3383
3447
  /** Public so a host template can bind `[disabled]` (a protected input fails strict template type-checking, TS2445). */
@@ -3420,6 +3484,11 @@ export declare class ToggleComponent implements ControlValueAccessor {
3420
3484
  "required": false;
3421
3485
  "isSignal": true;
3422
3486
  };
3487
+ "inputTestId": {
3488
+ "alias": "inputTestId";
3489
+ "required": false;
3490
+ "isSignal": true;
3491
+ };
3423
3492
  "checked": {
3424
3493
  "alias": "checked";
3425
3494
  "required": false;
@@ -3869,6 +3938,11 @@ export interface RadioOption {
3869
3938
  disabled?: boolean;
3870
3939
  /** `data-testid` of this option's native radio input (e.g. for end-to-end tests); none when omitted. */
3871
3940
  testId?: string;
3941
+ /**
3942
+ * Library source 2026-11-04, not yet published. Icon drawn in front of the option's label: a `<ui-icon>` key (`cup`, `wrench`, ...) or a raw SVG
3943
+ * path. Decorative (`aria-hidden`); none when omitted.
3944
+ */
3945
+ icon?: string;
3872
3946
  }
3873
3947
  /**
3874
3948
  * Group of native radio buttons inside a `<fieldset>` (+ `<legend>` = `label`), a ControlValueAccessor (string value, `''`
@@ -4065,7 +4139,7 @@ export declare class PhoneNumberPickerComponent {
4065
4139
  protected readonly modeCtl: FormControl<string>;
4066
4140
  protected readonly zipCtl: FormControl<string>;
4067
4141
  protected readonly areaCtl: FormControl<string>;
4068
- protected readonly step: import("@angular/core").WritableSignal<1 | 2 | 3>;
4142
+ protected readonly step: import("@angular/core").WritableSignal<2 | 1 | 3>;
4069
4143
  protected readonly mode: import("@angular/core").WritableSignal<PhoneNumberSearchMode>;
4070
4144
  private readonly _zip;
4071
4145
  private readonly _area;
@@ -4181,7 +4255,7 @@ export declare class ButtonComponent {
4181
4255
  * `ghost-start`: a ghost button for list / section toggles - a full-width row with its content aligned to the start, transparent
4182
4256
  * background, hover tint and the normal focus ring. Pair it with `ariaExpanded` / `ariaPressed`; the label may contain a heading element.
4183
4257
  */
4184
- readonly variant: import("@angular/core").InputSignal<"link" | "icon" | "warning" | "danger" | "primary" | "secondary" | "ghost" | "ghost-start" | "tab" | "icon-danger">;
4258
+ readonly variant: import("@angular/core").InputSignal<"link" | "primary" | "secondary" | "danger" | "warning" | "icon" | "ghost" | "ghost-start" | "tab" | "icon-danger">;
4185
4259
  /** 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`). */
4186
4260
  readonly routerLink: import("@angular/core").InputSignal<string | readonly unknown[] | null>;
4187
4261
  /** Query params of the `routerLink` (e.g. `{ section: 'deal-defaults' }`). */
@@ -4202,7 +4276,7 @@ export declare class ButtonComponent {
4202
4276
  */
4203
4277
  readonly href: import("@angular/core").InputSignal<string | null>;
4204
4278
  /** Where to open the `href` (`_blank` = a new tab). */
4205
- readonly target: import("@angular/core").InputSignal<"_self" | "_blank" | "_parent" | "_top" | null>;
4279
+ readonly target: import("@angular/core").InputSignal<"_blank" | "_self" | "_parent" | "_top" | null>;
4206
4280
  /** `rel` of the `href` link. A `_blank` target always gets `noopener noreferrer` added. */
4207
4281
  readonly rel: import("@angular/core").InputSignal<string | null>;
4208
4282
  /** The href when it is allowed (http, https, mailto, tel, sms or a relative URL), else null. */
@@ -4227,7 +4301,7 @@ export declare class ButtonComponent {
4227
4301
  readonly color: import("@angular/core").InputSignal<string | undefined>;
4228
4302
  readonly active: import("@angular/core").InputSignal<boolean>;
4229
4303
  readonly size: import("@angular/core").InputSignal<"sm" | "md" | "lg" | "xs">;
4230
- readonly type: import("@angular/core").InputSignal<"button" | "reset" | "submit">;
4304
+ readonly type: import("@angular/core").InputSignal<"reset" | "submit" | "button">;
4231
4305
  readonly disabled: import("@angular/core").InputSignal<boolean>;
4232
4306
  readonly loading: import("@angular/core").InputSignal<boolean>;
4233
4307
  readonly fullWidth: import("@angular/core").InputSignal<boolean>;
@@ -4236,6 +4310,14 @@ export declare class ButtonComponent {
4236
4310
  readonly ariaPressed: import("@angular/core").InputSignal<boolean | undefined>;
4237
4311
  /** Id of the element that describes this button (an error or hint rendered next to it), e.g. `<ui-error errorId="x">`. Absent when empty. */
4238
4312
  readonly ariaDescribedBy: import("@angular/core").InputSignal<string | undefined>;
4313
+ private readonly _hostEl;
4314
+ /**
4315
+ * Library source 2026-11-04, not yet published. Puts the keyboard focus on the inner native control (the `<button>`, or the `<a>` of a
4316
+ * `routerLink` / `href` button): `buttonRef.focus()` via `viewChild(ButtonComponent)`. Same options as the DOM method (`{ preventScroll: true }`).
4317
+ * Safe at any time: before the view exists, or while the button is `disabled` / `loading` (a disabled `<button>` cannot take focus; the
4318
+ * disabled-link `<span>` is not focusable), it does nothing and never throws.
4319
+ */
4320
+ focus(options?: FocusOptions): void;
4239
4321
  constructor();
4240
4322
  _footerLeft?: string;
4241
4323
  _footerRight?: string;
@@ -4446,11 +4528,26 @@ export declare class PillTabsComponent {
4446
4528
  /** 'vertical' stacks the tabs in a column (Up/Down arrows move between them, `aria-orientation="vertical"`). Default 'horizontal' = unchanged. */
4447
4529
  readonly orientation: import("@angular/core").InputSignal<"vertical" | "horizontal">;
4448
4530
  protected readonly vertical: () => boolean;
4531
+ /**
4532
+ * (library source 2026-11-04, not yet published) Associate the tabs with their panels: every tab gets
4533
+ * `aria-controls="<name>-panel-<key>"`, the id a `uiTabPanel` directive gives its element (see `PillTabPanelDirective`).
4534
+ * Default false = no `aria-controls` at all (unchanged markup). Turn it on only when every tab has a `uiTabPanel`
4535
+ * element in the page, otherwise `aria-controls` would point at a missing id. The tab ids themselves are unchanged
4536
+ * and always `<name>-<key>` (see `pillTabId`).
4537
+ *
4538
+ * Id collision: a tab whose KEY is `panel-x` has the id `<name>-panel-x`, which is also the panel id for key `x`. Avoid keys that start with
4539
+ * `panel-` when this is on; in development mode a `console.warn` names such a key.
4540
+ */
4541
+ readonly controlsPanels: import("@angular/core").InputSignal<boolean>;
4449
4542
  readonly tabChange: import("@angular/core").OutputEmitterRef<string>;
4450
4543
  /** True while pills are hidden past the start / end edge of the scroll area (drives the fade hints). */
4451
4544
  protected readonly canScrollStart: import("@angular/core").WritableSignal<boolean>;
4452
4545
  protected readonly canScrollEnd: import("@angular/core").WritableSignal<boolean>;
4453
4546
  constructor();
4547
+ /** Id of the tab button for [key] (`<name>-<key>`, the exported `pillTabId`). */
4548
+ protected tabId(key: string): string;
4549
+ /** Id of the panel [key] controls (`<name>-panel-<key>`, the exported `pillTabPanelId`). */
4550
+ protected panelId(key: string): string;
4454
4551
  protected updateOverflow(): void;
4455
4552
  select(key: string): void;
4456
4553
  /** Roving tabindex — the selected tab (or the first enabled one when none is selected) is tabbable. */
@@ -4488,10 +4585,80 @@ export declare class PillTabsComponent {
4488
4585
  "required": false;
4489
4586
  "isSignal": true;
4490
4587
  };
4588
+ "controlsPanels": {
4589
+ "alias": "controlsPanels";
4590
+ "required": false;
4591
+ "isSignal": true;
4592
+ };
4491
4593
  }, {
4492
4594
  "tabChange": "tabChange";
4493
4595
  }, never, never, true, never>;
4494
4596
  }
4597
+ /** Id of the tab button `ui-pill-tabs` renders for [key] when its `name` input is [name] (always `<name>-<key>`). */
4598
+ export declare function pillTabId(name: string, key: string): string;
4599
+ /** Id a `uiTabPanel` element gets, and the id every tab's `aria-controls` points at when `controlsPanels` is on: `<name>-panel-<key>`. */
4600
+ export declare function pillTabPanelId(name: string, key: string): string;
4601
+ /**
4602
+ * (library source 2026-11-04, not yet published) The panel that belongs to one `ui-pill-tabs` tab: a correct
4603
+ * WAI-ARIA tablist / tabpanel association with the smallest possible markup.
4604
+ *
4605
+ * ```html
4606
+ * <ui-pill-tabs name="billing" [tabs]="tabs" [activeKey]="tab()" [controlsPanels]="true" (tabChange)="tab.set($event)" />
4607
+ * <section uiTabPanel="invoices" tabsName="billing" [activeKey]="tab()"> ... </section>
4608
+ * <section uiTabPanel="payments" tabsName="billing" [activeKey]="tab()"> ... </section>
4609
+ * ```
4610
+ *
4611
+ * The host element gets `role="tabpanel"`, `id="<tabsName>-panel-<key>"` and `aria-labelledby="<tabsName>-<key>"` (the tab button).
4612
+ * - `uiTabPanel` the key of the tab this panel belongs to (required, the same `key` as in the tabs list).
4613
+ * - `tabsName` the `name` input of the `ui-pill-tabs` (required; give the tabs a fixed `name` so the ids are predictable).
4614
+ * - `activeKey` the tabs' active key. When given (not null), the panel gets the `hidden` attribute while another tab is active
4615
+ * (the panels stay in the DOM, so their state survives a tab change). Leave it unset when the page renders only the
4616
+ * active panel itself (`@if`), then no `hidden` attribute is ever set.
4617
+ * - `tabbable` default false. true adds `tabindex="0"` so a panel without any focusable content can be reached by keyboard
4618
+ * (WAI-ARIA tabs pattern).
4619
+ *
4620
+ * Id collision: ids are plain strings, so a tab whose KEY is `panel-x` has the tab id `<name>-panel-x`, which is the same string as the panel id of the
4621
+ * key `x`. Do not use keys that start with `panel-` together with `controlsPanels` (`ui-pill-tabs` logs a `console.warn` for such a key in development mode).
4622
+ *
4623
+ * Note: the `hidden` attribute loses against an author rule such as `display: flex` on the same element; put such layout on an
4624
+ * inner element, or style `[hidden] { display: none }`.
4625
+ */
4626
+ export declare class PillTabPanelDirective {
4627
+ /** Key of the tab this panel belongs to. */
4628
+ readonly key: import("@angular/core").InputSignal<string>;
4629
+ /** `name` of the `ui-pill-tabs` this panel belongs to. */
4630
+ readonly tabsName: import("@angular/core").InputSignal<string>;
4631
+ /** Active key of the tabs; the panel is `hidden` while it is another key. null (default) = never hidden by this directive. */
4632
+ readonly activeKey: import("@angular/core").InputSignal<string | null>;
4633
+ /** Makes the panel itself a Tab stop (for panels with no focusable content). Default false. */
4634
+ readonly tabbable: import("@angular/core").InputSignal<boolean>;
4635
+ protected panelId(): string;
4636
+ protected tabId(): string;
4637
+ protected isHidden(): boolean;
4638
+ static ɵfac: i0.ɵɵFactoryDeclaration<PillTabPanelDirective, never>;
4639
+ static ɵdir: i0.ɵɵDirectiveDeclaration<PillTabPanelDirective, "[uiTabPanel]", never, {
4640
+ "key": {
4641
+ "alias": "uiTabPanel";
4642
+ "required": true;
4643
+ "isSignal": true;
4644
+ };
4645
+ "tabsName": {
4646
+ "alias": "tabsName";
4647
+ "required": true;
4648
+ "isSignal": true;
4649
+ };
4650
+ "activeKey": {
4651
+ "alias": "activeKey";
4652
+ "required": false;
4653
+ "isSignal": true;
4654
+ };
4655
+ "tabbable": {
4656
+ "alias": "tabbable";
4657
+ "required": false;
4658
+ "isSignal": true;
4659
+ };
4660
+ }, {}, never, never, true, never>;
4661
+ }
4495
4662
  export interface ContactLookup {
4496
4663
  id: string;
4497
4664
  name: string;
@@ -4678,7 +4845,7 @@ export declare class BulkMessagePanelComponent {
4678
4845
  readonly sending: import("@angular/core").InputSignal<boolean>;
4679
4846
  readonly closed: import("@angular/core").OutputEmitterRef<void>;
4680
4847
  readonly send: import("@angular/core").OutputEmitterRef<BulkMessageSendEvent>;
4681
- readonly channel: import("@angular/core").WritableSignal<"email" | "text">;
4848
+ readonly channel: import("@angular/core").WritableSignal<"text" | "email">;
4682
4849
  private readonly _subject;
4683
4850
  private readonly _body;
4684
4851
  get subject(): string;
@@ -4733,7 +4900,7 @@ export declare class ImportSourceGridComponent {
4733
4900
  /** The `value` of the picked source (highlighted). `tile` only: the `card` appearance does not keep a selection. */
4734
4901
  readonly selected: import("@angular/core").InputSignal<string>;
4735
4902
  /** `tile`: the compact buttons of the import window. `card`: one `ui-detail-card` per source with its own select button (used on a page). */
4736
- readonly appearance: import("@angular/core").InputSignal<"card" | "tile">;
4903
+ readonly appearance: import("@angular/core").InputSignal<"tile" | "card">;
4737
4904
  /** `card`: disables every card's button (for example while the page is saving). */
4738
4905
  readonly disabled: import("@angular/core").InputSignal<boolean>;
4739
4906
  /** `card`: the text of each card's button. */
@@ -4930,7 +5097,7 @@ export declare class BankAccountFormComponent implements UiFieldValidity {
4930
5097
  protected readonly accountError: import("@angular/core").Signal<"" | "Account number must be at least 4 digits.">;
4931
5098
  protected readonly confirmError: import("@angular/core").Signal<"" | "Account numbers do not match.">;
4932
5099
  /** First reason the form cannot be submitted ('' when it can). */
4933
- readonly errorMessage: import("@angular/core").Signal<"" | "Account holder name is required." | "Routing number is required." | "Routing number must be 9 digits." | "Account number is required." | "Account number must be at least 4 digits." | "Confirm account number is required." | "Account numbers do not match." | "Select a valid account type." | "Select a valid holder type." | "You must authorize ACH debits to continue.">;
5100
+ readonly errorMessage: import("@angular/core").Signal<"" | "Routing number must be 9 digits." | "Account number must be at least 4 digits." | "Account numbers do not match." | "Account holder name is required." | "Routing number is required." | "Account number is required." | "Confirm account number is required." | "Select a valid account type." | "Select a valid holder type." | "You must authorize ACH debits to continue.">;
4934
5101
  /** True while the form cannot be submitted (`UiFieldValidity`). */
4935
5102
  readonly invalid: import("@angular/core").Signal<boolean>;
4936
5103
  /** True when the form can be submitted (ignores `disabled` / `busy`). */
@@ -4999,7 +5166,11 @@ export interface ActiveConfirm {
4999
5166
  /** Optional bullet list rendered under the message (plain text). */
5000
5167
  details: string[];
5001
5168
  }
5002
- export declare class ConfirmService {
5169
+ export declare class ConfirmService implements OnDestroy {
5170
+ private readonly _appRef;
5171
+ private readonly _envInjector;
5172
+ private readonly _doc;
5173
+ private readonly _browser;
5003
5174
  private _open;
5004
5175
  private _active;
5005
5176
  private _resolve;
@@ -5013,8 +5184,24 @@ export declare class ConfirmService {
5013
5184
  */
5014
5185
  private readonly _outlets;
5015
5186
  readonly primaryOutlet: import("@angular/core").Signal<object>;
5187
+ /**
5188
+ * The outlet this service created itself because `confirm()` was called while no `<ui-confirm-outlet>` existed (a page without a
5189
+ * `ui-data-table` and without a hand-placed outlet). Null while a template-placed outlet exists, before the first such confirm, and
5190
+ * on the server. Library source 2026-11-04, not yet published.
5191
+ */
5192
+ private _auto;
5193
+ /** True when a template-placed outlet appeared while the auto outlet's dialog was open: the auto outlet is removed once that dialog closes. */
5194
+ private _retireAutoOnDismiss;
5016
5195
  registerOutlet(outlet: object): void;
5017
5196
  unregisterOutlet(outlet: object): void;
5197
+ ngOnDestroy(): void;
5198
+ /**
5199
+ * Makes sure some outlet exists to render the dialog. Template-placed outlets (data-table, app-shell, a hand-placed
5200
+ * `<ui-confirm-outlet />`) are used as they are; only when there is none is one outlet created and attached to `document.body`
5201
+ * (reused for later confirms, removed when the service is destroyed or a template-placed outlet appears). Does nothing without a DOM (SSR).
5202
+ */
5203
+ private _ensureOutlet;
5204
+ private _destroyAuto;
5018
5205
  confirm(config: {
5019
5206
  title: string;
5020
5207
  message: string;
@@ -5069,12 +5256,19 @@ export declare class EmptyStateComponent {
5069
5256
  }, {}, never, ["*"], true, never>;
5070
5257
  }
5071
5258
  export declare class ErrorStateComponent {
5259
+ /** Optional bold heading line above the message (e.g. "Unable to load application"). Empty = no heading. */
5260
+ readonly title: import("@angular/core").InputSignal<string>;
5072
5261
  readonly message: import("@angular/core").InputSignal<string>;
5073
5262
  readonly retryLabel: import("@angular/core").InputSignal<string>;
5074
5263
  readonly retrying: import("@angular/core").InputSignal<boolean>;
5075
5264
  readonly retry: import("@angular/core").OutputEmitterRef<void>;
5076
5265
  static ɵfac: i0.ɵɵFactoryDeclaration<ErrorStateComponent, never>;
5077
5266
  static ɵcmp: i0.ɵɵComponentDeclaration<ErrorStateComponent, "ui-error-state", never, {
5267
+ "title": {
5268
+ "alias": "title";
5269
+ "required": false;
5270
+ "isSignal": true;
5271
+ };
5078
5272
  "message": {
5079
5273
  "alias": "message";
5080
5274
  "required": false;
@@ -5161,6 +5355,12 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
5161
5355
  * Meant for a short mark of 1-3 characters.
5162
5356
  */
5163
5357
  readonly prefix: import("@angular/core").InputSignal<string>;
5358
+ /**
5359
+ * Library source 2026-11-04, not yet published. An optional icon at the left inside the field: a `<ui-icon>` key, e.g. `leadingIcon="search"` for a search field.
5360
+ * Decorative (`aria-hidden`, no pointer events, not part of the value), so give the field a `label` or `ariaLabel`. The input's left padding grows to
5361
+ * make room (36px; with a `prefix` the mark moves right of the icon). An unknown key or empty (default) draws nothing and changes nothing.
5362
+ */
5363
+ readonly leadingIcon: import("@angular/core").InputSignal<string>;
5164
5364
  /**
5165
5365
  * `type="password"` only: puts an eye button inside the field, at its right end, that shows / hides the typed text (the eye with a slash
5166
5366
  * means "hidden again"). Per field, starts hidden; the button is a toggle (`aria-pressed`) named "Show password". Ignored for other types.
@@ -5173,7 +5373,7 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
5173
5373
  readonly passwordRequirements: import("@angular/core").InputSignal<boolean>;
5174
5374
  /** Rules for `passwordRequirements`; default = the library's five rules (8+ characters, upper, lower, digit, special). */
5175
5375
  readonly passwordRules: import("@angular/core").InputSignal<readonly PasswordRule[] | undefined>;
5176
- readonly type: import("@angular/core").InputSignal<"number" | "email" | "text" | "tel" | "password" | "url">;
5376
+ readonly type: import("@angular/core").InputSignal<"number" | "text" | "email" | "password" | "tel" | "url">;
5177
5377
  readonly maxlength: import("@angular/core").InputSignal<number | undefined>;
5178
5378
  readonly required: import("@angular/core").InputSignal<boolean>;
5179
5379
  readonly autocomplete: import("@angular/core").InputSignal<string>;
@@ -5182,7 +5382,7 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
5182
5382
  * `search`, `text`, `none`). Empty (default) = the browser's default for the field, except `type="tel"`, which keeps `tel`.
5183
5383
  * It only picks the keyboard; it does not restrict what can be typed or pasted.
5184
5384
  */
5185
- readonly inputmode: import("@angular/core").InputSignal<"" | "none" | "email" | "search" | "text" | "numeric" | "tel" | "url" | "decimal">;
5385
+ readonly inputmode: import("@angular/core").InputSignal<"" | "none" | "text" | "email" | "search" | "tel" | "url" | "decimal" | "numeric">;
5186
5386
  readonly readonly: import("@angular/core").InputSignal<boolean>;
5187
5387
  readonly hint: import("@angular/core").InputSignal<string>;
5188
5388
  /** 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. */
@@ -5240,15 +5440,21 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
5240
5440
  protected readonly disabled: import("@angular/core").Signal<boolean>;
5241
5441
  protected readonly _value: import("@angular/core").WritableSignal<string>;
5242
5442
  private readonly _reveal;
5243
- /** Left padding that makes room for the prefix (its width in `ch` plus the field's own 12px and a 6px gap); none without a prefix. */
5443
+ /** Path of the leading icon, or null when `leadingIcon` is empty or not a known icon key. */
5444
+ protected readonly _leadingD: import("@angular/core").Signal<string | null>;
5445
+ /**
5446
+ * Left padding that makes room for the prefix (its width in `ch` plus the field's own 12px and a 6px gap) and/or the leading icon (a 16px icon
5447
+ * plus an 8px gap, so 36px from the edge); none without either.
5448
+ */
5244
5449
  protected readonly _prefixPadding: import("@angular/core").Signal<string | null>;
5450
+ private readonly _fieldEl;
5245
5451
  /** True when the control value is a number: `valueType="number"` on a `type="number"` field. */
5246
5452
  private readonly _numeric;
5247
5453
  /** The native `step` attribute: only for `type="number"` and only for a finite number above 0; otherwise none (the browser's step of 1). */
5248
5454
  protected readonly _stepAttr: import("@angular/core").Signal<string | null>;
5249
5455
  protected readonly _revealable: import("@angular/core").Signal<boolean>;
5250
5456
  protected readonly _shown: import("@angular/core").WritableSignal<boolean>;
5251
- protected readonly _inputType: import("@angular/core").Signal<"number" | "email" | "text" | "tel" | "password" | "url">;
5457
+ protected readonly _inputType: import("@angular/core").Signal<"number" | "text" | "email" | "password" | "tel" | "url">;
5252
5458
  protected readonly _eyePath: string;
5253
5459
  protected readonly _eyeOffPath: string;
5254
5460
  protected readonly _showRequirements: import("@angular/core").Signal<boolean>;
@@ -5267,6 +5473,12 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
5267
5473
  protected readonly _activeError: import("@angular/core").Signal<string>;
5268
5474
  protected readonly _inputId: string;
5269
5475
  private static readonly _EMAIL_RE;
5476
+ /**
5477
+ * Library source 2026-11-04, not yet published. Puts the keyboard focus on the inner `<input>` (e.g. after a panel opens or a search is cleared):
5478
+ * `fieldRef.focus()` via `viewChild(TextInputComponent)`. Same options as the DOM method (`{ preventScroll: true }`). Safe at any time: before the
5479
+ * view exists, or on a disabled field, it does nothing and never throws.
5480
+ */
5481
+ focus(options?: FocusOptions): void;
5270
5482
  private _onChange;
5271
5483
  private _onTouched;
5272
5484
  private _onValidatorChange;
@@ -5327,6 +5539,11 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
5327
5539
  "required": false;
5328
5540
  "isSignal": true;
5329
5541
  };
5542
+ "leadingIcon": {
5543
+ "alias": "leadingIcon";
5544
+ "required": false;
5545
+ "isSignal": true;
5546
+ };
5330
5547
  "revealable": {
5331
5548
  "alias": "revealable";
5332
5549
  "required": false;
@@ -5584,6 +5801,13 @@ export declare class TextareaInputComponent implements ControlValueAccessor, Val
5584
5801
  validate(control: AbstractControl): ValidationErrors | null;
5585
5802
  registerOnValidatorChange(fn: () => void): void;
5586
5803
  protected readonly _inputId: string;
5804
+ private readonly _hostEl;
5805
+ /**
5806
+ * Library source 2026-11-04, not yet published. Puts the keyboard focus on the inner native `<textarea>` (`ref.focus()` via `viewChild`).
5807
+ * Same options as the DOM method (`{ preventScroll: true }`). Safe at any time: before the view exists, or on a disabled field, it does
5808
+ * nothing and never throws.
5809
+ */
5810
+ focus(options?: FocusOptions): void;
5587
5811
  private _onChange;
5588
5812
  private _onTouched;
5589
5813
  writeValue(val: string | null): void;
@@ -7056,7 +7280,7 @@ export declare class FormSectionComponent {
7056
7280
  }, {}, never, ["*"], true, never>;
7057
7281
  }
7058
7282
  export declare class FormRowComponent {
7059
- readonly cols: import("@angular/core").InputSignal<1 | 2 | 3 | 4>;
7283
+ readonly cols: import("@angular/core").InputSignal<2 | 1 | 3 | 4>;
7060
7284
  static ɵfac: i0.ɵɵFactoryDeclaration<FormRowComponent, never>;
7061
7285
  static ɵcmp: i0.ɵɵComponentDeclaration<FormRowComponent, "ui-form-row", never, {
7062
7286
  "cols": {
@@ -7112,6 +7336,16 @@ export declare class FormColSpanDirective {
7112
7336
  * badge="Archived" badgeVariant="gray" [alwaysShowBadge]="true">
7113
7337
  * <ui-button list-item-action variant="icon" ariaLabel="Remove" (click)="remove(d)">…</ui-button>
7114
7338
  * </ui-list-item>
7339
+ *
7340
+ * Library source 2026-11-04, not yet published: `[disabled]` (aria-disabled, not focusable, never emits `select`, non-colour cue), `[busy]`
7341
+ * (aria-busy, spinner, presses ignored) and a leading image slot, `<img list-item-image>` / `<ui-image list-item-image>`, rendered in front of
7342
+ * the text and instead of the icon tile (clicks on it select a plain row; on a radio / checkbox row they do not, because the image sits outside
7343
+ * the label). An interactive image (`<ui-image list-item-image [interactive]="true" (activate)=...>`) inside a plain pressable row: a click emits the
7344
+ * image's `activate` AND selects the row (the click bubbles); Enter / Space on the image emit `activate` only (the row's key handler ignores keys
7345
+ * whose target is not the row itself). Row-end actions stay in `list-item-action`.
7346
+ * <ui-list-item [title]="p.name" [details]="[p.price]" [disabled]="p.soldOut" [busy]="adding() === p.id" (select)="add(p)">
7347
+ * <ui-image list-item-image [src]="p.photo" [alt]="p.name" width="48px" height="48px" fit="cover" radius="md" />
7348
+ * </ui-list-item>
7115
7349
  */
7116
7350
  /** One secondary line under the title: plain text, or text with a small icon and a tone (`danger` red, `warning` amber). */
7117
7351
  export type ListItemDetail = string | {
@@ -7121,7 +7355,8 @@ export type ListItemDetail = string | {
7121
7355
  };
7122
7356
  /** Colour of the optional leading icon tile. */
7123
7357
  export type ListItemIconColor = 'slate' | 'amber' | 'red' | 'blue' | 'green' | 'purple' | 'teal' | 'orange';
7124
- export declare class ListItemComponent {
7358
+ export declare class ListItemComponent implements AfterContentChecked {
7359
+ private readonly host;
7125
7360
  /** Show a radio button, checkbox, or nothing on the left. */
7126
7361
  readonly leading: import("@angular/core").InputSignal<"none" | "radio" | "checkbox">;
7127
7362
  /** `name` attribute for the radio/checkbox (groups radios together). */
@@ -7148,7 +7383,24 @@ export declare class ListItemComponent {
7148
7383
  * Rows with `[interactive]="false"` always wrap (new in 2026-10-19, nothing to preserve).
7149
7384
  */
7150
7385
  readonly wrapText: import("@angular/core").InputSignal<boolean>;
7386
+ /**
7387
+ * Library source 2026-11-04, not yet published. `true` = the row cannot be used right now: the native radio / checkbox is `disabled` (that carries
7388
+ * the state for assistive tech), a plain pressable row (`role="button"`) gets `aria-disabled="true"` and loses its `tabindex` (not a tab stop). A row
7389
+ * without a role (radio / checkbox row wrapper, non-interactive row) gets NO `aria-disabled` (it is not valid on a role-less div); it only
7390
+ * gets the classes. Clicks, Enter and Space never emit `select`, and the row looks disabled without relying on colour alone (dimmed, muted
7391
+ * surface, `not-allowed` cursor, a dashed outline on a bordered card). Projected row-end actions (`list-item-action`) are NOT disabled by this
7392
+ * input; disable them yourself. Default `false` = unchanged.
7393
+ */
7394
+ readonly disabled: import("@angular/core").InputSignal<boolean>;
7395
+ /**
7396
+ * Library source 2026-11-04, not yet published. `true` = the row is working on a request: `aria-busy="true"`, a small spinner (decorative)
7397
+ * at the row end, and presses (click, Enter, Space, radio / checkbox change) are ignored: `select` never emits and a radio / checkbox keeps
7398
+ * its state (the click is cancelled, so a sibling radio of the same `name` stays checked too; arrow keys on a busy radio are blocked).
7399
+ * The row stays focusable. Default `false` = unchanged.
7400
+ */
7401
+ readonly busy: import("@angular/core").InputSignal<boolean>;
7151
7402
  get _borderedClass(): boolean;
7403
+ get _disabledClass(): boolean;
7152
7404
  /** Primary label. */
7153
7405
  readonly title: import("@angular/core").InputSignal<string>;
7154
7406
  /** Badge shown next to the title — only visible when the item is checked, unless `alwaysShowBadge` is set. */
@@ -7169,6 +7421,21 @@ export declare class ListItemComponent {
7169
7421
  readonly select: import("@angular/core").OutputEmitterRef<void>;
7170
7422
  /** A plain interactive row (no radio/checkbox) is itself clickable: click, Enter or Space emit `select`. */
7171
7423
  protected readonly pressable: () => boolean;
7424
+ /**
7425
+ * True while the leading image slot (`<img list-item-image>` / any element with the `list-item-image` attribute) holds content.
7426
+ * The slot is projected, so this is read from the DOM after every content check; the icon tile is not rendered while it is true.
7427
+ */
7428
+ protected readonly hasImage: import("@angular/core").WritableSignal<boolean>;
7429
+ ngAfterContentChecked(): void;
7430
+ /**
7431
+ * Radio / checkbox click while busy or disabled: cancelled, so the browser restores the checkedness of the clicked input AND of the other radios of
7432
+ * the same `name` group (clicking or arrowing onto this radio would otherwise uncheck the sibling that the model still holds as checked).
7433
+ */
7434
+ protected onInputClick(e: Event): void;
7435
+ /** Arrow keys on a busy / disabled radio would move the selection to a sibling of the group: blocked. (Arriving at it from a sibling is stopped by `onInputClick`.) */
7436
+ protected onInputKey(e: KeyboardEvent): void;
7437
+ /** Radio / checkbox change: never while disabled (the input is disabled anyway); ignored while busy. Safety net after `onInputClick`: the input is put back to `checked`. */
7438
+ protected onInputChange(e: Event): void;
7172
7439
  protected onRowClick(e: Event): void;
7173
7440
  protected onRowKey(e: Event): void;
7174
7441
  protected readonly visibleDetails: () => {
@@ -7223,6 +7490,16 @@ export declare class ListItemComponent {
7223
7490
  "required": false;
7224
7491
  "isSignal": true;
7225
7492
  };
7493
+ "disabled": {
7494
+ "alias": "disabled";
7495
+ "required": false;
7496
+ "isSignal": true;
7497
+ };
7498
+ "busy": {
7499
+ "alias": "busy";
7500
+ "required": false;
7501
+ "isSignal": true;
7502
+ };
7226
7503
  "title": {
7227
7504
  "alias": "title";
7228
7505
  "required": false;
@@ -7255,7 +7532,7 @@ export declare class ListItemComponent {
7255
7532
  };
7256
7533
  }, {
7257
7534
  "select": "select";
7258
- }, never, ["[list-item-action], [li-action]"], true, never>;
7535
+ }, never, ["[list-item-image]", "[list-item-action], [li-action]"], true, never>;
7259
7536
  }
7260
7537
  /** Colour of the priority dot (`high` red, `medium` amber, `low` grey, `blue`, `green`); `none` = no dot. */
7261
7538
  export type CardListIndicator = 'high' | 'medium' | 'low' | 'blue' | 'green' | 'none';
@@ -7650,6 +7927,12 @@ export declare class ListComponent<T = unknown> {
7650
7927
  readonly items: import("@angular/core").InputSignal<readonly T[]>;
7651
7928
  /** `false` (default) renders a `<ul>`; `true` renders an `<ol>` with native numbering (no numbers in the grid layout). */
7652
7929
  readonly ordered: import("@angular/core").InputSignal<boolean>;
7930
+ /**
7931
+ * Library source 2026-11-04, not yet published. `true` = the `<ul>` shows a visible bullet (disc) before every row, for plain text lines such as a
7932
+ * "what will happen" list: `<ui-list [items]="lines" [bulleted]="true" ariaLabel="What will happen" />` (string items render as their text, no template needed).
7933
+ * Still a real `<ul>` with `<li>` rows. Ignored with `[ordered]="true"` (which already has numbers) and in the grid layout. Default `false` = no markers, as before.
7934
+ */
7935
+ readonly bulleted: import("@angular/core").InputSignal<boolean>;
7653
7936
  /** 'list' = one column; 'grid' = wrapping columns of at least `gridMin` px (still a real `<ul>`). */
7654
7937
  readonly layout: import("@angular/core").InputSignal<"list" | "grid">;
7655
7938
  /** Minimum column width in px of the grid layout. */
@@ -7756,6 +8039,11 @@ export declare class ListComponent<T = unknown> {
7756
8039
  "required": false;
7757
8040
  "isSignal": true;
7758
8041
  };
8042
+ "bulleted": {
8043
+ "alias": "bulleted";
8044
+ "required": false;
8045
+ "isSignal": true;
8046
+ };
7759
8047
  "layout": {
7760
8048
  "alias": "layout";
7761
8049
  "required": false;
@@ -8207,9 +8495,9 @@ export declare class ChipGroupComponent {
8207
8495
  readonly spaceAbove: import("@angular/core").InputSignal<"none" | "sm" | "md">;
8208
8496
  /** Space below the chip group. */
8209
8497
  readonly spaceBelow: import("@angular/core").InputSignal<"none" | "sm" | "md">;
8210
- protected readonly _gap: import("@angular/core").Signal<"6px" | "12px" | "8px">;
8211
- protected readonly _spaceAbove: import("@angular/core").Signal<"0" | "6px" | "12px">;
8212
- protected readonly _spaceBelow: import("@angular/core").Signal<"0" | "6px" | "12px">;
8498
+ protected readonly _gap: import("@angular/core").Signal<"8px" | "12px" | "6px">;
8499
+ protected readonly _spaceAbove: import("@angular/core").Signal<"0" | "12px" | "6px">;
8500
+ protected readonly _spaceBelow: import("@angular/core").Signal<"0" | "12px" | "6px">;
8213
8501
  static ɵfac: i0.ɵɵFactoryDeclaration<ChipGroupComponent, never>;
8214
8502
  static ɵcmp: i0.ɵɵComponentDeclaration<ChipGroupComponent, "ui-chip-group", never, {
8215
8503
  "gap": {
@@ -8585,10 +8873,15 @@ export declare class AlertComponent {
8585
8873
  "dismissed": "dismissed";
8586
8874
  }, never, ["*"], true, never>;
8587
8875
  }
8876
+ /**
8877
+ * Every key `<ui-icon>` draws by itself (the data-table action keys such as `view` / `edit` / `call` are accepted too, see `builtInActionIcon`).
8878
+ * Each resolves with `iconPath(key)`. Includes `search`, `cup` (food / drink) and `wrench` (rental / tools), library source 2026-11-04, not yet published.
8879
+ */
8880
+ export declare const ICON_NAMES: readonly string[];
8588
8881
  /** The SVG path (24×24 stroke icon) for an icon key, or undefined when the key is unknown. */
8589
8882
  export declare function iconPath(name: string): string | undefined;
8590
8883
  /** Keys with an icon of their own (the data-table action keys are accepted too — see `builtInActionIcon`). */
8591
- export type IconName = 'add' | 'close' | 'check' | 'upload' | 'image' | 'chevron-up' | 'chevron-down' | 'arrow-left' | 'bell' | 'print' | 'lock' | 'shield' | 'arrow-up' | 'arrow-down' | 'arrow-right' | 'document' | 'grip' | 'card' | 'bank' | 'view' | 'view-off' | 'edit' | 'delete' | 'download' | 'duplicate' | 'archive' | 'restore' | 'share' | 'email' | 'message' | 'call' | 'refund' | 'chevron-right' | 'link' | 'save' | 'chart' | 'clipboard' | 'unlink' | 'send' | 'refresh';
8884
+ export type IconName = 'add' | 'close' | 'check' | 'upload' | 'image' | 'chevron-up' | 'chevron-down' | 'arrow-left' | 'bell' | 'print' | 'lock' | 'shield' | 'arrow-up' | 'arrow-down' | 'arrow-right' | 'document' | 'grip' | 'card' | 'bank' | 'view' | 'view-off' | 'edit' | 'delete' | 'download' | 'duplicate' | 'archive' | 'restore' | 'share' | 'email' | 'message' | 'call' | 'refund' | 'chevron-right' | 'link' | 'save' | 'chart' | 'clipboard' | 'unlink' | 'send' | 'refresh' | 'search' | 'cup' | 'wrench';
8592
8885
  /**
8593
8886
  * A clickable icon. The host passes a key (`name="delete"`) and the library draws that icon; clicking it emits
8594
8887
  * `iconClick`, and the host does the actual work (delete the row, open a panel, …).
@@ -8615,7 +8908,7 @@ export declare class IconComponent {
8615
8908
  readonly ariaLabel: import("@angular/core").InputSignal<string>;
8616
8909
  /** Icon size in px. */
8617
8910
  readonly size: import("@angular/core").InputSignal<number>;
8618
- readonly variant: import("@angular/core").InputSignal<"default" | "danger">;
8911
+ readonly variant: import("@angular/core").InputSignal<"danger" | "default">;
8619
8912
  readonly disabled: import("@angular/core").InputSignal<boolean>;
8620
8913
  /** The host is running the request this icon started: a spinner replaces the picture and the button is disabled (no click) until it is false again. */
8621
8914
  readonly loading: import("@angular/core").InputSignal<boolean>;
@@ -8727,7 +9020,7 @@ export declare class TimelineComponent {
8727
9020
  /** Any CSS length (e.g. `600px`). When set, the list scrolls inside a keyboard-focusable region of at most this height. Empty = no wrapper. */
8728
9021
  readonly maxHeight: import("@angular/core").InputSignal<string>;
8729
9022
  /** `below` (default): the time is under the title / description. `end`: the time sits right-aligned on the title row. */
8730
- readonly timePosition: import("@angular/core").InputSignal<"below" | "end">;
9023
+ readonly timePosition: import("@angular/core").InputSignal<"end" | "below">;
8731
9024
  /**
8732
9025
  * Group the items under a heading per calendar day of `dateTime` ("Today", "Yesterday", "Oct 3", "Oct 3, 2025"). Default false = no headings,
8733
9026
  * DOM unchanged. The given order is kept: consecutive items of one day share a heading, the same day appearing again later starts a new group.
@@ -9250,6 +9543,14 @@ export type ImageAlign = 'start' | 'center' | 'end';
9250
9543
  * - `placeholder` (default true): a neutral icon in the same box when there is no `src` or it fails to load. false renders nothing then.
9251
9544
  * - `priority`: above-the-fold image - loads eagerly with high fetch priority. Otherwise `loading="lazy"` and async decoding.
9252
9545
  * - Outputs `loaded` and `failed`. A new `src` (or a changed `retryKey`) gets a fresh chance to load.
9546
+ * - Library source 2026-11-04, not yet published: `[interactive]="true"` makes the image a button (e.g. a product photo that opens a preview):
9547
+ * the host gets `role="button"`, `tabindex="0"`, a focus ring, and click, Enter or Space emit `(activate)`. Its accessible name is the `alt`
9548
+ * text (also set as `aria-label`), so an interactive image NEEDS a non-empty `alt` (a decorative `alt=""` image would be an unnamed button). Not
9549
+ * interactive (default) = no role, no tabindex, no key handling, no output: exactly as before.
9550
+ * Inside a clickable parent (e.g. a pressable `ui-list-item` row via the `list-item-image` slot) the click bubbles: `activate` fires AND the parent's
9551
+ * own click handling runs (the row is selected). Enter / Space fire `activate` only; the parent's key handlers that require their own element as the
9552
+ * target (`ui-list-item`) ignore them.
9553
+ * <ui-image [src]="p.photo" [alt]="'Open photo of ' + p.name" [interactive]="true" (activate)="preview(p)" />
9253
9554
  */
9254
9555
  export declare class ImageComponent {
9255
9556
  /** Image URL (or data URL). Blank shows the placeholder. */
@@ -9276,8 +9577,15 @@ export declare class ImageComponent {
9276
9577
  readonly priority: import("@angular/core").InputSignal<boolean>;
9277
9578
  /** Bump to retry a failed image with the same `src`. */
9278
9579
  readonly retryKey: import("@angular/core").InputSignal<unknown>;
9580
+ /**
9581
+ * Library source 2026-11-04, not yet published. `true` = the image is a button: `role="button"`, `tabindex="0"`, `aria-label` from `alt`, and click /
9582
+ * Enter / Space emit `activate`. Needs a non-empty `alt` (it is the button's name). Default `false` = a plain image, nothing changes.
9583
+ */
9584
+ readonly interactive: import("@angular/core").InputSignal<boolean>;
9279
9585
  readonly loaded: import("@angular/core").OutputEmitterRef<void>;
9280
9586
  readonly failed: import("@angular/core").OutputEmitterRef<void>;
9587
+ /** Fires (once per press) when an `interactive` image is clicked, or Enter / Space is pressed on it. Never fires when not interactive. */
9588
+ readonly activate: import("@angular/core").OutputEmitterRef<void>;
9281
9589
  protected readonly _failed: import("@angular/core").WritableSignal<boolean>;
9282
9590
  protected readonly _url: import("@angular/core").Signal<string | null>;
9283
9591
  protected readonly radiusCss: import("@angular/core").Signal<string>;
@@ -9289,6 +9597,8 @@ export declare class ImageComponent {
9289
9597
  protected readonly isBlock: import("@angular/core").Signal<boolean>;
9290
9598
  constructor();
9291
9599
  protected _onError(): void;
9600
+ protected onActivate(): void;
9601
+ protected onKey(event: Event): void;
9292
9602
  static ɵfac: i0.ɵɵFactoryDeclaration<ImageComponent, never>;
9293
9603
  static ɵcmp: i0.ɵɵComponentDeclaration<ImageComponent, "ui-image", never, {
9294
9604
  "src": {
@@ -9366,9 +9676,15 @@ export declare class ImageComponent {
9366
9676
  "required": false;
9367
9677
  "isSignal": true;
9368
9678
  };
9679
+ "interactive": {
9680
+ "alias": "interactive";
9681
+ "required": false;
9682
+ "isSignal": true;
9683
+ };
9369
9684
  }, {
9370
9685
  "loaded": "loaded";
9371
9686
  "failed": "failed";
9687
+ "activate": "activate";
9372
9688
  }, never, never, true, never>;
9373
9689
  }
9374
9690
  /** One picture of a `ui-image-gallery`. */
@@ -9587,6 +9903,17 @@ export declare class KpiCardComponent {
9587
9903
  readonly highlight: import("@angular/core").InputSignal<boolean>;
9588
9904
  readonly clickable: import("@angular/core").InputSignal<boolean>;
9589
9905
  readonly valueColor: import("@angular/core").InputSignal<KpiCardValueColor>;
9906
+ /**
9907
+ * (library source 2026-11-04, not yet published) While true the value (and the subtitle, when one is set) are replaced by grey
9908
+ * placeholders and the card is `aria-busy="true"`; assistive tech reads the label followed by the `loadingLabel` text
9909
+ * (visually hidden), never the stale value or subtitle. The card keeps its size: the value placeholder has the value line's box and the
9910
+ * subtitle placeholder is the subtitle's own (transparent) text, so pass the subtitle you will show while loading to keep the height
9911
+ * identical. The progress ring (when there is one) stays visible but is hidden from assistive tech (`aria-hidden="true"` on it) while loading, since its
9912
+ * value belongs to the data that is being replaced. Default false = unchanged. Everything else (icon, ring, `kpi-footer` slot, `clickable`, colours) is unaffected.
9913
+ */
9914
+ readonly loading: import("@angular/core").InputSignal<boolean>;
9915
+ /** What assistive tech hears instead of the value while `loading` (default 'Loading'). */
9916
+ readonly loadingLabel: import("@angular/core").InputSignal<string>;
9590
9917
  /** Card background as any CSS colour (`#fef2f2`, `var(--surface)` …). Empty (default) = white. The text colours do not change, so use a light shade. */
9591
9918
  readonly background: import("@angular/core").InputSignal<string>;
9592
9919
  /** Completed amount shown as a `ui-progress-ring` beside the label. `null` (default) = no ring. */
@@ -9648,6 +9975,16 @@ export declare class KpiCardComponent {
9648
9975
  "required": false;
9649
9976
  "isSignal": true;
9650
9977
  };
9978
+ "loading": {
9979
+ "alias": "loading";
9980
+ "required": false;
9981
+ "isSignal": true;
9982
+ };
9983
+ "loadingLabel": {
9984
+ "alias": "loadingLabel";
9985
+ "required": false;
9986
+ "isSignal": true;
9987
+ };
9651
9988
  "background": {
9652
9989
  "alias": "background";
9653
9990
  "required": false;
@@ -9959,6 +10296,12 @@ export declare function humanReadableMessage(value: unknown): string | null;
9959
10296
  export declare class RadioComponent {
9960
10297
  readonly label: import("@angular/core").InputSignal<string>;
9961
10298
  readonly description: import("@angular/core").InputSignal<string>;
10299
+ /**
10300
+ * Library source 2026-11-04, not yet published. Optional icon drawn in front of the label: a `<ui-icon>` key (`cup`, `wrench`, `card`, ...) or a raw 24x24
10301
+ * stroke SVG path (`M12 5v14 M5 12h14`). Decorative (`aria-hidden`), so the accessible name stays the label. Empty (default), an unknown key or
10302
+ * text that is not a path = nothing is drawn and the DOM is unchanged.
10303
+ */
10304
+ readonly icon: import("@angular/core").InputSignal<string>;
9962
10305
  /** Accessible name when there is no visible `label`. */
9963
10306
  readonly ariaLabel: import("@angular/core").InputSignal<string>;
9964
10307
  /** `data-testid` of the native radio input; none when empty. */
@@ -9975,6 +10318,8 @@ export declare class RadioComponent {
9975
10318
  /** Public so a host template can bind `[disabled]` (a protected input fails strict template type-checking). */
9976
10319
  readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
9977
10320
  protected readonly disabled: import("@angular/core").InputSignal<boolean>;
10321
+ /** Path of the icon: a known icon key, else the text itself when it looks like an SVG path (drawing commands and numbers only), else none. */
10322
+ protected readonly _iconD: import("@angular/core").Signal<string | null>;
9978
10323
  /** Id of the visible label text. Optional: a host (e.g. `ui-radio-group`) can set it to point another element at the label with `aria-labelledby`; a unique id is generated when empty. */
9979
10324
  readonly labelId: import("@angular/core").InputSignal<string>;
9980
10325
  private readonly _generatedLabelId;
@@ -9999,6 +10344,11 @@ export declare class RadioComponent {
9999
10344
  "required": false;
10000
10345
  "isSignal": true;
10001
10346
  };
10347
+ "icon": {
10348
+ "alias": "icon";
10349
+ "required": false;
10350
+ "isSignal": true;
10351
+ };
10002
10352
  "ariaLabel": {
10003
10353
  "alias": "ariaLabel";
10004
10354
  "required": false;
@@ -10417,7 +10767,7 @@ export declare class PdfHotspotComponent {
10417
10767
  /** `ready`: clickable; `blocked`: disabled (a prerequisite is missing); `signed`: shows `image`. */
10418
10768
  readonly state: import("@angular/core").InputSignal<"ready" | "blocked" | "signed">;
10419
10769
  /** `warning` gives the ready state an amber look (e.g. for initials), default is blue. */
10420
- readonly tone: import("@angular/core").InputSignal<"warning" | "primary">;
10770
+ readonly tone: import("@angular/core").InputSignal<"primary" | "warning">;
10421
10771
  /** Text of the ready button (e.g. "Sign Here"). */
10422
10772
  readonly label: import("@angular/core").InputSignal<string>;
10423
10773
  /** Text of the blocked button (e.g. "Add signature above"). */
@@ -10520,6 +10870,9 @@ export declare class PdfHotspotComponent {
10520
10870
  * - `textColor`: the colour of the title, subtitle, chevron and body text (any CSS colour; default: the normal slate colours). Use it for light text on a dark `background`. Text you colour yourself inside the body keeps its own colour.
10521
10871
  * - `<ng-container card-footer>` / `<div card-footer>`: a footer bar under the body (a pager, totals, a link). Hidden while empty or collapsed, 10px 18px padding,
10522
10872
  * a light top line; `footerBackground` colours it (pair it with `headerBackground` to frame the card). In a `fill` card it is pinned to the bottom edge.
10873
+ * - `footerAlign="end"` (library source 2026-11-04, not yet published): turns the `[card-footer]` bar into a right-aligned action row (flex, `justify-content: flex-end`,
10874
+ * 8px gap, wraps on a narrow card) for one or several buttons under the body, e.g. `<ui-button card-footer variant="secondary" size="sm">Open Resident</ui-button>`.
10875
+ * Default `'start'` = the footer is unchanged (block content, left-aligned). Hidden while empty or collapsed in both modes.
10523
10876
  * - The body has built-in padding (16px 18px, matching the header's 18px side padding); there is no padding input.
10524
10877
  * - `collapsible` (default true): a chevron toggle and a clickable header; `[(expanded)]` is two-way.
10525
10878
  * Without a header, or with `collapsible` false, the body is always open.
@@ -10551,7 +10904,7 @@ export declare class DetailCardComponent {
10551
10904
  /** true (default) = the title is displayed in capitals (CSS only); false = shown as written. The text, aria-label and heading name are never changed. */
10552
10905
  readonly uppercaseTitle: import("@angular/core").InputSignal<boolean>;
10553
10906
  /** 1-6 makes the title a real heading for screen readers (role=heading, aria-level); null keeps it plain text. */
10554
- readonly headingLevel: import("@angular/core").InputSignal<1 | 2 | 3 | 4 | 5 | 6 | null>;
10907
+ readonly headingLevel: import("@angular/core").InputSignal<2 | 1 | 5 | 3 | 4 | 6 | null>;
10555
10908
  /** Optional id for the title text; the card is then labelled by it. Without it the title is the card's aria-label. */
10556
10909
  readonly titleId: import("@angular/core").InputSignal<string>;
10557
10910
  /** Accessible name of the card when the header gives none (no header, or no title). A visible title wins; blank = no name. */
@@ -10564,6 +10917,8 @@ export declare class DetailCardComponent {
10564
10917
  readonly headerBackground: import("@angular/core").InputSignal<string>;
10565
10918
  /** Background colour of the footer bar (the `[card-footer]` slot) as any CSS colour. Empty = no colour of its own. */
10566
10919
  readonly footerBackground: import("@angular/core").InputSignal<string>;
10920
+ /** Alignment of the `[card-footer]` content: `'start'` (default, unchanged) or `'end'` = a right-aligned action row with an 8px gap. */
10921
+ readonly footerAlign: import("@angular/core").InputSignal<"end" | "start">;
10567
10922
  /** Text colour as any CSS colour (`#fff`, `var(--on-dark)` …). Empty = the default colours. Colours the title, subtitle, chevron and body text. */
10568
10923
  readonly textColor: import("@angular/core").InputSignal<string>;
10569
10924
  /** false = no header at all (no title, edit button, toggle or divider): the card is only the body, always open. */
@@ -10650,6 +11005,11 @@ export declare class DetailCardComponent {
10650
11005
  "required": false;
10651
11006
  "isSignal": true;
10652
11007
  };
11008
+ "footerAlign": {
11009
+ "alias": "footerAlign";
11010
+ "required": false;
11011
+ "isSignal": true;
11012
+ };
10653
11013
  "textColor": {
10654
11014
  "alias": "textColor";
10655
11015
  "required": false;
@@ -13161,7 +13521,7 @@ export declare class SetupWizardComponent {
13161
13521
  protected customHintId(): string;
13162
13522
  protected readonly importBlocked: import("@angular/core").Signal<boolean>;
13163
13523
  /** 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). */
13164
- protected readonly splitTab: import("@angular/core").WritableSignal<"main" | "extra">;
13524
+ protected readonly splitTab: import("@angular/core").WritableSignal<"extra" | "main">;
13165
13525
  protected readonly splitTabs: import("@angular/core").Signal<{
13166
13526
  key: string;
13167
13527
  label: string;
@@ -15328,7 +15688,7 @@ export declare class PaymentSidePanelComponent {
15328
15688
  private readonly terminalAvailable;
15329
15689
  /** value -> label of every live method the rendered plugins contribute (the first plugin wins a duplicate value). */
15330
15690
  private readonly liveMethods;
15331
- protected readonly kind: import("@angular/core").Signal<"none" | "live" | "terminal" | "manual">;
15691
+ protected readonly kind: import("@angular/core").Signal<"none" | "manual" | "live" | "terminal">;
15332
15692
  private kindOf;
15333
15693
  /** The method list as shown: record-only built-ins (a plugin takes over its own values), plugin extras, and only manual ones while a split is being built. */
15334
15694
  readonly methodList: import("@angular/core").Signal<PaymentMethodOption[]>;