@forgeroute/ui 0.4.76 → 0.4.77

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.76",
3
+ "version": "0.4.77",
4
4
  "peerDependencies": {
5
5
  "@angular/common": ">=22.0.0",
6
6
  "@angular/core": ">=22.0.0",
@@ -196,6 +196,20 @@ export interface ColumnDef {
196
196
  * Example: `{ key: 'name', label: 'Name', starFn: (doc) => doc.isAuthForm ? 'Authorization Form' : null }`
197
197
  */
198
198
  starFn?: (item: any) => string | null | undefined;
199
+ /**
200
+ * Library source 2026-11-05, not yet published. Draws a small decorative icon (16px, `aria-hidden`, currentColor, on the first text line, never shrinks)
201
+ * to the LEFT of the cell text, in desktop cells and in the phone card (title, badge pills, detail rows). Returns a `<ui-icon>` key (see `iconPath()`) or a
202
+ * raw 24x24 stroke SVG path (drawing commands and numbers only, same rule as ui-radio's `icon`); null / undefined / '' / anything else draws nothing.
203
+ * Applies to text, badge, date, phone and number cells; never to avatar-name, link, tags, progress, image, days-ago or actions. The cell's text and the row's
204
+ * accessible name are unchanged (see `iconLabelFn` for meaningful icons). Placed before a `starFn` star.
205
+ * Example: `{ key: 'name', label: 'Name', iconFn: (r) => r.kind === 'rental' ? 'wrench' : 'cup' }`
206
+ */
207
+ iconFn?: (item: any) => string | null | undefined;
208
+ /**
209
+ * Library source 2026-11-05, not yet published. Accessible text for a MEANINGFUL `iconFn` icon: rendered as visually hidden text right after the icon
210
+ * (the icon stays `aria-hidden`). Default (absent / null / '') = the icon is decorative. Ignored when no icon is drawn for the row.
211
+ */
212
+ iconLabelFn?: (item: any) => string | null | undefined;
199
213
  /**
200
214
  * Footer text for this column, from the table's `totalsEndpoint` response (shown only while the table has rows and the totals loaded).
201
215
  * Return null / undefined / '' for an empty footer cell. `cellType: 'number'` columns are right-aligned like their body cells.
@@ -1195,7 +1209,7 @@ export declare class SelectComponent implements ControlValueAccessor, Validator,
1195
1209
  readonly error: import("@angular/core").InputSignal<string>;
1196
1210
  /** Reveal the built-in error messages now (e.g. after a failed Save click), without waiting for blur. */
1197
1211
  readonly showErrors: import("@angular/core").InputSignal<boolean>;
1198
- readonly size: import("@angular/core").InputSignal<"sm" | "default">;
1212
+ readonly size: import("@angular/core").InputSignal<"default" | "sm">;
1199
1213
  readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
1200
1214
  private readonly _cvaDisabled;
1201
1215
  protected readonly disabled: import("@angular/core").Signal<boolean>;
@@ -2114,6 +2128,16 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
2114
2128
  protected onLinkClick(e: MouseEvent, link: ResolvedLink, col: ColumnDef, item: T): void;
2115
2129
  protected getInitials(name: string): string;
2116
2130
  protected isCardOverdue(col: ColumnDef, item: T): boolean;
2131
+ /** Cell types that never get a leading icon: they draw their own leading visual or are not text-like. */
2132
+ private static readonly _NO_ICON_TYPES;
2133
+ /**
2134
+ * Path of the leading icon for a cell (library source 2026-11-05, not yet published): `iconFn` returns a `<ui-icon>` key (known key wins) or a raw
2135
+ * 24x24 stroke path (drawing commands and numbers only, same rule as ui-radio's `icon`); anything else, an empty value, a throwing `iconFn` or a
2136
+ * non-text-like cell type gives null (nothing is drawn).
2137
+ */
2138
+ protected cellIconPath(col: ColumnDef, item: T): string | null;
2139
+ /** Screen-reader text for a meaningful icon (`iconLabelFn`); '' (decorative) when absent, empty, throwing or when no icon is drawn. */
2140
+ protected cellIconLabel(col: ColumnDef, item: T): string;
2117
2141
  /** Renders any non-badge column value as a plain string for the mobile card view. */
2118
2142
  protected cardCellText(col: ColumnDef, item: T): string;
2119
2143
  /** Refresh data rows only — used internally for sort, filter, search, pagination. */
@@ -2352,7 +2376,7 @@ export declare class SidePanelComponent implements OnDestroy {
2352
2376
  readonly cancelLabel: import("@angular/core").InputSignal<string>;
2353
2377
  /** Right-aligned primary action button label. Empty string = hidden. */
2354
2378
  readonly primaryLabel: import("@angular/core").InputSignal<string>;
2355
- readonly primaryVariant: import("@angular/core").InputSignal<"primary" | "danger" | "warning">;
2379
+ readonly primaryVariant: import("@angular/core").InputSignal<"warning" | "danger" | "primary">;
2356
2380
  readonly primaryLoading: import("@angular/core").InputSignal<boolean>;
2357
2381
  readonly primaryDisabled: import("@angular/core").InputSignal<boolean>;
2358
2382
  /** `data-testid` of the Cancel button; none when empty (default). */
@@ -2483,7 +2507,7 @@ export declare class ModalComponent implements OnInit, OnDestroy {
2483
2507
  */
2484
2508
  readonly describedBy: import("@angular/core").InputSignal<string | null>;
2485
2509
  readonly maxWidth: import("@angular/core").InputSignal<string>;
2486
- readonly bodyOverflow: import("@angular/core").InputSignal<"hidden" | "auto" | "visible">;
2510
+ readonly bodyOverflow: import("@angular/core").InputSignal<"hidden" | "visible" | "auto">;
2487
2511
  /** `data-testid` of the dialog element itself (the host `<ui-modal>` is always in the page, the dialog only while open). None when empty. */
2488
2512
  readonly dialogTestId: import("@angular/core").InputSignal<string>;
2489
2513
  /** Hides the header X button (e.g. while a request is running). Escape and a backdrop click still close unless `closable` is false. */
@@ -3300,6 +3324,153 @@ export declare class StarComponent {
3300
3324
  "starClick": "starClick";
3301
3325
  }, never, never, true, never>;
3302
3326
  }
3327
+ /**
3328
+ * Library source 2026-11-05, not yet published.
3329
+ *
3330
+ * Accessible star rating, 1..`max` (default 5). A ControlValueAccessor with a number value (`0` = no rating).
3331
+ *
3332
+ * - Input mode (default): a `<fieldset role="radiogroup">` (+ `<legend>` = `label`) of native radio inputs that share one `name`, so the browser
3333
+ * gives the roving tab stop and ArrowLeft / ArrowRight / ArrowUp / ArrowDown (move + select) for free; Space selects the focused star natively,
3334
+ * Enter selects it too and Home / End select the first / last star (handled here). Each radio is named "1 star", "2 stars", ...
3335
+ * - `readonly`: all `max` stars are drawn (filled up to the value, the rest outlined) as one `role="img"` named "4 stars out of 5" ("No rating" for 0; with a `label`: "Quality: 4 stars out of 5"). No inputs.
3336
+ * - Validation follows `ui-radio-group` (`UiFieldValidity`, `Validator`, `invalidChange`): `required` -> "<label> is required." when the value is 0;
3337
+ * a value that is not a whole number from 0 to `max` -> "Select a valid option."; messages show after the group lost focus or while `[showErrors]="true"`;
3338
+ * a host `[error]` wins. Disabled and readonly are never invalid.
3339
+ * - Stars are gold (same look as `ui-star`, with a darker amber outline so the shape reaches 3:1 against white); empty stars are outlined, so the value never relies on colour alone. 44px touch targets on touch / phones.
3340
+ *
3341
+ * <ui-star-rating label="Quality" [required]="true" [showErrors]="touched()" [(ngModel)]="form.rating" />
3342
+ * <ui-star-rating [readonly]="true" [value]="4" />
3343
+ */
3344
+ export declare class StarRatingComponent implements ControlValueAccessor, Validator, UiFieldValidity {
3345
+ /** Largest rating (number of stars). Default 5; values below 1 or non-integers are clamped to a whole number of at least 1. */
3346
+ readonly max: import("@angular/core").InputSignal<number>;
3347
+ /** Current rating for standalone / readonly use (`[value]="4"`); `0` = none. With forms, the control value wins after it is written. */
3348
+ readonly value: import("@angular/core").InputSignal<number>;
3349
+ readonly label: import("@angular/core").InputSignal<string>;
3350
+ /** Accessible name when there is no visible `label` (default "Rating"). */
3351
+ readonly ariaLabel: import("@angular/core").InputSignal<string>;
3352
+ readonly hint: import("@angular/core").InputSignal<string>;
3353
+ readonly error: import("@angular/core").InputSignal<string>;
3354
+ readonly required: import("@angular/core").InputSignal<boolean>;
3355
+ /** Reveal the built-in error messages now (e.g. after a failed Save click), without waiting for blur. */
3356
+ readonly showErrors: import("@angular/core").InputSignal<boolean>;
3357
+ /** Star size in px (default 24). */
3358
+ readonly size: import("@angular/core").InputSignal<number>;
3359
+ /** Display only: filled stars as one image named "4 stars out of 5"; no inputs, never invalid. */
3360
+ readonly readonly: import("@angular/core").InputSignal<boolean>;
3361
+ /** Native `name` shared by the radios; a unique one is generated when omitted. */
3362
+ readonly name: import("@angular/core").InputSignal<string>;
3363
+ readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
3364
+ private readonly _cvaDisabled;
3365
+ protected readonly disabled: import("@angular/core").Signal<boolean>;
3366
+ /** Emits the new rating when the USER picks a star (not for values the host writes). */
3367
+ readonly valueChange: import("@angular/core").OutputEmitterRef<number>;
3368
+ /** Emits whenever the field becomes invalid / valid. */
3369
+ readonly invalidChange: import("@angular/core").OutputEmitterRef<boolean>;
3370
+ protected readonly _value: import("@angular/core").WritableSignal<number>;
3371
+ protected readonly _max: import("@angular/core").Signal<number>;
3372
+ protected readonly _stars: import("@angular/core").Signal<number[]>;
3373
+ /** Stars drawn filled: the value, kept inside 0..max (an invalid value never overflows the row). */
3374
+ protected readonly _shown: import("@angular/core").Signal<number>;
3375
+ protected readonly _readonlyText: import("@angular/core").Signal<string>;
3376
+ protected readonly _path = "M10 1.5l2.6 5.3 5.9.9-4.25 4.15 1 5.85L10 14.9l-5.25 2.8 1-5.85L1.5 7.7l5.9-.9L10 1.5z";
3377
+ private readonly _generatedName;
3378
+ protected get _name(): string;
3379
+ protected readonly _descId: string;
3380
+ private readonly _host;
3381
+ private readonly _reveal;
3382
+ private readonly _issue;
3383
+ /** True while the value breaks a built-in rule or the host passed an `[error]`. */
3384
+ readonly invalid: import("@angular/core").Signal<boolean>;
3385
+ /** Message of the first broken built-in rule ('' when valid), shown or not. */
3386
+ readonly errorMessage: import("@angular/core").Signal<string>;
3387
+ protected readonly _activeError: import("@angular/core").Signal<string>;
3388
+ private _onValidatorChange;
3389
+ constructor();
3390
+ /** Re-run the form control's validation when a rule input (required, max) changes. */
3391
+ ngOnChanges(): void;
3392
+ validate(control: AbstractControl): ValidationErrors | null;
3393
+ registerOnValidatorChange(fn: () => void): void;
3394
+ private _onChange;
3395
+ private _onTouched;
3396
+ writeValue(val: number | null): void;
3397
+ registerOnChange(fn: (v: number) => void): void;
3398
+ registerOnTouched(fn: () => void): void;
3399
+ setDisabledState(d: boolean): void;
3400
+ private static _norm;
3401
+ protected onSelect(n: number): void;
3402
+ /** Enter selects the focused star (Space and the arrow keys are native radio behaviour); Home / End select the first / last star. */
3403
+ protected onKeydown(event: KeyboardEvent, n: number): void;
3404
+ /** Touched once focus leaves the whole group (moving between its stars does not count). */
3405
+ protected onFocusOut(event: FocusEvent): void;
3406
+ private _check;
3407
+ static ɵfac: i0.ɵɵFactoryDeclaration<StarRatingComponent, never>;
3408
+ static ɵcmp: i0.ɵɵComponentDeclaration<StarRatingComponent, "ui-star-rating", never, {
3409
+ "max": {
3410
+ "alias": "max";
3411
+ "required": false;
3412
+ "isSignal": true;
3413
+ };
3414
+ "value": {
3415
+ "alias": "value";
3416
+ "required": false;
3417
+ "isSignal": true;
3418
+ };
3419
+ "label": {
3420
+ "alias": "label";
3421
+ "required": false;
3422
+ "isSignal": true;
3423
+ };
3424
+ "ariaLabel": {
3425
+ "alias": "ariaLabel";
3426
+ "required": false;
3427
+ "isSignal": true;
3428
+ };
3429
+ "hint": {
3430
+ "alias": "hint";
3431
+ "required": false;
3432
+ "isSignal": true;
3433
+ };
3434
+ "error": {
3435
+ "alias": "error";
3436
+ "required": false;
3437
+ "isSignal": true;
3438
+ };
3439
+ "required": {
3440
+ "alias": "required";
3441
+ "required": false;
3442
+ "isSignal": true;
3443
+ };
3444
+ "showErrors": {
3445
+ "alias": "showErrors";
3446
+ "required": false;
3447
+ "isSignal": true;
3448
+ };
3449
+ "size": {
3450
+ "alias": "size";
3451
+ "required": false;
3452
+ "isSignal": true;
3453
+ };
3454
+ "readonly": {
3455
+ "alias": "readonly";
3456
+ "required": false;
3457
+ "isSignal": true;
3458
+ };
3459
+ "name": {
3460
+ "alias": "name";
3461
+ "required": false;
3462
+ "isSignal": true;
3463
+ };
3464
+ "_disabledInput": {
3465
+ "alias": "disabled";
3466
+ "required": false;
3467
+ "isSignal": true;
3468
+ };
3469
+ }, {
3470
+ "valueChange": "valueChange";
3471
+ "invalidChange": "invalidChange";
3472
+ }, never, never, true, never>;
3473
+ }
3303
3474
  export type ImageRepositionShape = 'circle' | 'rounded';
3304
3475
  /**
3305
3476
  * Drag-to-center photo frame. The image fills the frame (`object-fit: cover`) and the user drags it, or uses the arrow
@@ -3397,7 +3568,7 @@ export declare class CheckboxComponent implements ControlValueAccessor, Validato
3397
3568
  * 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.
3398
3569
  * Default null: plain label text, exactly as before. Single mode only.
3399
3570
  */
3400
- readonly headingLevel: import("@angular/core").InputSignal<1 | 2 | 5 | 3 | 6 | 4 | null>;
3571
+ readonly headingLevel: import("@angular/core").InputSignal<1 | 2 | 3 | 4 | 5 | 6 | null>;
3401
3572
  readonly indeterminate: import("@angular/core").InputSignal<boolean>;
3402
3573
  readonly checked: import("@angular/core").ModelSignal<boolean>;
3403
3574
  /**
@@ -3802,7 +3973,7 @@ export declare class StepperComponent {
3802
3973
  * its circle, one continuous line behind the circles that fills as steps complete; a complete step shows a check, the current step an
3803
3974
  * accent ring with a dot, an upcoming step an empty circle (no numbers). Circles are 40px (32px with `size="sm"`).
3804
3975
  */
3805
- readonly labelPosition: import("@angular/core").InputSignal<"beside" | "below">;
3976
+ readonly labelPosition: import("@angular/core").InputSignal<"below" | "beside">;
3806
3977
  /** Viewport width in px below which a horizontal stepper is drawn vertical (labels beside the circles), e.g. `640`. null (default) = never. */
3807
3978
  readonly stackBelow: import("@angular/core").InputSignal<number | null>;
3808
3979
  /** CSS length (e.g. `10.5rem`): horizontal only - the list gets `min-width: calc(<step count> * <value>)`. Empty (default) = no minimum. */
@@ -4124,6 +4295,15 @@ export interface RadioOption {
4124
4295
  * path. Decorative (`aria-hidden`); none when omitted.
4125
4296
  */
4126
4297
  icon?: string;
4298
+ /**
4299
+ * Library source 2026-11-05, not yet published. Link shown after the option's description (e.g. "Read the terms"): only http(s), mailto, tel and
4300
+ * in-app paths are linked, an absolute http(s) address opens in a new tab. `testId` is the link's `data-testid`. None when omitted.
4301
+ */
4302
+ descriptionLink?: {
4303
+ label: string;
4304
+ url: string;
4305
+ testId?: string;
4306
+ };
4127
4307
  }
4128
4308
  /**
4129
4309
  * Group of native radio buttons inside a `<fieldset>` (+ `<legend>` = `label`), a ControlValueAccessor (string value, `''`
@@ -4436,7 +4616,7 @@ export declare class ButtonComponent {
4436
4616
  * `ghost-start`: a ghost button for list / section toggles - a full-width row with its content aligned to the start, transparent
4437
4617
  * background, hover tint and the normal focus ring. Pair it with `ariaExpanded` / `ariaPressed`; the label may contain a heading element.
4438
4618
  */
4439
- readonly variant: import("@angular/core").InputSignal<"link" | "primary" | "secondary" | "danger" | "warning" | "ghost" | "ghost-start" | "tab" | "icon" | "icon-danger">;
4619
+ readonly variant: import("@angular/core").InputSignal<"link" | "icon" | "warning" | "danger" | "primary" | "secondary" | "ghost" | "ghost-start" | "tab" | "icon-danger">;
4440
4620
  /** 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`). */
4441
4621
  readonly routerLink: import("@angular/core").InputSignal<string | readonly unknown[] | null>;
4442
4622
  /** Query params of the `routerLink` (e.g. `{ section: 'deal-defaults' }`). */
@@ -5065,7 +5245,7 @@ export declare class BulkMessagePanelComponent {
5065
5245
  readonly sending: import("@angular/core").InputSignal<boolean>;
5066
5246
  readonly closed: import("@angular/core").OutputEmitterRef<void>;
5067
5247
  readonly send: import("@angular/core").OutputEmitterRef<BulkMessageSendEvent>;
5068
- readonly channel: import("@angular/core").WritableSignal<"text" | "email">;
5248
+ readonly channel: import("@angular/core").WritableSignal<"email" | "text">;
5069
5249
  private readonly _subject;
5070
5250
  private readonly _body;
5071
5251
  get subject(): string;
@@ -5593,7 +5773,7 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
5593
5773
  readonly passwordRequirements: import("@angular/core").InputSignal<boolean>;
5594
5774
  /** Rules for `passwordRequirements`; default = the library's five rules (8+ characters, upper, lower, digit, special). */
5595
5775
  readonly passwordRules: import("@angular/core").InputSignal<readonly PasswordRule[] | undefined>;
5596
- readonly type: import("@angular/core").InputSignal<"number" | "text" | "email" | "tel" | "password" | "url">;
5776
+ readonly type: import("@angular/core").InputSignal<"number" | "email" | "text" | "tel" | "password" | "url">;
5597
5777
  readonly maxlength: import("@angular/core").InputSignal<number | undefined>;
5598
5778
  readonly required: import("@angular/core").InputSignal<boolean>;
5599
5779
  readonly autocomplete: import("@angular/core").InputSignal<string>;
@@ -5602,7 +5782,7 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
5602
5782
  * `search`, `text`, `none`). Empty (default) = the browser's default for the field, except `type="tel"`, which keeps `tel`.
5603
5783
  * It only picks the keyboard; it does not restrict what can be typed or pasted.
5604
5784
  */
5605
- readonly inputmode: import("@angular/core").InputSignal<"" | "none" | "text" | "search" | "decimal" | "email" | "tel" | "url" | "numeric">;
5785
+ readonly inputmode: import("@angular/core").InputSignal<"" | "none" | "email" | "search" | "text" | "numeric" | "tel" | "url" | "decimal">;
5606
5786
  readonly readonly: import("@angular/core").InputSignal<boolean>;
5607
5787
  readonly hint: import("@angular/core").InputSignal<string>;
5608
5788
  /** 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. */
@@ -5674,7 +5854,7 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
5674
5854
  protected readonly _stepAttr: import("@angular/core").Signal<string | null>;
5675
5855
  protected readonly _revealable: import("@angular/core").Signal<boolean>;
5676
5856
  protected readonly _shown: import("@angular/core").WritableSignal<boolean>;
5677
- protected readonly _inputType: import("@angular/core").Signal<"number" | "text" | "email" | "tel" | "password" | "url">;
5857
+ protected readonly _inputType: import("@angular/core").Signal<"number" | "email" | "text" | "tel" | "password" | "url">;
5678
5858
  protected readonly _eyePath: string;
5679
5859
  protected readonly _eyeOffPath: string;
5680
5860
  protected readonly _showRequirements: import("@angular/core").Signal<boolean>;
@@ -6033,6 +6213,10 @@ export declare class TextareaInputComponent implements ControlValueAccessor, Val
6033
6213
  readonly errorMessage: import("@angular/core").Signal<string>;
6034
6214
  /** Emits whenever the field becomes invalid / valid. */
6035
6215
  readonly invalidChange: import("@angular/core").OutputEmitterRef<boolean>;
6216
+ /** Library source 2026-11-05, not yet published. Emits when the inner `<textarea>` gains focus (same as `ui-text-input`). */
6217
+ readonly focused: import("@angular/core").OutputEmitterRef<void>;
6218
+ /** Library source 2026-11-05, not yet published. Emits when the inner `<textarea>` loses focus (same as `ui-text-input`); the form control is marked touched and the built-in error reveal still happens. */
6219
+ readonly blurred: import("@angular/core").OutputEmitterRef<void>;
6036
6220
  protected readonly _activeError: import("@angular/core").Signal<string>;
6037
6221
  private _onValidatorChange;
6038
6222
  constructor();
@@ -6076,6 +6260,7 @@ export declare class TextareaInputComponent implements ControlValueAccessor, Val
6076
6260
  registerOnTouched(fn: () => void): void;
6077
6261
  setDisabledState(d: boolean): void;
6078
6262
  protected onInput(event: Event): void;
6263
+ protected onFocus(): void;
6079
6264
  protected onBlur(): void;
6080
6265
  private _check;
6081
6266
  static ɵfac: i0.ɵɵFactoryDeclaration<TextareaInputComponent, never>;
@@ -6152,6 +6337,8 @@ export declare class TextareaInputComponent implements ControlValueAccessor, Val
6152
6337
  };
6153
6338
  }, {
6154
6339
  "invalidChange": "invalidChange";
6340
+ "focused": "focused";
6341
+ "blurred": "blurred";
6155
6342
  }, never, ["[uiLabelEnd]"], true, never>;
6156
6343
  }
6157
6344
  export type TextSize = 'sm' | 'md' | 'lg';
@@ -7745,6 +7932,13 @@ export declare class FormColSpanDirective {
7745
7932
  * <ui-button list-item-action variant="icon" ariaLabel="Remove" (click)="remove(d)">…</ui-button>
7746
7933
  * </ui-list-item>
7747
7934
  *
7935
+ * Library source 2026-11-05, not yet published: row-end content slot. An element with the `list-item-end` attribute (a `<ui-star-rating>`, a badge, a price...) is
7936
+ * projected at the END of the row, after the text and before the busy spinner and the `list-item-action` buttons, vertically centred, at its own size. Like the action
7937
+ * slot it sits outside the row's label: clicks inside it never emit `select` (also on a plain pressable row), and Enter / Space inside it are not treated as a row
7938
+ * press. Absent = no extra DOM, nothing changes. Accessibility note: a plain pressable row (`leading="none"`, interactive) is `role="button"`, whose children are presentational, so
7939
+ * INTERACTIVE content in this slot (a `<ui-star-rating>`, a button) should go on a row with `[interactive]="false"` (no role, nothing pressable); a badge or other static text is fine on any row.
7940
+ * <ui-list-item [title]="r.name" [details]="[r.date]"><ui-star-rating list-item-end [readonly]="true" [value]="r.rating" [size]="16" /></ui-list-item>
7941
+ *
7748
7942
  * Library source 2026-11-04, not yet published: `[disabled]` (aria-disabled, not focusable, never emits `select`, non-colour cue), `[busy]`
7749
7943
  * (aria-busy, spinner, presses ignored) and a leading image slot, `<img list-item-image>` / `<ui-image list-item-image>`, rendered in front of
7750
7944
  * 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
@@ -7778,7 +7972,7 @@ export type ListItemIconColor = 'slate' | 'amber' | 'red' | 'blue' | 'green' | '
7778
7972
  export declare class ListItemComponent implements AfterContentChecked {
7779
7973
  private readonly host;
7780
7974
  /** Show a radio button, checkbox, or nothing on the left. */
7781
- readonly leading: import("@angular/core").InputSignal<"none" | "checkbox" | "radio">;
7975
+ readonly leading: import("@angular/core").InputSignal<"none" | "radio" | "checkbox">;
7782
7976
  /** `name` attribute for the radio/checkbox (groups radios together). */
7783
7977
  readonly inputName: import("@angular/core").InputSignal<string>;
7784
7978
  /** `id` attribute for the radio/checkbox (links the label). */
@@ -7957,7 +8151,7 @@ export declare class ListItemComponent implements AfterContentChecked {
7957
8151
  };
7958
8152
  }, {
7959
8153
  "select": "select";
7960
- }, never, ["[list-item-image]", "[list-item-action], [li-action]"], true, never>;
8154
+ }, never, ["[list-item-image]", "[list-item-end]", "[list-item-action], [li-action]"], true, never>;
7961
8155
  }
7962
8156
  /** Colour of the priority dot (`high` red, `medium` amber, `low` grey, `blue`, `green`); `none` = no dot. */
7963
8157
  export type CardListIndicator = 'high' | 'medium' | 'low' | 'blue' | 'green' | 'none';
@@ -8920,7 +9114,7 @@ export declare class ChipGroupComponent {
8920
9114
  readonly spaceAbove: import("@angular/core").InputSignal<"none" | "sm" | "md">;
8921
9115
  /** Space below the chip group. */
8922
9116
  readonly spaceBelow: import("@angular/core").InputSignal<"none" | "sm" | "md">;
8923
- protected readonly _gap: import("@angular/core").Signal<"6px" | "12px" | "8px">;
9117
+ protected readonly _gap: import("@angular/core").Signal<"8px" | "6px" | "12px">;
8924
9118
  protected readonly _spaceAbove: import("@angular/core").Signal<"0" | "6px" | "12px">;
8925
9119
  protected readonly _spaceBelow: import("@angular/core").Signal<"0" | "6px" | "12px">;
8926
9120
  static ɵfac: i0.ɵɵFactoryDeclaration<ChipGroupComponent, never>;
@@ -9300,13 +9494,13 @@ export declare class AlertComponent {
9300
9494
  }
9301
9495
  /**
9302
9496
  * Every key `<ui-icon>` draws by itself (the data-table action keys such as `view` / `edit` / `call` are accepted too, see `builtInActionIcon`).
9303
- * Each resolves with `iconPath(key)`. Includes `search`, `cup` (food / drink) and `wrench` (rental / tools), library source 2026-11-04, and `cash` (banknote) and `dollar` (payment methods / amounts), library source 2026-11-05, not yet published.
9497
+ * Each resolves with `iconPath(key)`. Includes `search`, `cup` (food / drink) and `wrench` (rental / tools), library source 2026-11-04, and `cash` (banknote) and `dollar` (payment methods / amounts), library source 2026-11-05, not yet published. Also `star`, `gift`, `award` and `calendar-check` (library source 2026-11-05, not yet published).
9304
9498
  */
9305
9499
  export declare const ICON_NAMES: readonly string[];
9306
9500
  /** The SVG path (24×24 stroke icon) for an icon key, or undefined when the key is unknown. */
9307
9501
  export declare function iconPath(name: string): string | undefined;
9308
9502
  /** Keys with an icon of their own (the data-table action keys are accepted too — see `builtInActionIcon`). */
9309
- 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' | 'cash' | 'dollar' | 'history' | 'move-up' | 'move-down';
9503
+ 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' | 'cash' | 'dollar' | 'star' | 'gift' | 'award' | 'calendar-check' | 'history' | 'move-up' | 'move-down';
9310
9504
  /**
9311
9505
  * A clickable icon. The host passes a key (`name="delete"`) and the library draws that icon; clicking it emits
9312
9506
  * `iconClick`, and the host does the actual work (delete the row, open a panel, …).
@@ -9333,7 +9527,7 @@ export declare class IconComponent {
9333
9527
  readonly ariaLabel: import("@angular/core").InputSignal<string>;
9334
9528
  /** Icon size in px. */
9335
9529
  readonly size: import("@angular/core").InputSignal<number>;
9336
- readonly variant: import("@angular/core").InputSignal<"danger" | "default">;
9530
+ readonly variant: import("@angular/core").InputSignal<"default" | "danger">;
9337
9531
  readonly disabled: import("@angular/core").InputSignal<boolean>;
9338
9532
  /** 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. */
9339
9533
  readonly loading: import("@angular/core").InputSignal<boolean>;
@@ -9445,7 +9639,7 @@ export declare class TimelineComponent {
9445
9639
  /** Any CSS length (e.g. `600px`). When set, the list scrolls inside a keyboard-focusable region of at most this height. Empty = no wrapper. */
9446
9640
  readonly maxHeight: import("@angular/core").InputSignal<string>;
9447
9641
  /** `below` (default): the time is under the title / description. `end`: the time sits right-aligned on the title row. */
9448
- readonly timePosition: import("@angular/core").InputSignal<"end" | "below">;
9642
+ readonly timePosition: import("@angular/core").InputSignal<"below" | "end">;
9449
9643
  /**
9450
9644
  * Group the items under a heading per calendar day of `dateTime` ("Today", "Yesterday", "Oct 3", "Oct 3, 2025"). Default false = no headings,
9451
9645
  * 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.
@@ -10721,6 +10915,16 @@ export declare function humanReadableMessage(value: unknown): string | null;
10721
10915
  export declare class RadioComponent {
10722
10916
  readonly label: import("@angular/core").InputSignal<string>;
10723
10917
  readonly description: import("@angular/core").InputSignal<string>;
10918
+ /**
10919
+ * Library source 2026-11-05, not yet published. Optional link shown after the description: `linkLabel` is its text, `linkUrl` its address. Only `http:`, `https:`,
10920
+ * `mailto:` and `tel:` addresses and in-app paths (`/...`, `#...`) are linked; anything else (`javascript:`, `data:`, empty) draws nothing. An absolute http(s)
10921
+ * address opens in a new tab (`noopener noreferrer`, with "(opens in a new tab)" for screen readers); the others follow in the same tab. The radio's
10922
+ * accessible name stays the label only.
10923
+ */
10924
+ readonly linkLabel: import("@angular/core").InputSignal<string>;
10925
+ readonly linkUrl: import("@angular/core").InputSignal<string>;
10926
+ /** `data-testid` of the link; none when empty. */
10927
+ readonly linkTestId: import("@angular/core").InputSignal<string>;
10724
10928
  /**
10725
10929
  * 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
10726
10930
  * stroke SVG path (`M12 5v14 M5 12h14`). Decorative (`aria-hidden`), so the accessible name stays the label. Empty (default), an unknown key or
@@ -10745,11 +10949,14 @@ export declare class RadioComponent {
10745
10949
  protected readonly disabled: import("@angular/core").InputSignal<boolean>;
10746
10950
  /** 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. */
10747
10951
  protected readonly _iconD: import("@angular/core").Signal<string | null>;
10952
+ /** The address to link, or null when the link is not drawn (no label, empty or unsafe address). */
10953
+ protected readonly _linkHref: import("@angular/core").Signal<string | null>;
10954
+ protected readonly _linkNewTab: import("@angular/core").Signal<boolean>;
10748
10955
  /** 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. */
10749
10956
  readonly labelId: import("@angular/core").InputSignal<string>;
10750
10957
  private readonly _generatedLabelId;
10751
10958
  protected readonly _labelId: import("@angular/core").Signal<string>;
10752
- /** With a description inside the <label>, the accessible name would read "Email We send a message": name the input by the label text only. */
10959
+ /** With a description or link inside the <label>, the accessible name would read "Email We send a message": name the input by the label text only. */
10753
10960
  protected readonly _labelledBy: import("@angular/core").Signal<string | null>;
10754
10961
  protected readonly _descriptionId: string;
10755
10962
  /** Group hint/error id plus the option's own description (kept out of the label so the accessible name is label-only). */
@@ -10769,6 +10976,21 @@ export declare class RadioComponent {
10769
10976
  "required": false;
10770
10977
  "isSignal": true;
10771
10978
  };
10979
+ "linkLabel": {
10980
+ "alias": "linkLabel";
10981
+ "required": false;
10982
+ "isSignal": true;
10983
+ };
10984
+ "linkUrl": {
10985
+ "alias": "linkUrl";
10986
+ "required": false;
10987
+ "isSignal": true;
10988
+ };
10989
+ "linkTestId": {
10990
+ "alias": "linkTestId";
10991
+ "required": false;
10992
+ "isSignal": true;
10993
+ };
10772
10994
  "icon": {
10773
10995
  "alias": "icon";
10774
10996
  "required": false;
@@ -11426,7 +11648,7 @@ export declare class PdfHotspotComponent {
11426
11648
  /** `ready`: clickable; `blocked`: disabled (a prerequisite is missing); `signed`: shows `image`. */
11427
11649
  readonly state: import("@angular/core").InputSignal<"ready" | "blocked" | "signed">;
11428
11650
  /** `warning` gives the ready state an amber look (e.g. for initials), default is blue. */
11429
- readonly tone: import("@angular/core").InputSignal<"primary" | "warning">;
11651
+ readonly tone: import("@angular/core").InputSignal<"warning" | "primary">;
11430
11652
  /** Text of the ready button (e.g. "Sign Here"). */
11431
11653
  readonly label: import("@angular/core").InputSignal<string>;
11432
11654
  /** Text of the blocked button (e.g. "Add signature above"). */
@@ -11563,7 +11785,7 @@ export declare class DetailCardComponent {
11563
11785
  /** true (default) = the title is displayed in capitals (CSS only); false = shown as written. The text, aria-label and heading name are never changed. */
11564
11786
  readonly uppercaseTitle: import("@angular/core").InputSignal<boolean>;
11565
11787
  /** 1-6 makes the title a real heading for screen readers (role=heading, aria-level); null keeps it plain text. */
11566
- readonly headingLevel: import("@angular/core").InputSignal<1 | 2 | 5 | 3 | 6 | 4 | null>;
11788
+ readonly headingLevel: import("@angular/core").InputSignal<1 | 2 | 3 | 4 | 5 | 6 | null>;
11567
11789
  /** Optional id for the title text; the card is then labelled by it. Without it the title is the card's aria-label. */
11568
11790
  readonly titleId: import("@angular/core").InputSignal<string>;
11569
11791
  /** Accessible name of the card when the header gives none (no header, or no title). A visible title wins; blank = no name. */
@@ -11577,7 +11799,7 @@ export declare class DetailCardComponent {
11577
11799
  /** Background colour of the footer bar (the `[card-footer]` slot) as any CSS colour. Empty = no colour of its own. */
11578
11800
  readonly footerBackground: import("@angular/core").InputSignal<string>;
11579
11801
  /** Alignment of the `[card-footer]` content: `'start'` (default, unchanged) or `'end'` = a right-aligned action row with an 8px gap. */
11580
- readonly footerAlign: import("@angular/core").InputSignal<"start" | "end">;
11802
+ readonly footerAlign: import("@angular/core").InputSignal<"end" | "start">;
11581
11803
  /** Text colour as any CSS colour (`#fff`, `var(--on-dark)` …). Empty = the default colours. Colours the title, subtitle, chevron and body text. */
11582
11804
  readonly textColor: import("@angular/core").InputSignal<string>;
11583
11805
  /** false = no header at all (no title, edit button, toggle or divider): the card is only the body, always open. */