@forgeroute/ui 0.4.4 → 0.4.6

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.
@@ -940,6 +940,13 @@ export interface SelectOption<V extends string | number = string> {
940
940
  * `aria-describedby`) and sets it as the option's `title` tooltip where the browser shows one. Options without it are unchanged.
941
941
  */
942
942
  description?: string;
943
+ /**
944
+ * Optional short tag shown after the label, e.g. `{ label: 'Pro plan', badge: 'Partner: Acme' }` is listed as "Pro plan — Partner: Acme".
945
+ * A native `<option>` can only hold text (no elements, no colours), so the badge is a TEXT suffix joined by " —" (space, em dash,
946
+ * space); screen readers read it as part of the option. The selected value, search-by-typing and the description are unaffected.
947
+ * Options without it are unchanged.
948
+ */
949
+ badge?: string;
943
950
  }
944
951
  export declare class SelectComponent implements ControlValueAccessor, Validator, UiFieldValidity {
945
952
  readonly label: import("@angular/core").InputSignal<string>;
@@ -1808,6 +1815,10 @@ export declare class SidePanelComponent implements OnDestroy {
1808
1815
  readonly primaryVariant: import("@angular/core").InputSignal<"primary" | "danger" | "warning">;
1809
1816
  readonly primaryLoading: import("@angular/core").InputSignal<boolean>;
1810
1817
  readonly primaryDisabled: import("@angular/core").InputSignal<boolean>;
1818
+ /** `data-testid` of the Cancel button; none when empty (default). */
1819
+ readonly cancelTestId: import("@angular/core").InputSignal<string>;
1820
+ /** `data-testid` of the primary footer button; none when empty (default). */
1821
+ readonly primaryTestId: import("@angular/core").InputSignal<string>;
1811
1822
  readonly closed: import("@angular/core").OutputEmitterRef<void>;
1812
1823
  readonly primaryClick: import("@angular/core").OutputEmitterRef<void>;
1813
1824
  protected readonly titleId: string;
@@ -1875,10 +1886,20 @@ export declare class SidePanelComponent implements OnDestroy {
1875
1886
  "required": false;
1876
1887
  "isSignal": true;
1877
1888
  };
1889
+ "cancelTestId": {
1890
+ "alias": "cancelTestId";
1891
+ "required": false;
1892
+ "isSignal": true;
1893
+ };
1894
+ "primaryTestId": {
1895
+ "alias": "primaryTestId";
1896
+ "required": false;
1897
+ "isSignal": true;
1898
+ };
1878
1899
  }, {
1879
1900
  "closed": "closed";
1880
1901
  "primaryClick": "primaryClick";
1881
- }, never, ["*"], true, never>;
1902
+ }, never, ["*", "[panel-footer-extra]"], true, never>;
1882
1903
  }
1883
1904
  export declare class ModalComponent implements OnInit, OnDestroy {
1884
1905
  readonly open: import("@angular/core").InputSignal<boolean>;
@@ -1886,6 +1907,15 @@ export declare class ModalComponent implements OnInit, OnDestroy {
1886
1907
  readonly description: import("@angular/core").InputSignal<string>;
1887
1908
  readonly maxWidth: import("@angular/core").InputSignal<string>;
1888
1909
  readonly bodyOverflow: import("@angular/core").InputSignal<"hidden" | "auto" | "visible">;
1910
+ /** `data-testid` of the dialog element itself (the host `<ui-modal>` is always in the page, the dialog only while open). None when empty. */
1911
+ readonly dialogTestId: import("@angular/core").InputSignal<string>;
1912
+ /** Hides the header X button (e.g. while a request is running). Escape and a backdrop click still close unless `closable` is false. */
1913
+ readonly hideClose: import("@angular/core").InputSignal<boolean>;
1914
+ /**
1915
+ * `false` = the user cannot dismiss the dialog: the X button is hidden and Escape / a backdrop click do not emit `close`
1916
+ * (e.g. while a save is running; the host closes it itself). Default `true` = today's behaviour.
1917
+ */
1918
+ readonly closable: import("@angular/core").InputSignal<boolean>;
1889
1919
  readonly close: import("@angular/core").OutputEmitterRef<void>;
1890
1920
  protected readonly titleId: string;
1891
1921
  private readonly el;
@@ -1929,9 +1959,24 @@ export declare class ModalComponent implements OnInit, OnDestroy {
1929
1959
  "required": false;
1930
1960
  "isSignal": true;
1931
1961
  };
1962
+ "dialogTestId": {
1963
+ "alias": "dialogTestId";
1964
+ "required": false;
1965
+ "isSignal": true;
1966
+ };
1967
+ "hideClose": {
1968
+ "alias": "hideClose";
1969
+ "required": false;
1970
+ "isSignal": true;
1971
+ };
1972
+ "closable": {
1973
+ "alias": "closable";
1974
+ "required": false;
1975
+ "isSignal": true;
1976
+ };
1932
1977
  }, {
1933
1978
  "close": "close";
1934
- }, never, ["*", "[modal-footer-left]", "[modal-footer-right]"], true, never>;
1979
+ }, never, ["*", "[modal-footer-left]", "[modal-footer-center]", "[modal-footer-right]"], true, never>;
1935
1980
  }
1936
1981
  export type ToastType = 'success' | 'error' | 'info';
1937
1982
  export declare class ToastService implements OnDestroy {
@@ -2418,6 +2463,8 @@ export interface CheckboxOption {
2418
2463
  /** Helper text under the option. */
2419
2464
  description?: string;
2420
2465
  disabled?: boolean;
2466
+ /** `data-testid` of this option's native checkbox (e.g. for end-to-end tests); none when omitted. */
2467
+ testId?: string;
2421
2468
  }
2422
2469
  export declare class CheckboxComponent implements ControlValueAccessor, Validator, UiFieldValidity {
2423
2470
  readonly label: import("@angular/core").InputSignal<string>;
@@ -2434,6 +2481,26 @@ export declare class CheckboxComponent implements ControlValueAccessor, Validato
2434
2481
  readonly options: import("@angular/core").InputSignal<CheckboxOption[]>;
2435
2482
  /** Group heading (the fieldset's legend). */
2436
2483
  readonly legend: import("@angular/core").InputSignal<string>;
2484
+ /**
2485
+ * `ui-checkbox-group` is the same component under a group-friendly tag: `<ui-checkbox-group legend="Interests" [options]="opts" [(ngModel)]="picked" />`
2486
+ * (value = array of ticked option values). On the `<ui-checkbox-group>` tag the legend falls back to `label` when `legend` is empty (`<ui-checkbox [options]>` ignores `label` as before).
2487
+ */
2488
+ protected readonly _legend: import("@angular/core").Signal<string>;
2489
+ /** Group mode: lay the options out in a column (default) or in a wrapping row. */
2490
+ readonly orientation: import("@angular/core").InputSignal<"vertical" | "horizontal">;
2491
+ /**
2492
+ * Group mode: the ticked option values as a two-way model (`[(values)]`), an alternative to ngModel / forms. Unset (default) = the
2493
+ * group is driven by ngModel / FormControl only. Values that are not an option are dropped and the order follows `options`.
2494
+ */
2495
+ readonly values: import("@angular/core").ModelSignal<string[] | undefined>;
2496
+ /** Single mode: small helper text under the label, linked to the native checkbox with `aria-describedby`. None when empty (default). */
2497
+ readonly description: import("@angular/core").InputSignal<string>;
2498
+ /** Set when the host projects a `[checkbox-trailing]` element (see `CheckboxTrailingDirective`). */
2499
+ private readonly _trailingContent;
2500
+ protected readonly _trailing: import("@angular/core").Signal<boolean>;
2501
+ private readonly _host;
2502
+ /** `aria-describedby` of the single checkbox: its description, then the error / hint; none when neither exists (as before). */
2503
+ protected readonly _singleDescribedBy: import("@angular/core").Signal<string | null>;
2437
2504
  /** Indent this checkbox (or the whole group) under its parent option, aligned with the parent's label. */
2438
2505
  readonly indent: import("@angular/core").InputSignal<boolean>;
2439
2506
  protected readonly groupMode: import("@angular/core").Signal<boolean>;
@@ -2460,6 +2527,14 @@ export declare class CheckboxComponent implements ControlValueAccessor, Validato
2460
2527
  protected readonly _activeError: import("@angular/core").Signal<string>;
2461
2528
  private _onValidatorChange;
2462
2529
  constructor();
2530
+ /**
2531
+ * Puts the box back to a state chosen by the host after it refused a change (e.g. a confirm was declined). Writes the model, the
2532
+ * native input(s) and the form control, which re-setting the same bound value cannot do (the one-way binding sees no change
2533
+ * while the DOM and the internal state already moved). Single mode: `reset(false)` / `reset(true)`; group mode: `reset(['a'])`.
2534
+ */
2535
+ reset(value?: boolean | string[]): void;
2536
+ /** Sets every native checkbox of this component to the state the component holds (the DOM may have moved ahead of it). */
2537
+ private _syncNative;
2463
2538
  /** Re-run the form control's validation when a rule input (`required`, `requiredMessage`, `label`) changes. */
2464
2539
  ngOnChanges(): void;
2465
2540
  validate(control: AbstractControl): ValidationErrors | null;
@@ -2481,7 +2556,7 @@ export declare class CheckboxComponent implements ControlValueAccessor, Validato
2481
2556
  /** Group mode: ticks / unticks one option; the form gets the full list of ticked values. */
2482
2557
  onToggleOption(value: string, event: Event): void;
2483
2558
  static ɵfac: i0.ɵɵFactoryDeclaration<CheckboxComponent, never>;
2484
- static ɵcmp: i0.ɵɵComponentDeclaration<CheckboxComponent, "ui-checkbox", never, {
2559
+ static ɵcmp: i0.ɵɵComponentDeclaration<CheckboxComponent, "ui-checkbox, ui-checkbox-group", never, {
2485
2560
  "label": {
2486
2561
  "alias": "label";
2487
2562
  "required": false;
@@ -2512,6 +2587,21 @@ export declare class CheckboxComponent implements ControlValueAccessor, Validato
2512
2587
  "required": false;
2513
2588
  "isSignal": true;
2514
2589
  };
2590
+ "orientation": {
2591
+ "alias": "orientation";
2592
+ "required": false;
2593
+ "isSignal": true;
2594
+ };
2595
+ "values": {
2596
+ "alias": "values";
2597
+ "required": false;
2598
+ "isSignal": true;
2599
+ };
2600
+ "description": {
2601
+ "alias": "description";
2602
+ "required": false;
2603
+ "isSignal": true;
2604
+ };
2515
2605
  "indent": {
2516
2606
  "alias": "indent";
2517
2607
  "required": false;
@@ -2549,8 +2639,23 @@ export declare class CheckboxComponent implements ControlValueAccessor, Validato
2549
2639
  };
2550
2640
  }, {
2551
2641
  "checked": "checkedChange";
2642
+ "values": "valuesChange";
2552
2643
  "invalidChange": "invalidChange";
2553
- }, never, ["*"], true, never>;
2644
+ }, ["_trailingContent"], ["*", "[checkbox-trailing]"], true, never>;
2645
+ }
2646
+ /**
2647
+ * Marks content that a single `ui-checkbox` shows at the END of its row, outside the clickable label (a badge, a price, a link):
2648
+ *
2649
+ * <ui-checkbox label="Priority handling" description="Ships first" [(ngModel)]="priority">
2650
+ * <span checkbox-trailing>$5.00</span>
2651
+ * </ui-checkbox>
2652
+ *
2653
+ * Import this directive in the host component (it is how the checkbox knows a trailing slot is in use); without it the checkbox
2654
+ * renders exactly as before. Clicking the trailing content does not toggle the box.
2655
+ */
2656
+ export declare class CheckboxTrailingDirective {
2657
+ static ɵfac: i0.ɵɵFactoryDeclaration<CheckboxTrailingDirective, never>;
2658
+ static ɵdir: i0.ɵɵDirectiveDeclaration<CheckboxTrailingDirective, "[checkbox-trailing]", never, {}, {}, never, never, true, never>;
2554
2659
  }
2555
2660
  /**
2556
2661
  * On/off switch for settings: a label and optional hint on the left, the switch on the right
@@ -2935,6 +3040,11 @@ export interface RadioOption {
2935
3040
  * Built-in validation: `required` -> "<label> is required."; a non-empty value that is not one of the `options` ->
2936
3041
  * "Select a valid option." (not checked while `options` is empty). Disabled groups are never invalid.
2937
3042
  *
3043
+ * Option content (`<ng-template uiRadioOptionContent="value">`) is rendered right under its option, inside the fieldset, so the layout and
3044
+ * keyboard flow stay as they are. Because it is not a radio, it is exposed as its own `role="group"` named by that option's label
3045
+ * (`aria-labelledby` = the radio's label id, e.g. "Deliver, group") instead of being read as part of the radio group. Groups without
3046
+ * templates render no extra attributes or ids.
3047
+ *
2938
3048
  * Validity API (same on every ui input): Angular `Validator`, signals `invalid` + `errorMessage`, `invalidChange` output,
2939
3049
  * provides `UiFieldValidity`. Messages show after the group lost focus or while `[showErrors]="true"`; a host `[error]` wins.
2940
3050
  */
@@ -2946,15 +3056,22 @@ export declare class RadioGroupComponent implements ControlValueAccessor, Valida
2946
3056
  readonly error: import("@angular/core").InputSignal<string>;
2947
3057
  /** Reveal the built-in error messages now (e.g. after a failed Save click), without waiting for blur. */
2948
3058
  readonly showErrors: import("@angular/core").InputSignal<boolean>;
2949
- readonly orientation: import("@angular/core").InputSignal<"horizontal" | "vertical">;
3059
+ readonly orientation: import("@angular/core").InputSignal<"vertical" | "horizontal">;
2950
3060
  /** Native `name` shared by the radios; a unique one is generated when omitted. */
2951
3061
  readonly name: import("@angular/core").InputSignal<string>;
3062
+ /** `<ng-template uiRadioOptionContent="value">` children: content shown under that option while it is selected. */
3063
+ private readonly _optionContent;
3064
+ protected readonly _nestedContent: import("@angular/core").Signal<Map<string, TemplateRef<unknown>>>;
2952
3065
  protected readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
2953
3066
  private readonly _cvaDisabled;
2954
3067
  protected readonly disabled: import("@angular/core").Signal<boolean>;
2955
3068
  private readonly _generatedName;
2956
3069
  protected get _name(): string;
2957
3070
  protected readonly _descId: string;
3071
+ /** Id of the content block under the selected option; that radio points at it with aria-controls. */
3072
+ protected readonly _nestedId: string;
3073
+ /** Id of an option's label text (set on the radio only for options that have nested content); the nested group is named by it. */
3074
+ protected _optionLabelId(index: number): string;
2958
3075
  protected readonly _value: import("@angular/core").WritableSignal<string>;
2959
3076
  private readonly _reveal;
2960
3077
  private readonly _issue;
@@ -3030,7 +3147,7 @@ export declare class RadioGroupComponent implements ControlValueAccessor, Valida
3030
3147
  };
3031
3148
  }, {
3032
3149
  "invalidChange": "invalidChange";
3033
- }, never, never, true, never>;
3150
+ }, ["_optionContent"], never, true, never>;
3034
3151
  }
3035
3152
  /** One phone number the host found for sale. */
3036
3153
  export interface PhoneNumberOption {
@@ -3222,11 +3339,17 @@ export declare class PhoneNumberPickerComponent {
3222
3339
  }, never, never, true, never>;
3223
3340
  }
3224
3341
  export declare class ButtonComponent {
3225
- readonly variant: import("@angular/core").InputSignal<"primary" | "secondary" | "danger" | "warning" | "link" | "ghost" | "tab" | "icon" | "icon-danger">;
3226
- /** Renders an anchor to this route instead of a button (use with `variant="link"` for an inline text link). `['/settings']` or `'/settings'`. */
3342
+ /**
3343
+ * `ghost-start`: a ghost button for list / section toggles - a full-width row with its content aligned to the start, transparent
3344
+ * background, hover tint and the normal focus ring. Pair it with `ariaExpanded` / `ariaPressed`; the label may contain a heading element.
3345
+ */
3346
+ readonly variant: import("@angular/core").InputSignal<"primary" | "secondary" | "danger" | "warning" | "link" | "ghost" | "ghost-start" | "tab" | "icon" | "icon-danger">;
3347
+ /** 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`). */
3227
3348
  readonly routerLink: import("@angular/core").InputSignal<string | readonly unknown[] | null>;
3228
3349
  /** Query params of the `routerLink` (e.g. `{ section: 'deal-defaults' }`). */
3229
3350
  readonly queryParams: import("@angular/core").InputSignal<Record<string, unknown> | null>;
3351
+ /** Fragment (hash) of the `routerLink`, without the `#` (e.g. `'billing'` -> `/settings#billing`). */
3352
+ readonly fragment: import("@angular/core").InputSignal<string | null>;
3230
3353
  /**
3231
3354
  * Renders a plain `<a href>` instead of a button: for `mailto:`, `tel:`, `sms:`, `https://…` and relative URLs (use with
3232
3355
  * `variant="link"` for an inline text link). The browser handles the click, so middle-click, copy-link and open-in-new-tab work and
@@ -3272,6 +3395,11 @@ export declare class ButtonComponent {
3272
3395
  "required": false;
3273
3396
  "isSignal": true;
3274
3397
  };
3398
+ "fragment": {
3399
+ "alias": "fragment";
3400
+ "required": false;
3401
+ "isSignal": true;
3402
+ };
3275
3403
  "href": {
3276
3404
  "alias": "href";
3277
3405
  "required": false;
@@ -3761,6 +3889,12 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
3761
3889
  /** Accessible name for a field with no visible label (e.g. an inline cell or title input). */
3762
3890
  readonly ariaLabel: import("@angular/core").InputSignal<string>;
3763
3891
  readonly placeholder: import("@angular/core").InputSignal<string>;
3892
+ /**
3893
+ * An optional leading mark shown inside the field, left of the text (e.g. `prefix="$"` for a dollar amount). Hidden unless set; it is
3894
+ * decoration only (not part of the value, not read by screen readers), so say the unit in the label too when it matters ("Amount (USD)").
3895
+ * Meant for a short mark of 1-3 characters.
3896
+ */
3897
+ readonly prefix: import("@angular/core").InputSignal<string>;
3764
3898
  readonly type: import("@angular/core").InputSignal<"number" | "text" | "email" | "tel" | "password" | "url">;
3765
3899
  readonly maxlength: import("@angular/core").InputSignal<number | undefined>;
3766
3900
  readonly required: import("@angular/core").InputSignal<boolean>;
@@ -3793,17 +3927,31 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
3793
3927
  * (otherwise a dev-mode warning is logged once and string behaviour is used).
3794
3928
  */
3795
3929
  readonly valueType: import("@angular/core").InputSignal<"string" | "number">;
3930
+ /**
3931
+ * Optional text filter/mask applied to every typed or pasted value: `(raw) => cleaned`, e.g. `v => v.replace(/\D/g, '').slice(0, 9)`.
3932
+ * The result is what the box shows and what the model gets (the caret moves to the end when the text was changed). Unset (default)
3933
+ * = the typed text is used as is. Not applied to values the host writes (`writeValue`), and for `type="tel"` / `phoneFormat` the
3934
+ * phone formatting runs first and the formatter then sees its result.
3935
+ */
3936
+ readonly formatter: import("@angular/core").InputSignal<((raw: string) => string) | undefined>;
3796
3937
  /** Reveal the built-in error messages now (e.g. after a failed Save click), without waiting for blur. */
3797
3938
  readonly showErrors: import("@angular/core").InputSignal<boolean>;
3798
3939
  readonly focused: import("@angular/core").OutputEmitterRef<void>;
3799
3940
  readonly blurred: import("@angular/core").OutputEmitterRef<void>;
3800
3941
  /** Emits whenever the field becomes invalid / valid. */
3801
3942
  readonly invalidChange: import("@angular/core").OutputEmitterRef<boolean>;
3802
- protected readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
3943
+ /**
3944
+ * The `[disabled]` input. Public on purpose: a `protected` input makes `[disabled]="x"` in a host template fail strict template
3945
+ * type-checking (TS2445: Angular checks the field the alias points at). The field is disabled when this OR the form control
3946
+ * (`setDisabledState`, e.g. `FormControl.disable()`) says so.
3947
+ */
3948
+ readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
3803
3949
  private readonly _cvaDisabled;
3804
3950
  protected readonly disabled: import("@angular/core").Signal<boolean>;
3805
3951
  protected readonly _value: import("@angular/core").WritableSignal<string>;
3806
3952
  private readonly _reveal;
3953
+ /** 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. */
3954
+ protected readonly _prefixPadding: import("@angular/core").Signal<string | null>;
3807
3955
  /** True when the control value is a number: `valueType="number"` on a `type="number"` field. */
3808
3956
  private readonly _numeric;
3809
3957
  /** The native `step` attribute: only for `type="number"` and only for a finite number above 0; otherwise none (the browser's step of 1). */
@@ -3857,6 +4005,11 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
3857
4005
  "required": false;
3858
4006
  "isSignal": true;
3859
4007
  };
4008
+ "prefix": {
4009
+ "alias": "prefix";
4010
+ "required": false;
4011
+ "isSignal": true;
4012
+ };
3860
4013
  "type": {
3861
4014
  "alias": "type";
3862
4015
  "required": false;
@@ -3927,6 +4080,11 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
3927
4080
  "required": false;
3928
4081
  "isSignal": true;
3929
4082
  };
4083
+ "formatter": {
4084
+ "alias": "formatter";
4085
+ "required": false;
4086
+ "isSignal": true;
4087
+ };
3930
4088
  "showErrors": {
3931
4089
  "alias": "showErrors";
3932
4090
  "required": false;
@@ -4162,6 +4320,13 @@ export declare class FileInputComponent implements ControlValueAccessor, Validat
4162
4320
  readonly showField: import("@angular/core").InputSignal<boolean>;
4163
4321
  /** Reveal the built-in "required" message now (e.g. after a failed Save click). */
4164
4322
  readonly showErrors: import("@angular/core").InputSignal<boolean>;
4323
+ /**
4324
+ * Also report every refused file (wrong type, too big, too small, empty) with a `ToastService` error toast that names the file and
4325
+ * the reason, e.g. `"scan.exe" was not added. Only PDF files are allowed.` Meant for the picker-only mode (`[showField]="false"`),
4326
+ * where no field is visible to show the message; it works with a visible field too. Several refused files make ONE toast listing each.
4327
+ * Default `false`: nothing is toasted (the field message and `(fileRejected)` are unchanged). Needs a `ui-toast` outlet like any toast.
4328
+ */
4329
+ readonly toastOnReject: import("@angular/core").InputSignal<boolean>;
4165
4330
  /** Show a Remove button next to the chosen file. */
4166
4331
  readonly clearable: import("@angular/core").InputSignal<boolean>;
4167
4332
  readonly removeLabel: import("@angular/core").InputSignal<string>;
@@ -4207,6 +4372,7 @@ export declare class FileInputComponent implements ControlValueAccessor, Validat
4207
4372
  private readonly fileEl;
4208
4373
  protected readonly _dragging: import("@angular/core").WritableSignal<boolean>;
4209
4374
  /** Message of the last refused file ('' when the last pick was fine); shown in every mode. */
4375
+ private readonly _toast;
4210
4376
  private readonly _rejection;
4211
4377
  private readonly _reveal;
4212
4378
  private readonly _issue;
@@ -4304,6 +4470,11 @@ export declare class FileInputComponent implements ControlValueAccessor, Validat
4304
4470
  "required": false;
4305
4471
  "isSignal": true;
4306
4472
  };
4473
+ "toastOnReject": {
4474
+ "alias": "toastOnReject";
4475
+ "required": false;
4476
+ "isSignal": true;
4477
+ };
4307
4478
  "clearable": {
4308
4479
  "alias": "clearable";
4309
4480
  "required": false;
@@ -4400,7 +4571,8 @@ export declare class DateInputComponent implements ControlValueAccessor, Validat
4400
4571
  readonly error: import("@angular/core").InputSignal<string>;
4401
4572
  /** Reveal the built-in error messages now (e.g. after a failed Save click), without waiting for blur. */
4402
4573
  readonly showErrors: import("@angular/core").InputSignal<boolean>;
4403
- protected readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
4574
+ /** The `[disabled]` input. Public so `[disabled]="x"` in a host template type-checks (a protected alias target fails with TS2445); disabled when this OR the form control says so. */
4575
+ readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
4404
4576
  private readonly _cvaDisabled;
4405
4577
  protected readonly disabled: import("@angular/core").Signal<boolean>;
4406
4578
  protected readonly _value: import("@angular/core").WritableSignal<string>;
@@ -5183,6 +5355,24 @@ export declare class FormRowComponent {
5183
5355
  };
5184
5356
  }, {}, never, ["*"], true, never>;
5185
5357
  }
5358
+ /**
5359
+ * Lets a direct child of `ui-form-row` span several columns: `<ui-text-input uiColSpan="2" .../>` (2 or 3 columns) or
5360
+ * `uiColSpan="all"` (every column). It only adds the class `ui-span-2` / `ui-span-3` / `ui-span-all`, which `ui-form-row` styles, so a
5361
+ * plain `class="ui-span-2"` on the child works too without importing this directive. On a phone (<= 480px) the row is one column and the
5362
+ * child simply takes the full width. Keep a numeric span within the row's `cols` (use `all` for the whole row).
5363
+ */
5364
+ export declare class FormColSpanDirective {
5365
+ readonly uiColSpan: import("@angular/core").InputSignal<"" | "2" | "3" | 2 | 3 | "all">;
5366
+ protected readonly _class: import("@angular/core").Signal<string>;
5367
+ static ɵfac: i0.ɵɵFactoryDeclaration<FormColSpanDirective, never>;
5368
+ static ɵdir: i0.ɵɵDirectiveDeclaration<FormColSpanDirective, "[uiColSpan]", never, {
5369
+ "uiColSpan": {
5370
+ "alias": "uiColSpan";
5371
+ "required": false;
5372
+ "isSignal": true;
5373
+ };
5374
+ }, {}, never, never, true, never>;
5375
+ }
5186
5376
  /**
5187
5377
  * Fixed-layout list item with an optional leading radio/checkbox, a title + badge,
5188
5378
  * and a secondary detail row rendered from a string array. All layout is handled
@@ -5733,6 +5923,16 @@ export interface PanelInfoItem {
5733
5923
  }>;
5734
5924
  /** Router link for the value. */
5735
5925
  link?: string;
5926
+ /**
5927
+ * A real `<a href>` for the value (the visible `value` is the link text). Only `mailto:`, `tel:`, `http:` and `https:` are
5928
+ * allowed; any other scheme (`javascript:`, `data:` ...) renders the value as plain text. `http(s)` links open in a new tab with
5929
+ * `rel="noopener noreferrer"`. Wins over `email` / `phone` / `link`.
5930
+ */
5931
+ href?: string;
5932
+ /** Shortcut: the value becomes a `mailto:` link to this address (the value defaults to the address). */
5933
+ email?: string;
5934
+ /** Shortcut: the value becomes a `tel:` link to this number (digits and a leading + are kept; the value defaults to the number as written). */
5935
+ phone?: string;
5736
5936
  /** Show the value with an "open" icon instead of blue link styling. */
5737
5937
  linkIcon?: boolean;
5738
5938
  /** Renders a small edit (pencil) icon button after the value. */
@@ -5766,6 +5966,14 @@ export declare class PanelInfoListComponent {
5766
5966
  readonly sections: import("@angular/core").InputSignal<PanelInfoSection[]>;
5767
5967
  readonly showEmptyState: import("@angular/core").InputSignal<boolean>;
5768
5968
  readonly displaySections: import("@angular/core").Signal<PanelInfoSection[]>;
5969
+ /**
5970
+ * The safe href of an item, or null: `href` first, else `mailto:`/`tel:` built from `email`/`phone`. Only mailto, tel, http and https
5971
+ * are allowed (the scheme is checked after removing control characters and spaces, like browsers do).
5972
+ */
5973
+ hrefOf(item: PanelInfoItem): string | null;
5974
+ isWeb(href: string): boolean;
5975
+ /** Link text: the value, else the email / phone as written. */
5976
+ textOf(item: PanelInfoItem): string;
5769
5977
  visibleItems(section: PanelInfoSection): PanelInfoItem[];
5770
5978
  static ɵfac: i0.ɵɵFactoryDeclaration<PanelInfoListComponent, never>;
5771
5979
  static ɵcmp: i0.ɵɵComponentDeclaration<PanelInfoListComponent, "ui-panel-info-list", never, {
@@ -6098,9 +6306,9 @@ export declare class AppShellComponent implements OnInit, OnDestroy {
6098
6306
  "logoutClick": "logoutClick";
6099
6307
  }, never, ["[shell-brand]", "[shell-header-end]", "[shell-banners]", "*"], true, never>;
6100
6308
  }
6101
- export type AlertVariant = 'info' | 'success' | 'warning' | 'danger';
6309
+ export type AlertVariant = 'info' | 'success' | 'warning' | 'danger' | 'neutral';
6102
6310
  /**
6103
- * Inline status message (info / success / warning / danger) with an optional title,
6311
+ * Inline status message (info / success / warning / danger / neutral gray) with an optional title,
6104
6312
  * optional dismiss button, and projected body content (text, links, a retry ui-button…).
6105
6313
  * `quiet` drops the live-region role (no announcement) and `compact` tightens it for list rows — both off by default.
6106
6314
  *
@@ -6155,19 +6363,10 @@ export declare class AlertComponent {
6155
6363
  "dismissed": "dismissed";
6156
6364
  }, never, ["*"], true, never>;
6157
6365
  }
6158
- /**
6159
- * Small muted helper text shown under a form or panel section.
6160
- *
6161
- * <ui-hint>This does not affect the scheduled send date.</ui-hint>
6162
- */
6163
- export declare class HintComponent {
6164
- static ɵfac: i0.ɵɵFactoryDeclaration<HintComponent, never>;
6165
- static ɵcmp: i0.ɵɵComponentDeclaration<HintComponent, "ui-hint", never, {}, {}, never, ["*"], true, never>;
6166
- }
6167
6366
  /** The SVG path (24×24 stroke icon) for an icon key, or undefined when the key is unknown. */
6168
6367
  export declare function iconPath(name: string): string | undefined;
6169
6368
  /** Keys with an icon of their own (the data-table action keys are accepted too — see `builtInActionIcon`). */
6170
- export type IconName = 'add' | 'close' | 'check' | 'upload' | 'image' | 'chevron-up' | 'chevron-down' | 'arrow-left' | 'bell' | 'print' | 'view' | 'edit' | 'delete' | 'download' | 'duplicate' | 'archive' | 'restore' | 'share' | 'email' | 'message' | 'call';
6369
+ export type IconName = 'add' | 'close' | 'check' | 'upload' | 'image' | 'chevron-up' | 'chevron-down' | 'arrow-left' | 'bell' | 'print' | 'lock' | 'arrow-up' | 'arrow-down' | 'arrow-right' | 'document' | 'grip' | 'card' | 'bank' | 'view' | 'edit' | 'delete' | 'download' | 'duplicate' | 'archive' | 'restore' | 'share' | 'email' | 'message' | 'call';
6171
6370
  /**
6172
6371
  * A clickable icon. The host passes a key (`name="delete"`) and the library draws that icon; clicking it emits
6173
6372
  * `iconClick`, and the host does the actual work (delete the row, open a panel, …).
@@ -6251,6 +6450,71 @@ export declare class IconComponent {
6251
6450
  "iconClick": "iconClick";
6252
6451
  }, never, never, true, never>;
6253
6452
  }
6453
+ export type TimelineTone = 'default' | 'success' | 'warning' | 'danger';
6454
+ export interface TimelineItem {
6455
+ /** Stable id used for `track`; the index is used when absent. */
6456
+ id?: string;
6457
+ title: string;
6458
+ description?: string;
6459
+ /** Pre-formatted time text shown to the reader, e.g. "Oct 20, 2026, 3:15 PM". */
6460
+ time?: string;
6461
+ /** ISO date / date-time for the `datetime` attribute of the `<time>` element (machine-readable). */
6462
+ dateTime?: string;
6463
+ badge?: {
6464
+ label: string;
6465
+ variant: BadgeVariant;
6466
+ };
6467
+ /** Icon drawn inside the dot (static, decorative). Unknown names draw nothing. */
6468
+ icon?: IconName | (string & {});
6469
+ /** Colour of the dot / icon. Default `default`. */
6470
+ tone?: TimelineTone;
6471
+ }
6472
+ /**
6473
+ * Vertical activity feed: an ordered list of events joined by a line, each with a dot (or icon), title, optional badge,
6474
+ * description and time.
6475
+ *
6476
+ * <ui-timeline ariaLabel="Case activity" emptyMessage="No activity yet." [items]="[
6477
+ * { id: 'a', title: 'Case opened', time: 'Oct 20, 3:15 PM', dateTime: '2026-10-20T15:15:00Z', badge: { label: 'Open', variant: 'green' } },
6478
+ * { id: 'b', title: 'Letter sent', description: 'Mailed to the owner.', tone: 'success', icon: 'email' },
6479
+ * ]" />
6480
+ *
6481
+ * Semantics: `<ol>` / `<li>`; the line and dots are decorative (aria-hidden). `time` is the visible text; `dateTime` goes into
6482
+ * `<time datetime>`. With no items, `emptyMessage` (if set) is shown as a hint, otherwise nothing is rendered.
6483
+ */
6484
+ export declare class TimelineComponent {
6485
+ readonly items: import("@angular/core").InputSignal<TimelineItem[]>;
6486
+ /** Accessible name of the list (e.g. "Case activity"). */
6487
+ readonly ariaLabel: import("@angular/core").InputSignal<string>;
6488
+ /** Shown (as a hint) when there are no items. Empty = render nothing. */
6489
+ readonly emptyMessage: import("@angular/core").InputSignal<string>;
6490
+ static ɵfac: i0.ɵɵFactoryDeclaration<TimelineComponent, never>;
6491
+ static ɵcmp: i0.ɵɵComponentDeclaration<TimelineComponent, "ui-timeline", never, {
6492
+ "items": {
6493
+ "alias": "items";
6494
+ "required": false;
6495
+ "isSignal": true;
6496
+ };
6497
+ "ariaLabel": {
6498
+ "alias": "ariaLabel";
6499
+ "required": false;
6500
+ "isSignal": true;
6501
+ };
6502
+ "emptyMessage": {
6503
+ "alias": "emptyMessage";
6504
+ "required": false;
6505
+ "isSignal": true;
6506
+ };
6507
+ }, {}, never, never, true, never>;
6508
+ }
6509
+ /**
6510
+ * Small muted helper text shown under a form or panel section.
6511
+ *
6512
+ * <ui-hint>This does not affect the scheduled send date.</ui-hint>
6513
+ */
6514
+ export declare class HintComponent {
6515
+ static ɵfac: i0.ɵɵFactoryDeclaration<HintComponent, never>;
6516
+ static ɵcmp: i0.ɵɵComponentDeclaration<HintComponent, "ui-hint", never, {}, {}, never, ["*"], true, never>;
6517
+ }
6254
6518
  export type ImagePreviewShape = 'circle' | 'rounded';
6255
6519
  export type ImagePreviewSize = 'sm' | 'md' | 'lg';
6256
6520
  export type ImagePreviewPlaceholder = 'person' | 'image';
@@ -6741,10 +7005,15 @@ export declare class RadioComponent {
6741
7005
  readonly invalid: import("@angular/core").InputSignal<boolean>;
6742
7006
  /** Id(s) of the element(s) describing the group (hint / error). */
6743
7007
  readonly describedBy: import("@angular/core").InputSignal<string>;
7008
+ /** Id of an element this radio reveals while selected (`aria-controls`); no attribute when empty. */
7009
+ readonly controls: import("@angular/core").InputSignal<string>;
6744
7010
  /** Public so a host template can bind `[disabled]` (a protected input fails strict template type-checking). */
6745
7011
  readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
6746
7012
  protected readonly disabled: import("@angular/core").InputSignal<boolean>;
6747
- protected readonly _labelId: string;
7013
+ /** 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. */
7014
+ readonly labelId: import("@angular/core").InputSignal<string>;
7015
+ private readonly _generatedLabelId;
7016
+ protected readonly _labelId: import("@angular/core").Signal<string>;
6748
7017
  /** With a description inside the <label>, the accessible name would read "Email We send a message": name the input by the label text only. */
6749
7018
  protected readonly _labelledBy: import("@angular/core").Signal<string | null>;
6750
7019
  protected readonly _descriptionId: string;
@@ -6795,15 +7064,51 @@ export declare class RadioComponent {
6795
7064
  "required": false;
6796
7065
  "isSignal": true;
6797
7066
  };
7067
+ "controls": {
7068
+ "alias": "controls";
7069
+ "required": false;
7070
+ "isSignal": true;
7071
+ };
6798
7072
  "_disabledInput": {
6799
7073
  "alias": "disabled";
6800
7074
  "required": false;
6801
7075
  "isSignal": true;
6802
7076
  };
7077
+ "labelId": {
7078
+ "alias": "labelId";
7079
+ "required": false;
7080
+ "isSignal": true;
7081
+ };
6803
7082
  }, {
6804
7083
  "selected": "selected";
6805
7084
  }, never, ["*"], true, never>;
6806
7085
  }
7086
+ /**
7087
+ * Content shown directly under ONE option of a `ui-radio-group`, only while that option is selected (e.g. an address form under
7088
+ * "Ship to an alternate address"). Put an `<ng-template>` inside the group and name the option's value:
7089
+ *
7090
+ * <ui-radio-group label="Delivery" [options]="opts" [(ngModel)]="method">
7091
+ * <ng-template uiRadioOptionContent="SHIP">
7092
+ * <ui-text-input label="Street" ... />
7093
+ * </ng-template>
7094
+ * </ui-radio-group>
7095
+ *
7096
+ * Groups without such a template render exactly as before. The content is indented under the option's label; in a horizontal group it
7097
+ * takes a full row below the options. It lives inside the group's fieldset, so moving focus into it does not count as leaving the group.
7098
+ */
7099
+ export declare class RadioOptionContentDirective {
7100
+ /** The `value` of the option this content belongs to. */
7101
+ readonly value: import("@angular/core").InputSignal<string>;
7102
+ readonly template: TemplateRef<unknown>;
7103
+ static ɵfac: i0.ɵɵFactoryDeclaration<RadioOptionContentDirective, never>;
7104
+ static ɵdir: i0.ɵɵDirectiveDeclaration<RadioOptionContentDirective, "ng-template[uiRadioOptionContent]", never, {
7105
+ "value": {
7106
+ "alias": "uiRadioOptionContent";
7107
+ "required": true;
7108
+ "isSignal": true;
7109
+ };
7110
+ }, {}, never, never, true, never>;
7111
+ }
6807
7112
  /** One row of a `ui-radio-matrix`: `value` is the key in the model, `label` the row header. */
6808
7113
  export interface RadioMatrixRow {
6809
7114
  value: string;
@@ -6931,6 +7236,300 @@ export declare class RadioMatrixComponent implements ControlValueAccessor, Valid
6931
7236
  "invalidChange": "invalidChange";
6932
7237
  }, never, never, true, never>;
6933
7238
  }
7239
+ /**
7240
+ * A pad to draw a signature (or initials) on: a ControlValueAccessor whose value is a PNG data URL (`null` = empty).
7241
+ *
7242
+ * <ui-signature-pad label="Your signature" [(ngModel)]="signature" />
7243
+ * <ui-signature-pad ariaLabel="Initials" [outputWidth]="200" [outputHeight]="60" (signatureChange)="onSigned($event)" />
7244
+ *
7245
+ * Drawing works with a mouse, a finger or a pen (pointer events; the pad blocks touch scrolling while you draw) and with the keyboard:
7246
+ * focus the pad, move the cursor with the arrow keys (Shift = bigger steps), hold Space to draw, Escape hides the cursor (it does not
7247
+ * leave the dialog the pad may sit in until the cursor is hidden). When a stroke ends the drawing is cropped to its content (4px margin),
7248
+ * scaled to fit `outputWidth` x `outputHeight` (left-aligned, vertically centered) and emitted, so every signature has the same visual
7249
+ * weight. Clear empties the pad. `disabled` (input or form control) blocks drawing.
7250
+ *
7251
+ * The pad is shown at the container's width and keeps the bitmap's aspect ratio (`width` : `height`), so ink is never stretched and the saved PNG
7252
+ * looks like what was drawn. Changing `width` / `height` after drawing repaints the current signature (scaled to fit) instead of losing it.
7253
+ * Screen readers get the keyboard instructions as a description of the pad and a polite "Signature captured" / "Signature cleared" announcement.
7254
+ *
7255
+ * Public methods: `clear()`, `isEmpty()` and `toDataUrl()` (the current normalized signature, or `null` when empty).
7256
+ */
7257
+ export declare class SignaturePadComponent implements ControlValueAccessor {
7258
+ readonly label: import("@angular/core").InputSignal<string>;
7259
+ /** Accessible name when there is no visible label. A default describing the keyboard controls is used when neither is set. */
7260
+ readonly ariaLabel: import("@angular/core").InputSignal<string>;
7261
+ readonly hint: import("@angular/core").InputSignal<string>;
7262
+ readonly error: import("@angular/core").InputSignal<string>;
7263
+ /** Bitmap size of the drawing surface in pixels. The pad is displayed at the container's width with this same aspect ratio, so strokes keep their proportions. */
7264
+ readonly width: import("@angular/core").InputSignal<number>;
7265
+ readonly height: import("@angular/core").InputSignal<number>;
7266
+ /** Size of the emitted PNG: the drawing is cropped to its content and scaled to fit this box. */
7267
+ readonly outputWidth: import("@angular/core").InputSignal<number>;
7268
+ readonly outputHeight: import("@angular/core").InputSignal<number>;
7269
+ readonly penColor: import("@angular/core").InputSignal<string>;
7270
+ readonly penWidth: import("@angular/core").InputSignal<number>;
7271
+ /** Show the built-in Clear button under the pad. */
7272
+ readonly showClear: import("@angular/core").InputSignal<boolean>;
7273
+ readonly clearLabel: import("@angular/core").InputSignal<string>;
7274
+ readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
7275
+ /** Emits the normalized PNG data URL when a stroke ends, and `null` when the pad is cleared. */
7276
+ readonly signatureChange: import("@angular/core").OutputEmitterRef<string | null>;
7277
+ private readonly _canvas;
7278
+ private readonly _cvaDisabled;
7279
+ protected readonly disabled: import("@angular/core").Signal<boolean>;
7280
+ protected readonly _empty: import("@angular/core").WritableSignal<boolean>;
7281
+ protected readonly _cursorVisible: import("@angular/core").WritableSignal<boolean>;
7282
+ protected readonly _cursorX: import("@angular/core").WritableSignal<number>;
7283
+ protected readonly _cursorY: import("@angular/core").WritableSignal<number>;
7284
+ protected readonly _keyboardDrawing: import("@angular/core").WritableSignal<boolean>;
7285
+ protected readonly _announcement: import("@angular/core").WritableSignal<string>;
7286
+ protected readonly _keyboardHelp = "Use the arrow keys to move the cursor, hold Space to draw, press Escape to hide the cursor.";
7287
+ private readonly _injector;
7288
+ private readonly _id;
7289
+ protected readonly _labelId: string;
7290
+ protected readonly _descId: string;
7291
+ protected readonly _helpId: string;
7292
+ /** The `ariaLabel`; with neither it nor a visible `label`, a default name (the canvas always has one). The keyboard instructions are a separate description. */
7293
+ protected readonly _accessibleName: import("@angular/core").Signal<string | null>;
7294
+ /** The error / hint (when shown) plus the always-present keyboard instructions, so they are announced whatever names the canvas. */
7295
+ protected readonly _describedBy: import("@angular/core").Signal<string>;
7296
+ private _ctx;
7297
+ private _pointerId;
7298
+ private _dirty;
7299
+ /** A value was written before the canvas existed: the setup effect paints it. */
7300
+ private _pendingImage;
7301
+ private _value;
7302
+ /** A written / repainted image is still decoding: the bitmap does not hold the signature yet, `_value` does. */
7303
+ private _loading;
7304
+ /** `width`x`height` the bitmap was last set up for; a change wipes the canvas, so the signature is repainted from `_value`. */
7305
+ private _sizeKey;
7306
+ private _onChange;
7307
+ private _onTouched;
7308
+ constructor();
7309
+ isEmpty(): boolean;
7310
+ /** The current signature as a normalized PNG data URL, or `null` when nothing is drawn. */
7311
+ toDataUrl(): string | null;
7312
+ /** Empties the pad and tells the form (value `null`). */
7313
+ clear(): void;
7314
+ writeValue(value: string | null): void;
7315
+ /** Draws a written value scaled to fit, left-aligned and vertically centered (ignored when the value was replaced while it loaded). */
7316
+ private _paint;
7317
+ /**
7318
+ * Assigning the canvas `width` / `height` wipes the bitmap while `_value` and `_empty` still describe a signature: once the new size is
7319
+ * rendered, paint the current signature (the last committed / written PNG, scaled to fit) again so state and bitmap agree.
7320
+ */
7321
+ private _repaintAfterResize;
7322
+ registerOnChange(fn: (value: string | null) => void): void;
7323
+ registerOnTouched(fn: () => void): void;
7324
+ setDisabledState(disabled: boolean): void;
7325
+ protected onPointerDown(event: PointerEvent): void;
7326
+ protected onPointerMove(event: PointerEvent): void;
7327
+ protected onPointerEnd(event: PointerEvent): void;
7328
+ protected onKeyDown(event: KeyboardEvent): void;
7329
+ protected onKeyUp(event: KeyboardEvent): void;
7330
+ protected onBlur(): void;
7331
+ private _stopKeyboardStroke;
7332
+ /** A stroke ended: normalize the drawing, publish it to the form and the output. */
7333
+ private _commit;
7334
+ private _setUpContext;
7335
+ /** The drawing context, created on first use (a form can write its value before the setup effect has run). */
7336
+ private _contextOf;
7337
+ /**
7338
+ * Pen settings go on the context at the start of every stroke as well as in the setup effect: assigning the canvas `width` / `height`
7339
+ * (the `[width]` / `[height]` bindings, which run after the effect on the first render and on every size change) resets the context state.
7340
+ */
7341
+ private _applyPen;
7342
+ private _clearBitmap;
7343
+ /** Display coordinates -> bitmap coordinates (the pad is scaled by CSS). */
7344
+ private _pointOf;
7345
+ /** Crop the drawing to its content (4px margin) and scale it into `outputWidth` x `outputHeight`, left-aligned and vertically centered. */
7346
+ private _normalize;
7347
+ static ɵfac: i0.ɵɵFactoryDeclaration<SignaturePadComponent, never>;
7348
+ static ɵcmp: i0.ɵɵComponentDeclaration<SignaturePadComponent, "ui-signature-pad", never, {
7349
+ "label": {
7350
+ "alias": "label";
7351
+ "required": false;
7352
+ "isSignal": true;
7353
+ };
7354
+ "ariaLabel": {
7355
+ "alias": "ariaLabel";
7356
+ "required": false;
7357
+ "isSignal": true;
7358
+ };
7359
+ "hint": {
7360
+ "alias": "hint";
7361
+ "required": false;
7362
+ "isSignal": true;
7363
+ };
7364
+ "error": {
7365
+ "alias": "error";
7366
+ "required": false;
7367
+ "isSignal": true;
7368
+ };
7369
+ "width": {
7370
+ "alias": "width";
7371
+ "required": false;
7372
+ "isSignal": true;
7373
+ };
7374
+ "height": {
7375
+ "alias": "height";
7376
+ "required": false;
7377
+ "isSignal": true;
7378
+ };
7379
+ "outputWidth": {
7380
+ "alias": "outputWidth";
7381
+ "required": false;
7382
+ "isSignal": true;
7383
+ };
7384
+ "outputHeight": {
7385
+ "alias": "outputHeight";
7386
+ "required": false;
7387
+ "isSignal": true;
7388
+ };
7389
+ "penColor": {
7390
+ "alias": "penColor";
7391
+ "required": false;
7392
+ "isSignal": true;
7393
+ };
7394
+ "penWidth": {
7395
+ "alias": "penWidth";
7396
+ "required": false;
7397
+ "isSignal": true;
7398
+ };
7399
+ "showClear": {
7400
+ "alias": "showClear";
7401
+ "required": false;
7402
+ "isSignal": true;
7403
+ };
7404
+ "clearLabel": {
7405
+ "alias": "clearLabel";
7406
+ "required": false;
7407
+ "isSignal": true;
7408
+ };
7409
+ "_disabledInput": {
7410
+ "alias": "disabled";
7411
+ "required": false;
7412
+ "isSignal": true;
7413
+ };
7414
+ }, {
7415
+ "signatureChange": "signatureChange";
7416
+ }, never, never, true, never>;
7417
+ }
7418
+ /**
7419
+ * A "sign here" spot placed over a rendered PDF page, at the coordinates the document gives (pixels from the page's top-left corner).
7420
+ * Put it inside a `position: relative` element that holds the page, one per field:
7421
+ *
7422
+ * <div style="position: relative; width: 612px; height: 792px">
7423
+ * <canvas ...></canvas>
7424
+ * <ui-pdf-hotspot [x]="f.x" [y]="f.y" [width]="f.width" [height]="f.height"
7425
+ * [state]="ready ? 'ready' : 'blocked'" label="Sign Here" blockedLabel="Add signature above"
7426
+ * ariaLabel="Click to sign here" [image]="f.signatureImage" (activate)="apply(f)" />
7427
+ * </div>
7428
+ *
7429
+ * `state="ready"` is a clickable button (`label`), `"blocked"` the same button disabled (`blockedLabel`, e.g. "create your signature first"),
7430
+ * and `"signed"` shows the applied `image` (a signature data URL) contained inside the box instead (signed without an image is a disabled button showing `label`). The box size comes from the document
7431
+ * so the text is scaled to it (height x 0.25, clamped to 7-11px); on touch devices the tap area is extended to at least 44px tall.
7432
+ *
7433
+ * Inside an ancestor scaled with CSS `transform: scale(s)` (e.g. a PDF page shrunk to fit a phone), pass that factor as `scale` so the tap area
7434
+ * stays at least 44 CSS px on screen (the area is made 44 / s px tall before the ancestor shrinks it). Default 1; values <= 0, NaN or
7435
+ * non-finite count as 1. Only the touch tap area changes, not the look, font size or accessibility.
7436
+ *
7437
+ * <div [style.transform]="'scale(' + s + ')'" style="transform-origin: top left">
7438
+ * <ui-pdf-hotspot ... [scale]="s" /> <!-- s = 0.5 -> tap area at least 88px tall before scaling = 44px on screen -->
7439
+ * </div>
7440
+ */
7441
+ export declare class PdfHotspotComponent {
7442
+ /** Position and size in pixels, from the page's top-left corner. */
7443
+ readonly x: import("@angular/core").InputSignal<number>;
7444
+ readonly y: import("@angular/core").InputSignal<number>;
7445
+ readonly width: import("@angular/core").InputSignal<number>;
7446
+ readonly height: import("@angular/core").InputSignal<number>;
7447
+ /** `ready`: clickable; `blocked`: disabled (a prerequisite is missing); `signed`: shows `image`. */
7448
+ readonly state: import("@angular/core").InputSignal<"ready" | "blocked" | "signed">;
7449
+ /** `warning` gives the ready state an amber look (e.g. for initials), default is blue. */
7450
+ readonly tone: import("@angular/core").InputSignal<"primary" | "warning">;
7451
+ /** Text of the ready button (e.g. "Sign Here"). */
7452
+ readonly label: import("@angular/core").InputSignal<string>;
7453
+ /** Text of the blocked button (e.g. "Add signature above"). */
7454
+ readonly blockedLabel: import("@angular/core").InputSignal<string>;
7455
+ /** Accessible name of the button (its text is used when empty). */
7456
+ readonly ariaLabel: import("@angular/core").InputSignal<string>;
7457
+ /** The applied signature (data URL), shown when `state` is `signed`. */
7458
+ readonly image: import("@angular/core").InputSignal<string | null>;
7459
+ readonly imageAlt: import("@angular/core").InputSignal<string>;
7460
+ /** The CSS scale factor an ancestor applies (`transform: scale(s)`); keeps the touch tap area at least 44px on screen. Invalid values count as 1. */
7461
+ readonly scale: import("@angular/core").InputSignal<number>;
7462
+ /** The ready button was clicked. */
7463
+ readonly activate: import("@angular/core").OutputEmitterRef<void>;
7464
+ /** `--ph-scale` value, or null (no property at all) for scale 1 and invalid values. */
7465
+ protected readonly _scaleVar: import("@angular/core").Signal<string | null>;
7466
+ protected readonly fontSize: import("@angular/core").Signal<number>;
7467
+ static ɵfac: i0.ɵɵFactoryDeclaration<PdfHotspotComponent, never>;
7468
+ static ɵcmp: i0.ɵɵComponentDeclaration<PdfHotspotComponent, "ui-pdf-hotspot", never, {
7469
+ "x": {
7470
+ "alias": "x";
7471
+ "required": false;
7472
+ "isSignal": true;
7473
+ };
7474
+ "y": {
7475
+ "alias": "y";
7476
+ "required": false;
7477
+ "isSignal": true;
7478
+ };
7479
+ "width": {
7480
+ "alias": "width";
7481
+ "required": false;
7482
+ "isSignal": true;
7483
+ };
7484
+ "height": {
7485
+ "alias": "height";
7486
+ "required": false;
7487
+ "isSignal": true;
7488
+ };
7489
+ "state": {
7490
+ "alias": "state";
7491
+ "required": false;
7492
+ "isSignal": true;
7493
+ };
7494
+ "tone": {
7495
+ "alias": "tone";
7496
+ "required": false;
7497
+ "isSignal": true;
7498
+ };
7499
+ "label": {
7500
+ "alias": "label";
7501
+ "required": false;
7502
+ "isSignal": true;
7503
+ };
7504
+ "blockedLabel": {
7505
+ "alias": "blockedLabel";
7506
+ "required": false;
7507
+ "isSignal": true;
7508
+ };
7509
+ "ariaLabel": {
7510
+ "alias": "ariaLabel";
7511
+ "required": false;
7512
+ "isSignal": true;
7513
+ };
7514
+ "image": {
7515
+ "alias": "image";
7516
+ "required": false;
7517
+ "isSignal": true;
7518
+ };
7519
+ "imageAlt": {
7520
+ "alias": "imageAlt";
7521
+ "required": false;
7522
+ "isSignal": true;
7523
+ };
7524
+ "scale": {
7525
+ "alias": "scale";
7526
+ "required": false;
7527
+ "isSignal": true;
7528
+ };
7529
+ }, {
7530
+ "activate": "activate";
7531
+ }, never, never, true, never>;
7532
+ }
6934
7533
  /**
6935
7534
  * Card for detail pages: an optional header and a body, both filled by the page that uses it.
6936
7535
  *
@@ -6948,7 +7547,7 @@ export declare class RadioMatrixComponent implements ControlValueAccessor, Valid
6948
7547
  * - `collapsible` (default true): a chevron toggle and a clickable header; `[(expanded)]` is two-way.
6949
7548
  * Without a header, or with `collapsible` false, the body is always open.
6950
7549
  *
6951
- * The title is always shown in capitals; the subtitle keeps the case you give it. The body is the default content slot. A collapsed body is removed from the tab order and from assistive tech.
7550
+ * The title is shown in capitals unless `[uppercaseTitle]="false"` (then it shows as written, e.g. "Case IDs"); the casing is CSS only, so the accessible name and heading text are always the text you gave; the subtitle keeps the case you give it. The body is the default content slot. A collapsed body is removed from the tab order and from assistive tech.
6952
7551
  *
6953
7552
  * <ui-detail-card title="COMMUNICATIONS" subtitle="All calls, texts, and emails"> ...body... </ui-detail-card>
6954
7553
  * <ui-detail-card title="CONTACT INFO" [showEdit]="true" (editClick)="openEdit()"> ... </ui-detail-card>
@@ -6963,6 +7562,8 @@ export declare class RadioMatrixComponent implements ControlValueAccessor, Valid
6963
7562
  export declare class DetailCardComponent {
6964
7563
  /** Bold uppercase title. Empty = no title text. */
6965
7564
  readonly title: import("@angular/core").InputSignal<string>;
7565
+ /** true (default) = the title is displayed in capitals (CSS only); false = shown as written. The text, aria-label and heading name are never changed. */
7566
+ readonly uppercaseTitle: import("@angular/core").InputSignal<boolean>;
6966
7567
  /** 1-6 makes the title a real heading for screen readers (role=heading, aria-level); null keeps it plain text. */
6967
7568
  readonly headingLevel: import("@angular/core").InputSignal<1 | 2 | 3 | 4 | 5 | 6 | null>;
6968
7569
  /** Optional id for the title text; the card is then labelled by it. Without it the title is the card's aria-label. */
@@ -6999,6 +7600,11 @@ export declare class DetailCardComponent {
6999
7600
  "required": false;
7000
7601
  "isSignal": true;
7001
7602
  };
7603
+ "uppercaseTitle": {
7604
+ "alias": "uppercaseTitle";
7605
+ "required": false;
7606
+ "isSignal": true;
7607
+ };
7002
7608
  "headingLevel": {
7003
7609
  "alias": "headingLevel";
7004
7610
  "required": false;