@lifecorner/angular-ui-kit 3.15.0 → 3.17.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 (37) hide show
  1. package/README.md +2 -1
  2. package/fesm2022/lifecorner-angular-ui-kit-button.mjs +12 -7
  3. package/fesm2022/lifecorner-angular-ui-kit-button.mjs.map +1 -1
  4. package/fesm2022/lifecorner-angular-ui-kit-icon.mjs +2 -2
  5. package/fesm2022/lifecorner-angular-ui-kit-icon.mjs.map +1 -1
  6. package/fesm2022/lifecorner-angular-ui-kit-icons.mjs +26 -2
  7. package/fesm2022/lifecorner-angular-ui-kit-icons.mjs.map +1 -1
  8. package/fesm2022/lifecorner-angular-ui-kit-internal-icon-set.mjs +10 -1
  9. package/fesm2022/lifecorner-angular-ui-kit-internal-icon-set.mjs.map +1 -1
  10. package/fesm2022/lifecorner-angular-ui-kit-list.mjs +29 -6
  11. package/fesm2022/lifecorner-angular-ui-kit-list.mjs.map +1 -1
  12. package/fesm2022/lifecorner-angular-ui-kit-money.mjs +250 -0
  13. package/fesm2022/lifecorner-angular-ui-kit-money.mjs.map +1 -0
  14. package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs +21 -2
  15. package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs.map +1 -1
  16. package/fesm2022/lifecorner-angular-ui-kit-progress-bar.mjs +2 -2
  17. package/fesm2022/lifecorner-angular-ui-kit-progress-bar.mjs.map +1 -1
  18. package/fesm2022/lifecorner-angular-ui-kit-switch.mjs +21 -4
  19. package/fesm2022/lifecorner-angular-ui-kit-switch.mjs.map +1 -1
  20. package/fesm2022/lifecorner-angular-ui-kit-table.mjs +73 -7
  21. package/fesm2022/lifecorner-angular-ui-kit-table.mjs.map +1 -1
  22. package/fesm2022/lifecorner-angular-ui-kit-toast.mjs +2 -2
  23. package/fesm2022/lifecorner-angular-ui-kit-toast.mjs.map +1 -1
  24. package/fesm2022/lifecorner-angular-ui-kit.mjs +1 -0
  25. package/package.json +5 -1
  26. package/src/styles/theme-contrast.spec.ts +79 -0
  27. package/types/lifecorner-angular-ui-kit-button.d.ts +28 -1
  28. package/types/lifecorner-angular-ui-kit-icon.d.ts +2 -1
  29. package/types/lifecorner-angular-ui-kit-icons.d.ts +5 -1
  30. package/types/lifecorner-angular-ui-kit-list.d.ts +38 -0
  31. package/types/lifecorner-angular-ui-kit-money.d.ts +150 -0
  32. package/types/lifecorner-angular-ui-kit-next-step-card.d.ts +26 -0
  33. package/types/lifecorner-angular-ui-kit-progress-bar.d.ts +12 -1
  34. package/types/lifecorner-angular-ui-kit-switch.d.ts +19 -0
  35. package/types/lifecorner-angular-ui-kit-table.d.ts +61 -2
  36. package/types/lifecorner-angular-ui-kit-toast.d.ts +3 -1
  37. package/types/lifecorner-angular-ui-kit.d.ts +1 -0
@@ -280,3 +280,82 @@ describe('Component pairings of 3.15 (request 020)', () => {
280
280
  });
281
281
  });
282
282
  });
283
+
284
+ // Request 022 (3.16): the focus ring of clickable table rows and list link rows
285
+ // (--color-primary-500, 2 px) on every row fill (1.4.11 and 2.4.13 need 3:1).
286
+ describe('Component pairings of 3.16 (request 022)', () => {
287
+ /** Design 022 §5, per palette [light, dark]: table row fills on the card (--color-surface). */
288
+ const rows: [string, [number, number]][] = [
289
+ ['--color-surface', [4.37, 9.13]],
290
+ ['--color-surface-2', [4.18, 7.58]],
291
+ ['--color-surface-hover', [3.97, 8.18]],
292
+ ['--color-surface-selected', [3.76, 6.87]],
293
+ ];
294
+
295
+ describe.each(palettes.map(([name, tokens], i) => [name, tokens, i] as const))('%s palette', (_palette, tokens, i) => {
296
+ const solid = (name: string, base = '--color-surface') => over(color(tokens, name), color(tokens, base));
297
+
298
+ it.each(rows)('AC-5: the --color-primary-500 row ring reaches 3:1 on %s', (fill, values) => {
299
+ const r = ratio(solid('--color-primary-500'), solid(fill));
300
+ expect(r).toBeCloseTo(values[i], 1);
301
+ expect(r).toBeGreaterThanOrEqual(3);
302
+ });
303
+ });
304
+ });
305
+
306
+ // Request 021 (3.17): the lc-list status badges (12 px / 500, so 4.5:1) and the
307
+ // focus ring of a loading lc-button, which its 0.5 opacity fades. The token
308
+ // names come from the compiled component stylesheets, the values from the themes.
309
+ describe('Component pairings of 3.17 (request 021)', () => {
310
+ const listCss = compile(resolve(__dirname, '../lib/list/list.component.scss')).css;
311
+ const buttonCss = compile(resolve(__dirname, '../lib/button/button.component.scss')).css;
312
+
313
+ /** The background and ink token of a list badge variant (a fallback after the name is ignored). */
314
+ function badgeTokens(variant: string): [string, string] {
315
+ const body = listCss.match(new RegExp(`\\n\\.lc-list__badge--${variant} \\{([^}]*)\\}`))?.[1] ?? '';
316
+ const bg = body.match(/background-color: var\((--[\w-]+)/)?.[1] ?? '';
317
+ const ink = body.match(/\scolor: var\((--[\w-]+)/)?.[1] ?? '';
318
+ expect([bg, ink]).toEqual([expect.stringMatching(/^--color-/), expect.stringMatching(/^--color-/)]);
319
+ return [bg, ink];
320
+ }
321
+
322
+ /** Design 021 §5: the minimum over the bases, per palette [light, dark]. */
323
+ const badges: [string, [string, string], [number, number]][] = [
324
+ ['success', ['--color-success-subtle', '--color-on-success-subtle'], [4.85, 5.17]],
325
+ ['warning', ['--color-warning-subtle', '--color-on-warning-subtle'], [5.52, 4.61]],
326
+ ['error', ['--color-error-100', '--color-on-error-subtle'], [6.33, 7.17]],
327
+ ['primary', ['--color-primary-100', '--color-primary-700'], [7.85, 9.68]],
328
+ ['default', ['--color-surface-hover', '--color-text-secondary'], [6.87, 8.18]],
329
+ ];
330
+
331
+ describe.each(palettes.map(([name, tokens], i) => [name, tokens, i] as const))('%s palette', (_palette, tokens, i) => {
332
+ /** The grounds a list sits on: the page, the card surfaces and a hovered row (over the surface). */
333
+ const bases: Rgba[] = [
334
+ color(tokens, '--color-background'),
335
+ color(tokens, '--color-surface'),
336
+ over(color(tokens, '--color-surface-2'), color(tokens, '--color-surface')),
337
+ over(color(tokens, '--color-surface-hover'), color(tokens, '--color-surface')),
338
+ ].map((c) => over(c, color(tokens, '--color-background')));
339
+
340
+ it.each(badges)('AC-12: the %s list badge reaches 4.5:1 on every ground', (variant, pair, values) => {
341
+ expect(badgeTokens(variant)).toEqual(pair);
342
+ const [bg, ink] = pair;
343
+ const min = Math.min(
344
+ ...bases.map((base) => {
345
+ const fill = over(color(tokens, bg), base);
346
+ return ratio(over(color(tokens, ink), fill), fill);
347
+ }),
348
+ );
349
+ expect(min).toBeCloseTo(values[i], 2);
350
+ expect(min).toBeGreaterThanOrEqual(4.5);
351
+ });
352
+
353
+ it('AC-7: the ring of a focused loading button (--color-text-primary at 50 %) reaches 3:1 on the page and the surfaces', () => {
354
+ expect(buttonCss).toMatch(/\n\.btn\.btn-loading:focus-visible \{\s*outline-color: var\(--color-text-primary\);/);
355
+ const ink = color(tokens, '--color-text-primary');
356
+ for (const base of bases.slice(0, 3)) {
357
+ expect(ratio(over([ink[0], ink[1], ink[2], 0.5], base), base)).toBeGreaterThanOrEqual(3);
358
+ }
359
+ });
360
+ });
361
+ });
@@ -28,7 +28,28 @@ export declare class ButtonComponent {
28
28
  */
29
29
  readonly tone: import("@angular/core").InputSignal<ButtonTone>;
30
30
  readonly size: import("@angular/core").InputSignal<ButtonSize>;
31
+ /**
32
+ * Natively disabled: the button leaves the focus order and ignores clicks.
33
+ * For a temporary busy state that keeps focus, use `loading`.
34
+ * @default false
35
+ */
31
36
  readonly disabled: import("@angular/core").InputSignal<boolean>;
37
+ /**
38
+ * Shows a spinner in place of the icon slots and makes the button
39
+ * unavailable without removing it from the focus order (3.17). The inner
40
+ * `<button>` gets `aria-disabled="true"` and `aria-busy="true"` instead of
41
+ * the native `disabled`, so a focused button keeps focus. While it is
42
+ * loading, click, Enter and Space are ignored: `clicked` is not emitted, the
43
+ * click event stops at the button (a `(click)` on the host doesn't fire),
44
+ * and a `type="submit"`/`"reset"` button doesn't submit or reset its form.
45
+ * The look is unchanged: spinner, 50 % opacity, no hover. Screen readers may
46
+ * announce the state change ("unavailable"/"dimmed"), but the button doesn't
47
+ * announce the outcome: the page does that, for example with a polite live
48
+ * region ("USM wird geladen.", then the result). `disabledReason` also
49
+ * applies while loading. If `disabled` is set too, the native `disabled`
50
+ * wins.
51
+ * @default false
52
+ */
32
53
  readonly loading: import("@angular/core").InputSignal<boolean>;
33
54
  readonly iconOnly: import("@angular/core").InputSignal<boolean>;
34
55
  readonly fullWidth: import("@angular/core").InputSignal<boolean>;
@@ -72,7 +93,13 @@ export declare class ButtonComponent {
72
93
  * `title` otherwise.
73
94
  */
74
95
  readonly effectiveTitle: import("@angular/core").Signal<string | null>;
75
- handleClick(): void;
96
+ /**
97
+ * Emits `clicked` unless the button is disabled or loading. While loading
98
+ * (and not natively disabled) the event is cancelled and stopped, so a form
99
+ * isn't submitted and a host `(click)` doesn't fire. The parameter is
100
+ * optional, so callers without an argument still work.
101
+ */
102
+ handleClick(event?: Event): void;
76
103
  handleFocus(): void;
77
104
  handleBlur(): void;
78
105
  focus(): void;
@@ -284,7 +284,8 @@ export type IconName = string;
284
284
  * `provideLcIcons()` or loaded with the kit's set (3.6, AS-17). Covers the
285
285
  * hand-picked inline set, the Tabler icons inlined at build time (mail,
286
286
  * users, settings, logout, key, chevron-right, …) and aliases that resolve
287
- * to either — the same names as in 3.5.1. Use it to lint an app or a static
287
+ * to either — the names of 3.5.1, plus `wallet`, `building-bank` and
288
+ * `shield-lock` since 3.16 (TD-3). Use it to lint an app or a static
288
289
  * site against icons that would be fetched.
289
290
  *
290
291
  * @example
@@ -132,8 +132,12 @@ export declare const ICON_ALERT_CIRCLE: LcIconDefinition;
132
132
  export declare const ICON_ALERT_CIRCLE_SOLID: LcIconDefinition;
133
133
  export declare const ICON_CIRCLE_X: LcIconDefinition;
134
134
  export declare const ICON_CIRCLE_X_SOLID: LcIconDefinition;
135
+ export declare const ICON_WALLET: LcIconDefinition;
136
+ export declare const ICON_BUILDING_BANK: LcIconDefinition;
137
+ export declare const ICON_SHIELD_LOCK: LcIconDefinition;
138
+ export declare const ICON_SHIELD_LOCK_SOLID: LcIconDefinition;
135
139
  /**
136
- * Every glyph above (133): `provideLcIcons(BUNDLED_ICONS)` restores the
140
+ * Every glyph above (137): `provideLcIcons(BUNDLED_ICONS)` restores the
137
141
  * synchronous rendering of 3.5.1 for every inline name, e.g. in tests or
138
142
  * Storybook. An app that imports it bundles all of them.
139
143
  */
@@ -64,6 +64,15 @@ export interface ListItem {
64
64
  * label must be part of it (WCAG 2.5.3).
65
65
  */
66
66
  actionAriaLabel?: string;
67
+ /**
68
+ * URL of the row link (3.16, TD-4). The row renders as an `<a>` over its
69
+ * full area (at least 44 px high) with real link semantics (middle click,
70
+ * "open in new tab"). Not rendered with `href`: `action` (no control inside
71
+ * a link; a dev warning). Not emitted: `itemClick` (see `linkClick`). With
72
+ * `disabled` the row is the plain disabled row, no link. A custom
73
+ * `lcListItem` template must not hold controls in `href` rows.
74
+ */
75
+ href?: string;
67
76
  /** Item identifier */
68
77
  id?: string;
69
78
  /** Whether the item is disabled */
@@ -77,6 +86,15 @@ export interface ListItem {
77
86
  * List item size
78
87
  */
79
88
  export type ListSize = 'sm' | 'md' | 'lg';
89
+ /**
90
+ * A plain click (or Enter) on an `href` row (3.16, TD-4): `item` is the row,
91
+ * `event` the click. Call `event.preventDefault()` to navigate with your
92
+ * router instead of a full page load.
93
+ */
94
+ export interface ListLinkClickEvent {
95
+ item: ListItem;
96
+ event: MouseEvent;
97
+ }
80
98
  /**
81
99
  * List component for displaying structured item collections.
82
100
  *
@@ -87,6 +105,8 @@ export type ListSize = 'sm' | 'md' | 'lg';
87
105
  * - Icon and avatar support per item
88
106
  * - Action buttons with click events
89
107
  * - Accessible with ARIA list role; `clickable` rows are keyboard-operable
108
+ * - `ListItem.href` rows are real links over the full row (3.16, TD-4);
109
+ * `linkClick` hands plain clicks to your router
90
110
  *
91
111
  * @example
92
112
  * ```html
@@ -138,6 +158,18 @@ export declare class ListComponent {
138
158
  readonly itemClick: import("@angular/core").OutputEmitterRef<ListItem>;
139
159
  /** Event emitted when an action button is clicked */
140
160
  readonly actionClick: import("@angular/core").OutputEmitterRef<ListItem>;
161
+ /**
162
+ * A plain click (or Enter) on an `href` row: primary button, no
163
+ * Ctrl/Cmd/Shift/Alt (3.16, TD-4). Emitted before the browser follows the
164
+ * link; call `event.preventDefault()` and navigate with your router for an
165
+ * in-app route (`router.navigateByUrl(item.href)`). The kit never prevents
166
+ * the default; modifier and middle clicks are never emitted, so "open in new
167
+ * tab" keeps working.
168
+ */
169
+ readonly linkClick: import("@angular/core").OutputEmitterRef<ListLinkClickEvent>;
170
+ constructor();
171
+ /** Whether a row renders as a link: `href` set and not disabled. */
172
+ protected isLinkRow(item: ListItem): boolean;
141
173
  /**
142
174
  * Computed CSS classes for the list
143
175
  */
@@ -161,6 +193,11 @@ export declare class ListComponent {
161
193
  * Handle action button click
162
194
  */
163
195
  onActionClick(item: ListItem): void;
196
+ /**
197
+ * A click on a link row: only a plain primary click reaches `linkClick`.
198
+ * The default (following the link) is left to the browser and the consumer.
199
+ */
200
+ protected onLinkClick(event: MouseEvent, item: ListItem): void;
164
201
  static ɵfac: i0.ɵɵFactoryDeclaration<ListComponent, never>;
165
202
  static ɵcmp: i0.ɵɵComponentDeclaration<ListComponent, "lc-list", never, {
166
203
  "items": {
@@ -211,5 +248,6 @@ export declare class ListComponent {
211
248
  }, {
212
249
  "itemClick": "itemClick";
213
250
  "actionClick": "actionClick";
251
+ "linkClick": "linkClick";
214
252
  }, ["itemTemplate"], never, true, never>;
215
253
  }
@@ -0,0 +1,150 @@
1
+ import * as i0 from "@angular/core";
2
+ /**
3
+ * How the sign of an amount shows, as `Intl.NumberFormat`'s `signDisplay`:
4
+ * - `auto`: negative amounts only (−42,17 €)
5
+ * - `always`: plus and minus, also on zero (+0,00 €)
6
+ * - `exceptZero`: plus and minus, no sign on zero
7
+ * - `never`: no sign
8
+ */
9
+ type MoneySignDisplay = 'auto' | 'always' | 'exceptZero' | 'never';
10
+ /** Options of {@link formatMoney}. */
11
+ interface MoneyFormatOptions {
12
+ /** BCP 47 locale. An invalid one falls back to `en-US`. @default 'en-US' */
13
+ locale?: string;
14
+ /** As `Intl.NumberFormat`'s `signDisplay`. @default 'auto' */
15
+ signDisplay?: MoneySignDisplay;
16
+ /** Spoken word for the minus sign. @default 'minus' */
17
+ minusLabel?: string;
18
+ /** Spoken word for the plus sign. @default 'plus' */
19
+ plusLabel?: string;
20
+ }
21
+ /** A formatted amount: the visible text and the words a screen reader speaks. */
22
+ interface MoneyText {
23
+ /** Visible text, e.g. „−42,17 €“ (U+2212 minus, U+00A0 from `Intl`). */
24
+ text: string;
25
+ /** Spoken text, e.g. „minus 42,17 Euro“. */
26
+ spoken: string;
27
+ }
28
+ /** The ISO 4217 minor-unit exponent of `currency` (2 unless listed). */
29
+ declare function moneyMinorUnits(currency: string): number;
30
+ /** Text direction of an amount formatted for `locale`. */
31
+ declare function moneyDirection(locale: string): 'ltr' | 'rtl';
32
+ /**
33
+ * Formats an amount of money given in integer minor units (cents, yen, fils)
34
+ * exactly, never through a float: the decimal string goes into `Intl`.
35
+ * Returns `null` for an amount that is not a safe integer or a currency that
36
+ * is not a three-letter code. This is the formatter of `lc-money`, for table
37
+ * `formatter`s and texts.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * formatMoney(-4217, 'EUR', { locale: 'de-DE' });
42
+ * // { text: '−42,17 €', spoken: 'minus 42,17 Euro' }
43
+ * ```
44
+ */
45
+ export declare function formatMoney(amountMinor: number, currency: string, options?: MoneyFormatOptions): MoneyText | null;
46
+ /**
47
+ * Displays an amount of money (3.16, BA-4): locale, currency, sign, tabular
48
+ * figures and a spoken text. Display only, no input parsing or conversion.
49
+ *
50
+ * - `amountMinor` is an integer in the currency's minor units (cents, yen,
51
+ * fils), formatted exactly through a decimal string, never a float. Minor
52
+ * units follow ISO 4217: 2, except 0 (BIF CLP DJF GNF ISK JPY KMF KRW PYG
53
+ * RWF UGX UYI VND VUV XAF XOF XPF), 3 (BHD IQD JOD KWD LYD OMR TND) and 4
54
+ * (CLF UYW).
55
+ * - The visible amount („−42,17 €“, U+2212 minus, a no-break space from
56
+ * `Intl`) is `aria-hidden`; a visually hidden span holds the words
57
+ * („minus 42,17 Euro“), so a screen reader reads the amount once.
58
+ * - Tabular figures, no wrapping inside the amount; the amount is a `dir`
59
+ * isolate (`ltr`, or `rtl` for an RTL locale), safe inside RTL text.
60
+ * - Font and colour come from the context; colour never carries the sign.
61
+ * - `locale` empty: the app's `LOCALE_ID` (Angular's default `en-US`), the
62
+ * same on the server and in the browser.
63
+ * - For table `formatter`s and texts use {@link formatMoney}.
64
+ *
65
+ * Separate a `lc-money` from adjacent text with a space in your template, so
66
+ * the spoken text does not run into the words around it.
67
+ *
68
+ * @example
69
+ * ```html
70
+ * <lc-money [amountMinor]="-4217" currency="EUR" locale="de-DE" />
71
+ * ```
72
+ */
73
+ export declare class MoneyComponent {
74
+ private readonly appLocale;
75
+ /**
76
+ * Amount in minor units of `currency` (cents, yen, fils): a safe integer
77
+ * (±9,007,199,254,740,991), formatted exactly. Anything else renders
78
+ * nothing (a dev warning).
79
+ */
80
+ readonly amountMinor: import("@angular/core").InputSignal<number>;
81
+ /**
82
+ * ISO 4217 currency code (`EUR`, `USD`, `JPY`, `KWD`). It sets the minor
83
+ * units and the symbol. Not a three-letter code: renders nothing (a dev
84
+ * warning).
85
+ */
86
+ readonly currency: import("@angular/core").InputSignal<string>;
87
+ /**
88
+ * BCP 47 locale of the amount (`de-DE`, `en-GB`). Empty: the app's
89
+ * `LOCALE_ID` (Angular's default `en-US`). An invalid locale falls back to
90
+ * `en-US`.
91
+ * @default ''
92
+ */
93
+ readonly locale: import("@angular/core").InputSignal<string>;
94
+ /**
95
+ * Which signs show, as `Intl.NumberFormat`: `auto` (negative only),
96
+ * `always`, `exceptZero`, `never`. The spoken text says the sign whenever
97
+ * it shows.
98
+ * @default 'auto'
99
+ */
100
+ readonly signDisplay: import("@angular/core").InputSignal<MoneySignDisplay>;
101
+ /**
102
+ * Spoken word for the minus sign („minus 42,17 Euro“; the same in German).
103
+ * @default 'minus'
104
+ */
105
+ readonly minusLabel: import("@angular/core").InputSignal<string>;
106
+ /**
107
+ * Spoken word for the plus sign („plus 42,17 Euro“; the same in German).
108
+ * @default 'plus'
109
+ */
110
+ readonly plusLabel: import("@angular/core").InputSignal<string>;
111
+ /** The locale in use: the `locale` input or the app's `LOCALE_ID`. */
112
+ protected readonly effectiveLocale: import("@angular/core").Signal<string>;
113
+ protected readonly formatted: import("@angular/core").Signal<import("@lifecorner/angular-ui-kit/money").MoneyText | null>;
114
+ protected readonly dir: import("@angular/core").Signal<"ltr" | "rtl">;
115
+ constructor();
116
+ static ɵfac: i0.ɵɵFactoryDeclaration<MoneyComponent, never>;
117
+ static ɵcmp: i0.ɵɵComponentDeclaration<MoneyComponent, "lc-money", never, {
118
+ "amountMinor": {
119
+ "alias": "amountMinor";
120
+ "required": true;
121
+ "isSignal": true;
122
+ };
123
+ "currency": {
124
+ "alias": "currency";
125
+ "required": true;
126
+ "isSignal": true;
127
+ };
128
+ "locale": {
129
+ "alias": "locale";
130
+ "required": false;
131
+ "isSignal": true;
132
+ };
133
+ "signDisplay": {
134
+ "alias": "signDisplay";
135
+ "required": false;
136
+ "isSignal": true;
137
+ };
138
+ "minusLabel": {
139
+ "alias": "minusLabel";
140
+ "required": false;
141
+ "isSignal": true;
142
+ };
143
+ "plusLabel": {
144
+ "alias": "plusLabel";
145
+ "required": false;
146
+ "isSignal": true;
147
+ };
148
+ }, {}, never, never, true, never>;
149
+ }
150
+ export type { MoneyFormatOptions, MoneySignDisplay, MoneyText };
@@ -15,6 +15,15 @@ export type NextStepCardVariant = 'default' | 'soft';
15
15
  * - `stacked`: always in their own row, one per line at equal width, 8 px apart
16
16
  */
17
17
  export type NextStepCardActionsLayout = 'inline' | 'stacked';
18
+ /**
19
+ * Weight of the two built-in actions.
20
+ * - `default`: a filled primary and a ghost secondary with a chevron, the
21
+ * primary last
22
+ * - `equal`: two answers of the same weight (a question such as „Teilen?“):
23
+ * both `outline` in the primary tone at `actionSize`, the primary first,
24
+ * no chevron
25
+ */
26
+ export type NextStepCardActionsStyle = 'default' | 'equal';
18
27
  /** Element that renders the title (semantics only, the look stays the same). */
19
28
  export type NextStepCardTitleTag = 'div' | 'h2' | 'h3';
20
29
  /** Size of the built-in action buttons (`sm` 32 px, `md` 42 px, `lg` 48.5 px). */
@@ -44,6 +53,8 @@ export type NextStepCardActionSize = 'sm' | 'md' | 'lg';
44
53
  * `fullWidth` button gets its own row at every width.
45
54
  * - `variant="soft"`: the tinted card of the "Weite" look; `actionsLayout`
46
55
  * `stacked` for several equal-width actions; `titleTag` for a heading
56
+ * - `actionsStyle="equal"` (3.16, BA-5): a question with two answers of the
57
+ * same weight, both outline buttons in the primary tone, primary first
47
58
  *
48
59
  * The host is a size container (`container-type: inline-size`) and takes the
49
60
  * full inline size of its parent.
@@ -106,6 +117,16 @@ export declare class NextStepCardComponent implements AfterViewChecked {
106
117
  * @default 'sm'
107
118
  */
108
119
  actionSize: import("@angular/core").InputSignal<NextStepCardActionSize>;
120
+ /**
121
+ * Weight of the built-in actions. `default`: filled primary, ghost secondary
122
+ * with a chevron, primary last. `equal`: two answers of the same weight, both
123
+ * `outline` in the primary tone at `actionSize`, primary first, no chevron
124
+ * (`primaryClick`, `secondaryClick`, `primaryLoading`, `primaryDisabled` and
125
+ * `announce` work as before). Use `actionSize="lg"` (48.5 px, the 44 px
126
+ * target; a dev warning otherwise). No effect on `[slot='actions']`.
127
+ * @default 'default'
128
+ */
129
+ actionsStyle: import("@angular/core").InputSignal<NextStepCardActionsStyle>;
109
130
  /** Message below the title. For markup, use the default slot instead. */
110
131
  message: import("@angular/core").InputSignal<string | undefined>;
111
132
  /** Label of the primary action. Omit to render no primary button. */
@@ -200,6 +221,11 @@ export declare class NextStepCardComponent implements AfterViewChecked {
200
221
  "required": false;
201
222
  "isSignal": true;
202
223
  };
224
+ "actionsStyle": {
225
+ "alias": "actionsStyle";
226
+ "required": false;
227
+ "isSignal": true;
228
+ };
203
229
  "message": {
204
230
  "alias": "message";
205
231
  "required": false;
@@ -12,6 +12,13 @@ export type ProgressBarVariant = 'linear' | 'circular';
12
12
  * - Animated value transitions
13
13
  * - Accessible with ARIA progressbar role
14
14
  *
15
+ * The bar is a visual aid; the text next to it carries the meaning. Write the
16
+ * status as text ('USM wird geladen …') and announce changes from a live
17
+ * region (`role="status"`). Screen readers don't announce a progress bar's
18
+ * changes by themselves. Give `ariaLabel` the same words as the status. Under
19
+ * `forced-colors: active` the fill is `Highlight`, the linear track gets a
20
+ * 1 px `CanvasText` outline and the circle's track is `GrayText` (3.17).
21
+ *
15
22
  * @example
16
23
  * ```html
17
24
  * <lc-progress-bar [value]="75" color="primary" size="md"></lc-progress-bar>
@@ -57,7 +64,11 @@ export declare class ProgressBarComponent {
57
64
  */
58
65
  inline: import("@angular/core").InputSignal<boolean>;
59
66
  /**
60
- * Whether the progress is indeterminate (animated, no fixed value).
67
+ * Progress of unknown length: no value (`aria-valuenow` is absent) and no
68
+ * label. The linear bar moves a 40 % segment across the track, and the
69
+ * circle spins. Under `prefers-reduced-motion: reduce` nothing moves: the
70
+ * linear bar shows a full-width striped fill and the circle a dashed ring,
71
+ * so it still reads as busy, not as a value (3.17).
61
72
  * @default false
62
73
  */
63
74
  indeterminate: import("@angular/core").InputSignal<boolean>;
@@ -8,6 +8,10 @@ import * as i0 from "@angular/core";
8
8
  * - Size options (sm, md, lg)
9
9
  * - Loading state with spinner
10
10
  * - Configurable label positioning (left/right)
11
+ * - Help text below the label, linked by `aria-describedby` (`helpText`, 3.16)
12
+ * - Rows with a label or help text are at least 44 px high
13
+ * (`--lc-switch-min-height`, default `var(--size-min-touch-height)`; `0`
14
+ * restores the 3.15 rows of 21/24/28 px)
11
15
  * - Keyboard toggle support
12
16
  * - Disabled and required states
13
17
  * - ControlValueAccessor integration for reactive forms
@@ -54,12 +58,22 @@ export declare class SwitchComponent implements ControlValueAccessor {
54
58
  * ARIA label for accessibility (overrides the visible label as accessible name)
55
59
  */
56
60
  readonly ariaLabel: import("@angular/core").InputSignal<string | undefined>;
61
+ /**
62
+ * Description below the label, linked to the switch by `aria-describedby`
63
+ * (read after the name and state). Wraps; 14 px secondary text. A tap on it
64
+ * toggles the switch like the label. Empty renders no element and no
65
+ * `aria-describedby` (3.15).
66
+ * @default ''
67
+ */
68
+ readonly helpText: import("@angular/core").InputSignal<string>;
57
69
  /**
58
70
  * Emitted when checked state changes
59
71
  */
60
72
  readonly checkedChange: import("@angular/core").OutputEmitterRef<boolean>;
61
73
  /** Per-instance id so the visible `<label for>` points at this switch. */
62
74
  readonly switchId: string;
75
+ /** id of the rendered help text (only while `helpText` is set). */
76
+ readonly helpTextId: import("@angular/core").Signal<string | null>;
63
77
  /**
64
78
  * Effective checked state: follows the `checked` input, overridden by
65
79
  * form writes (`writeValue`) and user toggles.
@@ -135,6 +149,11 @@ export declare class SwitchComponent implements ControlValueAccessor {
135
149
  "required": false;
136
150
  "isSignal": true;
137
151
  };
152
+ "helpText": {
153
+ "alias": "helpText";
154
+ "required": false;
155
+ "isSignal": true;
156
+ };
138
157
  }, {
139
158
  "checkedChange": "checkedChange";
140
159
  }, never, never, true, never>;
@@ -37,7 +37,11 @@ export interface TableColumn {
37
37
  width?: string;
38
38
  /** Optional CSS class(es) applied to both th and td cells */
39
39
  cssClass?: string;
40
- /** Optional CSS class(es) for td cells only (string or resolver callback) */
40
+ /**
41
+ * Optional CSS class(es) for td cells only (string or resolver callback).
42
+ * A class colour or font size loses to the kit's cell rule; set them with
43
+ * `cellStyle`.
44
+ */
41
45
  cellClass?: TableCellClass;
42
46
  /** Optional inline styles for td cells only (object or resolver callback) */
43
47
  cellStyle?: TableCellStyle;
@@ -49,7 +53,21 @@ export interface TableColumn {
49
53
  editType?: 'text' | 'number' | 'select';
50
54
  /** Options for select edit type */
51
55
  editOptions?: string[];
56
+ /**
57
+ * Horizontal alignment of the column's header and cells. `end` aligns both
58
+ * at the end edge (right in LTR) and sets `font-variant-numeric:
59
+ * tabular-nums`, for amounts, counts and percentages. A sort arrow then sits
60
+ * before the label, so the label stays flush with the figures. Adds
61
+ * `lc-table__cell--end` to the `th` and every `td`. It wins over a
62
+ * `cellClass` that sets `text-align`; use `cellStyle` to override it. A
63
+ * custom `lcTableCell` template inherits the alignment, but a flex or block
64
+ * child needs its own `justify-content: flex-end`. (3.17)
65
+ * @default 'start'
66
+ */
67
+ align?: TableColumnAlign;
52
68
  }
69
+ /** Horizontal alignment of a table column (3.17). */
70
+ export type TableColumnAlign = 'start' | 'end';
53
71
  /**
54
72
  * A row-level action rendered in the table's actions column (e.g. Freigeben, Ablehnen).
55
73
  * Action button clicks never trigger the row's `rowClick` output.
@@ -162,6 +180,9 @@ interface DisplayRow {
162
180
  * - Composed cells (e.g. avatar + badge + actions)
163
181
  * - Hierarchical "tree" rows (grouped / expandable) via `idKey` + `parentKey`
164
182
  * - Responsive horizontal scrolling
183
+ * - `clickable` rows: tab stops, Enter/Space emit `rowClick` (3.16)
184
+ * - `caption` as the table's `<caption>`, visible or for screen readers only
185
+ * (`showCaption`, 3.16)
165
186
  * - Empty state text for no data
166
187
  * - Accessible with proper table semantics
167
188
  *
@@ -198,6 +219,29 @@ export declare class TableComponent {
198
219
  size: import("@angular/core").InputSignal<TableSize>;
199
220
  /** Whether rows should highlight on hover */
200
221
  hoverable: import("@angular/core").InputSignal<boolean>;
222
+ /**
223
+ * Rows are interactive (3.16, BA-3): each data row is a tab stop, Enter and
224
+ * Space emit `rowClick` (Space does not scroll the page), pointer and hover
225
+ * as `hoverable`. Clicks and keys on controls inside a row (buttons, links,
226
+ * inputs, switches) stay theirs and emit no `rowClick`. Set it whenever you
227
+ * handle `rowClick`. Tree mode keeps its roving tab stop. A focused row is
228
+ * read by its cells, not as "clickable": let the row open something that
229
+ * announces itself (a dialog, a page).
230
+ * @default false
231
+ */
232
+ clickable: import("@angular/core").InputSignal<boolean>;
233
+ /**
234
+ * Title of the table, rendered as its `<caption>` (3.16, BA-3), so it also
235
+ * names the table for screen readers. Empty renders no caption.
236
+ * @default ''
237
+ */
238
+ caption: import("@angular/core").InputSignal<string>;
239
+ /**
240
+ * Show the caption above the table (16 px semibold, 12 px above the table);
241
+ * `false` keeps it for screen readers only.
242
+ * @default true
243
+ */
244
+ showCaption: import("@angular/core").InputSignal<boolean>;
201
245
  /** Whether table should be responsive (horizontal scroll on mobile) */
202
246
  responsive: import("@angular/core").InputSignal<boolean>;
203
247
  /** Text shown when data is empty */
@@ -398,7 +442,7 @@ export declare class TableComponent {
398
442
  protected treeCellLabel(row: Record<string, unknown>): string;
399
443
  getCellTemplate(columnKey: string): TableCellDirective | undefined;
400
444
  hasCustomTemplate(columnKey: string): boolean;
401
- onRowClick(row: Record<string, unknown>): void;
445
+ onRowClick(row: Record<string, unknown>, event?: Event): void;
402
446
  /** Whether the trailing actions column should be rendered */
403
447
  protected readonly hasActions: import("@angular/core").Signal<boolean>;
404
448
  protected isActionHidden(action: TableAction, row: Record<string, unknown>, rowIndex: number): boolean;
@@ -469,6 +513,21 @@ export declare class TableComponent {
469
513
  "required": false;
470
514
  "isSignal": true;
471
515
  };
516
+ "clickable": {
517
+ "alias": "clickable";
518
+ "required": false;
519
+ "isSignal": true;
520
+ };
521
+ "caption": {
522
+ "alias": "caption";
523
+ "required": false;
524
+ "isSignal": true;
525
+ };
526
+ "showCaption": {
527
+ "alias": "showCaption";
528
+ "required": false;
529
+ "isSignal": true;
530
+ };
472
531
  "responsive": {
473
532
  "alias": "responsive";
474
533
  "required": false;
@@ -22,7 +22,9 @@ export interface Toast extends Required<Omit<ToastConfig, 'action'>> {
22
22
  * Toast service for showing ephemeral notifications.
23
23
  *
24
24
  * The toasts are rendered by `<lc-toast-outlet />`, which the application
25
- * places once (e.g. in its shell); without it nothing is shown.
25
+ * places once (e.g. in its shell); without it nothing is shown. The options,
26
+ * their defaults, the timing and how a toast is announced to screen readers
27
+ * are documented under *Feedback/Toast Outlet* (3.17).
26
28
  *
27
29
  * @example
28
30
  * ```typescript
@@ -58,6 +58,7 @@ export * from "@lifecorner/angular-ui-kit/toggle-group";
58
58
  export * from "@lifecorner/angular-ui-kit/list";
59
59
  export * from "@lifecorner/angular-ui-kit/chip";
60
60
  export * from "@lifecorner/angular-ui-kit/table";
61
+ export * from "@lifecorner/angular-ui-kit/money";
61
62
  export * from "@lifecorner/angular-ui-kit/field-group";
62
63
  export * from "@lifecorner/angular-ui-kit/stepper";
63
64
  export * from "@lifecorner/angular-ui-kit/filter-bar";