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.
- package/action-sheet/styles/_index.scss +4 -1
- package/anchor/styles/_index.scss +2 -1
- package/calendar/styles/_index.scss +11 -2
- package/cascader/styles/_index.scss +3 -1
- package/circular-text/styles/_index.scss +11 -0
- package/command-palette/styles/_index.scss +14 -1
- package/context-menu/styles/_index.scss +2 -1
- package/falling-text/styles/_index.scss +2 -1
- package/fesm2022/ngwr-action-sheet-testing.mjs +313 -0
- package/fesm2022/ngwr-action-sheet-testing.mjs.map +1 -0
- package/fesm2022/ngwr-bar-chart-testing.mjs +89 -0
- package/fesm2022/ngwr-bar-chart-testing.mjs.map +1 -0
- package/fesm2022/ngwr-blur-text-testing.mjs +203 -0
- package/fesm2022/ngwr-blur-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-blur-text.mjs +15 -1
- package/fesm2022/ngwr-blur-text.mjs.map +1 -1
- package/fesm2022/ngwr-border-glow-testing.mjs +325 -0
- package/fesm2022/ngwr-border-glow-testing.mjs.map +1 -0
- package/fesm2022/ngwr-border-glow.mjs +2 -2
- package/fesm2022/ngwr-breadcrumbs.mjs +2 -2
- package/fesm2022/ngwr-calendar-heatmap-testing.mjs +95 -0
- package/fesm2022/ngwr-calendar-heatmap-testing.mjs.map +1 -0
- package/fesm2022/ngwr-calendar-testing.mjs +368 -0
- package/fesm2022/ngwr-calendar-testing.mjs.map +1 -0
- package/fesm2022/ngwr-calendar.mjs +43 -3
- package/fesm2022/ngwr-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-card.mjs +2 -2
- package/fesm2022/ngwr-cascader.mjs +14 -2
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-checkbox.mjs +8 -0
- package/fesm2022/ngwr-checkbox.mjs.map +1 -1
- package/fesm2022/ngwr-circular-text-testing.mjs +230 -0
- package/fesm2022/ngwr-circular-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-circular-text.mjs +2 -2
- package/fesm2022/ngwr-circular-text.mjs.map +1 -1
- package/fesm2022/ngwr-color-picker-testing.mjs +432 -0
- package/fesm2022/ngwr-color-picker-testing.mjs.map +1 -0
- package/fesm2022/ngwr-color-picker.mjs +29 -3
- package/fesm2022/ngwr-color-picker.mjs.map +1 -1
- package/fesm2022/ngwr-context-menu.mjs +25 -5
- package/fesm2022/ngwr-context-menu.mjs.map +1 -1
- package/fesm2022/ngwr-date-picker-testing.mjs +10 -79
- package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -1
- package/fesm2022/ngwr-decrypt-text-testing.mjs +261 -0
- package/fesm2022/ngwr-decrypt-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-decrypt-text.mjs +6 -1
- package/fesm2022/ngwr-decrypt-text.mjs.map +1 -1
- package/fesm2022/ngwr-donut-chart-testing.mjs +93 -0
- package/fesm2022/ngwr-donut-chart-testing.mjs.map +1 -0
- package/fesm2022/ngwr-drag-drop.mjs +2 -2
- package/fesm2022/ngwr-drawer.mjs +36 -7
- package/fesm2022/ngwr-drawer.mjs.map +1 -1
- package/fesm2022/ngwr-dropdown.mjs +32 -2
- package/fesm2022/ngwr-dropdown.mjs.map +1 -1
- package/fesm2022/ngwr-event-calendar-testing.mjs +446 -0
- package/fesm2022/ngwr-event-calendar-testing.mjs.map +1 -0
- package/fesm2022/ngwr-event-calendar.mjs +43 -18
- package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-falling-text-testing.mjs +218 -0
- package/fesm2022/ngwr-falling-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-falling-text.mjs +2 -2
- package/fesm2022/ngwr-falling-text.mjs.map +1 -1
- package/fesm2022/ngwr-fuzzy-text-testing.mjs +134 -0
- package/fesm2022/ngwr-fuzzy-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-gauge-testing.mjs +86 -0
- package/fesm2022/ngwr-gauge-testing.mjs.map +1 -0
- package/fesm2022/ngwr-glitch-text-testing.mjs +181 -0
- package/fesm2022/ngwr-glitch-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-glitch-text.mjs +2 -2
- package/fesm2022/ngwr-gradient-text-testing.mjs +223 -0
- package/fesm2022/ngwr-gradient-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-gradient-text.mjs +2 -2
- package/fesm2022/ngwr-i18n-en.mjs +14 -0
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ru.mjs +14 -0
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-image-cropper-testing.mjs +156 -0
- package/fesm2022/ngwr-image-cropper-testing.mjs.map +1 -0
- package/fesm2022/ngwr-image-cropper.mjs +10 -3
- package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
- package/fesm2022/ngwr-input-number.mjs +73 -6
- package/fesm2022/ngwr-input-number.mjs.map +1 -1
- package/fesm2022/ngwr-knob-testing.mjs +220 -0
- package/fesm2022/ngwr-knob-testing.mjs.map +1 -0
- package/fesm2022/ngwr-lightbox-testing.mjs +223 -0
- package/fesm2022/ngwr-lightbox-testing.mjs.map +1 -0
- package/fesm2022/ngwr-lightbox.mjs +9 -2
- package/fesm2022/ngwr-lightbox.mjs.map +1 -1
- package/fesm2022/ngwr-line-chart-testing.mjs +119 -0
- package/fesm2022/ngwr-line-chart-testing.mjs.map +1 -0
- package/fesm2022/ngwr-list.mjs +2 -2
- package/fesm2022/ngwr-loading-bar.mjs +2 -2
- package/fesm2022/ngwr-marquee-testing.mjs +336 -0
- package/fesm2022/ngwr-marquee-testing.mjs.map +1 -0
- package/fesm2022/ngwr-marquee.mjs +2 -2
- package/fesm2022/ngwr-meter-group-testing.mjs +80 -0
- package/fesm2022/ngwr-meter-group-testing.mjs.map +1 -0
- package/fesm2022/ngwr-overlay.mjs +28 -1
- package/fesm2022/ngwr-overlay.mjs.map +1 -1
- package/fesm2022/ngwr-popover.mjs +14 -0
- package/fesm2022/ngwr-popover.mjs.map +1 -1
- package/fesm2022/ngwr-rotating-text-testing.mjs +220 -0
- package/fesm2022/ngwr-rotating-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-rotating-text.mjs +2 -2
- package/fesm2022/ngwr-rotating-text.mjs.map +1 -1
- package/fesm2022/ngwr-select.mjs +70 -11
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-shiny-text-testing.mjs +237 -0
- package/fesm2022/ngwr-shiny-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-shiny-text.mjs +2 -2
- package/fesm2022/ngwr-slider.mjs +44 -6
- package/fesm2022/ngwr-slider.mjs.map +1 -1
- package/fesm2022/ngwr-sparkline-testing.mjs +76 -0
- package/fesm2022/ngwr-sparkline-testing.mjs.map +1 -0
- package/fesm2022/ngwr-speed-dial-testing.mjs +279 -0
- package/fesm2022/ngwr-speed-dial-testing.mjs.map +1 -0
- package/fesm2022/ngwr-splash-cursor-testing.mjs +89 -0
- package/fesm2022/ngwr-splash-cursor-testing.mjs.map +1 -0
- package/fesm2022/ngwr-split-text-testing.mjs +224 -0
- package/fesm2022/ngwr-split-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-split-text.mjs +15 -1
- package/fesm2022/ngwr-split-text.mjs.map +1 -1
- package/fesm2022/ngwr-splitter-testing.mjs +245 -0
- package/fesm2022/ngwr-splitter-testing.mjs.map +1 -0
- package/fesm2022/ngwr-spotlight-card-testing.mjs +368 -0
- package/fesm2022/ngwr-spotlight-card-testing.mjs.map +1 -0
- package/fesm2022/ngwr-spotlight-card.mjs +2 -2
- package/fesm2022/ngwr-star-border-testing.mjs +172 -0
- package/fesm2022/ngwr-star-border-testing.mjs.map +1 -0
- package/fesm2022/ngwr-star-border.mjs +2 -2
- package/fesm2022/ngwr-table.mjs +13 -3
- package/fesm2022/ngwr-table.mjs.map +1 -1
- package/fesm2022/ngwr-tabs.mjs +15 -1
- package/fesm2022/ngwr-tabs.mjs.map +1 -1
- package/fesm2022/ngwr-tilt-card-testing.mjs +190 -0
- package/fesm2022/ngwr-tilt-card-testing.mjs.map +1 -0
- package/fesm2022/ngwr-tilt-card.mjs +21 -3
- package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
- package/fesm2022/ngwr-toast.mjs +36 -7
- package/fesm2022/ngwr-toast.mjs.map +1 -1
- package/fesm2022/ngwr-tour-testing.mjs +173 -0
- package/fesm2022/ngwr-tour-testing.mjs.map +1 -0
- package/fesm2022/ngwr-tour.mjs +2 -2
- package/fesm2022/ngwr-tour.mjs.map +1 -1
- package/fesm2022/ngwr-tree.mjs +10 -3
- package/fesm2022/ngwr-tree.mjs.map +1 -1
- package/fesm2022/ngwr-typewriter-testing.mjs +228 -0
- package/fesm2022/ngwr-typewriter-testing.mjs.map +1 -0
- package/fesm2022/ngwr-typewriter.mjs +2 -2
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/fesm2022/ngwr-virtual-scroll.mjs +2 -2
- package/fesm2022/ngwr-waves-testing.mjs +128 -0
- package/fesm2022/ngwr-waves-testing.mjs.map +1 -0
- package/fesm2022/ngwr-waves.mjs +2 -2
- package/fesm2022/ngwr-window-testing.mjs +361 -0
- package/fesm2022/ngwr-window-testing.mjs.map +1 -0
- package/fesm2022/ngwr-window.mjs +84 -10
- package/fesm2022/ngwr-window.mjs.map +1 -1
- package/file-upload/styles/_index.scss +7 -2
- package/i18n/en.json +16 -2
- package/i18n/ru.json +16 -2
- package/llms-full.txt +147 -0
- package/llms.txt +27 -8
- package/mcp/providers.js +29 -0
- package/mcp/tools.js +1 -29
- package/package.json +145 -1
- package/result/styles/_index.scss +3 -1
- package/segmented/styles/_index.scss +5 -1
- package/select/styles/_index.scss +3 -1
- package/skills/ngwr/SKILL.md +115 -0
- package/skills/ngwr/references/catalog.md +212 -0
- package/skills/ngwr/references/setup.md +73 -0
- package/stepper/styles/_index.scss +18 -2
- package/table/styles/_index.scss +3 -1
- package/theme/styles/_colors.scss +15 -2
- package/theme/styles/_dark.scss +24 -12
- package/tree/styles/_index.scss +4 -2
- package/types/ngwr-action-sheet-testing.d.ts +260 -0
- package/types/ngwr-bar-chart-testing.d.ts +77 -0
- package/types/ngwr-blur-text-testing.d.ts +180 -0
- package/types/ngwr-blur-text.d.ts +12 -0
- package/types/ngwr-border-glow-testing.d.ts +219 -0
- package/types/ngwr-calendar-heatmap-testing.d.ts +79 -0
- package/types/ngwr-calendar-testing.d.ts +277 -0
- package/types/ngwr-calendar.d.ts +10 -0
- package/types/ngwr-checkbox.d.ts +13 -0
- package/types/ngwr-circular-text-testing.d.ts +196 -0
- package/types/ngwr-color-picker-testing.d.ts +291 -0
- package/types/ngwr-color-picker.d.ts +13 -1
- package/types/ngwr-context-menu.d.ts +15 -1
- package/types/ngwr-date-picker-testing.d.ts +6 -66
- package/types/ngwr-decrypt-text-testing.d.ts +222 -0
- package/types/ngwr-donut-chart-testing.d.ts +79 -0
- package/types/ngwr-drawer.d.ts +12 -0
- package/types/ngwr-dropdown.d.ts +9 -0
- package/types/ngwr-event-calendar-testing.d.ts +301 -0
- package/types/ngwr-event-calendar.d.ts +9 -6
- package/types/ngwr-falling-text-testing.d.ts +186 -0
- package/types/ngwr-fuzzy-text-testing.d.ts +130 -0
- package/types/ngwr-gauge-testing.d.ts +71 -0
- package/types/ngwr-glitch-text-testing.d.ts +172 -0
- package/types/ngwr-gradient-text-testing.d.ts +173 -0
- package/types/ngwr-image-cropper-testing.d.ts +134 -0
- package/types/ngwr-image-cropper.d.ts +1 -0
- package/types/ngwr-input-number.d.ts +33 -1
- package/types/ngwr-knob-testing.d.ts +150 -0
- package/types/ngwr-lightbox-testing.d.ts +154 -0
- package/types/ngwr-lightbox.d.ts +6 -0
- package/types/ngwr-line-chart-testing.d.ts +93 -0
- package/types/ngwr-marquee-testing.d.ts +280 -0
- package/types/ngwr-meter-group-testing.d.ts +67 -0
- package/types/ngwr-overlay.d.ts +19 -1
- package/types/ngwr-rotating-text-testing.d.ts +191 -0
- package/types/ngwr-select.d.ts +32 -0
- package/types/ngwr-shiny-text-testing.d.ts +165 -0
- package/types/ngwr-slider.d.ts +15 -0
- package/types/ngwr-sparkline-testing.d.ts +69 -0
- package/types/ngwr-speed-dial-testing.d.ts +195 -0
- package/types/ngwr-splash-cursor-testing.d.ts +95 -0
- package/types/ngwr-split-text-testing.d.ts +209 -0
- package/types/ngwr-split-text.d.ts +12 -0
- package/types/ngwr-splitter-testing.d.ts +174 -0
- package/types/ngwr-spotlight-card-testing.d.ts +303 -0
- package/types/ngwr-star-border-testing.d.ts +135 -0
- package/types/ngwr-table.d.ts +10 -1
- package/types/ngwr-tilt-card-testing.d.ts +158 -0
- package/types/ngwr-tilt-card.d.ts +2 -0
- package/types/ngwr-toast.d.ts +14 -5
- package/types/ngwr-tour-testing.d.ts +143 -0
- package/types/ngwr-tree.d.ts +7 -0
- package/types/ngwr-typewriter-testing.d.ts +201 -0
- package/types/ngwr-version.d.ts +1 -1
- package/types/ngwr-waves-testing.d.ts +121 -0
- package/types/ngwr-window-testing.d.ts +263 -0
- package/types/ngwr-window.d.ts +27 -10
- package/window/styles/_index.scss +44 -16
|
@@ -0,0 +1,180 @@
|
|
|
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-blur-text>` a harness query matches. */
|
|
11
|
+
interface WrBlurTextHarnessFilters extends BaseHarnessFilters {
|
|
12
|
+
/**
|
|
13
|
+
* Match the string the component announces — the readable copy, not the pieces.
|
|
14
|
+
* A string is an exact match, a RegExp is tested.
|
|
15
|
+
*
|
|
16
|
+
* Matching on the accessible copy rather than on the host's text is deliberate:
|
|
17
|
+
* the host also holds a span per character, so its text reads back as the string
|
|
18
|
+
* twice over, and a filter written against that would depend on the split.
|
|
19
|
+
*/
|
|
20
|
+
readonly text?: string | RegExp;
|
|
21
|
+
/**
|
|
22
|
+
* Match on how many animated pieces the split produced — one per word, or one per
|
|
23
|
+
* character. The blunt way to tell two otherwise identical reveals apart, and the
|
|
24
|
+
* only number about the animation that is present in the DOM at all.
|
|
25
|
+
*/
|
|
26
|
+
readonly pieceCount?: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @license
|
|
31
|
+
*
|
|
32
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
33
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Test harness for `<wr-blur-text>`.
|
|
38
|
+
*
|
|
39
|
+
* **Most of what this component does cannot be read from a test, and the methods that
|
|
40
|
+
* are missing are missing on purpose.** The reveal is a Web Animations tween per piece
|
|
41
|
+
* — blur, vertical offset and opacity, staggered — started by an `IntersectionObserver`.
|
|
42
|
+
* A unit test has no layout, no compositor and no WAAPI, so there is no
|
|
43
|
+
* `getOpacity()`, no `getBlurRadius()` and no `getOffset()`: each would report the
|
|
44
|
+
* staged from-state forever in jsdom, and in a real browser it would report the inline
|
|
45
|
+
* value while the compositor paints a different one. There is no `isAnimating()` and no
|
|
46
|
+
* `whenAnimationComplete()` either — nothing in the DOM says a tween is running, and
|
|
47
|
+
* completion is the `animationComplete` OUTPUT, which the host binds. Nor is there an
|
|
48
|
+
* `enterViewport()` / `scrollIntoView()`: the trigger is an observer, which a
|
|
49
|
+
* `TestElement` cannot reach, and a method that pretended to scroll would do nothing in
|
|
50
|
+
* jsdom and something untimed in a browser. The inputs that shape the tween —
|
|
51
|
+
* `direction`, `delay`, `stepDuration`, `easing` — never reach the DOM at all; they live
|
|
52
|
+
* in a keyframe array and an effect timing, and neither is a document.
|
|
53
|
+
*
|
|
54
|
+
* **What is real is the split and the accessible layer, and they are two questions.**
|
|
55
|
+
* The string is carried once in a visually-hidden span, and every animated piece is
|
|
56
|
+
* `aria-hidden` so a screen reader does not spell the text out letter by letter — so
|
|
57
|
+
* {@link getAccessibleText} is what is heard and {@link getPieces} is what is drawn, and
|
|
58
|
+
* a spec that only asserted the second would pass on a component that announces
|
|
59
|
+
* `W. e. l. c. o. m. e.` {@link getRenderedText} closes the loop: the split has to be
|
|
60
|
+
* lossless, and comparing it against the accessible copy is what catches a dropped space
|
|
61
|
+
* or a halved surrogate pair. (Whether the hidden copy is really off-screen is CSS —
|
|
62
|
+
* `clip-path` and a 1px box — and a test running no stylesheets cannot tell a correctly
|
|
63
|
+
* hidden span from one printing the string twice, so nothing here claims to.)
|
|
64
|
+
*
|
|
65
|
+
* **{@link hasStagedMotion} is the one thing about the tween worth pinning**, and it
|
|
66
|
+
* reports that the pieces were taken over rather than that anything is moving. Under
|
|
67
|
+
* reduced motion the component returns before touching them, which is the promise: a
|
|
68
|
+
* reader who asked for less motion must never be left with text staged at `opacity: 0`
|
|
69
|
+
* by an animation that then never runs.
|
|
70
|
+
*
|
|
71
|
+
* Driving the reveal is the spec's job, since jsdom supplies neither half of it:
|
|
72
|
+
*
|
|
73
|
+
* ```ts
|
|
74
|
+
* // Before TestBed.createComponent — keep the callbacks so the spec can fire them.
|
|
75
|
+
* vi.stubGlobal('IntersectionObserver', StubObserver);
|
|
76
|
+
* // Otherwise `el.animate(...)` throws mid-stagger and leaves the DOM half-staged.
|
|
77
|
+
* Reflect.set(Element.prototype, 'animate', () => ({ cancel: () => undefined, onfinish: null }));
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* const text = await loader.getHarness(WrBlurTextHarness.with({ text: 'Welcome to ngwr' }));
|
|
83
|
+
*
|
|
84
|
+
* expect(await text.getPieces()).toEqual(['Welcome', 'to', 'ngwr']);
|
|
85
|
+
* expect(await text.getRenderedText()).toBe(await text.getAccessibleText());
|
|
86
|
+
* expect(await text.isTextHidden()).toBe(true);
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* @see https://ngwr.dev/guides/testing
|
|
90
|
+
*/
|
|
91
|
+
declare class WrBlurTextHarness extends ComponentHarness {
|
|
92
|
+
static hostSelector: string;
|
|
93
|
+
/** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
|
|
94
|
+
static with(options?: WrBlurTextHarnessFilters): HarnessPredicate<WrBlurTextHarness>;
|
|
95
|
+
private readonly pieces;
|
|
96
|
+
private readonly spaces;
|
|
97
|
+
/**
|
|
98
|
+
* The whole string, as the one readable copy holds it.
|
|
99
|
+
*
|
|
100
|
+
* The only thing a screen reader gets, since every drawn piece is out of the tree —
|
|
101
|
+
* lose this span and the component becomes a nameless pile of hidden spans with no
|
|
102
|
+
* other symptom anywhere in the DOM.
|
|
103
|
+
*
|
|
104
|
+
* Untrimmed, deliberately. Leading and trailing whitespace is content the split has to
|
|
105
|
+
* carry through, and {@link getRenderedText} is meant to compare equal to this; a
|
|
106
|
+
* trimmed read on one side of that comparison would quietly forgive the case it exists
|
|
107
|
+
* to catch.
|
|
108
|
+
*/
|
|
109
|
+
getAccessibleText(): Promise<string>;
|
|
110
|
+
/**
|
|
111
|
+
* The animated pieces, in document order — one per word or one per character.
|
|
112
|
+
*
|
|
113
|
+
* This is the split the stagger runs over: `['Hi', 'there']` for `animateBy="words"`
|
|
114
|
+
* against `['H', 'i', 't', 'h', 'e', 'r', 'e']` for `"chars"`, and `['a', '🚀']` for a
|
|
115
|
+
* surrogate pair the code-point split kept whole rather than halved into two broken
|
|
116
|
+
* glyphs. Whitespace is not here — it is rendered separately and never staggered, so
|
|
117
|
+
* see {@link getSpaceCount}.
|
|
118
|
+
*/
|
|
119
|
+
getPieces(): Promise<string[]>;
|
|
120
|
+
/**
|
|
121
|
+
* How many pieces the stagger runs over.
|
|
122
|
+
*
|
|
123
|
+
* `delay` × this is the whole length of the effect, and it is the only number about
|
|
124
|
+
* the animation that exists in the document.
|
|
125
|
+
*/
|
|
126
|
+
getPieceCount(): Promise<number>;
|
|
127
|
+
/**
|
|
128
|
+
* How many whitespace runs sit between the pieces.
|
|
129
|
+
*
|
|
130
|
+
* Worth a method of its own because whitespace is deliberately NOT a staggered piece:
|
|
131
|
+
* a regression that reclassified spaces as pieces would leave {@link getRenderedText}
|
|
132
|
+
* identical, change the stagger count and the rhythm of the reveal, and show up
|
|
133
|
+
* nowhere else.
|
|
134
|
+
*/
|
|
135
|
+
getSpaceCount(): Promise<number>;
|
|
136
|
+
/**
|
|
137
|
+
* Everything the component drew, pieces and spaces together, in document order.
|
|
138
|
+
*
|
|
139
|
+
* The assertion this exists for is `getRenderedText() === getAccessibleText()`: the
|
|
140
|
+
* split must be lossless. A swallowed space, a re-split that dropped a character, or a
|
|
141
|
+
* surrogate pair cut in half all leave the accessible copy untouched and are invisible
|
|
142
|
+
* from anywhere else.
|
|
143
|
+
*/
|
|
144
|
+
getRenderedText(): Promise<string>;
|
|
145
|
+
/**
|
|
146
|
+
* Whether every drawn piece is out of the accessibility tree.
|
|
147
|
+
*
|
|
148
|
+
* The defect this component exists to avoid is a screen reader reading
|
|
149
|
+
* `W. e. l. c. o. m. e.`, and one piece missing `aria-hidden` is enough to bring it
|
|
150
|
+
* back — so this is all-or-nothing, and across both element kinds: a stray readable
|
|
151
|
+
* space is heard as a pause in the middle of a word.
|
|
152
|
+
*
|
|
153
|
+
* Throws when the split produced nothing at all. An empty run of elements satisfies
|
|
154
|
+
* "every one of them is hidden" without anything being hidden, which is the answer a
|
|
155
|
+
* component that stopped rendering its pieces would also give.
|
|
156
|
+
*/
|
|
157
|
+
isTextHidden(): Promise<boolean>;
|
|
158
|
+
/**
|
|
159
|
+
* Whether the reveal has taken the pieces over — NOT whether anything is animating.
|
|
160
|
+
*
|
|
161
|
+
* Read off the inline `style` attribute the component writes itself, so it stays
|
|
162
|
+
* `true` after the reveal finishes: the tween commits its end state back to the same
|
|
163
|
+
* inline properties on `onfinish`. Anyone reaching for `isAnimating()` wants a frame,
|
|
164
|
+
* and there are no frames here.
|
|
165
|
+
*
|
|
166
|
+
* `false` is the answer worth asserting. It means no piece was written to at all,
|
|
167
|
+
* which is both the pre-trigger state and the reduced-motion promise — the component
|
|
168
|
+
* returns before staging anything, so a reader who asked for less motion cannot be
|
|
169
|
+
* left staring at text parked at `opacity: 0` by an animation that never runs.
|
|
170
|
+
*
|
|
171
|
+
* ANY piece counts, not all of them, and that is the conservative reading rather than
|
|
172
|
+
* a loose one: a stagger that stages the first piece and then throws leaves exactly one
|
|
173
|
+
* piece invisible, which is a real failure and one jsdom reproduces whenever
|
|
174
|
+
* `Element.prototype.animate` is missing.
|
|
175
|
+
*/
|
|
176
|
+
hasStagedMotion(): Promise<boolean>;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export { WrBlurTextHarness };
|
|
180
|
+
export type { WrBlurTextHarnessFilters };
|
|
@@ -52,6 +52,18 @@ declare class WrBlurText {
|
|
|
52
52
|
private readonly isBrowser;
|
|
53
53
|
private readonly platform;
|
|
54
54
|
private hasAnimated;
|
|
55
|
+
/**
|
|
56
|
+
* The ONE observer, replaced rather than stacked.
|
|
57
|
+
*
|
|
58
|
+
* `startObserver()` used to `new IntersectionObserver(…)` and register its own
|
|
59
|
+
* `destroyRef.onDestroy` every time, and the effect below calls it on every
|
|
60
|
+
* `text` change after setting `hasAnimated = false` — so the guard at the top
|
|
61
|
+
* of `startObserver` never blocked that path. An off-screen element (the only
|
|
62
|
+
* case where the observer does not immediately disconnect itself) therefore
|
|
63
|
+
* leaked one live observer AND one destroy callback per change, all of them
|
|
64
|
+
* watching the same host and all of them able to fire `animate()`.
|
|
65
|
+
*/
|
|
66
|
+
private observer;
|
|
55
67
|
constructor();
|
|
56
68
|
private startObserver;
|
|
57
69
|
private animate;
|
|
@@ -0,0 +1,219 @@
|
|
|
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-border-glow>` a harness query matches. */
|
|
11
|
+
interface WrBorderGlowHarnessFilters extends BaseHarnessFilters {
|
|
12
|
+
/**
|
|
13
|
+
* Match the card's projected text — a string is an exact match, a RegExp is tested.
|
|
14
|
+
* The component names itself nothing, so the content it wraps is the only readable
|
|
15
|
+
* way to tell two cards on a page apart.
|
|
16
|
+
*/
|
|
17
|
+
readonly text?: string | RegExp;
|
|
18
|
+
/**
|
|
19
|
+
* Match only cards that are mid mount-sweep (`true`) or only cards that are not
|
|
20
|
+
* (`false`) — see `WrBorderGlowHarness.isSweeping`, where the four-second window
|
|
21
|
+
* this is true for is explained.
|
|
22
|
+
*/
|
|
23
|
+
readonly sweeping?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @license
|
|
28
|
+
*
|
|
29
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
30
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Test harness for `<wr-border-glow>` — a card whose border lights up under the cursor.
|
|
35
|
+
*
|
|
36
|
+
* **Nearly all of this component is a bag of custom properties written onto the host,
|
|
37
|
+
* and that is what the harness reads.** The paint itself — the conic mask, the stacked
|
|
38
|
+
* `box-shadow` halo, the soft-light bloom — lives in the stylesheet, so a unit test can
|
|
39
|
+
* never see it. What it CAN see is the arithmetic that feeds it, and that is where the
|
|
40
|
+
* breakages are: the seven-step alpha ramp {@link getGlowAlphaRamp} derives from
|
|
41
|
+
* `glowIntensity`, the `[0,1,2,0,1,2,1]` palette mapping in {@link getGradientColors}
|
|
42
|
+
* with its clamp for short palettes, and the pointer maths behind
|
|
43
|
+
* {@link getPointerAngle} / {@link getEdgeProximity}.
|
|
44
|
+
*
|
|
45
|
+
* **Every custom-property getter reads the inline declaration** — see
|
|
46
|
+
* {@link parseInlineDeclarations} for why a computed read would be a different, and
|
|
47
|
+
* wrong, question.
|
|
48
|
+
*
|
|
49
|
+
* **A colour getter answering `null` means the component has never written that
|
|
50
|
+
* variable**, which is the contract when the input is unset: the stylesheet's per-theme
|
|
51
|
+
* default takes over. Note that it does not un-write them either — setting `[glowColor]`
|
|
52
|
+
* and then putting it back to `null` leaves the last value on the host — so `null` is
|
|
53
|
+
* "never set", not "not set now".
|
|
54
|
+
*
|
|
55
|
+
* There is deliberately no `getGlowOpacity()`, `isGlowVisible()` or `isHovered()`: the
|
|
56
|
+
* visible strength is a `calc()` in the stylesheet gated behind `:not(:hover)`, and
|
|
57
|
+
* jsdom loads no stylesheet and matches no `:hover`, so any number would be invented.
|
|
58
|
+
* There is no measured halo extent either — `.wr-border-glow__edge` is 0×0 in a test,
|
|
59
|
+
* and {@link getGlowRadius} reads what the component asked for instead. And there is no
|
|
60
|
+
* `getSweepProgress()` / `waitForSweep()`: the mount sweep is a four-second chain of
|
|
61
|
+
* `requestAnimationFrame` tweens, so awaiting it either hangs the spec or samples one
|
|
62
|
+
* frame and reports a value that was never settled. {@link isSweeping} answers the one
|
|
63
|
+
* durable fact — that the sweep started.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* const card = await loader.getHarness(WrBorderGlowHarness.with({ text: /Hover me/ }));
|
|
68
|
+
*
|
|
69
|
+
* expect(await card.getBorderRadius()).toBe(28);
|
|
70
|
+
* expect(await card.getPointerAngle()).toBeNull(); // nothing has pointed at it yet
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* @see https://ngwr.dev/guides/testing
|
|
74
|
+
*/
|
|
75
|
+
declare class WrBorderGlowHarness extends ComponentHarness {
|
|
76
|
+
static hostSelector: string;
|
|
77
|
+
/** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
|
|
78
|
+
static with(options?: WrBorderGlowHarnessFilters): HarnessPredicate<WrBorderGlowHarness>;
|
|
79
|
+
private readonly edge;
|
|
80
|
+
/** The corner radius the stylesheet is told to round to, in pixels. */
|
|
81
|
+
getBorderRadius(): Promise<number>;
|
|
82
|
+
/** How far past the card edge the halo is told to reach, in pixels. */
|
|
83
|
+
getGlowRadius(): Promise<number>;
|
|
84
|
+
/**
|
|
85
|
+
* The width of the lit cone, as a share of the perimeter.
|
|
86
|
+
*
|
|
87
|
+
* Unitless by contract — the stylesheet multiplies it — so a `px` creeping in here is
|
|
88
|
+
* a real regression that leaves the mask with a length where it wants a number.
|
|
89
|
+
*/
|
|
90
|
+
getConeSpread(): Promise<number>;
|
|
91
|
+
/** How sharply the halo fades as the cursor leaves an edge; lower is a wider falloff. */
|
|
92
|
+
getEdgeSensitivity(): Promise<number>;
|
|
93
|
+
/** Strength of the interior soft-light bloom, again unitless. */
|
|
94
|
+
getFillOpacity(): Promise<number>;
|
|
95
|
+
/**
|
|
96
|
+
* The card fill the author asked for, or `null` when they left it to the theme.
|
|
97
|
+
*
|
|
98
|
+
* The distinction is the whole point: an unset `[backgroundColor]` means the surface
|
|
99
|
+
* token decides, light or dark, and a card that starts declaring its own fill has
|
|
100
|
+
* stopped following the theme.
|
|
101
|
+
*/
|
|
102
|
+
getBackgroundColor(): Promise<string | null>;
|
|
103
|
+
/**
|
|
104
|
+
* The halo colour at full strength, or `null` when the theme decides.
|
|
105
|
+
*
|
|
106
|
+
* Comes back as the `hsl(H deg S% L% / A%)` the component assembled from the bare
|
|
107
|
+
* `'H S L'` input, so this also pins that assembly. Be aware the parse is forgiving to
|
|
108
|
+
* a fault: anything that is not three bare numbers — a hex colour, `rgb(…)`, even
|
|
109
|
+
* `hsl(40deg 80% 80%)` with its units — silently becomes the default amber, so a
|
|
110
|
+
* plausible-looking value here does not mean the input was understood.
|
|
111
|
+
*/
|
|
112
|
+
getGlowColor(): Promise<string | null>;
|
|
113
|
+
/**
|
|
114
|
+
* The seven halo alphas in percent, brightest first, or `null` when no glow colour
|
|
115
|
+
* was ever set.
|
|
116
|
+
*
|
|
117
|
+
* This is the whole of `[glowIntensity]`: the steps are `[100, 60, 50, 40, 30, 20,
|
|
118
|
+
* 10]` multiplied by the intensity and clamped at 100, so `0.5` gives
|
|
119
|
+
* `[50, 30, 25, 20, 15, 10, 5]` and anything above 1 saturates from the top down. The
|
|
120
|
+
* clamp is one-sided — a negative intensity produces negative percentages, which a
|
|
121
|
+
* browser drops as invalid declarations and the halo vanishes — so the numbers are
|
|
122
|
+
* returned as written rather than corrected, which is how a spec can see it.
|
|
123
|
+
*/
|
|
124
|
+
getGlowAlphaRamp(): Promise<number[] | null>;
|
|
125
|
+
/**
|
|
126
|
+
* The seven mesh-gradient colours, in slot order, or `null` when no palette was set.
|
|
127
|
+
*
|
|
128
|
+
* The slots do not map one-to-one onto the palette: they take colours
|
|
129
|
+
* `[0, 1, 2, 0, 1, 2, 1]`, each index clamped to the last entry the palette actually
|
|
130
|
+
* has. So a two-colour palette repeats the second colour rather than reading past the
|
|
131
|
+
* end — which is the case worth a spec, since `undefined` in a `radial-gradient()`
|
|
132
|
+
* kills the whole declaration silently.
|
|
133
|
+
*/
|
|
134
|
+
getGradientColors(): Promise<string[] | null>;
|
|
135
|
+
/**
|
|
136
|
+
* The flat colour behind the mesh, or `null` when no palette was set.
|
|
137
|
+
*
|
|
138
|
+
* Always the palette's FIRST entry. Worth its own method because the base slice is the
|
|
139
|
+
* one that shows where the gradients are transparent, and it drifting to the last
|
|
140
|
+
* colour changes the card's whole cast without touching a gradient.
|
|
141
|
+
*/
|
|
142
|
+
getBaseGradientColor(): Promise<string | null>;
|
|
143
|
+
/**
|
|
144
|
+
* Where the cursor last sat, in degrees: `0` is straight up and the angle grows
|
|
145
|
+
* clockwise. `null` until something has pointed at the card.
|
|
146
|
+
*
|
|
147
|
+
* `null` is a state of its own rather than a stand-in for zero — the stylesheet's own
|
|
148
|
+
* default applies until the first pointer arrives, and dead centre legitimately
|
|
149
|
+
* reports `0`, so a harness that folded the two together could not tell an untouched
|
|
150
|
+
* card from one being pointed at from the middle.
|
|
151
|
+
*/
|
|
152
|
+
getPointerAngle(): Promise<number | null>;
|
|
153
|
+
/**
|
|
154
|
+
* How close the cursor is to the perimeter: `0` at dead centre, `100` at the edge.
|
|
155
|
+
* `null` until something has pointed at the card.
|
|
156
|
+
*
|
|
157
|
+
* On a diagonal the NEARER axis wins rather than the two averaging, so a cursor level
|
|
158
|
+
* with the bottom edge reads 100 wherever it is along it.
|
|
159
|
+
*/
|
|
160
|
+
getEdgeProximity(): Promise<number | null>;
|
|
161
|
+
/**
|
|
162
|
+
* Point at the card, in client coordinates.
|
|
163
|
+
*
|
|
164
|
+
* **Refuses on a card with no box, which in a unit test is every card.** The component
|
|
165
|
+
* measures the pointer against its own centre, and with a 0×0 rect that maths
|
|
166
|
+
* degenerates: the centre is the top-left corner, and `1 / Math.min(0, 0)` pins the
|
|
167
|
+
* proximity at 100 for every position on the page. Both would come back as confident
|
|
168
|
+
* numbers describing nothing. Give the host a box first, exactly as the component's own
|
|
169
|
+
* spec does:
|
|
170
|
+
*
|
|
171
|
+
* ```ts
|
|
172
|
+
* const card = fixture.nativeElement.querySelector('wr-border-glow');
|
|
173
|
+
* card.getBoundingClientRect = () => ({ left: 0, top: 0, width: 200, height: 100 }) as DOMRect;
|
|
174
|
+
* ```
|
|
175
|
+
*
|
|
176
|
+
* A `pointermove` is dispatched on the host itself, so it needs no hit test and cannot
|
|
177
|
+
* miss — the coordinates only ever reach the component's own arithmetic.
|
|
178
|
+
*/
|
|
179
|
+
movePointerTo(clientX: number, clientY: number): Promise<void>;
|
|
180
|
+
/**
|
|
181
|
+
* Whether the one-shot mount sweep is running.
|
|
182
|
+
*
|
|
183
|
+
* The class is added synchronously when the sweep starts and removed when it ends
|
|
184
|
+
* about four seconds later, or when the component is torn down — so a spec asserts
|
|
185
|
+
* that it STARTED, and leaves the angle alone while it does. This is also the
|
|
186
|
+
* reduced-motion assertion: `[animated]="true"` for someone who asked for less motion
|
|
187
|
+
* must leave this `false`, and no angle written at all.
|
|
188
|
+
*/
|
|
189
|
+
isSweeping(): Promise<boolean>;
|
|
190
|
+
/** Whether the halo layer is in the markup — the element the whole outer glow paints on. */
|
|
191
|
+
hasHaloLayer(): Promise<boolean>;
|
|
192
|
+
/**
|
|
193
|
+
* Whether the decoration stays out of the accessibility tree.
|
|
194
|
+
*
|
|
195
|
+
* The halo layer is the component's only decorative NODE — every other layer is a
|
|
196
|
+
* pseudo-element and so was never in the tree to begin with. It carries no text and no
|
|
197
|
+
* name, so losing its `aria-hidden` puts an anonymous element between the reader and
|
|
198
|
+
* the card's content.
|
|
199
|
+
*/
|
|
200
|
+
isDecorationHiddenFromAssistiveTech(): Promise<boolean>;
|
|
201
|
+
/**
|
|
202
|
+
* The projected content's text, trimmed.
|
|
203
|
+
*
|
|
204
|
+
* Read from `.wr-border-glow__inner` rather than the host, which is the assertion:
|
|
205
|
+
* content that lands as a bare host child instead of inside the wrapper renders
|
|
206
|
+
* underneath the interior bloom, and reading the host would report the same string
|
|
207
|
+
* either way.
|
|
208
|
+
*/
|
|
209
|
+
getContentText(): Promise<string>;
|
|
210
|
+
/** The host's inline declarations — the component's whole written output. */
|
|
211
|
+
private declarations;
|
|
212
|
+
/** One inline custom property, or `null` when the component has not written it. */
|
|
213
|
+
private readVar;
|
|
214
|
+
/** One inline custom property that is always written, as a number. */
|
|
215
|
+
private readNumberVar;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export { WrBorderGlowHarness };
|
|
219
|
+
export type { WrBorderGlowHarnessFilters };
|
|
@@ -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-calendar-heatmap>` a harness query matches. */
|
|
11
|
+
interface WrCalendarHeatmapHarnessFilters extends BaseHarnessFilters {
|
|
12
|
+
/** Match the grid's accessible name. */
|
|
13
|
+
readonly ariaLabel?: string | RegExp;
|
|
14
|
+
}
|
|
15
|
+
/** One day square, as its tooltip describes it. */
|
|
16
|
+
interface WrCalendarHeatmapCell {
|
|
17
|
+
/** The ISO date the square stands for. */
|
|
18
|
+
readonly iso: string;
|
|
19
|
+
/** The value as printed in the tooltip. */
|
|
20
|
+
readonly value: string;
|
|
21
|
+
/** Which week column it sits in, one-based, as the grid places it. */
|
|
22
|
+
readonly week: number;
|
|
23
|
+
/** Which weekday row it sits in, one-based. */
|
|
24
|
+
readonly day: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @license
|
|
29
|
+
*
|
|
30
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
31
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Test harness for `<wr-calendar-heatmap>`.
|
|
36
|
+
*
|
|
37
|
+
* **Every square is `aria-hidden`, and that is the design.** The grid is one
|
|
38
|
+
* `role="img"` with a name; a year of individually announced days would be unusable
|
|
39
|
+
* with a screen reader. What each square carries instead is a `title` — its ISO date
|
|
40
|
+
* and value — which is the only text a spec can read, and what
|
|
41
|
+
* {@link getCells} parses.
|
|
42
|
+
*
|
|
43
|
+
* **Four of the seven weekday labels are blank on purpose**: seven do not fit beside
|
|
44
|
+
* a grid this dense. {@link getWeekdayLabels} returns them as they are, empties
|
|
45
|
+
* included, rather than filtering — a spec asserting seven entries with four blanks
|
|
46
|
+
* is pinning the real layout.
|
|
47
|
+
*
|
|
48
|
+
* @see https://ngwr.dev/guides/testing
|
|
49
|
+
*/
|
|
50
|
+
declare class WrCalendarHeatmapHarness extends ComponentHarness {
|
|
51
|
+
static hostSelector: string;
|
|
52
|
+
/** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
|
|
53
|
+
static with(options?: WrCalendarHeatmapHarnessFilters): HarnessPredicate<WrCalendarHeatmapHarness>;
|
|
54
|
+
private readonly grid;
|
|
55
|
+
/** The role the grid announces — `img`, for the whole picture. */
|
|
56
|
+
getRole(): Promise<string | null>;
|
|
57
|
+
/** The grid's accessible name — the only name a reader gets. */
|
|
58
|
+
getAccessibleName(): Promise<string | null>;
|
|
59
|
+
/** How many day squares were drawn. */
|
|
60
|
+
getCellCount(): Promise<number>;
|
|
61
|
+
/**
|
|
62
|
+
* Every square, from its tooltip and its grid placement.
|
|
63
|
+
*
|
|
64
|
+
* The `title` is `"<iso>: <value>"`, which is the component's own format and the
|
|
65
|
+
* only text on a square — everything else about it is colour.
|
|
66
|
+
*/
|
|
67
|
+
getCells(): Promise<WrCalendarHeatmapCell[]>;
|
|
68
|
+
/** The value a given ISO date's square reports, or `null` when that day is not drawn. */
|
|
69
|
+
getValueFor(iso: string): Promise<string | null>;
|
|
70
|
+
/** Whether the weekday and month labels are drawn (`showLabels`). */
|
|
71
|
+
hasLabels(): Promise<boolean>;
|
|
72
|
+
/** The weekday labels as drawn — seven entries, four of them deliberately empty. */
|
|
73
|
+
getWeekdayLabels(): Promise<string[]>;
|
|
74
|
+
/** The month labels along the top, in order. */
|
|
75
|
+
getMonthLabels(): Promise<string[]>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export { WrCalendarHeatmapHarness };
|
|
79
|
+
export type { WrCalendarHeatmapCell, WrCalendarHeatmapHarnessFilters };
|