@cdevhub/ngx-tw 0.5.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-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 +18 -3
  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 +110 -36
  140. package/theme/_high-contrast-dark.css +367 -0
  141. package/theme/_high-contrast.css +13 -2
  142. package/theme/_light.css +276 -0
  143. package/theme/_semantic.css +47 -12
  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
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, Signal, ElementRef, ViewContainerRef, Injector, ComponentRef, EventEmitter } from '@angular/core';
3
- import { AbstractControl } from '@angular/forms';
3
+ import { AbstractControl, NgControl, ValidatorFn } from '@angular/forms';
4
4
  import { ConnectedPosition, Overlay, ScrollStrategy, OverlayRef } from '@angular/cdk/overlay';
5
5
  import { ComponentType } from '@angular/cdk/portal';
6
6
  import { Observable } from 'rxjs';
@@ -83,6 +83,131 @@ declare const defaultErrorStateMatcher: ErrorStateMatcher;
83
83
  */
84
84
  declare const TW_ERROR_STATE_MATCHER: InjectionToken<ErrorStateMatcher>;
85
85
 
86
+ /**
87
+ * Configuration for {@link wireErrorState}. Every field is a callback rather
88
+ * than a `Signal`, so the options object may reference class members that are
89
+ * declared *below* the `wireErrorState()` call site — the callbacks are only
90
+ * invoked from inside the returned computeds, long after construction.
91
+ */
92
+ interface ErrorStateWiringOptions {
93
+ /**
94
+ * Resolves the host's bound `NgControl`, or `null` when the host is not bound
95
+ * to a form control. Pass a getter rather than the instance so controls that
96
+ * resolve `NgControl` lazily (pickers that self-provide `NG_VALIDATORS` and
97
+ * must defer the lookup to `ngOnInit`) work unchanged. Deliberately *not*
98
+ * injected by this helper: the host owns the `NgControl` reference because it
99
+ * also owns `ControlValueAccessor` registration.
100
+ */
101
+ readonly ngControl: () => NgControl | null;
102
+ /**
103
+ * Reads the host's per-instance `errorStateMatcher` input. When it returns
104
+ * `undefined` the matcher provided under `TW_ERROR_STATE_MATCHER` is used.
105
+ */
106
+ readonly matcher?: () => ErrorStateMatcher | undefined;
107
+ /**
108
+ * Reads the host's `required` input. When it returns `true`,
109
+ * {@link ErrorStateWiring.required} is `true` without consulting validators —
110
+ * the arm that keeps signal forms working, since `cvaControlCreate` writes the
111
+ * `required` input directly and never inspects validators.
112
+ */
113
+ readonly required?: () => boolean;
114
+ /**
115
+ * Validators that mark the control required when present on the bound
116
+ * `NgControl`. Defaults to `[Validators.required]`; boolean controls
117
+ * (`tw-checkbox`, `tw-switch`) also pass `Validators.requiredTrue`.
118
+ */
119
+ readonly requiredValidators?: readonly ValidatorFn[];
120
+ /**
121
+ * Extra reactive sources {@link ErrorStateWiring.errorState} track-reads.
122
+ * Controls pass their focus signal here so a blur — which flips `touched` on
123
+ * the bound control without changing its status or value — repaints the error
124
+ * styling.
125
+ */
126
+ readonly track?: readonly (() => unknown)[];
127
+ /**
128
+ * Short-circuits {@link ErrorStateWiring.errorState}. Return a boolean to use
129
+ * it as the error state without consulting the matcher, or `undefined` to fall
130
+ * through to the matcher. Used by the pickers (a parse or range error is an
131
+ * error regardless of validator status) and by `tw-radio` (a radio inside a
132
+ * group inherits the group's error state). Called after the revision signals
133
+ * are read, so its own reads are tracked normally.
134
+ */
135
+ readonly errorStateOverride?: () => boolean | undefined;
136
+ }
137
+ /** Reactive error-state surface returned by {@link wireErrorState}. */
138
+ interface ErrorStateWiring {
139
+ /**
140
+ * Whether the control should render as invalid, per the resolved
141
+ * {@link ErrorStateMatcher}. Satisfies `FormFieldControl.errorState`.
142
+ */
143
+ readonly errorState: Signal<boolean>;
144
+ /**
145
+ * Whether the control is required — the host's `required` input OR'd with the
146
+ * configured required validators on the bound `NgControl`. Satisfies
147
+ * `FormFieldControl.required`.
148
+ */
149
+ readonly required: Signal<boolean>;
150
+ /**
151
+ * Active validation errors on the bound `NgControl`, or `null` when it reports
152
+ * none or is unbound. Satisfies `FormFieldControl.errors`, which is what
153
+ * `[twError match="…"]` filters on inside a `<tw-form-field>`.
154
+ */
155
+ readonly errors: Signal<Record<string, unknown> | null>;
156
+ /**
157
+ * Revision counter bumped whenever the bound control may have changed. Read it
158
+ * from any other computed that dereferences `NgControl` — typically a
159
+ * `disabled` computed reading `ngControl.disabled` — so that computed
160
+ * invalidates on the same ticks the error state does.
161
+ */
162
+ readonly rev: Signal<number>;
163
+ /**
164
+ * Bumps {@link ErrorStateWiring.rev}. Call it from anywhere the bound control
165
+ * changed without emitting on `statusChanges`/`valueChanges` — a `FocusMonitor`
166
+ * blur that flipped `touched`, `setDisabledState`, or immediately after a
167
+ * deferred `NgControl` lookup.
168
+ */
169
+ bump(): void;
170
+ /**
171
+ * Subscribes to the bound control's `statusChanges`/`valueChanges` and to the
172
+ * parent form's `ngSubmit`. Call this from `ngOnInit`, never the constructor:
173
+ * `NgControl.control` is populated by the parent `FormControl*` directive's own
174
+ * `ngOnChanges`, which runs before children's `ngOnInit` but after their
175
+ * constructors. Teardown is wired to the host's `DestroyRef`.
176
+ */
177
+ connect(): void;
178
+ }
179
+ /**
180
+ * Builds the error-state, required and errors signals every ngx-tw form control
181
+ * exposes to `<tw-form-field>`, plus the revision plumbing that keeps them live.
182
+ *
183
+ * Call it from an injection context (a field initializer or the constructor).
184
+ * It injects `DestroyRef`, `NgForm`/`FormGroupDirective` (both optional) and
185
+ * `TW_ERROR_STATE_MATCHER` on the host's behalf; it does **not** inject
186
+ * `NgControl`, because the host must keep ownership of that reference for
187
+ * `ControlValueAccessor` registration.
188
+ *
189
+ * Wiring an error-state-aware control takes three steps:
190
+ *
191
+ * ```ts
192
+ * private readonly ngControl = inject(NgControl, { optional: true, self: true });
193
+ * private readonly errorWiring = wireErrorState({
194
+ * ngControl: () => this.ngControl,
195
+ * matcher: () => this.errorStateMatcher(),
196
+ * required: () => this.requiredInput(),
197
+ * track: [this._focused],
198
+ * });
199
+ *
200
+ * readonly errorState = this.errorWiring.errorState;
201
+ * readonly required = this.errorWiring.required;
202
+ * readonly errors = this.errorWiring.errors;
203
+ *
204
+ * ngOnInit(): void {
205
+ * this.errorWiring.connect();
206
+ * }
207
+ * ```
208
+ */
209
+ declare function wireErrorState(options: ErrorStateWiringOptions): ErrorStateWiring;
210
+
86
211
  /**
87
212
  * Read-only view of a sortable region's state.
88
213
  *
@@ -184,6 +309,15 @@ interface PickerOpenConfig<TOverlay> {
184
309
  readonly panelClass: string;
185
310
  /** Viewport margin forwarded to the CDK position-strategy. Defaults to `8`. */
186
311
  readonly viewportMargin?: number;
312
+ /**
313
+ * Whether keyboard focus is trapped inside the overlay while it is open.
314
+ * Defaults to `true`, which suits modal picker panels that move DOM focus
315
+ * into the overlay. Pass `false` for `aria-activedescendant` surfaces
316
+ * (`tw-select`, `tw-combobox`) where DOM focus deliberately stays on the
317
+ * trigger: the trap's capturing anchor elements would otherwise sit in the
318
+ * tab order around a panel that holds no focusable content.
319
+ */
320
+ readonly focusTrap?: boolean;
187
321
  }
188
322
  /** Synchronous return shape of {@link PickerOverlayCoordinator.open}. */
189
323
  interface PickerOpenResult<TOverlay> {
@@ -199,18 +333,23 @@ interface PickerOpenResult<TOverlay> {
199
333
  /**
200
334
  * Coordinator that owns the CDK `OverlayRef`, focus trap, panel-id, and
201
335
  * animation timing for an overlay-bearing form control. Consumed by
202
- * `DatePickerComponent` and `DateRangePickerComponent`; both pickers register
203
- * the coordinator at the component level (`providers: [PickerOverlayCoordinator]`)
204
- * so each picker instance owns its own coordinator state.
336
+ * `DatePickerComponent`, `DateRangePickerComponent`, `SelectComponent` and
337
+ * `ComboboxComponent`; every consumer registers the coordinator at the
338
+ * component level (`providers: [PickerOverlayCoordinator]`) so each instance
339
+ * owns its own coordinator state.
205
340
  *
206
341
  * Per the library "no `providedIn: 'root'` for services" rule (see
207
342
  * `.claude/CLAUDE.md` → "What NOT To Do"): the coordinator holds per-overlay
208
343
  * `OverlayRef` / `FocusTrap` state and MUST be component-scoped.
209
344
  *
210
345
  * Scope of responsibility:
211
- * - Create / dispose the CDK `OverlayRef`.
346
+ * - Create / dispose the CDK `OverlayRef`. The ref is **disposed** on close and
347
+ * rebuilt on the next open, so every creation-time value (`positions`,
348
+ * `scrollStrategy`, `panelClass`, and the position strategy's origin) is
349
+ * re-read on every open. Nothing here is frozen at first open.
212
350
  * - Attach a `ComponentPortal` and return the instance.
213
- * - Set up / tear down a `FocusTrap` around the overlay element.
351
+ * - Set up / tear down a `FocusTrap` around the overlay element, unless the
352
+ * consumer opts out via `focusTrap: false`.
214
353
  * - Emit `opened$` after the enter animation completes (closes the
215
354
  * synchronous-emit bug previously present in both pickers).
216
355
  * - Expose `backdropClick$` / `overlayKeydown$` / `escape$` streams scoped
@@ -219,7 +358,11 @@ interface PickerOpenResult<TOverlay> {
219
358
  * never touch a detached `OverlayRef` (mirrors the S14 command-palette
220
359
  * pattern).
221
360
  *
222
- * Out of scope (stays in the consuming picker):
361
+ * Out of scope (stays in the consuming component):
362
+ * - Panel width. `select` / `combobox` size their panel from a trigger
363
+ * measurement that only they can make (which of several host children is the
364
+ * measurable trigger differs per component), so they call
365
+ * `ref()?.updateSize(...)` themselves and own their `ResizeObserver`.
223
366
  * - "Restore previous value on close" — semantics differ per picker.
224
367
  * - Per-picker portal callbacks (calendar selection, action-bar buttons).
225
368
  * - View-mode change-detection nudges (the range-picker calls
@@ -648,18 +791,6 @@ declare const tabTriggerVariants: tailwind_variants.TVReturnType<{
648
791
  }, undefined, {
649
792
  twMerge: true;
650
793
  }, unknown, unknown, undefined>>;
651
- /** @internal Active trigger classes for horizontal underline variants, keyed by color. */
652
- declare const UNDERLINE_ACTIVE_HORIZONTAL: Record<TwColor, string>;
653
- /** @internal Active trigger classes for vertical underline variants, keyed by color. */
654
- declare const UNDERLINE_ACTIVE_VERTICAL: Record<TwColor, string>;
655
- /** @internal Active trigger classes for horizontal enclosed variants, keyed by color. */
656
- declare const ENCLOSED_ACTIVE_HORIZONTAL: Record<TwColor, string>;
657
- /** @internal Active trigger classes for vertical enclosed variants, keyed by color. */
658
- declare const ENCLOSED_ACTIVE_VERTICAL: Record<TwColor, string>;
659
- /** @internal Active trigger classes for pill variants, keyed by color. */
660
- declare const PILL_ACTIVE: Record<TwColor, string>;
661
- /** @internal Inactive trigger classes keyed by variant. */
662
- declare const INACTIVE_TRIGGER_CLASSES: Record<TabTriggerVariant, string>;
663
794
  /**
664
795
  * Returns the active-state trigger class string for the given variant, color,
665
796
  * and orientation. Tab-nav callers pass `'horizontal'` since it is horizontal-only.
@@ -715,5 +846,5 @@ declare function parseField(text: string): number | null;
715
846
  /** Total seconds since midnight for a (h, m, s) tuple — useful for min/max compare. */
716
847
  declare function timeOfDaySeconds(hour: number, minute: number, second: number): number;
717
848
 
718
- export { AriaIdQueue, ENCLOSED_ACTIVE_HORIZONTAL, ENCLOSED_ACTIVE_VERTICAL, INACTIVE_TRIGGER_CLASSES, OVERLAY_ANIMATION_FALLBACK_PADDING, OverlayContainerCoordinator, PICKER_ENTER_DURATION, PICKER_LEAVE_DURATION, PILL_ACTIVE, PickerOverlayCoordinator, TW_ERROR_STATE_MATCHER, TW_SORT_HANDLE, UNDERLINE_ACTIVE_HORIZONTAL, UNDERLINE_ACTIVE_VERTICAL, appendDigit, buildSelectLikePositions, clamp, coerceOverlayDuration, consumeOverlayEscape, defaultErrorStateMatcher, fieldMax, fieldMin, from12h, getActiveTriggerClasses, getInactiveTriggerClasses, isTerminalDigit, mergeOverlayPanelClass, padTwo, parseField, resolveSelectScrollStrategy, stepWithWrap, tabTriggerVariants, timeOfDaySeconds, to12h };
719
- export type { ErrorStateMatcher, OverlayContainerAnimationEvent, OverlayContainerState, PickerOpenConfig, PickerOpenResult, RangeBehaviorConfig, SelectScrollStrategyName, TabTriggerVariant, TimePickerFormat, TimePickerMeridiem, TwBreakpoint, TwColor, TwFormSubmitted, TwOrientation, TwSize, TwSortHandle };
849
+ export { AriaIdQueue, OVERLAY_ANIMATION_FALLBACK_PADDING, OverlayContainerCoordinator, PICKER_ENTER_DURATION, PICKER_LEAVE_DURATION, PickerOverlayCoordinator, TW_ERROR_STATE_MATCHER, TW_SORT_HANDLE, appendDigit, buildSelectLikePositions, clamp, coerceOverlayDuration, consumeOverlayEscape, defaultErrorStateMatcher, fieldMax, fieldMin, from12h, getActiveTriggerClasses, getInactiveTriggerClasses, isTerminalDigit, mergeOverlayPanelClass, padTwo, parseField, resolveSelectScrollStrategy, stepWithWrap, tabTriggerVariants, timeOfDaySeconds, to12h, wireErrorState };
850
+ export type { ErrorStateMatcher, ErrorStateWiring, ErrorStateWiringOptions, OverlayContainerAnimationEvent, OverlayContainerState, PickerOpenConfig, PickerOpenResult, RangeBehaviorConfig, SelectScrollStrategyName, TabTriggerVariant, TimePickerFormat, TimePickerMeridiem, TwBreakpoint, TwColor, TwFormSubmitted, TwOrientation, TwSize, TwSortHandle };
@@ -0,0 +1,141 @@
1
+ import { ComponentHarness, BaseHarnessFilters, HarnessPredicate } from '@angular/cdk/testing';
2
+ import { CalendarHarness } from '@cdevhub/ngx-tw/calendar/testing';
3
+
4
+ /** Filters accepted by `DatePickerHarness.with`. */
5
+ interface DatePickerHarnessFilters extends BaseHarnessFilters {
6
+ /** Match by the text input's accessible name. */
7
+ label?: string | RegExp;
8
+ /** Match by the text currently displayed in the input. */
9
+ value?: string | RegExp;
10
+ /** Match disabled / enabled pickers. */
11
+ disabled?: boolean;
12
+ }
13
+ /**
14
+ * Harness for `tw-date-picker`.
15
+ *
16
+ * `tw-date-picker` splits its trigger across **two** elements and the
17
+ * distinction matters for every method here:
18
+ *
19
+ * - `input[role="combobox"]` carries the displayed text, `aria-required`,
20
+ * `aria-invalid` and `aria-disabled`. `getValue`, `setValue`, `getLabel`,
21
+ * `isRequired`, `isInvalid` and `isDisabled` all read it.
22
+ * - a sibling `button[aria-haspopup="dialog"]` opens the calendar. `open`,
23
+ * `close` and `isOpen` go through it.
24
+ *
25
+ * The calendar renders into the CDK overlay, outside the `tw-date-picker`
26
+ * host, so it is resolved through `documentRootLocatorFactory()`. A consumer
27
+ * loads this harness from the ordinary fixture loader — no
28
+ * `documentRootLoader` ceremony required.
29
+ *
30
+ * Day-grid navigation is not reimplemented here: `getCalendar()` returns the
31
+ * `CalendarHarness` from `@cdevhub/ngx-tw/calendar/testing`, which already
32
+ * owns cells, view switching and header paging.
33
+ *
34
+ * **Not usable with a projected `[slot=trigger]`.** That opts the component out
35
+ * of its default chrome, so neither the text input nor the trigger button is
36
+ * rendered and every method here fails to resolve its element. A custom trigger
37
+ * is whatever the consumer projected; drive it with their own harness or a
38
+ * plain DOM query.
39
+ */
40
+ declare class DatePickerHarness extends ComponentHarness {
41
+ static hostSelector: string;
42
+ private readonly input;
43
+ private readonly trigger;
44
+ /**
45
+ * The inline clear control — the only button in the default trigger chrome
46
+ * that is not the calendar trigger. A consumer projecting `[slot=trigger]`
47
+ * replaces that chrome entirely, so neither this nor `trigger` resolves then.
48
+ */
49
+ private readonly clearButton;
50
+ /** Resolves the overlay's calendar, which lives outside this harness's host. */
51
+ private readonly calendar;
52
+ /** Predicate for `locatorFor` / `locatorForAll`. */
53
+ static with(options?: DatePickerHarnessFilters): HarnessPredicate<DatePickerHarness>;
54
+ /** The text input's accessible name, from `aria-label` when one is set. */
55
+ getLabel(): Promise<string | null>;
56
+ /**
57
+ * The formatted date currently shown in the text input. Empty string when no
58
+ * date is selected — the placeholder is not part of the value.
59
+ */
60
+ getValue(): Promise<string>;
61
+ /** The text input's `placeholder`, or `null` when none is set. */
62
+ getPlaceholder(): Promise<string | null>;
63
+ /**
64
+ * Types `value` into the text input and blurs, which is what commits it —
65
+ * `tw-date-picker` parses on blur (and on Enter), never on keystroke. An
66
+ * unparseable string commits `null` and puts the control in its parse-error
67
+ * state, exactly as it would for a user.
68
+ */
69
+ setValue(value: string): Promise<void>;
70
+ /** Whether the calendar overlay is open, read from the trigger's `aria-expanded`. */
71
+ isOpen(): Promise<boolean>;
72
+ /** Whether the text input reports `aria-disabled="true"`. */
73
+ isDisabled(): Promise<boolean>;
74
+ /** Whether the text input reports `aria-invalid="true"`. */
75
+ isInvalid(): Promise<boolean>;
76
+ /**
77
+ * Whether the text input reports `aria-required="true"`. Reflects the
78
+ * `required` input *and* a `Validators.required` on a bound control.
79
+ */
80
+ isRequired(): Promise<boolean>;
81
+ /**
82
+ * Opens the calendar overlay by clicking the trigger button. No-op when
83
+ * already open; a disabled picker ignores it, as it does in the browser.
84
+ */
85
+ open(): Promise<void>;
86
+ /**
87
+ * Closes the calendar overlay by clicking the trigger button again. No-op
88
+ * when already closed.
89
+ *
90
+ * Deliberately not Escape: `tw-date-picker` treats Escape as *cancel* and
91
+ * restores the value the overlay opened with, which would make `close()`
92
+ * silently undo a selection. The trigger toggles without that side effect.
93
+ *
94
+ * The overlay runs a leave animation before it detaches, so `isOpen()` flips
95
+ * to `false` immediately while the panel element lingers for a few more
96
+ * frames. Two consequences worth knowing:
97
+ *
98
+ * - Do not assert `getCalendar()` is `null` on the tick after a close; the
99
+ * old panel is still mounted.
100
+ * - An `open()` inside that window does **not** attach a fresh panel — the
101
+ * component sees an overlay ref it has not disposed yet and silently
102
+ * keeps the outgoing one. Let the animation finish before reopening.
103
+ */
104
+ close(): Promise<void>;
105
+ /**
106
+ * The `CalendarHarness` for the open overlay, or `null` when no overlay is
107
+ * attached. Use it for anything grid-shaped — paging months, switching to the
108
+ * year view, reading disabled cells.
109
+ */
110
+ getCalendar(): Promise<CalendarHarness | null>;
111
+ /**
112
+ * Opens the overlay if needed and clicks the calendar cell whose text matches
113
+ * `day` exactly (`'15'`, not `'April 15'`). Throws when no such cell is
114
+ * visible in the current view.
115
+ *
116
+ * With `showActions` off this commits and closes; with it on the pick stays
117
+ * pending until {@link clickAction} confirms it.
118
+ */
119
+ selectDay(day: string): Promise<void>;
120
+ /**
121
+ * Clicks a button in the overlay's action bar (`Today`, `Clear`, `Cancel`,
122
+ * `Apply`) by its visible text. Matching on text rather than position is what
123
+ * keeps this usable when a consumer relabels the actions via `todayLabel` and
124
+ * friends — pass whatever label you configured.
125
+ *
126
+ * Preset entries are excluded: they are `role="option"`, not action buttons.
127
+ * Throws when the overlay is closed or nothing matches.
128
+ */
129
+ clickAction(label: string | RegExp): Promise<void>;
130
+ /**
131
+ * Whether the inline clear control is rendered. It appears only while
132
+ * `showClear` is on, the picker is enabled and not readonly, and a value is
133
+ * set.
134
+ */
135
+ hasClearButton(): Promise<boolean>;
136
+ /** Clicks the inline clear control. Throws when none is rendered. */
137
+ clear(): Promise<void>;
138
+ }
139
+
140
+ export { DatePickerHarness };
141
+ export type { DatePickerHarnessFilters };
@@ -79,23 +79,23 @@ declare class DatePickerComponent<D = Date> extends FormFieldControl<D> implemen
79
79
  readonly minDate: _angular_core.InputSignal<D | null>;
80
80
  /** Maximum selectable date. Typed input later than this commits the value and marks the bound control invalid with `calendarMaxDate`; the calendar disables the cell. Defaults to `null`. */
81
81
  readonly maxDate: _angular_core.InputSignal<D | null>;
82
- /** Per-date predicate — return `false` to disable. Applied in the calendar, the text-parse path, and the `calendarDisabledDate` validation error. */
82
+ /** Per-date predicate — return `false` to disable. Applied in the calendar, the text-parse path, and the `calendarDisabledDate` validation error. Defaults to `null`. */
83
83
  readonly dateFilter: _angular_core.InputSignal<DateFilterFn<D> | null>;
84
84
  /** Which calendar view opens first — `'day'`, `'month'`, or `'year'`. Defaults to `'day'`. */
85
85
  readonly startView: _angular_core.InputSignal<CalendarViewState>;
86
- /** Date to focus when the calendar opens with no selection. Falls back to today. */
86
+ /** Date to focus when the calendar opens with no selection. Falls back to today. Defaults to `null`. */
87
87
  readonly startAt: _angular_core.InputSignal<D | null>;
88
88
  /** Display format passed to `DateAdapter.format()`. With the default adapter, accepts `{ dateTimeFormat: Intl.DateTimeFormatOptions }`. When `withTime` is true and this is left at the default, hour/minute (and optional seconds) are folded in automatically. */
89
89
  readonly format: _angular_core.InputSignal<unknown>;
90
90
  /** Optional format hint passed to `DateAdapter.parse()`. Ignored by the native adapter. */
91
91
  readonly parseFormat: _angular_core.InputSignal<unknown>;
92
- /** Placeholder text shown in the input when no value is entered. */
92
+ /** Placeholder text shown in the input when no value is entered. Defaults to `undefined`. */
93
93
  readonly placeholder: _angular_core.InputSignal<string | undefined>;
94
94
  /** When true, the input is disabled, the trigger cannot open the calendar, and `aria-disabled="true"` is set. Defaults to `false`. */
95
95
  readonly disabledInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
96
96
  /** When true, exposes `aria-required="true"`. Validators.required on a bound NgControl is also honoured. Defaults to `false`. */
97
97
  readonly requiredInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
98
- /** When true, blocks typing but still allows picking via the calendar trigger. Defaults to `false`. */
98
+ /** When true, blocks typing but still allows picking via the calendar trigger. Defaults to `false`. Alias: `readonly`. */
99
99
  readonly readonlyInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
100
100
  /** Trigger padding, font size, and calendar cell density. Defaults to `'md'`. */
101
101
  readonly size: _angular_core.InputSignal<TwSize>;
@@ -103,21 +103,21 @@ declare class DatePickerComponent<D = Date> extends FormFieldControl<D> implemen
103
103
  readonly color: _angular_core.InputSignal<TwColor>;
104
104
  /** Visual style of the trigger. `'default'` draws its own border; `'naked'` strips chrome. Auto-resolves to `'naked'` when inside `<tw-form-field>`. */
105
105
  readonly variant: _angular_core.InputSignal<DatePickerVariant | undefined>;
106
- /** Whether to show a clear-button affordance inside the trigger when a value is set. Defaults to `true`. */
106
+ /** 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. */
107
107
  readonly showClear: _angular_core.InputSignal<boolean>;
108
108
  /** When true, renders a `Today / Clear / Cancel / Apply` action bar at the bottom of the overlay. Defaults to `false`. */
109
109
  readonly showActions: _angular_core.InputSignal<boolean>;
110
- /** Label for the `Today` action in the overlay's action bar. */
110
+ /** Label for the `Today` action in the overlay's action bar. Defaults to `'Today'`. */
111
111
  readonly todayLabel: _angular_core.InputSignal<string>;
112
- /** Label for the `Clear` action in the overlay's action bar. */
112
+ /** Label for the `Clear` action in the overlay's action bar. Defaults to `'Clear'`. */
113
113
  readonly clearLabel: _angular_core.InputSignal<string>;
114
- /** Label for the `Cancel` action in the overlay's action bar. */
114
+ /** Label for the `Cancel` action in the overlay's action bar. Defaults to `'Cancel'`. */
115
115
  readonly cancelLabel: _angular_core.InputSignal<string>;
116
- /** Label for the `Apply` action in the overlay's action bar. */
116
+ /** Label for the `Apply` action in the overlay's action bar. Defaults to `'Apply'`. */
117
117
  readonly applyLabel: _angular_core.InputSignal<string>;
118
118
  /** When true, focusing the text input opens the overlay. Defaults to `false`. */
119
119
  readonly openOnFocus: _angular_core.InputSignal<boolean>;
120
- /** Extra class(es) applied to the overlay panel element. */
120
+ /** Extra class(es) applied to the overlay panel element. Defaults to an empty string. */
121
121
  readonly panelClass: _angular_core.InputSignal<string | readonly string[]>;
122
122
  /** CDK scroll strategy for the overlay. Defaults to `'reposition'`. */
123
123
  readonly scrollStrategy: _angular_core.InputSignal<"reposition" | "close" | "block">;
@@ -125,33 +125,35 @@ declare class DatePickerComponent<D = Date> extends FormFieldControl<D> implemen
125
125
  readonly offset: _angular_core.InputSignal<number>;
126
126
  /** Accessible name for the calendar trigger button. Defaults to `'Open calendar'`. */
127
127
  readonly triggerAriaLabel: _angular_core.InputSignal<string>;
128
+ /** Accessible name for the inline clear button shown when a value is set. Mirrors `tw-date-range-picker`'s input of the same name; distinct from `clearLabel`, which is the overlay action bar's visible button text. Defaults to `'Clear date'`. */
129
+ readonly clearAriaLabel: _angular_core.InputSignal<string>;
128
130
  /**
129
131
  * Bundles the time-of-day configuration. Passing a non-null object turns on the embedded `<tw-time-picker>` and forwards each field.
130
132
  *
131
133
  * Defaults to `null` (no time field). Pass an empty object `{}` to enable the time picker with all defaults.
132
134
  */
133
135
  readonly timeConfig: _angular_core.InputSignal<DatePickerTimeConfig<D> | null>;
134
- /** Per-instance locale override. Forwarded to the embedded calendar and the underlying `DateAdapter` for parse/format. Falls back to Angular `LOCALE_ID` when `null`. */
136
+ /** Per-instance locale override. Forwarded to the embedded calendar and the underlying `DateAdapter` for parse/format. Falls back to Angular `LOCALE_ID` when `null`. Defaults to `null`. */
135
137
  readonly locale: _angular_core.InputSignal<string | null>;
136
- /** Function producing per-cell CSS classes, forwarded to the embedded calendar. Useful for visually marking special dates (holidays, billing cycles). */
138
+ /** Function producing per-cell CSS classes, forwarded to the embedded calendar. Useful for visually marking special dates (holidays, billing cycles). Defaults to `null`. */
137
139
  readonly dateClass: _angular_core.InputSignal<DateClassFn<D> | null>;
138
- /** Optional cell-content template, forwarded to the embedded calendar. Use to customize cell visuals beyond `dateClass`. */
140
+ /** Optional cell-content template, forwarded to the embedded calendar. Use to customize cell visuals beyond `dateClass`. Defaults to `null`. */
139
141
  readonly cellTemplate: _angular_core.InputSignal<TemplateRef<{
140
142
  $implicit: CalendarCell<D>;
141
143
  }> | null>;
142
- /** Optional quick-select presets rendered as a vertical list before the calendar. Each preset provides a `label` and a `date` factory. An empty array hides the preset panel. */
144
+ /** Optional quick-select presets rendered as a vertical list before the calendar. Each preset provides a `label` and a `date` factory. An empty array hides the preset panel. Defaults to an empty array. */
143
145
  readonly presets: _angular_core.InputSignal<readonly DatePickerPreset<D>[]>;
144
- /** Per-instance override of the `ErrorStateMatcher`. */
146
+ /** Per-instance override of the `ErrorStateMatcher`. Defaults to `undefined`. */
145
147
  readonly errorStateMatcher: _angular_core.InputSignal<ErrorStateMatcher | undefined>;
146
- /** Accessible name for the input. Required when no visible label is supplied. Alias: `aria-label`. */
148
+ /** Accessible name for the input. Required when no visible label is supplied. Alias: `aria-label`. Defaults to `undefined`. */
147
149
  readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
148
- /** ID of an external element that labels the input. Alias: `aria-labelledby`. */
150
+ /** ID of an external element that labels the input. Alias: `aria-labelledby`. Defaults to `undefined`. */
149
151
  readonly ariaLabelledby: _angular_core.InputSignal<string | undefined>;
150
- /** Consumer-supplied `aria-describedby` ids. The form-field preserves these when merging hint/error ids. Alias: `aria-describedby`. */
152
+ /** Consumer-supplied `aria-describedby` ids. The form-field preserves these when merging hint/error ids. Alias: `aria-describedby`. Defaults to `undefined`. */
151
153
  readonly userAriaDescribedByInput: _angular_core.InputSignal<string | undefined>;
152
- /** Two-way bound selected date. `null` when no selection. Setting programmatically updates the display; does NOT trigger `onChange`. */
154
+ /** Two-way bound selected date. `null` when no selection. Setting programmatically updates the display; does NOT trigger `onChange`. Defaults to `null`. */
153
155
  readonly value: _angular_core.ModelSignal<D | null>;
154
- /** Two-way bound open state of the calendar overlay. */
156
+ /** Two-way bound open state of the calendar overlay. Defaults to `false`. */
155
157
  readonly open: _angular_core.ModelSignal<boolean>;
156
158
  /** Fires after the overlay's enter animation completes. Payload is the trigger element. */
157
159
  readonly opened: _angular_core.OutputEmitterRef<DatePickerOpenedEvent>;
@@ -174,9 +176,6 @@ declare class DatePickerComponent<D = Date> extends FormFieldControl<D> implemen
174
176
  private readonly destroyRef;
175
177
  private readonly formField;
176
178
  private ngControl;
177
- private readonly parentForm;
178
- private readonly parentFormGroup;
179
- private readonly defaultMatcher;
180
179
  private readonly inputRef;
181
180
  private readonly triggerRef;
182
181
  /** @internal Whether a `[slot=trigger]` is projected. Detected post-mount via DOM query so we can drop the default chrome. */
@@ -219,17 +218,17 @@ declare class DatePickerComponent<D = Date> extends FormFieldControl<D> implemen
219
218
  readonly focusedSignal: _angular_core.WritableSignal<boolean>;
220
219
  private readonly cvaDisabled;
221
220
  private readonly describedByIdsSignal;
222
- private readonly closingSignal;
223
221
  private readonly lastValueBeforeOpen;
224
222
  private readonly pendingCalendarValue;
225
223
  private readonly activePresetIdSignal;
226
- private readonly _ngControlRev;
227
- private readonly _formSubmitRev;
224
+ /** @internal Shared `errorState` / `required` / `errors` derivation — see `wireErrorState`. */
225
+ private readonly errorWiring;
228
226
  private onChange;
229
227
  private onTouched;
230
- private readonly overlayInstanceSignal;
228
+ private overlayInstance;
229
+ private closing;
231
230
  private returnFocusTo;
232
- private get overlayInstance();
231
+ private readonly isAttached;
233
232
  /** @internal */
234
233
  readonly isDisabled: Signal<boolean>;
235
234
  /** @internal Effective variant — auto-naked when wrapped in tw-form-field. */
@@ -270,6 +269,15 @@ declare class DatePickerComponent<D = Date> extends FormFieldControl<D> implemen
270
269
  readonly required: Signal<boolean>;
271
270
  /** @internal */
272
271
  readonly errorState: Signal<boolean>;
272
+ /**
273
+ * @internal Active validation errors map from the bound `NgControl` (or `null` when the
274
+ * control reports none / is unbound). This is what `[twError match="…"]` filters on inside a
275
+ * `<tw-form-field>`; without it every `match`-targeted message — including the
276
+ * `calendarMinDate` / `calendarMaxDate` / `calendarDisabledDate` / `calendarInvalidValue`
277
+ * codes this component's `NG_VALIDATORS` apparatus exists to produce — stays permanently
278
+ * hidden. (Authoritative key list: `CalendarValidationErrors` in `calendar.types.ts`.)
279
+ */
280
+ readonly errors: Signal<Record<string, unknown> | null>;
273
281
  /** @internal */
274
282
  readonly controlType = "date-picker";
275
283
  /** @internal */
@@ -336,7 +344,7 @@ declare class DatePickerComponent<D = Date> extends FormFieldControl<D> implemen
336
344
  /** @internal */
337
345
  onContainerClick(event: MouseEvent): void;
338
346
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DatePickerComponent<any>, never>;
339
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DatePickerComponent<any>, "tw-date-picker", never, { "idInput": { "alias": "id"; "required": false; "isSignal": true; }; "minDate": { "alias": "minDate"; "required": false; "isSignal": true; }; "maxDate": { "alias": "maxDate"; "required": false; "isSignal": true; }; "dateFilter": { "alias": "dateFilter"; "required": false; "isSignal": true; }; "startView": { "alias": "startView"; "required": false; "isSignal": true; }; "startAt": { "alias": "startAt"; "required": false; "isSignal": true; }; "format": { "alias": "format"; "required": false; "isSignal": true; }; "parseFormat": { "alias": "parseFormat"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "disabledInput": { "alias": "disabled"; "required": false; "isSignal": true; }; "requiredInput": { "alias": "required"; "required": false; "isSignal": true; }; "readonlyInput": { "alias": "readonly"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "showClear": { "alias": "showClear"; "required": false; "isSignal": true; }; "showActions": { "alias": "showActions"; "required": false; "isSignal": true; }; "todayLabel": { "alias": "todayLabel"; "required": false; "isSignal": true; }; "clearLabel": { "alias": "clearLabel"; "required": false; "isSignal": true; }; "cancelLabel": { "alias": "cancelLabel"; "required": false; "isSignal": true; }; "applyLabel": { "alias": "applyLabel"; "required": false; "isSignal": true; }; "openOnFocus": { "alias": "openOnFocus"; "required": false; "isSignal": true; }; "panelClass": { "alias": "panelClass"; "required": false; "isSignal": true; }; "scrollStrategy": { "alias": "scrollStrategy"; "required": false; "isSignal": true; }; "offset": { "alias": "offset"; "required": false; "isSignal": true; }; "triggerAriaLabel": { "alias": "triggerAriaLabel"; "required": false; "isSignal": true; }; "timeConfig": { "alias": "timeConfig"; "required": false; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "dateClass": { "alias": "dateClass"; "required": false; "isSignal": true; }; "cellTemplate": { "alias": "cellTemplate"; "required": false; "isSignal": true; }; "presets": { "alias": "presets"; "required": false; "isSignal": true; }; "errorStateMatcher": { "alias": "errorStateMatcher"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "ariaLabelledby": { "alias": "aria-labelledby"; "required": false; "isSignal": true; }; "userAriaDescribedByInput": { "alias": "aria-describedby"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "open": "openChange"; "opened": "opened"; "closed": "closed"; "dateInput": "dateInput"; "dateChange": "dateChange"; "presetSelected": "presetSelected"; }, never, ["[slot=trigger]", "[slot=trigger-icon]"], true, never>;
347
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DatePickerComponent<any>, "tw-date-picker", never, { "idInput": { "alias": "id"; "required": false; "isSignal": true; }; "minDate": { "alias": "minDate"; "required": false; "isSignal": true; }; "maxDate": { "alias": "maxDate"; "required": false; "isSignal": true; }; "dateFilter": { "alias": "dateFilter"; "required": false; "isSignal": true; }; "startView": { "alias": "startView"; "required": false; "isSignal": true; }; "startAt": { "alias": "startAt"; "required": false; "isSignal": true; }; "format": { "alias": "format"; "required": false; "isSignal": true; }; "parseFormat": { "alias": "parseFormat"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "disabledInput": { "alias": "disabled"; "required": false; "isSignal": true; }; "requiredInput": { "alias": "required"; "required": false; "isSignal": true; }; "readonlyInput": { "alias": "readonly"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "showClear": { "alias": "showClear"; "required": false; "isSignal": true; }; "showActions": { "alias": "showActions"; "required": false; "isSignal": true; }; "todayLabel": { "alias": "todayLabel"; "required": false; "isSignal": true; }; "clearLabel": { "alias": "clearLabel"; "required": false; "isSignal": true; }; "cancelLabel": { "alias": "cancelLabel"; "required": false; "isSignal": true; }; "applyLabel": { "alias": "applyLabel"; "required": false; "isSignal": true; }; "openOnFocus": { "alias": "openOnFocus"; "required": false; "isSignal": true; }; "panelClass": { "alias": "panelClass"; "required": false; "isSignal": true; }; "scrollStrategy": { "alias": "scrollStrategy"; "required": false; "isSignal": true; }; "offset": { "alias": "offset"; "required": false; "isSignal": true; }; "triggerAriaLabel": { "alias": "triggerAriaLabel"; "required": false; "isSignal": true; }; "clearAriaLabel": { "alias": "clearAriaLabel"; "required": false; "isSignal": true; }; "timeConfig": { "alias": "timeConfig"; "required": false; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "dateClass": { "alias": "dateClass"; "required": false; "isSignal": true; }; "cellTemplate": { "alias": "cellTemplate"; "required": false; "isSignal": true; }; "presets": { "alias": "presets"; "required": false; "isSignal": true; }; "errorStateMatcher": { "alias": "errorStateMatcher"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "ariaLabelledby": { "alias": "aria-labelledby"; "required": false; "isSignal": true; }; "userAriaDescribedByInput": { "alias": "aria-describedby"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "open": "openChange"; "opened": "opened"; "closed": "closed"; "dateInput": "dateInput"; "dateChange": "dateChange"; "presetSelected": "presetSelected"; }, never, ["[slot=trigger]", "[slot=trigger-icon]"], true, never>;
340
348
  }
341
349
 
342
350
  export { DatePickerComponent };