ngwr 11.0.0 → 11.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/action-sheet/styles/_index.scss +4 -1
  2. package/anchor/styles/_index.scss +2 -1
  3. package/calendar/styles/_index.scss +11 -2
  4. package/cascader/styles/_index.scss +3 -1
  5. package/circular-text/styles/_index.scss +11 -0
  6. package/command-palette/styles/_index.scss +14 -1
  7. package/context-menu/styles/_index.scss +2 -1
  8. package/falling-text/styles/_index.scss +2 -1
  9. package/fesm2022/ngwr-action-sheet-testing.mjs +313 -0
  10. package/fesm2022/ngwr-action-sheet-testing.mjs.map +1 -0
  11. package/fesm2022/ngwr-bar-chart-testing.mjs +89 -0
  12. package/fesm2022/ngwr-bar-chart-testing.mjs.map +1 -0
  13. package/fesm2022/ngwr-blur-text-testing.mjs +203 -0
  14. package/fesm2022/ngwr-blur-text-testing.mjs.map +1 -0
  15. package/fesm2022/ngwr-blur-text.mjs +15 -1
  16. package/fesm2022/ngwr-blur-text.mjs.map +1 -1
  17. package/fesm2022/ngwr-border-glow-testing.mjs +325 -0
  18. package/fesm2022/ngwr-border-glow-testing.mjs.map +1 -0
  19. package/fesm2022/ngwr-border-glow.mjs +2 -2
  20. package/fesm2022/ngwr-breadcrumbs.mjs +2 -2
  21. package/fesm2022/ngwr-calendar-heatmap-testing.mjs +95 -0
  22. package/fesm2022/ngwr-calendar-heatmap-testing.mjs.map +1 -0
  23. package/fesm2022/ngwr-calendar-testing.mjs +368 -0
  24. package/fesm2022/ngwr-calendar-testing.mjs.map +1 -0
  25. package/fesm2022/ngwr-calendar.mjs +43 -3
  26. package/fesm2022/ngwr-calendar.mjs.map +1 -1
  27. package/fesm2022/ngwr-card.mjs +2 -2
  28. package/fesm2022/ngwr-cascader.mjs +14 -2
  29. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  30. package/fesm2022/ngwr-checkbox.mjs +8 -0
  31. package/fesm2022/ngwr-checkbox.mjs.map +1 -1
  32. package/fesm2022/ngwr-circular-text-testing.mjs +230 -0
  33. package/fesm2022/ngwr-circular-text-testing.mjs.map +1 -0
  34. package/fesm2022/ngwr-circular-text.mjs +2 -2
  35. package/fesm2022/ngwr-circular-text.mjs.map +1 -1
  36. package/fesm2022/ngwr-color-picker-testing.mjs +432 -0
  37. package/fesm2022/ngwr-color-picker-testing.mjs.map +1 -0
  38. package/fesm2022/ngwr-color-picker.mjs +29 -3
  39. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  40. package/fesm2022/ngwr-context-menu.mjs +25 -5
  41. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  42. package/fesm2022/ngwr-date-picker-testing.mjs +10 -79
  43. package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -1
  44. package/fesm2022/ngwr-decrypt-text-testing.mjs +261 -0
  45. package/fesm2022/ngwr-decrypt-text-testing.mjs.map +1 -0
  46. package/fesm2022/ngwr-decrypt-text.mjs +6 -1
  47. package/fesm2022/ngwr-decrypt-text.mjs.map +1 -1
  48. package/fesm2022/ngwr-donut-chart-testing.mjs +93 -0
  49. package/fesm2022/ngwr-donut-chart-testing.mjs.map +1 -0
  50. package/fesm2022/ngwr-drag-drop.mjs +2 -2
  51. package/fesm2022/ngwr-drawer.mjs +36 -7
  52. package/fesm2022/ngwr-drawer.mjs.map +1 -1
  53. package/fesm2022/ngwr-dropdown.mjs +32 -2
  54. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  55. package/fesm2022/ngwr-event-calendar-testing.mjs +446 -0
  56. package/fesm2022/ngwr-event-calendar-testing.mjs.map +1 -0
  57. package/fesm2022/ngwr-event-calendar.mjs +43 -18
  58. package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
  59. package/fesm2022/ngwr-falling-text-testing.mjs +218 -0
  60. package/fesm2022/ngwr-falling-text-testing.mjs.map +1 -0
  61. package/fesm2022/ngwr-falling-text.mjs +2 -2
  62. package/fesm2022/ngwr-falling-text.mjs.map +1 -1
  63. package/fesm2022/ngwr-fuzzy-text-testing.mjs +134 -0
  64. package/fesm2022/ngwr-fuzzy-text-testing.mjs.map +1 -0
  65. package/fesm2022/ngwr-gauge-testing.mjs +86 -0
  66. package/fesm2022/ngwr-gauge-testing.mjs.map +1 -0
  67. package/fesm2022/ngwr-glitch-text-testing.mjs +181 -0
  68. package/fesm2022/ngwr-glitch-text-testing.mjs.map +1 -0
  69. package/fesm2022/ngwr-glitch-text.mjs +2 -2
  70. package/fesm2022/ngwr-gradient-text-testing.mjs +223 -0
  71. package/fesm2022/ngwr-gradient-text-testing.mjs.map +1 -0
  72. package/fesm2022/ngwr-gradient-text.mjs +2 -2
  73. package/fesm2022/ngwr-i18n-en.mjs +14 -0
  74. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  75. package/fesm2022/ngwr-i18n-ru.mjs +14 -0
  76. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  77. package/fesm2022/ngwr-image-cropper-testing.mjs +156 -0
  78. package/fesm2022/ngwr-image-cropper-testing.mjs.map +1 -0
  79. package/fesm2022/ngwr-image-cropper.mjs +10 -3
  80. package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
  81. package/fesm2022/ngwr-input-number.mjs +73 -6
  82. package/fesm2022/ngwr-input-number.mjs.map +1 -1
  83. package/fesm2022/ngwr-knob-testing.mjs +220 -0
  84. package/fesm2022/ngwr-knob-testing.mjs.map +1 -0
  85. package/fesm2022/ngwr-lightbox-testing.mjs +223 -0
  86. package/fesm2022/ngwr-lightbox-testing.mjs.map +1 -0
  87. package/fesm2022/ngwr-lightbox.mjs +9 -2
  88. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  89. package/fesm2022/ngwr-line-chart-testing.mjs +119 -0
  90. package/fesm2022/ngwr-line-chart-testing.mjs.map +1 -0
  91. package/fesm2022/ngwr-list.mjs +2 -2
  92. package/fesm2022/ngwr-loading-bar.mjs +2 -2
  93. package/fesm2022/ngwr-marquee-testing.mjs +336 -0
  94. package/fesm2022/ngwr-marquee-testing.mjs.map +1 -0
  95. package/fesm2022/ngwr-marquee.mjs +2 -2
  96. package/fesm2022/ngwr-meter-group-testing.mjs +80 -0
  97. package/fesm2022/ngwr-meter-group-testing.mjs.map +1 -0
  98. package/fesm2022/ngwr-overlay.mjs +28 -1
  99. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  100. package/fesm2022/ngwr-popover.mjs +14 -0
  101. package/fesm2022/ngwr-popover.mjs.map +1 -1
  102. package/fesm2022/ngwr-rotating-text-testing.mjs +220 -0
  103. package/fesm2022/ngwr-rotating-text-testing.mjs.map +1 -0
  104. package/fesm2022/ngwr-rotating-text.mjs +2 -2
  105. package/fesm2022/ngwr-rotating-text.mjs.map +1 -1
  106. package/fesm2022/ngwr-select.mjs +70 -11
  107. package/fesm2022/ngwr-select.mjs.map +1 -1
  108. package/fesm2022/ngwr-shiny-text-testing.mjs +237 -0
  109. package/fesm2022/ngwr-shiny-text-testing.mjs.map +1 -0
  110. package/fesm2022/ngwr-shiny-text.mjs +2 -2
  111. package/fesm2022/ngwr-slider.mjs +44 -6
  112. package/fesm2022/ngwr-slider.mjs.map +1 -1
  113. package/fesm2022/ngwr-sparkline-testing.mjs +76 -0
  114. package/fesm2022/ngwr-sparkline-testing.mjs.map +1 -0
  115. package/fesm2022/ngwr-speed-dial-testing.mjs +279 -0
  116. package/fesm2022/ngwr-speed-dial-testing.mjs.map +1 -0
  117. package/fesm2022/ngwr-splash-cursor-testing.mjs +89 -0
  118. package/fesm2022/ngwr-splash-cursor-testing.mjs.map +1 -0
  119. package/fesm2022/ngwr-split-text-testing.mjs +224 -0
  120. package/fesm2022/ngwr-split-text-testing.mjs.map +1 -0
  121. package/fesm2022/ngwr-split-text.mjs +15 -1
  122. package/fesm2022/ngwr-split-text.mjs.map +1 -1
  123. package/fesm2022/ngwr-splitter-testing.mjs +245 -0
  124. package/fesm2022/ngwr-splitter-testing.mjs.map +1 -0
  125. package/fesm2022/ngwr-spotlight-card-testing.mjs +368 -0
  126. package/fesm2022/ngwr-spotlight-card-testing.mjs.map +1 -0
  127. package/fesm2022/ngwr-spotlight-card.mjs +2 -2
  128. package/fesm2022/ngwr-star-border-testing.mjs +172 -0
  129. package/fesm2022/ngwr-star-border-testing.mjs.map +1 -0
  130. package/fesm2022/ngwr-star-border.mjs +2 -2
  131. package/fesm2022/ngwr-table.mjs +13 -3
  132. package/fesm2022/ngwr-table.mjs.map +1 -1
  133. package/fesm2022/ngwr-tabs.mjs +15 -1
  134. package/fesm2022/ngwr-tabs.mjs.map +1 -1
  135. package/fesm2022/ngwr-tilt-card-testing.mjs +190 -0
  136. package/fesm2022/ngwr-tilt-card-testing.mjs.map +1 -0
  137. package/fesm2022/ngwr-tilt-card.mjs +21 -3
  138. package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
  139. package/fesm2022/ngwr-toast.mjs +36 -7
  140. package/fesm2022/ngwr-toast.mjs.map +1 -1
  141. package/fesm2022/ngwr-tour-testing.mjs +173 -0
  142. package/fesm2022/ngwr-tour-testing.mjs.map +1 -0
  143. package/fesm2022/ngwr-tour.mjs +2 -2
  144. package/fesm2022/ngwr-tour.mjs.map +1 -1
  145. package/fesm2022/ngwr-tree.mjs +10 -3
  146. package/fesm2022/ngwr-tree.mjs.map +1 -1
  147. package/fesm2022/ngwr-typewriter-testing.mjs +228 -0
  148. package/fesm2022/ngwr-typewriter-testing.mjs.map +1 -0
  149. package/fesm2022/ngwr-typewriter.mjs +2 -2
  150. package/fesm2022/ngwr-version.mjs +1 -1
  151. package/fesm2022/ngwr-version.mjs.map +1 -1
  152. package/fesm2022/ngwr-virtual-scroll.mjs +2 -2
  153. package/fesm2022/ngwr-waves-testing.mjs +128 -0
  154. package/fesm2022/ngwr-waves-testing.mjs.map +1 -0
  155. package/fesm2022/ngwr-waves.mjs +2 -2
  156. package/fesm2022/ngwr-window-testing.mjs +361 -0
  157. package/fesm2022/ngwr-window-testing.mjs.map +1 -0
  158. package/fesm2022/ngwr-window.mjs +84 -10
  159. package/fesm2022/ngwr-window.mjs.map +1 -1
  160. package/file-upload/styles/_index.scss +7 -2
  161. package/i18n/en.json +16 -2
  162. package/i18n/ru.json +16 -2
  163. package/llms-full.txt +147 -0
  164. package/llms.txt +27 -8
  165. package/mcp/providers.js +29 -0
  166. package/mcp/tools.js +1 -29
  167. package/package.json +145 -1
  168. package/result/styles/_index.scss +3 -1
  169. package/segmented/styles/_index.scss +5 -1
  170. package/select/styles/_index.scss +3 -1
  171. package/skills/ngwr/SKILL.md +115 -0
  172. package/skills/ngwr/references/catalog.md +212 -0
  173. package/skills/ngwr/references/setup.md +73 -0
  174. package/stepper/styles/_index.scss +18 -2
  175. package/table/styles/_index.scss +3 -1
  176. package/theme/styles/_colors.scss +15 -2
  177. package/theme/styles/_dark.scss +24 -12
  178. package/tree/styles/_index.scss +4 -2
  179. package/types/ngwr-action-sheet-testing.d.ts +260 -0
  180. package/types/ngwr-bar-chart-testing.d.ts +77 -0
  181. package/types/ngwr-blur-text-testing.d.ts +180 -0
  182. package/types/ngwr-blur-text.d.ts +12 -0
  183. package/types/ngwr-border-glow-testing.d.ts +219 -0
  184. package/types/ngwr-calendar-heatmap-testing.d.ts +79 -0
  185. package/types/ngwr-calendar-testing.d.ts +277 -0
  186. package/types/ngwr-calendar.d.ts +10 -0
  187. package/types/ngwr-checkbox.d.ts +13 -0
  188. package/types/ngwr-circular-text-testing.d.ts +196 -0
  189. package/types/ngwr-color-picker-testing.d.ts +291 -0
  190. package/types/ngwr-color-picker.d.ts +13 -1
  191. package/types/ngwr-context-menu.d.ts +15 -1
  192. package/types/ngwr-date-picker-testing.d.ts +6 -66
  193. package/types/ngwr-decrypt-text-testing.d.ts +222 -0
  194. package/types/ngwr-donut-chart-testing.d.ts +79 -0
  195. package/types/ngwr-drawer.d.ts +12 -0
  196. package/types/ngwr-dropdown.d.ts +9 -0
  197. package/types/ngwr-event-calendar-testing.d.ts +301 -0
  198. package/types/ngwr-event-calendar.d.ts +9 -6
  199. package/types/ngwr-falling-text-testing.d.ts +186 -0
  200. package/types/ngwr-fuzzy-text-testing.d.ts +130 -0
  201. package/types/ngwr-gauge-testing.d.ts +71 -0
  202. package/types/ngwr-glitch-text-testing.d.ts +172 -0
  203. package/types/ngwr-gradient-text-testing.d.ts +173 -0
  204. package/types/ngwr-image-cropper-testing.d.ts +134 -0
  205. package/types/ngwr-image-cropper.d.ts +1 -0
  206. package/types/ngwr-input-number.d.ts +33 -1
  207. package/types/ngwr-knob-testing.d.ts +150 -0
  208. package/types/ngwr-lightbox-testing.d.ts +154 -0
  209. package/types/ngwr-lightbox.d.ts +6 -0
  210. package/types/ngwr-line-chart-testing.d.ts +93 -0
  211. package/types/ngwr-marquee-testing.d.ts +280 -0
  212. package/types/ngwr-meter-group-testing.d.ts +67 -0
  213. package/types/ngwr-overlay.d.ts +19 -1
  214. package/types/ngwr-rotating-text-testing.d.ts +191 -0
  215. package/types/ngwr-select.d.ts +32 -0
  216. package/types/ngwr-shiny-text-testing.d.ts +165 -0
  217. package/types/ngwr-slider.d.ts +15 -0
  218. package/types/ngwr-sparkline-testing.d.ts +69 -0
  219. package/types/ngwr-speed-dial-testing.d.ts +195 -0
  220. package/types/ngwr-splash-cursor-testing.d.ts +95 -0
  221. package/types/ngwr-split-text-testing.d.ts +209 -0
  222. package/types/ngwr-split-text.d.ts +12 -0
  223. package/types/ngwr-splitter-testing.d.ts +174 -0
  224. package/types/ngwr-spotlight-card-testing.d.ts +303 -0
  225. package/types/ngwr-star-border-testing.d.ts +135 -0
  226. package/types/ngwr-table.d.ts +10 -1
  227. package/types/ngwr-tilt-card-testing.d.ts +158 -0
  228. package/types/ngwr-tilt-card.d.ts +2 -0
  229. package/types/ngwr-toast.d.ts +14 -5
  230. package/types/ngwr-tour-testing.d.ts +143 -0
  231. package/types/ngwr-tree.d.ts +7 -0
  232. package/types/ngwr-typewriter-testing.d.ts +201 -0
  233. package/types/ngwr-version.d.ts +1 -1
  234. package/types/ngwr-waves-testing.d.ts +121 -0
  235. package/types/ngwr-window-testing.d.ts +263 -0
  236. package/types/ngwr-window.d.ts +27 -10
  237. package/window/styles/_index.scss +44 -16
@@ -0,0 +1,368 @@
1
+ import { ComponentHarness, HarnessPredicate, TestKey } from '@angular/cdk/testing';
2
+
3
+ /**
4
+ * @license
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
8
+ */
9
+ /**
10
+ * Test harness for one day cell of a `<wr-calendar>` grid.
11
+ *
12
+ * The cell belongs to the calendar, and a date-picker's popup is a calendar in an
13
+ * overlay — so this is the harness for both, re-exported from
14
+ * `ngwr/date-picker/testing` under the name it shipped as
15
+ * (`WrDatePickerDayHarness`). Reach it through `WrCalendarHarness.getDays()`, or
16
+ * through `WrDatePickerHarness.getDay()` / `getDays()`, which scope it to ONE
17
+ * picker's panel — those cells are in the shared overlay container, so a bare query
18
+ * would answer with whichever picker opened first.
19
+ *
20
+ * State is read the way a screen reader reads it (`role`, `aria-selected`,
21
+ * `aria-disabled`) with the `.wr-calendar__day--*` modifiers filling in what
22
+ * ARIA has no word for: today, the spill days of the neighbouring months, and
23
+ * the interior of a picked range.
24
+ *
25
+ * @see https://ngwr.dev/guides/testing
26
+ */
27
+ class WrCalendarDayHarness extends ComponentHarness {
28
+ static hostSelector = '.wr-calendar__day';
29
+ /** Build a predicate that narrows the query. */
30
+ static with(options = {}) {
31
+ return new HarnessPredicate(WrCalendarDayHarness, options)
32
+ .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text))
33
+ .addOption('selected', options.selected, async (harness, selected) => (await harness.isSelected()) === selected)
34
+ .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)
35
+ .addOption('inRange', options.inRange, async (harness, inRange) => (await harness.isInRange()) === inRange);
36
+ }
37
+ /** The day number as rendered. */
38
+ async getText() {
39
+ return (await this.host()).text();
40
+ }
41
+ /** The day number as a number, for mapping a list of cells to dates. */
42
+ async getDayOfMonth() {
43
+ return Number(await this.getText());
44
+ }
45
+ /** `'gridcell'` — the cell is a button, and the grid semantics are what a spec should assert. */
46
+ async getRole() {
47
+ return (await this.host()).getAttribute('role');
48
+ }
49
+ /** Whether this day is (one end of) the current selection. */
50
+ async isSelected() {
51
+ return (await (await this.host()).getAttribute('aria-selected')) === 'true';
52
+ }
53
+ /**
54
+ * Whether the day refuses selection — `min` / `max` or `dateFilter` ruled it
55
+ * out, or the whole calendar is disabled.
56
+ */
57
+ async isDisabled() {
58
+ return (await (await this.host()).getAttribute('aria-disabled')) === 'true';
59
+ }
60
+ /** Whether the cell is today's date. */
61
+ async isToday() {
62
+ return (await this.host()).hasClass('wr-calendar__day--today');
63
+ }
64
+ /**
65
+ * Whether the cell belongs to a neighbouring month. The grid is always 6x7, so
66
+ * every month is padded with days that are selectable but not "in" the month —
67
+ * which is why `WrDatePickerHarness.getDay` and {@link WrCalendarHarness.getDay} skip them.
68
+ */
69
+ async isOutOfMonth() {
70
+ return (await this.host()).hasClass('wr-calendar__day--out-of-month');
71
+ }
72
+ /** Whether the day lies strictly between the two ends of a picked range. */
73
+ async isInRange() {
74
+ return (await this.host()).hasClass('wr-calendar__day--in-range');
75
+ }
76
+ /**
77
+ * Whether this is the roving cell — the grid's single tab stop, and where the
78
+ * arrow keys move from.
79
+ *
80
+ * At most ONE cell answers `true`, and it is not always one: the calendar's
81
+ * roving date does not follow `next()` / `previous()`, so a grid navigated away
82
+ * from that month has no active cell (and, deliberately or not, no tab stop)
83
+ * until a cell is clicked or the arrows move it.
84
+ */
85
+ async isActive() {
86
+ return (await this.host()).hasClass('wr-calendar__day--focused');
87
+ }
88
+ /** Click the cell. A disabled cell swallows the click — assert, do not assume. */
89
+ async click() {
90
+ return (await this.host()).click();
91
+ }
92
+ }
93
+
94
+ /**
95
+ * @license
96
+ *
97
+ * Use of this source code is governed by an MIT-style license that can be
98
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
99
+ */
100
+ const ARROWS = {
101
+ left: TestKey.LEFT_ARROW,
102
+ right: TestKey.RIGHT_ARROW,
103
+ up: TestKey.UP_ARROW,
104
+ down: TestKey.DOWN_ARROW,
105
+ };
106
+ /**
107
+ * Test harness for `<wr-calendar>` — the standalone month grid, and the one
108
+ * `<wr-date-picker>` puts in an overlay.
109
+ *
110
+ * **It is three views behind one header.** Clicking the header label walks
111
+ * `day → month → year`, and each view renders something different: a
112
+ * `role="grid"` of day cells, or a `role="listbox"` of chips. Every day method
113
+ * throws off the day view rather than answering `[]`, which would read as "this
114
+ * month has no days".
115
+ *
116
+ * **The roving cell is not the selection.** The grid has one tab stop and the
117
+ * arrows move it; it starts on the selected date, or on today when nothing is
118
+ * picked. And it does NOT follow {@link next} / {@link previous} — a grid paged
119
+ * away from the roving month has no active cell at all, and so no tab stop, until
120
+ * a key or a click puts one back. That is the component's behaviour, and
121
+ * {@link getActiveDay} is how a spec sees it.
122
+ *
123
+ * **Keys go to the host, not to a cell.** The component listens on its own element,
124
+ * so {@link pressArrow} works whether or not jsdom managed to put real focus
125
+ * anywhere — which it often does not, since the calendar moves focus in an
126
+ * `afterNextRender` and a disabled cell cannot take it.
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * const calendar = await loader.getHarness(WrCalendarHarness);
131
+ *
132
+ * expect(await calendar.getHeaderLabel()).toBe('March 2026');
133
+ * await (await calendar.getDay(14)).click();
134
+ * expect(await calendar.getSelectedDayNumbers()).toEqual([14]);
135
+ * ```
136
+ *
137
+ * @see https://ngwr.dev/guides/testing
138
+ */
139
+ class WrCalendarHarness extends ComponentHarness {
140
+ static hostSelector = 'wr-calendar';
141
+ /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
142
+ static with(options = {}) {
143
+ return new HarnessPredicate(WrCalendarHarness, options)
144
+ .addOption('headerLabel', options.headerLabel, (harness, label) => HarnessPredicate.stringMatches(harness.getHeaderLabel(), label))
145
+ .addOption('mode', options.mode, async (harness, mode) => (await harness.getMode()) === mode)
146
+ .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);
147
+ }
148
+ header = this.locatorFor('.wr-calendar__label');
149
+ prevButton = this.locatorFor('.wr-calendar__nav--prev');
150
+ nextButton = this.locatorFor('.wr-calendar__nav--next');
151
+ /** Which sub-view is showing. */
152
+ async getView() {
153
+ if ((await this.locatorForOptional('.wr-calendar__months')()) !== null)
154
+ return 'month';
155
+ if ((await this.locatorForOptional('.wr-calendar__years')()) !== null)
156
+ return 'year';
157
+ return 'day';
158
+ }
159
+ /** Single- or range-selection, from the host modifier. */
160
+ async getMode() {
161
+ return (await (await this.host()).hasClass('wr-calendar--range')) ? 'range' : 'single';
162
+ }
163
+ /** Whether the whole calendar refuses interaction. */
164
+ async isDisabled() {
165
+ return (await this.host()).hasClass('wr-calendar--disabled');
166
+ }
167
+ /** The header text — `March 2026`, `2026`, or `2016 – 2027` depending on the view. */
168
+ async getHeaderLabel() {
169
+ return (await this.header()).text();
170
+ }
171
+ /**
172
+ * Click the header — stepping `day → month → year`.
173
+ *
174
+ * The year view is the end of the walk: the header is disabled there, so this
175
+ * throws rather than clicking a button the DOM would ignore.
176
+ */
177
+ async clickHeader() {
178
+ const header = await this.header();
179
+ if (await header.getProperty('disabled')) {
180
+ throw new Error(`WrCalendarHarness.clickHeader(): the header is disabled — the calendar is on the ` +
181
+ `${await this.getView()} view, which is where the walk stops (or the whole calendar is disabled).`);
182
+ }
183
+ await header.click();
184
+ }
185
+ /**
186
+ * Step back — a month, a year or twelve years, depending on the view.
187
+ *
188
+ * The roving day cell does NOT come along: paging is a view change, not a
189
+ * navigation, and the tab stop stays on the month it was in.
190
+ */
191
+ async previous() {
192
+ await (await this.prevButton()).click();
193
+ }
194
+ /** Step forward — a month, a year or twelve years, depending on the view. */
195
+ async next() {
196
+ await (await this.nextButton()).click();
197
+ }
198
+ /**
199
+ * The back arrow's accessible name, which changes with the view — the arrows are
200
+ * icon-only, so this is the only name they have.
201
+ */
202
+ async getPreviousLabel() {
203
+ return (await this.prevButton()).getAttribute('aria-label');
204
+ }
205
+ /** The forward arrow's accessible name. */
206
+ async getNextLabel() {
207
+ return (await this.nextButton()).getAttribute('aria-label');
208
+ }
209
+ /** The weekday column headers, in the order the adapter's first day of week puts them. */
210
+ async getWeekdayNames() {
211
+ await this.requireView('day', 'getWeekdayNames');
212
+ const names = await this.locatorForAll('.wr-calendar__weekday')();
213
+ return Promise.all(names.map(name => name.text()));
214
+ }
215
+ /**
216
+ * Every day cell, in DOM order — 42 of them, since the grid is always six weeks.
217
+ *
218
+ * That includes the spill days of the neighbouring months, which are selectable
219
+ * and not "in" the month; {@link getDay} skips them, and
220
+ * `WrCalendarDayHarness.isOutOfMonth()` tells them apart.
221
+ */
222
+ async getDays(filters = {}) {
223
+ await this.requireView('day', 'getDays');
224
+ return this.locatorForAll(WrCalendarDayHarness.with(filters))();
225
+ }
226
+ /**
227
+ * The cell for a day of THIS month.
228
+ *
229
+ * The number alone is ambiguous — a 42-cell grid shows most numbers twice — so
230
+ * the spill days are skipped rather than matched, which is what "the 3rd" means
231
+ * to someone reading the calendar.
232
+ */
233
+ async getDay(dayOfMonth) {
234
+ for (const day of await this.getDays({ text: String(dayOfMonth) })) {
235
+ if (!(await day.isOutOfMonth()))
236
+ return day;
237
+ }
238
+ throw new Error(`WrCalendarHarness.getDay(${dayOfMonth}): no such day in ${await this.getHeaderLabel()}. Only cells of ` +
239
+ 'the displayed month count — the grid spills into its neighbours, and those are skipped.');
240
+ }
241
+ /** The day numbers currently selected — one in single mode, both ends in range mode. */
242
+ async getSelectedDayNumbers() {
243
+ const selected = await this.getDays({ selected: true });
244
+ return Promise.all(selected.map(day => day.getDayOfMonth()));
245
+ }
246
+ /** The day numbers strictly inside a picked range — never the ends. */
247
+ async getInRangeDayNumbers() {
248
+ const inRange = await this.getDays({ inRange: true });
249
+ return Promise.all(inRange.map(day => day.getDayOfMonth()));
250
+ }
251
+ /**
252
+ * The day number holding the roving tab stop, or `null` when the grid has none.
253
+ *
254
+ * `null` is a real answer, not a failure: paging with {@link next} leaves the
255
+ * roving date behind in another month, and the grid then has no `tabindex="0"`
256
+ * at all until a key or a click puts one back.
257
+ */
258
+ async getActiveDayNumber() {
259
+ for (const day of await this.getDays()) {
260
+ if (await day.isActive())
261
+ return day.getDayOfMonth();
262
+ }
263
+ return null;
264
+ }
265
+ /** The month chips, with their state. Throws off the month view. */
266
+ async getMonths() {
267
+ await this.requireView('month', 'getMonths');
268
+ return this.readChips();
269
+ }
270
+ /** The year chips, with their state. Throws off the year view. */
271
+ async getYears() {
272
+ await this.requireView('year', 'getYears');
273
+ return this.readChips();
274
+ }
275
+ /**
276
+ * Click a month or year chip by its printed label — which drops the calendar back
277
+ * one view, the way clicking the header climbed up.
278
+ *
279
+ * Throws on the day view, where there are no chips, and on a label the view does
280
+ * not offer, naming what it does.
281
+ */
282
+ async selectChip(label) {
283
+ const view = await this.getView();
284
+ if (view === 'day') {
285
+ throw new Error('WrCalendarHarness.selectChip(): the calendar is on the day view, which has no chips. Click the ' +
286
+ 'header first — it walks day → month → year.');
287
+ }
288
+ for (const chip of await this.locatorForAll('.wr-calendar__chip')()) {
289
+ if ((await chip.text()) === label) {
290
+ await chip.click();
291
+ return;
292
+ }
293
+ }
294
+ const offered = (await this.readChips()).map(chip => chip.label);
295
+ throw new Error(`WrCalendarHarness.selectChip("${label}"): the ${view} view offers: ${offered.join(', ')}.`);
296
+ }
297
+ /**
298
+ * Press an arrow key — one day left or right, one WEEK up or down.
299
+ *
300
+ * Sent to the host, where the component listens, so this does not depend on jsdom
301
+ * having managed to focus a cell. Under `dir="rtl"` the horizontal pair mirrors:
302
+ * ArrowRight goes back a day, because the grid itself is mirrored.
303
+ */
304
+ async pressArrow(arrow) {
305
+ await (await this.host()).sendKeys(ARROWS[arrow]);
306
+ }
307
+ /** Press Home — the first day of the roving cell's week, not of the month. */
308
+ async pressHome() {
309
+ await (await this.host()).sendKeys(TestKey.HOME);
310
+ }
311
+ /** Press End — the last day of the roving cell's week. */
312
+ async pressEnd() {
313
+ await (await this.host()).sendKeys(TestKey.END);
314
+ }
315
+ /** Press PageUp — a month back, or a YEAR back with `shift`. */
316
+ async pressPageUp(options = {}) {
317
+ const host = await this.host();
318
+ await (options.shift ? host.sendKeys({ shift: true }, TestKey.PAGE_UP) : host.sendKeys(TestKey.PAGE_UP));
319
+ }
320
+ /** Press PageDown — a month on, or a YEAR on with `shift`. */
321
+ async pressPageDown(options = {}) {
322
+ const host = await this.host();
323
+ await (options.shift ? host.sendKeys({ shift: true }, TestKey.PAGE_DOWN) : host.sendKeys(TestKey.PAGE_DOWN));
324
+ }
325
+ /** Press Enter — picking the roving day, exactly as clicking it would. */
326
+ async pressEnter() {
327
+ await (await this.host()).sendKeys(TestKey.ENTER);
328
+ }
329
+ /**
330
+ * The role of the element that owns the day rows.
331
+ *
332
+ * Worth asserting rather than assuming: the grid is NOT the host. The host also
333
+ * holds the nav header, and a `role="grid"` may only own rows — so the role sits
334
+ * on the body, and the weekday strip is a row inside it rather than a sibling.
335
+ */
336
+ async getGridRole() {
337
+ const body = await this.locatorForOptional('.wr-calendar__body')();
338
+ return body ? body.getAttribute('role') : null;
339
+ }
340
+ /** How many week rows the grid renders — always six, which is what keeps it from reflowing. */
341
+ async getWeekCount() {
342
+ await this.requireView('day', 'getWeekCount');
343
+ return (await this.locatorForAll('.wr-calendar__week')()).length;
344
+ }
345
+ async readChips() {
346
+ const chips = await this.locatorForAll('.wr-calendar__chip')();
347
+ return Promise.all(chips.map(async (chip) => ({
348
+ label: await chip.text(),
349
+ selected: (await chip.getAttribute('aria-selected')) === 'true',
350
+ current: await chip.hasClass('wr-calendar__chip--current'),
351
+ disabled: (await chip.getAttribute('aria-disabled')) === 'true',
352
+ })));
353
+ }
354
+ async requireView(view, method) {
355
+ const current = await this.getView();
356
+ if (current === view)
357
+ return;
358
+ throw new Error(`WrCalendarHarness.${method}(): the calendar is showing the ${current} view, not the ${view} one — those ` +
359
+ 'elements are not rendered at all. The header walks day → month → year; clicking a chip walks back down.');
360
+ }
361
+ }
362
+
363
+ /**
364
+ * Generated bundle index. Do not edit.
365
+ */
366
+
367
+ export { WrCalendarDayHarness, WrCalendarHarness };
368
+ //# sourceMappingURL=ngwr-calendar-testing.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngwr-calendar-testing.mjs","sources":["../../../projects/lib/calendar/testing/wr-calendar-day-harness.ts","../../../projects/lib/calendar/testing/wr-calendar-harness.ts","../../../projects/lib/calendar/testing/ngwr-calendar-testing.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';\n\nimport type { WrCalendarDayHarnessFilters } from './interfaces';\n\n/**\n * Test harness for one day cell of a `<wr-calendar>` grid.\n *\n * The cell belongs to the calendar, and a date-picker's popup is a calendar in an\n * overlay — so this is the harness for both, re-exported from\n * `ngwr/date-picker/testing` under the name it shipped as\n * (`WrDatePickerDayHarness`). Reach it through `WrCalendarHarness.getDays()`, or\n * through `WrDatePickerHarness.getDay()` / `getDays()`, which scope it to ONE\n * picker's panel — those cells are in the shared overlay container, so a bare query\n * would answer with whichever picker opened first.\n *\n * State is read the way a screen reader reads it (`role`, `aria-selected`,\n * `aria-disabled`) with the `.wr-calendar__day--*` modifiers filling in what\n * ARIA has no word for: today, the spill days of the neighbouring months, and\n * the interior of a picked range.\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrCalendarDayHarness extends ComponentHarness {\n static hostSelector = '.wr-calendar__day';\n\n /** Build a predicate that narrows the query. */\n static with(options: WrCalendarDayHarnessFilters = {}): HarnessPredicate<WrCalendarDayHarness> {\n return new HarnessPredicate(WrCalendarDayHarness, options)\n .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text))\n .addOption('selected', options.selected, async (harness, selected) => (await harness.isSelected()) === selected)\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)\n .addOption('inRange', options.inRange, async (harness, inRange) => (await harness.isInRange()) === inRange);\n }\n\n /** The day number as rendered. */\n async getText(): Promise<string> {\n return (await this.host()).text();\n }\n\n /** The day number as a number, for mapping a list of cells to dates. */\n async getDayOfMonth(): Promise<number> {\n return Number(await this.getText());\n }\n\n /** `'gridcell'` — the cell is a button, and the grid semantics are what a spec should assert. */\n async getRole(): Promise<string | null> {\n return (await this.host()).getAttribute('role');\n }\n\n /** Whether this day is (one end of) the current selection. */\n async isSelected(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-selected')) === 'true';\n }\n\n /**\n * Whether the day refuses selection — `min` / `max` or `dateFilter` ruled it\n * out, or the whole calendar is disabled.\n */\n async isDisabled(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-disabled')) === 'true';\n }\n\n /** Whether the cell is today's date. */\n async isToday(): Promise<boolean> {\n return (await this.host()).hasClass('wr-calendar__day--today');\n }\n\n /**\n * Whether the cell belongs to a neighbouring month. The grid is always 6x7, so\n * every month is padded with days that are selectable but not \"in\" the month —\n * which is why `WrDatePickerHarness.getDay` and {@link WrCalendarHarness.getDay} skip them.\n */\n async isOutOfMonth(): Promise<boolean> {\n return (await this.host()).hasClass('wr-calendar__day--out-of-month');\n }\n\n /** Whether the day lies strictly between the two ends of a picked range. */\n async isInRange(): Promise<boolean> {\n return (await this.host()).hasClass('wr-calendar__day--in-range');\n }\n\n /**\n * Whether this is the roving cell — the grid's single tab stop, and where the\n * arrow keys move from.\n *\n * At most ONE cell answers `true`, and it is not always one: the calendar's\n * roving date does not follow `next()` / `previous()`, so a grid navigated away\n * from that month has no active cell (and, deliberately or not, no tab stop)\n * until a cell is clicked or the arrows move it.\n */\n async isActive(): Promise<boolean> {\n return (await this.host()).hasClass('wr-calendar__day--focused');\n }\n\n /** Click the cell. A disabled cell swallows the click — assert, do not assume. */\n async click(): Promise<void> {\n return (await this.host()).click();\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate, TestKey, type TestElement } from '@angular/cdk/testing';\n\nimport type { WrCalendarMode } from 'ngwr/calendar';\n\nimport type {\n WrCalendarChip,\n WrCalendarDayHarnessFilters,\n WrCalendarHarnessFilters,\n WrCalendarView,\n} from './interfaces';\nimport { WrCalendarDayHarness } from './wr-calendar-day-harness';\n\n/** The arrow keys, by the direction a user would say out loud. */\ntype Arrow = 'left' | 'right' | 'up' | 'down';\n\nconst ARROWS: Record<Arrow, TestKey> = {\n left: TestKey.LEFT_ARROW,\n right: TestKey.RIGHT_ARROW,\n up: TestKey.UP_ARROW,\n down: TestKey.DOWN_ARROW,\n};\n\n/**\n * Test harness for `<wr-calendar>` — the standalone month grid, and the one\n * `<wr-date-picker>` puts in an overlay.\n *\n * **It is three views behind one header.** Clicking the header label walks\n * `day → month → year`, and each view renders something different: a\n * `role=\"grid\"` of day cells, or a `role=\"listbox\"` of chips. Every day method\n * throws off the day view rather than answering `[]`, which would read as \"this\n * month has no days\".\n *\n * **The roving cell is not the selection.** The grid has one tab stop and the\n * arrows move it; it starts on the selected date, or on today when nothing is\n * picked. And it does NOT follow {@link next} / {@link previous} — a grid paged\n * away from the roving month has no active cell at all, and so no tab stop, until\n * a key or a click puts one back. That is the component's behaviour, and\n * {@link getActiveDay} is how a spec sees it.\n *\n * **Keys go to the host, not to a cell.** The component listens on its own element,\n * so {@link pressArrow} works whether or not jsdom managed to put real focus\n * anywhere — which it often does not, since the calendar moves focus in an\n * `afterNextRender` and a disabled cell cannot take it.\n *\n * @example\n * ```ts\n * const calendar = await loader.getHarness(WrCalendarHarness);\n *\n * expect(await calendar.getHeaderLabel()).toBe('March 2026');\n * await (await calendar.getDay(14)).click();\n * expect(await calendar.getSelectedDayNumbers()).toEqual([14]);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrCalendarHarness extends ComponentHarness {\n static hostSelector = 'wr-calendar';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrCalendarHarnessFilters = {}): HarnessPredicate<WrCalendarHarness> {\n return new HarnessPredicate(WrCalendarHarness, options)\n .addOption('headerLabel', options.headerLabel, (harness, label) =>\n HarnessPredicate.stringMatches(harness.getHeaderLabel(), label)\n )\n .addOption('mode', options.mode, async (harness, mode) => (await harness.getMode()) === mode)\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);\n }\n\n private readonly header = this.locatorFor('.wr-calendar__label');\n private readonly prevButton = this.locatorFor('.wr-calendar__nav--prev');\n private readonly nextButton = this.locatorFor('.wr-calendar__nav--next');\n\n /** Which sub-view is showing. */\n async getView(): Promise<WrCalendarView> {\n if ((await this.locatorForOptional('.wr-calendar__months')()) !== null) return 'month';\n if ((await this.locatorForOptional('.wr-calendar__years')()) !== null) return 'year';\n return 'day';\n }\n\n /** Single- or range-selection, from the host modifier. */\n async getMode(): Promise<WrCalendarMode> {\n return (await (await this.host()).hasClass('wr-calendar--range')) ? 'range' : 'single';\n }\n\n /** Whether the whole calendar refuses interaction. */\n async isDisabled(): Promise<boolean> {\n return (await this.host()).hasClass('wr-calendar--disabled');\n }\n\n /** The header text — `March 2026`, `2026`, or `2016 – 2027` depending on the view. */\n async getHeaderLabel(): Promise<string> {\n return (await this.header()).text();\n }\n\n /**\n * Click the header — stepping `day → month → year`.\n *\n * The year view is the end of the walk: the header is disabled there, so this\n * throws rather than clicking a button the DOM would ignore.\n */\n async clickHeader(): Promise<void> {\n const header = await this.header();\n if (await header.getProperty<boolean>('disabled')) {\n throw new Error(\n `WrCalendarHarness.clickHeader(): the header is disabled — the calendar is on the ` +\n `${await this.getView()} view, which is where the walk stops (or the whole calendar is disabled).`\n );\n }\n await header.click();\n }\n\n /**\n * Step back — a month, a year or twelve years, depending on the view.\n *\n * The roving day cell does NOT come along: paging is a view change, not a\n * navigation, and the tab stop stays on the month it was in.\n */\n async previous(): Promise<void> {\n await (await this.prevButton()).click();\n }\n\n /** Step forward — a month, a year or twelve years, depending on the view. */\n async next(): Promise<void> {\n await (await this.nextButton()).click();\n }\n\n /**\n * The back arrow's accessible name, which changes with the view — the arrows are\n * icon-only, so this is the only name they have.\n */\n async getPreviousLabel(): Promise<string | null> {\n return (await this.prevButton()).getAttribute('aria-label');\n }\n\n /** The forward arrow's accessible name. */\n async getNextLabel(): Promise<string | null> {\n return (await this.nextButton()).getAttribute('aria-label');\n }\n\n /** The weekday column headers, in the order the adapter's first day of week puts them. */\n async getWeekdayNames(): Promise<string[]> {\n await this.requireView('day', 'getWeekdayNames');\n const names = await this.locatorForAll('.wr-calendar__weekday')();\n return Promise.all(names.map(name => name.text()));\n }\n\n /**\n * Every day cell, in DOM order — 42 of them, since the grid is always six weeks.\n *\n * That includes the spill days of the neighbouring months, which are selectable\n * and not \"in\" the month; {@link getDay} skips them, and\n * `WrCalendarDayHarness.isOutOfMonth()` tells them apart.\n */\n async getDays(filters: WrCalendarDayHarnessFilters = {}): Promise<WrCalendarDayHarness[]> {\n await this.requireView('day', 'getDays');\n return this.locatorForAll(WrCalendarDayHarness.with(filters))();\n }\n\n /**\n * The cell for a day of THIS month.\n *\n * The number alone is ambiguous — a 42-cell grid shows most numbers twice — so\n * the spill days are skipped rather than matched, which is what \"the 3rd\" means\n * to someone reading the calendar.\n */\n async getDay(dayOfMonth: number): Promise<WrCalendarDayHarness> {\n for (const day of await this.getDays({ text: String(dayOfMonth) })) {\n if (!(await day.isOutOfMonth())) return day;\n }\n throw new Error(\n `WrCalendarHarness.getDay(${dayOfMonth}): no such day in ${await this.getHeaderLabel()}. Only cells of ` +\n 'the displayed month count — the grid spills into its neighbours, and those are skipped.'\n );\n }\n\n /** The day numbers currently selected — one in single mode, both ends in range mode. */\n async getSelectedDayNumbers(): Promise<number[]> {\n const selected = await this.getDays({ selected: true });\n return Promise.all(selected.map(day => day.getDayOfMonth()));\n }\n\n /** The day numbers strictly inside a picked range — never the ends. */\n async getInRangeDayNumbers(): Promise<number[]> {\n const inRange = await this.getDays({ inRange: true });\n return Promise.all(inRange.map(day => day.getDayOfMonth()));\n }\n\n /**\n * The day number holding the roving tab stop, or `null` when the grid has none.\n *\n * `null` is a real answer, not a failure: paging with {@link next} leaves the\n * roving date behind in another month, and the grid then has no `tabindex=\"0\"`\n * at all until a key or a click puts one back.\n */\n async getActiveDayNumber(): Promise<number | null> {\n for (const day of await this.getDays()) {\n if (await day.isActive()) return day.getDayOfMonth();\n }\n return null;\n }\n\n /** The month chips, with their state. Throws off the month view. */\n async getMonths(): Promise<WrCalendarChip[]> {\n await this.requireView('month', 'getMonths');\n return this.readChips();\n }\n\n /** The year chips, with their state. Throws off the year view. */\n async getYears(): Promise<WrCalendarChip[]> {\n await this.requireView('year', 'getYears');\n return this.readChips();\n }\n\n /**\n * Click a month or year chip by its printed label — which drops the calendar back\n * one view, the way clicking the header climbed up.\n *\n * Throws on the day view, where there are no chips, and on a label the view does\n * not offer, naming what it does.\n */\n async selectChip(label: string): Promise<void> {\n const view = await this.getView();\n if (view === 'day') {\n throw new Error(\n 'WrCalendarHarness.selectChip(): the calendar is on the day view, which has no chips. Click the ' +\n 'header first — it walks day → month → year.'\n );\n }\n\n for (const chip of await this.locatorForAll('.wr-calendar__chip')()) {\n if ((await chip.text()) === label) {\n await chip.click();\n return;\n }\n }\n\n const offered = (await this.readChips()).map(chip => chip.label);\n throw new Error(`WrCalendarHarness.selectChip(\"${label}\"): the ${view} view offers: ${offered.join(', ')}.`);\n }\n\n /**\n * Press an arrow key — one day left or right, one WEEK up or down.\n *\n * Sent to the host, where the component listens, so this does not depend on jsdom\n * having managed to focus a cell. Under `dir=\"rtl\"` the horizontal pair mirrors:\n * ArrowRight goes back a day, because the grid itself is mirrored.\n */\n async pressArrow(arrow: Arrow): Promise<void> {\n await (await this.host()).sendKeys(ARROWS[arrow]);\n }\n\n /** Press Home — the first day of the roving cell's week, not of the month. */\n async pressHome(): Promise<void> {\n await (await this.host()).sendKeys(TestKey.HOME);\n }\n\n /** Press End — the last day of the roving cell's week. */\n async pressEnd(): Promise<void> {\n await (await this.host()).sendKeys(TestKey.END);\n }\n\n /** Press PageUp — a month back, or a YEAR back with `shift`. */\n async pressPageUp(options: { shift?: boolean } = {}): Promise<void> {\n const host = await this.host();\n await (options.shift ? host.sendKeys({ shift: true }, TestKey.PAGE_UP) : host.sendKeys(TestKey.PAGE_UP));\n }\n\n /** Press PageDown — a month on, or a YEAR on with `shift`. */\n async pressPageDown(options: { shift?: boolean } = {}): Promise<void> {\n const host = await this.host();\n await (options.shift ? host.sendKeys({ shift: true }, TestKey.PAGE_DOWN) : host.sendKeys(TestKey.PAGE_DOWN));\n }\n\n /** Press Enter — picking the roving day, exactly as clicking it would. */\n async pressEnter(): Promise<void> {\n await (await this.host()).sendKeys(TestKey.ENTER);\n }\n\n /**\n * The role of the element that owns the day rows.\n *\n * Worth asserting rather than assuming: the grid is NOT the host. The host also\n * holds the nav header, and a `role=\"grid\"` may only own rows — so the role sits\n * on the body, and the weekday strip is a row inside it rather than a sibling.\n */\n async getGridRole(): Promise<string | null> {\n const body = await this.locatorForOptional('.wr-calendar__body')();\n return body ? body.getAttribute('role') : null;\n }\n\n /** How many week rows the grid renders — always six, which is what keeps it from reflowing. */\n async getWeekCount(): Promise<number> {\n await this.requireView('day', 'getWeekCount');\n return (await this.locatorForAll('.wr-calendar__week')()).length;\n }\n\n private async readChips(): Promise<WrCalendarChip[]> {\n const chips = await this.locatorForAll('.wr-calendar__chip')();\n\n return Promise.all(\n chips.map(async (chip: TestElement) => ({\n label: await chip.text(),\n selected: (await chip.getAttribute('aria-selected')) === 'true',\n current: await chip.hasClass('wr-calendar__chip--current'),\n disabled: (await chip.getAttribute('aria-disabled')) === 'true',\n }))\n );\n }\n\n private async requireView(view: WrCalendarView, method: string): Promise<void> {\n const current = await this.getView();\n if (current === view) return;\n\n throw new Error(\n `WrCalendarHarness.${method}(): the calendar is showing the ${current} view, not the ${view} one — those ` +\n 'elements are not rendered at all. The header walks day → month → year; clicking a chip walks back down.'\n );\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  import { Directionality } from '@angular/cdk/bidi';
2
2
  import { coerceBooleanProperty } from '@angular/cdk/coercion';
3
3
  import * as i0 from '@angular/core';
4
- import { input, model, inject, ElementRef, Injector, signal, computed, afterNextRender, effect, untracked, ViewEncapsulation, Component } from '@angular/core';
4
+ import { signal, input, model, inject, ElementRef, Injector, computed, afterNextRender, effect, untracked, ViewEncapsulation, Component } from '@angular/core';
5
5
  import { WrDateAdapter } from 'ngwr/date-adapter';
6
+ import { useI18nText } from 'ngwr/i18n';
6
7
 
7
8
  /**
8
9
  * @license
@@ -10,6 +11,11 @@ import { WrDateAdapter } from 'ngwr/date-adapter';
10
11
  * Use of this source code is governed by an MIT-style license that can be
11
12
  * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
12
13
  */
14
+ /**
15
+ * Stands in for the consumer input `useI18nText` expects, for labels the calendar
16
+ * exposes no input for. Constant and read-only, so one instance is safe to share.
17
+ */
18
+ const NO_OVERRIDE = signal(null).asReadonly();
13
19
  const ROWS = 6;
14
20
  const COLS = 7;
15
21
  /**
@@ -75,6 +81,40 @@ class WrCalendar {
75
81
  /** Which sub-view is currently shown. Cycles `day → month → year` on header click. */
76
82
  viewMode = signal('day', /* @ts-ignore */
77
83
  ...(ngDevMode ? [{ debugName: "viewMode" }] : /* istanbul ignore next */ []));
84
+ // The four month/year strings have been in both catalogs since they were written
85
+ // and nothing read them: the template hard-coded the same English beside them, so a
86
+ // localized app announced its calendar's arrows in English. `nullSignal()` is the
87
+ // shim for exactly this — a label with no consumer input to forward.
88
+ prevMonthLabel = useI18nText(NO_OVERRIDE, 'calendar.prevMonth', 'Previous month');
89
+ nextMonthLabel = useI18nText(NO_OVERRIDE, 'calendar.nextMonth', 'Next month');
90
+ prevYearLabel = useI18nText(NO_OVERRIDE, 'calendar.prevYear', 'Previous year');
91
+ nextYearLabel = useI18nText(NO_OVERRIDE, 'calendar.nextYear', 'Next year');
92
+ prevYearsLabel = useI18nText(NO_OVERRIDE, 'calendar.prevYears', 'Previous 12 years');
93
+ nextYearsLabel = useI18nText(NO_OVERRIDE, 'calendar.nextYears', 'Next 12 years');
94
+ /** What the ← button does from here — a month, a year, or a 12-year page. */
95
+ prevLabel = computed(() => {
96
+ switch (this.viewMode()) {
97
+ case 'year':
98
+ return this.prevYearsLabel();
99
+ case 'month':
100
+ return this.prevYearLabel();
101
+ default:
102
+ return this.prevMonthLabel();
103
+ }
104
+ }, /* @ts-ignore */
105
+ ...(ngDevMode ? [{ debugName: "prevLabel" }] : /* istanbul ignore next */ []));
106
+ /** What the → button does from here. */
107
+ nextLabel = computed(() => {
108
+ switch (this.viewMode()) {
109
+ case 'year':
110
+ return this.nextYearsLabel();
111
+ case 'month':
112
+ return this.nextYearLabel();
113
+ default:
114
+ return this.nextMonthLabel();
115
+ }
116
+ }, /* @ts-ignore */
117
+ ...(ngDevMode ? [{ debugName: "nextLabel" }] : /* istanbul ignore next */ []));
78
118
  today = computed(() => this.adapter.today(), /* @ts-ignore */
79
119
  ...(ngDevMode ? [{ debugName: "today" }] : /* istanbul ignore next */ []));
80
120
  weekdayNames = computed(() => this.adapter.getDayOfWeekNames('short'), /* @ts-ignore */
@@ -482,7 +522,7 @@ class WrCalendar {
482
522
  return key;
483
523
  }
484
524
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrCalendar, deps: [], target: i0.ɵɵFactoryTarget.Component });
485
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: WrCalendar, isStandalone: true, selector: "wr-calendar", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, range: { classPropertyName: "range", publicName: "range", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, dateFilter: { classPropertyName: "dateFilter", publicName: "dateFilter", isSignal: true, isRequired: false, transformFunction: null }, autoFocus: { classPropertyName: "autoFocus", publicName: "autoFocus", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { date: "dateChange", range: "rangeChange" }, host: { listeners: { "keydown": "onKeyDown($event)" }, properties: { "class": "classes()" } }, ngImport: i0, template: "<div class=\"wr-calendar__header\">\n <button\n type=\"button\"\n class=\"wr-calendar__nav wr-calendar__nav--prev\"\n [attr.aria-label]=\"\n viewMode() === 'year' ? 'Previous 12 years' : viewMode() === 'month' ? 'Previous year' : 'Previous month'\n \"\n [disabled]=\"disabled()\"\n (click)=\"prev()\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n </button>\n <button\n type=\"button\"\n class=\"wr-calendar__label\"\n [disabled]=\"disabled() || viewMode() === 'year'\"\n (click)=\"onLabelClick()\"\n >\n {{ headerLabel() }}\n </button>\n <button\n type=\"button\"\n class=\"wr-calendar__nav wr-calendar__nav--next\"\n [attr.aria-label]=\"viewMode() === 'year' ? 'Next 12 years' : viewMode() === 'month' ? 'Next year' : 'Next month'\"\n [disabled]=\"disabled()\"\n (click)=\"next()\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n </button>\n</div>\n\n@switch (viewMode()) {\n @case ('day') {\n <!--\n The weekday strip and the week rows are one grid, so they share a wrapper:\n `role=\"grid\"` may only own rows, and as siblings the header row had no grid\n parent at all. `.wr-calendar__body` repeats the host's column gap, so the\n rendered spacing is unchanged.\n -->\n <div class=\"wr-calendar__body\" role=\"grid\">\n <div class=\"wr-calendar__weekdays\" role=\"row\">\n @for (name of weekdayNames(); track name) {\n <span class=\"wr-calendar__weekday\" role=\"columnheader\">{{ name }}</span>\n }\n </div>\n\n <div class=\"wr-calendar__grid\" role=\"rowgroup\" (mouseleave)=\"onCellLeave()\">\n @for (week of weeks(); track $index) {\n <div class=\"wr-calendar__week\" role=\"row\">\n @for (day of week; track trackByTime($index, day)) {\n <button\n type=\"button\"\n class=\"wr-calendar__day\"\n role=\"gridcell\"\n [class.wr-calendar__day--today]=\"isToday(day)\"\n [class.wr-calendar__day--out-of-month]=\"isOutOfMonth(day)\"\n [class.wr-calendar__day--selected]=\"isSelected(day)\"\n [class.wr-calendar__day--in-range]=\"isInRange(day)\"\n [class.wr-calendar__day--range-preview]=\"isInRangePreview(day)\"\n [class.wr-calendar__day--focused]=\"isFocused(day)\"\n [disabled]=\"isDisabled(day)\"\n [attr.tabindex]=\"isFocused(day) ? 0 : -1\"\n [attr.aria-selected]=\"isSelected(day)\"\n [attr.aria-disabled]=\"isDisabled(day)\"\n (click)=\"onCellClick(day)\"\n (mouseenter)=\"onCellEnter(day)\"\n >\n {{ day.getDate() }}\n </button>\n }\n </div>\n }\n </div>\n </div>\n }\n\n @case ('month') {\n <div class=\"wr-calendar__months\" role=\"listbox\">\n @for (name of monthsView(); track name) {\n <button\n type=\"button\"\n class=\"wr-calendar__chip\"\n role=\"option\"\n [class.wr-calendar__chip--current]=\"isMonthCurrent($index)\"\n [class.wr-calendar__chip--selected]=\"isMonthSelected($index)\"\n [disabled]=\"isMonthDisabled($index)\"\n [attr.aria-selected]=\"isMonthSelected($index)\"\n [attr.aria-disabled]=\"isMonthDisabled($index)\"\n (click)=\"onMonthSelect($index)\"\n >\n {{ name }}\n </button>\n }\n </div>\n }\n\n @case ('year') {\n <div class=\"wr-calendar__years\" role=\"listbox\">\n @for (year of yearsView(); track year) {\n <button\n type=\"button\"\n class=\"wr-calendar__chip\"\n role=\"option\"\n [class.wr-calendar__chip--current]=\"isYearCurrent(year)\"\n [class.wr-calendar__chip--selected]=\"isYearSelected(year)\"\n [disabled]=\"isYearDisabled(year)\"\n [attr.aria-selected]=\"isYearSelected(year)\"\n [attr.aria-disabled]=\"isYearDisabled(year)\"\n (click)=\"onYearSelect(year)\"\n >\n {{ year }}\n </button>\n }\n </div>\n }\n}\n", encapsulation: i0.ViewEncapsulation.None });
525
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: WrCalendar, isStandalone: true, selector: "wr-calendar", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, range: { classPropertyName: "range", publicName: "range", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, dateFilter: { classPropertyName: "dateFilter", publicName: "dateFilter", isSignal: true, isRequired: false, transformFunction: null }, autoFocus: { classPropertyName: "autoFocus", publicName: "autoFocus", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { date: "dateChange", range: "rangeChange" }, host: { listeners: { "keydown": "onKeyDown($event)" }, properties: { "class": "classes()" } }, ngImport: i0, template: "<div class=\"wr-calendar__header\">\n <button\n type=\"button\"\n class=\"wr-calendar__nav wr-calendar__nav--prev\"\n [attr.aria-label]=\"prevLabel()\"\n [disabled]=\"disabled()\"\n (click)=\"prev()\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n </button>\n <button\n type=\"button\"\n class=\"wr-calendar__label\"\n [disabled]=\"disabled() || viewMode() === 'year'\"\n (click)=\"onLabelClick()\"\n >\n {{ headerLabel() }}\n </button>\n <button\n type=\"button\"\n class=\"wr-calendar__nav wr-calendar__nav--next\"\n [attr.aria-label]=\"nextLabel()\"\n [disabled]=\"disabled()\"\n (click)=\"next()\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n </button>\n</div>\n\n@switch (viewMode()) {\n @case ('day') {\n <!--\n The weekday strip and the week rows are one grid, so they share a wrapper:\n `role=\"grid\"` may only own rows, and as siblings the header row had no grid\n parent at all. `.wr-calendar__body` repeats the host's column gap, so the\n rendered spacing is unchanged.\n -->\n <div class=\"wr-calendar__body\" role=\"grid\">\n <div class=\"wr-calendar__weekdays\" role=\"row\">\n @for (name of weekdayNames(); track name) {\n <span class=\"wr-calendar__weekday\" role=\"columnheader\">{{ name }}</span>\n }\n </div>\n\n <div class=\"wr-calendar__grid\" role=\"rowgroup\" (mouseleave)=\"onCellLeave()\">\n @for (week of weeks(); track $index) {\n <div class=\"wr-calendar__week\" role=\"row\">\n @for (day of week; track trackByTime($index, day)) {\n <button\n type=\"button\"\n class=\"wr-calendar__day\"\n role=\"gridcell\"\n [class.wr-calendar__day--today]=\"isToday(day)\"\n [class.wr-calendar__day--out-of-month]=\"isOutOfMonth(day)\"\n [class.wr-calendar__day--selected]=\"isSelected(day)\"\n [class.wr-calendar__day--in-range]=\"isInRange(day)\"\n [class.wr-calendar__day--range-preview]=\"isInRangePreview(day)\"\n [class.wr-calendar__day--focused]=\"isFocused(day)\"\n [disabled]=\"isDisabled(day)\"\n [attr.tabindex]=\"isFocused(day) ? 0 : -1\"\n [attr.aria-selected]=\"isSelected(day)\"\n [attr.aria-disabled]=\"isDisabled(day)\"\n (click)=\"onCellClick(day)\"\n (mouseenter)=\"onCellEnter(day)\"\n >\n {{ day.getDate() }}\n </button>\n }\n </div>\n }\n </div>\n </div>\n }\n\n @case ('month') {\n <div class=\"wr-calendar__months\" role=\"listbox\">\n @for (name of monthsView(); track name) {\n <button\n type=\"button\"\n class=\"wr-calendar__chip\"\n role=\"option\"\n [class.wr-calendar__chip--current]=\"isMonthCurrent($index)\"\n [class.wr-calendar__chip--selected]=\"isMonthSelected($index)\"\n [disabled]=\"isMonthDisabled($index)\"\n [attr.aria-selected]=\"isMonthSelected($index)\"\n [attr.aria-disabled]=\"isMonthDisabled($index)\"\n (click)=\"onMonthSelect($index)\"\n >\n {{ name }}\n </button>\n }\n </div>\n }\n\n @case ('year') {\n <div class=\"wr-calendar__years\" role=\"listbox\">\n @for (year of yearsView(); track year) {\n <button\n type=\"button\"\n class=\"wr-calendar__chip\"\n role=\"option\"\n [class.wr-calendar__chip--current]=\"isYearCurrent(year)\"\n [class.wr-calendar__chip--selected]=\"isYearSelected(year)\"\n [disabled]=\"isYearDisabled(year)\"\n [attr.aria-selected]=\"isYearSelected(year)\"\n [attr.aria-disabled]=\"isYearDisabled(year)\"\n (click)=\"onYearSelect(year)\"\n >\n {{ year }}\n </button>\n }\n </div>\n }\n}\n", encapsulation: i0.ViewEncapsulation.None });
486
526
  }
487
527
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrCalendar, decorators: [{
488
528
  type: Component,
@@ -492,7 +532,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImpor
492
532
  // only own rows. The role sits on `.wr-calendar__body`, which is the day
493
533
  // matrix and nothing else.
494
534
  '(keydown)': 'onKeyDown($event)',
495
- }, template: "<div class=\"wr-calendar__header\">\n <button\n type=\"button\"\n class=\"wr-calendar__nav wr-calendar__nav--prev\"\n [attr.aria-label]=\"\n viewMode() === 'year' ? 'Previous 12 years' : viewMode() === 'month' ? 'Previous year' : 'Previous month'\n \"\n [disabled]=\"disabled()\"\n (click)=\"prev()\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n </button>\n <button\n type=\"button\"\n class=\"wr-calendar__label\"\n [disabled]=\"disabled() || viewMode() === 'year'\"\n (click)=\"onLabelClick()\"\n >\n {{ headerLabel() }}\n </button>\n <button\n type=\"button\"\n class=\"wr-calendar__nav wr-calendar__nav--next\"\n [attr.aria-label]=\"viewMode() === 'year' ? 'Next 12 years' : viewMode() === 'month' ? 'Next year' : 'Next month'\"\n [disabled]=\"disabled()\"\n (click)=\"next()\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n </button>\n</div>\n\n@switch (viewMode()) {\n @case ('day') {\n <!--\n The weekday strip and the week rows are one grid, so they share a wrapper:\n `role=\"grid\"` may only own rows, and as siblings the header row had no grid\n parent at all. `.wr-calendar__body` repeats the host's column gap, so the\n rendered spacing is unchanged.\n -->\n <div class=\"wr-calendar__body\" role=\"grid\">\n <div class=\"wr-calendar__weekdays\" role=\"row\">\n @for (name of weekdayNames(); track name) {\n <span class=\"wr-calendar__weekday\" role=\"columnheader\">{{ name }}</span>\n }\n </div>\n\n <div class=\"wr-calendar__grid\" role=\"rowgroup\" (mouseleave)=\"onCellLeave()\">\n @for (week of weeks(); track $index) {\n <div class=\"wr-calendar__week\" role=\"row\">\n @for (day of week; track trackByTime($index, day)) {\n <button\n type=\"button\"\n class=\"wr-calendar__day\"\n role=\"gridcell\"\n [class.wr-calendar__day--today]=\"isToday(day)\"\n [class.wr-calendar__day--out-of-month]=\"isOutOfMonth(day)\"\n [class.wr-calendar__day--selected]=\"isSelected(day)\"\n [class.wr-calendar__day--in-range]=\"isInRange(day)\"\n [class.wr-calendar__day--range-preview]=\"isInRangePreview(day)\"\n [class.wr-calendar__day--focused]=\"isFocused(day)\"\n [disabled]=\"isDisabled(day)\"\n [attr.tabindex]=\"isFocused(day) ? 0 : -1\"\n [attr.aria-selected]=\"isSelected(day)\"\n [attr.aria-disabled]=\"isDisabled(day)\"\n (click)=\"onCellClick(day)\"\n (mouseenter)=\"onCellEnter(day)\"\n >\n {{ day.getDate() }}\n </button>\n }\n </div>\n }\n </div>\n </div>\n }\n\n @case ('month') {\n <div class=\"wr-calendar__months\" role=\"listbox\">\n @for (name of monthsView(); track name) {\n <button\n type=\"button\"\n class=\"wr-calendar__chip\"\n role=\"option\"\n [class.wr-calendar__chip--current]=\"isMonthCurrent($index)\"\n [class.wr-calendar__chip--selected]=\"isMonthSelected($index)\"\n [disabled]=\"isMonthDisabled($index)\"\n [attr.aria-selected]=\"isMonthSelected($index)\"\n [attr.aria-disabled]=\"isMonthDisabled($index)\"\n (click)=\"onMonthSelect($index)\"\n >\n {{ name }}\n </button>\n }\n </div>\n }\n\n @case ('year') {\n <div class=\"wr-calendar__years\" role=\"listbox\">\n @for (year of yearsView(); track year) {\n <button\n type=\"button\"\n class=\"wr-calendar__chip\"\n role=\"option\"\n [class.wr-calendar__chip--current]=\"isYearCurrent(year)\"\n [class.wr-calendar__chip--selected]=\"isYearSelected(year)\"\n [disabled]=\"isYearDisabled(year)\"\n [attr.aria-selected]=\"isYearSelected(year)\"\n [attr.aria-disabled]=\"isYearDisabled(year)\"\n (click)=\"onYearSelect(year)\"\n >\n {{ year }}\n </button>\n }\n </div>\n }\n}\n" }]
535
+ }, template: "<div class=\"wr-calendar__header\">\n <button\n type=\"button\"\n class=\"wr-calendar__nav wr-calendar__nav--prev\"\n [attr.aria-label]=\"prevLabel()\"\n [disabled]=\"disabled()\"\n (click)=\"prev()\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n </button>\n <button\n type=\"button\"\n class=\"wr-calendar__label\"\n [disabled]=\"disabled() || viewMode() === 'year'\"\n (click)=\"onLabelClick()\"\n >\n {{ headerLabel() }}\n </button>\n <button\n type=\"button\"\n class=\"wr-calendar__nav wr-calendar__nav--next\"\n [attr.aria-label]=\"nextLabel()\"\n [disabled]=\"disabled()\"\n (click)=\"next()\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n </button>\n</div>\n\n@switch (viewMode()) {\n @case ('day') {\n <!--\n The weekday strip and the week rows are one grid, so they share a wrapper:\n `role=\"grid\"` may only own rows, and as siblings the header row had no grid\n parent at all. `.wr-calendar__body` repeats the host's column gap, so the\n rendered spacing is unchanged.\n -->\n <div class=\"wr-calendar__body\" role=\"grid\">\n <div class=\"wr-calendar__weekdays\" role=\"row\">\n @for (name of weekdayNames(); track name) {\n <span class=\"wr-calendar__weekday\" role=\"columnheader\">{{ name }}</span>\n }\n </div>\n\n <div class=\"wr-calendar__grid\" role=\"rowgroup\" (mouseleave)=\"onCellLeave()\">\n @for (week of weeks(); track $index) {\n <div class=\"wr-calendar__week\" role=\"row\">\n @for (day of week; track trackByTime($index, day)) {\n <button\n type=\"button\"\n class=\"wr-calendar__day\"\n role=\"gridcell\"\n [class.wr-calendar__day--today]=\"isToday(day)\"\n [class.wr-calendar__day--out-of-month]=\"isOutOfMonth(day)\"\n [class.wr-calendar__day--selected]=\"isSelected(day)\"\n [class.wr-calendar__day--in-range]=\"isInRange(day)\"\n [class.wr-calendar__day--range-preview]=\"isInRangePreview(day)\"\n [class.wr-calendar__day--focused]=\"isFocused(day)\"\n [disabled]=\"isDisabled(day)\"\n [attr.tabindex]=\"isFocused(day) ? 0 : -1\"\n [attr.aria-selected]=\"isSelected(day)\"\n [attr.aria-disabled]=\"isDisabled(day)\"\n (click)=\"onCellClick(day)\"\n (mouseenter)=\"onCellEnter(day)\"\n >\n {{ day.getDate() }}\n </button>\n }\n </div>\n }\n </div>\n </div>\n }\n\n @case ('month') {\n <div class=\"wr-calendar__months\" role=\"listbox\">\n @for (name of monthsView(); track name) {\n <button\n type=\"button\"\n class=\"wr-calendar__chip\"\n role=\"option\"\n [class.wr-calendar__chip--current]=\"isMonthCurrent($index)\"\n [class.wr-calendar__chip--selected]=\"isMonthSelected($index)\"\n [disabled]=\"isMonthDisabled($index)\"\n [attr.aria-selected]=\"isMonthSelected($index)\"\n [attr.aria-disabled]=\"isMonthDisabled($index)\"\n (click)=\"onMonthSelect($index)\"\n >\n {{ name }}\n </button>\n }\n </div>\n }\n\n @case ('year') {\n <div class=\"wr-calendar__years\" role=\"listbox\">\n @for (year of yearsView(); track year) {\n <button\n type=\"button\"\n class=\"wr-calendar__chip\"\n role=\"option\"\n [class.wr-calendar__chip--current]=\"isYearCurrent(year)\"\n [class.wr-calendar__chip--selected]=\"isYearSelected(year)\"\n [disabled]=\"isYearDisabled(year)\"\n [attr.aria-selected]=\"isYearSelected(year)\"\n [attr.aria-disabled]=\"isYearDisabled(year)\"\n (click)=\"onYearSelect(year)\"\n >\n {{ year }}\n </button>\n }\n </div>\n }\n}\n" }]
496
536
  }], ctorParameters: () => [], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }, { type: i0.Output, args: ["dateChange"] }], range: [{ type: i0.Input, args: [{ isSignal: true, alias: "range", required: false }] }, { type: i0.Output, args: ["rangeChange"] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], dateFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFilter", required: false }] }], autoFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoFocus", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
497
537
 
498
538
  /**