@forgeroute/ui 0.4.9 → 0.4.10

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.
@@ -578,7 +578,7 @@ export declare class ColumnFilterComponent {
578
578
  cancel(): void;
579
579
  clear(): void;
580
580
  onDocumentClick(_event: Event): void;
581
- onEscape(): void;
581
+ onEscape(event?: Event): void;
582
582
  onArrow(event: Event, dir: 1 | -1): void;
583
583
  /**
584
584
  * Places the fixed dropdown from the trigger's viewport rect: centred under the trigger, clamped
@@ -725,7 +725,7 @@ export declare class MoreMenuComponent {
725
725
  onDocumentClick(): void;
726
726
  /** A touch or mouse press anywhere outside the menu closes it (more reliable than a click on phones: iOS does not send clicks for plain page areas). */
727
727
  onDocumentPointerDown(event: Event): void;
728
- onEscape(): void;
728
+ onEscape(event?: Event): void;
729
729
  onArrow(event: Event, dir: 1 | -1): void;
730
730
  /** Visible top/bottom of the nearest scrolling ancestor, clipped to the viewport. */
731
731
  private _visibleBounds;
@@ -961,7 +961,7 @@ export declare class SelectComponent implements ControlValueAccessor, Validator,
961
961
  readonly error: import("@angular/core").InputSignal<string>;
962
962
  /** Reveal the built-in error messages now (e.g. after a failed Save click), without waiting for blur. */
963
963
  readonly showErrors: import("@angular/core").InputSignal<boolean>;
964
- readonly size: import("@angular/core").InputSignal<"sm" | "default">;
964
+ readonly size: import("@angular/core").InputSignal<"default" | "sm">;
965
965
  readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
966
966
  private readonly _cvaDisabled;
967
967
  protected readonly disabled: import("@angular/core").Signal<boolean>;
@@ -1909,7 +1909,7 @@ export declare class ModalComponent implements OnInit, OnDestroy {
1909
1909
  readonly title: import("@angular/core").InputSignal<string>;
1910
1910
  readonly description: import("@angular/core").InputSignal<string>;
1911
1911
  readonly maxWidth: import("@angular/core").InputSignal<string>;
1912
- readonly bodyOverflow: import("@angular/core").InputSignal<"auto" | "hidden" | "visible">;
1912
+ readonly bodyOverflow: import("@angular/core").InputSignal<"hidden" | "auto" | "visible">;
1913
1913
  /** `data-testid` of the dialog element itself (the host `<ui-modal>` is always in the page, the dialog only while open). None when empty. */
1914
1914
  readonly dialogTestId: import("@angular/core").InputSignal<string>;
1915
1915
  /** Hides the header X button (e.g. while a request is running). Escape and a backdrop click still close unless `closable` is false. */
@@ -2809,6 +2809,8 @@ export interface StepperStep {
2809
2809
  selectable?: boolean;
2810
2810
  }
2811
2811
  export type StepperOrientation = 'horizontal' | 'vertical';
2812
+ /** Viewport width below which a `compact` stepper shows its summary: 'sm' (480px) | 'md' (768px) | 'lg' (1024px) or a pixel number. */
2813
+ export type StepperCompactBreakpoint = 'sm' | 'md' | 'lg' | number;
2812
2814
  /**
2813
2815
  * Step indicator for wizards, onboarding flows and progress timelines. The state of every step comes from the order of
2814
2816
  * `steps` and the key in `current`: steps before it are complete, it is current, steps after it are upcoming.
@@ -2855,6 +2857,22 @@ export type StepperOrientation = 'horizontal' | 'vertical';
2855
2857
  * on the left). Long labels wrap. At <= 480px a horizontal stepper with `labelsOnSmallScreens="current"` (default) shows
2856
2858
  * only the current step's label (the others stay in the accessible name); `"all"` keeps them. Touch devices and phones
2857
2859
  * get >= 44px tall step buttons. The connector transition honours `prefers-reduced-motion`.
2860
+ *
2861
+ * Wide / responsive headers (all optional, default off, nothing changes without them):
2862
+ * - `scrollable`: the step list sits in an `overflow-x: auto` region with 4px top / bottom padding so focus rings are not clipped.
2863
+ * - `minStepWidth` (CSS length, e.g. `10.5rem`): horizontal only; the list gets `min-width: calc(<step count> * <minStepWidth>)`, so with
2864
+ * `scrollable` it scrolls sideways instead of breaking labels mid-word. The page-level `max-width` / centring stays the host's job.
2865
+ * - `<img stepper-leading>` (any element with the `stepper-leading` attribute) + `leadingWidth` (CSS length): a logo shown at the start of a
2866
+ * horizontal stepper, vertically centred and absolutely positioned, so the steps stay centred; the steps start at `leadingWidth + 1rem`.
2867
+ * Hidden in the compact summary and in vertical orientation.
2868
+ * - `compact` (`'sm' | 'md' | 'lg'` or a pixel number; default null = never): below that viewport width (a width exactly at it is NOT below)
2869
+ * the list is hidden (`display: none`, so it leaves the accessibility tree) and a summary is shown instead: the current step's label
2870
+ * (semibold, large, in `accentColor` when set) with "n / m" at the right, and a `ui-progress-bar` (`aria-label` "Step n of m: <label>").
2871
+ * At / above the breakpoint the summary is hidden. Without a current step the summary reads "0 / m".
2872
+ *
2873
+ * <ui-stepper [steps]="steps" [current]="key" [scrollable]="true" minStepWidth="10.5rem" leadingWidth="7.5rem" compact="md" accentColor="#f97316">
2874
+ * <img stepper-leading src="logo.svg" alt="Acme" />
2875
+ * </ui-stepper>
2858
2876
  */
2859
2877
  export declare class StepperComponent {
2860
2878
  /** The steps in order. Keys must be unique. */
@@ -2877,9 +2895,29 @@ export declare class StepperComponent {
2877
2895
  readonly ariaLabel: import("@angular/core").InputSignal<string>;
2878
2896
  /** Horizontal, <= 480px: show only the current step's label (`'current'`, default) or every label (`'all'`). */
2879
2897
  readonly labelsOnSmallScreens: import("@angular/core").InputSignal<"all" | "current">;
2898
+ /** CSS length (e.g. `10.5rem`): horizontal only - the list gets `min-width: calc(<step count> * <value>)`. Empty (default) = no minimum. */
2899
+ readonly minStepWidth: import("@angular/core").InputSignal<string>;
2900
+ /** true = the list scrolls sideways (`overflow-x: auto`, 4px top / bottom padding so focus rings are not clipped) instead of squeezing. Default false. */
2901
+ readonly scrollable: import("@angular/core").InputSignal<boolean>;
2902
+ /** CSS length: width reserved for the `[stepper-leading]` element (a logo); the steps start at this width + 1rem. Empty = no leading area. */
2903
+ readonly leadingWidth: import("@angular/core").InputSignal<string>;
2904
+ /** Below this viewport width ('sm' 480 | 'md' 768 | 'lg' 1024 | pixels) the list is replaced by a summary (label, "n / m", progress bar). null (default) = never. */
2905
+ readonly compact: import("@angular/core").InputSignal<StepperCompactBreakpoint | null>;
2880
2906
  /** Emits the key of an activated selectable step that was not already current (after `current` was updated). */
2881
2907
  readonly stepClick: import("@angular/core").OutputEmitterRef<string>;
2908
+ private readonly _win;
2909
+ private readonly _narrow;
2910
+ /** True when `compact` is a pixel number and the viewport is below it (tokens use CSS media queries instead). */
2911
+ protected readonly compactPx: import("@angular/core").Signal<boolean>;
2882
2912
  private readonly _id;
2913
+ constructor();
2914
+ protected readonly olMinWidth: import("@angular/core").Signal<string | null>;
2915
+ protected readonly summary: import("@angular/core").Signal<{
2916
+ n: number;
2917
+ m: number;
2918
+ label: string;
2919
+ aria: string;
2920
+ }>;
2883
2921
  protected readonly rows: import("@angular/core").Signal<{
2884
2922
  step: StepperStep;
2885
2923
  index: number;
@@ -2953,10 +2991,30 @@ export declare class StepperComponent {
2953
2991
  "required": false;
2954
2992
  "isSignal": true;
2955
2993
  };
2994
+ "minStepWidth": {
2995
+ "alias": "minStepWidth";
2996
+ "required": false;
2997
+ "isSignal": true;
2998
+ };
2999
+ "scrollable": {
3000
+ "alias": "scrollable";
3001
+ "required": false;
3002
+ "isSignal": true;
3003
+ };
3004
+ "leadingWidth": {
3005
+ "alias": "leadingWidth";
3006
+ "required": false;
3007
+ "isSignal": true;
3008
+ };
3009
+ "compact": {
3010
+ "alias": "compact";
3011
+ "required": false;
3012
+ "isSignal": true;
3013
+ };
2956
3014
  }, {
2957
3015
  "current": "currentChange";
2958
3016
  "stepClick": "stepClick";
2959
- }, never, never, true, never>;
3017
+ }, never, ["[stepper-leading]"], true, never>;
2960
3018
  }
2961
3019
  /** One weekday of the schedule. `open` / `close` are `HH:mm`; `open2` / `close2` are the optional second shift (split shift). */
2962
3020
  export interface BusinessHoursDay {
@@ -3448,13 +3506,19 @@ export declare class ButtonComponent {
3448
3506
  * `ghost-start`: a ghost button for list / section toggles - a full-width row with its content aligned to the start, transparent
3449
3507
  * background, hover tint and the normal focus ring. Pair it with `ariaExpanded` / `ariaPressed`; the label may contain a heading element.
3450
3508
  */
3451
- readonly variant: import("@angular/core").InputSignal<"primary" | "secondary" | "ghost" | "ghost-start" | "danger" | "link" | "warning" | "tab" | "icon" | "icon-danger">;
3509
+ readonly variant: import("@angular/core").InputSignal<"primary" | "secondary" | "danger" | "warning" | "link" | "ghost" | "ghost-start" | "tab" | "icon" | "icon-danger">;
3452
3510
  /** 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`). */
3453
3511
  readonly routerLink: import("@angular/core").InputSignal<string | readonly unknown[] | null>;
3454
3512
  /** Query params of the `routerLink` (e.g. `{ section: 'deal-defaults' }`). */
3455
3513
  readonly queryParams: import("@angular/core").InputSignal<Record<string, unknown> | null>;
3456
3514
  /** Fragment (hash) of the `routerLink`, without the `#` (e.g. `'billing'` -> `/settings#billing`). */
3457
3515
  readonly fragment: import("@angular/core").InputSignal<string | null>;
3516
+ /**
3517
+ * Router navigation state of the `routerLink` (the `history.state` of the page it opens), e.g. `{ returnTo: '/compliance' }` so the
3518
+ * target page can offer a "Back" link. Ignored without `routerLink`. Middle-click / open-in-new-tab open the plain href, which carries
3519
+ * no state (the target page then falls back to its default back target).
3520
+ */
3521
+ readonly state: import("@angular/core").InputSignal<Record<string, unknown> | null>;
3458
3522
  /**
3459
3523
  * Renders a plain `<a href>` instead of a button: for `mailto:`, `tel:`, `sms:`, `https://…` and relative URLs (use with
3460
3524
  * `variant="link"` for an inline text link). The browser handles the click, so middle-click, copy-link and open-in-new-tab work and
@@ -3463,16 +3527,32 @@ export declare class ButtonComponent {
3463
3527
  */
3464
3528
  readonly href: import("@angular/core").InputSignal<string | null>;
3465
3529
  /** Where to open the `href` (`_blank` = a new tab). */
3466
- readonly target: import("@angular/core").InputSignal<"_blank" | "_self" | "_parent" | "_top" | null>;
3530
+ readonly target: import("@angular/core").InputSignal<"_self" | "_blank" | "_parent" | "_top" | null>;
3467
3531
  /** `rel` of the `href` link. A `_blank` target always gets `noopener noreferrer` added. */
3468
3532
  readonly rel: import("@angular/core").InputSignal<string | null>;
3469
3533
  /** The href when it is allowed (http, https, mailto, tel, sms or a relative URL), else null. */
3470
3534
  protected readonly _safeHref: import("@angular/core").Signal<string | null>;
3471
3535
  protected readonly _rel: import("@angular/core").Signal<string | null>;
3536
+ /**
3537
+ * A shorter text for narrow screens (e.g. content "Previous", `shortLabel="Back"`). Below `shortBelow` the button shows this text instead of
3538
+ * its content. Accessibility: the projected (long) content stays in the page, only visually hidden, so the accessible name is always the
3539
+ * long text - the short text is `aria-hidden` and never read twice; an explicit `ariaLabel` still wins. Empty (default) = the content is
3540
+ * rendered exactly as before. Meant for text content (icons inside the content are hidden together with it).
3541
+ */
3542
+ readonly shortLabel: import("@angular/core").InputSignal<string>;
3543
+ /**
3544
+ * Where `shortLabel` applies: a library token `'sm'` (480px) / `'md'` (768px) / `'lg'` (1024px), or a pixel number (e.g. `640`). The short text
3545
+ * shows when the viewport is narrower than this; from the width itself the long text shows (`640`: >= 640px long, < 640px short, like a
3546
+ * `min-width: 640px` switch). Tokens are pure CSS; a number is tracked with `matchMedia`. Default `'md'`.
3547
+ */
3548
+ readonly shortBelow: import("@angular/core").InputSignal<number | "sm" | "md" | "lg">;
3549
+ /** Classes of the two label spans: the token class, or `btn-sl-narrow` while a pixel breakpoint is active. */
3550
+ protected readonly _slClass: import("@angular/core").Signal<string>;
3551
+ private readonly _narrow;
3472
3552
  readonly color: import("@angular/core").InputSignal<string | undefined>;
3473
3553
  readonly active: import("@angular/core").InputSignal<boolean>;
3474
- readonly size: import("@angular/core").InputSignal<"xs" | "sm" | "md" | "lg">;
3475
- readonly type: import("@angular/core").InputSignal<"button" | "submit" | "reset">;
3554
+ readonly size: import("@angular/core").InputSignal<"sm" | "md" | "lg" | "xs">;
3555
+ readonly type: import("@angular/core").InputSignal<"reset" | "submit" | "button">;
3476
3556
  readonly disabled: import("@angular/core").InputSignal<boolean>;
3477
3557
  readonly loading: import("@angular/core").InputSignal<boolean>;
3478
3558
  readonly fullWidth: import("@angular/core").InputSignal<boolean>;
@@ -3481,6 +3561,7 @@ export declare class ButtonComponent {
3481
3561
  readonly ariaPressed: import("@angular/core").InputSignal<boolean | undefined>;
3482
3562
  /** Id of the element that describes this button (an error or hint rendered next to it), e.g. `<ui-error errorId="x">`. Absent when empty. */
3483
3563
  readonly ariaDescribedBy: import("@angular/core").InputSignal<string | undefined>;
3564
+ constructor();
3484
3565
  _footerLeft?: string;
3485
3566
  _footerRight?: string;
3486
3567
  static ɵfac: i0.ɵɵFactoryDeclaration<ButtonComponent, never>;
@@ -3505,6 +3586,11 @@ export declare class ButtonComponent {
3505
3586
  "required": false;
3506
3587
  "isSignal": true;
3507
3588
  };
3589
+ "state": {
3590
+ "alias": "state";
3591
+ "required": false;
3592
+ "isSignal": true;
3593
+ };
3508
3594
  "href": {
3509
3595
  "alias": "href";
3510
3596
  "required": false;
@@ -3520,6 +3606,16 @@ export declare class ButtonComponent {
3520
3606
  "required": false;
3521
3607
  "isSignal": true;
3522
3608
  };
3609
+ "shortLabel": {
3610
+ "alias": "shortLabel";
3611
+ "required": false;
3612
+ "isSignal": true;
3613
+ };
3614
+ "shortBelow": {
3615
+ "alias": "shortBelow";
3616
+ "required": false;
3617
+ "isSignal": true;
3618
+ };
3523
3619
  "color": {
3524
3620
  "alias": "color";
3525
3621
  "required": false;
@@ -4000,7 +4096,7 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
4000
4096
  * Meant for a short mark of 1-3 characters.
4001
4097
  */
4002
4098
  readonly prefix: import("@angular/core").InputSignal<string>;
4003
- readonly type: import("@angular/core").InputSignal<"number" | "text" | "tel" | "email" | "password" | "url">;
4099
+ readonly type: import("@angular/core").InputSignal<"number" | "text" | "email" | "tel" | "password" | "url">;
4004
4100
  readonly maxlength: import("@angular/core").InputSignal<number | undefined>;
4005
4101
  readonly required: import("@angular/core").InputSignal<boolean>;
4006
4102
  readonly autocomplete: import("@angular/core").InputSignal<string>;
@@ -4009,7 +4105,7 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
4009
4105
  * `search`, `text`, `none`). Empty (default) = the browser's default for the field, except `type="tel"`, which keeps `tel`.
4010
4106
  * It only picks the keyboard; it does not restrict what can be typed or pasted.
4011
4107
  */
4012
- readonly inputmode: import("@angular/core").InputSignal<"" | "none" | "text" | "tel" | "search" | "email" | "url" | "decimal" | "numeric">;
4108
+ readonly inputmode: import("@angular/core").InputSignal<"" | "none" | "text" | "search" | "email" | "tel" | "url" | "decimal" | "numeric">;
4013
4109
  readonly readonly: import("@angular/core").InputSignal<boolean>;
4014
4110
  readonly hint: import("@angular/core").InputSignal<string>;
4015
4111
  readonly error: import("@angular/core").InputSignal<string>;
@@ -4039,6 +4135,14 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
4039
4135
  * phone formatting runs first and the formatter then sees its result.
4040
4136
  */
4041
4137
  readonly formatter: import("@angular/core").InputSignal<((raw: string) => string) | undefined>;
4138
+ /**
4139
+ * Whole numbers only (default off). Every typed or pasted value is cut at its first `.`, `e` or `E` (`2.7` -> `2`, `1e1` -> `1`, `12` stays),
4140
+ * the same filter as cremo's `wholeNumber`. It runs after the phone formatting and before a host `formatter`. It also picks the numeric
4141
+ * on-screen keyboard (`inputmode="numeric"`), the native `step` 1 and `maxDecimals` 0 for `type="number"` - each only while the host has not
4142
+ * set `inputmode` / `step` / `maxDecimals` itself. Values the host writes (`writeValue`) are shown as they are (a decimal there still fails
4143
+ * the 0-decimals rule).
4144
+ */
4145
+ readonly integer: import("@angular/core").InputSignal<boolean>;
4042
4146
  /** Reveal the built-in error messages now (e.g. after a failed Save click), without waiting for blur. */
4043
4147
  readonly showErrors: import("@angular/core").InputSignal<boolean>;
4044
4148
  /** Emits the new value when the USER changes it (typing, paste, autofill) - the same value the form control receives. Not emitted for values the host writes. */
@@ -4192,6 +4296,11 @@ export declare class TextInputComponent implements ControlValueAccessor, Validat
4192
4296
  "required": false;
4193
4297
  "isSignal": true;
4194
4298
  };
4299
+ "integer": {
4300
+ "alias": "integer";
4301
+ "required": false;
4302
+ "isSignal": true;
4303
+ };
4195
4304
  "showErrors": {
4196
4305
  "alias": "showErrors";
4197
4306
  "required": false;
@@ -5377,7 +5486,7 @@ export declare class DropdownComponent {
5377
5486
  readonly loader: import("@angular/core").InputSignal<(() => Promise<DropdownItem[]>) | null>;
5378
5487
  readonly active: import("@angular/core").InputSignal<boolean>;
5379
5488
  readonly activeValue: import("@angular/core").InputSignal<string>;
5380
- readonly variant: import("@angular/core").InputSignal<"button" | "badge">;
5489
+ readonly variant: import("@angular/core").InputSignal<"badge" | "button">;
5381
5490
  readonly menuWidth: import("@angular/core").InputSignal<string>;
5382
5491
  /**
5383
5492
  * Accessible name. Set it when the trigger has no meaningful visible text. Applied as `aria-label` on the
@@ -5489,6 +5598,10 @@ export declare class DropdownComponent {
5489
5598
  * - `ariaLabel` (or `ariaLabelledby`): the form's name. A named form is a landmark, so give it one only for a main form of the page.
5490
5599
  * - The browser's own validation bubbles are off (`novalidate`): library inputs show their own messages.
5491
5600
  * - `submitted` emits the submit event after the default action (a page reload) was prevented.
5601
+ * - `focusFirstInvalid({ scroll })`: after a failed Save, call it (e.g. `form.focusFirstInvalid()` from a `viewChild(FormComponent)`) to scroll to and focus the first
5602
+ * field that shows an error. It looks for `aria-invalid="true"` in DOM order (what every library input sets once it shows an error); on a
5603
+ * group (radio group, checkbox group, business hours) it focuses the group's first enabled control. Disabled and hidden controls are
5604
+ * skipped. Returns whether something was focused. `invalidFields()` returns those controls without moving focus.
5492
5605
  * - Layout: the host is a block and the form inside is a plain block - it adds no spacing; put a `ui-stack` / `ui-form-section` inside.
5493
5606
  */
5494
5607
  export declare class FormComponent {
@@ -5500,6 +5613,20 @@ export declare class FormComponent {
5500
5613
  readonly autocomplete: import("@angular/core").InputSignal<"" | "off" | "on">;
5501
5614
  /** Emits the submit event (Enter in a field, or a submit button). The page is never reloaded. */
5502
5615
  readonly submitted: import("@angular/core").OutputEmitterRef<Event>;
5616
+ private readonly _host;
5617
+ private static _usable;
5618
+ /**
5619
+ * The native controls that currently show an error (`aria-invalid="true"`), in DOM order. A group marked invalid (radio group, checkbox
5620
+ * group, business hours...) contributes its first enabled, visible control. Disabled and hidden controls are left out.
5621
+ */
5622
+ invalidFields(): HTMLElement[];
5623
+ /**
5624
+ * Scrolls the first invalid field (see `invalidFields`) to the middle of the screen and focuses it without a second scroll.
5625
+ * `scroll: false` only focuses. Returns false (and does nothing) when no field is invalid.
5626
+ */
5627
+ focusFirstInvalid(options?: {
5628
+ scroll?: boolean;
5629
+ }): boolean;
5503
5630
  protected onSubmit(event: Event): void;
5504
5631
  static ɵfac: i0.ɵɵFactoryDeclaration<FormComponent, never>;
5505
5632
  static ɵcmp: i0.ɵɵComponentDeclaration<FormComponent, "ui-form", never, {
@@ -5557,7 +5684,7 @@ export declare class FormRowComponent {
5557
5684
  * child simply takes the full width. Keep a numeric span within the row's `cols` (use `all` for the whole row).
5558
5685
  */
5559
5686
  export declare class FormColSpanDirective {
5560
- readonly uiColSpan: import("@angular/core").InputSignal<"" | 2 | 3 | "all" | "2" | "3">;
5687
+ readonly uiColSpan: import("@angular/core").InputSignal<"" | "2" | "3" | 2 | 3 | "all">;
5561
5688
  protected readonly _class: import("@angular/core").Signal<string>;
5562
5689
  static ɵfac: i0.ɵɵFactoryDeclaration<FormColSpanDirective, never>;
5563
5690
  static ɵdir: i0.ɵɵDirectiveDeclaration<FormColSpanDirective, "[uiColSpan]", never, {
@@ -6292,12 +6419,12 @@ export declare class ChipGroupComponent {
6292
6419
  /** Space between each chip. */
6293
6420
  readonly gap: import("@angular/core").InputSignal<"sm" | "md" | "lg">;
6294
6421
  /** Space above the chip group. */
6295
- readonly spaceAbove: import("@angular/core").InputSignal<"sm" | "md" | "none">;
6422
+ readonly spaceAbove: import("@angular/core").InputSignal<"none" | "sm" | "md">;
6296
6423
  /** Space below the chip group. */
6297
- readonly spaceBelow: import("@angular/core").InputSignal<"sm" | "md" | "none">;
6298
- protected readonly _gap: import("@angular/core").Signal<"12px" | "6px" | "8px">;
6299
- protected readonly _spaceAbove: import("@angular/core").Signal<"0" | "12px" | "6px">;
6300
- protected readonly _spaceBelow: import("@angular/core").Signal<"0" | "12px" | "6px">;
6424
+ readonly spaceBelow: import("@angular/core").InputSignal<"none" | "sm" | "md">;
6425
+ protected readonly _gap: import("@angular/core").Signal<"6px" | "12px" | "8px">;
6426
+ protected readonly _spaceAbove: import("@angular/core").Signal<"0" | "6px" | "12px">;
6427
+ protected readonly _spaceBelow: import("@angular/core").Signal<"0" | "6px" | "12px">;
6301
6428
  static ɵfac: i0.ɵɵFactoryDeclaration<ChipGroupComponent, never>;
6302
6429
  static ɵcmp: i0.ɵɵComponentDeclaration<ChipGroupComponent, "ui-chip-group", never, {
6303
6430
  "gap": {
@@ -8103,6 +8230,7 @@ export declare class PdfHotspotComponent {
8103
8230
  * one row end at the same height; the default card is only as tall as its content.
8104
8231
  * Use it in grid / flex cells: the spacing between cells comes from the gap, so a filled card's margin-bottom is 0 (the default card keeps 16px).
8105
8232
  * - `background`: the card's background colour (any CSS colour; default white).
8233
+ * - `headerBackground`: the background colour of the header bar only (any CSS colour; default none, the card's own background shows). The body keeps the card's `background`, and a header-less card (`showHeader` false) has no bar to colour. A collapsible header keeps this colour on hover. Pair it with `textColor` when the colour is dark.
8106
8234
  * - `textColor`: the colour of the title, subtitle, chevron and body text (any CSS colour; default: the normal slate colours). Use it for light text on a dark `background`. Text you colour yourself inside the body keeps its own colour.
8107
8235
  * - The body has built-in padding (16px 18px, matching the header's 18px side padding); there is no padding input.
8108
8236
  * - `collapsible` (default true): a chevron toggle and a clickable header; `[(expanded)]` is two-way.
@@ -8110,6 +8238,15 @@ export declare class PdfHotspotComponent {
8110
8238
  *
8111
8239
  * 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.
8112
8240
  *
8241
+ * - `selectable` (default false) + `[(selected)]` + `selectedColor` / `selectedBackground`: a pickable card (a product card, a plan). A click anywhere on the card
8242
+ * toggles `selected`, except a click on or inside an interactive element (`button, a[href], input, select, textarea, label, [role=button],
8243
+ * [role=link], [data-no-select]`; mark any other control with `data-no-select`) and except when text inside the card is being selected
8244
+ * (a drag). A selected card gets `data-selected="true"` on the host, a 2px outline (`selectedColor`, default `#3b82f6`, drawn 1px inside the edge) and,
8245
+ * when `selectedBackground` is set, that background (instead of `background`). A selectable card shows the pointer cursor.
8246
+ * The card is NOT focusable and has no extra role: **a selectable card must contain its own checkbox (or radio)**, which is the keyboard and
8247
+ * assistive-tech path (`[checked]="selected()"` / `(change)`). With `selectable` false there is no handler, cursor or outline.
8248
+ * (A click on a collapsible header outside its controls still collapses the card as before.)
8249
+ *
8113
8250
  * <ui-detail-card title="COMMUNICATIONS" subtitle="All calls, texts, and emails"> ...body... </ui-detail-card>
8114
8251
  * <ui-detail-card title="CONTACT INFO" [showEdit]="true" (editClick)="openEdit()"> ... </ui-detail-card>
8115
8252
  * <ui-detail-card [showHeader]="false"> ...body only... </ui-detail-card>
@@ -8135,6 +8272,8 @@ export declare class DetailCardComponent {
8135
8272
  readonly subtitle: import("@angular/core").InputSignal<string>;
8136
8273
  /** Card background as any CSS colour (`#f8fafc`, `var(--surface)` …). Empty = white. */
8137
8274
  readonly background: import("@angular/core").InputSignal<string>;
8275
+ /** Background colour of the header bar only, as any CSS colour (`#eaf3ff`, `var(--surface-2)` …). Empty = the header has no colour of its own (the card background shows). The body is not affected. */
8276
+ readonly headerBackground: import("@angular/core").InputSignal<string>;
8138
8277
  /** Text colour as any CSS colour (`#fff`, `var(--on-dark)` …). Empty = the default colours. Colours the title, subtitle, chevron and body text. */
8139
8278
  readonly textColor: import("@angular/core").InputSignal<string>;
8140
8279
  /** false = no header at all (no title, edit button, toggle or divider): the card is only the body, always open. */
@@ -8155,10 +8294,20 @@ export declare class DetailCardComponent {
8155
8294
  readonly editAriaLabel: import("@angular/core").InputSignal<string>;
8156
8295
  /** true = the card fills the height of its container (a grid cell / flex item) so sibling cards line up; the body grows. Spacing between cells comes from the gap: the filled card's margin-bottom is 0. Default false: unchanged. */
8157
8296
  readonly fill: import("@angular/core").InputSignal<boolean>;
8297
+ /** true = a click on the card (outside interactive controls and text selections) toggles `selected`. The card must contain its own checkbox for keyboard / screen-reader users. Default false: no handler, cursor or outline. */
8298
+ readonly selectable: import("@angular/core").InputSignal<boolean>;
8299
+ /** Two-way: whether the card is selected (only shown / toggled when `selectable`). */
8300
+ readonly selected: import("@angular/core").ModelSignal<boolean>;
8301
+ /** CSS colour of the 2px outline of a selected card. Default `#3b82f6`. */
8302
+ readonly selectedColor: import("@angular/core").InputSignal<string>;
8303
+ /** CSS colour used as the card background while selected (wins over `background`). Empty = the background does not change. */
8304
+ readonly selectedBackground: import("@angular/core").InputSignal<string>;
8158
8305
  /** The group's aria-label: the visible title (unless `titleId` names the card instead), else `ariaLabel`, else none. */
8159
8306
  groupLabel(): string | null;
8160
8307
  /** The body is open unless the card has a header that is collapsible and was collapsed. */
8161
8308
  isOpen(): boolean;
8309
+ /** selectable: a click on the card toggles `selected` unless it came from an interactive element or ends a text selection. */
8310
+ onCardClick(event: Event): void;
8162
8311
  toggle(): void;
8163
8312
  /** A click on the header toggles, except on a control inside it (Edit, your own header actions, links, inputs). */
8164
8313
  onHeaderClick(event: Event): void;
@@ -8199,6 +8348,11 @@ export declare class DetailCardComponent {
8199
8348
  "required": false;
8200
8349
  "isSignal": true;
8201
8350
  };
8351
+ "headerBackground": {
8352
+ "alias": "headerBackground";
8353
+ "required": false;
8354
+ "isSignal": true;
8355
+ };
8202
8356
  "textColor": {
8203
8357
  "alias": "textColor";
8204
8358
  "required": false;
@@ -8249,9 +8403,30 @@ export declare class DetailCardComponent {
8249
8403
  "required": false;
8250
8404
  "isSignal": true;
8251
8405
  };
8406
+ "selectable": {
8407
+ "alias": "selectable";
8408
+ "required": false;
8409
+ "isSignal": true;
8410
+ };
8411
+ "selected": {
8412
+ "alias": "selected";
8413
+ "required": false;
8414
+ "isSignal": true;
8415
+ };
8416
+ "selectedColor": {
8417
+ "alias": "selectedColor";
8418
+ "required": false;
8419
+ "isSignal": true;
8420
+ };
8421
+ "selectedBackground": {
8422
+ "alias": "selectedBackground";
8423
+ "required": false;
8424
+ "isSignal": true;
8425
+ };
8252
8426
  }, {
8253
8427
  "expanded": "expandedChange";
8254
8428
  "editClick": "editClick";
8429
+ "selected": "selectedChange";
8255
8430
  }, never, ["[card-header-leading]", "[card-header]", "[card-header-action]", "*"], true, never>;
8256
8431
  }
8257
8432
  export type DividerSpace = 'none' | 'sm' | 'md' | 'lg';
@@ -8790,6 +8965,7 @@ export type StackJustify = 'start' | 'center' | 'end' | 'between';
8790
8965
  * - `align`: start | center | end | stretch (cross axis, default stretch).
8791
8966
  * - `justify`: start | center | end | between (main axis, default start).
8792
8967
  * - `wrap`: let a horizontal stack wrap onto more lines (default false).
8968
+ * - `maxWidth` (CSS length) / `padding` (CSS padding) / `centered` (margin-inline auto): limit, pad and centre the stack. Defaults '' / '' / false = unchanged.
8793
8969
  *
8794
8970
  * <ui-stack gap="20px">
8795
8971
  * <ui-detail-card title="EMAIL"> ... </ui-detail-card>
@@ -8807,6 +8983,12 @@ export declare class StackComponent {
8807
8983
  readonly minHeight: import("@angular/core").InputSignal<string>;
8808
8984
  /** Width of the stack (any CSS length or "100%"). Empty = the normal block width. */
8809
8985
  readonly width: import("@angular/core").InputSignal<string>;
8986
+ /** Maximum width of the stack (any CSS length). Empty = none. */
8987
+ readonly maxWidth: import("@angular/core").InputSignal<string>;
8988
+ /** Padding of the stack (any CSS padding value). Empty = none. */
8989
+ readonly padding: import("@angular/core").InputSignal<string>;
8990
+ /** Centre the stack horizontally (margin-inline: auto; use with `maxWidth`). */
8991
+ readonly centered: import("@angular/core").InputSignal<boolean>;
8810
8992
  protected readonly gapCss: import("@angular/core").Signal<string>;
8811
8993
  protected readonly alignCss: import("@angular/core").Signal<string>;
8812
8994
  protected readonly justifyCss: import("@angular/core").Signal<string>;
@@ -8847,6 +9029,21 @@ export declare class StackComponent {
8847
9029
  "required": false;
8848
9030
  "isSignal": true;
8849
9031
  };
9032
+ "maxWidth": {
9033
+ "alias": "maxWidth";
9034
+ "required": false;
9035
+ "isSignal": true;
9036
+ };
9037
+ "padding": {
9038
+ "alias": "padding";
9039
+ "required": false;
9040
+ "isSignal": true;
9041
+ };
9042
+ "centered": {
9043
+ "alias": "centered";
9044
+ "required": false;
9045
+ "isSignal": true;
9046
+ };
8850
9047
  }, {}, never, ["*"], true, never>;
8851
9048
  }
8852
9049
  export type ActionBarAlign = 'start' | 'center' | 'end' | 'between';
@@ -9287,4 +9484,328 @@ export declare class CalendarComponent {
9287
9484
  "moreClick": "moreClick";
9288
9485
  }, never, ["[calendar-summary]", "[calendar-actions]", "[calendar-summary-mobile]"], true, never>;
9289
9486
  }
9487
+ /**
9488
+ * The shell of a public (not signed-in) page or wizard: an optional header, the content in a single `<main>`, an optional footer.
9489
+ *
9490
+ * <ui-page maxWidth="80rem" padding="responsive" background="#f9fafb" [fillViewport]="true" [stickyHeader]="true" [stickyFooter]="true"
9491
+ * [ownScroll]="true" [transparent]="embed()" [focusKey]="step()">
9492
+ * <div page-header> ...stepper... </div>
9493
+ * ...the current screen...
9494
+ * <div page-footer> ...navigation bar... </div>
9495
+ * </ui-page>
9496
+ *
9497
+ * Inputs (all defaults leave the page plain: no limits, no padding, no sticky parts):
9498
+ * - `maxWidth`: CSS length of the main content area ("80rem"). Default '' = none.
9499
+ * - `padding`: '' (none) | 'responsive' (32px 16px 16px; 32px 24px 16px from 640px; 32px 0 16px from 1024px) | any CSS padding value.
9500
+ * - `centered`: centre the main area when `maxWidth` is set (default true).
9501
+ * - `background`: CSS colour of the page. Default '' = none.
9502
+ * - `fillViewport`: the page is at least one viewport high (100dvh, 100vh fallback) and the footer sticks to the bottom (default false).
9503
+ * - `stickyHeader` / `stickyFooter`: the header slot is `position: sticky; top: 0`, the footer slot `bottom: 0`, z-index 20 (default false).
9504
+ * Sticky is relative to the nearest scrolling ancestor: NO ancestor may be an overflow container (overflow other than visible), or
9505
+ * the bars stop sticking. When the page owns the scrolling, use `ownScroll`.
9506
+ * - `transparent`: embed (iframe) mode: transparent background, no minimum height, no maximum width, the padding reduced to 8px 0 16px
9507
+ * (only when a padding is set) and neither bar is sticky (default false).
9508
+ * - `ownScroll`: make the document the scroll container (html overflow auto; body and app-root overflow visible; with `transparent` also
9509
+ * a transparent html/body background). The previous inline values are restored when the page is destroyed (default false).
9510
+ * - `focusKey`: when this value CHANGES (not on the first render), the page scrolls its top into view and moves focus to a zero-height
9511
+ * anchor so screen readers start at the new content. Smooth scrolling follows the page CSS, instant with prefers-reduced-motion.
9512
+ * `focusTop()` does the same on demand.
9513
+ *
9514
+ * Accessibility: the content wrapper is the only `<main>`; the header and footer slots are plain divs (they are landmarks only if the
9515
+ * host projects a `<header>` / `<footer>` / role itself).
9516
+ */
9517
+ export declare class PageComponent {
9518
+ readonly maxWidth: import("@angular/core").InputSignal<string>;
9519
+ readonly padding: import("@angular/core").InputSignal<string>;
9520
+ readonly centered: import("@angular/core").InputSignal<boolean>;
9521
+ readonly background: import("@angular/core").InputSignal<string>;
9522
+ readonly fillViewport: import("@angular/core").InputSignal<boolean>;
9523
+ readonly stickyHeader: import("@angular/core").InputSignal<boolean>;
9524
+ readonly stickyFooter: import("@angular/core").InputSignal<boolean>;
9525
+ readonly transparent: import("@angular/core").InputSignal<boolean>;
9526
+ readonly ownScroll: import("@angular/core").InputSignal<boolean>;
9527
+ readonly focusKey: import("@angular/core").InputSignal<unknown>;
9528
+ private readonly anchor;
9529
+ private readonly doc;
9530
+ private readonly injector;
9531
+ private readonly browser;
9532
+ protected readonly backgroundCss: import("@angular/core").Signal<string | null>;
9533
+ protected readonly maxWidthCss: import("@angular/core").Signal<string | null>;
9534
+ protected readonly paddingCss: import("@angular/core").Signal<string | null>;
9535
+ private scrollSaved;
9536
+ private bgSaved;
9537
+ private focusInitialised;
9538
+ private lastFocusKey;
9539
+ constructor();
9540
+ /** Scrolls the top of the page into view and moves focus to the (invisible) top anchor. */
9541
+ focusTop(): void;
9542
+ private save;
9543
+ private applyScroll;
9544
+ private releaseScroll;
9545
+ private applyBackground;
9546
+ private releaseBackground;
9547
+ static ɵfac: i0.ɵɵFactoryDeclaration<PageComponent, never>;
9548
+ static ɵcmp: i0.ɵɵComponentDeclaration<PageComponent, "ui-page", never, {
9549
+ "maxWidth": {
9550
+ "alias": "maxWidth";
9551
+ "required": false;
9552
+ "isSignal": true;
9553
+ };
9554
+ "padding": {
9555
+ "alias": "padding";
9556
+ "required": false;
9557
+ "isSignal": true;
9558
+ };
9559
+ "centered": {
9560
+ "alias": "centered";
9561
+ "required": false;
9562
+ "isSignal": true;
9563
+ };
9564
+ "background": {
9565
+ "alias": "background";
9566
+ "required": false;
9567
+ "isSignal": true;
9568
+ };
9569
+ "fillViewport": {
9570
+ "alias": "fillViewport";
9571
+ "required": false;
9572
+ "isSignal": true;
9573
+ };
9574
+ "stickyHeader": {
9575
+ "alias": "stickyHeader";
9576
+ "required": false;
9577
+ "isSignal": true;
9578
+ };
9579
+ "stickyFooter": {
9580
+ "alias": "stickyFooter";
9581
+ "required": false;
9582
+ "isSignal": true;
9583
+ };
9584
+ "transparent": {
9585
+ "alias": "transparent";
9586
+ "required": false;
9587
+ "isSignal": true;
9588
+ };
9589
+ "ownScroll": {
9590
+ "alias": "ownScroll";
9591
+ "required": false;
9592
+ "isSignal": true;
9593
+ };
9594
+ "focusKey": {
9595
+ "alias": "focusKey";
9596
+ "required": false;
9597
+ "isSignal": true;
9598
+ };
9599
+ }, {}, never, ["[page-header]", "*", "[page-footer]"], true, never>;
9600
+ }
9601
+ /**
9602
+ * A block wrapper whose content fades in (opacity 0 to 1) when it is created and again whenever `key` changes.
9603
+ * The projected content is NOT re-created: the animation restarts by alternating between two identical keyframes.
9604
+ *
9605
+ * <ui-fade [key]="step()"> ...the current screen... </ui-fade>
9606
+ *
9607
+ * - `key`: any value; a change restarts the fade (default undefined).
9608
+ * - `duration`: milliseconds (default 300).
9609
+ * - `disabled`: no animation at all (default false).
9610
+ * With prefers-reduced-motion: reduce nothing animates.
9611
+ */
9612
+ export declare class FadeComponent {
9613
+ readonly key: import("@angular/core").InputSignal<unknown>;
9614
+ readonly duration: import("@angular/core").InputSignal<number>;
9615
+ readonly disabled: import("@angular/core").InputSignal<boolean>;
9616
+ protected readonly odd: import("@angular/core").WritableSignal<boolean>;
9617
+ private first;
9618
+ private last;
9619
+ constructor();
9620
+ static ɵfac: i0.ɵɵFactoryDeclaration<FadeComponent, never>;
9621
+ static ɵcmp: i0.ɵɵComponentDeclaration<FadeComponent, "ui-fade", never, {
9622
+ "key": {
9623
+ "alias": "key";
9624
+ "required": false;
9625
+ "isSignal": true;
9626
+ };
9627
+ "duration": {
9628
+ "alias": "duration";
9629
+ "required": false;
9630
+ "isSignal": true;
9631
+ };
9632
+ "disabled": {
9633
+ "alias": "disabled";
9634
+ "required": false;
9635
+ "isSignal": true;
9636
+ };
9637
+ }, {}, never, ["*"], true, never>;
9638
+ }
9639
+ export type ShowBreakpoint = 'sm' | 'md' | 'lg' | number;
9640
+ /**
9641
+ * Responsive visibility wrapper (display: block when visible, display: none when hidden; never `display: contents`).
9642
+ *
9643
+ * <ui-show from="md"> desktop only </ui-show> visible at width >= 768px
9644
+ * <ui-show below="md"> phone/tablet only </ui-show> visible at width < 768px
9645
+ * <ui-show [from]="640" [below]="1024"> a range </ui-show>
9646
+ *
9647
+ * - `from`: visible only at viewport width >= from. `below`: visible only at width < below. Both = a range; none = always visible.
9648
+ * - Breakpoints are the tokens 'sm' (480px) | 'md' (768px) | 'lg' (1024px) or a pixel number.
9649
+ *
9650
+ * Difference: TOKEN breakpoints are pure CSS media queries (no JavaScript, correct on first paint and when server rendered).
9651
+ * NUMERIC breakpoints use `matchMedia` with a signal that updates on change (the listener is removed on destroy); without
9652
+ * `matchMedia` (server rendering) the content counts as visible. The two kinds can be mixed. Hidden content stays in the DOM.
9653
+ */
9654
+ export declare class ShowComponent {
9655
+ readonly from: import("@angular/core").InputSignal<ShowBreakpoint | null>;
9656
+ readonly below: import("@angular/core").InputSignal<ShowBreakpoint | null>;
9657
+ private readonly win;
9658
+ protected readonly fromToken: import("@angular/core").Signal<"sm" | "md" | "lg" | null>;
9659
+ protected readonly belowToken: import("@angular/core").Signal<"sm" | "md" | "lg" | null>;
9660
+ protected readonly fromMatch: import("@angular/core").WritableSignal<boolean>;
9661
+ protected readonly belowMatch: import("@angular/core").WritableSignal<boolean>;
9662
+ constructor();
9663
+ private watch;
9664
+ static ɵfac: i0.ɵɵFactoryDeclaration<ShowComponent, never>;
9665
+ static ɵcmp: i0.ɵɵComponentDeclaration<ShowComponent, "ui-show", never, {
9666
+ "from": {
9667
+ "alias": "from";
9668
+ "required": false;
9669
+ "isSignal": true;
9670
+ };
9671
+ "below": {
9672
+ "alias": "below";
9673
+ "required": false;
9674
+ "isSignal": true;
9675
+ };
9676
+ }, {}, never, ["*"], true, never>;
9677
+ }
9678
+ /**
9679
+ * Small formatting helpers shared by apps (money and postal addresses).
9680
+ */
9681
+ export interface FormatCurrencyOptions {
9682
+ /** ISO 4217 code. Default `'USD'`. */
9683
+ currency?: string;
9684
+ /** BCP 47 locale. Default `'en-US'`. */
9685
+ locale?: string;
9686
+ /** Thousands separators. Default `true`; `false` gives `$1605.00` (like a plain `'$' + n.toFixed(2)`). */
9687
+ grouping?: boolean;
9688
+ /** Digits after the decimal point. Default 2. */
9689
+ decimals?: number;
9690
+ }
9691
+ /**
9692
+ * Formats an amount as money: `formatCurrency(1605)` -> `$1,605.00`, `formatCurrency(-5)` -> `-$5.00`.
9693
+ * `null`, `undefined`, `NaN`, infinities and text that is not a number count as 0 (a numeric string such as `'12.5'` is parsed with
9694
+ * `parseFloat`, like cremo's `formatPrice`). `{ grouping: false }` reproduces `'$' + price.toFixed(2)` exactly (`$1605.00`).
9695
+ * An amount that rounds to zero is shown without a minus sign (`-0.001` -> `$0.00`).
9696
+ */
9697
+ export declare function formatCurrency(value: number | string | null | undefined, options?: FormatCurrencyOptions): string;
9698
+ export interface AddressParts {
9699
+ street?: string | null;
9700
+ apt?: string | null;
9701
+ city?: string | null;
9702
+ state?: string | null;
9703
+ zip?: string | null;
9704
+ }
9705
+ export interface FormatAddressOptions {
9706
+ /** Joiner between the parts. Default `', '`. */
9707
+ separator?: string;
9708
+ /**
9709
+ * `'comma'` (default): every non-empty part joined with the separator - `Street, Apt 4, City, ST, 12345` (cremo's next-of-kin and
9710
+ * informant address). `'usa'`: the postal layout - `Street, Apt 4, City, ST 12345`: the apartment is prefixed with `Apt ` and the
9711
+ * zip follows the state with a space (cremo's summary `joinAddress`); a state or city alone is still shown.
9712
+ */
9713
+ style?: 'comma' | 'usa';
9714
+ }
9715
+ /**
9716
+ * Joins the non-empty, trimmed address parts in the order street, apt, city, state, zip. See `FormatAddressOptions.style`.
9717
+ * `formatAddress({ street: '1 Main', city: 'Austin', state: 'TX', zip: '78701' })` -> `1 Main, Austin, TX, 78701`;
9718
+ * with `{ style: 'usa' }` -> `1 Main, Austin, TX 78701`.
9719
+ */
9720
+ export declare function formatAddress(parts: AddressParts, options?: FormatAddressOptions): string;
9721
+ /**
9722
+ * Starts the browser download of a blob under `fileName`. The anchor is attached to the page while it is clicked (Firefox ignores a click on
9723
+ * a detached anchor) and the object URL is revoked 1000 ms later (Safari reads it asynchronously, so an immediate revoke can cancel the
9724
+ * download). A no-op without a DOM (server-side rendering).
9725
+ */
9726
+ export declare function downloadBlob(blob: Blob, fileName: string): void;
9727
+ /**
9728
+ * A lightbox: a `ui-modal` that shows a `ui-image-gallery` with a Close button in the footer.
9729
+ *
9730
+ * <ui-image-gallery-dialog [(open)]="galleryOpen" [images]="images" title="Photos of the urn" galleryLabel="Urn photos"
9731
+ * dialogTestId="gallery-dialog" closeTestId="gallery-close" />
9732
+ *
9733
+ * - `open` (two-way): shown while true. Escape, a click on the backdrop and the footer Close button set it to false (the header X is
9734
+ * hidden, the footer button replaces it). Focus returns to the element that opened the dialog (modal behaviour).
9735
+ * - `images` (`GalleryImage[]`), `index` (two-way): the shown picture; it resets to 0 every time the dialog opens.
9736
+ * - `title`, `dialogTestId` (on the dialog element), `closeLabel` (default "Close"), `closeTestId` (on the Close button), `maxWidth`
9737
+ * (default `56rem`), `galleryLabel` (accessible name of the gallery group, default "Image gallery").
9738
+ * - The gallery has `autofocus` on: the dialog opens with focus on "Next image" so the arrow keys work at once (touch screens focus the dialog itself).
9739
+ * - The gallery is only created while the dialog is open, so closed dialogs load no pictures.
9740
+ */
9741
+ export declare class ImageGalleryDialogComponent {
9742
+ /** Two-way: whether the dialog is shown. */
9743
+ readonly open: import("@angular/core").ModelSignal<boolean>;
9744
+ readonly images: import("@angular/core").InputSignal<GalleryImage[]>;
9745
+ /** Two-way: the shown picture. Reset to 0 whenever the dialog opens. */
9746
+ readonly index: import("@angular/core").ModelSignal<number>;
9747
+ readonly title: import("@angular/core").InputSignal<string>;
9748
+ /** `data-testid` of the dialog element. */
9749
+ readonly dialogTestId: import("@angular/core").InputSignal<string>;
9750
+ /** Text of the footer Close button. */
9751
+ readonly closeLabel: import("@angular/core").InputSignal<string>;
9752
+ /** `data-testid` of the footer Close button (on the `ui-button` host); none when empty. */
9753
+ readonly closeTestId: import("@angular/core").InputSignal<string>;
9754
+ /** Max width of the dialog (any CSS length). */
9755
+ readonly maxWidth: import("@angular/core").InputSignal<string>;
9756
+ /** Accessible name of the gallery group. */
9757
+ readonly galleryLabel: import("@angular/core").InputSignal<string>;
9758
+ constructor();
9759
+ static ɵfac: i0.ɵɵFactoryDeclaration<ImageGalleryDialogComponent, never>;
9760
+ static ɵcmp: i0.ɵɵComponentDeclaration<ImageGalleryDialogComponent, "ui-image-gallery-dialog", never, {
9761
+ "open": {
9762
+ "alias": "open";
9763
+ "required": false;
9764
+ "isSignal": true;
9765
+ };
9766
+ "images": {
9767
+ "alias": "images";
9768
+ "required": false;
9769
+ "isSignal": true;
9770
+ };
9771
+ "index": {
9772
+ "alias": "index";
9773
+ "required": false;
9774
+ "isSignal": true;
9775
+ };
9776
+ "title": {
9777
+ "alias": "title";
9778
+ "required": false;
9779
+ "isSignal": true;
9780
+ };
9781
+ "dialogTestId": {
9782
+ "alias": "dialogTestId";
9783
+ "required": false;
9784
+ "isSignal": true;
9785
+ };
9786
+ "closeLabel": {
9787
+ "alias": "closeLabel";
9788
+ "required": false;
9789
+ "isSignal": true;
9790
+ };
9791
+ "closeTestId": {
9792
+ "alias": "closeTestId";
9793
+ "required": false;
9794
+ "isSignal": true;
9795
+ };
9796
+ "maxWidth": {
9797
+ "alias": "maxWidth";
9798
+ "required": false;
9799
+ "isSignal": true;
9800
+ };
9801
+ "galleryLabel": {
9802
+ "alias": "galleryLabel";
9803
+ "required": false;
9804
+ "isSignal": true;
9805
+ };
9806
+ }, {
9807
+ "open": "openChange";
9808
+ "index": "indexChange";
9809
+ }, never, never, true, never>;
9810
+ }
9290
9811
  export type { CalendarDay, CalendarRange, CalendarViewMode };