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,130 @@
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-fuzzy-text>` a harness query matches. */
11
+ interface WrFuzzyTextHarnessFilters extends BaseHarnessFilters {
12
+ /**
13
+ * Match the headline — a string is an exact match, a RegExp is tested.
14
+ *
15
+ * The only filter, and the only one possible: everything else this component is told
16
+ * ends up as a canvas font string or a fill style and never reaches the DOM, so the
17
+ * readable copy of the text is the sole thing that tells two headlines apart. Matched
18
+ * through `WrFuzzyTextHarness.getText`, which reads the screen-reader span rather than
19
+ * the pixels.
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-fuzzy-text>` — a headline drawn into a canvas, one row of pixels
33
+ * at a time, with a random offset per row.
34
+ *
35
+ * **The drawing is out of reach and the accessible half is not, which is the whole shape
36
+ * of this harness.** There is no 2D context in a unit test — `getContext('2d')` returns
37
+ * `null`, and the component's `init()` gives up on the line after — so nothing downstream
38
+ * of that ever happens: no font load, no animation frame, no canvas listeners, no sizing.
39
+ * What survives is the markup, and the markup is the part that regressed: everything this
40
+ * component rendered used to be a canvas, so a screen reader got an empty element where
41
+ * the page showed a headline. {@link getText} and {@link isDecorative} are that fix,
42
+ * asserted as the PAIR it has to be — a readable copy plus a hidden pixel copy. Reading
43
+ * one without the other passes just as happily on a component that announces the headline
44
+ * twice.
45
+ *
46
+ * **The canvas is selected by tag, not by a class.** It carries no BEM name, unlike the
47
+ * two sibling animation canvases — this entry point ships no stylesheet at all, which is
48
+ * also why {@link isTextVisuallyHidden} is a real question rather than a formality.
49
+ *
50
+ * Nothing about the animation is offered, and none of it is a gap that could be closed by
51
+ * trying harder. There is no `getIntensity()` / `isFuzzing()` / `isGlitching()`: those are
52
+ * closure variables inside `init()` that only ever manifest as pixels, and in a test the
53
+ * function returns before they exist. No `hover()` / `click()` / `getHoverIntensity()`:
54
+ * the pointer listeners are attached only after a real context AND a resolved
55
+ * `document.fonts` — neither of which a unit test has — so a dispatched event would land
56
+ * on nothing and the assertion would pass vacuously; the hit test also measures the canvas
57
+ * box, which is all zeros. No `getCanvasSize()`, which would be asserting jsdom's untouched
58
+ * 300×150 default rather than the component's layout maths. No `getColor()` /
59
+ * `getFontSize()` / `getFontFamily()` / `getGradient()`: every one of those becomes a
60
+ * canvas font string or a fill style and never reaches the DOM. No `getRenderedText()` or
61
+ * `readPixel()` — there are no pixels, and faking a context would change what every spec
62
+ * here is testing. And no `isReducedMotion()`: the preference is honoured by taking a
63
+ * different DRAWING path, with identical markup, classes and attributes either way, so the
64
+ * method would answer the same for a component that honoured it and one that ignored it.
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * const headline = await loader.getHarness(WrFuzzyTextHarness.with({ text: '404' }));
69
+ *
70
+ * expect(await headline.getText()).toBe('404');
71
+ * expect(await headline.isDecorative()).toBe(true);
72
+ * ```
73
+ *
74
+ * @see https://ngwr.dev/guides/testing
75
+ */
76
+ declare class WrFuzzyTextHarness extends ComponentHarness {
77
+ static hostSelector: string;
78
+ /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
79
+ static with(options?: WrFuzzyTextHarnessFilters): HarnessPredicate<WrFuzzyTextHarness>;
80
+ private readonly srOnly;
81
+ private readonly canvas;
82
+ /**
83
+ * The headline as TEXT, trimmed.
84
+ *
85
+ * From the screen-reader span, which is the only place the string exists as characters —
86
+ * the visible copy is glyphs painted into a canvas. This is the single assertion that
87
+ * separates the component from an empty box for anyone not looking at the screen, and it
88
+ * is the one that has already regressed once.
89
+ *
90
+ * There is no letter-by-letter split to worry about here, unlike the other text
91
+ * animations in the library: the span holds one text node, so what a reader announces is
92
+ * what {@link WrFuzzyTextHarness.getText} returns.
93
+ */
94
+ getText(): Promise<string>;
95
+ /**
96
+ * Whether the pixel copy stays out of the accessibility tree.
97
+ *
98
+ * The other half of {@link getText}. The canvas has no text and no name, so without its
99
+ * `aria-hidden` a reader meets an anonymous element next to the headline it already
100
+ * read — or, if the span ever goes away again, only the anonymous element. Asserting the
101
+ * two together is what pins the arrangement; asserting either alone does not.
102
+ */
103
+ isDecorative(): Promise<boolean>;
104
+ /**
105
+ * Whether the drawing surface is in the markup.
106
+ *
107
+ * True even where it can never be painted — under SSR, in a prerender, in a browser that
108
+ * refuses a 2D context, and in every unit test — because the element is rendered
109
+ * unconditionally and only the drawing depends on a context. That is precisely the state
110
+ * the readable copy exists to cover, so this is the method that says "the fallback is
111
+ * carrying the page right now".
112
+ */
113
+ hasCanvas(): Promise<boolean>;
114
+ /**
115
+ * Whether the readable copy hides itself without a stylesheet.
116
+ *
117
+ * This entry point ships no CSS. The span is therefore hidden with inline declarations
118
+ * rather than an `.sr-only` class, and that is load-bearing rather than a style choice:
119
+ * move the block into a class and every consumer who imported no CSS sees the headline
120
+ * twice — once as pixels, once as a stray line of markup underneath.
121
+ *
122
+ * Three of the declarations are checked, not one, because they fail apart: `position`
123
+ * takes the span out of flow, the 1px box collapses it, and `clip-path` is what keeps
124
+ * the character still reachable by a reader instead of `display: none`-ing it away.
125
+ */
126
+ isTextVisuallyHidden(): Promise<boolean>;
127
+ }
128
+
129
+ export { WrFuzzyTextHarness };
130
+ export type { WrFuzzyTextHarnessFilters };
@@ -0,0 +1,71 @@
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-gauge>` a harness query matches. */
11
+ interface WrGaugeHarnessFilters extends BaseHarnessFilters {
12
+ /** Match the dial's accessible name. */
13
+ readonly ariaLabel?: string | RegExp;
14
+ /** Match the value the dial announces. */
15
+ readonly value?: number;
16
+ }
17
+
18
+ /**
19
+ * @license
20
+ *
21
+ * Use of this source code is governed by an MIT-style license that can be
22
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
23
+ */
24
+
25
+ /**
26
+ * Test harness for `<wr-gauge>`.
27
+ *
28
+ * **The dial is `aria-hidden` and the printed number is optional, so the ARIA is the
29
+ * whole readable surface.** The component carries `role="meter"` with the value
30
+ * trio and an `aria-valuetext` that includes the suffix — which is what makes a
31
+ * gauge with `showValue` off readable at all. {@link getValue} is what it announces;
32
+ * {@link getDisplayValue} is what is drawn, and it is `null` when nothing is.
33
+ *
34
+ * The arc is an SVG path, and its `d` is a rendering detail rather than an
35
+ * assertion — it moves with the size, the stroke width and the sweep.
36
+ *
37
+ * @see https://ngwr.dev/guides/testing
38
+ */
39
+ declare class WrGaugeHarness extends ComponentHarness {
40
+ static hostSelector: string;
41
+ /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
42
+ static with(options?: WrGaugeHarnessFilters): HarnessPredicate<WrGaugeHarness>;
43
+ private readonly surface;
44
+ /** The role the dial announces — `meter`, which is what a gauge is. */
45
+ getRole(): Promise<string | null>;
46
+ /** The dial's accessible name. */
47
+ getAccessibleName(): Promise<string | null>;
48
+ /** The value it announces, from `aria-valuenow`. */
49
+ getValue(): Promise<number>;
50
+ /** The bottom of the range, from `aria-valuemin`. */
51
+ getMin(): Promise<number>;
52
+ /** The top of the range, from `aria-valuemax`. */
53
+ getMax(): Promise<number>;
54
+ /**
55
+ * The spoken form of the value — the number with its suffix.
56
+ *
57
+ * The reason a gauge with no printed value is still readable, and worth asserting
58
+ * separately from {@link getValue}: a percentage announced as a bare `72` says
59
+ * something different from `72%`.
60
+ */
61
+ getValueText(): Promise<string | null>;
62
+ /** The number printed in the middle, suffix included, or `null` when `showValue` is off. */
63
+ getDisplayValue(): Promise<string | null>;
64
+ /** The suffix alone, or `null` when there is none — or nothing is printed. */
65
+ getSuffix(): Promise<string | null>;
66
+ /** The dial's width in pixels, as the component writes it inline. */
67
+ getSize(): Promise<number>;
68
+ }
69
+
70
+ export { WrGaugeHarness };
71
+ export type { WrGaugeHarnessFilters };
@@ -0,0 +1,172 @@
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-glitch-text>` a harness query matches. */
11
+ interface WrGlitchTextHarnessFilters extends BaseHarnessFilters {
12
+ /** Match the rendered text — a string is an exact match, a RegExp is tested. */
13
+ readonly text?: string | RegExp;
14
+ /**
15
+ * Match only the hover-gated variant (`true`) or only the always-on one (`false`).
16
+ * Note that hover-gated is the DEFAULT, so `{ hoverOnly: false }` selects the
17
+ * component that was explicitly told `[enableOnHover]="false"`.
18
+ */
19
+ readonly hoverOnly?: boolean;
20
+ }
21
+ /** How long each clone layer takes to complete one tear cycle, in seconds. */
22
+ interface WrGlitchTextDurations {
23
+ /** The `::before` clone — `speed × 2`. */
24
+ readonly before: number;
25
+ /** The `::after` clone — `speed × 3`. */
26
+ readonly after: number;
27
+ }
28
+ /** The two clone `text-shadow`s, exactly as the component wrote them. */
29
+ interface WrGlitchTextColourSplit {
30
+ /** The `::before` clone's shadow — offset right, and tinted `info`. */
31
+ readonly before: string;
32
+ /** The `::after` clone's shadow — offset left, and tinted `danger`. */
33
+ readonly after: string;
34
+ }
35
+
36
+ /**
37
+ * @license
38
+ *
39
+ * Use of this source code is governed by an MIT-style license that can be
40
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
41
+ */
42
+
43
+ /**
44
+ * Test harness for `<wr-glitch-text>`.
45
+ *
46
+ * **The one thing worth testing here is the pairing.** The two torn clones are
47
+ * `::before` / `::after` pseudo-elements whose glyphs come from `content:
48
+ * attr(data-text)`, so the string has to be in the host's text node AND in the host's
49
+ * `data-text` attribute. Drop either binding and the visible text stays flawless while
50
+ * the effect disappears — no error, no missing element, nothing else in the DOM
51
+ * changes. {@link isCloneTextInSync} is that assertion in one call.
52
+ *
53
+ * **Everything else the harness reads is an inline custom property**, because that is
54
+ * everything the component writes: the two clone durations, the two colour-split
55
+ * shadows and the optional slice background. They are worth pinning for the unit
56
+ * transforms — a duration that loses its `s`, or two clones that end up on the same
57
+ * multiple and tear in lockstep, is a regression that changes no class, no attribute
58
+ * and no text.
59
+ *
60
+ * **What the harness deliberately does not offer**, and why. There is no
61
+ * `isGlitching()`: the tear is a `@keyframes` animation on a pseudo-element, applied by
62
+ * a stylesheet a unit test never loads, so the only available answer is a class name
63
+ * repackaged as a state. There is no `hover()` / `isGlitchingOnHover()`: the gate is a
64
+ * `:hover` SELECTOR, and the DOM after a dispatched mouse event is byte-identical to
65
+ * the DOM before it — a spec built on that would pass against a component whose hover
66
+ * rules had been deleted. There is no `getCloneOffset()` / `getClipPath()`: the ±10px
67
+ * offsets and the tear bands live in the stylesheet and are pure layout besides. There
68
+ * is no `respectsReducedMotion()`: the handling is a `@media` block with no TypeScript
69
+ * counterpart, so the DOM is identical in both states and there is nothing to read.
70
+ * There is no resolver for the shadow colours — they hold `var(--wr-color-info)` /
71
+ * `var(--wr-color-danger)`, and resolving those needs the theme stylesheet. And there
72
+ * is no `getSpeed()`: the input is never written to the DOM, only its two products are,
73
+ * and dividing one back would invent a precision the component never published (at
74
+ * `[speed]="0.3"` the after-duration is literally `0.8999999999999999s`).
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * const glitch = await loader.getHarness(WrGlitchTextHarness);
79
+ *
80
+ * expect(await glitch.isCloneTextInSync()).toBe(true);
81
+ * expect((await glitch.getDurations()).after).toBeCloseTo(3);
82
+ * ```
83
+ *
84
+ * @see https://ngwr.dev/guides/testing
85
+ */
86
+ declare class WrGlitchTextHarness extends ComponentHarness {
87
+ static hostSelector: string;
88
+ /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
89
+ static with(options?: WrGlitchTextHarnessFilters): HarnessPredicate<WrGlitchTextHarness>;
90
+ /**
91
+ * The rendered text, trimmed.
92
+ *
93
+ * The half a sighted user reads, and the half every other check would notice
94
+ * breaking. The component interpolates the input straight onto the host, so there is
95
+ * no inner element to query.
96
+ */
97
+ getText(): Promise<string>;
98
+ /**
99
+ * The string the two clone layers draw from — the host's `data-text`.
100
+ *
101
+ * The half nothing else notices. `content: attr(data-text)` is how both pseudo-clones
102
+ * get their glyphs, so this attribute IS the effect. `null` means the mirror is gone
103
+ * and the component is rendering plain text with extra classes.
104
+ */
105
+ getCloneText(): Promise<string | null>;
106
+ /**
107
+ * Whether the clone attribute still mirrors the rendered text.
108
+ *
109
+ * The component's defining silent failure, as a single assertion — two separate reads
110
+ * are two things a spec can forget to write together. Compared raw on both sides,
111
+ * with no trimming: the template is the bare interpolation, so the text node and the
112
+ * attribute are byte-identical or the mirror is broken. An empty `text` is legal and
113
+ * counts as in sync — `data-text=""` is a mirror of nothing, not a missing binding,
114
+ * which is why {@link getCloneText} reports the absent case as `null` instead.
115
+ */
116
+ isCloneTextInSync(): Promise<boolean>;
117
+ /**
118
+ * Whether the effect idles until the pointer arrives (`enableOnHover`).
119
+ *
120
+ * The `wr-glitch-text--hover-only` class is the only DOM trace of that input, the gate
121
+ * itself being a `:hover` rule. It defaults to `true`, so this is also how a spec
122
+ * catches the day someone "fixes" the default to match the component's own JSDoc,
123
+ * which describes the opposite.
124
+ */
125
+ isHoverOnly(): Promise<boolean>;
126
+ /**
127
+ * How long each clone takes to complete a cycle, in seconds.
128
+ *
129
+ * The two must NOT be equal: they run at 2× and 3× the `speed` multiplier so the tears
130
+ * fall out of phase, and clones tearing in lockstep read as one shifted copy rather
131
+ * than as a glitch. That regression changes no class, no attribute and no text, and no
132
+ * visual gate in this repo can see it either.
133
+ *
134
+ * These are raw JavaScript floats — `[speed]="0.3"` writes `0.8999999999999999s` —
135
+ * so compare with `toBeCloseTo`, never against a formatted string.
136
+ */
137
+ getDurations(): Promise<WrGlitchTextDurations>;
138
+ /**
139
+ * Whether the red / cyan colour split is switched on (`enableShadows`).
140
+ *
141
+ * The component writes the literal `none` rather than removing the properties when the
142
+ * split is off, so "disabled" and "never set" stay distinguishable — an absent property
143
+ * would mean a broken binding, and this reports that as no split either.
144
+ */
145
+ hasColourSplit(): Promise<boolean>;
146
+ /**
147
+ * The two clone `text-shadow`s, exactly as written — `var()` tokens and all.
148
+ *
149
+ * Returned unresolved on purpose: resolving `var(--wr-color-info)` needs the theme
150
+ * stylesheet, and a unit test that answered with a colour would be inventing one.
151
+ * What the raw pair does prove is the thing a copy-paste breaks — the offsets must
152
+ * have OPPOSITE signs and the two tints must be DIFFERENT intents. Give both clones
153
+ * the same colour, or the same sign, and the chromatic aberration is gone while every
154
+ * other reading stays green.
155
+ */
156
+ getColourSplit(): Promise<WrGlitchTextColourSplit>;
157
+ /**
158
+ * The masking colour behind the clone slices, or `null` when none was given.
159
+ *
160
+ * The binding emits `null` for an empty input, so the property is ABSENT rather than
161
+ * set to `transparent`, and the stylesheet's own `var(--wr-glitch-text-bg, transparent)`
162
+ * fallback does the work. A component that started writing `transparent` inline would
163
+ * look identical and break nothing until a consumer relied on that fallback — which is
164
+ * the whole reason this reports the absent case as `null` instead of as a colour.
165
+ */
166
+ getSliceBackground(): Promise<string | null>;
167
+ /** One of the host's inline duration properties, as a number of seconds. */
168
+ private seconds;
169
+ }
170
+
171
+ export { WrGlitchTextHarness };
172
+ export type { WrGlitchTextColourSplit, WrGlitchTextDurations, WrGlitchTextHarnessFilters };
@@ -0,0 +1,173 @@
1
+ import { BaseHarnessFilters, ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';
2
+ import { WrGradientTextDirection } from 'ngwr/gradient-text';
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-gradient-text>` a harness query matches. */
12
+ interface WrGradientTextHarnessFilters extends BaseHarnessFilters {
13
+ /** Match the projected text — a string is an exact match, a RegExp is tested. */
14
+ readonly text?: string | RegExp;
15
+ /**
16
+ * Match the sweep direction. `'horizontal'` is the ABSENCE of a modifier rather than a
17
+ * class of its own — see `WrGradientTextHarness.getDirection`, which resolves it.
18
+ */
19
+ readonly direction?: WrGradientTextDirection;
20
+ /** Match only the pill variant (`true`) or only the bare one (`false`). */
21
+ readonly border?: boolean;
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-gradient-text>`.
33
+ *
34
+ * **The gradient string is the component.** Everything `[colors]` and `[direction]`
35
+ * decide ends up in one inline custom property — the angle keyword, the stop list, and
36
+ * the first colour repeated at the end, which is what makes the loop seamless instead of
37
+ * snapping back at the wrap. {@link getColors} returns that list AS WRITTEN, wrap stop
38
+ * included, because the duplicate is the thing worth asserting and stripping it would
39
+ * hide the day it goes missing.
40
+ *
41
+ * **Direction is two facts, not one.** The modifier class says which way the gradient
42
+ * travels and {@link getBackgroundSize} says which axis it was stretched along, and they
43
+ * are computed separately: a direction change that forgets the size leaves every class
44
+ * looking right while the effect is squashed flat. Note too that `horizontal` writes NO
45
+ * class at all — {@link getDirection} resolves the absence, which is the mapping a
46
+ * refactor breaks most easily.
47
+ *
48
+ * **What the harness deliberately does not offer**, and why. There is no `isAnimating()`
49
+ * / `isPaused()`: the sweep is a stylesheet keyframe, and a unit test loads no
50
+ * stylesheet, so the answer would be the same constant for a working component and a
51
+ * broken one. There is no `getBackgroundPosition()`: the swept value exists only
52
+ * mid-animation, and the static declaration it would return corresponds to no frame the
53
+ * user ever sees. {@link pausesOnHover} claims the CLASS and not the pause, deliberately
54
+ * — `:hover` is a selector, and the DOM after a dispatched mouse event is identical to
55
+ * the DOM before it. There is no `respectsReducedMotion()`: the only handling is a
56
+ * `@media` block with no TypeScript counterpart, so nothing in the DOM changes in either
57
+ * state. And there is nothing that reports the painted text colour: the fill comes from
58
+ * `background-clip: text` over a `color: transparent` declared in the stylesheet, so a
59
+ * read would describe the inherited colour and call the text readable where the browser
60
+ * paints a gradient.
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * const gradient = await loader.getHarness(WrGradientTextHarness);
65
+ *
66
+ * expect(await gradient.getColors()).toEqual(['#111111', '#222222', '#111111']);
67
+ * expect(await gradient.getBackgroundSize()).toBe('300% 100%');
68
+ * ```
69
+ *
70
+ * @see https://ngwr.dev/guides/testing
71
+ */
72
+ declare class WrGradientTextHarness extends ComponentHarness {
73
+ static hostSelector: string;
74
+ /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
75
+ static with(options?: WrGradientTextHarnessFilters): HarnessPredicate<WrGradientTextHarness>;
76
+ private readonly text;
77
+ private readonly ring;
78
+ /**
79
+ * The projected text, trimmed.
80
+ *
81
+ * Read from the text span rather than from the host, so the answer stays correct on the
82
+ * day the decorative ring gains content of its own — it is a sibling of this span, and
83
+ * the host's text would include both.
84
+ */
85
+ getText(): Promise<string>;
86
+ /**
87
+ * Which way the gradient travels.
88
+ *
89
+ * `horizontal` is reported for the absence of both modifiers, because the component
90
+ * writes no `--horizontal` class — there is nothing to read for the default, only the
91
+ * two exceptions.
92
+ */
93
+ getDirection(): Promise<WrGradientTextDirection>;
94
+ /**
95
+ * The whole gradient the component computed, as written.
96
+ *
97
+ * Unresolved on purpose: a consumer may pass theme tokens, and resolving `var()` needs
98
+ * the stylesheet. The stops come back spelled as they were written — a custom property
99
+ * holds an unparsed token stream, so `#111111` stays `#111111` rather than being
100
+ * re-serialised as `rgb()` the way it would be inside a standard `background-image`.
101
+ * Whitespace is the exception, so prefer {@link getColors} over string-equalling the
102
+ * whole gradient.
103
+ */
104
+ getGradient(): Promise<string>;
105
+ /**
106
+ * The gradient's colour stops, in order, INCLUDING the repeated first colour at the end.
107
+ *
108
+ * So the list is one longer than the `[colors]` input, and that extra entry is the
109
+ * point: it is what lets the sweep wrap without a visible snap, and nothing else in the
110
+ * DOM records it. An empty `[colors]` falls back to the three built-in stops, which
111
+ * shows up here as four entries rather than one.
112
+ *
113
+ * Throws rather than guessing when the property holds something that is not a
114
+ * `linear-gradient()` — an empty read means the host binding is gone, and a list of
115
+ * fragments parsed out of the wreckage would look like a colour set.
116
+ */
117
+ getColors(): Promise<string[]>;
118
+ /**
119
+ * How far the gradient is stretched, as the `background-size` pair.
120
+ *
121
+ * The other half of direction: the gradient has to be oversized along the axis it
122
+ * travels — `300% 100%` horizontal, `100% 300%` vertical, `300% 300%` diagonal — or
123
+ * there is nothing outside the box to slide in. Worth asserting beside
124
+ * {@link getDirection}, since the two are computed independently and only agree by
125
+ * intent.
126
+ */
127
+ getBackgroundSize(): Promise<string>;
128
+ /**
129
+ * One full sweep in seconds, from `[animationSpeed]`.
130
+ *
131
+ * Proves the input reaches CSS at all, `numAttr` coercion included — a string attribute
132
+ * arrives as a number and garbage falls back to the documented default. Throws when the
133
+ * property holds no number, which is the only way the read can fail.
134
+ */
135
+ getAnimationDurationSeconds(): Promise<number>;
136
+ /**
137
+ * Whether the decorative ring element was rendered (`showBorder`).
138
+ *
139
+ * Strictly more than the `wr-gradient-text--border` class says: the class is a host
140
+ * binding and the ring is an `@if` branch in the template, two mechanisms reading one
141
+ * input, and they can drift. This asks whether the element that paints the pill is
142
+ * actually there.
143
+ */
144
+ hasBorderRing(): Promise<boolean>;
145
+ /**
146
+ * Whether the ring is hidden from assistive tech, or `null` when there is no ring.
147
+ *
148
+ * The ring is an empty, nameless span. Paired with {@link hasBorderRing} this is the
149
+ * component's whole a11y contract: if it ever loses `aria-hidden`, a screen reader stops
150
+ * on an element with nothing to say. `null` rather than `false` for the absent case, so
151
+ * "no ring" cannot be mistaken for "an exposed ring".
152
+ */
153
+ isBorderDecorative(): Promise<boolean | null>;
154
+ /**
155
+ * Whether the sweep bounces instead of restarting (`yoyo`).
156
+ *
157
+ * Defaults to `true` here, unlike every other boolean on this component and unlike the
158
+ * same-named input on `wr-shiny-text` — worth pinning in both directions. The class is
159
+ * the only thing the `animation-direction: alternate` rule keys off.
160
+ */
161
+ isYoyo(): Promise<boolean>;
162
+ /**
163
+ * Whether the opt-in reached the class the `:hover` rule needs.
164
+ *
165
+ * Named for the class and not for the pause on purpose: the pause itself is a CSS
166
+ * selector match, which no unit test can observe. What this catches is the input never
167
+ * arriving, which is the half that can go wrong in TypeScript.
168
+ */
169
+ pausesOnHover(): Promise<boolean>;
170
+ }
171
+
172
+ export { WrGradientTextHarness };
173
+ export type { WrGradientTextHarnessFilters };