@cdevhub/ngx-tw 0.5.0 → 0.6.1

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-testing.mjs +122 -0
  47. package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs.map +1 -0
  48. package/fesm2022/cdevhub-ngx-tw-dialog.mjs +11 -2
  49. package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -1
  50. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +1 -1
  51. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -1
  52. package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs +149 -0
  53. package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs.map +1 -0
  54. package/fesm2022/cdevhub-ngx-tw-file-upload.mjs +57 -67
  55. package/fesm2022/cdevhub-ngx-tw-file-upload.mjs.map +1 -1
  56. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +42 -24
  57. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -1
  58. package/fesm2022/cdevhub-ngx-tw-form-field.mjs +114 -21
  59. package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -1
  60. package/fesm2022/cdevhub-ngx-tw-icon.mjs +16 -6
  61. package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -1
  62. package/fesm2022/cdevhub-ngx-tw-input.mjs +52 -61
  63. package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -1
  64. package/fesm2022/cdevhub-ngx-tw-item.mjs +28 -4
  65. package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -1
  66. package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs +168 -0
  67. package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs.map +1 -0
  68. package/fesm2022/cdevhub-ngx-tw-menu.mjs +58 -21
  69. package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -1
  70. package/fesm2022/cdevhub-ngx-tw-number-input.mjs +34 -1
  71. package/fesm2022/cdevhub-ngx-tw-number-input.mjs.map +1 -1
  72. package/fesm2022/cdevhub-ngx-tw-paginator.mjs +95 -45
  73. package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -1
  74. package/fesm2022/cdevhub-ngx-tw-popover.mjs +81 -32
  75. package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -1
  76. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +1 -1
  77. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -1
  78. package/fesm2022/cdevhub-ngx-tw-radio.mjs +131 -98
  79. package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -1
  80. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +207 -42
  81. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -1
  82. package/fesm2022/cdevhub-ngx-tw-select-testing.mjs +165 -0
  83. package/fesm2022/cdevhub-ngx-tw-select-testing.mjs.map +1 -0
  84. package/fesm2022/cdevhub-ngx-tw-select.mjs +386 -210
  85. package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -1
  86. package/fesm2022/{cdevhub-ngx-tw-sheet-sheet-renderer-ByyNluUd.mjs → cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs} +3 -3
  87. package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs.map +1 -0
  88. package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs +129 -0
  89. package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs.map +1 -0
  90. package/fesm2022/cdevhub-ngx-tw-sheet.mjs +23 -7
  91. package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -1
  92. package/fesm2022/cdevhub-ngx-tw-slider.mjs +89 -54
  93. package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -1
  94. package/fesm2022/cdevhub-ngx-tw-sort.mjs +122 -17
  95. package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -1
  96. package/fesm2022/cdevhub-ngx-tw-split.mjs +72 -19
  97. package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -1
  98. package/fesm2022/cdevhub-ngx-tw-stat.mjs +63 -25
  99. package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -1
  100. package/fesm2022/cdevhub-ngx-tw-stepper.mjs +35 -8
  101. package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -1
  102. package/fesm2022/cdevhub-ngx-tw-switch.mjs +54 -48
  103. package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -1
  104. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +12 -15
  105. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -1
  106. package/fesm2022/cdevhub-ngx-tw-table.mjs +74 -13
  107. package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -1
  108. package/fesm2022/cdevhub-ngx-tw-tabs.mjs +84 -30
  109. package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -1
  110. package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs +172 -0
  111. package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs.map +1 -0
  112. package/fesm2022/cdevhub-ngx-tw-tags-input.mjs +107 -71
  113. package/fesm2022/cdevhub-ngx-tw-tags-input.mjs.map +1 -1
  114. package/fesm2022/cdevhub-ngx-tw-textarea.mjs +41 -9
  115. package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -1
  116. package/fesm2022/cdevhub-ngx-tw-theme.mjs +257 -45
  117. package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -1
  118. package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs +201 -0
  119. package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs.map +1 -0
  120. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +184 -77
  121. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -1
  122. package/fesm2022/cdevhub-ngx-tw-timeline.mjs +110 -27
  123. package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -1
  124. package/fesm2022/{cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs → cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs} +107 -19
  125. package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs.map +1 -0
  126. package/fesm2022/cdevhub-ngx-tw-toast.mjs +21 -13
  127. package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -1
  128. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +102 -15
  129. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -1
  130. package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs +219 -0
  131. package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs.map +1 -0
  132. package/fesm2022/cdevhub-ngx-tw-transfer.mjs +88 -69
  133. package/fesm2022/cdevhub-ngx-tw-transfer.mjs.map +1 -1
  134. package/fesm2022/cdevhub-ngx-tw-tree.mjs +68 -19
  135. package/fesm2022/cdevhub-ngx-tw-tree.mjs.map +1 -1
  136. package/index.json +1 -1
  137. package/package.json +63 -2
  138. package/theme/_base.css +13 -0
  139. package/theme/_dark.css +111 -36
  140. package/theme/_high-contrast-dark.css +367 -0
  141. package/theme/_high-contrast.css +13 -2
  142. package/theme/_light.css +332 -0
  143. package/theme/_semantic.css +60 -26
  144. package/theme/_typography.css +17 -0
  145. package/theme/index.css +86 -7
  146. package/types/cdevhub-ngx-tw-accordion.d.ts +12 -4
  147. package/types/cdevhub-ngx-tw-avatar.d.ts +10 -3
  148. package/types/cdevhub-ngx-tw-button.d.ts +1 -0
  149. package/types/cdevhub-ngx-tw-calendar-luxon.d.ts +2 -2
  150. package/types/cdevhub-ngx-tw-calendar-testing.d.ts +1 -1
  151. package/types/cdevhub-ngx-tw-calendar.d.ts +179 -73
  152. package/types/cdevhub-ngx-tw-card.d.ts +11 -3
  153. package/types/cdevhub-ngx-tw-carousel.d.ts +89 -20
  154. package/types/cdevhub-ngx-tw-checkbox.d.ts +40 -12
  155. package/types/cdevhub-ngx-tw-code-block.d.ts +11 -2
  156. package/types/cdevhub-ngx-tw-collapsible.d.ts +32 -5
  157. package/types/cdevhub-ngx-tw-combobox-testing.d.ts +157 -0
  158. package/types/cdevhub-ngx-tw-combobox.d.ts +94 -53
  159. package/types/cdevhub-ngx-tw-command-palette-testing.d.ts +136 -0
  160. package/types/cdevhub-ngx-tw-command-palette.d.ts +33 -5
  161. package/types/cdevhub-ngx-tw-core.d.ts +152 -21
  162. package/types/cdevhub-ngx-tw-date-picker-testing.d.ts +141 -0
  163. package/types/cdevhub-ngx-tw-date-picker.d.ts +37 -29
  164. package/types/cdevhub-ngx-tw-date-range-picker-testing.d.ts +148 -0
  165. package/types/cdevhub-ngx-tw-date-range-picker.d.ts +36 -29
  166. package/types/cdevhub-ngx-tw-dialog-testing.d.ts +98 -0
  167. package/types/cdevhub-ngx-tw-dialog.d.ts +12 -3
  168. package/types/cdevhub-ngx-tw-file-upload-testing.d.ts +120 -0
  169. package/types/cdevhub-ngx-tw-file-upload.d.ts +8 -10
  170. package/types/cdevhub-ngx-tw-flip-card.d.ts +18 -11
  171. package/types/cdevhub-ngx-tw-form-field.d.ts +19 -2
  172. package/types/cdevhub-ngx-tw-icon.d.ts +3 -3
  173. package/types/cdevhub-ngx-tw-input.d.ts +5 -8
  174. package/types/cdevhub-ngx-tw-item.d.ts +2 -0
  175. package/types/cdevhub-ngx-tw-menu-testing.d.ts +131 -0
  176. package/types/cdevhub-ngx-tw-menu.d.ts +2 -2
  177. package/types/cdevhub-ngx-tw-number-input.d.ts +20 -0
  178. package/types/cdevhub-ngx-tw-paginator.d.ts +58 -24
  179. package/types/cdevhub-ngx-tw-popover.d.ts +41 -10
  180. package/types/cdevhub-ngx-tw-progress-bar.d.ts +1 -1
  181. package/types/cdevhub-ngx-tw-radio.d.ts +68 -25
  182. package/types/cdevhub-ngx-tw-segmented-control.d.ts +79 -16
  183. package/types/cdevhub-ngx-tw-select-testing.d.ts +114 -0
  184. package/types/cdevhub-ngx-tw-select.d.ts +104 -33
  185. package/types/cdevhub-ngx-tw-sheet-testing.d.ts +104 -0
  186. package/types/cdevhub-ngx-tw-sheet.d.ts +19 -3
  187. package/types/cdevhub-ngx-tw-slider.d.ts +79 -25
  188. package/types/cdevhub-ngx-tw-sort.d.ts +45 -4
  189. package/types/cdevhub-ngx-tw-split.d.ts +32 -2
  190. package/types/cdevhub-ngx-tw-stat.d.ts +14 -4
  191. package/types/cdevhub-ngx-tw-stepper.d.ts +16 -2
  192. package/types/cdevhub-ngx-tw-switch.d.ts +35 -13
  193. package/types/cdevhub-ngx-tw-tab-nav.d.ts +7 -6
  194. package/types/cdevhub-ngx-tw-table.d.ts +53 -10
  195. package/types/cdevhub-ngx-tw-tabs.d.ts +41 -10
  196. package/types/cdevhub-ngx-tw-tags-input-testing.d.ts +135 -0
  197. package/types/cdevhub-ngx-tw-tags-input.d.ts +26 -11
  198. package/types/cdevhub-ngx-tw-textarea.d.ts +3 -2
  199. package/types/cdevhub-ngx-tw-theme.d.ts +245 -39
  200. package/types/cdevhub-ngx-tw-time-picker-testing.d.ts +129 -0
  201. package/types/cdevhub-ngx-tw-time-picker.d.ts +76 -19
  202. package/types/cdevhub-ngx-tw-timeline.d.ts +36 -12
  203. package/types/cdevhub-ngx-tw-toast.d.ts +20 -6
  204. package/types/cdevhub-ngx-tw-tooltip.d.ts +28 -6
  205. package/types/cdevhub-ngx-tw-transfer-testing.d.ts +152 -0
  206. package/types/cdevhub-ngx-tw-transfer.d.ts +21 -8
  207. package/types/cdevhub-ngx-tw-tree.d.ts +6 -1
  208. package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-ByyNluUd.mjs.map +0 -1
  209. package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs.map +0 -1
@@ -49,13 +49,13 @@ declare class SortDirective {
49
49
  readonly active: _angular_core.ModelSignal<string | null>;
50
50
  /** Current sort direction. `null` represents the cleared state. Two-way bindable via `[(twSortDirection)]`. Defaults to `null`. */
51
51
  readonly direction: _angular_core.ModelSignal<SortDirection>;
52
- /** Starting direction used when a header becomes active for the first time. Per-header `start` overrides this. Defaults to `'asc'`. */
52
+ /** Starting direction used when a header becomes active for the first time. Per-header `start` overrides this. Defaults to `'asc'`. Alias: `twSortStart`. */
53
53
  readonly start: _angular_core.InputSignal<"asc" | "desc">;
54
- /** When true, the direction cycle skips the cleared (`null`) state — headers toggle between `'asc'` and `'desc'` only. Per-header `disableClear` overrides this. Defaults to `false`. */
54
+ /** When true, the direction cycle skips the cleared (`null`) state — headers toggle between `'asc'` and `'desc'` only. Per-header `disableClear` overrides this. Defaults to `false`. Alias: `twSortDisableClear`. */
55
55
  readonly disableClear: _angular_core.InputSignal<boolean>;
56
- /** When true, all child sort headers are disabled. Defaults to `false`. */
56
+ /** When true, all child sort headers are disabled. Defaults to `false`. Alias: `twSortDisabled`. */
57
57
  readonly disabled: _angular_core.InputSignal<boolean>;
58
- /** Fires whenever the user changes `active` or `direction` by interacting with a header. Programmatic writes to `[(twSortActive)]` / `[(twSortDirection)]` do NOT emit. */
58
+ /** Fires whenever the user changes `active` or `direction` by interacting with a header. Programmatic writes to `[(twSortActive)]` / `[(twSortDirection)]` do NOT emit. Alias: `twSortChange`. */
59
59
  readonly sortChange: _angular_core.OutputEmitterRef<TwSortEvent>;
60
60
  private readonly sortableIds;
61
61
  /** Registers a header id so duplicates can be detected. Called by `SortHeaderComponent` on init. Throws in dev mode if another header with the same id is already registered. */
@@ -76,6 +76,24 @@ type TwSortArrowPosition = 'before' | 'after';
76
76
  * Turns any element (e.g., `<th>`, `<div>`, `<button>`) into a sortable header under a parent
77
77
  * `SortDirective`. Renders the projected label plus an arrow that reflects the current direction.
78
78
  * Triggers a sort cycle on click or Enter/Space.
79
+ *
80
+ * @remarks
81
+ * **Where the control and `aria-sort` live depends on the host element.** Both are decided once,
82
+ * at construction, from the host's tag name and its *static* `role` attribute:
83
+ *
84
+ * | Host | `aria-sort` | Interactive element |
85
+ * |---|---|---|
86
+ * | `<th>` / `[role="columnheader"\|"rowheader"]` | on the host | inner container (`role="button"`) |
87
+ * | `<span>` / `<div>` (no role) | **not emitted** | inner container (`role="button"`) |
88
+ * | `<button>` / `<a href>` / `[role="button"\|"link"]` | **not emitted** | the host itself |
89
+ *
90
+ * `aria-sort` is only valid on a `columnheader` / `rowheader`, so emitting it on a `<span>` or
91
+ * `<button>` is an axe `aria-allowed-attr` failure and is silently ignored by assistive tech. When
92
+ * the header is composed *inside* a header cell — `<th><span tw-sort-header>…</span></th>`, the
93
+ * shape `tw-table` generates — the `<th>` owns `aria-sort` (see `tw-column`'s `sortState` input,
94
+ * which auto-resolves against the same `[twSort]` directive). Outside a table there is no
95
+ * `columnheader` to carry the state; the header remains a labelled button and the sort direction
96
+ * is conveyed by the arrow plus the consumer's own live region.
79
97
  */
80
98
  declare class SortHeaderComponent implements OnInit, AfterViewInit, OnDestroy {
81
99
  /** Unique id for this header. Required — identifies the field/column this header sorts. */
@@ -97,6 +115,15 @@ declare class SortHeaderComponent implements OnInit, AfterViewInit, OnDestroy {
97
115
  private readonly parent;
98
116
  private readonly focusMonitor;
99
117
  private readonly ariaDescriber;
118
+ private readonly hostEl;
119
+ /**
120
+ * Whether the host element can legally carry `aria-sort`. Resolved once, at construction — the
121
+ * host's tag name and static attributes are already applied by then, and a later `[attr.role]`
122
+ * binding would make this timing-dependent.
123
+ */
124
+ private readonly hostIsHeaderCell;
125
+ /** Whether the host is already a control, in which case the inner container must stay inert. */
126
+ private readonly hostIsControl;
100
127
  private readonly containerRef;
101
128
  private _describedBy;
102
129
  constructor();
@@ -108,8 +135,22 @@ declare class SortHeaderComponent implements OnInit, AfterViewInit, OnDestroy {
108
135
  readonly effectiveDirection: _angular_core.Signal<SortDirection>;
109
136
  /** `aria-sort` value: `'ascending' | 'descending' | 'none'`. */
110
137
  readonly ariaSort: _angular_core.Signal<"none" | "ascending" | "descending">;
138
+ /**
139
+ * @internal Value actually written to the host's `aria-sort` attribute. `null` — i.e. no
140
+ * attribute — unless the host is a `columnheader` / `rowheader`; see the class remarks.
141
+ */
142
+ readonly hostAriaSort: _angular_core.Signal<"none" | "ascending" | "descending" | null>;
143
+ /** @internal `role` for the inner container: `'button'` unless the host is already the control. */
144
+ readonly controlRole: _angular_core.Signal<"button" | null>;
145
+ /** @internal `tabindex` for the inner container. Mirrors `controlRole()`. */
146
+ readonly controlTabIndex: _angular_core.Signal<0 | null>;
111
147
  /** Whether the arrow element should render. Active headers always render; inactive render when not disabled so hover reveals the affordance. */
112
148
  readonly renderArrow: _angular_core.Signal<boolean>;
149
+ /**
150
+ * The element that carries focus and the accessible description — the host when the consumer
151
+ * mounted the header on a control, the inner container otherwise.
152
+ */
153
+ private controlElement;
113
154
  private readonly variantResult;
114
155
  /** @internal */
115
156
  readonly hostClasses: _angular_core.Signal<string>;
@@ -118,7 +118,7 @@ declare class SplitComponent {
118
118
  readonly direction: _angular_core.InputSignal<SplitDirection>;
119
119
  /** How sizes are expressed and reported. A single unit governs the whole container. Defaults to `'percent'`. */
120
120
  readonly unit: _angular_core.InputSignal<SplitUnit>;
121
- /** Thickness of each gutter in pixels, perpendicular to the split axis. Defaults to `6`. */
121
+ /** Painted thickness of each gutter in pixels, perpendicular to the split axis, and the space it takes from the panes. The pointer target is padded out to a 24px minimum independently of this value (WCAG 2.2 SC 2.5.8), so a thin gutter stays thin without becoming hard to grab. Defaults to `6`. */
122
122
  readonly gutterSize: _angular_core.InputSignal<number>;
123
123
  /** When true, all resize interactions are disabled. Gutters are not focusable and do not respond to input. Defaults to `false`. */
124
124
  readonly disabled: _angular_core.InputSignal<boolean>;
@@ -168,7 +168,12 @@ declare class SplitComponent {
168
168
  * Pixel mode: values are absolute pixel sizes.
169
169
  */
170
170
  readonly _sizes: _angular_core.WritableSignal<number[]>;
171
- /** Tracks the live `dir` attribute resolved through CDK Directionality. */
171
+ /**
172
+ * Live `dir` resolved through CDK `Directionality`. Read straight from
173
+ * `valueSignal` (CDK 22+) so `_isRtl` re-evaluates on a runtime `dir` flip
174
+ * with no manual subscription mirror. Falls back to 'ltr' when the consumer's
175
+ * injector cannot supply the token (`{ optional: true }`).
176
+ */
172
177
  private readonly _cdkDir;
173
178
  /** Resolves the effective RTL state: explicit `rtl` input overrides CDK `dir`. */
174
179
  readonly _isRtl: _angular_core.Signal<boolean>;
@@ -179,6 +184,31 @@ declare class SplitComponent {
179
184
  private readonly _classes;
180
185
  readonly _rootClass: _angular_core.Signal<string>;
181
186
  readonly _gutterClass: _angular_core.Signal<string>;
187
+ /**
188
+ * @internal
189
+ * Transparent padding added to each side of the gutter so its pointer target
190
+ * reaches the WCAG 2.2 SC 2.5.8 24x24 floor while the painted line stays
191
+ * `gutterSize` thick (the default gutter is 6px — a quarter of the floor).
192
+ *
193
+ * The padding is cancelled by an equal negative margin on the same side, so
194
+ * the gutter's *layout* footprint is still exactly `gutterSize` and the
195
+ * `availableSpace()` math is untouched; only its border box — which is what
196
+ * receives the pointer and what a target-size audit measures — grows. The
197
+ * overhang reaches `_gutterHitPad` px into each neighbouring pane and takes
198
+ * pointer events there (including over a pane's own scrollbar, if it has
199
+ * one); that is the accepted cost of the technique and mirrors how VS Code
200
+ * and every other thin-sash implementation reaches the floor.
201
+ *
202
+ * Zero once `gutterSize` is 24 or more — a gutter that already clears the
203
+ * floor needs no padding and no overhang.
204
+ */
205
+ readonly _gutterHitPad: _angular_core.Signal<number>;
206
+ /** @internal Horizontal half of `_gutterHitPad` — non-zero only for a horizontal split, where the gutter is thin across the X axis. Physical (not logical) properties: the padding is symmetric, so RTL needs no separate handling. */
207
+ readonly _gutterHitPadX: _angular_core.Signal<number>;
208
+ /** @internal Vertical half of `_gutterHitPad` — non-zero only for a vertical split. */
209
+ readonly _gutterHitPadY: _angular_core.Signal<number>;
210
+ /** @internal Gutter border-box thickness: `gutterSize` plus the SC 2.5.8 hit padding on both sides, i.e. `max(gutterSize, 24)`. The negative margins give back the padding, so the *layout* footprint stays `gutterSize`. */
211
+ readonly _gutterBoxPx: _angular_core.Signal<number>;
182
212
  /** Indices `0..panes.length - 2` representing the gutter between pane[i] and pane[i+1]. */
183
213
  readonly _gutterIndices: _angular_core.Signal<number[]>;
184
214
  /** @internal — drag state for the active pointer. */
@@ -3,7 +3,14 @@ import { ElementRef } from '@angular/core';
3
3
  import { TwSize } from '@cdevhub/ngx-tw/core';
4
4
 
5
5
  /** Surface treatment for the stat tile. */
6
- type StatVariant = 'plain' | 'outlined' | 'elevated' | 'filled';
6
+ type StatVariant = 'ghost' | 'outline' | 'elevated' | 'solid' | StatVariantLegacy;
7
+ /**
8
+ * Legacy `variant` spellings, kept so existing templates keep compiling.
9
+ * @deprecated `'plain'` aliases `'ghost'`, `'outlined'` aliases `'outline'`
10
+ * and `'filled'` aliases `'solid'`. Each renders identically to its
11
+ * replacement and will be removed in the next major.
12
+ */
13
+ type StatVariantLegacy = 'plain' | 'outlined' | 'filled';
7
14
  /** Direction of trend conveyed by the delta indicator. */
8
15
  type StatDeltaDirection = 'up' | 'down' | 'neutral';
9
16
  /** Display style of the trend delta. */
@@ -51,12 +58,13 @@ declare class StatDeltaComponent {
51
58
  readonly variant: _angular_core.InputSignal<StatDeltaVariant>;
52
59
  /** Optional comparison label rendered next to the delta value (e.g. `"vs last week"`, `"since launch"`). Defaults to `undefined`. */
53
60
  readonly comparisonLabel: _angular_core.InputSignal<string | undefined>;
54
- /** Explicit accessible label. When omitted, the component composes one from `direction` + projected text + `comparisonLabel`. Override when projected content is purely symbolic or already localized. Defaults to `undefined`. */
61
+ /** Explicit accessible label, mirrored to `aria-label`. When omitted, the component composes one from `direction` + projected text + `comparisonLabel`. Override when projected content is purely symbolic or already localized. Defaults to `undefined`. */
55
62
  readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
56
63
  /** @internal */
57
64
  protected readonly textEl: _angular_core.Signal<ElementRef<HTMLElement> | undefined>;
58
65
  /** @internal */
59
66
  protected readonly projectedText: _angular_core.WritableSignal<string>;
67
+ private readonly destroyRef;
60
68
  constructor();
61
69
  /** @internal */
62
70
  protected readonly effectiveColor: _angular_core.Signal<"neutral" | "success" | "error">;
@@ -70,7 +78,7 @@ declare class StatDeltaComponent {
70
78
  protected readonly textClasses: _angular_core.Signal<string>;
71
79
  protected readonly comparisonClasses: _angular_core.Signal<string>;
72
80
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<StatDeltaComponent, never>;
73
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<StatDeltaComponent, "tw-stat-delta", never, { "direction": { "alias": "direction"; "required": false; "isSignal": true; }; "inverted": { "alias": "inverted"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "comparisonLabel": { "alias": "comparisonLabel"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
81
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StatDeltaComponent, "tw-stat-delta", never, { "direction": { "alias": "direction"; "required": false; "isSignal": true; }; "inverted": { "alias": "inverted"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "comparisonLabel": { "alias": "comparisonLabel"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
74
82
  }
75
83
  /**
76
84
  * KPI tile — a compact display tile surfacing a single key performance
@@ -91,7 +99,7 @@ declare class StatDeltaComponent {
91
99
  * consumers can compose their own skeleton charts.
92
100
  */
93
101
  declare class StatComponent {
94
- /** Surface treatment. `'plain'` removes border and background; `'outlined'` (default) adds a border on the surface token; `'elevated'` adds shadow and uses the raised surface; `'filled'` uses the muted surface with no border. */
102
+ /** Surface treatment. `'ghost'` removes border and background; `'outline'` (default) adds a border on the surface token; `'elevated'` adds shadow and uses the raised surface; `'solid'` uses the muted surface with no border. `'plain'`, `'outlined'` and `'filled'` are deprecated aliases for `'ghost'`, `'outline'` and `'solid'` and render identically. */
95
103
  readonly variant: _angular_core.InputSignal<StatVariant>;
96
104
  /** Density scale — drives padding, internal gaps, value/label typography, and the skeleton placeholder dimensions. Defaults to `'md'`. */
97
105
  readonly size: _angular_core.InputSignal<TwSize>;
@@ -120,6 +128,8 @@ declare class StatComponent {
120
128
  protected readonly loadingValueWidth: _angular_core.Signal<"4rem" | "5rem" | "6rem" | "8rem" | "10rem">;
121
129
  /** Skeleton height during loading state — matches the value font size. */
122
130
  protected readonly loadingValueHeight: _angular_core.Signal<"0.75rem" | "0.875rem" | "1rem">;
131
+ /** @internal Canonical variant with legacy spellings folded in. */
132
+ private readonly resolvedVariant;
123
133
  private readonly variantResult;
124
134
  protected readonly rootClasses: _angular_core.Signal<string>;
125
135
  protected readonly iconFlexClasses: _angular_core.Signal<string>;
@@ -50,9 +50,9 @@ declare class StepperComponent extends CdkStepper implements AfterViewInit {
50
50
  readonly color: _angular_core.InputSignal<TwColor>;
51
51
  /** Controls indicator size and label typography. Defaults to `'md'`. */
52
52
  readonly size: _angular_core.InputSignal<TwSize>;
53
- /** When true, steps with `hasError` render error styling, icon, and `aria-invalid`. Defaults to `true`. */
53
+ /** When true, steps with `hasError` render error styling, icon, and `aria-invalid`. Defaults to `true` — error states must be visible by default, since silently swallowing a stepped flow's failure state is a UX regression; the special case is opting out per step. */
54
54
  readonly showError: _angular_core.InputSignal<boolean>;
55
- /** When true, clicking a navigable step header selects it. Set to `false` to only allow advancement via `twStepperNext` / `twStepperPrevious`. Defaults to `true`. */
55
+ /** When true, clicking a navigable step header selects it. Set to `false` to only allow advancement via `twStepperNext` / `twStepperPrevious`. Defaults to `true` — free navigation is the standard stepper UX; the special case is a restricted flow such as a wizard that must complete in order. */
56
56
  readonly headerInteractive: _angular_core.InputSignal<boolean>;
57
57
  private readonly _liveAnnouncer;
58
58
  private readonly _destroyRef;
@@ -73,6 +73,19 @@ declare class StepperComponent extends CdkStepper implements AfterViewInit {
73
73
  readonly selectedIndexValue: _angular_core.Signal<number>;
74
74
  set orientation(value: StepperOrientation);
75
75
  get orientation(): StepperOrientation;
76
+ /** @internal Whether the header strip is exposed as a WAI-ARIA tablist. True for horizontal orientation only. */
77
+ readonly usesTabPattern: _angular_core.Signal<boolean>;
78
+ /** @internal Whether a step renders its panel inline beneath its own header (vertical orientation, selected step, step has content). */
79
+ hasInlinePanel(step: StepComponent, index: number): boolean;
80
+ /**
81
+ * @internal Id the step header's `aria-controls` points at, or `null`.
82
+ *
83
+ * Vertical headers only claim control of a panel that is actually in the
84
+ * DOM: an `aria-expanded="true"` button pointing at a missing id is an
85
+ * invalid reference, whereas the collapsed steps simply carry no
86
+ * `aria-controls` at all.
87
+ */
88
+ controlledPanelId(step: StepComponent, index: number): string | null;
76
89
  private readonly _variantResult;
77
90
  readonly rootClasses: _angular_core.Signal<string>;
78
91
  readonly headerClasses: _angular_core.Signal<string>;
@@ -134,6 +147,7 @@ declare class StepperComponent extends CdkStepper implements AfterViewInit {
134
147
  private syncFocusIndex;
135
148
  /** @internal Relays tablist keydown to CdkStepper, then republishes the tab stop. */
136
149
  onTablistKeydown(event: KeyboardEvent): void;
150
+ /** @internal Selects a step from a header click. Ignored when `headerInteractive` is false or the step is not navigable. */
137
151
  onHeaderClick(step: StepComponent, index: number): void;
138
152
  /** @internal Whether the stepper should render the error state for a step. */
139
153
  shouldRenderError(step: StepComponent): boolean;
@@ -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;