@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
@@ -1 +1 @@
1
- {"version":3,"file":"cdevhub-ngx-tw-core.mjs","sources":["../../../projects/ngx-tw/core/error-state-matcher.ts","../../../projects/ngx-tw/core/sort-handle.ts","../../../projects/ngx-tw/core/overlay/positions.ts","../../../projects/ngx-tw/core/overlay/scroll-strategy.ts","../../../projects/ngx-tw/core/overlay/escape.ts","../../../projects/ngx-tw/core/overlay/picker-overlay-coordinator.ts","../../../projects/ngx-tw/core/overlay/overlay-container-helpers.ts","../../../projects/ngx-tw/core/overlay/overlay-container-coordinator.ts","../../../projects/ngx-tw/core/tab-trigger-variants.ts","../../../projects/ngx-tw/core/time-utils.ts","../../../projects/ngx-tw/core/cdevhub-ngx-tw-core.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport type { AbstractControl } from '@angular/forms';\n\n/**\n * Minimal contract for a parent form's \"submitted\" state. Both `NgForm` and\n * `FormGroupDirective` satisfy this, so the matcher can work with either.\n */\nexport interface TwFormSubmitted {\n readonly submitted: boolean;\n}\n\n/**\n * Strategy that decides when a form control should be rendered in the error\n * state. Controls read the injected matcher (or accept a per-instance\n * override) and combine the result with their own signals. Override at any\n * injector level via {@link TW_ERROR_STATE_MATCHER}.\n */\nexport interface ErrorStateMatcher {\n /** Returns true when the control should display an error. */\n isErrorState(\n control: AbstractControl | null,\n form: TwFormSubmitted | null,\n ): boolean;\n}\n\n/**\n * Default error-state strategy: errored when the control is `invalid` and\n * either has been interacted with (`dirty` or `touched`) or its parent form\n * has been submitted. Matches Material's default behavior.\n */\nexport const defaultErrorStateMatcher: ErrorStateMatcher = {\n isErrorState(control, form) {\n if (!control) {\n return false;\n }\n const interacted = control.dirty || control.touched;\n return !!control.invalid && (interacted || !!form?.submitted);\n },\n};\n\n/**\n * Injection token carrying the {@link ErrorStateMatcher} used by every ngx-tw\n * form control. Defaults to {@link defaultErrorStateMatcher}; provide a\n * different matcher at root to change global error-display policy, or at any\n * descendant injector to scope the change.\n */\nexport const TW_ERROR_STATE_MATCHER = new InjectionToken<ErrorStateMatcher>(\n 'TW_ERROR_STATE_MATCHER',\n {\n providedIn: 'root',\n factory: () => defaultErrorStateMatcher,\n },\n);\n","import { InjectionToken, type Signal } from '@angular/core';\n\n/**\n * Read-only view of a sortable region's state.\n *\n * Components that render column headers (e.g., `<tw-table>`) consume this handle to\n * project `aria-sort` onto the active column without taking a hard dependency on the\n * sort implementation. The canonical provider is `SortDirective` (`[twSort]`).\n */\nexport interface TwSortHandle {\n /** Signal of the id of the currently active sort header, or `null` when no sort is active. */\n readonly active: Signal<string | null>;\n /** Signal of the active sort direction (`'asc'` / `'desc'`), or `null` when cleared. */\n readonly direction: Signal<'asc' | 'desc' | null>;\n}\n\n/**\n * DI token through which sort containers expose their state to consumers. Provided by\n * `SortDirective` (`[twSort]`). Inject with `{ optional: true }` — components that need\n * aria-sort plumbing should degrade gracefully when no sort directive is present.\n */\nexport const TW_SORT_HANDLE = new InjectionToken<TwSortHandle>('TwSortHandle');\n","import type { ConnectedPosition } from '@angular/cdk/overlay';\n\n/**\n * Connected-overlay position list for \"select-like\" overlays — overlays whose\n * panel attaches directly under (or above) a trigger element and falls back to\n * the opposite vertical side when there is not enough room. Returns four\n * fallback positions: below-start, below-end, above-start, above-end.\n *\n * Used by `SelectComponent`, `ComboboxComponent`, `DatePickerComponent`, and\n * `DateRangePickerComponent` — any overlay-bearing form control that anchors\n * a listbox / menu / calendar panel to its trigger. The shape is identical for\n * all four; the historical \"select-like\" name refers to the original consumer.\n *\n * @param offset Vertical offset in pixels applied between the trigger edge and\n * the panel edge. Below-positions use `+offset`; above-positions use\n * `-offset` so the panel pulls away from the trigger consistently.\n */\nexport function buildSelectLikePositions(offset = 0): ConnectedPosition[] {\n return [\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: offset },\n { originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: offset },\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -offset },\n { originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetY: -offset },\n ];\n}\n","import type { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\n\n/** Named scroll-strategy variants supported by select-like overlays. */\nexport type SelectScrollStrategyName = 'reposition' | 'close' | 'block';\n\n/**\n * Maps a named scroll-strategy variant to the corresponding CDK\n * `ScrollStrategy` instance. `'reposition'` is the default for select-like\n * overlays; `'close'` dismisses the panel on scroll; `'block'` locks page\n * scrolling while the panel is open.\n *\n * Used by `SelectComponent`, `ComboboxComponent`, `DatePickerComponent`, and\n * `DateRangePickerComponent` — any overlay-bearing form control that exposes\n * the same three-option scroll-strategy input.\n */\nexport function resolveSelectScrollStrategy(\n name: SelectScrollStrategyName,\n overlay: Overlay,\n): ScrollStrategy {\n switch (name) {\n case 'close':\n return overlay.scrollStrategies.close();\n case 'block':\n return overlay.scrollStrategies.block();\n default:\n return overlay.scrollStrategies.reposition();\n }\n}\n","import type { OverlayRef } from '@angular/cdk/overlay';\nimport { filter } from 'rxjs/operators';\n\n/**\n * Subscribes to overlay-level `Escape` keydown events and invokes `onEscape`\n * for each one. Returns an unsubscribe function so callers can scope teardown\n * to the open lifecycle of the overlay (typically tied into a `Subscription`\n * aggregate or a `takeUntilDestroyed` flow).\n *\n * Listens via `OverlayRef.keydownEvents()` so the handler fires for any\n * keystroke originating inside the overlay, regardless of which element holds\n * DOM focus — useful for select-style overlays whose search/listbox children\n * may receive focus apart from the trigger.\n *\n * Callers remain responsible for calling `event.preventDefault()` /\n * `stopPropagation()` inside `onEscape` if they want to short-circuit further\n * key handling.\n */\nexport function consumeOverlayEscape(\n overlayRef: OverlayRef,\n onEscape: (event: KeyboardEvent) => void,\n): () => void {\n const subscription = overlayRef\n .keydownEvents()\n .pipe(filter((event) => event.key === 'Escape'))\n .subscribe((event) => onEscape(event));\n return () => subscription.unsubscribe();\n}\n","import {\n type ComponentRef,\n DestroyRef,\n type ElementRef,\n inject,\n Injectable,\n type Injector,\n signal,\n type Signal,\n type ViewContainerRef,\n} from '@angular/core';\nimport {\n _IdGenerator,\n FocusTrapFactory,\n} from '@angular/cdk/a11y';\nimport {\n type ConnectedPosition,\n Overlay,\n type OverlayRef,\n type ScrollStrategy,\n} from '@angular/cdk/overlay';\nimport { ComponentPortal, type ComponentType } from '@angular/cdk/portal';\nimport { Subject, type Observable } from 'rxjs';\nimport { filter, takeUntil } from 'rxjs/operators';\n\n/**\n * Enter-animation duration for date-picker / date-range-picker overlays.\n * Matches `theme/_base.css` `.scale-in 140ms` — the keyframe the picker\n * overlays apply via `animate.enter=\"scale-in\"`. The coordinator delays\n * `opened$` emission by this duration so consumers can hook the moment the\n * panel has fully appeared instead of the moment `open()` was called.\n */\nexport const PICKER_ENTER_DURATION = 140;\n\n/**\n * Leave-animation duration for date-picker / date-range-picker overlays.\n * Matches `theme/_base.css` `.scale-out 120ms` — the keyframe the picker\n * overlays apply via `animate.leave=\"scale-out\"`. The coordinator delays\n * overlay detach by this duration so the leave animation can play through.\n */\nexport const PICKER_LEAVE_DURATION = 120;\n\n/** Configuration passed to {@link PickerOverlayCoordinator.open}. */\nexport interface PickerOpenConfig<TOverlay> {\n /** Element used as the connected-overlay origin (typically the picker trigger). */\n readonly origin: ElementRef<HTMLElement>;\n /** Component type to render inside the overlay (e.g. `DatePickerOverlayComponent`). */\n readonly portalComponent: ComponentType<TOverlay>;\n /** View-container that hosts the embedded view; usually the picker's `ViewContainerRef`. */\n readonly viewContainerRef: ViewContainerRef;\n /** Optional injector forwarded to the portal so DI tokens resolve from the picker's tree. */\n readonly injector?: Injector;\n /** Connected-position list — typically the result of `buildSelectLikePositions(offset)`. */\n readonly positions: ConnectedPosition[];\n /** CDK scroll-strategy instance for the overlay. */\n readonly scrollStrategy: ScrollStrategy;\n /** CSS class applied to the CDK overlay-pane element (NOT the panel root). */\n readonly panelClass: string;\n /** Viewport margin forwarded to the CDK position-strategy. Defaults to `8`. */\n readonly viewportMargin?: number;\n}\n\n/** Synchronous return shape of {@link PickerOverlayCoordinator.open}. */\nexport interface PickerOpenResult<TOverlay> {\n /** The CDK `OverlayRef` driving the overlay — exposed for advanced consumers. */\n readonly overlayRef: OverlayRef;\n /** The Angular `ComponentRef` for the attached portal — exposed so consumers may run `detectChanges()` to flush an initial-config push synchronously. */\n readonly componentRef: ComponentRef<TOverlay>;\n /** The instance of the attached portal component. Equivalent to `componentRef.instance`. */\n readonly instance: TOverlay;\n /** Auto-generated id consumers may wire to `aria-controls` / dialog `id`. */\n readonly panelId: string;\n}\n\n/**\n * Coordinator that owns the CDK `OverlayRef`, focus trap, panel-id, and\n * animation timing for an overlay-bearing form control. Consumed by\n * `DatePickerComponent` and `DateRangePickerComponent`; both pickers register\n * the coordinator at the component level (`providers: [PickerOverlayCoordinator]`)\n * so each picker instance owns its own coordinator state.\n *\n * Per the library \"no `providedIn: 'root'` for services\" rule (see\n * `.claude/CLAUDE.md` → \"What NOT To Do\"): the coordinator holds per-overlay\n * `OverlayRef` / `FocusTrap` state and MUST be component-scoped.\n *\n * Scope of responsibility:\n * - Create / dispose the CDK `OverlayRef`.\n * - Attach a `ComponentPortal` and return the instance.\n * - Set up / tear down a `FocusTrap` around the overlay element.\n * - Emit `opened$` after the enter animation completes (closes the\n * synchronous-emit bug previously present in both pickers).\n * - Expose `backdropClick$` / `overlayKeydown$` / `escape$` streams scoped\n * to the current open lifecycle.\n * - Run a leave-animation timer with an `isAttached` guard so close races\n * never touch a detached `OverlayRef` (mirrors the S14 command-palette\n * pattern).\n *\n * Out of scope (stays in the consuming picker):\n * - \"Restore previous value on close\" — semantics differ per picker.\n * - Per-picker portal callbacks (calendar selection, action-bar buttons).\n * - View-mode change-detection nudges (the range-picker calls\n * `changeDetectorRef.detectChanges()` after pushing its initial overlay\n * config; the date-picker does not).\n */\n@Injectable()\nexport class PickerOverlayCoordinator {\n private readonly overlay = inject(Overlay);\n private readonly focusTrapFactory = inject(FocusTrapFactory);\n private readonly destroyRef = inject(DestroyRef);\n private readonly idGenerator = inject(_IdGenerator);\n\n private overlayRef: OverlayRef | null = null;\n private focusTrap: ReturnType<FocusTrapFactory['create']> | null = null;\n private closeTimer: ReturnType<typeof setTimeout> | null = null;\n private openedTimer: ReturnType<typeof setTimeout> | null = null;\n private currentPanelId: string | null = null;\n private currentClose$: Subject<void> | null = null;\n private openedSubject: Subject<void> | null = null;\n\n private readonly attachedSignal = signal(false);\n private readonly openedSignal = signal(false);\n\n /** Whether the overlay is currently attached (between `open()` and detach). */\n readonly attached: Signal<boolean> = this.attachedSignal.asReadonly();\n\n /** Whether the enter animation has completed (`opened$` has fired). */\n readonly opened: Signal<boolean> = this.openedSignal.asReadonly();\n\n constructor() {\n this.destroyRef.onDestroy(() => this.disposeImmediate());\n }\n\n /**\n * Creates and attaches the overlay. Returns the live overlay metadata\n * synchronously; callers should subscribe to {@link opened$} to observe the\n * moment the enter animation completes. Returns `null` if an overlay is\n * already attached.\n */\n open<TOverlay>(config: PickerOpenConfig<TOverlay>): PickerOpenResult<TOverlay> | null {\n if (this.overlayRef) return null;\n\n const positionStrategy = this.overlay\n .position()\n .flexibleConnectedTo(config.origin)\n .withPositions(config.positions)\n .withFlexibleDimensions(false)\n .withPush(false)\n .withViewportMargin(config.viewportMargin ?? 8);\n\n this.overlayRef = this.overlay.create({\n positionStrategy,\n scrollStrategy: config.scrollStrategy,\n hasBackdrop: true,\n backdropClass: 'cdk-overlay-transparent-backdrop',\n panelClass: config.panelClass,\n });\n\n const portal = new ComponentPortal<TOverlay>(\n config.portalComponent,\n config.viewContainerRef,\n config.injector,\n );\n const ref = this.overlayRef.attach(portal);\n const instance = ref.instance;\n\n this.currentPanelId = this.idGenerator.getId('tw-picker-overlay-');\n this.currentClose$ = new Subject<void>();\n this.openedSubject = new Subject<void>();\n this.attachedSignal.set(true);\n this.openedSignal.set(false);\n\n this.setupFocusTrap();\n this.scheduleOpenedEmission();\n\n return {\n overlayRef: this.overlayRef,\n componentRef: ref,\n instance,\n panelId: this.currentPanelId,\n };\n }\n\n /**\n * Starts the close sequence — destroys the focus trap immediately so focus\n * can return to the trigger, then detaches the overlay after the leave\n * animation runs ({@link PICKER_LEAVE_DURATION}). Invokes `onAfterClose`\n * once the overlay is fully detached. No-op if no overlay is open or a\n * close is already in flight.\n *\n * Mirrors the S14 command-palette `isAttached`-guarded close pattern:\n * after the timer fires we re-check `attachedSignal` before touching the\n * overlay so a race (programmatic dispose, double-close) cannot touch a\n * destroyed instance.\n */\n close(onAfterClose: () => void = () => {}): void {\n if (!this.overlayRef || this.closeTimer !== null) return;\n this.destroyFocusTrap();\n this.clearOpenedTimer();\n\n this.closeTimer = setTimeout(() => {\n this.closeTimer = null;\n if (!this.attachedSignal()) {\n // Lost race with disposeImmediate / destroyRef.onDestroy.\n return;\n }\n if (this.overlayRef?.hasAttached()) {\n this.overlayRef.detach();\n }\n // Dispose the OverlayRef so the next open() builds a fresh one with the\n // current inputs (offset, scrollStrategy, panelClass). Without this the\n // `if (this.overlayRef) return null;` guard at the top of open() would\n // permanently block re-opens after the first close.\n this.overlayRef?.dispose();\n this.overlayRef = null;\n this.currentClose$?.next();\n this.currentClose$?.complete();\n this.currentClose$ = null;\n this.openedSubject?.complete();\n this.openedSubject = null;\n this.attachedSignal.set(false);\n this.openedSignal.set(false);\n this.currentPanelId = null;\n onAfterClose();\n }, PICKER_LEAVE_DURATION);\n }\n\n /**\n * Stream of overlay-level backdrop clicks for the current open lifecycle.\n * Completes when the overlay closes.\n */\n backdropClick$(): Observable<MouseEvent> {\n this.assertOpen('backdropClick$');\n return this.overlayRef!.backdropClick().pipe(takeUntil(this.currentClose$!));\n }\n\n /**\n * Stream of overlay-level keydown events for the current open lifecycle.\n * Completes when the overlay closes.\n */\n overlayKeydown$(): Observable<KeyboardEvent> {\n this.assertOpen('overlayKeydown$');\n return this.overlayRef!.keydownEvents().pipe(takeUntil(this.currentClose$!));\n }\n\n /**\n * Stream filtered to `Escape` keydowns inside the overlay for the current\n * open lifecycle. Equivalent to `overlayKeydown$().pipe(filter(e => e.key === 'Escape'))`\n * but spelled out so consumers don't import RxJS operators just for the\n * common case.\n */\n escape$(): Observable<KeyboardEvent> {\n return this.overlayKeydown$().pipe(filter((e) => e.key === 'Escape'));\n }\n\n /**\n * Emits exactly once after the enter animation completes\n * ({@link PICKER_ENTER_DURATION}ms after `open()`). Used by consumers to\n * fire their `opened` output at the moment the overlay panel is actually\n * visible — closes the synchronous-emit bug the pickers carried before\n * this coordinator existed.\n *\n * Completes when the overlay closes.\n */\n opened$(): Observable<void> {\n this.assertOpen('opened$');\n return this.openedSubject!.asObservable().pipe(takeUntil(this.currentClose$!));\n }\n\n /** Exposes the live `OverlayRef` for advanced consumers (e.g. width sync). */\n ref(): OverlayRef | null {\n return this.overlayRef;\n }\n\n /**\n * Exposes the current panel id (auto-generated via CDK `_IdGenerator`,\n * stable for the open lifecycle, reset to `null` on close). Neither\n * consuming picker uses this today — both keep their own\n * `${hostId}-dialog` id for `aria-controls` wiring — but the helper is\n * exposed for future consumers (e.g. a picker wrapper that wants its\n * panel id auto-managed).\n */\n panelId(): string | null {\n return this.currentPanelId;\n }\n\n /**\n * Immediately disposes the overlay and tears down the focus trap without\n * running the leave animation. Called from {@link DestroyRef.onDestroy};\n * consumers should NOT call this — use {@link close} for the user-visible\n * close path.\n */\n private disposeImmediate(): void {\n this.clearCloseTimer();\n this.clearOpenedTimer();\n this.destroyFocusTrap();\n if (this.currentClose$) {\n this.currentClose$.next();\n this.currentClose$.complete();\n this.currentClose$ = null;\n }\n this.openedSubject?.complete();\n this.openedSubject = null;\n this.overlayRef?.dispose();\n this.overlayRef = null;\n this.attachedSignal.set(false);\n this.openedSignal.set(false);\n this.currentPanelId = null;\n }\n\n private setupFocusTrap(): void {\n if (!this.overlayRef) return;\n this.focusTrap = this.focusTrapFactory.create(this.overlayRef.overlayElement);\n }\n\n private destroyFocusTrap(): void {\n this.focusTrap?.destroy();\n this.focusTrap = null;\n }\n\n private scheduleOpenedEmission(): void {\n this.clearOpenedTimer();\n if (!this.overlayRef || !this.overlayRef.hasAttached()) return;\n this.openedTimer = setTimeout(() => {\n this.openedTimer = null;\n if (!this.attachedSignal()) return;\n this.openedSignal.set(true);\n this.openedSubject?.next();\n }, PICKER_ENTER_DURATION);\n }\n\n private clearCloseTimer(): void {\n if (this.closeTimer !== null) {\n clearTimeout(this.closeTimer);\n this.closeTimer = null;\n }\n }\n\n private clearOpenedTimer(): void {\n if (this.openedTimer !== null) {\n clearTimeout(this.openedTimer);\n this.openedTimer = null;\n }\n }\n\n private assertOpen(method: string): void {\n if (!this.overlayRef || !this.currentClose$ || !this.openedSubject) {\n throw new Error(\n `PickerOverlayCoordinator.${method}() called before open() — no overlay attached.`,\n );\n }\n }\n}\n","/**\n * Pure helpers shared by `DialogContainer` and `SheetContainer` (both live\n * under `projects/ngx-tw/{dialog,sheet}/`) — and consumable by any future\n * `CdkDialogContainer` subclass that needs the same plumbing.\n *\n * No DOM, no Angular DI. The DI-bound state lives in\n * {@link OverlayContainerCoordinator}; this file is the data-only layer.\n */\n\n/**\n * Fallback padding (ms) added on top of an enter/exit animation duration when\n * scheduling the `transitionend` fallback timer. The browser SHOULD fire\n * `transitionend` at the configured duration, but transitions can be\n * swallowed (focus changes during the animation, interrupted transitions,\n * etc.) — the padding gives the browser a small grace period before our\n * fallback runs.\n *\n * Both dialog and sheet containers used the same constant — extracted here so\n * a future tweak applies to both at once.\n */\nexport const OVERLAY_ANIMATION_FALLBACK_PADDING = 50;\n\n/**\n * Coerces a user-supplied animation duration to a safe positive integer, or\n * falls back to a default if the input is `null`, `undefined`, negative, or\n * non-finite (`NaN`, `Infinity`). Dialog and sheet containers both used this\n * same standalone function; centralised here.\n */\nexport function coerceOverlayDuration(value: number | undefined, fallback: number): number {\n if (value == null || value < 0 || !Number.isFinite(value)) return fallback;\n return value;\n}\n\n/**\n * Merges a consumer-supplied `panelClass` (single class, list, or\n * `undefined`) with the container's internal class string. Returns a single\n * space-separated class string suitable for `[class]` host binding.\n *\n * `consumer` always wins ordering (appended after `internal`) so consumer\n * overrides resolve correctly through `tailwind-merge` upstream.\n */\nexport function mergeOverlayPanelClass(\n internal: string,\n consumer: string | readonly string[] | undefined,\n): string {\n if (!consumer) return internal;\n return Array.isArray(consumer) ? [internal, ...consumer].join(' ') : `${internal} ${consumer}`;\n}\n\n/**\n * Append-only id list with idempotent insertion, used for the\n * `aria-describedby` queue both `DialogContainer` and `SheetContainer`\n * maintain (the matching `aria-labelledby` queue lives in CDK's\n * `CdkDialogContainer`).\n *\n * Pure data structure — no DOM, no Angular signals. Consumers wrap an\n * instance in their own change-detection mechanism (the\n * {@link OverlayContainerCoordinator} keeps the live snapshot in a signal so\n * the container's `[attr.aria-describedby]` binding refreshes via OnPush\n * without a manual `markForCheck()`).\n *\n * First-registered-wins semantics for `first()` mirror CDK's\n * `_ariaLabelledByQueue[0]` host binding — describing the dialog by the\n * earliest registered description prevents a late-mounted nested directive\n * from silently re-aiming the description target.\n */\nexport class AriaIdQueue {\n private readonly ids: string[] = [];\n\n /** Inserts an id at the tail. No-op if the id is already present. */\n add(id: string): void {\n if (this.ids.includes(id)) return;\n this.ids.push(id);\n }\n\n /** Removes the given id. No-op if the id is not present. */\n remove(id: string): void {\n const index = this.ids.indexOf(id);\n if (index >= 0) this.ids.splice(index, 1);\n }\n\n /** First registered id (or `null` if empty). Matches CDK's `_ariaLabelledByQueue[0]` semantics. */\n first(): string | null {\n return this.ids[0] ?? null;\n }\n\n /** Returns a fresh snapshot of all registered ids in insertion order. */\n snapshot(): readonly string[] {\n return [...this.ids];\n }\n}\n","import {\n computed,\n DestroyRef,\n EventEmitter,\n inject,\n Injectable,\n signal,\n type Signal,\n} from '@angular/core';\nimport { AriaIdQueue, OVERLAY_ANIMATION_FALLBACK_PADDING } from './overlay-container-helpers';\n\n/** Lifecycle states an overlay container passes through. Shared by dialog and sheet. */\nexport type OverlayContainerState = 'opening' | 'open' | 'closing' | 'closed';\n\n/** Event emitted on every overlay-container animation-state transition. */\nexport interface OverlayContainerAnimationEvent {\n /** State that the container just transitioned into. */\n state: OverlayContainerState;\n /** Duration, in ms, of the transition that triggered the event. */\n totalTime: number;\n}\n\n/**\n * Component-scoped coordinator that owns the enter/exit animation state\n * machine, ARIA-describedby id queue, and panel-class merge for an overlay\n * container that subclasses `@angular/cdk/dialog`'s `CdkDialogContainer`.\n *\n * Consumed by `DialogContainer` and `SheetContainer`; both register the\n * coordinator at the component level (`providers: [OverlayContainerCoordinator]`)\n * so each container instance owns its own animation state and queue.\n *\n * Per the library \"no `providedIn: 'root'` for services\" rule (see\n * `.claude/CLAUDE.md` → \"What NOT To Do\"): the coordinator holds per-overlay\n * state (the current animation timer, the describedby queue, the lifecycle\n * signal) and MUST be component-scoped.\n *\n * Scope of responsibility:\n * - Animation state signal (`state`) and `transitionDuration` computed.\n * - Enter/exit animation timing (`startEnterAnimation`, `startExitAnimation`)\n * with a `transitionend`-fallback timer.\n * - `animationStateChanged` EventEmitter forwarded to the consuming `Ref`.\n * - ARIA-describedby id queue (the matching labelledby queue is already\n * owned by CDK's `CdkDialogContainer._ariaLabelledByQueue`).\n *\n * Out of scope (stays on the container subclass):\n * - The `CdkDialogContainer` contract — focus trap, escape key, backdrop\n * click, overlay attach/detach. The container subclass keeps inheriting\n * `CdkDialogContainer` directly; this coordinator layers on top.\n * - Tailwind class resolution (`tv()` variant slots) — that's per-container.\n * - Host bindings on the container element — that's per-container.\n */\n@Injectable()\nexport class OverlayContainerCoordinator {\n private readonly destroyRef = inject(DestroyRef);\n\n private readonly stateSignal = signal<OverlayContainerState>('opening');\n private readonly ariaDescribedByQueue = signal<readonly string[]>([]);\n private readonly queue = new AriaIdQueue();\n\n private animationTimer: ReturnType<typeof setTimeout> | null = null;\n private enterDuration = 0;\n private exitDuration = 0;\n\n /** Lifecycle state of the container's enter/exit animation. */\n readonly state: Signal<OverlayContainerState> = this.stateSignal.asReadonly();\n\n /** Live snapshot of the describedby id queue. */\n readonly describedByIds: Signal<readonly string[]> = this.ariaDescribedByQueue.asReadonly();\n\n /**\n * Active transition duration for the current state — the enter duration for\n * `opening` / `open`, the exit duration for `closing`, and 0 once `closed`.\n * Drives the container's `[style.transition-duration.ms]` host binding so a\n * one-line `data-[state]` transition rule can run with per-call timing.\n */\n readonly transitionDuration = computed(() => {\n const current = this.stateSignal();\n if (current === 'opening' || current === 'open') return this.enterDuration;\n if (current === 'closing') return this.exitDuration;\n return 0;\n });\n\n /**\n * Emits whenever the animation state transitions. The container's `Ref`\n * (`TwDialogRef` / `SheetRef`) subscribes to drive its own lifecycle\n * (`afterOpened`, `afterClosed`, exit-animation completion).\n */\n readonly animationStateChanged = new EventEmitter<OverlayContainerAnimationEvent>();\n\n constructor() {\n this.destroyRef.onDestroy(() => {\n this.clearAnimationTimer();\n this.animationStateChanged.complete();\n });\n }\n\n /**\n * Records the resolved enter/exit durations for the open lifecycle.\n * Called once from the container constructor with values coerced via\n * `coerceOverlayDuration`. Stored on the coordinator so\n * `transitionDuration()` and the timer-driven state transitions read from\n * a single source.\n */\n setDurations(enter: number, exit: number): void {\n this.enterDuration = enter;\n this.exitDuration = exit;\n }\n\n /**\n * Drives the enter animation: emits `opening` immediately, then defers the\n * state flip to `open` by one frame so the browser applies the initial\n * (hidden / off-screen) styles before transitioning. If `enter` is `0`\n * everything resolves synchronously (no animation).\n */\n startEnterAnimation(): void {\n this.animationStateChanged.emit({ state: 'opening', totalTime: this.enterDuration });\n\n if (this.enterDuration === 0) {\n this.stateSignal.set('open');\n this.animationStateChanged.emit({ state: 'open', totalTime: 0 });\n return;\n }\n\n requestAnimationFrame(() => {\n this.stateSignal.set('open');\n this.runAnimationTimer(this.enterDuration, () => {\n this.animationStateChanged.emit({\n state: 'open',\n totalTime: this.enterDuration,\n });\n });\n });\n }\n\n /**\n * Drives the exit animation: emits `closing` synchronously and schedules\n * the `closed` emission for after the exit duration (+ a small fallback\n * padding) elapses. The consuming `Ref` listens for the `closed` emission\n * to detach the CDK overlay.\n */\n startExitAnimation(): void {\n this.stateSignal.set('closing');\n this.animationStateChanged.emit({ state: 'closing', totalTime: this.exitDuration });\n\n this.runAnimationTimer(this.exitDuration, () => {\n this.stateSignal.set('closed');\n this.animationStateChanged.emit({ state: 'closed', totalTime: this.exitDuration });\n });\n }\n\n /** Registers a description id with the `aria-describedby` queue. */\n addAriaDescribedBy(id: string): void {\n this.queue.add(id);\n this.ariaDescribedByQueue.set(this.queue.snapshot());\n }\n\n /** Removes a previously registered description id. */\n removeAriaDescribedBy(id: string): void {\n this.queue.remove(id);\n this.ariaDescribedByQueue.set(this.queue.snapshot());\n }\n\n /** First-registered-wins resolution for the `aria-describedby` attribute. */\n firstDescribedBy(): string | null {\n return this.queue.first();\n }\n\n private runAnimationTimer(duration: number, callback: () => void): void {\n this.clearAnimationTimer();\n if (duration === 0) {\n callback();\n return;\n }\n this.animationTimer = setTimeout(callback, duration + OVERLAY_ANIMATION_FALLBACK_PADDING);\n }\n\n private clearAnimationTimer(): void {\n if (this.animationTimer !== null) {\n clearTimeout(this.animationTimer);\n this.animationTimer = null;\n }\n }\n}\n","import { tv } from 'tailwind-variants';\nimport type { TwColor } from './types';\n\n/**\n * Visual style shared by `tw-tabs` (`TabsVariant`) and `nav[twTabNav]` (`TabNavVariant`).\n * Kept as a string-literal union so downstream consumers can narrow when needed.\n */\nexport type TabTriggerVariant = 'underline' | 'enclosed' | 'pill';\n\n/**\n * Trigger-only tailwind-variants config shared by tabs and tab-nav.\n *\n * Both components own additional component-local slots (tablist/list/panel/nav,\n * etc.) — only the trigger shape is canonical enough to share here. The\n * resulting class string is merged with each component's local trigger\n * additions (e.g. tab-nav prepends `no-underline` because anchor elements need\n * to override the default underline; tabs adds nothing extra at the base).\n *\n * Active and inactive trigger state is applied separately via\n * {@link getActiveTriggerClasses} / {@link getInactiveTriggerClasses} so the\n * `Record<TwColor, string>` lookups stay statically scannable by the Tailwind\n * v4 content scanner.\n */\nexport const tabTriggerVariants = tv(\n {\n slots: {\n trigger:\n 'inline-flex items-center gap-1.5 font-medium whitespace-nowrap cursor-pointer transition-colors duration-normal motion-reduce:transition-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500',\n },\n variants: {\n variant: {\n underline: {\n trigger: 'border-b-2 border-transparent -mb-px text-fg-muted hover:text-fg',\n },\n enclosed: {\n trigger:\n 'border border-transparent bg-surface-muted text-fg-muted hover:text-fg -mb-px',\n },\n pill: {\n trigger: 'rounded-md text-fg-muted hover:text-fg',\n },\n },\n size: {\n xs: { trigger: 'px-2 py-1 text-xs' },\n sm: { trigger: 'px-3 py-1.5 text-sm' },\n md: { trigger: 'px-4 py-2 text-sm' },\n lg: { trigger: 'px-5 py-2.5 text-base' },\n xl: { trigger: 'px-6 py-3 text-base' },\n },\n fitted: {\n true: { trigger: 'flex-1 justify-center' },\n false: {},\n },\n color: {\n primary: {},\n secondary: {},\n accent: {},\n neutral: {},\n info: {},\n success: {},\n warning: {},\n error: {},\n },\n },\n defaultVariants: {\n variant: 'underline',\n color: 'primary',\n size: 'md',\n fitted: false,\n },\n },\n { twMerge: true },\n);\n\n// ── Active-state class lookups ──\n// Slot tokens own light/dark contrast — no `dark:`, no shade picks. Classes\n// stay statically written so the Tailwind v4 scanner sees them. The neutral\n// rows use surface/fg/border tokens which already auto-adapt to dark mode.\n\n/** @internal Active trigger classes for horizontal underline variants, keyed by color. */\nexport const UNDERLINE_ACTIVE_HORIZONTAL: Record<TwColor, string> = {\n primary: 'border-b-2 border-primary-border-strong text-primary-fg',\n secondary: 'border-b-2 border-secondary-border-strong text-secondary-fg',\n accent: 'border-b-2 border-accent-border-strong text-accent-fg',\n neutral: 'border-b-2 border-border-strong text-fg',\n info: 'border-b-2 border-info-border-strong text-info-fg',\n success: 'border-b-2 border-success-border-strong text-success-fg',\n warning: 'border-b-2 border-warning-border-strong text-warning-fg',\n error: 'border-b-2 border-error-border-strong text-error-fg',\n};\n\n/** @internal Active trigger classes for vertical underline variants, keyed by color. */\nexport const UNDERLINE_ACTIVE_VERTICAL: Record<TwColor, string> = {\n primary: 'border-r-2 border-primary-border-strong text-primary-fg',\n secondary: 'border-r-2 border-secondary-border-strong text-secondary-fg',\n accent: 'border-r-2 border-accent-border-strong text-accent-fg',\n neutral: 'border-r-2 border-border-strong text-fg',\n info: 'border-r-2 border-info-border-strong text-info-fg',\n success: 'border-r-2 border-success-border-strong text-success-fg',\n warning: 'border-r-2 border-warning-border-strong text-warning-fg',\n error: 'border-r-2 border-error-border-strong text-error-fg',\n};\n\n/** @internal Active trigger classes for horizontal enclosed variants, keyed by color. */\nexport const ENCLOSED_ACTIVE_HORIZONTAL: Record<TwColor, string> = {\n primary: 'bg-surface border border-border border-b-transparent text-primary-fg',\n secondary: 'bg-surface border border-border border-b-transparent text-secondary-fg',\n accent: 'bg-surface border border-border border-b-transparent text-accent-fg',\n neutral: 'bg-surface border border-border border-b-transparent text-fg',\n info: 'bg-surface border border-border border-b-transparent text-info-fg',\n success: 'bg-surface border border-border border-b-transparent text-success-fg',\n warning: 'bg-surface border border-border border-b-transparent text-warning-fg',\n error: 'bg-surface border border-border border-b-transparent text-error-fg',\n};\n\n/** @internal Active trigger classes for vertical enclosed variants, keyed by color. */\nexport const ENCLOSED_ACTIVE_VERTICAL: Record<TwColor, string> = {\n primary: 'bg-surface border border-border border-r-transparent text-primary-fg',\n secondary: 'bg-surface border border-border border-r-transparent text-secondary-fg',\n accent: 'bg-surface border border-border border-r-transparent text-accent-fg',\n neutral: 'bg-surface border border-border border-r-transparent text-fg',\n info: 'bg-surface border border-border border-r-transparent text-info-fg',\n success: 'bg-surface border border-border border-r-transparent text-success-fg',\n warning: 'bg-surface border border-border border-r-transparent text-warning-fg',\n error: 'bg-surface border border-border border-r-transparent text-error-fg',\n};\n\n/** @internal Active trigger classes for pill variants, keyed by color. */\nexport const PILL_ACTIVE: Record<TwColor, string> = {\n primary: 'bg-surface shadow-sm text-primary-fg',\n secondary: 'bg-surface shadow-sm text-secondary-fg',\n accent: 'bg-surface shadow-sm text-accent-fg',\n neutral: 'bg-surface shadow-sm text-fg',\n info: 'bg-surface shadow-sm text-info-fg',\n success: 'bg-surface shadow-sm text-success-fg',\n warning: 'bg-surface shadow-sm text-warning-fg',\n error: 'bg-surface shadow-sm text-error-fg',\n};\n\n/** @internal Inactive trigger classes keyed by variant. */\nexport const INACTIVE_TRIGGER_CLASSES: Record<TabTriggerVariant, string> = {\n underline: 'border-transparent',\n enclosed: 'border-transparent bg-surface-muted',\n pill: '',\n};\n\n/**\n * Returns the active-state trigger class string for the given variant, color,\n * and orientation. Tab-nav callers pass `'horizontal'` since it is horizontal-only.\n */\nexport function getActiveTriggerClasses(\n variant: TabTriggerVariant,\n color: TwColor,\n orientation: 'horizontal' | 'vertical' = 'horizontal',\n): string {\n switch (variant) {\n case 'underline':\n return orientation === 'vertical'\n ? UNDERLINE_ACTIVE_VERTICAL[color]\n : UNDERLINE_ACTIVE_HORIZONTAL[color];\n case 'enclosed':\n return orientation === 'vertical'\n ? ENCLOSED_ACTIVE_VERTICAL[color]\n : ENCLOSED_ACTIVE_HORIZONTAL[color];\n case 'pill':\n return PILL_ACTIVE[color];\n }\n}\n\n/** Returns the inactive-state trigger class string for the given variant. */\nexport function getInactiveTriggerClasses(variant: TabTriggerVariant): string {\n return INACTIVE_TRIGGER_CLASSES[variant];\n}\n","/**\n * Pure helpers shared by `tw-time-picker` and `tw-calendar`'s `withTime`\n * controls. No Angular / CDK imports — safe to drop into either package\n * without pulling a circular dependency.\n */\n\n/** Supported time-picker formats. */\nexport type TimePickerFormat = '12h' | '24h';\n\n/** Meridiem used by the 12h format. */\nexport type TimePickerMeridiem = 'AM' | 'PM';\n\n/** Zero-pads a non-negative integer to exactly two digits. */\nexport function padTwo(value: number): string {\n return value < 10 ? `0${value}` : `${value}`;\n}\n\n/** Converts a 24h hour (0–23) to its 12h display value (1–12). */\nexport function to12h(hour24: number): number {\n const modded = hour24 % 12;\n return modded === 0 ? 12 : modded;\n}\n\n/** Builds a canonical 0–23 hour from a 12h display hour and meridiem. */\nexport function from12h(hour12: number, meridiem: TimePickerMeridiem): number {\n if (hour12 === 12) return meridiem === 'AM' ? 0 : 12;\n return meridiem === 'AM' ? hour12 : hour12 + 12;\n}\n\n/** Maximum allowed value for a field given the picker format. */\nexport function fieldMax(\n field: 'hour' | 'minute' | 'second',\n format: TimePickerFormat,\n): number {\n if (field === 'hour') return format === '12h' ? 12 : 23;\n return 59;\n}\n\n/** Minimum allowed value for a field given the picker format. */\nexport function fieldMin(\n field: 'hour' | 'minute' | 'second',\n format: TimePickerFormat,\n): number {\n return field === 'hour' && format === '12h' ? 1 : 0;\n}\n\n/**\n * Buffers a typed digit onto the current field text, matching the standard\n * two-digit time-field behaviour:\n * - empty + 'x' → 'x'\n * - 'x' + 'y' → 'xy' (if value stays in range)\n * - 'xy' + 'z' → 'z' (overflow → reset)\n * - any combo that would exceed `max` resets to the new digit alone.\n */\nexport function appendDigit(current: string, digit: string, max: number): string {\n if (!/^\\d$/.test(digit)) return current;\n if (current.length >= 2) return digit;\n const candidate = current + digit;\n const numeric = Number(candidate);\n if (numeric > max) return digit;\n return candidate;\n}\n\n/**\n * Reports whether `current` + `digit` unambiguously fills the field — either\n * because the buffer reaches two chars or because the first digit alone\n * already excludes a valid second digit (e.g., `'6'` for minutes, `'3'` for 24h\n * hour). Used to auto-advance focus to the next field.\n */\nexport function isTerminalDigit(current: string, digit: string, max: number): boolean {\n if (current.length === 1) return true;\n if (!/^\\d$/.test(digit)) return false;\n const maxFirst = Math.floor(max / 10);\n return Number(digit) > maxFirst;\n}\n\n/**\n * Steps a numeric value by `step`, wrapping inside `[min, max]`. Works for\n * arbitrary step sizes; a step of 0 behaves as 1 to protect against mis-configs.\n */\nexport function stepWithWrap(\n value: number,\n step: number,\n direction: 1 | -1,\n min: number,\n max: number,\n): number {\n const safeStep = Math.max(1, Math.abs(step));\n const range = max - min + 1;\n const delta = safeStep * direction;\n return ((((value - min + delta) % range) + range) % range) + min;\n}\n\n/** Clamps a number into `[min, max]` without wrapping. */\nexport function clamp(value: number, min: number, max: number): number {\n if (value < min) return min;\n if (value > max) return max;\n return value;\n}\n\n/** Parses a 1- or 2-digit text field; returns `null` if empty or non-numeric. */\nexport function parseField(text: string): number | null {\n if (!text) return null;\n if (!/^\\d{1,2}$/.test(text)) return null;\n return Number(text);\n}\n\n/** Total seconds since midnight for a (h, m, s) tuple — useful for min/max compare. */\nexport function timeOfDaySeconds(hour: number, minute: number, second: number): number {\n return hour * 3600 + minute * 60 + second;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cdevhub-ngx-tw-core.mjs","sources":["../../../projects/ngx-tw/core/error-state-matcher.ts","../../../projects/ngx-tw/core/error-state-wiring.ts","../../../projects/ngx-tw/core/sort-handle.ts","../../../projects/ngx-tw/core/overlay/positions.ts","../../../projects/ngx-tw/core/overlay/scroll-strategy.ts","../../../projects/ngx-tw/core/overlay/escape.ts","../../../projects/ngx-tw/core/overlay/picker-overlay-coordinator.ts","../../../projects/ngx-tw/core/overlay/overlay-container-helpers.ts","../../../projects/ngx-tw/core/overlay/overlay-container-coordinator.ts","../../../projects/ngx-tw/core/tab-trigger-variants.ts","../../../projects/ngx-tw/core/time-utils.ts","../../../projects/ngx-tw/core/cdevhub-ngx-tw-core.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport type { AbstractControl } from '@angular/forms';\n\n/**\n * Minimal contract for a parent form's \"submitted\" state. Both `NgForm` and\n * `FormGroupDirective` satisfy this, so the matcher can work with either.\n */\nexport interface TwFormSubmitted {\n readonly submitted: boolean;\n}\n\n/**\n * Strategy that decides when a form control should be rendered in the error\n * state. Controls read the injected matcher (or accept a per-instance\n * override) and combine the result with their own signals. Override at any\n * injector level via {@link TW_ERROR_STATE_MATCHER}.\n */\nexport interface ErrorStateMatcher {\n /** Returns true when the control should display an error. */\n isErrorState(\n control: AbstractControl | null,\n form: TwFormSubmitted | null,\n ): boolean;\n}\n\n/**\n * Default error-state strategy: errored when the control is `invalid` and\n * either has been interacted with (`dirty` or `touched`) or its parent form\n * has been submitted. Matches Material's default behavior.\n */\nexport const defaultErrorStateMatcher: ErrorStateMatcher = {\n isErrorState(control, form) {\n if (!control) {\n return false;\n }\n const interacted = control.dirty || control.touched;\n return !!control.invalid && (interacted || !!form?.submitted);\n },\n};\n\n/**\n * Injection token carrying the {@link ErrorStateMatcher} used by every ngx-tw\n * form control. Defaults to {@link defaultErrorStateMatcher}; provide a\n * different matcher at root to change global error-display policy, or at any\n * descendant injector to scope the change.\n */\nexport const TW_ERROR_STATE_MATCHER = new InjectionToken<ErrorStateMatcher>(\n 'TW_ERROR_STATE_MATCHER',\n {\n providedIn: 'root',\n factory: () => defaultErrorStateMatcher,\n },\n);\n","import { computed, DestroyRef, inject, signal, type Signal } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport {\n FormGroupDirective,\n NgForm,\n Validators,\n type NgControl,\n type ValidatorFn,\n} from '@angular/forms';\nimport { merge } from 'rxjs';\nimport {\n TW_ERROR_STATE_MATCHER,\n type ErrorStateMatcher,\n type TwFormSubmitted,\n} from './error-state-matcher';\n\n/** Default validator set consulted by {@link ErrorStateWiring.required}. */\nconst DEFAULT_REQUIRED_VALIDATORS: readonly ValidatorFn[] = [Validators.required];\n\nconst NO_TRACKED_SOURCES: readonly (() => unknown)[] = [];\n\n/**\n * Configuration for {@link wireErrorState}. Every field is a callback rather\n * than a `Signal`, so the options object may reference class members that are\n * declared *below* the `wireErrorState()` call site — the callbacks are only\n * invoked from inside the returned computeds, long after construction.\n */\nexport interface ErrorStateWiringOptions {\n /**\n * Resolves the host's bound `NgControl`, or `null` when the host is not bound\n * to a form control. Pass a getter rather than the instance so controls that\n * resolve `NgControl` lazily (pickers that self-provide `NG_VALIDATORS` and\n * must defer the lookup to `ngOnInit`) work unchanged. Deliberately *not*\n * injected by this helper: the host owns the `NgControl` reference because it\n * also owns `ControlValueAccessor` registration.\n */\n readonly ngControl: () => NgControl | null;\n /**\n * Reads the host's per-instance `errorStateMatcher` input. When it returns\n * `undefined` the matcher provided under `TW_ERROR_STATE_MATCHER` is used.\n */\n readonly matcher?: () => ErrorStateMatcher | undefined;\n /**\n * Reads the host's `required` input. When it returns `true`,\n * {@link ErrorStateWiring.required} is `true` without consulting validators —\n * the arm that keeps signal forms working, since `cvaControlCreate` writes the\n * `required` input directly and never inspects validators.\n */\n readonly required?: () => boolean;\n /**\n * Validators that mark the control required when present on the bound\n * `NgControl`. Defaults to `[Validators.required]`; boolean controls\n * (`tw-checkbox`, `tw-switch`) also pass `Validators.requiredTrue`.\n */\n readonly requiredValidators?: readonly ValidatorFn[];\n /**\n * Extra reactive sources {@link ErrorStateWiring.errorState} track-reads.\n * Controls pass their focus signal here so a blur — which flips `touched` on\n * the bound control without changing its status or value — repaints the error\n * styling.\n */\n readonly track?: readonly (() => unknown)[];\n /**\n * Short-circuits {@link ErrorStateWiring.errorState}. Return a boolean to use\n * it as the error state without consulting the matcher, or `undefined` to fall\n * through to the matcher. Used by the pickers (a parse or range error is an\n * error regardless of validator status) and by `tw-radio` (a radio inside a\n * group inherits the group's error state). Called after the revision signals\n * are read, so its own reads are tracked normally.\n */\n readonly errorStateOverride?: () => boolean | undefined;\n}\n\n/** Reactive error-state surface returned by {@link wireErrorState}. */\nexport interface ErrorStateWiring {\n /**\n * Whether the control should render as invalid, per the resolved\n * {@link ErrorStateMatcher}. Satisfies `FormFieldControl.errorState`.\n */\n readonly errorState: Signal<boolean>;\n /**\n * Whether the control is required — the host's `required` input OR'd with the\n * configured required validators on the bound `NgControl`. Satisfies\n * `FormFieldControl.required`.\n */\n readonly required: Signal<boolean>;\n /**\n * Active validation errors on the bound `NgControl`, or `null` when it reports\n * none or is unbound. Satisfies `FormFieldControl.errors`, which is what\n * `[twError match=\"…\"]` filters on inside a `<tw-form-field>`.\n */\n readonly errors: Signal<Record<string, unknown> | null>;\n /**\n * Revision counter bumped whenever the bound control may have changed. Read it\n * from any other computed that dereferences `NgControl` — typically a\n * `disabled` computed reading `ngControl.disabled` — so that computed\n * invalidates on the same ticks the error state does.\n */\n readonly rev: Signal<number>;\n /**\n * Bumps {@link ErrorStateWiring.rev}. Call it from anywhere the bound control\n * changed without emitting on `statusChanges`/`valueChanges` — a `FocusMonitor`\n * blur that flipped `touched`, `setDisabledState`, or immediately after a\n * deferred `NgControl` lookup.\n */\n bump(): void;\n /**\n * Subscribes to the bound control's `statusChanges`/`valueChanges` and to the\n * parent form's `ngSubmit`. Call this from `ngOnInit`, never the constructor:\n * `NgControl.control` is populated by the parent `FormControl*` directive's own\n * `ngOnChanges`, which runs before children's `ngOnInit` but after their\n * constructors. Teardown is wired to the host's `DestroyRef`.\n */\n connect(): void;\n}\n\n/**\n * Builds the error-state, required and errors signals every ngx-tw form control\n * exposes to `<tw-form-field>`, plus the revision plumbing that keeps them live.\n *\n * Call it from an injection context (a field initializer or the constructor).\n * It injects `DestroyRef`, `NgForm`/`FormGroupDirective` (both optional) and\n * `TW_ERROR_STATE_MATCHER` on the host's behalf; it does **not** inject\n * `NgControl`, because the host must keep ownership of that reference for\n * `ControlValueAccessor` registration.\n *\n * Wiring an error-state-aware control takes three steps:\n *\n * ```ts\n * private readonly ngControl = inject(NgControl, { optional: true, self: true });\n * private readonly errorWiring = wireErrorState({\n * ngControl: () => this.ngControl,\n * matcher: () => this.errorStateMatcher(),\n * required: () => this.requiredInput(),\n * track: [this._focused],\n * });\n *\n * readonly errorState = this.errorWiring.errorState;\n * readonly required = this.errorWiring.required;\n * readonly errors = this.errorWiring.errors;\n *\n * ngOnInit(): void {\n * this.errorWiring.connect();\n * }\n * ```\n */\nexport function wireErrorState(options: ErrorStateWiringOptions): ErrorStateWiring {\n const destroyRef = inject(DestroyRef);\n const parentForm = inject(NgForm, { optional: true });\n const parentFormGroup = inject(FormGroupDirective, { optional: true });\n const defaultMatcher = inject(TW_ERROR_STATE_MATCHER);\n\n const {\n ngControl,\n matcher,\n required: requiredInput,\n requiredValidators = DEFAULT_REQUIRED_VALIDATORS,\n track = NO_TRACKED_SOURCES,\n errorStateOverride,\n } = options;\n\n // Revision counters. `controlRev` invalidates everything derived from the\n // bound control; `submitRev` invalidates only the matcher's `form.submitted`\n // arm. They are separate because a submit must not make `required`/`errors`\n // recompute.\n const controlRev = signal(0);\n const submitRev = signal(0);\n\n const errorState = computed(() => {\n controlRev();\n submitRev();\n for (const source of track) {\n source();\n }\n const overridden = errorStateOverride?.();\n if (overridden !== undefined) return overridden;\n const resolved = matcher?.() ?? defaultMatcher;\n const form: TwFormSubmitted | null =\n (parentFormGroup as TwFormSubmitted | null) ?? (parentForm as TwFormSubmitted | null);\n return resolved.isErrorState(ngControl()?.control ?? null, form);\n });\n\n const required = computed(() => {\n controlRev();\n if (requiredInput?.()) return true;\n const control = ngControl()?.control;\n if (!control) return false;\n return requiredValidators.some((validator) => control.hasValidator(validator));\n });\n\n const errors = computed<Record<string, unknown> | null>(() => {\n controlRev();\n return (ngControl()?.control?.errors as Record<string, unknown> | null) ?? null;\n });\n\n return {\n errorState,\n required,\n errors,\n rev: controlRev.asReadonly(),\n bump: () => controlRev.update((n) => n + 1),\n connect: () => {\n const control = ngControl()?.control;\n if (control) {\n const streams = [control.statusChanges, control.valueChanges].filter(\n (stream): stream is NonNullable<typeof stream> => !!stream,\n );\n if (streams.length) {\n merge(...streams)\n .pipe(takeUntilDestroyed(destroyRef))\n .subscribe(() => controlRev.update((n) => n + 1));\n }\n }\n\n const submit = parentFormGroup?.ngSubmit ?? parentForm?.ngSubmit;\n if (submit) {\n submit\n .pipe(takeUntilDestroyed(destroyRef))\n .subscribe(() => submitRev.update((n) => n + 1));\n }\n },\n };\n}\n","import { InjectionToken, type Signal } from '@angular/core';\n\n/**\n * Read-only view of a sortable region's state.\n *\n * Components that render column headers (e.g., `<tw-table>`) consume this handle to\n * project `aria-sort` onto the active column without taking a hard dependency on the\n * sort implementation. The canonical provider is `SortDirective` (`[twSort]`).\n */\nexport interface TwSortHandle {\n /** Signal of the id of the currently active sort header, or `null` when no sort is active. */\n readonly active: Signal<string | null>;\n /** Signal of the active sort direction (`'asc'` / `'desc'`), or `null` when cleared. */\n readonly direction: Signal<'asc' | 'desc' | null>;\n}\n\n/**\n * DI token through which sort containers expose their state to consumers. Provided by\n * `SortDirective` (`[twSort]`). Inject with `{ optional: true }` — components that need\n * aria-sort plumbing should degrade gracefully when no sort directive is present.\n */\nexport const TW_SORT_HANDLE = new InjectionToken<TwSortHandle>('TwSortHandle');\n","import type { ConnectedPosition } from '@angular/cdk/overlay';\n\n/**\n * Connected-overlay position list for \"select-like\" overlays — overlays whose\n * panel attaches directly under (or above) a trigger element and falls back to\n * the opposite vertical side when there is not enough room. Returns four\n * fallback positions: below-start, below-end, above-start, above-end.\n *\n * Used by `SelectComponent`, `ComboboxComponent`, `DatePickerComponent`, and\n * `DateRangePickerComponent` — any overlay-bearing form control that anchors\n * a listbox / menu / calendar panel to its trigger. The shape is identical for\n * all four; the historical \"select-like\" name refers to the original consumer.\n *\n * @param offset Vertical offset in pixels applied between the trigger edge and\n * the panel edge. Below-positions use `+offset`; above-positions use\n * `-offset` so the panel pulls away from the trigger consistently.\n */\nexport function buildSelectLikePositions(offset = 0): ConnectedPosition[] {\n return [\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: offset },\n { originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: offset },\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -offset },\n { originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetY: -offset },\n ];\n}\n","import type { Overlay, ScrollStrategy } from '@angular/cdk/overlay';\n\n/** Named scroll-strategy variants supported by select-like overlays. */\nexport type SelectScrollStrategyName = 'reposition' | 'close' | 'block';\n\n/**\n * Maps a named scroll-strategy variant to the corresponding CDK\n * `ScrollStrategy` instance. `'reposition'` is the default for select-like\n * overlays; `'close'` dismisses the panel on scroll; `'block'` locks page\n * scrolling while the panel is open.\n *\n * Used by `SelectComponent`, `ComboboxComponent`, `DatePickerComponent`, and\n * `DateRangePickerComponent` — any overlay-bearing form control that exposes\n * the same three-option scroll-strategy input.\n */\nexport function resolveSelectScrollStrategy(\n name: SelectScrollStrategyName,\n overlay: Overlay,\n): ScrollStrategy {\n switch (name) {\n case 'close':\n return overlay.scrollStrategies.close();\n case 'block':\n return overlay.scrollStrategies.block();\n default:\n return overlay.scrollStrategies.reposition();\n }\n}\n","import type { OverlayRef } from '@angular/cdk/overlay';\nimport { filter } from 'rxjs/operators';\n\n/**\n * Subscribes to overlay-level `Escape` keydown events and invokes `onEscape`\n * for each one. Returns an unsubscribe function so callers can scope teardown\n * to the open lifecycle of the overlay (typically tied into a `Subscription`\n * aggregate or a `takeUntilDestroyed` flow).\n *\n * Listens via `OverlayRef.keydownEvents()` so the handler fires for any\n * keystroke originating inside the overlay, regardless of which element holds\n * DOM focus — useful for select-style overlays whose search/listbox children\n * may receive focus apart from the trigger.\n *\n * Callers remain responsible for calling `event.preventDefault()` /\n * `stopPropagation()` inside `onEscape` if they want to short-circuit further\n * key handling.\n */\nexport function consumeOverlayEscape(\n overlayRef: OverlayRef,\n onEscape: (event: KeyboardEvent) => void,\n): () => void {\n const subscription = overlayRef\n .keydownEvents()\n .pipe(filter((event) => event.key === 'Escape'))\n .subscribe((event) => onEscape(event));\n return () => subscription.unsubscribe();\n}\n","import {\n type ComponentRef,\n DestroyRef,\n type ElementRef,\n inject,\n Injectable,\n type Injector,\n signal,\n type Signal,\n type ViewContainerRef,\n} from '@angular/core';\nimport {\n _IdGenerator,\n FocusTrapFactory,\n} from '@angular/cdk/a11y';\nimport {\n type ConnectedPosition,\n Overlay,\n type OverlayRef,\n type ScrollStrategy,\n} from '@angular/cdk/overlay';\nimport { ComponentPortal, type ComponentType } from '@angular/cdk/portal';\nimport { Subject, type Observable } from 'rxjs';\nimport { filter, takeUntil } from 'rxjs/operators';\n\n/**\n * Enter-animation duration for date-picker / date-range-picker overlays.\n * Matches `theme/_base.css` `.scale-in 140ms` — the keyframe the picker\n * overlays apply via `animate.enter=\"scale-in\"`. The coordinator delays\n * `opened$` emission by this duration so consumers can hook the moment the\n * panel has fully appeared instead of the moment `open()` was called.\n */\nexport const PICKER_ENTER_DURATION = 140;\n\n/**\n * Leave-animation duration for date-picker / date-range-picker overlays.\n * Matches `theme/_base.css` `.scale-out 120ms` — the keyframe the picker\n * overlays apply via `animate.leave=\"scale-out\"`. The coordinator delays\n * overlay detach by this duration so the leave animation can play through.\n */\nexport const PICKER_LEAVE_DURATION = 120;\n\n/** Configuration passed to {@link PickerOverlayCoordinator.open}. */\nexport interface PickerOpenConfig<TOverlay> {\n /** Element used as the connected-overlay origin (typically the picker trigger). */\n readonly origin: ElementRef<HTMLElement>;\n /** Component type to render inside the overlay (e.g. `DatePickerOverlayComponent`). */\n readonly portalComponent: ComponentType<TOverlay>;\n /** View-container that hosts the embedded view; usually the picker's `ViewContainerRef`. */\n readonly viewContainerRef: ViewContainerRef;\n /** Optional injector forwarded to the portal so DI tokens resolve from the picker's tree. */\n readonly injector?: Injector;\n /** Connected-position list — typically the result of `buildSelectLikePositions(offset)`. */\n readonly positions: ConnectedPosition[];\n /** CDK scroll-strategy instance for the overlay. */\n readonly scrollStrategy: ScrollStrategy;\n /** CSS class applied to the CDK overlay-pane element (NOT the panel root). */\n readonly panelClass: string;\n /** Viewport margin forwarded to the CDK position-strategy. Defaults to `8`. */\n readonly viewportMargin?: number;\n /**\n * Whether keyboard focus is trapped inside the overlay while it is open.\n * Defaults to `true`, which suits modal picker panels that move DOM focus\n * into the overlay. Pass `false` for `aria-activedescendant` surfaces\n * (`tw-select`, `tw-combobox`) where DOM focus deliberately stays on the\n * trigger: the trap's capturing anchor elements would otherwise sit in the\n * tab order around a panel that holds no focusable content.\n */\n readonly focusTrap?: boolean;\n}\n\n/** Synchronous return shape of {@link PickerOverlayCoordinator.open}. */\nexport interface PickerOpenResult<TOverlay> {\n /** The CDK `OverlayRef` driving the overlay — exposed for advanced consumers. */\n readonly overlayRef: OverlayRef;\n /** The Angular `ComponentRef` for the attached portal — exposed so consumers may run `detectChanges()` to flush an initial-config push synchronously. */\n readonly componentRef: ComponentRef<TOverlay>;\n /** The instance of the attached portal component. Equivalent to `componentRef.instance`. */\n readonly instance: TOverlay;\n /** Auto-generated id consumers may wire to `aria-controls` / dialog `id`. */\n readonly panelId: string;\n}\n\n/**\n * Coordinator that owns the CDK `OverlayRef`, focus trap, panel-id, and\n * animation timing for an overlay-bearing form control. Consumed by\n * `DatePickerComponent`, `DateRangePickerComponent`, `SelectComponent` and\n * `ComboboxComponent`; every consumer registers the coordinator at the\n * component level (`providers: [PickerOverlayCoordinator]`) so each instance\n * owns its own coordinator state.\n *\n * Per the library \"no `providedIn: 'root'` for services\" rule (see\n * `.claude/CLAUDE.md` → \"What NOT To Do\"): the coordinator holds per-overlay\n * `OverlayRef` / `FocusTrap` state and MUST be component-scoped.\n *\n * Scope of responsibility:\n * - Create / dispose the CDK `OverlayRef`. The ref is **disposed** on close and\n * rebuilt on the next open, so every creation-time value (`positions`,\n * `scrollStrategy`, `panelClass`, and the position strategy's origin) is\n * re-read on every open. Nothing here is frozen at first open.\n * - Attach a `ComponentPortal` and return the instance.\n * - Set up / tear down a `FocusTrap` around the overlay element, unless the\n * consumer opts out via `focusTrap: false`.\n * - Emit `opened$` after the enter animation completes (closes the\n * synchronous-emit bug previously present in both pickers).\n * - Expose `backdropClick$` / `overlayKeydown$` / `escape$` streams scoped\n * to the current open lifecycle.\n * - Run a leave-animation timer with an `isAttached` guard so close races\n * never touch a detached `OverlayRef` (mirrors the S14 command-palette\n * pattern).\n *\n * Out of scope (stays in the consuming component):\n * - Panel width. `select` / `combobox` size their panel from a trigger\n * measurement that only they can make (which of several host children is the\n * measurable trigger differs per component), so they call\n * `ref()?.updateSize(...)` themselves and own their `ResizeObserver`.\n * - \"Restore previous value on close\" — semantics differ per picker.\n * - Per-picker portal callbacks (calendar selection, action-bar buttons).\n * - View-mode change-detection nudges (the range-picker calls\n * `changeDetectorRef.detectChanges()` after pushing its initial overlay\n * config; the date-picker does not).\n */\n@Injectable()\nexport class PickerOverlayCoordinator {\n private readonly overlay = inject(Overlay);\n private readonly focusTrapFactory = inject(FocusTrapFactory);\n private readonly destroyRef = inject(DestroyRef);\n private readonly idGenerator = inject(_IdGenerator);\n\n private overlayRef: OverlayRef | null = null;\n private focusTrap: ReturnType<FocusTrapFactory['create']> | null = null;\n private closeTimer: ReturnType<typeof setTimeout> | null = null;\n private openedTimer: ReturnType<typeof setTimeout> | null = null;\n private currentPanelId: string | null = null;\n private currentClose$: Subject<void> | null = null;\n private openedSubject: Subject<void> | null = null;\n\n private readonly attachedSignal = signal(false);\n private readonly openedSignal = signal(false);\n\n /** Whether the overlay is currently attached (between `open()` and detach). */\n readonly attached: Signal<boolean> = this.attachedSignal.asReadonly();\n\n /** Whether the enter animation has completed (`opened$` has fired). */\n readonly opened: Signal<boolean> = this.openedSignal.asReadonly();\n\n constructor() {\n this.destroyRef.onDestroy(() => this.disposeImmediate());\n }\n\n /**\n * Creates and attaches the overlay. Returns the live overlay metadata\n * synchronously; callers should subscribe to {@link opened$} to observe the\n * moment the enter animation completes. Returns `null` if an overlay is\n * already attached.\n */\n open<TOverlay>(config: PickerOpenConfig<TOverlay>): PickerOpenResult<TOverlay> | null {\n if (this.overlayRef) return null;\n\n const positionStrategy = this.overlay\n .position()\n .flexibleConnectedTo(config.origin)\n .withPositions(config.positions)\n .withFlexibleDimensions(false)\n .withPush(false)\n .withViewportMargin(config.viewportMargin ?? 8);\n\n this.overlayRef = this.overlay.create({\n positionStrategy,\n scrollStrategy: config.scrollStrategy,\n hasBackdrop: true,\n backdropClass: 'cdk-overlay-transparent-backdrop',\n panelClass: config.panelClass,\n });\n\n const portal = new ComponentPortal<TOverlay>(\n config.portalComponent,\n config.viewContainerRef,\n config.injector,\n );\n const ref = this.overlayRef.attach(portal);\n const instance = ref.instance;\n\n this.currentPanelId = this.idGenerator.getId('tw-picker-overlay-');\n this.currentClose$ = new Subject<void>();\n this.openedSubject = new Subject<void>();\n this.attachedSignal.set(true);\n this.openedSignal.set(false);\n\n if (config.focusTrap !== false) {\n this.setupFocusTrap();\n }\n this.scheduleOpenedEmission();\n\n return {\n overlayRef: this.overlayRef,\n componentRef: ref,\n instance,\n panelId: this.currentPanelId,\n };\n }\n\n /**\n * Starts the close sequence — destroys the focus trap immediately so focus\n * can return to the trigger, then detaches the overlay after the leave\n * animation runs ({@link PICKER_LEAVE_DURATION}). Invokes `onAfterClose`\n * once the overlay is fully detached. No-op if no overlay is open or a\n * close is already in flight.\n *\n * Mirrors the S14 command-palette `isAttached`-guarded close pattern:\n * after the timer fires we re-check `attachedSignal` before touching the\n * overlay so a race (programmatic dispose, double-close) cannot touch a\n * destroyed instance.\n */\n close(onAfterClose: () => void = () => {}): void {\n if (!this.overlayRef || this.closeTimer !== null) return;\n this.destroyFocusTrap();\n this.clearOpenedTimer();\n\n this.closeTimer = setTimeout(() => {\n this.closeTimer = null;\n if (!this.attachedSignal()) {\n // Lost race with disposeImmediate / destroyRef.onDestroy.\n return;\n }\n if (this.overlayRef?.hasAttached()) {\n this.overlayRef.detach();\n }\n // Dispose the OverlayRef so the next open() builds a fresh one with the\n // current inputs (offset, scrollStrategy, panelClass). Without this the\n // `if (this.overlayRef) return null;` guard at the top of open() would\n // permanently block re-opens after the first close.\n this.overlayRef?.dispose();\n this.overlayRef = null;\n this.currentClose$?.next();\n this.currentClose$?.complete();\n this.currentClose$ = null;\n this.openedSubject?.complete();\n this.openedSubject = null;\n this.attachedSignal.set(false);\n this.openedSignal.set(false);\n this.currentPanelId = null;\n onAfterClose();\n }, PICKER_LEAVE_DURATION);\n }\n\n /**\n * Stream of overlay-level backdrop clicks for the current open lifecycle.\n * Completes when the overlay closes.\n */\n backdropClick$(): Observable<MouseEvent> {\n this.assertOpen('backdropClick$');\n return this.overlayRef!.backdropClick().pipe(takeUntil(this.currentClose$!));\n }\n\n /**\n * Stream of overlay-level keydown events for the current open lifecycle.\n * Completes when the overlay closes.\n */\n overlayKeydown$(): Observable<KeyboardEvent> {\n this.assertOpen('overlayKeydown$');\n return this.overlayRef!.keydownEvents().pipe(takeUntil(this.currentClose$!));\n }\n\n /**\n * Stream filtered to `Escape` keydowns inside the overlay for the current\n * open lifecycle. Equivalent to `overlayKeydown$().pipe(filter(e => e.key === 'Escape'))`\n * but spelled out so consumers don't import RxJS operators just for the\n * common case.\n */\n escape$(): Observable<KeyboardEvent> {\n return this.overlayKeydown$().pipe(filter((e) => e.key === 'Escape'));\n }\n\n /**\n * Emits exactly once after the enter animation completes\n * ({@link PICKER_ENTER_DURATION}ms after `open()`). Used by consumers to\n * fire their `opened` output at the moment the overlay panel is actually\n * visible — closes the synchronous-emit bug the pickers carried before\n * this coordinator existed.\n *\n * Completes when the overlay closes.\n */\n opened$(): Observable<void> {\n this.assertOpen('opened$');\n return this.openedSubject!.asObservable().pipe(takeUntil(this.currentClose$!));\n }\n\n /** Exposes the live `OverlayRef` for advanced consumers (e.g. width sync). */\n ref(): OverlayRef | null {\n return this.overlayRef;\n }\n\n /**\n * Exposes the current panel id (auto-generated via CDK `_IdGenerator`,\n * stable for the open lifecycle, reset to `null` on close). Neither\n * consuming picker uses this today — both keep their own\n * `${hostId}-dialog` id for `aria-controls` wiring — but the helper is\n * exposed for future consumers (e.g. a picker wrapper that wants its\n * panel id auto-managed).\n */\n panelId(): string | null {\n return this.currentPanelId;\n }\n\n /**\n * Immediately disposes the overlay and tears down the focus trap without\n * running the leave animation. Called from {@link DestroyRef.onDestroy};\n * consumers should NOT call this — use {@link close} for the user-visible\n * close path.\n */\n private disposeImmediate(): void {\n this.clearCloseTimer();\n this.clearOpenedTimer();\n this.destroyFocusTrap();\n if (this.currentClose$) {\n this.currentClose$.next();\n this.currentClose$.complete();\n this.currentClose$ = null;\n }\n this.openedSubject?.complete();\n this.openedSubject = null;\n this.overlayRef?.dispose();\n this.overlayRef = null;\n this.attachedSignal.set(false);\n this.openedSignal.set(false);\n this.currentPanelId = null;\n }\n\n private setupFocusTrap(): void {\n if (!this.overlayRef) return;\n this.focusTrap = this.focusTrapFactory.create(this.overlayRef.overlayElement);\n }\n\n private destroyFocusTrap(): void {\n this.focusTrap?.destroy();\n this.focusTrap = null;\n }\n\n private scheduleOpenedEmission(): void {\n this.clearOpenedTimer();\n if (!this.overlayRef || !this.overlayRef.hasAttached()) return;\n this.openedTimer = setTimeout(() => {\n this.openedTimer = null;\n if (!this.attachedSignal()) return;\n this.openedSignal.set(true);\n this.openedSubject?.next();\n }, PICKER_ENTER_DURATION);\n }\n\n private clearCloseTimer(): void {\n if (this.closeTimer !== null) {\n clearTimeout(this.closeTimer);\n this.closeTimer = null;\n }\n }\n\n private clearOpenedTimer(): void {\n if (this.openedTimer !== null) {\n clearTimeout(this.openedTimer);\n this.openedTimer = null;\n }\n }\n\n private assertOpen(method: string): void {\n if (!this.overlayRef || !this.currentClose$ || !this.openedSubject) {\n throw new Error(\n `PickerOverlayCoordinator.${method}() called before open() — no overlay attached.`,\n );\n }\n }\n}\n","/**\n * Pure helpers shared by `DialogContainer` and `SheetContainer` (both live\n * under `projects/ngx-tw/{dialog,sheet}/`) — and consumable by any future\n * `CdkDialogContainer` subclass that needs the same plumbing.\n *\n * No DOM, no Angular DI. The DI-bound state lives in\n * {@link OverlayContainerCoordinator}; this file is the data-only layer.\n */\n\n/**\n * Fallback padding (ms) added on top of an enter/exit animation duration when\n * scheduling the `transitionend` fallback timer. The browser SHOULD fire\n * `transitionend` at the configured duration, but transitions can be\n * swallowed (focus changes during the animation, interrupted transitions,\n * etc.) — the padding gives the browser a small grace period before our\n * fallback runs.\n *\n * Both dialog and sheet containers used the same constant — extracted here so\n * a future tweak applies to both at once.\n */\nexport const OVERLAY_ANIMATION_FALLBACK_PADDING = 50;\n\n/**\n * Coerces a user-supplied animation duration to a safe positive integer, or\n * falls back to a default if the input is `null`, `undefined`, negative, or\n * non-finite (`NaN`, `Infinity`). Dialog and sheet containers both used this\n * same standalone function; centralised here.\n */\nexport function coerceOverlayDuration(value: number | undefined, fallback: number): number {\n if (value == null || value < 0 || !Number.isFinite(value)) return fallback;\n return value;\n}\n\n/**\n * Merges a consumer-supplied `panelClass` (single class, list, or\n * `undefined`) with the container's internal class string. Returns a single\n * space-separated class string suitable for `[class]` host binding.\n *\n * `consumer` always wins ordering (appended after `internal`) so consumer\n * overrides resolve correctly through `tailwind-merge` upstream.\n */\nexport function mergeOverlayPanelClass(\n internal: string,\n consumer: string | readonly string[] | undefined,\n): string {\n if (!consumer) return internal;\n return Array.isArray(consumer) ? [internal, ...consumer].join(' ') : `${internal} ${consumer}`;\n}\n\n/**\n * Append-only id list with idempotent insertion, used for the\n * `aria-describedby` queue both `DialogContainer` and `SheetContainer`\n * maintain (the matching `aria-labelledby` queue lives in CDK's\n * `CdkDialogContainer`).\n *\n * Pure data structure — no DOM, no Angular signals. Consumers wrap an\n * instance in their own change-detection mechanism (the\n * {@link OverlayContainerCoordinator} keeps the live snapshot in a signal so\n * the container's `[attr.aria-describedby]` binding refreshes via OnPush\n * without a manual `markForCheck()`).\n *\n * First-registered-wins semantics for `first()` mirror CDK's\n * `_ariaLabelledByQueue[0]` host binding — describing the dialog by the\n * earliest registered description prevents a late-mounted nested directive\n * from silently re-aiming the description target.\n */\nexport class AriaIdQueue {\n private readonly ids: string[] = [];\n\n /** Inserts an id at the tail. No-op if the id is already present. */\n add(id: string): void {\n if (this.ids.includes(id)) return;\n this.ids.push(id);\n }\n\n /** Removes the given id. No-op if the id is not present. */\n remove(id: string): void {\n const index = this.ids.indexOf(id);\n if (index >= 0) this.ids.splice(index, 1);\n }\n\n /** First registered id (or `null` if empty). Matches CDK's `_ariaLabelledByQueue[0]` semantics. */\n first(): string | null {\n return this.ids[0] ?? null;\n }\n\n /** Returns a fresh snapshot of all registered ids in insertion order. */\n snapshot(): readonly string[] {\n return [...this.ids];\n }\n}\n","import {\n computed,\n DestroyRef,\n EventEmitter,\n inject,\n Injectable,\n signal,\n type Signal,\n} from '@angular/core';\nimport { AriaIdQueue, OVERLAY_ANIMATION_FALLBACK_PADDING } from './overlay-container-helpers';\n\n/** Lifecycle states an overlay container passes through. Shared by dialog and sheet. */\nexport type OverlayContainerState = 'opening' | 'open' | 'closing' | 'closed';\n\n/** Event emitted on every overlay-container animation-state transition. */\nexport interface OverlayContainerAnimationEvent {\n /** State that the container just transitioned into. */\n state: OverlayContainerState;\n /** Duration, in ms, of the transition that triggered the event. */\n totalTime: number;\n}\n\n/**\n * Component-scoped coordinator that owns the enter/exit animation state\n * machine, ARIA-describedby id queue, and panel-class merge for an overlay\n * container that subclasses `@angular/cdk/dialog`'s `CdkDialogContainer`.\n *\n * Consumed by `DialogContainer` and `SheetContainer`; both register the\n * coordinator at the component level (`providers: [OverlayContainerCoordinator]`)\n * so each container instance owns its own animation state and queue.\n *\n * Per the library \"no `providedIn: 'root'` for services\" rule (see\n * `.claude/CLAUDE.md` → \"What NOT To Do\"): the coordinator holds per-overlay\n * state (the current animation timer, the describedby queue, the lifecycle\n * signal) and MUST be component-scoped.\n *\n * Scope of responsibility:\n * - Animation state signal (`state`) and `transitionDuration` computed.\n * - Enter/exit animation timing (`startEnterAnimation`, `startExitAnimation`)\n * with a `transitionend`-fallback timer.\n * - `animationStateChanged` EventEmitter forwarded to the consuming `Ref`.\n * - ARIA-describedby id queue (the matching labelledby queue is already\n * owned by CDK's `CdkDialogContainer._ariaLabelledByQueue`).\n *\n * Out of scope (stays on the container subclass):\n * - The `CdkDialogContainer` contract — focus trap, escape key, backdrop\n * click, overlay attach/detach. The container subclass keeps inheriting\n * `CdkDialogContainer` directly; this coordinator layers on top.\n * - Tailwind class resolution (`tv()` variant slots) — that's per-container.\n * - Host bindings on the container element — that's per-container.\n */\n@Injectable()\nexport class OverlayContainerCoordinator {\n private readonly destroyRef = inject(DestroyRef);\n\n private readonly stateSignal = signal<OverlayContainerState>('opening');\n private readonly ariaDescribedByQueue = signal<readonly string[]>([]);\n private readonly queue = new AriaIdQueue();\n\n private animationTimer: ReturnType<typeof setTimeout> | null = null;\n private enterDuration = 0;\n private exitDuration = 0;\n\n /** Lifecycle state of the container's enter/exit animation. */\n readonly state: Signal<OverlayContainerState> = this.stateSignal.asReadonly();\n\n /** Live snapshot of the describedby id queue. */\n readonly describedByIds: Signal<readonly string[]> = this.ariaDescribedByQueue.asReadonly();\n\n /**\n * Active transition duration for the current state — the enter duration for\n * `opening` / `open`, the exit duration for `closing`, and 0 once `closed`.\n * Drives the container's `[style.transition-duration.ms]` host binding so a\n * one-line `data-[state]` transition rule can run with per-call timing.\n */\n readonly transitionDuration = computed(() => {\n const current = this.stateSignal();\n if (current === 'opening' || current === 'open') return this.enterDuration;\n if (current === 'closing') return this.exitDuration;\n return 0;\n });\n\n /**\n * Emits whenever the animation state transitions. The container's `Ref`\n * (`TwDialogRef` / `SheetRef`) subscribes to drive its own lifecycle\n * (`afterOpened`, `afterClosed`, exit-animation completion).\n */\n readonly animationStateChanged = new EventEmitter<OverlayContainerAnimationEvent>();\n\n constructor() {\n this.destroyRef.onDestroy(() => {\n this.clearAnimationTimer();\n this.animationStateChanged.complete();\n });\n }\n\n /**\n * Records the resolved enter/exit durations for the open lifecycle.\n * Called once from the container constructor with values coerced via\n * `coerceOverlayDuration`. Stored on the coordinator so\n * `transitionDuration()` and the timer-driven state transitions read from\n * a single source.\n */\n setDurations(enter: number, exit: number): void {\n this.enterDuration = enter;\n this.exitDuration = exit;\n }\n\n /**\n * Drives the enter animation: emits `opening` immediately, then defers the\n * state flip to `open` by one frame so the browser applies the initial\n * (hidden / off-screen) styles before transitioning. If `enter` is `0`\n * everything resolves synchronously (no animation).\n */\n startEnterAnimation(): void {\n this.animationStateChanged.emit({ state: 'opening', totalTime: this.enterDuration });\n\n if (this.enterDuration === 0) {\n this.stateSignal.set('open');\n this.animationStateChanged.emit({ state: 'open', totalTime: 0 });\n return;\n }\n\n requestAnimationFrame(() => {\n this.stateSignal.set('open');\n this.runAnimationTimer(this.enterDuration, () => {\n this.animationStateChanged.emit({\n state: 'open',\n totalTime: this.enterDuration,\n });\n });\n });\n }\n\n /**\n * Drives the exit animation: emits `closing` synchronously and schedules\n * the `closed` emission for after the exit duration (+ a small fallback\n * padding) elapses. The consuming `Ref` listens for the `closed` emission\n * to detach the CDK overlay.\n */\n startExitAnimation(): void {\n this.stateSignal.set('closing');\n this.animationStateChanged.emit({ state: 'closing', totalTime: this.exitDuration });\n\n this.runAnimationTimer(this.exitDuration, () => {\n this.stateSignal.set('closed');\n this.animationStateChanged.emit({ state: 'closed', totalTime: this.exitDuration });\n });\n }\n\n /** Registers a description id with the `aria-describedby` queue. */\n addAriaDescribedBy(id: string): void {\n this.queue.add(id);\n this.ariaDescribedByQueue.set(this.queue.snapshot());\n }\n\n /** Removes a previously registered description id. */\n removeAriaDescribedBy(id: string): void {\n this.queue.remove(id);\n this.ariaDescribedByQueue.set(this.queue.snapshot());\n }\n\n /** First-registered-wins resolution for the `aria-describedby` attribute. */\n firstDescribedBy(): string | null {\n return this.queue.first();\n }\n\n private runAnimationTimer(duration: number, callback: () => void): void {\n this.clearAnimationTimer();\n if (duration === 0) {\n callback();\n return;\n }\n this.animationTimer = setTimeout(callback, duration + OVERLAY_ANIMATION_FALLBACK_PADDING);\n }\n\n private clearAnimationTimer(): void {\n if (this.animationTimer !== null) {\n clearTimeout(this.animationTimer);\n this.animationTimer = null;\n }\n }\n}\n","import { tv } from 'tailwind-variants';\nimport type { TwColor } from './types';\n\n/**\n * Visual style shared by `tw-tabs` (`TabsVariant`) and `nav[twTabNav]` (`TabNavVariant`).\n * Kept as a string-literal union so downstream consumers can narrow when needed.\n */\nexport type TabTriggerVariant = 'underline' | 'enclosed' | 'pill';\n\n/**\n * Trigger-only tailwind-variants config shared by tabs and tab-nav.\n *\n * Both components own additional component-local slots (tablist/list/panel/nav,\n * etc.) — only the trigger shape is canonical enough to share here. The\n * resulting class string is merged with each component's local trigger\n * additions (e.g. tab-nav prepends `no-underline` because anchor elements need\n * to override the default underline; tabs adds nothing extra at the base).\n *\n * Active and inactive trigger state is applied separately via\n * {@link getActiveTriggerClasses} / {@link getInactiveTriggerClasses} so the\n * `Record<TwColor, string>` lookups stay statically scannable by the Tailwind\n * v4 content scanner.\n */\nexport const tabTriggerVariants = tv(\n {\n slots: {\n trigger:\n 'inline-flex items-center gap-1.5 font-medium whitespace-nowrap cursor-pointer transition-colors duration-normal motion-reduce:transition-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500',\n },\n variants: {\n variant: {\n underline: {\n trigger: 'border-b-2 border-transparent -mb-px text-fg-muted hover:text-fg',\n },\n enclosed: {\n trigger:\n 'border border-transparent bg-surface-muted text-fg-muted hover:text-fg -mb-px',\n },\n pill: {\n trigger: 'rounded-md text-fg-muted hover:text-fg',\n },\n },\n // Pinned control heights — see `docs/vertical-rhythm.md`. Vertical padding\n // is deliberately absent: the height is declared, not derived, and the\n // trigger's own border (`border-b-2` on underline, `border` on enclosed)\n // sits *inside* it under Preflight's global `box-sizing: border-box`.\n // `inline-flex items-center` on the base slot does the centring.\n size: {\n xs: { trigger: 'px-2 text-xs h-6' },\n sm: { trigger: 'px-3 text-sm h-8' },\n md: { trigger: 'px-4 text-sm h-9' },\n lg: { trigger: 'px-5 text-base h-11' },\n xl: { trigger: 'px-6 text-base h-12' },\n },\n fitted: {\n true: { trigger: 'flex-1 justify-center' },\n false: {},\n },\n color: {\n primary: {},\n secondary: {},\n accent: {},\n neutral: {},\n info: {},\n success: {},\n warning: {},\n error: {},\n },\n },\n defaultVariants: {\n variant: 'underline',\n color: 'primary',\n size: 'md',\n fitted: false,\n },\n },\n { twMerge: true },\n);\n\n// ── Active-state class lookups ──\n// Slot tokens own light/dark contrast — no `dark:`, no shade picks. Classes\n// stay statically written so the Tailwind v4 scanner sees them. The neutral\n// rows use surface/fg/border tokens which already auto-adapt to dark mode.\n\n/** @internal Active trigger classes for horizontal underline variants, keyed by color. */\nconst UNDERLINE_ACTIVE_HORIZONTAL: Record<TwColor, string> = {\n primary: 'border-b-2 border-primary-border-strong text-primary-fg',\n secondary: 'border-b-2 border-secondary-border-strong text-secondary-fg',\n accent: 'border-b-2 border-accent-border-strong text-accent-fg',\n neutral: 'border-b-2 border-border-strong text-fg',\n info: 'border-b-2 border-info-border-strong text-info-fg',\n success: 'border-b-2 border-success-border-strong text-success-fg',\n warning: 'border-b-2 border-warning-border-strong text-warning-fg',\n error: 'border-b-2 border-error-border-strong text-error-fg',\n};\n\n/** @internal Active trigger classes for vertical underline variants, keyed by color. */\nconst UNDERLINE_ACTIVE_VERTICAL: Record<TwColor, string> = {\n primary: 'border-r-2 border-primary-border-strong text-primary-fg',\n secondary: 'border-r-2 border-secondary-border-strong text-secondary-fg',\n accent: 'border-r-2 border-accent-border-strong text-accent-fg',\n neutral: 'border-r-2 border-border-strong text-fg',\n info: 'border-r-2 border-info-border-strong text-info-fg',\n success: 'border-r-2 border-success-border-strong text-success-fg',\n warning: 'border-r-2 border-warning-border-strong text-warning-fg',\n error: 'border-r-2 border-error-border-strong text-error-fg',\n};\n\n/** @internal Active trigger classes for horizontal enclosed variants, keyed by color. */\nconst ENCLOSED_ACTIVE_HORIZONTAL: Record<TwColor, string> = {\n primary: 'bg-surface border border-border border-b-transparent text-primary-fg',\n secondary: 'bg-surface border border-border border-b-transparent text-secondary-fg',\n accent: 'bg-surface border border-border border-b-transparent text-accent-fg',\n neutral: 'bg-surface border border-border border-b-transparent text-fg',\n info: 'bg-surface border border-border border-b-transparent text-info-fg',\n success: 'bg-surface border border-border border-b-transparent text-success-fg',\n warning: 'bg-surface border border-border border-b-transparent text-warning-fg',\n error: 'bg-surface border border-border border-b-transparent text-error-fg',\n};\n\n/** @internal Active trigger classes for vertical enclosed variants, keyed by color. */\nconst ENCLOSED_ACTIVE_VERTICAL: Record<TwColor, string> = {\n primary: 'bg-surface border border-border border-r-transparent text-primary-fg',\n secondary: 'bg-surface border border-border border-r-transparent text-secondary-fg',\n accent: 'bg-surface border border-border border-r-transparent text-accent-fg',\n neutral: 'bg-surface border border-border border-r-transparent text-fg',\n info: 'bg-surface border border-border border-r-transparent text-info-fg',\n success: 'bg-surface border border-border border-r-transparent text-success-fg',\n warning: 'bg-surface border border-border border-r-transparent text-warning-fg',\n error: 'bg-surface border border-border border-r-transparent text-error-fg',\n};\n\n/** @internal Active trigger classes for pill variants, keyed by color. */\nconst PILL_ACTIVE: Record<TwColor, string> = {\n primary: 'bg-surface shadow-sm text-primary-fg',\n secondary: 'bg-surface shadow-sm text-secondary-fg',\n accent: 'bg-surface shadow-sm text-accent-fg',\n neutral: 'bg-surface shadow-sm text-fg',\n info: 'bg-surface shadow-sm text-info-fg',\n success: 'bg-surface shadow-sm text-success-fg',\n warning: 'bg-surface shadow-sm text-warning-fg',\n error: 'bg-surface shadow-sm text-error-fg',\n};\n\n/** @internal Inactive trigger classes keyed by variant. */\nconst INACTIVE_TRIGGER_CLASSES: Record<TabTriggerVariant, string> = {\n underline: 'border-transparent',\n enclosed: 'border-transparent bg-surface-muted',\n pill: '',\n};\n\n/**\n * Returns the active-state trigger class string for the given variant, color,\n * and orientation. Tab-nav callers pass `'horizontal'` since it is horizontal-only.\n */\nexport function getActiveTriggerClasses(\n variant: TabTriggerVariant,\n color: TwColor,\n orientation: 'horizontal' | 'vertical' = 'horizontal',\n): string {\n switch (variant) {\n case 'underline':\n return orientation === 'vertical'\n ? UNDERLINE_ACTIVE_VERTICAL[color]\n : UNDERLINE_ACTIVE_HORIZONTAL[color];\n case 'enclosed':\n return orientation === 'vertical'\n ? ENCLOSED_ACTIVE_VERTICAL[color]\n : ENCLOSED_ACTIVE_HORIZONTAL[color];\n case 'pill':\n return PILL_ACTIVE[color];\n }\n}\n\n/** Returns the inactive-state trigger class string for the given variant. */\nexport function getInactiveTriggerClasses(variant: TabTriggerVariant): string {\n return INACTIVE_TRIGGER_CLASSES[variant];\n}\n","/**\n * Pure helpers shared by `tw-time-picker` and `tw-calendar`'s `withTime`\n * controls. No Angular / CDK imports — safe to drop into either package\n * without pulling a circular dependency.\n */\n\n/** Supported time-picker formats. */\nexport type TimePickerFormat = '12h' | '24h';\n\n/** Meridiem used by the 12h format. */\nexport type TimePickerMeridiem = 'AM' | 'PM';\n\n/** Zero-pads a non-negative integer to exactly two digits. */\nexport function padTwo(value: number): string {\n return value < 10 ? `0${value}` : `${value}`;\n}\n\n/** Converts a 24h hour (0–23) to its 12h display value (1–12). */\nexport function to12h(hour24: number): number {\n const modded = hour24 % 12;\n return modded === 0 ? 12 : modded;\n}\n\n/** Builds a canonical 0–23 hour from a 12h display hour and meridiem. */\nexport function from12h(hour12: number, meridiem: TimePickerMeridiem): number {\n if (hour12 === 12) return meridiem === 'AM' ? 0 : 12;\n return meridiem === 'AM' ? hour12 : hour12 + 12;\n}\n\n/** Maximum allowed value for a field given the picker format. */\nexport function fieldMax(\n field: 'hour' | 'minute' | 'second',\n format: TimePickerFormat,\n): number {\n if (field === 'hour') return format === '12h' ? 12 : 23;\n return 59;\n}\n\n/** Minimum allowed value for a field given the picker format. */\nexport function fieldMin(\n field: 'hour' | 'minute' | 'second',\n format: TimePickerFormat,\n): number {\n return field === 'hour' && format === '12h' ? 1 : 0;\n}\n\n/**\n * Buffers a typed digit onto the current field text, matching the standard\n * two-digit time-field behaviour:\n * - empty + 'x' → 'x'\n * - 'x' + 'y' → 'xy' (if value stays in range)\n * - 'xy' + 'z' → 'z' (overflow → reset)\n * - any combo that would exceed `max` resets to the new digit alone.\n */\nexport function appendDigit(current: string, digit: string, max: number): string {\n if (!/^\\d$/.test(digit)) return current;\n if (current.length >= 2) return digit;\n const candidate = current + digit;\n const numeric = Number(candidate);\n if (numeric > max) return digit;\n return candidate;\n}\n\n/**\n * Reports whether `current` + `digit` unambiguously fills the field — either\n * because the buffer reaches two chars or because the first digit alone\n * already excludes a valid second digit (e.g., `'6'` for minutes, `'3'` for 24h\n * hour). Used to auto-advance focus to the next field.\n */\nexport function isTerminalDigit(current: string, digit: string, max: number): boolean {\n if (current.length === 1) return true;\n if (!/^\\d$/.test(digit)) return false;\n const maxFirst = Math.floor(max / 10);\n return Number(digit) > maxFirst;\n}\n\n/**\n * Steps a numeric value by `step`, wrapping inside `[min, max]`. Works for\n * arbitrary step sizes; a step of 0 behaves as 1 to protect against mis-configs.\n */\nexport function stepWithWrap(\n value: number,\n step: number,\n direction: 1 | -1,\n min: number,\n max: number,\n): number {\n const safeStep = Math.max(1, Math.abs(step));\n const range = max - min + 1;\n const delta = safeStep * direction;\n return ((((value - min + delta) % range) + range) % range) + min;\n}\n\n/** Clamps a number into `[min, max]` without wrapping. */\nexport function clamp(value: number, min: number, max: number): number {\n if (value < min) return min;\n if (value > max) return max;\n return value;\n}\n\n/** Parses a 1- or 2-digit text field; returns `null` if empty or non-numeric. */\nexport function parseField(text: string): number | null {\n if (!text) return null;\n if (!/^\\d{1,2}$/.test(text)) return null;\n return Number(text);\n}\n\n/** Total seconds since midnight for a (h, m, s) tuple — useful for min/max compare. */\nexport function timeOfDaySeconds(hour: number, minute: number, second: number): number {\n return hour * 3600 + minute * 60 + second;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,203 @@
1
+ import { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';
2
+ import { CalendarHarness } from '@cdevhub/ngx-tw/calendar/testing';
3
+
4
+ /**
5
+ * Harness for `tw-date-picker`.
6
+ *
7
+ * `tw-date-picker` splits its trigger across **two** elements and the
8
+ * distinction matters for every method here:
9
+ *
10
+ * - `input[role="combobox"]` carries the displayed text, `aria-required`,
11
+ * `aria-invalid` and `aria-disabled`. `getValue`, `setValue`, `getLabel`,
12
+ * `isRequired`, `isInvalid` and `isDisabled` all read it.
13
+ * - a sibling `button[aria-haspopup="dialog"]` opens the calendar. `open`,
14
+ * `close` and `isOpen` go through it.
15
+ *
16
+ * The calendar renders into the CDK overlay, outside the `tw-date-picker`
17
+ * host, so it is resolved through `documentRootLocatorFactory()`. A consumer
18
+ * loads this harness from the ordinary fixture loader — no
19
+ * `documentRootLoader` ceremony required.
20
+ *
21
+ * Day-grid navigation is not reimplemented here: `getCalendar()` returns the
22
+ * `CalendarHarness` from `@cdevhub/ngx-tw/calendar/testing`, which already
23
+ * owns cells, view switching and header paging.
24
+ *
25
+ * **Not usable with a projected `[slot=trigger]`.** That opts the component out
26
+ * of its default chrome, so neither the text input nor the trigger button is
27
+ * rendered and every method here fails to resolve its element. A custom trigger
28
+ * is whatever the consumer projected; drive it with their own harness or a
29
+ * plain DOM query.
30
+ */
31
+ class DatePickerHarness extends ComponentHarness {
32
+ static hostSelector = 'tw-date-picker';
33
+ input = this.locatorFor('input[role="combobox"]');
34
+ trigger = this.locatorFor('button[aria-haspopup="dialog"]');
35
+ /**
36
+ * The inline clear control — the only button in the default trigger chrome
37
+ * that is not the calendar trigger. A consumer projecting `[slot=trigger]`
38
+ * replaces that chrome entirely, so neither this nor `trigger` resolves then.
39
+ */
40
+ clearButton = this.locatorForOptional('button:not([aria-haspopup])');
41
+ /** Resolves the overlay's calendar, which lives outside this harness's host. */
42
+ calendar = this.documentRootLocatorFactory().locatorForOptional(CalendarHarness);
43
+ /** Predicate for `locatorFor` / `locatorForAll`. */
44
+ static with(options = {}) {
45
+ return new HarnessPredicate(DatePickerHarness, options)
46
+ .addOption('label', options.label, async (h, label) => HarnessPredicate.stringMatches(await h.getLabel(), label))
47
+ .addOption('value', options.value, async (h, value) => HarnessPredicate.stringMatches(await h.getValue(), value))
48
+ .addOption('disabled', options.disabled, async (h, disabled) => (await h.isDisabled()) === disabled);
49
+ }
50
+ /** The text input's accessible name, from `aria-label` when one is set. */
51
+ async getLabel() {
52
+ return (await this.input()).getAttribute('aria-label');
53
+ }
54
+ /**
55
+ * The formatted date currently shown in the text input. Empty string when no
56
+ * date is selected — the placeholder is not part of the value.
57
+ */
58
+ async getValue() {
59
+ return (await this.input()).getProperty('value');
60
+ }
61
+ /** The text input's `placeholder`, or `null` when none is set. */
62
+ async getPlaceholder() {
63
+ return (await this.input()).getAttribute('placeholder');
64
+ }
65
+ /**
66
+ * Types `value` into the text input and blurs, which is what commits it —
67
+ * `tw-date-picker` parses on blur (and on Enter), never on keystroke. An
68
+ * unparseable string commits `null` and puts the control in its parse-error
69
+ * state, exactly as it would for a user.
70
+ */
71
+ async setValue(value) {
72
+ const input = await this.input();
73
+ await input.focus();
74
+ await input.setInputValue(value);
75
+ // `setInputValue` only assigns `element.value`; the component listens on
76
+ // `input`, so the event has to be dispatched explicitly.
77
+ await input.dispatchEvent('input');
78
+ await input.blur();
79
+ await this.waitForTasksOutsideAngular();
80
+ }
81
+ /** Whether the calendar overlay is open, read from the trigger's `aria-expanded`. */
82
+ async isOpen() {
83
+ return (await (await this.trigger()).getAttribute('aria-expanded')) === 'true';
84
+ }
85
+ /** Whether the text input reports `aria-disabled="true"`. */
86
+ async isDisabled() {
87
+ return (await (await this.input()).getAttribute('aria-disabled')) === 'true';
88
+ }
89
+ /** Whether the text input reports `aria-invalid="true"`. */
90
+ async isInvalid() {
91
+ return (await (await this.input()).getAttribute('aria-invalid')) === 'true';
92
+ }
93
+ /**
94
+ * Whether the text input reports `aria-required="true"`. Reflects the
95
+ * `required` input *and* a `Validators.required` on a bound control.
96
+ */
97
+ async isRequired() {
98
+ return (await (await this.input()).getAttribute('aria-required')) === 'true';
99
+ }
100
+ /**
101
+ * Opens the calendar overlay by clicking the trigger button. No-op when
102
+ * already open; a disabled picker ignores it, as it does in the browser.
103
+ */
104
+ async open() {
105
+ if (await this.isOpen())
106
+ return;
107
+ await (await this.trigger()).click();
108
+ await this.waitForTasksOutsideAngular();
109
+ }
110
+ /**
111
+ * Closes the calendar overlay by clicking the trigger button again. No-op
112
+ * when already closed.
113
+ *
114
+ * Deliberately not Escape: `tw-date-picker` treats Escape as *cancel* and
115
+ * restores the value the overlay opened with, which would make `close()`
116
+ * silently undo a selection. The trigger toggles without that side effect.
117
+ *
118
+ * The overlay runs a leave animation before it detaches, so `isOpen()` flips
119
+ * to `false` immediately while the panel element lingers for a few more
120
+ * frames. Two consequences worth knowing:
121
+ *
122
+ * - Do not assert `getCalendar()` is `null` on the tick after a close; the
123
+ * old panel is still mounted.
124
+ * - An `open()` inside that window does **not** attach a fresh panel — the
125
+ * component sees an overlay ref it has not disposed yet and silently
126
+ * keeps the outgoing one. Let the animation finish before reopening.
127
+ */
128
+ async close() {
129
+ if (!(await this.isOpen()))
130
+ return;
131
+ await (await this.trigger()).click();
132
+ await this.waitForTasksOutsideAngular();
133
+ }
134
+ /**
135
+ * The `CalendarHarness` for the open overlay, or `null` when no overlay is
136
+ * attached. Use it for anything grid-shaped — paging months, switching to the
137
+ * year view, reading disabled cells.
138
+ */
139
+ async getCalendar() {
140
+ return this.calendar();
141
+ }
142
+ /**
143
+ * Opens the overlay if needed and clicks the calendar cell whose text matches
144
+ * `day` exactly (`'15'`, not `'April 15'`). Throws when no such cell is
145
+ * visible in the current view.
146
+ *
147
+ * With `showActions` off this commits and closes; with it on the pick stays
148
+ * pending until {@link clickAction} confirms it.
149
+ */
150
+ async selectDay(day) {
151
+ await this.open();
152
+ const calendar = await this.getCalendar();
153
+ if (!calendar) {
154
+ throw new Error('DatePickerHarness.selectDay: the calendar overlay is not attached.');
155
+ }
156
+ await calendar.selectCell(day);
157
+ await this.waitForTasksOutsideAngular();
158
+ }
159
+ /**
160
+ * Clicks a button in the overlay's action bar (`Today`, `Clear`, `Cancel`,
161
+ * `Apply`) by its visible text. Matching on text rather than position is what
162
+ * keeps this usable when a consumer relabels the actions via `todayLabel` and
163
+ * friends — pass whatever label you configured.
164
+ *
165
+ * Preset entries are excluded: they are `role="option"`, not action buttons.
166
+ * Throws when the overlay is closed or nothing matches.
167
+ */
168
+ async clickAction(label) {
169
+ const buttons = await this.documentRootLocatorFactory().locatorForAll('tw-date-picker-overlay button:not([role="option"])')();
170
+ for (const button of buttons) {
171
+ if (await HarnessPredicate.stringMatches((await button.text()).trim(), label)) {
172
+ await button.click();
173
+ await this.waitForTasksOutsideAngular();
174
+ return;
175
+ }
176
+ }
177
+ throw new Error(`DatePickerHarness.clickAction: no overlay action button matching ${String(label)}. Is the overlay open and \`showActions\` on?`);
178
+ }
179
+ /**
180
+ * Whether the inline clear control is rendered. It appears only while
181
+ * `showClear` is on, the picker is enabled and not readonly, and a value is
182
+ * set.
183
+ */
184
+ async hasClearButton() {
185
+ return (await this.clearButton()) !== null;
186
+ }
187
+ /** Clicks the inline clear control. Throws when none is rendered. */
188
+ async clear() {
189
+ const button = await this.clearButton();
190
+ if (!button) {
191
+ throw new Error('DatePickerHarness.clear: no clear control is rendered. It appears only while `showClear` is on, the picker is enabled and not readonly, and a value is set.');
192
+ }
193
+ await button.click();
194
+ await this.waitForTasksOutsideAngular();
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Generated bundle index. Do not edit.
200
+ */
201
+
202
+ export { DatePickerHarness };
203
+ //# sourceMappingURL=cdevhub-ngx-tw-date-picker-testing.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdevhub-ngx-tw-date-picker-testing.mjs","sources":["../../../projects/ngx-tw/date-picker/testing/date-picker-harness.ts","../../../projects/ngx-tw/date-picker/testing/cdevhub-ngx-tw-date-picker-testing.ts"],"sourcesContent":["import { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';\nimport type { BaseHarnessFilters, TestElement } from '@angular/cdk/testing';\nimport { CalendarHarness } from '@cdevhub/ngx-tw/calendar/testing';\n\n/** Filters accepted by `DatePickerHarness.with`. */\nexport interface DatePickerHarnessFilters extends BaseHarnessFilters {\n /** Match by the text input's accessible name. */\n label?: string | RegExp;\n /** Match by the text currently displayed in the input. */\n value?: string | RegExp;\n /** Match disabled / enabled pickers. */\n disabled?: boolean;\n}\n\n/**\n * Harness for `tw-date-picker`.\n *\n * `tw-date-picker` splits its trigger across **two** elements and the\n * distinction matters for every method here:\n *\n * - `input[role=\"combobox\"]` carries the displayed text, `aria-required`,\n * `aria-invalid` and `aria-disabled`. `getValue`, `setValue`, `getLabel`,\n * `isRequired`, `isInvalid` and `isDisabled` all read it.\n * - a sibling `button[aria-haspopup=\"dialog\"]` opens the calendar. `open`,\n * `close` and `isOpen` go through it.\n *\n * The calendar renders into the CDK overlay, outside the `tw-date-picker`\n * host, so it is resolved through `documentRootLocatorFactory()`. A consumer\n * loads this harness from the ordinary fixture loader — no\n * `documentRootLoader` ceremony required.\n *\n * Day-grid navigation is not reimplemented here: `getCalendar()` returns the\n * `CalendarHarness` from `@cdevhub/ngx-tw/calendar/testing`, which already\n * owns cells, view switching and header paging.\n *\n * **Not usable with a projected `[slot=trigger]`.** That opts the component out\n * of its default chrome, so neither the text input nor the trigger button is\n * rendered and every method here fails to resolve its element. A custom trigger\n * is whatever the consumer projected; drive it with their own harness or a\n * plain DOM query.\n */\nexport class DatePickerHarness extends ComponentHarness {\n static hostSelector = 'tw-date-picker';\n\n private readonly input = this.locatorFor('input[role=\"combobox\"]');\n private readonly trigger = this.locatorFor('button[aria-haspopup=\"dialog\"]');\n /**\n * The inline clear control — the only button in the default trigger chrome\n * that is not the calendar trigger. A consumer projecting `[slot=trigger]`\n * replaces that chrome entirely, so neither this nor `trigger` resolves then.\n */\n private readonly clearButton = this.locatorForOptional('button:not([aria-haspopup])');\n /** Resolves the overlay's calendar, which lives outside this harness's host. */\n private readonly calendar =\n this.documentRootLocatorFactory().locatorForOptional(CalendarHarness);\n\n /** Predicate for `locatorFor` / `locatorForAll`. */\n static with(options: DatePickerHarnessFilters = {}): HarnessPredicate<DatePickerHarness> {\n return new HarnessPredicate(DatePickerHarness, options)\n .addOption('label', options.label, async (h, label) =>\n HarnessPredicate.stringMatches(await h.getLabel(), label),\n )\n .addOption('value', options.value, async (h, value) =>\n HarnessPredicate.stringMatches(await h.getValue(), value),\n )\n .addOption(\n 'disabled',\n options.disabled,\n async (h, disabled) => (await h.isDisabled()) === disabled,\n );\n }\n\n /** The text input's accessible name, from `aria-label` when one is set. */\n async getLabel(): Promise<string | null> {\n return (await this.input()).getAttribute('aria-label');\n }\n\n /**\n * The formatted date currently shown in the text input. Empty string when no\n * date is selected — the placeholder is not part of the value.\n */\n async getValue(): Promise<string> {\n return (await this.input()).getProperty<string>('value');\n }\n\n /** The text input's `placeholder`, or `null` when none is set. */\n async getPlaceholder(): Promise<string | null> {\n return (await this.input()).getAttribute('placeholder');\n }\n\n /**\n * Types `value` into the text input and blurs, which is what commits it —\n * `tw-date-picker` parses on blur (and on Enter), never on keystroke. An\n * unparseable string commits `null` and puts the control in its parse-error\n * state, exactly as it would for a user.\n */\n async setValue(value: string): Promise<void> {\n const input = await this.input();\n await input.focus();\n await input.setInputValue(value);\n // `setInputValue` only assigns `element.value`; the component listens on\n // `input`, so the event has to be dispatched explicitly.\n await input.dispatchEvent('input');\n await input.blur();\n await this.waitForTasksOutsideAngular();\n }\n\n /** Whether the calendar overlay is open, read from the trigger's `aria-expanded`. */\n async isOpen(): Promise<boolean> {\n return (await (await this.trigger()).getAttribute('aria-expanded')) === 'true';\n }\n\n /** Whether the text input reports `aria-disabled=\"true\"`. */\n async isDisabled(): Promise<boolean> {\n return (await (await this.input()).getAttribute('aria-disabled')) === 'true';\n }\n\n /** Whether the text input reports `aria-invalid=\"true\"`. */\n async isInvalid(): Promise<boolean> {\n return (await (await this.input()).getAttribute('aria-invalid')) === 'true';\n }\n\n /**\n * Whether the text input reports `aria-required=\"true\"`. Reflects the\n * `required` input *and* a `Validators.required` on a bound control.\n */\n async isRequired(): Promise<boolean> {\n return (await (await this.input()).getAttribute('aria-required')) === 'true';\n }\n\n /**\n * Opens the calendar overlay by clicking the trigger button. No-op when\n * already open; a disabled picker ignores it, as it does in the browser.\n */\n async open(): Promise<void> {\n if (await this.isOpen()) return;\n await (await this.trigger()).click();\n await this.waitForTasksOutsideAngular();\n }\n\n /**\n * Closes the calendar overlay by clicking the trigger button again. No-op\n * when already closed.\n *\n * Deliberately not Escape: `tw-date-picker` treats Escape as *cancel* and\n * restores the value the overlay opened with, which would make `close()`\n * silently undo a selection. The trigger toggles without that side effect.\n *\n * The overlay runs a leave animation before it detaches, so `isOpen()` flips\n * to `false` immediately while the panel element lingers for a few more\n * frames. Two consequences worth knowing:\n *\n * - Do not assert `getCalendar()` is `null` on the tick after a close; the\n * old panel is still mounted.\n * - An `open()` inside that window does **not** attach a fresh panel — the\n * component sees an overlay ref it has not disposed yet and silently\n * keeps the outgoing one. Let the animation finish before reopening.\n */\n async close(): Promise<void> {\n if (!(await this.isOpen())) return;\n await (await this.trigger()).click();\n await this.waitForTasksOutsideAngular();\n }\n\n /**\n * The `CalendarHarness` for the open overlay, or `null` when no overlay is\n * attached. Use it for anything grid-shaped — paging months, switching to the\n * year view, reading disabled cells.\n */\n async getCalendar(): Promise<CalendarHarness | null> {\n return this.calendar();\n }\n\n /**\n * Opens the overlay if needed and clicks the calendar cell whose text matches\n * `day` exactly (`'15'`, not `'April 15'`). Throws when no such cell is\n * visible in the current view.\n *\n * With `showActions` off this commits and closes; with it on the pick stays\n * pending until {@link clickAction} confirms it.\n */\n async selectDay(day: string): Promise<void> {\n await this.open();\n const calendar = await this.getCalendar();\n if (!calendar) {\n throw new Error('DatePickerHarness.selectDay: the calendar overlay is not attached.');\n }\n await calendar.selectCell(day);\n await this.waitForTasksOutsideAngular();\n }\n\n /**\n * Clicks a button in the overlay's action bar (`Today`, `Clear`, `Cancel`,\n * `Apply`) by its visible text. Matching on text rather than position is what\n * keeps this usable when a consumer relabels the actions via `todayLabel` and\n * friends — pass whatever label you configured.\n *\n * Preset entries are excluded: they are `role=\"option\"`, not action buttons.\n * Throws when the overlay is closed or nothing matches.\n */\n async clickAction(label: string | RegExp): Promise<void> {\n const buttons = await this.documentRootLocatorFactory().locatorForAll(\n 'tw-date-picker-overlay button:not([role=\"option\"])',\n )();\n for (const button of buttons) {\n if (await HarnessPredicate.stringMatches((await button.text()).trim(), label)) {\n await button.click();\n await this.waitForTasksOutsideAngular();\n return;\n }\n }\n throw new Error(\n `DatePickerHarness.clickAction: no overlay action button matching ${String(label)}. Is the overlay open and \\`showActions\\` on?`,\n );\n }\n\n /**\n * Whether the inline clear control is rendered. It appears only while\n * `showClear` is on, the picker is enabled and not readonly, and a value is\n * set.\n */\n async hasClearButton(): Promise<boolean> {\n return (await this.clearButton()) !== null;\n }\n\n /** Clicks the inline clear control. Throws when none is rendered. */\n async clear(): Promise<void> {\n const button: TestElement | null = await this.clearButton();\n if (!button) {\n throw new Error(\n 'DatePickerHarness.clear: no clear control is rendered. It appears only while `showClear` is on, the picker is enabled and not readonly, and a value is set.',\n );\n }\n await button.click();\n await this.waitForTasksOutsideAngular();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}