@lifecorner/angular-ui-kit 3.34.0 → 3.35.0

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.
Files changed (28) hide show
  1. package/fesm2022/lifecorner-angular-ui-kit-alert.mjs +2 -2
  2. package/fesm2022/lifecorner-angular-ui-kit-alert.mjs.map +1 -1
  3. package/fesm2022/lifecorner-angular-ui-kit-bottom-nav.mjs.map +1 -1
  4. package/fesm2022/lifecorner-angular-ui-kit-combobox.mjs +5 -2
  5. package/fesm2022/lifecorner-angular-ui-kit-combobox.mjs.map +1 -1
  6. package/fesm2022/lifecorner-angular-ui-kit-drawer.mjs +30 -2
  7. package/fesm2022/lifecorner-angular-ui-kit-drawer.mjs.map +1 -1
  8. package/fesm2022/lifecorner-angular-ui-kit-gallery.mjs.map +1 -1
  9. package/fesm2022/lifecorner-angular-ui-kit-internal-overlay.mjs +6 -1
  10. package/fesm2022/lifecorner-angular-ui-kit-internal-overlay.mjs.map +1 -1
  11. package/fesm2022/lifecorner-angular-ui-kit-modal.mjs +2 -4
  12. package/fesm2022/lifecorner-angular-ui-kit-modal.mjs.map +1 -1
  13. package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs +41 -1
  14. package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs.map +1 -1
  15. package/fesm2022/lifecorner-angular-ui-kit-textarea.mjs +3 -0
  16. package/fesm2022/lifecorner-angular-ui-kit-textarea.mjs.map +1 -1
  17. package/fesm2022/lifecorner-angular-ui-kit-toast.mjs.map +1 -1
  18. package/package.json +1 -1
  19. package/src/styles/theme-contrast.spec.ts +2 -0
  20. package/types/lifecorner-angular-ui-kit-alert.d.ts +12 -2
  21. package/types/lifecorner-angular-ui-kit-bottom-nav.d.ts +5 -1
  22. package/types/lifecorner-angular-ui-kit-combobox.d.ts +21 -0
  23. package/types/lifecorner-angular-ui-kit-drawer.d.ts +37 -1
  24. package/types/lifecorner-angular-ui-kit-gallery.d.ts +3 -1
  25. package/types/lifecorner-angular-ui-kit-internal-overlay.d.ts +9 -1
  26. package/types/lifecorner-angular-ui-kit-sidenav.d.ts +42 -1
  27. package/types/lifecorner-angular-ui-kit-textarea.d.ts +17 -0
  28. package/types/lifecorner-angular-ui-kit-toast.d.ts +4 -2
@@ -138,7 +138,11 @@ export declare class BottomNavComponent {
138
138
  * destinations' badges; pass the value to show. It sits on the bar's last
139
139
  * entry; values up to three characters (`'99+'`) fit: on the last entry a
140
140
  * badge that would pass the entry's edge moves left until it ends there
141
- * (3.33). `null` or `undefined`: no badge.
141
+ * (3.33). `null` or `undefined`: no badge. Known limit (3.35, 052-n3):
142
+ * '99+' on the last entry of a five-entry bar at 360 px starts 3.2 px
143
+ * (docked) / 3.4 px (floating) left of the pill centre and covers two of the
144
+ * More glyph's three dots; the label and the read badge text still name the
145
+ * entry.
142
146
  *
143
147
  * @default null
144
148
  */
@@ -25,6 +25,10 @@ export type ComboboxSize = 'xs' | 'sm' | 'md' | 'lg';
25
25
  * (`[(selectedValue)]`, single mode), next to the `valueChange` output with
26
26
  * the option object and the forms binding.
27
27
  *
28
+ * `focus()` (3.35) moves the focus into the field's `<input>` when a form
29
+ * opens or after a rejected save (WCAG 2.4.3); it opens the list as a user's
30
+ * focus does (`openOnFocus`).
31
+ *
28
32
  * @example
29
33
  * ```html
30
34
  * <lc-combobox
@@ -176,6 +180,23 @@ export declare class ComboboxComponent implements ControlValueAccessor {
176
180
  registerOnChange(fn: (value: ComboboxValue) => void): void;
177
181
  registerOnTouched(fn: () => void): void;
178
182
  setDisabledState(isDisabled: boolean): void;
183
+ /**
184
+ * Moves the focus into the field's `<input>` (3.35), e.g. when a form opens
185
+ * with this field first, or to the field with the error after a rejected
186
+ * save (422) (WCAG 2.4.3). `options` as for `HTMLElement.focus()`
187
+ * (`{ preventScroll: true }`). Shows the same focus ring as a user's focus.
188
+ * Like a user's focus it opens the list when `openOnFocus` is `true` and
189
+ * there is something to show; with `false` the list stays closed
190
+ * (`aria-expanded="false"`). A disabled field takes no focus (it stays where
191
+ * it is). Call it once the field has rendered, e.g.
192
+ * `afterNextRender(() => this.month().focus(), { injector })` with
193
+ * `month = viewChild.required(ComboboxComponent)` and the page component's
194
+ * `injector = inject(Injector)`. In an `lc-modal` that opens with the field,
195
+ * that call runs after the dialog moved the focus to its first control.
196
+ * Does nothing before the component has rendered.
197
+ * @param options Passed to the native `focus()`.
198
+ */
199
+ focus(options?: FocusOptions): void;
179
200
  /**
180
201
  * Clear the current selection and query. Emits `null` (single) or `[]`
181
202
  * (multiple) exactly once, like a user-initiated deselect.
@@ -12,7 +12,10 @@ export type DrawerSize = 'sm' | 'md' | 'lg' | 'xl';
12
12
  * - Close on Escape key support
13
13
  * - Heading text display
14
14
  * - Content projection for arbitrary body content
15
- * - Accessible with ARIA dialog role, focus trap and focus restore
15
+ * - Accessible with ARIA dialog role, focus trap and focus restore;
16
+ * `returnFocusTo` (3.35) names the element that gets the focus back after
17
+ * the drawer closed (WebKit doesn't focus a tapped button, so the one
18
+ * captured at open is `body`)
16
19
  *
17
20
  * @example
18
21
  * ```html
@@ -42,6 +45,20 @@ export declare class DrawerComponent implements OnDestroy {
42
45
  readonly ariaLabel: import("@angular/core").InputSignal<string>;
43
46
  /** Accessible name of the close button. */
44
47
  readonly closeAriaLabel: import("@angular/core").InputSignal<string>;
48
+ /**
49
+ * Element that gets the focus back after the drawer closed (3.35), instead
50
+ * of the one that had it at open. Set it to the trigger: WebKit (Safari,
51
+ * every iOS browser) doesn't focus a tapped button, so the captured element
52
+ * is `body`. Applied when the panel has left the DOM after its 250 ms
53
+ * slide-out, once the focus trap has restored its captured element. Holds
54
+ * on ×, Escape, backdrop, `open` false, and when the drawer is destroyed
55
+ * while open. A custom-element host that can't take focus (`<lc-button>`)
56
+ * hands it to its first focusable descendant. Ignored when the element is
57
+ * no longer in the document or can't take focus; the captured element then
58
+ * keeps it. `null`: as before.
59
+ * @default null
60
+ */
61
+ readonly returnFocusTo: import("@angular/core").InputSignal<HTMLElement | null>;
45
62
  /** Emitted when the drawer should close. */
46
63
  readonly closed: import("@angular/core").OutputEmitterRef<void>;
47
64
  /** Internal visibility — stays true during the slide-out animation. */
@@ -54,8 +71,22 @@ export declare class DrawerComponent implements OnDestroy {
54
71
  private readonly drawerId;
55
72
  private closeTimer?;
56
73
  private originalOverflow?;
74
+ /**
75
+ * The environment injector: a node injector would cancel the focus-return
76
+ * hook when the drawer is destroyed while open.
77
+ */
78
+ private readonly environmentInjector;
79
+ private destroyed;
57
80
  constructor();
58
81
  ngOnDestroy(): void;
82
+ /**
83
+ * Focuses `returnFocusTo` after the next render (3.35): the template
84
+ * refresh has removed the panel, and `cdkTrapFocus` has restored its
85
+ * captured element on destroy, so this is the last focus write. Reads the
86
+ * input again then, so a trigger re-rendered meanwhile is taken from a
87
+ * fresh query. Does nothing when the drawer opened again meanwhile.
88
+ */
89
+ private scheduleFocusReturn;
59
90
  /**
60
91
  * Handle backdrop click. Ignored while another overlay (menu, popover, …)
61
92
  * sits above this drawer — the click belongs to that layer.
@@ -118,6 +149,11 @@ export declare class DrawerComponent implements OnDestroy {
118
149
  "required": false;
119
150
  "isSignal": true;
120
151
  };
152
+ "returnFocusTo": {
153
+ "alias": "returnFocusTo";
154
+ "required": false;
155
+ "isSignal": true;
156
+ };
121
157
  }, {
122
158
  "closed": "closed";
123
159
  }, never, ["*"], true, never>;
@@ -23,7 +23,9 @@ export interface GalleryItem {
23
23
  * - Configurable custom column count
24
24
  * - Lightbox overlay with navigation (prev/next)
25
25
  * - Keyboard navigation (Arrow keys, Escape); focus is trapped inside the
26
- * lightbox and returned to the originating thumbnail on close
26
+ * lightbox and returned to the originating thumbnail on close: the clicked
27
+ * or tapped thumbnail, also in WebKit, where a tap doesn't focus it, so the
28
+ * gallery needs no `returnFocusTo` (3.35)
27
29
  * - Optional captions and category filtering
28
30
  * - Lazy loading with placeholder shimmer
29
31
  * - Zoom control in lightbox
@@ -49,4 +49,12 @@ export declare class OverlayInsetsService {
49
49
  readonly bottom: import("@angular/core").WritableSignal<string | null>;
50
50
  static ɵfac: i0.ɵɵFactoryDeclaration<OverlayInsetsService, never>;
51
51
  static ɵprov: i0.ɵɵInjectableDeclaration<any>;
52
- }
52
+ }
53
+ /**
54
+ * Gives the focus to an overlay's `returnFocusTo` element (3.34 in
55
+ * `lc-modal`, shared since 3.35 with `lc-drawer` and `lc-sidenav`). A
56
+ * custom-element host that can't take focus (`<lc-button>`) hands it to its
57
+ * first focusable descendant. An element that can't take focus at all leaves
58
+ * the focus where it is.
59
+ */
60
+ export declare function focusReturnTarget(target: HTMLElement): void;
@@ -53,7 +53,9 @@ export type SidenavVariant = 'default' | 'transparent';
53
53
  * `--color-on-surface-selected` (AA on the selected tint)
54
54
  * - Accessible: the inner `<nav>` is the navigation landmark; in drawer mode
55
55
  * the panel is a modal dialog (`role="dialog"`, focus moved to the close
56
- * button on open, trapped while open, restored on close)
56
+ * button on open, trapped while open, restored on close); `returnFocusTo`
57
+ * (3.35) names the element that gets the focus back after the drawer
58
+ * closed (WebKit doesn't focus a tapped button)
57
59
  *
58
60
  * @example
59
61
  * ```html
@@ -162,6 +164,22 @@ export declare class SidenavComponent implements OnDestroy {
162
164
  readonly ariaLabel: import("@angular/core").InputSignal<string>;
163
165
  /** Whether to show the overlay backdrop */
164
166
  readonly hasOverlay: import("@angular/core").InputSignal<boolean>;
167
+ /**
168
+ * Drawer mode only (`mode="drawer"`, or `docked` below `mobileBreakpoint`):
169
+ * element that gets the focus back after the drawer closed (3.35), instead
170
+ * of the one that had it at open. Set it to the trigger: WebKit (Safari,
171
+ * every iOS browser) doesn't focus a tapped button, so the captured element
172
+ * is `body`. Applied after the next render, once the panel has left the DOM
173
+ * and the focus trap has restored its captured element. Holds on ×,
174
+ * Escape, backdrop, an item or brand tap on a phone (they close it through
175
+ * `closed`), `isOpen` false, and when the sidenav is destroyed while open.
176
+ * A custom-element host that can't take focus (`<lc-button>`) hands it to
177
+ * its first focusable descendant. Ignored when the element is no longer in
178
+ * the document or can't take focus; the captured element then keeps it.
179
+ * `null`: as before.
180
+ * @default null
181
+ */
182
+ readonly returnFocusTo: import("@angular/core").InputSignal<HTMLElement | null>;
165
183
  /**
166
184
  * Navigation items (`NavigationItem[]`): `id`, `icon`, `label`, `route`,
167
185
  * `displayOrder` (sort order, 1 = first); optional `children`
@@ -261,8 +279,26 @@ export declare class SidenavComponent implements OnDestroy {
261
279
  * Event emitted when an item's action button is clicked
262
280
  */
263
281
  readonly itemAction: import("@angular/core").OutputEmitterRef<NavigationItem>;
282
+ /** Whether the drawer panel is rendered (drawer mode and open). */
283
+ private readonly drawerOpen;
284
+ /** Whether the drawer panel was shown without a close after it. */
285
+ private drawerShown;
286
+ /**
287
+ * The environment injector: a node injector would cancel the focus-return
288
+ * hook when the sidenav is destroyed while open.
289
+ */
290
+ private readonly environmentInjector;
264
291
  constructor();
265
292
  ngOnDestroy(): void;
293
+ /** Ends a shown drawer panel; schedules `returnFocusTo` when set. */
294
+ private drawerClosed;
295
+ /**
296
+ * Focuses `returnFocusTo` after the next render: the template refresh has
297
+ * removed the panel, and `cdkTrapFocus` has restored its captured element
298
+ * on destroy, so this is the last focus write. Reads the input again then,
299
+ * so a trigger re-rendered meanwhile is taken from a fresh query.
300
+ */
301
+ private scheduleFocusReturn;
266
302
  private setupMediaQuery;
267
303
  private teardownMediaQuery;
268
304
  /**
@@ -434,6 +470,11 @@ export declare class SidenavComponent implements OnDestroy {
434
470
  "required": false;
435
471
  "isSignal": true;
436
472
  };
473
+ "returnFocusTo": {
474
+ "alias": "returnFocusTo";
475
+ "required": false;
476
+ "isSignal": true;
477
+ };
437
478
  "items": {
438
479
  "alias": "items";
439
480
  "required": false;
@@ -14,6 +14,8 @@ import { ControlValueAccessor } from "@angular/forms";
14
14
  * - ControlValueAccessor integration for reactive forms
15
15
  * - Plain form posts without JavaScript: `name`, and a `value` that is
16
16
  * prerendered into the native `<textarea>`
17
+ * - `focus()` (3.35): moves the focus into the native `<textarea>` when a
18
+ * form opens or after a rejected save (WCAG 2.4.3)
17
19
  *
18
20
  * @example
19
21
  * ```html
@@ -214,6 +216,21 @@ export declare class TextareaComponent implements ControlValueAccessor {
214
216
  * Handle blur event
215
217
  */
216
218
  onBlur(): void;
219
+ /**
220
+ * Moves the focus into the native `<textarea>` (3.35), e.g. when a form
221
+ * opens with this field first, or to the field with the error after a
222
+ * rejected save (422) (WCAG 2.4.3). `options` as for `HTMLElement.focus()`
223
+ * (`{ preventScroll: true }`). Shows the same focus ring as a user's focus.
224
+ * A disabled field takes no focus (it stays where it is); a read-only one
225
+ * does. Call it once the field has rendered, e.g.
226
+ * `afterNextRender(() => this.note().focus(), { injector })` with
227
+ * `note = viewChild.required(TextareaComponent)` and the page component's
228
+ * `injector = inject(Injector)`. In an `lc-modal` that opens with the field,
229
+ * that call runs after the dialog moved the focus to its first control.
230
+ * Does nothing before the component has rendered.
231
+ * @param options Passed to the native `focus()`.
232
+ */
233
+ focus(options?: FocusOptions): void;
217
234
  writeValue(value: string | null | undefined): void;
218
235
  registerOnChange(fn: (value: string) => void): void;
219
236
  registerOnTouched(fn: () => void): void;
@@ -194,8 +194,10 @@ type ToastLive = 'polite' | 'assertive';
194
194
  * as the space between the offsets and scrolls when its toasts need more
195
195
  * (200 % text), so each toast stays reachable.
196
196
  *
197
- * Bottom stacks show the newest toast nearest the edge (3.33); top stacks the
198
- * oldest at the top. The toasts of a stack are 8 px (`--spacing-2`) apart
197
+ * Bottom stacks show the newest toast nearest the edge (3.33). A top stack
198
+ * shows its assertive region (error, warning) above its polite one (success,
199
+ * info), each oldest first, so a newer error sits above an older success
200
+ * (3.35, 053-n2). The toasts of a stack are 8 px (`--spacing-2`) apart
199
201
  * (3.33.1), within a live region and across the two; an empty region and the
200
202
  * last toast add no space, and the stack keeps its 16 px padding. A `top-*`
201
203
  * stack lies over the page on purpose (a toast stays visible wherever the