@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
@@ -59,6 +59,16 @@ declare class TimePickerIntl {
59
59
  * }),
60
60
  * ]
61
61
  * ```
62
+ *
63
+ * Keys explicitly set to `undefined` are dropped before merging. Root
64
+ * `tsconfig.json` does not set `exactOptionalPropertyTypes`, so
65
+ * `provideTimePickerIntl({ hoursLabel: bundle['time.hours'] })` type-checks
66
+ * even when the lookup misses — and a plain `Object.assign` would then copy
67
+ * that `undefined` over a field `TimePickerIntl` types as `string`. Because
68
+ * this is a bootstrap-level provider, one missing key broke *every*
69
+ * time-picker in the app: `focusedFieldLabel()` calls `.toLowerCase()` on the
70
+ * field labels to build the stepper aria-labels, so the picker threw on first
71
+ * render. Filtering here makes a missing key fall back to the English default.
62
72
  */
63
73
  declare function provideTimePickerIntl(custom: Partial<TimePickerIntl>): Provider;
64
74
 
@@ -115,13 +125,13 @@ type TimePickerValidationErrors = Partial<{
115
125
  };
116
126
  }>;
117
127
  declare class TimePickerComponent<D = Date> extends FormFieldControl<D> implements ControlValueAccessor, Validator, OnInit {
118
- /** Id on the time-picker's host element. Auto-generated when not provided. Used by the form-field's `<label for>` attribute. */
128
+ /** Id on the time-picker's host element. Auto-generated when not provided. The accessible name inside a `<tw-form-field>` comes from `aria-labelledby` on the inner `role="group"` wrapper, not from the field's `<label for>` — the host is a custom element, which `for` cannot target. */
119
129
  readonly idInput: _angular_core.InputSignal<string | undefined>;
120
130
  /** When true, the whole component is disabled and every field sets `aria-disabled="true"`. Defaults to `false`. */
121
131
  readonly disabledInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
122
132
  /** When true, exposes `aria-required="true"`. Validators.required on a bound NgControl is also honoured. Defaults to `false`. */
123
133
  readonly requiredInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
124
- /** When true, blocks typing, stepping, and the AM/PM toggle — the value is still read-only visible. Defaults to `false`. */
134
+ /** When true, blocks typing, stepping, and the AM/PM toggle — the value is still read-only visible. Defaults to `false`. Alias: `readonly`. */
125
135
  readonly readonlyInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
126
136
  /** Controls field height, font size, and stepper density. Defaults to `'md'`. */
127
137
  readonly size: _angular_core.InputSignal<TwSize>;
@@ -129,7 +139,7 @@ declare class TimePickerComponent<D = Date> extends FormFieldControl<D> implemen
129
139
  readonly color: _angular_core.InputSignal<TwColor>;
130
140
  /** Visual style of the chrome. `'default'` draws its own border; `'naked'` strips chrome. Auto-resolves to `'naked'` inside `<tw-form-field>`. */
131
141
  readonly variant: _angular_core.InputSignal<TimePickerVariant | undefined>;
132
- /** `'12h'` renders 1–12 hours with an AM/PM toggle; `'24h'` renders 00–23. Defaults to `'24h'`. */
142
+ /** `'12h'` renders 1–12 hours with an AM/PM toggle; `'24h'` renders 00–23. The same axis is spelled `timeFormat` on `tw-date-range-picker` and lives under `timeConfig.format` on `tw-date-picker`, where `format` instead means the display-format descriptor. Defaults to `'24h'`. */
133
143
  readonly format: _angular_core.InputSignal<TimePickerFormat>;
134
144
  /** When true, renders a seconds field after minutes. Defaults to `false`. */
135
145
  readonly showSeconds: _angular_core.InputSignal<boolean>;
@@ -147,21 +157,21 @@ declare class TimePickerComponent<D = Date> extends FormFieldControl<D> implemen
147
157
  readonly referenceDate: _angular_core.InputSignal<D | null>;
148
158
  /** Placeholder shown in each field when empty. Defaults to `'--'`. */
149
159
  readonly placeholder: _angular_core.InputSignal<string | undefined>;
150
- /** Whether to render the up/down stepper column. Defaults to `true`. */
160
+ /** Whether to render the up/down stepper column. Defaults to `true`. Pointer users expect inline up/down chevrons next to a numeric editor; without them the picker reads as a static display and consumers must rebuild stepping for every instance. Ignored at `size="xs"` on the bordered `default` variant, where the 24px control leaves no room for a stacked pair — use ↑/↓ on a field instead. */
151
161
  readonly showSteppers: _angular_core.InputSignal<boolean>;
152
- /** Whether to render the clear affordance when a value is set. Defaults to `true`. */
162
+ /** Whether to render the clear affordance when a value is set. Defaults to `true` — it matches `<tw-date-picker>` and `<tw-input>` clear behaviour; without the inline clear every form has to wire its own reset surface for an obvious affordance. */
153
163
  readonly showClear: _angular_core.InputSignal<boolean>;
154
- /** Accessible label for the clear button. Defaults to `'Clear time'`. */
164
+ /** Accessible label for the clear button. Note the name differs in meaning from the date pickers, which spell this `clearAriaLabel` and reserve `clearLabel` for the overlay action bar's visible button text. Defaults to `'Clear time'`. */
155
165
  readonly clearLabel: _angular_core.InputSignal<string>;
156
- /** Per-instance override of the `ErrorStateMatcher`. */
166
+ /** Per-instance override of the `ErrorStateMatcher`. Defaults to `undefined`. */
157
167
  readonly errorStateMatcher: _angular_core.InputSignal<ErrorStateMatcher | undefined>;
158
- /** Accessible name for the fields group. Required when no visible label is supplied. Alias: `aria-label`. */
168
+ /** Accessible name for the fields group. Required when no visible label is supplied. Alias: `aria-label`. Defaults to `undefined`. */
159
169
  readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
160
- /** ID of an external element that labels the group. Alias: `aria-labelledby`. */
170
+ /** ID of an external element that labels the group. Alias: `aria-labelledby`. Defaults to `undefined`. */
161
171
  readonly ariaLabelledby: _angular_core.InputSignal<string | undefined>;
162
- /** Consumer-supplied `aria-describedby` ids. The form-field preserves these when merging hint/error ids. Alias: `aria-describedby`. */
172
+ /** Consumer-supplied `aria-describedby` ids. The form-field preserves these when merging hint/error ids. Alias: `aria-describedby`. Defaults to `undefined`. */
163
173
  readonly userAriaDescribedByInput: _angular_core.InputSignal<string | undefined>;
164
- /** Two-way bound current time. `null` when empty. Setting programmatically updates the fields without firing `onChange`. */
174
+ /** Two-way bound current time. `null` when empty. Setting programmatically updates the fields without firing `onChange`. Defaults to `null`. */
165
175
  readonly value: _angular_core.ModelSignal<D | null>;
166
176
  /** Fires on every keystroke, stepper press, or AM/PM toggle — before the new value is committed. */
167
177
  readonly timeInput: _angular_core.OutputEmitterRef<TimePickerInputEvent<D>>;
@@ -175,9 +185,6 @@ declare class TimePickerComponent<D = Date> extends FormFieldControl<D> implemen
175
185
  private readonly injector;
176
186
  private readonly formField;
177
187
  private ngControl;
178
- private readonly parentForm;
179
- private readonly parentFormGroup;
180
- private readonly defaultMatcher;
181
188
  /** @internal — exposed for the template; consumers configure via `provideTimePickerIntl()`. */
182
189
  protected readonly intl: TimePickerIntl;
183
190
  private readonly hourInputRef;
@@ -200,9 +207,10 @@ declare class TimePickerComponent<D = Date> extends FormFieldControl<D> implemen
200
207
  readonly internalValue: _angular_core.WritableSignal<D | null>;
201
208
  private readonly cvaDisabled;
202
209
  private readonly describedByIdsSignal;
210
+ private readonly labelledByIdsSignal;
203
211
  private readonly focusedSignal;
204
- private readonly _ngControlRev;
205
- private readonly _formSubmitRev;
212
+ /** @internal Shared `errorState` / `required` / `errors` derivation — see `wireErrorState`. */
213
+ private readonly errorWiring;
206
214
  /** When true, an effect should not rewrite field text from the external value. */
207
215
  private editing;
208
216
  private onChange;
@@ -213,6 +221,23 @@ declare class TimePickerComponent<D = Date> extends FormFieldControl<D> implemen
213
221
  readonly isEmpty: Signal<boolean>;
214
222
  /** @internal Effective variant — auto-naked when wrapped in tw-form-field. */
215
223
  readonly resolvedVariant: Signal<TimePickerVariant>;
224
+ /**
225
+ * @internal Whether the stepper column actually renders.
226
+ *
227
+ * `showSteppers` stays the consumer's switch, but the column is geometrically
228
+ * impossible at `size="xs"` on the bordered `default` variant: the pinned h-6
229
+ * root is 24px border-box, leaving a 22px content box, while a stacked pair of
230
+ * chevron buttons has a 24px min-content height (2 × size-3). Rendering it
231
+ * anyway would either overflow the shell or squeeze each button to 11px — far
232
+ * under any usable pointer target. The `naked` variant keeps its steppers: it
233
+ * draws no border, so in the date-picker / date-range-picker overlay footers a
234
+ * 24px row leaves a full 24px content box and the pair fits exactly. (Inside
235
+ * `<tw-form-field>` the row is governed by the field's own padding and its
236
+ * `min-h-*` floor, which is a minimum — the row grows rather than clipping.)
237
+ * Stepping stays available everywhere via ↑/↓ on a focused field, so nothing
238
+ * becomes unreachable.
239
+ */
240
+ readonly steppersVisible: Signal<boolean>;
216
241
  /** @internal */
217
242
  readonly hourMin: Signal<number>;
218
243
  /** @internal */
@@ -231,8 +256,23 @@ declare class TimePickerComponent<D = Date> extends FormFieldControl<D> implemen
231
256
  readonly secondValueNow: Signal<number | null>;
232
257
  /** @internal */
233
258
  readonly secondValueText: Signal<string>;
234
- /** @internal */
235
- readonly groupAriaLabel: Signal<string>;
259
+ /**
260
+ * @internal Merged `aria-labelledby` for the `role="group"` wrapper: the ids a
261
+ * wrapping `<tw-form-field>` pushes down (its projected `<label twLabel>` plus
262
+ * anything the consumer supplied) or, standalone, the consumer's own
263
+ * `aria-labelledby`. The host is `<tw-time-picker>`, a custom element the
264
+ * field's `<label for>` cannot target, so this attribute is the only route
265
+ * from the visible label to the composite. Returns `null` when nothing labels
266
+ * the group by reference.
267
+ */
268
+ readonly groupLabelledBy: Signal<string | null>;
269
+ /**
270
+ * @internal `aria-label` for the group. An explicit `aria-label` always wins;
271
+ * otherwise the generic intl fallback is suppressed whenever `groupLabelledBy`
272
+ * already names the group, so a real label is not shadowed by "Time" in the
273
+ * accessibility tree inspector.
274
+ */
275
+ readonly groupAriaLabel: Signal<string | null>;
236
276
  /** @internal Label of the currently focused field, used by stepper aria-labels. */
237
277
  readonly focusedFieldLabel: Signal<string>;
238
278
  /** @internal */
@@ -254,12 +294,27 @@ declare class TimePickerComponent<D = Date> extends FormFieldControl<D> implemen
254
294
  /** @internal */ readonly focused: Signal<boolean>;
255
295
  /** @internal */ readonly empty: Signal<boolean>;
256
296
  /** @internal */ readonly disabled: Signal<boolean>;
257
- /** @internal */ readonly required: Signal<boolean>;
297
+ /**
298
+ * Whether the control is required — the `required` input OR `Validators.required`
299
+ * on a bound `NgControl`. Bound to `aria-required` on each spinbutton field, not on
300
+ * the `role="group"` wrapper, which does not permit the attribute.
301
+ */
302
+ readonly required: Signal<boolean>;
258
303
  /** @internal */
259
304
  readonly errorState: Signal<boolean>;
305
+ /**
306
+ * @internal Active validation errors map from the bound `NgControl` (or `null` when the
307
+ * control reports none / is unbound). This is what `[twError match="…"]` filters on inside a
308
+ * `<tw-form-field>`; without it every `match`-targeted message — including the
309
+ * `timePickerMin` / `timePickerMax` codes this component's `NG_VALIDATORS` apparatus exists
310
+ * to produce — stays permanently hidden.
311
+ */
312
+ readonly errors: Signal<Record<string, unknown> | null>;
260
313
  /** @internal */ readonly controlType = "time-picker";
261
314
  /** @internal */
262
315
  readonly userAriaDescribedBy: Signal<string | undefined>;
316
+ /** @internal Consumer-supplied `aria-labelledby`, surfaced so the wrapping form-field merges it into the ids it pushes back rather than replacing it. */
317
+ readonly userAriaLabelledby: Signal<string | undefined>;
263
318
  constructor();
264
319
  ngOnInit(): void;
265
320
  /** Moves focus to the hours field. */
@@ -318,6 +373,8 @@ declare class TimePickerComponent<D = Date> extends FormFieldControl<D> implemen
318
373
  setDisabledState(isDisabled: boolean): void;
319
374
  /** @internal */
320
375
  setDescribedByIds(ids: string[]): void;
376
+ /** @internal Receives the merged `aria-labelledby` ids from the wrapping form-field and applies them to the `role="group"` wrapper. Required because the host is a custom element rather than a labelable control, so the field's `<label for>` never reaches it. */
377
+ setLabelledByIds(ids: string[]): void;
321
378
  /** @internal */
322
379
  onContainerClick(event: MouseEvent): void;
323
380
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TimePickerComponent<any>, never>;
@@ -12,19 +12,38 @@ type TimelineAlign = 'left' | 'right' | 'alternate' | 'split';
12
12
  type TimelineLineStyle = 'solid' | 'dashed';
13
13
  /** Visibility policy for the horizontal-overflow chevron buttons. */
14
14
  type TimelineScrollControls = 'auto' | 'always' | 'never';
15
- /** Localisable labels for the horizontal-overflow chevron buttons on `tw-timeline`. */
15
+ /**
16
+ * Localisable labels for the horizontal-overflow chevron buttons on
17
+ * `tw-timeline`.
18
+ *
19
+ * Every member is optional. This interface only ever reaches consumers through
20
+ * `provideTwTimelineScrollLabels(labels: Partial<TwTimelineScrollLabels>)`, and
21
+ * unset keys fall back to {@link DEFAULT_TW_TIMELINE_SCROLL_LABELS} — so a
22
+ * consumer who annotates a complete literal must not be forced to restate keys
23
+ * they do not override, and adding a label in a future minor must not break
24
+ * them on a non-major release. `scrollRegion` was already optional for exactly
25
+ * this reason when it was added after the interface shipped; making the other
26
+ * two optional is the structural version of the same fix, so the next added
27
+ * label does not reproduce the break.
28
+ */
16
29
  interface TwTimelineScrollLabels {
17
30
  /** Accessible label for the previous-scroll chevron. Used as `aria-label`. Defaults to `'Scroll to previous events'`. */
18
- scrollPrevious: string;
31
+ scrollPrevious?: string;
19
32
  /** Accessible label for the next-scroll chevron. Used as `aria-label`. Defaults to `'Scroll to next events'`. */
20
- scrollNext: string;
33
+ scrollNext?: string;
34
+ /** Accessible label for the horizontal scroll viewport, which is a keyboard-focusable scrollable region. Defaults to `'Timeline events'`. */
35
+ scrollRegion?: string;
21
36
  }
22
- /** Default English labels used when `TW_TIMELINE_SCROLL_LABELS` is not provided. */
23
- declare const DEFAULT_TW_TIMELINE_SCROLL_LABELS: TwTimelineScrollLabels;
37
+ /**
38
+ * Default English labels used when `TW_TIMELINE_SCROLL_LABELS` is not provided.
39
+ * Typed `Required<TwTimelineScrollLabels>` so readers keep a non-optional
40
+ * `string` for every key even though the interface itself is all-optional.
41
+ */
42
+ declare const DEFAULT_TW_TIMELINE_SCROLL_LABELS: Required<TwTimelineScrollLabels>;
24
43
  /**
25
44
  * Injection token carrying localisable `aria-label` strings for the timeline's
26
- * horizontal-overflow chevron buttons. The container uses these labels exclusively
27
- * on the prev/next buttons; they do not affect any other rendered text.
45
+ * horizontal-overflow affordances the prev/next chevron buttons and the
46
+ * scrollable viewport between them. They do not affect any other rendered text.
28
47
  *
29
48
  * Provide via `provideTwTimelineScrollLabels({ ... })` at the root or feature level.
30
49
  * If both keys are present they override the English defaults; if only one is present
@@ -129,19 +148,24 @@ declare class TimelineComponent {
129
148
  private readonly _directionality;
130
149
  private readonly _viewportRef;
131
150
  private readonly _scrollLabelsOverride;
132
- /** @internal Live `dir` from CDK `Directionality`. */
151
+ /**
152
+ * @internal Live `dir` from CDK `Directionality`. Read straight from
153
+ * `valueSignal` (CDK 22+) so `_isRtl` re-evaluates on a runtime `dir` flip
154
+ * with no manual subscription mirror.
155
+ */
133
156
  private readonly _cdkDir;
134
157
  /** @internal True when the host renders inside a `dir="rtl"` ancestor. */
135
158
  readonly _isRtl: _angular_core.Signal<boolean>;
136
159
  /**
137
- * @internal Defaults to `false` until the first measurement runs in
138
- * `afterNextRender`. This avoids a one-frame "enabled-then-disabled" flash
139
- * where the buttons appear live before the scroll state has been read.
160
+ * @internal Defaults to `false` until the first measurement runs in the
161
+ * `afterRenderEffect` in the constructor. This avoids a one-frame
162
+ * "enabled-then-disabled" flash where the buttons appear live before the
163
+ * scroll state has been read.
140
164
  */
141
165
  readonly _canScrollPrev: _angular_core.WritableSignal<boolean>;
142
166
  readonly _canScrollNext: _angular_core.WritableSignal<boolean>;
143
167
  /** @internal Resolved label record. Falls back to English defaults for any missing key. */
144
- readonly scrollLabels: _angular_core.Signal<TwTimelineScrollLabels>;
168
+ readonly scrollLabels: _angular_core.Signal<Required<TwTimelineScrollLabels>>;
145
169
  /** @internal True when the prev button should be aria-hidden + visually suppressed. */
146
170
  readonly _prevButtonHidden: _angular_core.Signal<boolean>;
147
171
  /** @internal True when the next button should be aria-hidden + visually suppressed. */
@@ -88,6 +88,17 @@ declare class ToastRef<C = unknown, R = unknown> {
88
88
  private enterTimer;
89
89
  private leaveTimer;
90
90
  constructor(id: string, content: ToastContent, config: ToastConfig<unknown, R>, dismissCallback: (ref: ToastRef) => void);
91
+ /**
92
+ * @internal Start the enter animation clock. Called by the service once the
93
+ * toast has actually been attached to its container.
94
+ *
95
+ * This deliberately does NOT run from the constructor. The renderer is loaded
96
+ * through a dynamic `import()`, so a ref can exist for an arbitrary stretch
97
+ * before anything is on screen — starting the clock at construction would let
98
+ * a toast burn part (or all) of its auto-dismiss duration while still
99
+ * invisible on a slow connection. Idempotent and safe to call after dismissal.
100
+ */
101
+ _startEnterSequence(): void;
91
102
  /**
92
103
  * Dismiss the toast programmatically. The leave animation plays before the
93
104
  * element is removed and subscribers are notified. Safe to call multiple times.
@@ -165,7 +176,16 @@ declare class ToastConfig<D = unknown, _R = unknown> {
165
176
  severity?: ToastSeverity;
166
177
  /** Screen position of the toast stack. Defaults to `'bottom-right'`. */
167
178
  position?: ToastPosition;
168
- /** Auto-dismiss duration in ms. `0` disables auto-dismiss. Defaults to `5000`. */
179
+ /**
180
+ * Auto-dismiss duration in ms. `0` disables auto-dismiss. Defaults to `5000`.
181
+ *
182
+ * The duration alone would fail SC 2.2.1 (Timing Adjustable) — a time limit the
183
+ * user cannot influence. What makes 5s conformant is `pauseOnInteraction`
184
+ * (default `true`): the clock stops while the pointer is over the toast or
185
+ * focus is anywhere inside it, and resumes on leave / blur. Setting
186
+ * `pauseOnInteraction: false` alongside a non-zero duration re-introduces the
187
+ * failure, so pair it with `duration: 0`.
188
+ */
169
189
  duration?: number;
170
190
  /** When true, renders a close (×) button. Defaults to `true`. */
171
191
  dismissible?: boolean;
@@ -190,7 +210,7 @@ declare class ToastConfig<D = unknown, _R = unknown> {
190
210
  * primitives for the string-content path.
191
211
  */
192
212
  icon?: string | false;
193
- /** When true, pause the auto-dismiss timer while the toast is hovered or holds focus. Defaults to `true`. */
213
+ /** When true, pause the auto-dismiss timer while the toast is hovered or holds focus anywhere inside it, resuming on leave / blur. Defaults to `true`. */
194
214
  pauseOnInteraction?: boolean;
195
215
  /** Enable horizontal swipe-to-dismiss via pointer gestures. Defaults to `true`. */
196
216
  swipeToDismiss?: boolean;
@@ -215,6 +235,11 @@ declare const TW_TOAST_DEFAULT_OPTIONS: InjectionToken<Partial<ToastConfig<unkno
215
235
  /** Accepted content forms for `ToastService.show()`. */
216
236
  type ToastContent = string | TemplateRef<ToastTemplateContext> | Type<unknown>;
217
237
 
238
+ /**
239
+ * The three messages {@link ToastService.promise} shows as a promise settles.
240
+ * `success` and `error` may be functions, receiving the resolved value or the
241
+ * rejection reason so the message can quote it.
242
+ */
218
243
  interface PromiseMessages<T> {
219
244
  loading: string;
220
245
  success: string | ((value: T) => string);
@@ -225,14 +250,22 @@ interface PromiseMessages<T> {
225
250
  * created per `ToastPosition` on first use and reused for the lifetime of the
226
251
  * service; toasts stack vertically inside their position container.
227
252
  *
253
+ * The rendering layer (CDK overlay + the toast components) is loaded through a
254
+ * dynamic `import()` on the first `show()` call, so merely registering this
255
+ * service costs nothing in the initial bundle. Every open method still returns
256
+ * its {@link ToastRef} synchronously — the toast is attached once the chunk
257
+ * lands, and `update()` / `dismiss()` called in the meantime are honoured.
258
+ *
228
259
  * Not `providedIn: 'root'` — register via {@link provideToast}.
229
260
  */
230
261
  declare class ToastService implements OnDestroy {
231
- private readonly overlay;
232
262
  private readonly injector;
233
263
  private readonly defaultOptions;
234
264
  private readonly parent;
235
- private readonly positionOverlays;
265
+ /** Cached renderer chunk. Non-null once the first `show()` has kicked off the import. */
266
+ private rendererPromise;
267
+ private renderer;
268
+ private destroyed;
236
269
  private readonly activeRefsAtThisLevel;
237
270
  private readonly afterOpenedSubject;
238
271
  private readonly afterAllDismissedSubject;
@@ -273,14 +306,30 @@ declare class ToastService implements OnDestroy {
273
306
  ngOnDestroy(): void;
274
307
  private openWithSeverity;
275
308
  private openInternal;
309
+ /**
310
+ * Attach a toast once the renderer chunk has loaded. The ref was already
311
+ * returned to the caller, so it may have been dismissed (or the service
312
+ * destroyed) while the import was in flight — both are checked before
313
+ * anything is put on screen.
314
+ */
315
+ private attachWhenRendererReady;
316
+ /**
317
+ * @internal Resolves once the renderer chunk has loaded and pending toasts
318
+ * have been attached. Exposed for tests, which must await the dynamic import
319
+ * before asserting on rendered DOM.
320
+ */
321
+ _whenRendered(): Promise<void>;
322
+ /** Load (once) and instantiate the rendering layer. Resolves to `null` if the service was destroyed mid-import. */
323
+ private loadRenderer;
276
324
  private enforceMaxVisible;
277
325
  private registerOpen;
278
326
  private handleDismissed;
279
- private attachToContainer;
280
- private announceOpen;
327
+ /**
328
+ * Re-announce an updated toast. If the renderer has not landed yet there is
329
+ * nothing on screen to announce — the announcement that fires on attach
330
+ * reads the ref's current (already updated) content, so nothing is lost.
331
+ */
281
332
  private announceUpdate;
282
- private getContainerForPosition;
283
- private buildPositionStrategy;
284
333
  private resolveConfig;
285
334
  private getAfterAllDismissedSource;
286
335
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ToastService, never>;
@@ -341,7 +390,7 @@ declare class ToastActionDirective {
341
390
  declare class ToastComponent {
342
391
  /** Severity variant. Drives color palette, default icon, and ARIA role / live politeness. Defaults to `'info'`. */
343
392
  readonly severity: _angular_core.InputSignal<ToastSeverity>;
344
- /** Whether to render the close button. Defaults to `true`. */
393
+ /** Whether to render the close button. Defaults to `true` — mirroring `ToastConfig.dismissible`, toasts must offer an escape hatch; the special case is an ephemeral progress marker paired with `duration`. */
345
394
  readonly dismissible: _angular_core.InputSignal<boolean>;
346
395
  /**
347
396
  * Icon override. Pass a string to render as text inside the icon slot, or
@@ -351,7 +400,7 @@ declare class ToastComponent {
351
400
  * For arbitrary icon markup, project a `[twToastIcon]` child instead.
352
401
  */
353
402
  readonly icon: _angular_core.InputSignal<string | false | undefined>;
354
- /** Explicit aria-label for the toast wrapper. When omitted, text content is used by assistive tech. */
403
+ /** Explicit aria-label for the toast wrapper. Mirrored to `aria-label`. When omitted, text content is used by assistive tech. Defaults to `undefined`. */
355
404
  readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
356
405
  /** Fires when the close button is clicked. */
357
406
  readonly dismissed: _angular_core.OutputEmitterRef<void>;
@@ -381,8 +430,8 @@ declare class ToastComponent {
381
430
  /** @internal */
382
431
  protected readonly ariaLiveAttr: _angular_core.Signal<"polite" | "assertive">;
383
432
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ToastComponent, never>;
384
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<ToastComponent, "tw-toast", never, { "severity": { "alias": "severity"; "required": false; "isSignal": true; }; "dismissible": { "alias": "dismissible"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "dismissed": "dismissed"; "actionClicked": "actionClicked"; }, ["projectedIcon"], ["[twToastIcon]", "[twToastTitle]", "[twToastDescription]", "*", "[twToastAction]"], true, never>;
433
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ToastComponent, "tw-toast", never, { "severity": { "alias": "severity"; "required": false; "isSignal": true; }; "dismissible": { "alias": "dismissible"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; }, { "dismissed": "dismissed"; "actionClicked": "actionClicked"; }, ["projectedIcon"], ["[twToastIcon]", "[twToastTitle]", "[twToastDescription]", "*", "[twToastAction]"], true, never>;
385
434
  }
386
435
 
387
436
  export { TW_TOAST_DATA, TW_TOAST_DEFAULT_OPTIONS, TW_TOAST_REF, ToastActionDirective, ToastComponent, ToastConfig, ToastDescriptionDirective, ToastIconDirective, ToastRef, ToastService, ToastTitleDirective, provideToast };
388
- export type { ToastAction, ToastContent, ToastDismissReason, ToastDismissal, ToastPosition, ToastSeverity, ToastState, ToastTemplateContext, ToastUpdatePatch };
437
+ export type { PromiseMessages, ToastAction, ToastContent, ToastDismissReason, ToastDismissal, ToastPosition, ToastSeverity, ToastState, ToastTemplateContext, ToastUpdatePatch };
@@ -20,17 +20,19 @@ declare class TooltipDirective {
20
20
  */
21
21
  readonly twTooltipShowDelay: _angular_core.InputSignal<number>;
22
22
  /**
23
- * Milliseconds to wait before hiding after trigger ends. Defaults to `0`
24
- * (immediate dismiss). The asymmetry with `twTooltipShowDelay` is
25
- * intentional show is gated to filter noise, hide is instant so the
26
- * tooltip never lingers over content the user has moved on from.
23
+ * Milliseconds to wait before hiding after the trigger is left. Defaults to
24
+ * `150` a grace period, not a lingering delay: WCAG 2.1 SC 1.4.13 requires
25
+ * the tooltip to be hoverable, and the panel sits 8px clear of its trigger,
26
+ * so the pointer needs a window in which to cross that gap. Hovering the
27
+ * panel itself cancels the pending hide entirely. Set `0` to opt out (the
28
+ * tooltip is then dismissible by Escape but not reachable by pointer).
27
29
  */
28
30
  readonly twTooltipHideDelay: _angular_core.InputSignal<number>;
29
31
  /** When true, tooltip never shows. Defaults to `false`. */
30
32
  readonly twTooltipDisabled: _angular_core.InputSignal<boolean>;
31
- /** When true, renders an arrow pointing to the trigger. Defaults to `true`. */
33
+ /** When true, renders an arrow pointing to the trigger. Defaults to `true` — arrows reinforce the visual association between the floating panel and its trigger and match every other ngx-tw overlay (popover, menu); the special case is a compact iconic context. */
32
34
  readonly twTooltipArrow: _angular_core.InputSignal<boolean>;
33
- /** Optional class string (space-separated) merged into the panel slot for consumer customization. */
35
+ /** Optional class string (space-separated) merged into the panel slot for consumer customization. Defaults to an empty string. */
34
36
  readonly twTooltipPanelClass: _angular_core.InputSignal<string>;
35
37
  /** Fires when the tooltip becomes visible. */
36
38
  readonly twTooltipShown: _angular_core.OutputEmitterRef<void>;
@@ -41,9 +43,18 @@ declare class TooltipDirective {
41
43
  private readonly destroyRef;
42
44
  private readonly ariaDescriber;
43
45
  private overlayRef;
46
+ /**
47
+ * The live position strategy. Held as a field so every show can re-apply
48
+ * `twTooltipPosition` onto it — see `applyPositions`.
49
+ */
50
+ private positionStrategy;
51
+ /** The `twTooltipPosition` value currently baked into `positionStrategy`. */
52
+ private appliedPosition;
44
53
  private tooltipInstance;
45
54
  private showTimer;
46
55
  private hideTimer;
56
+ /** Removes the panel's hover listeners. Set in `createOverlay`, invoked from `disposeOverlay`. */
57
+ private overlayHoverCleanup;
47
58
  /** Last description string handed to `AriaDescriber.describe` — required so the symmetrical `removeDescription` call passes the same key. */
48
59
  private _describedBy;
49
60
  /** True when the trigger's `aria-describedby` was set directly to the overlay id (TemplateRef fallback path); used by `removeAriaDescription` to choose the symmetrical teardown. */
@@ -64,6 +75,17 @@ declare class TooltipDirective {
64
75
  protected onTouchEnd(): void;
65
76
  private createAndShow;
66
77
  private createOverlay;
78
+ /**
79
+ * Pushes the current `twTooltipPosition` onto the live position strategy.
80
+ *
81
+ * Updating the strategy in place rather than disposing the `OverlayRef` on
82
+ * hide is not just the cheaper option — it is the correct one. `createOverlay`
83
+ * subscribes to `positionStrategy.positionChanges` exactly once, and that feed
84
+ * is what drives the arrow direction; `FlexibleConnectedPositionStrategy`
85
+ * completes that subject in `dispose()`, so a dispose-on-hide would silently
86
+ * kill arrow placement from the second show onward.
87
+ */
88
+ private applyPositions;
67
89
  private updateTooltip;
68
90
  private detach;
69
91
  /**
@@ -0,0 +1,152 @@
1
+ import { BaseHarnessFilters, ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';
2
+
3
+ /** Filters accepted by `TransferItemHarness.with`. */
4
+ interface TransferItemHarnessFilters extends BaseHarnessFilters {
5
+ /** Match by the row's visible text. */
6
+ text?: string | RegExp;
7
+ /** Match ticked / unticked rows. */
8
+ checked?: boolean;
9
+ /** Match disabled / enabled rows. */
10
+ disabled?: boolean;
11
+ }
12
+ /**
13
+ * Harness for a single row inside one of a `tw-transfer`'s two panels.
14
+ *
15
+ * Rows are `CdkOption`s, so the harness reads ARIA that CDK owns rather than
16
+ * anything ngx-tw renders: `aria-selected` for the ticked state and
17
+ * `aria-disabled` for the per-item disable predicate.
18
+ *
19
+ * "Checked" here is the *ephemeral pending-move* state — which rows the next
20
+ * move button press will shuttle — not membership of a side. Membership is the
21
+ * component's value; read it by asking {@link TransferHarness} which panel a
22
+ * row is in.
23
+ *
24
+ * Reach these through {@link TransferHarness.getItems}: located from a document
25
+ * root the selector would match every listbox option on the page.
26
+ */
27
+ declare class TransferItemHarness extends ComponentHarness {
28
+ static hostSelector: string;
29
+ /** Predicate for `locatorFor` / `locatorForAll`. */
30
+ static with(options?: TransferItemHarnessFilters): HarnessPredicate<TransferItemHarness>;
31
+ /**
32
+ * The row's rendered text, trimmed. With the default row rendering this is
33
+ * `labelFn(item)`; a projected `*twTransferItem` template makes it whatever
34
+ * that template renders.
35
+ */
36
+ getText(): Promise<string>;
37
+ /** Whether the row is ticked for the next move, from `aria-selected`. */
38
+ isChecked(): Promise<boolean>;
39
+ /** Whether the row reports `aria-disabled="true"` (`behavior.disabledItem`). */
40
+ isDisabled(): Promise<boolean>;
41
+ /** Ticks the row for the next move. No-op when already ticked. */
42
+ check(): Promise<void>;
43
+ /** Unticks the row. No-op when already unticked. */
44
+ uncheck(): Promise<void>;
45
+ }
46
+
47
+ /**
48
+ * Which panel of a `tw-transfer` a call addresses. Structurally identical to
49
+ * the component's own `TwTransferSide`, redeclared here so the testing entry
50
+ * point stays free of any import from the component entry point.
51
+ */
52
+ type TransferHarnessSide = 'source' | 'target';
53
+ /** Filters accepted by `TransferHarness.with`. */
54
+ interface TransferHarnessFilters extends BaseHarnessFilters {
55
+ /** Match by the control's accessible name (its `aria-label`). */
56
+ label?: string | RegExp;
57
+ /** Match disabled / enabled controls. */
58
+ disabled?: boolean;
59
+ }
60
+ /**
61
+ * Harness for `tw-transfer`.
62
+ *
63
+ * ## How the two panels are told apart
64
+ *
65
+ * The panels are one `ng-template` instantiated twice, and neither the panel
66
+ * element nor its list carries a side marker. The only per-side hook the
67
+ * component renders is the auto-generated panel-title id — `…-source-title` /
68
+ * `…-target-title` — which the listbox references through `aria-labelledby`
69
+ * and which the component's own `focusDestination()` already matches on for
70
+ * the same reason. This harness scopes every per-side query with a suffix
71
+ * match on that id.
72
+ *
73
+ * Two consequences worth knowing:
74
+ *
75
+ * - Ordering is never assumed, so a panel that has emptied (its listbox is
76
+ * removed entirely — an empty `role="listbox"` violates
77
+ * `aria-required-children`) does not shift the other panel's identity.
78
+ * {@link getItems} simply returns `[]` for the empty side.
79
+ * - The hook is a derived id, not a declared contract. If the panels ever gain
80
+ * a real marker attribute, this is the code that should move onto it.
81
+ *
82
+ * The whole control lives inside the `tw-transfer` host — there is no CDK
83
+ * overlay — so the ordinary fixture loader is enough.
84
+ */
85
+ declare class TransferHarness extends ComponentHarness {
86
+ static hostSelector: string;
87
+ /**
88
+ * The move buttons, in DOM order: `[0]` shuttles source → target and `[1]`
89
+ * target → source (absent under `behavior.oneWay`).
90
+ *
91
+ * The `:not()` excludes buttons a consumer projected into a
92
+ * `*twTransferItem` template, which would otherwise be picked up ahead of
93
+ * the real controls — rows render before the button column.
94
+ */
95
+ private readonly moveButtons;
96
+ /** Predicate for `locatorFor` / `locatorForAll`. */
97
+ static with(options?: TransferHarnessFilters): HarnessPredicate<TransferHarness>;
98
+ /** The control's accessible name, from `aria-label` when one is set. */
99
+ getLabel(): Promise<string | null>;
100
+ /** Whether the control reports `aria-disabled="true"`. */
101
+ isDisabled(): Promise<boolean>;
102
+ /** The title rendered in a panel's header. */
103
+ getTitle(side: TransferHarnessSide): Promise<string>;
104
+ /**
105
+ * Every visible row in a panel, in render order. Returns `[]` for a panel
106
+ * with nothing in it — including one hidden behind a search query, since
107
+ * filtering removes rows from the DOM rather than hiding them.
108
+ *
109
+ * `filters.ancestor` is ignored: picking the side *is* the ancestor.
110
+ */
111
+ getItems(side: TransferHarnessSide, filters?: TransferItemHarnessFilters): Promise<TransferItemHarness[]>;
112
+ /** The visible text of every row in a panel, in render order. */
113
+ getItemTexts(side: TransferHarnessSide): Promise<string[]>;
114
+ /**
115
+ * How many rows a panel is showing. This is the number the panel header's
116
+ * count also reports, so it tracks the search query rather than total
117
+ * membership.
118
+ */
119
+ getItemCount(side: TransferHarnessSide): Promise<number>;
120
+ /**
121
+ * Ticks the first row in a panel whose text matches, staging it for the next
122
+ * move. Throws when nothing matches, rather than failing silently.
123
+ */
124
+ checkItem(side: TransferHarnessSide, text: string | RegExp): Promise<void>;
125
+ /**
126
+ * Drives a panel's header select-all checkbox to `checked`, ticking or
127
+ * clearing every enabled visible row in one gesture. This is how "move
128
+ * everything" is expressed: `setAllChecked('source', true)` then
129
+ * {@link moveToTarget}.
130
+ *
131
+ * The checkbox is tri-state. From `mixed` a single click resolves to
132
+ * *checked*, the way a native indeterminate checkbox does, so clearing from
133
+ * a partial selection takes two clicks — which is what a user does too, and
134
+ * what this method issues. Everything is ticked in between.
135
+ *
136
+ * Throws when the checkbox is not rendered (`display.showSelectAll: false`).
137
+ */
138
+ setAllChecked(side: TransferHarnessSide, checked: boolean): Promise<void>;
139
+ /**
140
+ * Presses the → button, shuttling the source panel's ticked rows to the
141
+ * target. Rows that are disabled are skipped by the component.
142
+ */
143
+ moveToTarget(): Promise<void>;
144
+ /**
145
+ * Presses the ← button, shuttling the target panel's ticked rows back to the
146
+ * source. Throws under `behavior.oneWay`, where that button is not rendered.
147
+ */
148
+ moveToSource(): Promise<void>;
149
+ }
150
+
151
+ export { TransferHarness, TransferItemHarness };
152
+ export type { TransferHarnessFilters, TransferHarnessSide, TransferItemHarnessFilters };