@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
@@ -0,0 +1,148 @@
1
+ import { ComponentHarness, BaseHarnessFilters, HarnessPredicate } from '@angular/cdk/testing';
2
+ import { CalendarHarness } from '@cdevhub/ngx-tw/calendar/testing';
3
+
4
+ /** Filters accepted by `DateRangePickerHarness.with`. */
5
+ interface DateRangePickerHarnessFilters extends BaseHarnessFilters {
6
+ /** Match by the trigger's accessible name. */
7
+ label?: string | RegExp;
8
+ /** Match by the whole text currently rendered in the trigger. */
9
+ triggerText?: string | RegExp;
10
+ /** Match disabled / enabled pickers. */
11
+ disabled?: boolean;
12
+ }
13
+ /**
14
+ * Harness for `tw-date-range-picker`.
15
+ *
16
+ * Unlike `tw-date-picker`, this component has **no text input**: its trigger is
17
+ * a `button[role="combobox"]` that renders the start label, a separator and the
18
+ * end label as three sibling spans (or a single placeholder span when empty).
19
+ * A range is therefore read, never typed — {@link getStartText} /
20
+ * {@link getEndText} read it, and {@link selectRange} sets it through the
21
+ * calendar.
22
+ *
23
+ * The calendar renders into the CDK overlay, outside the
24
+ * `tw-date-range-picker` host, so it is resolved through
25
+ * `documentRootLocatorFactory()`. A consumer loads this harness from the
26
+ * ordinary fixture loader — no `documentRootLoader` ceremony required.
27
+ *
28
+ * Day-grid navigation is not reimplemented here: {@link getCalendar} returns
29
+ * the `CalendarHarness` from `@cdevhub/ngx-tw/calendar/testing`, which already
30
+ * owns cells, view switching and header paging.
31
+ */
32
+ declare class DateRangePickerHarness extends ComponentHarness {
33
+ static hostSelector: string;
34
+ private readonly trigger;
35
+ /**
36
+ * The start / separator / end spans, or a single placeholder span when the
37
+ * range is empty. They carry no distinguishing attribute, so position inside
38
+ * the trigger is the only handle — see {@link getStartText}.
39
+ */
40
+ private readonly triggerSpans;
41
+ /**
42
+ * The inline clear control — the only button in the host that is not the
43
+ * trigger.
44
+ */
45
+ private readonly clearButton;
46
+ /** Resolves the overlay's calendar, which lives outside this harness's host. */
47
+ private readonly calendar;
48
+ /** Predicate for `locatorFor` / `locatorForAll`. */
49
+ static with(options?: DateRangePickerHarnessFilters): HarnessPredicate<DateRangePickerHarness>;
50
+ /**
51
+ * The trigger's accessible name.
52
+ *
53
+ * Note this is *composed*, not the bare `aria-label`: once a complete range
54
+ * is set the component appends the range to it
55
+ * (`"Report period. Current range: Apr 10 to Apr 15."`). Match with a RegExp
56
+ * in {@link with} if you need it to survive a selection.
57
+ */
58
+ getLabel(): Promise<string | null>;
59
+ /**
60
+ * The whole text rendered in the trigger, trimmed — start, separator and end
61
+ * run together, or the placeholder when no range is set.
62
+ */
63
+ getTriggerText(): Promise<string>;
64
+ /**
65
+ * The formatted start date, or `null` when no range is set (the trigger then
66
+ * renders a single placeholder span instead of the start/separator/end
67
+ * triple).
68
+ */
69
+ getStartText(): Promise<string | null>;
70
+ /** The formatted end date, or `null` when no range is set. */
71
+ getEndText(): Promise<string | null>;
72
+ /** Whether the calendar overlay is open, read from the trigger's `aria-expanded`. */
73
+ isOpen(): Promise<boolean>;
74
+ /** Whether the trigger reports `aria-disabled="true"`. */
75
+ isDisabled(): Promise<boolean>;
76
+ /** Whether the trigger reports `aria-invalid="true"`. */
77
+ isInvalid(): Promise<boolean>;
78
+ /**
79
+ * Whether the trigger reports `aria-required="true"`. Reflects the `required`
80
+ * input *and* a `Validators.required` on a bound control.
81
+ */
82
+ isRequired(): Promise<boolean>;
83
+ /**
84
+ * Opens the calendar overlay by clicking the trigger. No-op when already
85
+ * open; a disabled picker ignores it, as it does in the browser.
86
+ */
87
+ open(): Promise<void>;
88
+ /**
89
+ * Closes the calendar overlay by clicking the trigger again. No-op when
90
+ * already closed.
91
+ *
92
+ * Deliberately not Escape: `tw-date-range-picker` treats Escape as *cancel*
93
+ * and restores the range the overlay opened with, which would make `close()`
94
+ * silently undo a selection. The trigger toggles without that side effect.
95
+ *
96
+ * The overlay runs a leave animation before it detaches, so `isOpen()` flips
97
+ * to `false` immediately while the panel element lingers for a few more
98
+ * frames. Two consequences worth knowing:
99
+ *
100
+ * - Do not assert `getCalendar()` is `null` on the tick after a close; the
101
+ * old panel is still mounted.
102
+ * - An `open()` inside that window does **not** attach a fresh panel — the
103
+ * component sees an overlay ref it has not disposed yet and silently
104
+ * keeps the outgoing one. Let the animation finish before reopening.
105
+ */
106
+ close(): Promise<void>;
107
+ /**
108
+ * The `CalendarHarness` for the open overlay, or `null` when no overlay is
109
+ * attached. One `tw-calendar` renders all `numberOfMonths` months under a
110
+ * single header, so this is a single harness whatever that input is set to.
111
+ */
112
+ getCalendar(): Promise<CalendarHarness | null>;
113
+ /**
114
+ * Opens the overlay if needed and clicks the two cells whose text matches
115
+ * `start` then `end` exactly (`'10'`, not `'April 10'`). Throws when either
116
+ * cell is not visible in the current view.
117
+ *
118
+ * With more than one month rendered a day number appears once per month grid;
119
+ * the first match wins, which is the earliest visible month. Page the
120
+ * calendar via {@link getCalendar} first if you need a later one.
121
+ *
122
+ * With `showActions` off this commits and closes on the second click; with it
123
+ * on the range stays pending until {@link clickAction} confirms it.
124
+ */
125
+ selectRange(start: string, end: string): Promise<void>;
126
+ /**
127
+ * Clicks a button in the overlay's action bar (`Today`, `Clear`, `Cancel`,
128
+ * `Apply`) by its visible text. Matching on text rather than position is what
129
+ * keeps this usable when a consumer relabels the actions via `todayLabel` and
130
+ * friends — pass whatever label you configured.
131
+ *
132
+ * Preset entries are excluded: they are `role="option"`, not action buttons.
133
+ * Throws when the overlay is closed or nothing matches.
134
+ */
135
+ clickAction(label: string | RegExp): Promise<void>;
136
+ /**
137
+ * Whether the inline clear control is rendered. It appears only while
138
+ * `showClear` is on, the picker is enabled, and a range is set.
139
+ */
140
+ hasClearButton(): Promise<boolean>;
141
+ /** Clicks the inline clear control. Throws when none is rendered. */
142
+ clear(): Promise<void>;
143
+ /** @internal Text of one of the start/separator/end spans, or `null` when the trigger is empty. */
144
+ private rangeSpanText;
145
+ }
146
+
147
+ export { DateRangePickerHarness };
148
+ export type { DateRangePickerHarnessFilters };
@@ -55,21 +55,21 @@ declare class DateRangePickerComponent<D = Date> extends FormFieldControl<TwDate
55
55
  readonly minDate: _angular_core.InputSignal<D | null>;
56
56
  /** Latest selectable date for either endpoint. Presets and calendar cells later than this are rejected or disabled. Defaults to `null`. */
57
57
  readonly maxDate: _angular_core.InputSignal<D | null>;
58
- /** Per-date predicate — return `false` to disable. Applied in both calendars. Presets that fall on a filtered date are skipped. */
58
+ /** Per-date predicate — return `false` to disable. Applied in both calendars. Presets that fall on a filtered date are skipped. Defaults to `null`. */
59
59
  readonly dateFilter: _angular_core.InputSignal<DateFilterFn<D> | null>;
60
60
  /** Which calendar view opens first — `'day'`, `'month'`, or `'year'`. Defaults to `'day'`. */
61
61
  readonly startView: _angular_core.InputSignal<CalendarViewState>;
62
- /** Date the left calendar focuses on when opened with no value. Falls back to today. Ignored when a value is already set. */
62
+ /** Date the left calendar focuses on when opened with no value. Falls back to today. Ignored when a value is already set. Defaults to `null`. */
63
63
  readonly startAt: _angular_core.InputSignal<D | null>;
64
64
  /** Display format for each endpoint, passed to `DateAdapter.format()`. When `showTime` is true and this is left at the default, hour/minute (and optional seconds) are folded in automatically. */
65
65
  readonly format: _angular_core.InputSignal<unknown>;
66
66
  /** Separator rendered between the two formatted endpoints in the trigger. Defaults to `" – "`. */
67
67
  readonly rangeSeparator: _angular_core.InputSignal<string>;
68
- /** Placeholder text shown in the trigger for an empty `start` endpoint. */
68
+ /** Placeholder text shown in the trigger for an empty `start` endpoint. Defaults to `'Start date'`. */
69
69
  readonly emptyStartLabel: _angular_core.InputSignal<string>;
70
- /** Placeholder text shown in the trigger for an empty `end` endpoint. */
70
+ /** Placeholder text shown in the trigger for an empty `end` endpoint. Defaults to `'End date'`. */
71
71
  readonly emptyEndLabel: _angular_core.InputSignal<string>;
72
- /** When set, overrides the composed `${emptyStartLabel}${rangeSeparator}${emptyEndLabel}` placeholder with a single string. */
72
+ /** When set, overrides the composed `${emptyStartLabel}${rangeSeparator}${emptyEndLabel}` placeholder with a single string. Defaults to `undefined`. */
73
73
  readonly placeholder: _angular_core.InputSignal<string | undefined>;
74
74
  /** When true, the trigger cannot open the overlay and `aria-disabled="true"` is set. Defaults to `false`. */
75
75
  readonly disabledInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
@@ -83,9 +83,9 @@ declare class DateRangePickerComponent<D = Date> extends FormFieldControl<TwDate
83
83
  readonly variant: _angular_core.InputSignal<DateRangePickerVariant | undefined>;
84
84
  /** How many months the overlay shows side-by-side. `2` is the standard range-picker layout; use `1` for compact contexts. Defaults to `2`. */
85
85
  readonly numberOfMonths: _angular_core.InputSignal<DateRangePickerMonths>;
86
- /** Optional quick-select presets rendered as a vertical list before the calendars. Each preset provides a label and a factory returning a `TwDateRange<D>`. An empty array hides the preset panel. */
86
+ /** Optional quick-select presets rendered as a vertical list before the calendars. Each preset provides a label and a factory returning a `TwDateRange<D>`. An empty array hides the preset panel. Defaults to an empty array. */
87
87
  readonly presets: _angular_core.InputSignal<readonly DateRangePreset<D>[]>;
88
- /** Whether to show a clear-button affordance inside the trigger when a value is set. Defaults to `true`. */
88
+ /** Whether to show a clear-button affordance inside the trigger when a value is set. Defaults to `true` — most form pickers expect the inline clear, matching `<tw-input>`'s clear button; without it consumers must wire one themselves. */
89
89
  readonly showClear: _angular_core.InputSignal<boolean>;
90
90
  /** Minimum range length in days, inclusive. Commits shorter than this are rejected and surface `calendarRangeTooShort` on the bound `NgControl`. `null` = no minimum. Defaults to `null`. */
91
91
  readonly minRangeLength: _angular_core.InputSignal<number | null>;
@@ -101,11 +101,11 @@ declare class DateRangePickerComponent<D = Date> extends FormFieldControl<TwDate
101
101
  readonly rangeClickBehavior: _angular_core.InputSignal<RangeClickBehavior>;
102
102
  /** Override first day of week (0=Sun, 1=Mon) on the embedded calendar. Falls back to the adapter's default. */
103
103
  readonly firstDayOfWeek: _angular_core.InputSignal<number | null>;
104
- /** Per-instance locale override. Forwarded to the embedded calendar and the underlying `DateAdapter` so the trigger display tracks the picker's locale. Falls back to Angular `LOCALE_ID` when `null`. */
104
+ /** Per-instance locale override. Forwarded to the embedded calendar and the underlying `DateAdapter` so the trigger display tracks the picker's locale. Falls back to Angular `LOCALE_ID` when `null`. Defaults to `null`. */
105
105
  readonly locale: _angular_core.InputSignal<string | null>;
106
- /** Function producing per-cell CSS classes on the embedded calendar. */
106
+ /** Function producing per-cell CSS classes on the embedded calendar. Defaults to `null`. */
107
107
  readonly dateClass: _angular_core.InputSignal<DateClassFn<D> | null>;
108
- /** Optional cell-content template, forwarded to the embedded calendar. Use to customize cell visuals beyond `dateClass`. */
108
+ /** Optional cell-content template, forwarded to the embedded calendar. Use to customize cell visuals beyond `dateClass`. Defaults to `null`. */
109
109
  readonly cellTemplate: _angular_core.InputSignal<TemplateRef<{
110
110
  $implicit: CalendarCell<D>;
111
111
  }> | null>;
@@ -123,15 +123,15 @@ declare class DateRangePickerComponent<D = Date> extends FormFieldControl<TwDate
123
123
  readonly minuteStep: _angular_core.InputSignal<number>;
124
124
  /** Step for the embedded time-pickers' second fields. Defaults to `1`. */
125
125
  readonly secondStep: _angular_core.InputSignal<number>;
126
- /** Label for the `Today` action in the overlay's action bar. */
126
+ /** Label for the `Today` action in the overlay's action bar. Defaults to `'Today'`. */
127
127
  readonly todayLabel: _angular_core.InputSignal<string>;
128
- /** Label for the `Clear` action in the overlay's action bar. */
128
+ /** Label for the `Clear` action in the overlay's action bar. Defaults to `'Clear'`. */
129
129
  readonly clearLabel: _angular_core.InputSignal<string>;
130
- /** Label for the `Cancel` action in the overlay's action bar. */
130
+ /** Label for the `Cancel` action in the overlay's action bar. Defaults to `'Cancel'`. */
131
131
  readonly cancelLabel: _angular_core.InputSignal<string>;
132
- /** Label for the `Apply` action in the overlay's action bar. */
132
+ /** Label for the `Apply` action in the overlay's action bar. Defaults to `'Apply'`. */
133
133
  readonly applyLabel: _angular_core.InputSignal<string>;
134
- /** Extra class(es) applied to the overlay panel element. `twMerge` resolves conflicts with internal classes. */
134
+ /** Extra class(es) applied to the overlay panel element. `twMerge` resolves conflicts with internal classes. Defaults to an empty string. */
135
135
  readonly panelClass: _angular_core.InputSignal<string | readonly string[]>;
136
136
  /** CDK scroll strategy for the overlay. Defaults to `'reposition'`. */
137
137
  readonly scrollStrategy: _angular_core.InputSignal<"reposition" | "close" | "block">;
@@ -139,17 +139,17 @@ declare class DateRangePickerComponent<D = Date> extends FormFieldControl<TwDate
139
139
  readonly offset: _angular_core.InputSignal<number>;
140
140
  /** Accessible label for the clear button. Defaults to `'Clear date range'`. */
141
141
  readonly clearAriaLabel: _angular_core.InputSignal<string>;
142
- /** Per-instance override of the `ErrorStateMatcher`. When omitted, uses the injected `TW_ERROR_STATE_MATCHER`. */
142
+ /** Per-instance override of the `ErrorStateMatcher`. When omitted, uses the injected `TW_ERROR_STATE_MATCHER`. Defaults to `undefined`. */
143
143
  readonly errorStateMatcher: _angular_core.InputSignal<ErrorStateMatcher | undefined>;
144
- /** Accessible name for the trigger. Required when no visible label is supplied via `tw-form-field` or an external `aria-labelledby`. Alias: `aria-label`. */
144
+ /** Accessible name for the trigger. Required when no visible label is supplied via `tw-form-field` or an external `aria-labelledby`. Alias: `aria-label`. Defaults to `undefined`. */
145
145
  readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
146
- /** ID of an external element that labels the trigger. Alias: `aria-labelledby`. */
146
+ /** ID of an external element that labels the trigger. Alias: `aria-labelledby`. Defaults to `undefined`. */
147
147
  readonly ariaLabelledby: _angular_core.InputSignal<string | undefined>;
148
- /** Consumer-supplied `aria-describedby` ids. The form-field preserves these when merging hint/error ids. Alias: `aria-describedby`. */
148
+ /** Consumer-supplied `aria-describedby` ids. The form-field preserves these when merging hint/error ids. Alias: `aria-describedby`. Defaults to `undefined`. */
149
149
  readonly userAriaDescribedByInput: _angular_core.InputSignal<string | undefined>;
150
- /** Two-way bound selected range. `null` when no selection. Setting programmatically updates the trigger display and the calendar selection; it does NOT trigger `onChange`. */
150
+ /** Two-way bound selected range. `null` when no selection. Setting programmatically updates the trigger display and the calendar selection; it does NOT trigger `onChange`. Defaults to `null`. */
151
151
  readonly value: _angular_core.ModelSignal<TwDateRange<D> | null>;
152
- /** Two-way bound open state of the overlay. Setting to `true` opens; setting to `false` closes. */
152
+ /** Two-way bound open state of the overlay. Setting to `true` opens; setting to `false` closes. Defaults to `false`. */
153
153
  readonly open: _angular_core.ModelSignal<boolean>;
154
154
  /** Fires after the overlay's enter animation completes. Payload is the trigger element. */
155
155
  readonly opened: _angular_core.OutputEmitterRef<DateRangePickerOpenedEvent>;
@@ -170,9 +170,6 @@ declare class DateRangePickerComponent<D = Date> extends FormFieldControl<TwDate
170
170
  private readonly destroyRef;
171
171
  private readonly formField;
172
172
  private ngControl;
173
- private readonly parentForm;
174
- private readonly parentFormGroup;
175
- private readonly defaultMatcher;
176
173
  private readonly triggerRef;
177
174
  private readonly uid;
178
175
  /** @internal */
@@ -189,16 +186,16 @@ declare class DateRangePickerComponent<D = Date> extends FormFieldControl<TwDate
189
186
  readonly focusedSignal: _angular_core.WritableSignal<boolean>;
190
187
  private readonly cvaDisabled;
191
188
  private readonly describedByIdsSignal;
192
- private readonly closingSignal;
193
189
  private readonly lastValueBeforeOpen;
194
190
  private readonly pendingRange;
195
191
  private readonly currentView;
196
- private readonly _ngControlRev;
197
- private readonly _formSubmitRev;
192
+ /** @internal Shared `errorState` / `required` / `errors` derivation — see `wireErrorState`. */
193
+ private readonly errorWiring;
198
194
  private onChange;
199
195
  private onTouched;
200
- private readonly overlayInstanceSignal;
201
- private get overlayInstance();
196
+ private overlayInstance;
197
+ private closing;
198
+ private readonly isAttached;
202
199
  /** @internal */
203
200
  readonly isDisabled: Signal<boolean>;
204
201
  /** @internal Effective variant — auto-naked when wrapped in tw-form-field. */
@@ -250,6 +247,16 @@ declare class DateRangePickerComponent<D = Date> extends FormFieldControl<TwDate
250
247
  readonly required: Signal<boolean>;
251
248
  /** @internal */
252
249
  readonly errorState: Signal<boolean>;
250
+ /**
251
+ * @internal Active validation errors map from the bound `NgControl` (or `null` when the
252
+ * control reports none / is unbound). This is what `[twError match="…"]` filters on inside a
253
+ * `<tw-form-field>`; without it every `match`-targeted message — including the
254
+ * `calendarMinDate` / `calendarMaxDate` / `calendarInvalidRange` / `calendarRangeTooShort` /
255
+ * `calendarRangeTooLong` codes this component's `NG_VALIDATORS` apparatus exists to produce —
256
+ * stays permanently hidden. (Authoritative key list: `CalendarValidationErrors` in
257
+ * `calendar.types.ts`.)
258
+ */
259
+ readonly errors: Signal<Record<string, unknown> | null>;
253
260
  /** @internal */
254
261
  readonly controlType = "date-range-picker";
255
262
  /** @internal */
@@ -0,0 +1,98 @@
1
+ import { ComponentHarness, BaseHarnessFilters, HarnessPredicate } from '@angular/cdk/testing';
2
+
3
+ /** Filters accepted by `DialogHarness.with`. */
4
+ interface DialogHarnessFilters extends BaseHarnessFilters {
5
+ /** Match by the dialog's id — the same value as `TwDialogRef.id`. */
6
+ id?: string | RegExp;
7
+ /** Match by the text of the projected `[twDialogTitle]` element. */
8
+ title?: string | RegExp;
9
+ /** Match by ARIA role — `'dialog'` or `'alertdialog'`. */
10
+ role?: string | RegExp;
11
+ }
12
+ /**
13
+ * Harness for a dialog opened with `TwDialog.open()`.
14
+ *
15
+ * ## Loading it
16
+ *
17
+ * A dialog is **service-opened**, not template-declared: nothing in the test
18
+ * fixture's own DOM represents it, and the container renders into the CDK
19
+ * overlay container on `document.body`. This harness's host *is* that container,
20
+ * so it must be loaded from
21
+ * `TestbedHarnessEnvironment.documentRootLoader(fixture)` — the ordinary
22
+ * `loader(fixture)` searches inside `fixture.nativeElement` and will never find
23
+ * it. This is not the same situation as an overlay *panel* belonging to a
24
+ * template-declared component (`tw-select`, `tw-popover-overlay`, `tw-menu`),
25
+ * where the harness hosts on the in-fixture trigger and reaches its panel
26
+ * internally; there the plain fixture loader is correct.
27
+ *
28
+ * ## Waiting for it
29
+ *
30
+ * `TwDialog` loads its render layer through a dynamic `import()`, so the
31
+ * container does **not** exist synchronously after `open()`. Await the ref's
32
+ * public {@link TwDialogRef.whenComponentReady} before asking for the harness —
33
+ * it resolves once the chunk has landed and the overlay is attached, for
34
+ * template dialogs (with `null`) as well as component dialogs.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * const ref = dialog.open(EditorDialog);
39
+ * await ref.whenComponentReady();
40
+ * const rootLoader = TestbedHarnessEnvironment.documentRootLoader(fixture);
41
+ * const harness = await rootLoader.getHarness(DialogHarness);
42
+ * expect(await harness.getTitleText()).toBe('Edit profile');
43
+ * ```
44
+ */
45
+ declare class DialogHarness extends ComponentHarness {
46
+ static hostSelector: string;
47
+ private readonly title;
48
+ private readonly content;
49
+ /** Any descendant of the container that currently holds DOM focus. */
50
+ private readonly focusedDescendant;
51
+ /**
52
+ * Overlay backdrops, which are siblings of the dialog's overlay pane rather
53
+ * than descendants of the container — hence the document-root lookup.
54
+ */
55
+ private readonly backdrops;
56
+ /** Predicate for `locatorFor` / `locatorForAll`. */
57
+ static with(options?: DialogHarnessFilters): HarnessPredicate<DialogHarness>;
58
+ /** The dialog's id. Matches the `id` on the `TwDialogRef` returned by `open()`. */
59
+ getId(): Promise<string | null>;
60
+ /** The dialog's ARIA role — `'dialog'`, or `'alertdialog'` when so configured. */
61
+ getRole(): Promise<string | null>;
62
+ /**
63
+ * Text of the projected `[twDialogTitle]` element, trimmed, or `null` when
64
+ * the dialog's content does not use the title directive.
65
+ */
66
+ getTitleText(): Promise<string | null>;
67
+ /**
68
+ * Text of the projected `[twDialogContent]` region, trimmed, or `null` when
69
+ * the dialog's content does not use the content directive.
70
+ */
71
+ getContentText(): Promise<string | null>;
72
+ /**
73
+ * Whether DOM focus currently sits on the dialog container or anywhere inside
74
+ * it — the observable consequence of the CDK focus trap. CDK moves focus
75
+ * asynchronously, so let the fixture settle after opening before asserting.
76
+ */
77
+ containsFocus(): Promise<boolean>;
78
+ /** Whether the dialog rendered a backdrop. */
79
+ hasBackdrop(): Promise<boolean>;
80
+ /**
81
+ * Clicks the backdrop — the pointer dismiss gesture. Does nothing observable
82
+ * when the dialog was opened with `disableClose: true`, which is exactly how
83
+ * a test asserts that flag.
84
+ *
85
+ * Throws when no backdrop is rendered. With several overlays stacked, the
86
+ * last backdrop in the overlay container is used, i.e. the topmost one.
87
+ */
88
+ clickBackdrop(): Promise<void>;
89
+ /**
90
+ * Sends Escape to the dialog — the keyboard dismiss gesture. Like
91
+ * {@link clickBackdrop}, it is deliberately a no-op when the dialog was
92
+ * opened with `disableClose: true`.
93
+ */
94
+ pressEscape(): Promise<void>;
95
+ }
96
+
97
+ export { DialogHarness };
98
+ export type { DialogHarnessFilters };
@@ -139,7 +139,16 @@ declare class TwDialogRef<R = unknown, C = unknown> {
139
139
  private pendingResult;
140
140
  private closeFocusOrigin;
141
141
  constructor(id: string, config: TwDialogConfig<unknown, R>);
142
- /** The Tailwind container instance, or `null` until the dialog has attached. */
142
+ /**
143
+ * The Tailwind container instance, or `null` until the dialog has attached.
144
+ * `null` is the normal value for the first tick after `open()` returns,
145
+ * because the render layer is loaded through a dynamic `import()`.
146
+ *
147
+ * Only `state`, `animationStateChanged`, `enterAnimationDuration` and
148
+ * `exitAnimationDuration` are supported reads; the `_`-prefixed members are
149
+ * library-internal wiring and may change without a major bump. Prefer
150
+ * {@link state} and {@link afterOpened} on the ref itself.
151
+ */
143
152
  get containerInstance(): DialogContainer | null;
144
153
  /**
145
154
  * @internal Wire this facade to its CDK backend. Called from the dialog
@@ -350,7 +359,7 @@ declare class DialogActionsDirective {
350
359
  * `[twDialogClose]` value to pass a result to `afterClosed()` subscribers.
351
360
  */
352
361
  declare class DialogCloseDirective {
353
- /** Value passed to `afterClosed()` when the button is clicked. */
362
+ /** Value passed to `afterClosed()` when the button is clicked. Defaults to `undefined`. */
354
363
  readonly twDialogClose: i0.InputSignal<unknown>;
355
364
  /** Native button `type`. Defaults to `'button'` to avoid accidental form submission. */
356
365
  readonly type: i0.InputSignal<"button" | "submit" | "reset">;
@@ -360,5 +369,5 @@ declare class DialogCloseDirective {
360
369
  static ɵdir: i0.ɵɵDirectiveDeclaration<DialogCloseDirective, "[twDialogClose]", never, { "twDialogClose": { "alias": "twDialogClose"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
361
370
  }
362
371
 
363
- export { DialogActionsDirective, DialogCloseDirective, DialogContentDirective, DialogDescriptionDirective, DialogHeaderDirective, DialogIconDirective, DialogSubtitleDirective, DialogTitleDirective, TW_DIALOG_DATA, TW_DIALOG_DEFAULT_OPTIONS, TwDialog, TwDialogConfig, TwDialogRef, provideTwDialog };
372
+ export { DialogActionsDirective, DialogCloseDirective, DialogContainer, DialogContentDirective, DialogDescriptionDirective, DialogHeaderDirective, DialogIconDirective, DialogSubtitleDirective, DialogTitleDirective, TW_DIALOG_DATA, TW_DIALOG_DEFAULT_OPTIONS, TwDialog, TwDialogConfig, TwDialogRef, provideTwDialog };
364
373
  export type { DialogActionsAlign, DialogAnimationEvent, DialogState, TwDialogAutoFocus, TwDialogRestoreFocus, TwDialogRole, TwDialogScrollStrategy, TwDialogSize };
@@ -0,0 +1,120 @@
1
+ import { ComponentHarness, BaseHarnessFilters, HarnessPredicate } from '@angular/cdk/testing';
2
+
3
+ /** Filters accepted by `FileUploadFileHarness.with`. */
4
+ interface FileUploadFileHarnessFilters extends BaseHarnessFilters {
5
+ /** Match by the attached file's name. */
6
+ name?: string | RegExp;
7
+ }
8
+ /**
9
+ * Harness for a single attached file in a `tw-file-upload`'s list.
10
+ *
11
+ * Reach these through {@link FileUploadHarness.getFiles}.
12
+ *
13
+ * Everything here reads the *default* row rendering. A consumer who projects a
14
+ * `*twFileUploadItem` template replaces the row wholesale — including the
15
+ * remove control this harness drives — so {@link getName} and {@link remove}
16
+ * apply only to the built-in row.
17
+ */
18
+ declare class FileUploadFileHarness extends ComponentHarness {
19
+ static hostSelector: string;
20
+ private readonly removeButton;
21
+ /** Predicate for `locatorFor` / `locatorForAll`. */
22
+ static with(options?: FileUploadFileHarnessFilters): HarnessPredicate<FileUploadFileHarness>;
23
+ /**
24
+ * The attached file's name, read from the remove control's accessible name
25
+ * (`Remove <name>`). That is the one place the name is exposed through an
26
+ * accessibility contract rather than through presentational markup.
27
+ */
28
+ getName(): Promise<string>;
29
+ /**
30
+ * The row's full rendered text, whitespace-collapsed.
31
+ *
32
+ * The name and the meta line sit in adjacent `<span>`s with only a
33
+ * whitespace-only text node between them, which Angular strips, so they run
34
+ * together here (`notes.txt10 B`). Prefer {@link getName} and
35
+ * {@link getMetaText} for the parts; this is the raw read that still says
36
+ * something about a row rendered from a projected template.
37
+ */
38
+ getText(): Promise<string>;
39
+ /**
40
+ * The row's meta line — the formatted size, plus the status and error text
41
+ * once the item leaves `pending` (`10 B`, `10 B · Uploading`,
42
+ * `10 B · Failed — <error>`).
43
+ *
44
+ * This string is the only place per-item status and error surface in the
45
+ * DOM: there is no `data-status` hook, and the status otherwise shows up
46
+ * only in Tailwind classes, which a harness must not read. Derived by
47
+ * subtracting {@link getName} from {@link getText} for the same reason.
48
+ */
49
+ getMetaText(): Promise<string>;
50
+ /**
51
+ * Clicks the row's remove control.
52
+ *
53
+ * The component retargets focus in an `afterNextRender` — deliberately, so
54
+ * that the list has re-rendered before focus moves — so the focus assertion
55
+ * a caller makes after this resolves is the post-render one.
56
+ */
57
+ remove(): Promise<void>;
58
+ }
59
+
60
+ /** Filters accepted by `FileUploadHarness.with`. */
61
+ interface FileUploadHarnessFilters extends BaseHarnessFilters {
62
+ /** Match by the control's accessible name (its `aria-label`). */
63
+ label?: string | RegExp;
64
+ /** Match disabled / enabled controls. */
65
+ disabled?: boolean;
66
+ }
67
+ /**
68
+ * Harness for `tw-file-upload`.
69
+ *
70
+ * ## What this harness deliberately cannot do
71
+ *
72
+ * It cannot attach a file. Selecting a file means populating
73
+ * `HTMLInputElement.files`, which is read-only to script and which CDK's
74
+ * `TestElement` — the whole reason a harness runs unchanged against a real
75
+ * browser — has no operation for. The only way to do it is
76
+ * `Object.defineProperty` on the raw DOM node, which exists solely in the
77
+ * Testbed environment. Exposing that would make the harness silently
78
+ * unusable in every other environment, so attaching stays the caller's job:
79
+ * seed files through the bound form control (`writeValue` takes a `File[]`),
80
+ * or through the component's own API, and use this harness for everything
81
+ * downstream of the attachment.
82
+ *
83
+ * Nothing here needs a CDK overlay, so the ordinary fixture loader is enough.
84
+ *
85
+ * Note where the ARIA lives: the host is a `role="group"`, which ARIA 1.2 does
86
+ * not allow to carry `aria-required` / `aria-invalid`, so both sit on the
87
+ * hidden `<input type="file">` — the element that actually owns the value.
88
+ * {@link isRequired} and {@link isInvalid} read them from there;
89
+ * {@link isDisabled} reads `aria-disabled` from the group, which is allowed.
90
+ */
91
+ declare class FileUploadHarness extends ComponentHarness {
92
+ static hostSelector: string;
93
+ /** The hidden native control. It carries the value-owning ARIA and state. */
94
+ private readonly nativeInput;
95
+ /** Predicate for `locatorFor` / `locatorForAll`. */
96
+ static with(options?: FileUploadHarnessFilters): HarnessPredicate<FileUploadHarness>;
97
+ /** The control's accessible name, from `aria-label` when one is set. */
98
+ getLabel(): Promise<string | null>;
99
+ /** Whether the group reports `aria-disabled="true"`. */
100
+ isDisabled(): Promise<boolean>;
101
+ /** Whether the native file input is marked required. */
102
+ isRequired(): Promise<boolean>;
103
+ /** Whether the native file input reports `aria-invalid="true"`. */
104
+ isInvalid(): Promise<boolean>;
105
+ /**
106
+ * Every attached file, in list order. Returns `[]` when nothing is attached
107
+ * — the list element is always rendered, just empty.
108
+ */
109
+ getFiles(filters?: FileUploadFileHarnessFilters): Promise<FileUploadFileHarness[]>;
110
+ /** The name of every attached file, in list order. */
111
+ getFileNames(): Promise<string[]>;
112
+ /**
113
+ * Removes the first attached file whose name matches. Throws when nothing
114
+ * matches, rather than failing silently.
115
+ */
116
+ removeFile(name: string | RegExp): Promise<void>;
117
+ }
118
+
119
+ export { FileUploadFileHarness, FileUploadHarness };
120
+ export type { FileUploadFileHarnessFilters, FileUploadHarnessFilters };
@@ -65,17 +65,17 @@ declare class FileUploadComponent extends FormFieldControl<File[]> implements Co
65
65
  readonly disabledInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
66
66
  /** Marks the control as required. Mirrors to `aria-required`. Also inferred from `Validators.required` on a bound `NgControl`. Defaults to `false`. */
67
67
  readonly requiredInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
68
- /** Headline text rendered inside the drop zone (e.g., `'Drag files here'`). Projected `[twFileUploadHeadline]` content takes precedence over this input. */
68
+ /** Headline text rendered inside the drop zone (e.g., `'Drag files here'`). Projected `[twFileUploadHeadline]` content takes precedence over this input. Defaults to `undefined`. */
69
69
  readonly label: _angular_core.InputSignal<string | undefined>;
70
- /** Secondary text rendered under the label (e.g., `'PDF up to 10MB'`). Projected `[twFileUploadDescription]` content takes precedence. */
70
+ /** Secondary text rendered under the label (e.g., `'PDF up to 10MB'`). Projected `[twFileUploadDescription]` content takes precedence. Defaults to `undefined`. */
71
71
  readonly description: _angular_core.InputSignal<string | undefined>;
72
72
  /** Label rendered inside the trigger button. Defaults to `'Choose files'`. Use `'Choose file'` when `multiple` is `false` (consumer responsibility). */
73
73
  readonly triggerLabel: _angular_core.InputSignal<string>;
74
- /** Accessible name applied to the host when no visible label is projected. Mirrored to `aria-label`. */
74
+ /** Accessible name applied to the host when no visible label is projected. Mirrored to `aria-label`. Defaults to `undefined`. */
75
75
  readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
76
- /** ID of an external element that labels the control. Mirrored to `aria-labelledby`. */
76
+ /** ID of an external element that labels the control. Mirrored to `aria-labelledby`. Defaults to `undefined`. */
77
77
  readonly ariaLabelledby: _angular_core.InputSignal<string | undefined>;
78
- /** ID of an external element that describes the control. Form-field merges its hint/error ids alongside. */
78
+ /** ID of an external element that describes the control. Form-field merges its hint/error ids alongside. Defaults to `undefined`. Alias: `aria-describedby`. */
79
79
  readonly ariaDescribedby: _angular_core.InputSignal<string | undefined>;
80
80
  /** Optional `name` attribute on the hidden `<input type="file">` for native form submissions. */
81
81
  readonly name: _angular_core.InputSignal<string | undefined>;
@@ -92,20 +92,18 @@ declare class FileUploadComponent extends FormFieldControl<File[]> implements Co
92
92
  /** Fires when all files are cleared at once via programmatic `clear()`. Does not fire on `writeValue`, even when the new value is empty. */
93
93
  readonly cleared: _angular_core.OutputEmitterRef<void>;
94
94
  private readonly elementRef;
95
+ private readonly injector;
95
96
  private readonly focusMonitor;
96
97
  private readonly liveAnnouncer;
97
98
  private readonly destroyRef;
98
99
  private readonly ngControl;
99
- private readonly parentForm;
100
- private readonly parentFormGroup;
101
- private readonly defaultMatcher;
102
100
  private readonly itemsSignal;
103
101
  private readonly cvaDisabled;
104
102
  private readonly isDraggingSignal;
105
103
  private readonly dragHasInvalidFilesSignal;
106
104
  private readonly _focused;
107
- private readonly _ngControlRev;
108
- private readonly _formSubmitRev;
105
+ /** @internal Shared `errorState` / `required` / `errors` derivation — see `wireErrorState`. */
106
+ private readonly errorWiring;
109
107
  private readonly describedByIdsSignal;
110
108
  private readonly labelledByIdsSignal;
111
109
  private dragCounter;