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,79 @@
1
+ import { BaseHarnessFilters, ComponentHarness, HarnessPredicate } 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
+ /** Narrows which `<wr-donut-chart>` a harness query matches. */
11
+ interface WrDonutChartHarnessFilters extends BaseHarnessFilters {
12
+ /** Match the chart's accessible name. */
13
+ readonly ariaLabel?: string | RegExp;
14
+ /** Match a chart whose legend holds this label. */
15
+ readonly sliceLabel?: string | RegExp;
16
+ }
17
+ /** One legend row — the only place a slice's label and value are readable. */
18
+ interface WrDonutChartLegendEntry {
19
+ readonly label: string;
20
+ readonly value: string;
21
+ }
22
+
23
+ /**
24
+ * @license
25
+ *
26
+ * Use of this source code is governed by an MIT-style license that can be
27
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
28
+ */
29
+
30
+ /**
31
+ * Test harness for `<wr-donut-chart>`.
32
+ *
33
+ * **The ring itself is unreadable, and that is by design.** The slices are SVG
34
+ * paths inside an `aria-hidden` drawing: a screen reader is given the chart's
35
+ * `aria-label` and nothing else, and a spec cannot get a label or a value off a
36
+ * path's `d`. {@link getLegend} is where the numbers are — which is also the
37
+ * argument for keeping `showLegend` on, since with it off the chart's data has no
38
+ * textual form at all.
39
+ *
40
+ * {@link getSliceCount} is therefore the one thing the ring answers: how many
41
+ * wedges were drawn. Compare it with the legend's length to catch a slice that was
42
+ * filtered out of one and not the other.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * const chart = await loader.getHarness(WrDonutChartHarness);
47
+ *
48
+ * expect(await chart.getSliceCount()).toBe(3);
49
+ * expect(await chart.getLegend()).toEqual([
50
+ * { label: 'Direct', value: '48' },
51
+ * { label: 'Search', value: '32' },
52
+ * { label: 'Social', value: '20' },
53
+ * ]);
54
+ * ```
55
+ *
56
+ * @see https://ngwr.dev/guides/testing
57
+ */
58
+ declare class WrDonutChartHarness extends ComponentHarness {
59
+ static hostSelector: string;
60
+ /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
61
+ static with(options?: WrDonutChartHarnessFilters): HarnessPredicate<WrDonutChartHarness>;
62
+ /** The name the ring announces — the whole chart's, since the slices announce nothing. */
63
+ getAccessibleName(): Promise<string | null>;
64
+ /** How many wedges were drawn. */
65
+ getSliceCount(): Promise<number>;
66
+ /** Whether the legend is rendered (`showLegend`, and at least one slice). */
67
+ hasLegend(): Promise<boolean>;
68
+ /** The legend rows in order — the only textual form the data has. */
69
+ getLegend(): Promise<WrDonutChartLegendEntry[]>;
70
+ /** The big number in the middle, or `null` when the chart has none. */
71
+ getCenterValue(): Promise<string | null>;
72
+ /** The caption under the centre value, or `null`. */
73
+ getCenterLabel(): Promise<string | null>;
74
+ /** The ring's diameter in pixels, as the component writes it inline. */
75
+ getSize(): Promise<number>;
76
+ }
77
+
78
+ export { WrDonutChartHarness };
79
+ export type { WrDonutChartHarnessFilters, WrDonutChartLegendEntry };
@@ -143,6 +143,18 @@ declare class WrDrawer {
143
143
  private focusTrap;
144
144
  private previouslyFocused;
145
145
  constructor();
146
+ /**
147
+ * Point the panel's `aria-labelledby` at the CURRENT `[wrDrawerTitle]`.
148
+ *
149
+ * Re-resolved after every render rather than once when the drawer opens,
150
+ * because the title element is projected content and can come and go while
151
+ * the drawer stays open — an `@if` around it, or a heading that only exists
152
+ * once the data arrives. A one-shot lookup leaves the attribute naming an
153
+ * element that has been removed or replaced, and a dangling reference is not
154
+ * a name: the dialog is announced as unnamed, with nothing on screen to say
155
+ * so. A missing title clears the attribute for the same reason.
156
+ */
157
+ private syncLabel;
146
158
  private openOverlay;
147
159
  private closeOverlay;
148
160
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrDrawer, never>;
@@ -97,6 +97,15 @@ declare class WrDropdown {
97
97
  /** Toggle the menu. */
98
98
  toggle(): void;
99
99
  /** @internal */
100
+ /**
101
+ * Whether the pointer, rather than the keyboard, opened the current menu.
102
+ *
103
+ * A hover-opened menu must not take focus — the APG shows a menu on hover and
104
+ * leaves the caret where it was — while a keyboard-opened one must. The
105
+ * trigger MODE cannot answer that on its own: a `trigger="hover"` menu is
106
+ * still openable with Enter, and that open should focus the first item.
107
+ */
108
+ private openedByPointer;
100
109
  protected onClick(event: MouseEvent): void;
101
110
  /** @internal */
102
111
  protected onMouseEnter(): void;
@@ -0,0 +1,301 @@
1
+ import { BaseHarnessFilters, ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';
2
+ import { WrCalendarView } from 'ngwr/event-calendar';
3
+
4
+ /**
5
+ * @license
6
+ *
7
+ * Use of this source code is governed by an MIT-style license that can be
8
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
9
+ */
10
+
11
+ /** Narrows which `<wr-event-calendar>` a harness query matches. */
12
+ interface WrEventCalendarHarnessFilters extends BaseHarnessFilters {
13
+ /** Match the header title as printed — a string is an exact match, a RegExp is tested. */
14
+ readonly title?: string | RegExp;
15
+ /** Match the view the calendar is showing. */
16
+ readonly view?: WrCalendarView;
17
+ }
18
+ /** Narrows which event chip a harness query matches. */
19
+ interface WrEventCalendarChipHarnessFilters extends BaseHarnessFilters {
20
+ /**
21
+ * Match the chip's accessible name, which is the time and the title together —
22
+ * the visible text is `aria-hidden`, so this is what a screen reader gets.
23
+ */
24
+ readonly label?: string | RegExp;
25
+ /** Match the chip's title text as printed. */
26
+ readonly title?: string | RegExp;
27
+ /** Match day-spanning bands (`true`) or timed chips (`false`). */
28
+ readonly band?: boolean;
29
+ }
30
+
31
+ /**
32
+ * @license
33
+ *
34
+ * Use of this source code is governed by an MIT-style license that can be
35
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
36
+ */
37
+
38
+ /** The arrow keys, by the direction a user would say out loud. */
39
+ type Arrow$1 = 'left' | 'right' | 'up' | 'down';
40
+ /**
41
+ * Test harness for one event chip inside a {@link WrEventCalendarHarness}.
42
+ *
43
+ * **The visible text is `aria-hidden`; the name is on the button.** A chip prints a
44
+ * time and a title for the eye, and publishes both as one `aria-label` for a screen
45
+ * reader — so {@link getLabel} is what the control announces and {@link getTitle} is
46
+ * what is drawn. They are separate because a consumer's `[wrCalendarEvent]` template
47
+ * replaces the drawn half and not the announced one.
48
+ *
49
+ * **Moving and resizing are on the keyboard here, and not because of jsdom.** The
50
+ * pointer drag is real, but the same two operations are bound to the arrows —
51
+ * `Alt` to move, `Alt` + `Shift` to resize — precisely so the calendar is usable
52
+ * without one. That is the path this harness drives; a synthetic drag would divide
53
+ * by a rect that measures 0×0 anyway.
54
+ *
55
+ * @see https://ngwr.dev/guides/testing
56
+ */
57
+ declare class WrEventCalendarChipHarness extends ComponentHarness {
58
+ static hostSelector: string;
59
+ /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
60
+ static with(options?: WrEventCalendarChipHarnessFilters): HarnessPredicate<WrEventCalendarChipHarness>;
61
+ /** What the chip announces — its time and title in one string. */
62
+ getLabel(): Promise<string | null>;
63
+ /**
64
+ * The title as drawn, or `null` when a consumer template replaced it.
65
+ *
66
+ * The default chip prints its own `.wr-event-calendar__chip-title`; a
67
+ * `[wrCalendarEvent]` template renders whatever the consumer wrote instead, and
68
+ * there is no title element to find. {@link getText} is the fallback that always
69
+ * answers.
70
+ */
71
+ getTitle(): Promise<string | null>;
72
+ /** The chip's whole rendered text, whoever drew it. */
73
+ getText(): Promise<string>;
74
+ /** The time as printed on a timed chip, or `null` on a band, which prints none. */
75
+ getTime(): Promise<string | null>;
76
+ /**
77
+ * Whether this is a day-spanning BAND rather than a timed chip.
78
+ *
79
+ * One shape covers two places — a month cell and the all-day row — and the other
80
+ * is the block in a time grid. They size themselves completely differently (a
81
+ * `calc()` width across columns versus a percentage height down one), which is why
82
+ * the two are worth telling apart.
83
+ */
84
+ isBand(): Promise<boolean>;
85
+ /** Whether the event started before this cell — the chip is drawn cut off at the leading edge. */
86
+ continuesBefore(): Promise<boolean>;
87
+ /** Whether the event runs past this cell. */
88
+ continuesAfter(): Promise<boolean>;
89
+ /** Whether the chip is mid-drag. */
90
+ isDragging(): Promise<boolean>;
91
+ /**
92
+ * Whether the chip offers a resize grab area.
93
+ *
94
+ * It is `aria-hidden` and not focusable on purpose — the same resize is `Alt` +
95
+ * `Shift` + arrows on the chip itself, so a second tab stop here would lead
96
+ * nowhere. Its
97
+ * presence is still the mouse affordance, and it is dropped on a chip whose event
98
+ * continues past this cell.
99
+ */
100
+ hasResizeHandle(): Promise<boolean>;
101
+ /**
102
+ * Click the chip — which emits `eventClick` and does NOT bubble to the cell
103
+ * underneath.
104
+ *
105
+ * On an editable calendar this needs `document.elementFromPoint` to exist: the CDK
106
+ * dispatches a whole pointer sequence, and the chip's `pointerdown` hit-tests for
107
+ * the cell under the cursor. jsdom implements no such method, so stub it in your
108
+ * spec — `() => null` is the honest answer where nothing has a box — or the click
109
+ * throws out of the listener.
110
+ */
111
+ click(): Promise<void>;
112
+ /** Move keyboard focus to the chip. */
113
+ focus(): Promise<void>;
114
+ /** Whether the chip currently holds focus. */
115
+ isFocused(): Promise<boolean>;
116
+ /**
117
+ * Move the event — `Alt` + an arrow, a day sideways or a slot vertically.
118
+ *
119
+ * The calendar never mutates `events`: this emits `eventChange` and the host is
120
+ * expected to apply it. A spec whose host ignores the output is asserting a
121
+ * CANCELLED move, which is the contract and the most common surprise here. A
122
+ * calendar without `editable` ignores the keys entirely — the same gate the pointer
123
+ * path uses.
124
+ */
125
+ move(arrow: Arrow$1): Promise<void>;
126
+ /**
127
+ * Resize the event — `Alt` + `Shift` + an arrow, which moves the END alone.
128
+ *
129
+ * A resize that would end at or before the start emits nothing rather than
130
+ * inverting the event, which is the pointer path's rule too.
131
+ */
132
+ resize(arrow: Arrow$1): Promise<void>;
133
+ /** Press a bare arrow — which the chip ignores, letting the grid's own navigation run. */
134
+ pressArrow(arrow: Arrow$1): Promise<void>;
135
+ /** Press Escape — handing focus back to the cell the chip sits in. */
136
+ sendEscape(): Promise<void>;
137
+ }
138
+
139
+ /**
140
+ * @license
141
+ *
142
+ * Use of this source code is governed by an MIT-style license that can be
143
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
144
+ */
145
+
146
+ /** The arrow keys, by the direction a user would say out loud. */
147
+ type Arrow = 'left' | 'right' | 'up' | 'down';
148
+ /**
149
+ * Test harness for `<wr-event-calendar>` — month, week and day in one component.
150
+ *
151
+ * **Every chip lives inside the `role="gridcell"` where its event STARTS**, and
152
+ * reaches out from there with a `calc()` width or a percentage height. That is a
153
+ * deliberate structural choice — a floating events layer would leave `role="row"`
154
+ * owning something other than cells — and it is why {@link getChips} can be scoped
155
+ * to a cell at all.
156
+ *
157
+ * **The view is read from the DOM, not from the input.** A month renders one grid
158
+ * shape and week / day another, and those two are told apart by how many day columns
159
+ * they draw. That is the honest answer for a harness: `view` is a model a consumer
160
+ * can write, and the grid is what the user sees.
161
+ *
162
+ * **Nothing here mutates the events.** A move or a resize emits `eventChange` and
163
+ * the host applies it — so a spec whose host ignores the output is asserting a
164
+ * CANCELLED gesture, which is the contract rather than a bug.
165
+ *
166
+ * @example
167
+ * ```ts
168
+ * const calendar = await loader.getHarness(WrEventCalendarHarness);
169
+ *
170
+ * expect(await calendar.getView()).toBe('month');
171
+ * const [standup] = await calendar.getChips({ title: 'Standup' });
172
+ * await standup.move('right');
173
+ * ```
174
+ *
175
+ * @see https://ngwr.dev/guides/testing
176
+ */
177
+ declare class WrEventCalendarHarness extends ComponentHarness {
178
+ static hostSelector: string;
179
+ /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
180
+ static with(options?: WrEventCalendarHarnessFilters): HarnessPredicate<WrEventCalendarHarness>;
181
+ private readonly grid;
182
+ /**
183
+ * Which view is on screen.
184
+ *
185
+ * `month` has its own grid modifier; `week` and `day` share the time grid and are
186
+ * told apart by the column count the component publishes on it. Reading the DOM
187
+ * rather than the `view` model is the point — that model is an input a consumer can
188
+ * set to anything, and this is what got rendered.
189
+ */
190
+ getView(): Promise<WrCalendarView>;
191
+ /** The header title — the month, the week's range, or the day. */
192
+ getTitle(): Promise<string>;
193
+ /** Whether the header is rendered at all (`hideHeader`). */
194
+ hasHeader(): Promise<boolean>;
195
+ /** The grid's accessible name. */
196
+ getAccessibleName(): Promise<string | null>;
197
+ /** Step back one month, week or day, depending on the view. */
198
+ previous(): Promise<void>;
199
+ /** Step forward one month, week or day. */
200
+ next(): Promise<void>;
201
+ /** Press the Today button — jumping to the period containing today. */
202
+ goToday(): Promise<void>;
203
+ /** The back arrow's accessible name — the two steps are icon-only. */
204
+ getPreviousLabel(): Promise<string | null>;
205
+ /** The forward arrow's accessible name. */
206
+ getNextLabel(): Promise<string | null>;
207
+ /** The Today button's label. */
208
+ getTodayLabel(): Promise<string>;
209
+ /**
210
+ * The view switcher's labels, in order — empty when the calendar was given a single
211
+ * view, which drops the switcher entirely.
212
+ */
213
+ getViewLabels(): Promise<string[]>;
214
+ /** The label of the view currently pressed, or `null` when there is no switcher. */
215
+ getActiveViewLabel(): Promise<string | null>;
216
+ /**
217
+ * Switch view by the label the switcher prints.
218
+ *
219
+ * By label rather than by the `WrCalendarView` value, because the label is what the
220
+ * DOM has — the value never reaches it, and a spec that passed one would be naming
221
+ * something only the component can see. {@link getViewLabels} lists them.
222
+ */
223
+ setView(label: string): Promise<void>;
224
+ /** The weekday column headers of the month view. */
225
+ getWeekdayNames(): Promise<string[]>;
226
+ /** The day numbers of the month grid, in order — 42 of them, spill days included. */
227
+ getDayNumbers(): Promise<string[]>;
228
+ /** The time-gutter labels down the left of a week or day view. */
229
+ getSlotLabels(): Promise<string[]>;
230
+ /** Whether the time views drew an all-day band, which they only do when something needs it. */
231
+ hasAllDayRow(): Promise<boolean>;
232
+ /**
233
+ * Every chip on screen, in DOM order.
234
+ *
235
+ * A multi-day event has ONE chip, in the cell where it starts — the band reaches
236
+ * across the rest — so this counts events-in-view rather than event-days.
237
+ */
238
+ getChips(filters?: WrEventCalendarChipHarnessFilters): Promise<WrEventCalendarChipHarness[]>;
239
+ /** The chips' announced names, in DOM order. */
240
+ getChipLabels(): Promise<(string | null)[]>;
241
+ /**
242
+ * The "+N more" overflow buttons of the month view, by the text they print.
243
+ *
244
+ * A month cell shows `maxLanes` chips and hides the rest behind one of these, which
245
+ * opens the day view — so its presence is the only sign that a cell has more than
246
+ * it is showing.
247
+ */
248
+ getOverflowLabels(): Promise<string[]>;
249
+ /** Click the first "+N more" button, which drops to the day view for that date. */
250
+ openOverflow(): Promise<void>;
251
+ /**
252
+ * Click an empty part of a cell — which emits `slotClick` with its date and minutes.
253
+ *
254
+ * A cell is addressed by its DAY and, in a time view, the minutes from midnight of
255
+ * its row (`-1` means a month cell or the all-day band). Both come off the two data
256
+ * attributes every cell publishes for the drag's own hit-testing, which makes them
257
+ * the one stable way to name a cell from outside — a row index would mean something
258
+ * different in each view.
259
+ */
260
+ clickCell(day: Date, minutes?: number): Promise<void>;
261
+ /** A cell's accessible name — the date, and the time for a slot. */
262
+ getCellLabel(day: Date, minutes?: number): Promise<string | null>;
263
+ /** The chips inside ONE cell, which is where a chip's event starts. */
264
+ getCellChips(day: Date, minutes?: number): Promise<WrEventCalendarChipHarness[]>;
265
+ /**
266
+ * The grid's single tab stop, as `"<day>:<minutes>"`.
267
+ *
268
+ * The cursor roves rather than every cell being tabbable, and it is RAW — it
269
+ * survives a view switch, so the same pair means a different cell in a month grid
270
+ * and a week one.
271
+ */
272
+ getCursor(): Promise<string | null>;
273
+ /** Move keyboard focus to a cell, which is also what moves the roving cursor onto it. */
274
+ focusCell(day: Date, minutes?: number): Promise<void>;
275
+ /**
276
+ * Press an arrow on the cell that currently holds the cursor.
277
+ *
278
+ * Sent to that cell rather than to the grid, because the component listens per cell
279
+ * — the element carrying the keyboard should be the one that holds focus — and
280
+ * anything originating inside a chip is deliberately let through untouched.
281
+ */
282
+ pressArrow(arrow: Arrow): Promise<void>;
283
+ /** Press Home on the cursor cell — the first day of its week. */
284
+ pressHome(): Promise<void>;
285
+ /** Press End on the cursor cell — the last day of its week. */
286
+ pressEnd(): Promise<void>;
287
+ private step;
288
+ private stepElement;
289
+ private headerButton;
290
+ /**
291
+ * The stamp a cell publishes for a day — local midnight, which is what the
292
+ * component's own `startOfDay` produces. Taking a `Date` and normalising here keeps
293
+ * the timestamp out of every spec.
294
+ */
295
+ private stamp;
296
+ private requireCell;
297
+ private cursorCell;
298
+ }
299
+
300
+ export { WrEventCalendarChipHarness, WrEventCalendarHarness };
301
+ export type { WrEventCalendarChipHarnessFilters, WrEventCalendarHarnessFilters };
@@ -220,13 +220,16 @@ declare class WrEventCalendar {
220
220
  private readonly document;
221
221
  private readonly dir;
222
222
  private readonly chipTpl;
223
- protected readonly todayLabel: string;
224
- protected readonly previousLabel: string;
225
- protected readonly nextLabel: string;
226
- protected readonly allDayLabel: string;
227
- protected readonly timeLabel: string;
223
+ protected readonly todayLabel: _angular_core.Signal<string>;
224
+ protected readonly previousLabel: _angular_core.Signal<string>;
225
+ protected readonly nextLabel: _angular_core.Signal<string>;
226
+ protected readonly allDayLabel: _angular_core.Signal<string>;
227
+ protected readonly timeLabel: _angular_core.Signal<string>;
228
228
  protected readonly moreLabel: (params?: ngwr_i18n.WrI18nParams) => string;
229
- protected readonly viewLabels: Record<WrCalendarView, string>;
229
+ private readonly monthLabel;
230
+ private readonly weekLabel;
231
+ private readonly dayLabel;
232
+ protected readonly viewLabels: _angular_core.Signal<Record<WrCalendarView, string>>;
230
233
  /** Accessible name of the grid; overridable for a page with several. */
231
234
  readonly ariaLabel: _angular_core.InputSignal<string | null>;
232
235
  protected readonly resolvedAriaLabel: _angular_core.Signal<string>;
@@ -0,0 +1,186 @@
1
+ import { BaseHarnessFilters, ComponentHarness, HarnessPredicate } 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
+ /** Narrows which `<wr-falling-text>` a harness query matches. */
11
+ interface WrFallingTextHarnessFilters extends BaseHarnessFilters {
12
+ /**
13
+ * Match the rendered sentence — the only thing that tells two of these apart, the
14
+ * component having no name, id or role of its own. A string is an exact match, a
15
+ * RegExp is tested.
16
+ *
17
+ * Compared against `WrFallingTextHarness.getText()`, so the non-breaking spaces the
18
+ * component types between the words are already back to plain ones: pass the sentence
19
+ * as it was written.
20
+ */
21
+ readonly text?: string | RegExp;
22
+ }
23
+
24
+ /**
25
+ * @license
26
+ *
27
+ * Use of this source code is governed by an MIT-style license that can be
28
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
29
+ */
30
+
31
+ /**
32
+ * Test harness for `<wr-falling-text>`.
33
+ *
34
+ * **The assertion that matters here is that the animation did not eat the text.** The
35
+ * component cuts the sentence into one span per word so a physics loop can throw them
36
+ * around, and {@link getText} is the check that a screen reader still gets prose out of
37
+ * the other end. It normalises whitespace on the way, because the separators are real
38
+ * `&nbsp;` characters rather than plain spaces — so `textContent` is never byte-identical
39
+ * to the `[text]` input, and a spec comparing the two raw would fail on a component that
40
+ * works perfectly.
41
+ *
42
+ * The rest of the readable surface is the split itself: {@link getWords} pins the rule
43
+ * (split on spaces, empty tokens dropped) and {@link getHighlightedWords} pins the
44
+ * prefix match, which is genuine logic — `grav` highlights `gravity`, and a whole-word
45
+ * implementation would satisfy every naive test but not this one.
46
+ *
47
+ * **Nothing positional is offered, and that is not a jsdom concession.** The words'
48
+ * `transform` values are one frame of a loop that never stops, seeded by `Math.random()`,
49
+ * so they are not reproducible even in a real browser; there is no rest state to call
50
+ * settled; the drag path needs `setPointerCapture` and AABB hit-testing over boxes that
51
+ * a unit test measures as 0×0 at the origin, where every word contains every point. Nor
52
+ * is `[gravity]` or `[trigger]` readable — neither reaches the DOM, and answering them
53
+ * would mean reaching into the component instance. There is no `isReducedMotion()`
54
+ * either: under reduced motion the component simply returns before touching anything, so
55
+ * the only honest proxy is {@link hasReleased}, which reports what it did rather than
56
+ * what it was told.
57
+ *
58
+ * **{@link hasReleased} and {@link release} have a precondition, and without it they are
59
+ * worthless.** The simulator measures the host and each word before it starts, and bails
60
+ * on a zero-sized box — which is every box in a test with no layout. So the spec has to
61
+ * give them one, and it has to do it BEFORE the trigger fires: the component marks itself
62
+ * started on the way past that guard, and the trigger listener is `{ once: true }`, so a
63
+ * failed first attempt is permanent.
64
+ *
65
+ * ```ts
66
+ * // In your spec, on a fixture mounted with trigger="click", before calling release():
67
+ * const box = { width: 300, height: 120, left: 0, top: 0, right: 300, bottom: 120 } as DOMRect;
68
+ * for (const el of fixture.nativeElement.querySelectorAll('wr-falling-text, .wr-falling-text__word')) {
69
+ * el.getBoundingClientRect = () => box;
70
+ * }
71
+ * ```
72
+ *
73
+ * Assert `hasReleased()` is `true` in that control case before you assert it is `false`
74
+ * anywhere else, or a spec proves only that the guard fired.
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * const loader = TestbedHarnessEnvironment.loader(fixture);
79
+ * const text = await loader.getHarness(WrFallingTextHarness);
80
+ *
81
+ * expect(await text.getText()).toBe('gravity pulls every word down');
82
+ * expect(await text.getHighlightedWords()).toEqual(['gravity']);
83
+ * ```
84
+ *
85
+ * @see https://ngwr.dev/guides/testing
86
+ */
87
+ declare class WrFallingTextHarness extends ComponentHarness {
88
+ static hostSelector: string;
89
+ /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
90
+ static with(options?: WrFallingTextHarnessFilters): HarnessPredicate<WrFallingTextHarness>;
91
+ private readonly wordEls;
92
+ /**
93
+ * The whole sentence, as a screen reader reads it: whitespace collapsed and trimmed.
94
+ *
95
+ * The one assertion worth making about a component that dismantles a paragraph. The
96
+ * words are separated by `.wr-falling-text__space` spans holding U+00A0, so this
97
+ * collapses them back to ordinary spaces — losing those spans would be invisible to
98
+ * every other check here while turning the announcement into one run-on word.
99
+ *
100
+ * DOM order never changes once the physics starts. The words are absolutely positioned
101
+ * and scattered on screen, but they are still read in the order they were typeset, so
102
+ * this answers the same before and after {@link release}.
103
+ */
104
+ getText(): Promise<string>;
105
+ /**
106
+ * Each word, in DOM order.
107
+ *
108
+ * Pins the split rule: on a literal space, with empty tokens dropped. Each of these is
109
+ * also one body in the simulator, so the length is the body count — which is why there
110
+ * is no separate `getWordCount()`, a method that would invite asserting how many
111
+ * without asserting which.
112
+ */
113
+ getWords(): Promise<string[]>;
114
+ /**
115
+ * The words carrying the highlight, in DOM order.
116
+ *
117
+ * `[highlightWords]` is matched as a PREFIX and case-sensitively, so `['grav']` picks
118
+ * up `gravity` and `['Grav']` picks up nothing. The highlight is colour alone with no
119
+ * non-visual counterpart, which is acceptable only because it adds no meaning the
120
+ * sentence does not already carry.
121
+ */
122
+ getHighlightedWords(): Promise<string[]>;
123
+ /**
124
+ * Whether one word is highlighted — for asserting a keyword without depending on the
125
+ * order or the completeness of the whole list.
126
+ *
127
+ * Takes the word as it is rendered, not the keyword that matched it: ask for `gravity`,
128
+ * not for `grav`. Throws for a word the sentence does not contain, since `false` there
129
+ * would read as "present and not highlighted" and quietly survive a typo. A word that
130
+ * appears twice is answered once, which is safe — matching is on the text alone, so
131
+ * both copies always agree.
132
+ */
133
+ isHighlighted(word: string): Promise<boolean>;
134
+ /**
135
+ * The font size as the consumer wrote it — `'2rem'`, not `'32px'`.
136
+ *
137
+ * Read off the inline `style` attribute rather than through `getCssValue()`. The two
138
+ * agree here and would part company in a real browser, which resolves `font-size` to
139
+ * pixels; `[fontSize]` takes a CSS length and handing back a different unit than the
140
+ * one that went in is the sort of green unit test that hides a broken assertion.
141
+ *
142
+ * Throws when nothing is written, which takes an empty `[fontSize]` — the component
143
+ * writes this on every render otherwise, default included.
144
+ */
145
+ getFontSize(): Promise<string>;
146
+ /**
147
+ * Whether the simulator has taken the words over.
148
+ *
149
+ * Reads the `position: absolute` the component writes onto every word before its first
150
+ * frame — a value it wrote itself, not a measurement, and the only difference in the
151
+ * DOM between "the physics is running" and "the words are still in normal flow". That
152
+ * makes it the way to observe the trigger contract and the reduced-motion escape, since
153
+ * neither leaves anything else behind.
154
+ *
155
+ * **It is `false` by default in a test, for a reason that has nothing to do with the
156
+ * component.** Without layout every box measures 0×0 and the simulator refuses to start
157
+ * — see this class's docs for the stub, and assert a `true` before you trust a `false`.
158
+ *
159
+ * Throws for a component rendering no words at all, where the question does not apply.
160
+ */
161
+ hasReleased(): Promise<boolean>;
162
+ /**
163
+ * Fire the events a `click` or `hover` trigger is waiting for.
164
+ *
165
+ * Both, because the harness cannot tell which one it is: `[trigger]` never reaches the
166
+ * DOM. The component consumes at most one — its listener is registered `{ once: true }`
167
+ * and the simulator refuses to start twice — so this is safe to call whatever the
168
+ * trigger is, and safe to call again.
169
+ *
170
+ * It does nothing for `auto`, which released on mount, and nothing for `scroll`, which
171
+ * waits on an `IntersectionObserver`: jsdom has none, so a spec has to stub the global
172
+ * and fire the callback itself. Same precondition as {@link hasReleased} — stub the
173
+ * boxes BEFORE calling this, because a start that bails on a zero-sized host still
174
+ * burns the trigger.
175
+ *
176
+ * Both are dispatched as bare events rather than through the harness's `click()` and
177
+ * `hover()` helpers, which would bring a whole pointer sequence with them. Released
178
+ * words listen for `pointerdown` so they can be picked up and thrown, and that handler
179
+ * calls `setPointerCapture` — which a unit environment does not implement, so the
180
+ * realistic version of this method would throw the moment the simulator was running.
181
+ */
182
+ release(): Promise<void>;
183
+ }
184
+
185
+ export { WrFallingTextHarness };
186
+ export type { WrFallingTextHarnessFilters };