@cdevhub/ngx-tw 0.4.0 → 0.6.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 (209) hide show
  1. package/README.md +78 -15
  2. package/fesm2022/cdevhub-ngx-tw-accordion.mjs +16 -5
  3. package/fesm2022/cdevhub-ngx-tw-accordion.mjs.map +1 -1
  4. package/fesm2022/cdevhub-ngx-tw-avatar.mjs +26 -15
  5. package/fesm2022/cdevhub-ngx-tw-avatar.mjs.map +1 -1
  6. package/fesm2022/cdevhub-ngx-tw-badge.mjs +17 -5
  7. package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -1
  8. package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs +27 -6
  9. package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs.map +1 -1
  10. package/fesm2022/cdevhub-ngx-tw-button.mjs +23 -11
  11. package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -1
  12. package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs +5 -5
  13. package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs.map +1 -1
  14. package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs +3 -3
  15. package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs.map +1 -1
  16. package/fesm2022/cdevhub-ngx-tw-calendar.mjs +427 -122
  17. package/fesm2022/cdevhub-ngx-tw-calendar.mjs.map +1 -1
  18. package/fesm2022/cdevhub-ngx-tw-card.mjs +21 -11
  19. package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -1
  20. package/fesm2022/cdevhub-ngx-tw-carousel.mjs +215 -96
  21. package/fesm2022/cdevhub-ngx-tw-carousel.mjs.map +1 -1
  22. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +108 -64
  23. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -1
  24. package/fesm2022/cdevhub-ngx-tw-code-block.mjs +18 -6
  25. package/fesm2022/cdevhub-ngx-tw-code-block.mjs.map +1 -1
  26. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +55 -30
  27. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -1
  28. package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs +218 -0
  29. package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs.map +1 -0
  30. package/fesm2022/cdevhub-ngx-tw-combobox.mjs +236 -211
  31. package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -1
  32. package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs +200 -0
  33. package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs.map +1 -0
  34. package/fesm2022/cdevhub-ngx-tw-command-palette.mjs +34 -7
  35. package/fesm2022/cdevhub-ngx-tw-command-palette.mjs.map +1 -1
  36. package/fesm2022/cdevhub-ngx-tw-core.mjs +135 -15
  37. package/fesm2022/cdevhub-ngx-tw-core.mjs.map +1 -1
  38. package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs +203 -0
  39. package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs.map +1 -0
  40. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +160 -102
  41. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -1
  42. package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs +209 -0
  43. package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs.map +1 -0
  44. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +182 -107
  45. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -1
  46. package/fesm2022/cdevhub-ngx-tw-dialog-dialog-renderer-DoIhoV3d.mjs +198 -0
  47. package/fesm2022/cdevhub-ngx-tw-dialog-dialog-renderer-DoIhoV3d.mjs.map +1 -0
  48. package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs +122 -0
  49. package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs.map +1 -0
  50. package/fesm2022/cdevhub-ngx-tw-dialog.mjs +199 -220
  51. package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -1
  52. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +1 -1
  53. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -1
  54. package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs +149 -0
  55. package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs.map +1 -0
  56. package/fesm2022/cdevhub-ngx-tw-file-upload.mjs +57 -67
  57. package/fesm2022/cdevhub-ngx-tw-file-upload.mjs.map +1 -1
  58. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +42 -24
  59. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -1
  60. package/fesm2022/cdevhub-ngx-tw-form-field.mjs +114 -21
  61. package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -1
  62. package/fesm2022/cdevhub-ngx-tw-icon.mjs +16 -6
  63. package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -1
  64. package/fesm2022/cdevhub-ngx-tw-input.mjs +52 -61
  65. package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -1
  66. package/fesm2022/cdevhub-ngx-tw-item.mjs +18 -3
  67. package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -1
  68. package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs +168 -0
  69. package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs.map +1 -0
  70. package/fesm2022/cdevhub-ngx-tw-menu.mjs +58 -21
  71. package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -1
  72. package/fesm2022/cdevhub-ngx-tw-number-input.mjs +34 -1
  73. package/fesm2022/cdevhub-ngx-tw-number-input.mjs.map +1 -1
  74. package/fesm2022/cdevhub-ngx-tw-paginator.mjs +95 -45
  75. package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -1
  76. package/fesm2022/cdevhub-ngx-tw-popover.mjs +81 -32
  77. package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -1
  78. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +1 -1
  79. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -1
  80. package/fesm2022/cdevhub-ngx-tw-radio.mjs +131 -98
  81. package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -1
  82. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +207 -42
  83. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -1
  84. package/fesm2022/cdevhub-ngx-tw-select-testing.mjs +165 -0
  85. package/fesm2022/cdevhub-ngx-tw-select-testing.mjs.map +1 -0
  86. package/fesm2022/cdevhub-ngx-tw-select.mjs +386 -210
  87. package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -1
  88. package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs +256 -0
  89. package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs.map +1 -0
  90. package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs +129 -0
  91. package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs.map +1 -0
  92. package/fesm2022/cdevhub-ngx-tw-sheet.mjs +197 -278
  93. package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -1
  94. package/fesm2022/cdevhub-ngx-tw-slider.mjs +89 -54
  95. package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -1
  96. package/fesm2022/cdevhub-ngx-tw-sort.mjs +122 -17
  97. package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -1
  98. package/fesm2022/cdevhub-ngx-tw-split.mjs +72 -19
  99. package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -1
  100. package/fesm2022/cdevhub-ngx-tw-stat.mjs +63 -25
  101. package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -1
  102. package/fesm2022/cdevhub-ngx-tw-stepper.mjs +35 -8
  103. package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -1
  104. package/fesm2022/cdevhub-ngx-tw-switch.mjs +54 -48
  105. package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -1
  106. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +12 -15
  107. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -1
  108. package/fesm2022/cdevhub-ngx-tw-table.mjs +74 -13
  109. package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -1
  110. package/fesm2022/cdevhub-ngx-tw-tabs.mjs +84 -30
  111. package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -1
  112. package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs +172 -0
  113. package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs.map +1 -0
  114. package/fesm2022/cdevhub-ngx-tw-tags-input.mjs +107 -71
  115. package/fesm2022/cdevhub-ngx-tw-tags-input.mjs.map +1 -1
  116. package/fesm2022/cdevhub-ngx-tw-textarea.mjs +41 -9
  117. package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -1
  118. package/fesm2022/cdevhub-ngx-tw-theme.mjs +257 -45
  119. package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -1
  120. package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs +201 -0
  121. package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs.map +1 -0
  122. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +184 -77
  123. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -1
  124. package/fesm2022/cdevhub-ngx-tw-timeline.mjs +110 -27
  125. package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -1
  126. package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs +616 -0
  127. package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs.map +1 -0
  128. package/fesm2022/cdevhub-ngx-tw-toast.mjs +556 -945
  129. package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -1
  130. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +102 -15
  131. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -1
  132. package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs +219 -0
  133. package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs.map +1 -0
  134. package/fesm2022/cdevhub-ngx-tw-transfer.mjs +88 -69
  135. package/fesm2022/cdevhub-ngx-tw-transfer.mjs.map +1 -1
  136. package/fesm2022/cdevhub-ngx-tw-tree.mjs +68 -19
  137. package/fesm2022/cdevhub-ngx-tw-tree.mjs.map +1 -1
  138. package/index.json +1 -1
  139. package/package.json +63 -2
  140. package/theme/_base.css +13 -0
  141. package/theme/_dark.css +110 -36
  142. package/theme/_high-contrast-dark.css +367 -0
  143. package/theme/_high-contrast.css +13 -2
  144. package/theme/_light.css +276 -0
  145. package/theme/_semantic.css +47 -12
  146. package/theme/_typography.css +17 -0
  147. package/theme/index.css +86 -7
  148. package/types/cdevhub-ngx-tw-accordion.d.ts +12 -4
  149. package/types/cdevhub-ngx-tw-avatar.d.ts +10 -3
  150. package/types/cdevhub-ngx-tw-button.d.ts +1 -0
  151. package/types/cdevhub-ngx-tw-calendar-luxon.d.ts +2 -2
  152. package/types/cdevhub-ngx-tw-calendar-testing.d.ts +1 -1
  153. package/types/cdevhub-ngx-tw-calendar.d.ts +179 -73
  154. package/types/cdevhub-ngx-tw-card.d.ts +11 -3
  155. package/types/cdevhub-ngx-tw-carousel.d.ts +89 -20
  156. package/types/cdevhub-ngx-tw-checkbox.d.ts +40 -12
  157. package/types/cdevhub-ngx-tw-code-block.d.ts +11 -2
  158. package/types/cdevhub-ngx-tw-collapsible.d.ts +32 -5
  159. package/types/cdevhub-ngx-tw-combobox-testing.d.ts +157 -0
  160. package/types/cdevhub-ngx-tw-combobox.d.ts +94 -53
  161. package/types/cdevhub-ngx-tw-command-palette-testing.d.ts +136 -0
  162. package/types/cdevhub-ngx-tw-command-palette.d.ts +33 -5
  163. package/types/cdevhub-ngx-tw-core.d.ts +152 -21
  164. package/types/cdevhub-ngx-tw-date-picker-testing.d.ts +141 -0
  165. package/types/cdevhub-ngx-tw-date-picker.d.ts +37 -29
  166. package/types/cdevhub-ngx-tw-date-range-picker-testing.d.ts +148 -0
  167. package/types/cdevhub-ngx-tw-date-range-picker.d.ts +36 -29
  168. package/types/cdevhub-ngx-tw-dialog-testing.d.ts +98 -0
  169. package/types/cdevhub-ngx-tw-dialog.d.ts +89 -19
  170. package/types/cdevhub-ngx-tw-file-upload-testing.d.ts +120 -0
  171. package/types/cdevhub-ngx-tw-file-upload.d.ts +8 -10
  172. package/types/cdevhub-ngx-tw-flip-card.d.ts +18 -11
  173. package/types/cdevhub-ngx-tw-form-field.d.ts +19 -2
  174. package/types/cdevhub-ngx-tw-icon.d.ts +3 -3
  175. package/types/cdevhub-ngx-tw-input.d.ts +5 -8
  176. package/types/cdevhub-ngx-tw-item.d.ts +2 -0
  177. package/types/cdevhub-ngx-tw-menu-testing.d.ts +131 -0
  178. package/types/cdevhub-ngx-tw-menu.d.ts +2 -2
  179. package/types/cdevhub-ngx-tw-number-input.d.ts +20 -0
  180. package/types/cdevhub-ngx-tw-paginator.d.ts +58 -24
  181. package/types/cdevhub-ngx-tw-popover.d.ts +41 -10
  182. package/types/cdevhub-ngx-tw-progress-bar.d.ts +1 -1
  183. package/types/cdevhub-ngx-tw-radio.d.ts +68 -25
  184. package/types/cdevhub-ngx-tw-segmented-control.d.ts +79 -16
  185. package/types/cdevhub-ngx-tw-select-testing.d.ts +114 -0
  186. package/types/cdevhub-ngx-tw-select.d.ts +104 -33
  187. package/types/cdevhub-ngx-tw-sheet-testing.d.ts +104 -0
  188. package/types/cdevhub-ngx-tw-sheet.d.ts +96 -21
  189. package/types/cdevhub-ngx-tw-slider.d.ts +79 -25
  190. package/types/cdevhub-ngx-tw-sort.d.ts +45 -4
  191. package/types/cdevhub-ngx-tw-split.d.ts +32 -2
  192. package/types/cdevhub-ngx-tw-stat.d.ts +14 -4
  193. package/types/cdevhub-ngx-tw-stepper.d.ts +16 -2
  194. package/types/cdevhub-ngx-tw-switch.d.ts +35 -13
  195. package/types/cdevhub-ngx-tw-tab-nav.d.ts +7 -6
  196. package/types/cdevhub-ngx-tw-table.d.ts +53 -10
  197. package/types/cdevhub-ngx-tw-tabs.d.ts +41 -10
  198. package/types/cdevhub-ngx-tw-tags-input-testing.d.ts +135 -0
  199. package/types/cdevhub-ngx-tw-tags-input.d.ts +26 -11
  200. package/types/cdevhub-ngx-tw-textarea.d.ts +3 -2
  201. package/types/cdevhub-ngx-tw-theme.d.ts +245 -39
  202. package/types/cdevhub-ngx-tw-time-picker-testing.d.ts +129 -0
  203. package/types/cdevhub-ngx-tw-time-picker.d.ts +76 -19
  204. package/types/cdevhub-ngx-tw-timeline.d.ts +36 -12
  205. package/types/cdevhub-ngx-tw-toast.d.ts +61 -12
  206. package/types/cdevhub-ngx-tw-tooltip.d.ts +28 -6
  207. package/types/cdevhub-ngx-tw-transfer-testing.d.ts +152 -0
  208. package/types/cdevhub-ngx-tw-transfer.d.ts +21 -8
  209. package/types/cdevhub-ngx-tw-tree.d.ts +6 -1
@@ -12,8 +12,19 @@ declare class SwitchComponent implements ControlValueAccessor, OnInit {
12
12
  readonly size: _angular_core.InputSignal<TwSize>;
13
13
  /** When true, prevents interaction and applies muted styling. Defaults to `false`. */
14
14
  readonly disabled: _angular_core.InputSignal<boolean>;
15
- /** When true, sets `aria-required="true"` so assistive tech announces the control as required. Defaults to `false`. */
16
- readonly required: _angular_core.InputSignal<boolean>;
15
+ /** When true, sets `aria-required="true"` so assistive tech announces the control as required. Also inferred from `Validators.required` / `Validators.requiredTrue` on a bound control, so a reactive/template-driven form does not have to state it twice. Defaults to `false`. */
16
+ readonly requiredInput: _angular_core.InputSignal<boolean>;
17
+ /**
18
+ * @internal Shared `errorState` / `required` / `errors` derivation — see
19
+ * `wireErrorState`. Declared here, above `required`, because class field
20
+ * initializers run in declaration order.
21
+ */
22
+ private readonly errorWiring;
23
+ /**
24
+ * @internal Resolved required state: the `required` input OR'd with
25
+ * `Validators.required` / `Validators.requiredTrue` on a bound `NgControl`.
26
+ */
27
+ readonly required: Signal<boolean>;
17
28
  /** Optional inline label rendered next to the switch. Use default content projection for rich label content instead. */
18
29
  readonly label: _angular_core.InputSignal<string | undefined>;
19
30
  /** Optional secondary description rendered under the label. Use `[slot="description"]` content projection for rich content instead. */
@@ -22,30 +33,41 @@ declare class SwitchComponent implements ControlValueAccessor, OnInit {
22
33
  readonly labelPosition: _angular_core.InputSignal<SwitchLabelPosition>;
23
34
  /** Optional name attribute, mirrored to the host for form association. */
24
35
  readonly name: _angular_core.InputSignal<string | undefined>;
25
- /** Accessible name when no visible label is provided. Mirrored to `aria-label`. */
36
+ /** Accessible name when no visible label is provided. Mirrored to `aria-label`. Defaults to `undefined`. */
26
37
  readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
27
- /** ID of an external element that labels the switch. Mirrored to `aria-labelledby`. */
38
+ /** ID of an external element that labels the switch. Mirrored to `aria-labelledby`. Defaults to `undefined`. */
28
39
  readonly ariaLabelledby: _angular_core.InputSignal<string | undefined>;
29
- /** ID of an external element that describes the switch. Mirrored to `aria-describedby`. */
40
+ /** ID of an external element that describes the switch. Mirrored to `aria-describedby`. Defaults to `undefined`. */
30
41
  readonly ariaDescribedby: _angular_core.InputSignal<string | undefined>;
31
- /** Two-way bound checked state. Updates when the user toggles via click or Space. */
42
+ /**
43
+ * Two-way bound checked state. Updates when the user toggles via click or
44
+ * Space, **and** when a bound form writes into the control
45
+ * (`FormControl.setValue`, `ngModel`, `writeValue`). Defaults to `false`.
46
+ *
47
+ * The two-way binding mints a `checkedChange` output. That output is the
48
+ * *any-change* channel: it fires on programmatic writes as well as user
49
+ * gestures. `(change)` is the *user-gesture-only* channel. Bind
50
+ * `(checkedChange)` to mirror state; bind `(change)` for analytics or a
51
+ * confirmation prompt, where a programmatic write must not count as a click.
52
+ * Writing back into the same form from a `(checkedChange)` handler will echo.
53
+ */
32
54
  readonly checked: _angular_core.ModelSignal<boolean>;
33
55
  /** Per-instance override of the {@link ErrorStateMatcher}. When omitted, the switch uses the `TW_ERROR_STATE_MATCHER` token's value. */
34
56
  readonly errorStateMatcher: _angular_core.InputSignal<ErrorStateMatcher | undefined>;
35
- /** Fires after the checked state changes from a user interaction. Does not fire when the value is updated programmatically via `writeValue`. */
57
+ /**
58
+ * Fires after the checked state changes from a user interaction (click or
59
+ * Space). Does **not** fire when the value is updated programmatically via
60
+ * `writeValue` / `FormControl.setValue` / `ngModel` — for those, bind the
61
+ * two-way binding's `(checkedChange)` instead, which fires on any change.
62
+ */
36
63
  readonly change: _angular_core.OutputEmitterRef<boolean>;
37
64
  private readonly focusMonitor;
38
65
  private readonly elementRef;
39
66
  private readonly destroyRef;
40
67
  private readonly ngControl;
41
- private readonly parentForm;
42
- private readonly parentFormGroup;
43
- private readonly defaultMatcher;
44
68
  private onChange;
45
69
  private onTouched;
46
70
  private readonly cvaDisabled;
47
- private readonly _ngControlRev;
48
- private readonly _formSubmitRev;
49
71
  private readonly uid;
50
72
  readonly hostId: string;
51
73
  readonly labelId: string;
@@ -81,7 +103,7 @@ declare class SwitchComponent implements ControlValueAccessor, OnInit {
81
103
  ngOnInit(): void;
82
104
  private hasAccessibleNameHint;
83
105
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SwitchComponent, never>;
84
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<SwitchComponent, "tw-switch", never, { "color": { "alias": "color"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "description": { "alias": "description"; "required": false; "isSignal": true; }; "labelPosition": { "alias": "labelPosition"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "ariaLabelledby": { "alias": "aria-labelledby"; "required": false; "isSignal": true; }; "ariaDescribedby": { "alias": "aria-describedby"; "required": false; "isSignal": true; }; "checked": { "alias": "checked"; "required": false; "isSignal": true; }; "errorStateMatcher": { "alias": "errorStateMatcher"; "required": false; "isSignal": true; }; }, { "checked": "checkedChange"; "change": "change"; }, never, ["[slot='off-icon']", "[slot='on-icon']", "*", "[slot='description']"], true, never>;
106
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SwitchComponent, "tw-switch", never, { "color": { "alias": "color"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "requiredInput": { "alias": "required"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "description": { "alias": "description"; "required": false; "isSignal": true; }; "labelPosition": { "alias": "labelPosition"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "ariaLabelledby": { "alias": "aria-labelledby"; "required": false; "isSignal": true; }; "ariaDescribedby": { "alias": "aria-describedby"; "required": false; "isSignal": true; }; "checked": { "alias": "checked"; "required": false; "isSignal": true; }; "errorStateMatcher": { "alias": "errorStateMatcher"; "required": false; "isSignal": true; }; }, { "checked": "checkedChange"; "change": "change"; }, never, ["[slot='off-icon']", "[slot='on-icon']", "*", "[slot='description']"], true, never>;
85
107
  }
86
108
 
87
109
  export { SwitchComponent };
@@ -10,7 +10,7 @@ interface TabNavLabels {
10
10
  activeTabAnnouncement?: (label: string, index: number, total: number) => string;
11
11
  }
12
12
  declare class TabNavPanel {
13
- /** Unique id for this panel. Referenced by the active link's `aria-controls`. Auto-generated when not provided. */
13
+ /** Unique id for this panel. Referenced by the active link's `aria-controls`. Defaults to an auto-generated `tw-tab-nav-panel-N` id. */
14
14
  readonly id: _angular_core.InputSignal<string>;
15
15
  /** @internal Id of the active link — set by the associated TabNavComponent. */
16
16
  readonly activeTabId: _angular_core.WritableSignal<string | undefined>;
@@ -30,9 +30,9 @@ declare class TabNavComponent {
30
30
  readonly tabPanel: _angular_core.InputSignal<TabNavPanel | undefined>;
31
31
  /** Additional classes merged onto the `<nav>` host. Useful for layout tweaks or borders that the default tv() config does not cover. */
32
32
  readonly navClass: _angular_core.InputSignal<string>;
33
- /** Additional classes merged onto every tab link. Applied after base/active/disabled classes so consumer styles always win the cascade. */
33
+ /** Additional classes merged onto every tab link. Applied after base/active/disabled classes so consumer styles always win the cascade. Defaults to an empty string. */
34
34
  readonly linkClass: _angular_core.InputSignal<string>;
35
- /** Optional label overrides for screen-reader announcements. Only used in the ARIA tabs pattern (i.e. when a panel is associated). */
35
+ /** Optional label overrides for screen-reader announcements. Only used in the ARIA tabs pattern (i.e. when a panel is associated). Defaults to an empty object — every field falls back to its own default. */
36
36
  readonly labels: _angular_core.InputSignal<TabNavLabels>;
37
37
  /** @internal Tab links discovered via content projection. */
38
38
  readonly links: _angular_core.Signal<readonly TabLinkDirective[]>;
@@ -42,11 +42,12 @@ declare class TabNavComponent {
42
42
  readonly resolvedPanel: _angular_core.Signal<TabNavPanel | undefined>;
43
43
  private readonly liveAnnouncer;
44
44
  private readonly directionality;
45
- private readonly destroyRef;
46
45
  /**
47
46
  * Live layout direction. Hardcoding 'ltr' inverts ArrowLeft/ArrowRight in RTL
48
47
  * locales — the arrow moves to the next link in DOM order but the previous
49
- * one visually. Mirrored into a signal so the key manager rebuilds on change.
48
+ * one visually. Read straight from CDK's `Directionality.valueSignal`
49
+ * (CDK 22+) so the key-manager effect rebuilds on a runtime `dir` flip with
50
+ * no manual subscription mirror.
50
51
  */
51
52
  private readonly layoutDirection;
52
53
  /** Tracks the previously-announced active link id so we only announce on actual changes. `null` = before the first sync. */
@@ -80,7 +81,7 @@ declare class TabLinkDirective {
80
81
  readonly active: _angular_core.InputSignal<boolean>;
81
82
  /** When true, the link is visually disabled and cannot be activated by click or keyboard. Defaults to `false`. */
82
83
  readonly disabled: _angular_core.InputSignal<boolean>;
83
- /** Unique id for this link. Referenced by the panel's `aria-labelledby` when the link is active. Auto-generated when not provided. */
84
+ /** Unique id for this link. Referenced by the panel's `aria-labelledby` when the link is active. Defaults to an auto-generated `tw-tab-link-N` id. */
84
85
  readonly linkId: _angular_core.InputSignal<string>;
85
86
  /**
86
87
  * @internal ARIA role — `'tab'` when the nav is wired to a panel (APG
@@ -87,6 +87,18 @@ interface TwTableLabels {
87
87
  collapseRowLabel: string;
88
88
  /** Accessible label for the master "select all" checkbox in the leading selection column. */
89
89
  selectAllLabel: string;
90
+ /**
91
+ * Accessible name for the leading selection column's header cell, used when no master checkbox
92
+ * can be rendered (non-array data sources). Without it the `<th>` is literally empty, which is an
93
+ * axe `empty-table-header` failure and leaves the column unnamed in a screen reader's table
94
+ * summary. Rendered visually hidden.
95
+ *
96
+ * Optional on purpose: added after the interface shipped, so a required
97
+ * member would be a compile break for any consumer annotating a complete
98
+ * `TwTableLabels` literal — in exchange for a label that already has a
99
+ * sensible default. The component merges against `DEFAULT_TABLE_LABELS`.
100
+ */
101
+ selectionColumnLabel?: string;
90
102
  /** Accessible label template for each per-row selection checkbox. Variable: `{index}` (1-based). */
91
103
  selectRowLabel: string;
92
104
  }
@@ -171,8 +183,11 @@ interface TwRowClickEvent<T> {
171
183
  row: T;
172
184
  /** Zero-based index in the rendered data. */
173
185
  index: number;
174
- /** The original DOM event. */
175
- event: MouseEvent;
186
+ /**
187
+ * The original DOM event. A `MouseEvent` for pointer activation, or a `KeyboardEvent` when the
188
+ * row was activated with Enter / Space (only possible when `clickableRows` is `true`).
189
+ */
190
+ event: MouseEvent | KeyboardEvent;
176
191
  }
177
192
  /** Payload emitted by `selectionChange`. */
178
193
  interface TwSelectionChangeEvent<T> {
@@ -228,7 +243,7 @@ declare class NoDataRowDirective extends CdkNoDataRow {
228
243
  }
229
244
  /** Structural directive on an `<ng-template>` declaring the row-expansion template. Requires `[multiTemplateRows]="true"` on the parent `<tw-table>`. */
230
245
  declare class RowExpansionDirective<T = unknown> {
231
- /** Optional predicate that decides whether this expansion renders for a given row. Defaults to `undefined` (render for every expanded row). */
246
+ /** Optional predicate that decides whether this expansion renders for a given row. Defaults to `undefined` (render for every expanded row). Alias: `twRowExpansionWhen`. */
232
247
  readonly predicate: _angular_core.InputSignal<((row: T, index: number) => boolean) | undefined>;
233
248
  /** @internal */
234
249
  readonly template: TemplateRef<any>;
@@ -347,15 +362,22 @@ declare class TableComponent<T = unknown> {
347
362
  readonly selection: _angular_core.InputSignal<TwTableSelection>;
348
363
  /** Whether multiple row templates may render per data object. Required for `*twRowExpansion` and advanced `*twRowDef [when]` usage. Defaults to `false`. */
349
364
  readonly multiTemplateRows: _angular_core.InputSignal<boolean>;
365
+ /**
366
+ * Whether data rows are activatable. Set this whenever you bind `(rowClicked)` — it is what puts
367
+ * each row in the tab order, wires Enter / Space to the same handler as a click, and paints the
368
+ * focus ring. Left `false`, `(rowClicked)` stays pointer-only, which keeps a static table out of
369
+ * the tab order. Defaults to `false`.
370
+ */
371
+ readonly clickableRows: _angular_core.InputSignal<boolean>;
350
372
  /** Overrides for user-facing strings. Unset keys fall back to the English defaults. Defaults to `{}`. */
351
373
  readonly labels: _angular_core.InputSignal<Partial<TwTableLabels>>;
352
- /** Accessible name for the `<table>`. Required when no visible `<caption slot="caption">` is provided. */
374
+ /** Accessible name for the `<table>`. Required when no visible `<caption slot="caption">` is provided. Defaults to `undefined`. Alias: `aria-label`. */
353
375
  readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
354
- /** Id of an external element labelling the table. Mirrored to `aria-labelledby` on the `<table>`. */
376
+ /** Id of an external element labelling the table. Mirrored to `aria-labelledby` on the `<table>`. Defaults to `undefined`. */
355
377
  readonly ariaLabelledby: _angular_core.InputSignal<string | undefined>;
356
- /** Two-way bound set of rows currently expanded. Immutable — set a new `Set` on every change; do not mutate in place. */
378
+ /** Two-way bound set of rows currently expanded. Immutable — set a new `Set` on every change; do not mutate in place. Defaults to an empty set. */
357
379
  readonly expandedRows: _angular_core.ModelSignal<ReadonlySet<T>>;
358
- /** Two-way bound list of selected rows. Set a new array on every change; do not mutate. Only used when `selection.enabled` is `true`. */
380
+ /** Two-way bound list of selected rows. Set a new array on every change; do not mutate. Only used when `selection.enabled` is `true`. Defaults to an empty array. */
359
381
  readonly selected: _angular_core.ModelSignal<readonly T[]>;
360
382
  /** Fires when a row is clicked. Suppressed when the click originated inside an interactive descendant (button, link, input, etc.). */
361
383
  readonly rowClicked: _angular_core.OutputEmitterRef<TwRowClickEvent<T>>;
@@ -396,8 +418,16 @@ declare class TableComponent<T = unknown> {
396
418
  readonly shouldRenderEmptyOverlay: _angular_core.Signal<boolean>;
397
419
  /** @internal Whether the error overlay should render. */
398
420
  readonly shouldRenderErrorOverlay: _angular_core.Signal<boolean>;
399
- /** @internal Resolved table labels (defaults merged with input overrides). */
400
- readonly resolvedLabels: _angular_core.Signal<TwTableLabels>;
421
+ /**
422
+ * @internal Resolved table labels (defaults merged with input overrides).
423
+ *
424
+ * Explicitly-undefined keys are dropped before merging: a plain spread lets
425
+ * `{ selectionColumnLabel: undefined }` overwrite the default with undefined,
426
+ * which renders an empty `sr-only` span and reinstates the
427
+ * `empty-table-header` failure the label exists to prevent. `Required<>`
428
+ * then guarantees the template a string for every label.
429
+ */
430
+ readonly resolvedLabels: _angular_core.Signal<Required<TwTableLabels>>;
401
431
  /** @internal Computed error message for the default error overlay. Empty when no error is set. */
402
432
  readonly errorMessage: _angular_core.Signal<string>;
403
433
  /** @internal CSS max-height string for the scroll container. */
@@ -434,6 +464,7 @@ declare class TableComponent<T = unknown> {
434
464
  readonly errorMessageClasses: _angular_core.Signal<string>;
435
465
  readonly footerSlotClasses: _angular_core.Signal<string>;
436
466
  readonly paginationSlotClasses: _angular_core.Signal<string>;
467
+ readonly dataRowClasses: _angular_core.Signal<string>;
437
468
  readonly expansionRowClasses: _angular_core.Signal<string>;
438
469
  readonly expansionCellClasses: _angular_core.Signal<string>;
439
470
  readonly selectionHeaderClasses: _angular_core.Signal<string>;
@@ -441,6 +472,18 @@ declare class TableComponent<T = unknown> {
441
472
  constructor();
442
473
  /** @internal Called by the template when a data row is clicked. */
443
474
  handleRowClick(row: T, index: number, event: MouseEvent): void;
475
+ /**
476
+ * @internal Keyboard counterpart to `handleRowClick`. Only reachable when `clickableRows` is
477
+ * `true`, because that is the only state in which the `<tr>` carries `tabindex`.
478
+ *
479
+ * The `target !== currentTarget` guard is what keeps Enter on a button *inside* a cell from also
480
+ * activating the row: that keystroke's target is the button, and its own click already bubbles
481
+ * into `handleRowClick`, which suppresses it. Reusing the `composedPath()` walk here would let
482
+ * the row fire a second time.
483
+ */
484
+ handleRowKeydown(row: T, index: number, event: KeyboardEvent): void;
485
+ /** @internal `tabindex` for a data row — present only while rows are activatable. */
486
+ readonly rowTabIndex: _angular_core.Signal<0 | null>;
444
487
  /** @internal Whether a row is currently expanded. */
445
488
  isRowExpanded(row: T): boolean;
446
489
  /** @internal CDK `when` predicate used for the auto-generated expansion row. */
@@ -501,7 +544,7 @@ declare class TableComponent<T = unknown> {
501
544
  /** @internal Formatted accessible label for a per-row selection checkbox. */
502
545
  selectRowLabel(rowIndex: number): string;
503
546
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TableComponent<any>, never>;
504
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<TableComponent<any>, "tw-table", ["twTable"], { "data": { "alias": "data"; "required": false; "isSignal": true; }; "trackBy": { "alias": "trackBy"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "error": { "alias": "error"; "required": false; "isSignal": true; }; "appearance": { "alias": "appearance"; "required": false; "isSignal": true; }; "sticky": { "alias": "sticky"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; "selection": { "alias": "selection"; "required": false; "isSignal": true; }; "multiTemplateRows": { "alias": "multiTemplateRows"; "required": false; "isSignal": true; }; "labels": { "alias": "labels"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "ariaLabelledby": { "alias": "aria-labelledby"; "required": false; "isSignal": true; }; "expandedRows": { "alias": "expandedRows"; "required": false; "isSignal": true; }; "selected": { "alias": "selected"; "required": false; "isSignal": true; }; }, { "expandedRows": "expandedRowsChange"; "selected": "selectedChange"; "rowClicked": "rowClicked"; "selectionChange": "selectionChange"; "expansionChange": "expansionChange"; }, ["columns", "noDataRow", "expansionTemplate"], ["[slot='toolbar']", "[slot='caption']", "*", "[slot='empty']", "[slot='error']", "[slot='loading']", "[slot='footer']", "[slot='pagination']"], true, never>;
547
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TableComponent<any>, "tw-table", ["twTable"], { "data": { "alias": "data"; "required": false; "isSignal": true; }; "trackBy": { "alias": "trackBy"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "error": { "alias": "error"; "required": false; "isSignal": true; }; "appearance": { "alias": "appearance"; "required": false; "isSignal": true; }; "sticky": { "alias": "sticky"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; "selection": { "alias": "selection"; "required": false; "isSignal": true; }; "multiTemplateRows": { "alias": "multiTemplateRows"; "required": false; "isSignal": true; }; "clickableRows": { "alias": "clickableRows"; "required": false; "isSignal": true; }; "labels": { "alias": "labels"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "ariaLabelledby": { "alias": "aria-labelledby"; "required": false; "isSignal": true; }; "expandedRows": { "alias": "expandedRows"; "required": false; "isSignal": true; }; "selected": { "alias": "selected"; "required": false; "isSignal": true; }; }, { "expandedRows": "expandedRowsChange"; "selected": "selectedChange"; "rowClicked": "rowClicked"; "selectionChange": "selectionChange"; "expansionChange": "expansionChange"; }, ["columns", "noDataRow", "expansionTemplate"], ["[slot='toolbar']", "[slot='caption']", "*", "[slot='empty']", "[slot='error']", "[slot='loading']", "[slot='footer']", "[slot='pagination']"], true, never>;
505
548
  }
506
549
 
507
550
  export { CellDefDirective, ColumnComponent, DEFAULT_TABLE_LABELS, FooterCellDefDirective, HeaderCellDefDirective, NoDataRowDirective, RowExpansionDirective, TableComponent };
@@ -18,11 +18,11 @@ declare class TabContentDirective {
18
18
  declare class TabComponent {
19
19
  /** Unique identifier for this tab. Used to match the active tab value. */
20
20
  readonly value: _angular_core.InputSignal<string>;
21
- /** Plain text label shown in the trigger. Ignored when a custom trigger template is provided. */
21
+ /** Plain text label shown in the trigger. Ignored when a custom trigger template is provided. Defaults to an empty string. */
22
22
  readonly label: _angular_core.InputSignal<string>;
23
23
  /** When true, the tab cannot be selected and is skipped by keyboard navigation. Defaults to false. */
24
24
  readonly disabled: _angular_core.InputSignal<boolean>;
25
- /** When true, a close button is rendered in the tab trigger. Defaults to false. */
25
+ /** When true, a dismiss control is rendered in the tab trigger. The control is pointer-only; the keyboard gesture is Delete on the focused tab. Defaults to false. */
26
26
  readonly closable: _angular_core.InputSignal<boolean>;
27
27
  /** When true, the tab panel content is only instantiated when the tab becomes active for the first time. Defaults to false. */
28
28
  readonly lazy: _angular_core.InputSignal<boolean>;
@@ -37,9 +37,17 @@ declare class TabComponent {
37
37
  }
38
38
  declare class TabTriggerElementDirective implements FocusableOption {
39
39
  readonly elementRef: ElementRef<any>;
40
- readonly isActive: _angular_core.InputSignal<boolean>;
40
+ /**
41
+ * Whether this trigger owns the tablist's single tab stop. Drives
42
+ * `tabindex`. Normally the active tab, but the parent falls back to the
43
+ * first enabled tab when `value` matches nothing, so the tablist is never
44
+ * left with zero tab stops. Defaults to `false`.
45
+ */
46
+ readonly isFocusStop: _angular_core.InputSignal<boolean>;
47
+ /** Whether this trigger is disabled. Read by `FocusKeyManager` so disabled triggers are skipped during arrow navigation. Defaults to `false`. */
41
48
  readonly isDisabled: _angular_core.InputSignal<boolean>;
42
49
  readonly tabIndex: _angular_core.Signal<0 | -1>;
50
+ /** Moves DOM focus to the trigger element. Called by `FocusKeyManager` during arrow-key navigation. */
43
51
  focus(): void;
44
52
  /**
45
53
  * FocusableOption getter. NOTE: we cannot expose the `isDisabled` input
@@ -49,7 +57,7 @@ declare class TabTriggerElementDirective implements FocusableOption {
49
57
  */
50
58
  get disabled(): boolean;
51
59
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TabTriggerElementDirective, never>;
52
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TabTriggerElementDirective, "[twTabTriggerElement]", never, { "isActive": { "alias": "isActive"; "required": false; "isSignal": true; }; "isDisabled": { "alias": "isDisabled"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
60
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TabTriggerElementDirective, "[twTabTriggerElement]", never, { "isFocusStop": { "alias": "isFocusStop"; "required": false; "isSignal": true; }; "isDisabled": { "alias": "isDisabled"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
53
61
  }
54
62
  declare class TabsComponent implements AfterViewInit {
55
63
  /** Controls the visual style of the tab strip. Defaults to 'underline'. */
@@ -62,18 +70,20 @@ declare class TabsComponent implements AfterViewInit {
62
70
  readonly orientation: _angular_core.InputSignal<"vertical" | "horizontal">;
63
71
  /** When true, tab triggers stretch to fill the available width equally. Defaults to false. */
64
72
  readonly fitted: _angular_core.InputSignal<boolean>;
65
- /** The value of the currently active tab. Two-way bound. Updates when the user selects a tab. */
73
+ /** The value of the currently active tab. Two-way bound. Updates when the user selects a tab. Defaults to an empty string. */
66
74
  readonly value: _angular_core.ModelSignal<string>;
67
- /** Fires when a closable tab's close button is clicked. Payload is the tab's value. */
75
+ /** Fires when a closable tab is dismissed, either by clicking its close control or by pressing Delete while the tab has focus. Payload is the tab's value. */
68
76
  readonly closed: _angular_core.OutputEmitterRef<string>;
69
77
  private readonly destroyRef;
70
78
  private readonly liveAnnouncer;
71
79
  private readonly directionality;
72
80
  /**
73
- * Live layout direction, mirrored into a signal so the key manager rebuilds
74
- * when it changes. Without this the tablist hardcodes 'ltr' and ArrowRight
75
- * moves to the next tab in DOM order but the *previous* tab visually in an
76
- * RTL locale. CdkStepper and `tw-split` already honour Directionality.
81
+ * Live layout direction, read straight from CDK's `Directionality.valueSignal`
82
+ * (CDK 22+) so the key-manager effect re-runs on a runtime `dir` flip with no
83
+ * manual subscription mirror. Without a live direction the tablist hardcodes
84
+ * 'ltr' and ArrowRight moves to the next tab in DOM order but the *previous*
85
+ * tab visually in an RTL locale. CdkStepper and `tw-split` already honour
86
+ * Directionality; `tw-paginator` reads `valueSignal` the same way.
77
87
  */
78
88
  private readonly layoutDirection;
79
89
  /** @internal */
@@ -100,11 +110,30 @@ declare class TabsComponent implements AfterViewInit {
100
110
  readonly closeButtonClasses: _angular_core.Signal<string>;
101
111
  /** @internal Get combined trigger classes for a given tab. */
102
112
  getTriggerClasses(_tabValue: string, isActive: boolean): string;
113
+ /** Builds the DOM id for a tab trigger, used by the panel's `aria-labelledby`. */
103
114
  getTabId(tabValue: string): string;
115
+ /** Builds the DOM id for a tab panel, used by the trigger's `aria-controls`. */
104
116
  getPanelId(tabValue: string): string;
117
+ /** Whether the tab with the given value is the currently active one. */
105
118
  isTabActive(tabValue: string): boolean;
119
+ /**
120
+ * @internal Value of the tab that owns the tablist's single tab stop.
121
+ *
122
+ * The active tab whenever it exists and is enabled. When `value` matches no
123
+ * tab — a stale id, a value cleared after init, or an active tab that is
124
+ * disabled — the first enabled tab takes the tab stop instead (standard
125
+ * roving-tabindex recovery). Without the fallback every trigger renders
126
+ * `tabindex="-1"` and the whole tablist silently leaves the tab order
127
+ * (WCAG SC 2.1.1).
128
+ */
129
+ readonly focusStopValue: _angular_core.Signal<string | null>;
130
+ /** Whether the tab with the given value owns the tablist's single tab stop. */
131
+ isTabFocusStop(tabValue: string): boolean;
132
+ /** Whether a tab's panel content should be in the DOM. Always true for eager tabs; for lazy tabs, true only once the tab has been activated at least once. */
106
133
  shouldRenderPanel(tab: TabComponent): boolean;
134
+ /** Activates a tab, updating the two-way bound `value`, marking it rendered for lazy panels, and announcing the change via `LiveAnnouncer`. Ignored when the tab is disabled. */
107
135
  selectTab(tab: TabComponent): void;
136
+ /** Closes a closable tab, emitting `closed` with its value and moving activation to the nearest enabled sibling when the closed tab was active. */
108
137
  closeTab(tab: TabComponent, event: Event): void;
109
138
  private findNearestEnabledTab;
110
139
  private keyManager;
@@ -114,7 +143,9 @@ declare class TabsComponent implements AfterViewInit {
114
143
  * so we lose the native button activation) and Delete to close a closable tab.
115
144
  */
116
145
  onKeydown(event: KeyboardEvent): void;
146
+ /** Smoothly scrolls the tablist back toward its start by one step, along the current orientation's axis. */
117
147
  scrollStart(): void;
148
+ /** Smoothly scrolls the tablist forward toward its end by one step, along the current orientation's axis. */
118
149
  scrollEnd(): void;
119
150
  private updateScrollState;
120
151
  ngAfterViewInit(): void;
@@ -0,0 +1,135 @@
1
+ import { BaseHarnessFilters, ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';
2
+
3
+ /** Filters accepted by `TagsInputTagHarness.with`. */
4
+ interface TagsInputTagHarnessFilters extends BaseHarnessFilters {
5
+ /** Match by the chip's visible label. */
6
+ text?: string | RegExp;
7
+ }
8
+ /**
9
+ * Harness for a single committed chip inside a `tw-tags-input`.
10
+ *
11
+ * Chips are rendered by composing `[twBadge]`, so that attribute is the host
12
+ * selector. Reach these through {@link TagsInputHarness.getTags} rather than
13
+ * locating them directly against a fixture — located from a document root the
14
+ * selector would also match every unrelated badge on the page.
15
+ */
16
+ declare class TagsInputTagHarness extends ComponentHarness {
17
+ static hostSelector: string;
18
+ /**
19
+ * The chip's remove control. It is the only `<button>` a chip contains: the
20
+ * badge's own `dismissible` button is not enabled here, so this always
21
+ * resolves to the tags-input remove control.
22
+ */
23
+ private readonly removeButton;
24
+ /** Predicate for `locatorFor` / `locatorForAll`. */
25
+ static with(options?: TagsInputTagHarnessFilters): HarnessPredicate<TagsInputTagHarness>;
26
+ /**
27
+ * The chip's visible label, trimmed. This is `tagLabel(tag)`, not the tag
28
+ * value — for object tags the two differ.
29
+ */
30
+ getText(): Promise<string>;
31
+ /**
32
+ * The remove control's accessible name (`Remove <label>`). Useful for
33
+ * asserting the control is announced, which is the only signal a screen
34
+ * reader gets for a chip.
35
+ */
36
+ getRemoveLabel(): Promise<string | null>;
37
+ /**
38
+ * Clicks the chip's remove control. The component restores focus to the
39
+ * neighbouring chip (or the text input when none remain), so the caller may
40
+ * assert focus immediately afterwards.
41
+ */
42
+ remove(): Promise<void>;
43
+ }
44
+
45
+ /** Filters accepted by `TagsInputHarness.with`. */
46
+ interface TagsInputHarnessFilters extends BaseHarnessFilters {
47
+ /** Match by the control's accessible name (its `aria-label`). */
48
+ label?: string | RegExp;
49
+ /** Match disabled / enabled controls. */
50
+ disabled?: boolean;
51
+ }
52
+ /**
53
+ * Harness for `tw-tags-input`.
54
+ *
55
+ * The control renders committed tags as chips followed by a single text input;
56
+ * everything lives inside the `tw-tags-input` host, so no overlay handling is
57
+ * needed and the ordinary fixture loader is enough.
58
+ *
59
+ * Note where the ARIA lives: the host is a `role="group"`, which ARIA 1.2 does
60
+ * not allow to carry `aria-required` / `aria-invalid`, so those sit on the
61
+ * inner text input — the element that actually owns the pending value.
62
+ * {@link isRequired} and {@link isInvalid} read them from there;
63
+ * {@link isDisabled} reads `aria-disabled` from the group, which is allowed.
64
+ */
65
+ declare class TagsInputHarness extends ComponentHarness {
66
+ static hostSelector: string;
67
+ private readonly textInput;
68
+ /** Predicate for `locatorFor` / `locatorForAll`. */
69
+ static with(options?: TagsInputHarnessFilters): HarnessPredicate<TagsInputHarness>;
70
+ /** The control's accessible name, from `aria-label` when one is set. */
71
+ getLabel(): Promise<string | null>;
72
+ /** Whether the group reports `aria-disabled="true"`. */
73
+ isDisabled(): Promise<boolean>;
74
+ /** Whether the text input reports `aria-required="true"`. */
75
+ isRequired(): Promise<boolean>;
76
+ /** Whether the text input reports `aria-invalid="true"`. */
77
+ isInvalid(): Promise<boolean>;
78
+ /**
79
+ * Every committed chip, in render order. Remove by index by indexing this
80
+ * array — `(await input.getTags())[1].remove()` — which is why no
81
+ * `removeTagAt(index)` exists.
82
+ */
83
+ getTags(filters?: TagsInputTagHarnessFilters): Promise<TagsInputTagHarness[]>;
84
+ /** The visible label of every committed chip, in render order. */
85
+ getTagTexts(): Promise<string[]>;
86
+ /** The in-progress (uncommitted) text currently in the input. */
87
+ getInputValue(): Promise<string>;
88
+ /**
89
+ * Types `text` into the input and commits it with Enter. Typing appends, so
90
+ * any pending text already in the input is committed along with it.
91
+ *
92
+ * Enter is the commit gesture only while `separatorKeys` contains `'Enter'`
93
+ * (the default). A control configured with, say, `[separatorKeys]="[';']"`
94
+ * commits through {@link typeInput} instead — `typeInput('alpha;')`.
95
+ *
96
+ * The commit may be dropped by the component (empty, duplicate, or `maxTags`
97
+ * reached); assert against {@link getTagTexts} rather than assuming it
98
+ * landed.
99
+ */
100
+ addTag(text: string): Promise<void>;
101
+ /**
102
+ * Types `text` into the input character by character, appending to whatever
103
+ * is already there. Use it to stage pending text that {@link addTag} would
104
+ * commit for you — reading it back, discarding it, or letting `addOnBlur`
105
+ * pick it up.
106
+ *
107
+ * A separator character in `text` does commit the text before it, but CDK's
108
+ * synthetic typing appends every character to the input regardless of the
109
+ * component's `preventDefault()`, so the separator itself is left behind in
110
+ * the input where a real browser swallows it. Commit with {@link addTag},
111
+ * and treat a trailing separator here as staging, not as a commit gesture.
112
+ */
113
+ typeInput(text: string): Promise<void>;
114
+ /**
115
+ * Removes the first chip whose label matches. Throws when nothing matches,
116
+ * rather than failing silently.
117
+ */
118
+ removeTag(text: string | RegExp): Promise<void>;
119
+ /**
120
+ * Discards the in-progress text with Escape — the control's own clear
121
+ * gesture. A no-op when the input is already empty. Does not touch committed
122
+ * chips.
123
+ */
124
+ clearInput(): Promise<void>;
125
+ /** Moves focus to the text input. */
126
+ focus(): Promise<void>;
127
+ /**
128
+ * Moves focus out of the control. This is the gesture that marks the control
129
+ * touched and, with `addOnBlur`, commits the pending text.
130
+ */
131
+ blur(): Promise<void>;
132
+ }
133
+
134
+ export { TagsInputHarness, TagsInputTagHarness };
135
+ export type { TagsInputHarnessFilters, TagsInputTagHarnessFilters };
@@ -59,7 +59,7 @@ declare class TagsInputComponent<T = string> extends FormFieldControl<T[]> imple
59
59
  readonly disabledInput: _angular_core.InputSignal<boolean>;
60
60
  /** Marks the control as required. Mirrored to the input's `aria-required`. Also inferred from `Validators.required` on a bound control. Defaults to `false`. */
61
61
  readonly requiredInput: _angular_core.InputSignal<boolean>;
62
- /** Placeholder shown in the text input only while there are no chips and the input is empty. */
62
+ /** Placeholder shown in the text input only while there are no chips and the input is empty. Defaults to `undefined`. */
63
63
  readonly placeholder: _angular_core.InputSignal<string | undefined>;
64
64
  /** Keys that commit the in-progress text as a tag. Each entry is a `KeyboardEvent.key` value (`'Enter'`) or a single separator character (`','`). Single-character separators also split pasted text. Defaults to `['Enter', ',']`. */
65
65
  readonly separatorKeys: _angular_core.InputSignal<readonly string[]>;
@@ -75,19 +75,30 @@ declare class TagsInputComponent<T = string> extends FormFieldControl<T[]> imple
75
75
  readonly tagLabel: _angular_core.InputSignal<TwTagLabelFn<T>>;
76
76
  /** Equality comparator used for dedup when `allowDuplicates` is false. Defaults to `Object.is` (reference / value identity). String tags dedupe case-sensitively by default; pass `(a, b) => a.toLowerCase() === b.toLowerCase()` for case-insensitive dedup. */
77
77
  readonly compareWith: _angular_core.InputSignal<TwTagCompareFn<T>>;
78
- /** Applied to the text input for labeling and identification only; does not submit the tag array via native (non-Angular) form posting. */
78
+ /** Applied to the text input for labeling and identification only; does not submit the tag array via native (non-Angular) form posting. Defaults to `undefined`. */
79
79
  readonly name: _angular_core.InputSignal<string | undefined>;
80
80
  /** Id on the host element. Auto-generated as `tw-tags-input-N` when not provided. Used by the form-field's `<label for>` association. */
81
81
  readonly idInput: _angular_core.InputSignal<string | undefined>;
82
- /** Accessible name applied to the control when no visible label is wired. Mirrored to `aria-label`. */
82
+ /** Accessible name applied to the control when no visible label is wired. Mirrored to `aria-label`. Defaults to `undefined`. */
83
83
  readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
84
- /** ID of an external element that labels the control. Mirrored to `aria-labelledby`. */
84
+ /** ID of an external element that labels the control. Mirrored to `aria-labelledby`. Defaults to `undefined`. */
85
85
  readonly ariaLabelledby: _angular_core.InputSignal<string | undefined>;
86
- /** ID of an external element that describes the control. Form-field merges its hint / error ids alongside. */
86
+ /** ID of an external element that describes the control. Form-field merges its hint / error ids alongside. Defaults to `undefined`. Alias: `aria-describedby`. */
87
87
  readonly ariaDescribedby: _angular_core.InputSignal<string | undefined>;
88
88
  /** Per-instance override of the {@link ErrorStateMatcher}. When omitted, uses the `TW_ERROR_STATE_MATCHER` token's value. */
89
89
  readonly errorStateMatcher: _angular_core.InputSignal<ErrorStateMatcher | undefined>;
90
- /** Fires when the tag array changes through user interaction (add, remove, clear). Emits a fresh array reference. Does not fire on `writeValue`. */
90
+ /**
91
+ * Fires when the tag array changes through user interaction (add, remove,
92
+ * clear). Emits a fresh array reference. Does **not** fire on `writeValue` /
93
+ * `FormControl.setValue` / `ngModel`.
94
+ *
95
+ * This is a hand-written, user-gesture-only output. The control exposes no
96
+ * `value` input and therefore no two-way binding, so — unlike
97
+ * `tw-checkbox` / `tw-switch` / `tw-radio-group`, where `(valueChange)` /
98
+ * `(checkedChange)` is minted by a `model()` and fires on programmatic writes
99
+ * too — there is no any-change channel here. Observe programmatic writes
100
+ * through the bound form control's own `valueChanges`.
101
+ */
91
102
  readonly valueChange: _angular_core.OutputEmitterRef<T[]>;
92
103
  /** Fires when a tag is committed via Enter, a separator key, paste, or `addTag()`. Does not fire for dropped duplicates, blocked-by-max commits, empty commits, or `writeValue`. */
93
104
  readonly tagAdded: _angular_core.OutputEmitterRef<TwTagAddedEvent<T>>;
@@ -98,10 +109,14 @@ declare class TagsInputComponent<T = string> extends FormFieldControl<T[]> imple
98
109
  private readonly elementRef;
99
110
  private readonly destroyRef;
100
111
  private readonly ngControl;
101
- private readonly parentForm;
102
- private readonly parentFormGroup;
103
- private readonly defaultMatcher;
104
112
  private readonly formField;
113
+ /**
114
+ * Optional so a consumer that never imports `BidiModule` still gets a working
115
+ * control — chip navigation falls back to LTR when the token is absent. Read
116
+ * imperatively inside the keydown handlers; nothing here needs to re-render
117
+ * on a direction change.
118
+ */
119
+ private readonly directionality;
105
120
  private readonly textInputRef;
106
121
  private readonly removeButtons;
107
122
  private onChange;
@@ -113,8 +128,8 @@ declare class TagsInputComponent<T = string> extends FormFieldControl<T[]> imple
113
128
  protected readonly activeChipIndex: _angular_core.WritableSignal<number | null>;
114
129
  private readonly cvaDisabled;
115
130
  private readonly _focused;
116
- private readonly _ngControlRev;
117
- private readonly _formSubmitRev;
131
+ /** @internal Shared `errorState` / `required` / `errors` derivation — see `wireErrorState`. */
132
+ private readonly errorWiring;
118
133
  private readonly describedByIdsSignal;
119
134
  private readonly labelledByIdsSignal;
120
135
  /** Nonce bumped only on explicit focus intent — keeps the focus effect from stealing focus on unrelated renders. */
@@ -33,7 +33,8 @@ type TwTextareaResize = 'none' | 'vertical' | 'both';
33
33
  */
34
34
  declare class TextareaDirective extends InputDirective {
35
35
  private readonly cdkAutosize;
36
- /** Density of a standalone textarea. Maps to the inline-padding + font scale (`xs` … `xl`). Ignored inside a `<tw-form-field>` — the wrapper's `size` carries density. Defaults to `'md'`. */
36
+ private readonly parentFormField;
37
+ /** Density of a standalone textarea. Maps to the inline-padding + font scale (`xs` … `xl`) and to a `min-h-*` floor on the control-height scale (24/32/36/44/48px) — a floor, not a fixed height, because a textarea must grow with its content. The floor is dropped while `autosize` is on (CDK owns the height then; `minRows` is the floor). Ignored inside a `<tw-form-field>` — the wrapper's `size` carries density. Defaults to `'md'`. */
37
38
  readonly size: _angular_core.InputSignal<TwSize>;
38
39
  /** Grows the textarea with its content (composed from CDK's `CdkTextareaAutosize`). When `true` the user-resize handle is forced off — autosize owns the height. Defaults to `false`. */
39
40
  readonly autosize: _angular_core.InputSignalWithTransform<boolean, unknown>;
@@ -49,7 +50,7 @@ declare class TextareaDirective extends InputDirective {
49
50
  readonly maxLength: _angular_core.InputSignalWithTransform<number | undefined, unknown>;
50
51
  /** Current value length, updates on every `input` event. Wire `<span twHint align="end">{{ ta.valueLength() }} / {{ ta.maxLength() }}</span>` for a character counter. */
51
52
  readonly valueLength: Signal<number>;
52
- /** @internal Textarea-specific Tailwind classes (resize axis). Combined with the inherited `classes()` in the host `[class]` binding. */
53
+ /** @internal Textarea-specific Tailwind classes (resize axis + control-height floor). Combined with the inherited `classes()` in the host `[class]` binding — the two strings never emit conflicting utilities, so concatenating them needs no cross-config merge. */
53
54
  readonly textareaClasses: Signal<string>;
54
55
  constructor();
55
56
  /** Triggers a CDK autosize recalculation. Useful after programmatic value changes that bypass the native `(input)` event (e.g., clipboard write APIs). No-op when `autosize` is `false`. */