@blotch/dolan 22.2.2 → 22.2.4
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/dist/commands/add.d.ts +6 -2
- package/dist/commands/add.js +41 -11
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/add.test.js +162 -9
- package/dist/commands/add.test.js.map +1 -1
- package/dist/commands/diff.d.ts +2 -1
- package/dist/commands/diff.js +38 -25
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/diff.test.js +72 -11
- package/dist/commands/diff.test.js.map +1 -1
- package/dist/commands/doctor.js +228 -34
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/doctor.test.js +367 -10
- package/dist/commands/doctor.test.js.map +1 -1
- package/dist/commands/eject.js +7 -0
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/eject.test.js +39 -0
- package/dist/commands/eject.test.js.map +1 -1
- package/dist/commands/info.js +3 -2
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/init.d.ts +37 -1
- package/dist/commands/init.js +169 -40
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/init.test.js +392 -27
- package/dist/commands/init.test.js.map +1 -1
- package/dist/commands/install-packages.d.ts +6 -0
- package/dist/commands/install-packages.js +20 -0
- package/dist/commands/install-packages.js.map +1 -0
- package/dist/commands/install-packages.test.d.ts +1 -0
- package/dist/commands/install-packages.test.js +55 -0
- package/dist/commands/install-packages.test.js.map +1 -0
- package/dist/commands/list.js +21 -14
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/list.test.js +62 -5
- package/dist/commands/list.test.js.map +1 -1
- package/dist/commands/outdated.js +11 -10
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/outdated.test.js +20 -5
- package/dist/commands/outdated.test.js.map +1 -1
- package/dist/commands/remove.d.ts +4 -0
- package/dist/commands/remove.js +17 -4
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/remove.test.js +53 -2
- package/dist/commands/remove.test.js.map +1 -1
- package/dist/commands/theme.js +1 -1
- package/dist/commands/theme.js.map +1 -1
- package/dist/commands/update.d.ts +11 -0
- package/dist/commands/update.js +174 -58
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/update.test.js +587 -33
- package/dist/commands/update.test.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/lockfile.d.ts +7 -0
- package/dist/lockfile.js +36 -0
- package/dist/lockfile.js.map +1 -1
- package/dist/lockfile.test.d.ts +1 -0
- package/dist/lockfile.test.js +25 -0
- package/dist/lockfile.test.js.map +1 -0
- package/dist/registry.d.ts +14 -0
- package/dist/registry.js +78 -24
- package/dist/registry.js.map +1 -1
- package/dist/registry.test.js +119 -38
- package/dist/registry.test.js.map +1 -1
- package/dist/test-utils.d.ts +5 -0
- package/dist/test-utils.js +6 -1
- package/dist/test-utils.js.map +1 -1
- package/dist/testing/fire-lynx-event.d.ts +14 -0
- package/dist/testing/fire-lynx-event.js +19 -0
- package/dist/testing/fire-lynx-event.js.map +1 -0
- package/dist/testing/fire-lynx-event.test.d.ts +1 -0
- package/dist/testing/fire-lynx-event.test.js +44 -0
- package/dist/testing/fire-lynx-event.test.js.map +1 -0
- package/dist/testing/lynx-main-thread.d.ts +22 -0
- package/dist/testing/lynx-main-thread.js +11 -0
- package/dist/testing/lynx-main-thread.js.map +1 -0
- package/dist/testing/lynx-main-thread.test.d.ts +1 -0
- package/dist/testing/lynx-main-thread.test.js +24 -0
- package/dist/testing/lynx-main-thread.test.js.map +1 -0
- package/dist/testing/set-input-signal.d.ts +14 -0
- package/dist/testing/set-input-signal.js +21 -0
- package/dist/testing/set-input-signal.js.map +1 -0
- package/dist/testing/set-input-signal.test.d.ts +1 -0
- package/dist/testing/set-input-signal.test.js +20 -0
- package/dist/testing/set-input-signal.test.js.map +1 -0
- package/dist/ui/components/accordion/accordion.test.ts +158 -144
- package/dist/ui/components/accordion/accordion.ts +19 -14
- package/dist/ui/components/action-sheet/action-sheet.test.ts +283 -151
- package/dist/ui/components/action-sheet/action-sheet.ts +77 -43
- package/dist/ui/components/alert/alert.test.ts +67 -19
- package/dist/ui/components/alert/alert.ts +14 -16
- package/dist/ui/components/alert-dialog/alert-dialog.test.ts +208 -94
- package/dist/ui/components/alert-dialog/alert-dialog.ts +75 -38
- package/dist/ui/components/area-chart/area-chart.test.ts +134 -119
- package/dist/ui/components/area-chart/area-chart.ts +100 -315
- package/dist/ui/components/area-chart/index.ts +2 -3
- package/dist/ui/components/avatar/avatar.test.ts +89 -45
- package/dist/ui/components/badge/badge.test.ts +57 -23
- package/dist/ui/components/badge/badge.ts +12 -14
- package/dist/ui/components/bar-chart/bar-chart.test.ts +172 -45
- package/dist/ui/components/bar-chart/bar-chart.ts +140 -294
- package/dist/ui/components/bar-chart/index.ts +3 -3
- package/dist/ui/components/bottom-sheet/bottom-sheet.test.ts +386 -128
- package/dist/ui/components/bottom-sheet/bottom-sheet.ts +170 -53
- package/dist/ui/components/button/button.test.ts +611 -2
- package/dist/ui/components/button/button.ts +434 -49
- package/dist/ui/components/button/index.ts +2 -0
- package/dist/ui/components/button-group/button-group.test.ts +484 -2
- package/dist/ui/components/button-group/button-group.ts +380 -68
- package/dist/ui/components/button-group/index.ts +3 -0
- package/dist/ui/components/candlestick-chart/candlestick-chart.test.ts +183 -58
- package/dist/ui/components/candlestick-chart/candlestick-chart.ts +150 -323
- package/dist/ui/components/candlestick-chart/index.ts +3 -4
- package/dist/ui/components/card/card.test.ts +82 -62
- package/dist/ui/components/chart/chart-focus.test.ts +132 -0
- package/dist/ui/components/chart/chart-focus.ts +115 -0
- package/dist/ui/components/chart/chart-presets.test.ts +335 -0
- package/dist/ui/components/chart/chart-presets.ts +278 -0
- package/dist/ui/components/chart/chart-scene.test.ts +589 -0
- package/dist/ui/components/chart/chart-scene.ts +483 -0
- package/dist/ui/components/chart/chart-theme.test.ts +85 -0
- package/dist/ui/components/chart/chart-theme.ts +210 -0
- package/dist/ui/components/chart/chart-zoom.test.ts +159 -0
- package/dist/ui/components/chart/chart-zoom.ts +162 -0
- package/dist/ui/components/chart/chart.test.ts +1017 -0
- package/dist/ui/components/chart/chart.ts +934 -0
- package/dist/ui/components/chart/index.ts +24 -0
- package/dist/ui/components/checkbox/checkbox.test.ts +124 -42
- package/dist/ui/components/checkbox/checkbox.ts +23 -23
- package/dist/ui/components/collapsible/collapsible.test.ts +158 -81
- package/dist/ui/components/collapsible/collapsible.ts +19 -14
- package/dist/ui/components/context-menu/context-menu.test.ts +224 -0
- package/dist/ui/components/context-menu/context-menu.ts +110 -0
- package/dist/ui/components/context-menu/index.ts +1 -0
- package/dist/ui/components/dialog/dialog.test.ts +213 -108
- package/dist/ui/components/dialog/dialog.ts +72 -35
- package/dist/ui/components/dock/dock-scroll.test.ts +130 -0
- package/dist/ui/components/dock/dock-scroll.ts +133 -0
- package/dist/ui/components/dock/dock.test.ts +749 -0
- package/dist/ui/components/dock/dock.ts +960 -0
- package/dist/ui/components/dock/index.ts +2 -0
- package/dist/ui/components/empty-state/empty-state.test.ts +28 -39
- package/dist/ui/components/glass/concentric-radius.test.ts +13 -0
- package/dist/ui/components/glass/concentric-radius.ts +17 -0
- package/dist/ui/components/glass/glass-design.test.ts +78 -0
- package/dist/ui/components/glass/glass-design.ts +119 -0
- package/dist/ui/components/glass/glass.test.ts +338 -0
- package/dist/ui/components/glass/glass.ts +360 -0
- package/dist/ui/components/glass/index.ts +18 -0
- package/dist/ui/components/icon/icon-theme.test.ts +169 -0
- package/dist/ui/components/icon/icon-theme.ts +227 -0
- package/dist/ui/components/icon/icon.test.ts +85 -25
- package/dist/ui/components/icon/icon.ts +38 -21
- package/dist/ui/components/input/input.test.ts +178 -101
- package/dist/ui/components/input/input.ts +15 -12
- package/dist/ui/components/label/label.test.ts +11 -24
- package/dist/ui/components/line-chart/index.ts +2 -3
- package/dist/ui/components/line-chart/line-chart.test.ts +149 -56
- package/dist/ui/components/line-chart/line-chart.ts +83 -241
- package/dist/ui/components/list/list.test.ts +119 -21
- package/dist/ui/components/list/list.ts +21 -15
- package/dist/ui/components/menu/index.ts +25 -0
- package/dist/ui/components/menu/menu-placement.test.ts +153 -0
- package/dist/ui/components/menu/menu-placement.ts +159 -0
- package/dist/ui/components/menu/menu-popup.test.ts +632 -0
- package/dist/ui/components/menu/menu-popup.ts +544 -0
- package/dist/ui/components/menu/menu.test.ts +429 -0
- package/dist/ui/components/menu/menu.ts +415 -0
- package/dist/ui/components/nav-drawer/nav-drawer.test.ts +435 -191
- package/dist/ui/components/nav-drawer/nav-drawer.ts +127 -56
- package/dist/ui/components/pagination/pagination.test.ts +177 -65
- package/dist/ui/components/pagination/pagination.ts +55 -8
- package/dist/ui/components/progress/progress.test.ts +102 -46
- package/dist/ui/components/progress/progress.ts +52 -54
- package/dist/ui/components/radio-group/radio-group.test.ts +128 -83
- package/dist/ui/components/radio-group/radio-group.ts +24 -24
- package/dist/ui/components/scatter-chart/index.ts +2 -3
- package/dist/ui/components/scatter-chart/scatter-chart.test.ts +131 -26
- package/dist/ui/components/scatter-chart/scatter-chart.ts +104 -250
- package/dist/ui/components/scroll-area/scroll-area.test.ts +95 -24
- package/dist/ui/components/scroll-area/scroll-area.ts +8 -8
- package/dist/ui/components/select/select.test.ts +138 -78
- package/dist/ui/components/select/select.ts +17 -11
- package/dist/ui/components/separator/separator.test.ts +18 -17
- package/dist/ui/components/sheet/sheet.test.ts +64 -11
- package/dist/ui/components/sheet/sheet.ts +9 -1
- package/dist/ui/components/skeleton/skeleton.test.ts +24 -7
- package/dist/ui/components/skeleton/skeleton.ts +10 -16
- package/dist/ui/components/spinner/spinner.test.ts +67 -22
- package/dist/ui/components/spinner/spinner.ts +48 -41
- package/dist/ui/components/switch/switch.test.ts +116 -46
- package/dist/ui/components/switch/switch.ts +8 -13
- package/dist/ui/components/tab-bar/index.ts +1 -0
- package/dist/ui/components/tab-bar/tab-bar.test.ts +280 -0
- package/dist/ui/components/tab-bar/tab-bar.ts +230 -0
- package/dist/ui/components/tabs/tabs.test.ts +215 -157
- package/dist/ui/components/tabs/tabs.ts +110 -118
- package/dist/ui/components/textarea/textarea.test.ts +206 -100
- package/dist/ui/components/textarea/textarea.ts +14 -12
- package/dist/ui/components/toast/toast.test.ts +436 -315
- package/dist/ui/components/toast/toast.ts +62 -55
- package/dist/ui/components/toggle/toggle.test.ts +247 -140
- package/dist/ui/theme/chart-colors.test.ts +35 -0
- package/dist/ui/theme/dark.css +46 -2
- package/dist/ui/theme/default.css +63 -7
- package/dist/ui/theme/icon-colors.test.ts +35 -0
- package/dist/ui/theme/rgb-channels.test.ts +84 -0
- package/dist/ui/theme/tailwind-build.test.ts +114 -0
- package/dist/ui/theme/tailwind-css.test.ts +83 -0
- package/dist/ui/theme/tailwind-plugin.test.ts +42 -2
- package/dist/ui/theme/tailwind-plugin.ts +98 -25
- package/dist/ui/theme/tailwind.css +113 -0
- package/dist/ui/utils/animate.test.ts +13 -1
- package/dist/utils/analyze.d.ts +14 -0
- package/dist/utils/analyze.js +15 -0
- package/dist/utils/analyze.js.map +1 -1
- package/dist/utils/analyze.test.js +14 -1
- package/dist/utils/analyze.test.js.map +1 -1
- package/dist/utils/installed.d.ts +29 -0
- package/dist/utils/installed.js +43 -0
- package/dist/utils/installed.js.map +1 -0
- package/dist/utils/installed.test.d.ts +1 -0
- package/dist/utils/installed.test.js +57 -0
- package/dist/utils/installed.test.js.map +1 -0
- package/dist/utils/interactive.d.ts +9 -0
- package/dist/utils/interactive.js +10 -0
- package/dist/utils/interactive.js.map +1 -0
- package/dist/utils/interactive.test.d.ts +1 -0
- package/dist/utils/interactive.test.js +24 -0
- package/dist/utils/interactive.test.js.map +1 -0
- package/dist/utils/packages.d.ts +36 -0
- package/dist/utils/packages.js +70 -0
- package/dist/utils/packages.js.map +1 -0
- package/dist/utils/packages.test.d.ts +1 -0
- package/dist/utils/packages.test.js +89 -0
- package/dist/utils/packages.test.js.map +1 -0
- package/dist/utils/resolve-paths.d.ts +17 -1
- package/dist/utils/resolve-paths.js +21 -3
- package/dist/utils/resolve-paths.js.map +1 -1
- package/dist/utils/resolve-paths.test.js +38 -2
- package/dist/utils/resolve-paths.test.js.map +1 -1
- package/dist/utils/tailwind.d.ts +25 -0
- package/dist/utils/tailwind.js +51 -0
- package/dist/utils/tailwind.js.map +1 -0
- package/dist/utils/tailwind.test.d.ts +1 -0
- package/dist/utils/tailwind.test.js +71 -0
- package/dist/utils/tailwind.test.js.map +1 -0
- package/package.json +13 -1
- package/dist/ui/components/area-chart/area-chart-render.test.ts +0 -121
- package/dist/ui/components/bar-chart/bar-chart-render.test.ts +0 -174
- package/dist/ui/components/button/button-render.test.ts +0 -113
- package/dist/ui/components/button-group/button-group-render.test.ts +0 -146
- package/dist/ui/components/candlestick-chart/candlestick-chart-render.test.ts +0 -174
- package/dist/ui/components/cartesian-chart/cartesian-chart-render.test.ts +0 -188
- package/dist/ui/components/cartesian-chart/cartesian-chart.test.ts +0 -525
- package/dist/ui/components/cartesian-chart/cartesian-chart.ts +0 -1140
- package/dist/ui/components/cartesian-chart/index.ts +0 -18
- package/dist/ui/components/line-chart/line-chart-render.test.ts +0 -121
- package/dist/ui/components/scatter-chart/scatter-chart-render.test.ts +0 -157
|
@@ -1,163 +1,421 @@
|
|
|
1
1
|
import { Component, signal } from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
fireEvent,
|
|
4
|
+
render,
|
|
5
|
+
waitForUpdate,
|
|
6
|
+
} from '@blotch/angular-lynx-testing-library';
|
|
3
7
|
import { LYNX_ELEMENTS } from '@blotch/angular-lynx';
|
|
4
|
-
import {
|
|
5
|
-
|
|
8
|
+
import {
|
|
9
|
+
type MockInstance,
|
|
10
|
+
afterEach,
|
|
11
|
+
beforeEach,
|
|
12
|
+
describe,
|
|
13
|
+
expect,
|
|
14
|
+
it,
|
|
15
|
+
vi,
|
|
16
|
+
} from 'vitest';
|
|
17
|
+
import { DURATION } from '../../utils/animate';
|
|
18
|
+
import {
|
|
19
|
+
type LynxMainThread,
|
|
20
|
+
lynxMainThread,
|
|
21
|
+
} from '../../../test-utils/lynx-main-thread';
|
|
6
22
|
import { UiBottomSheet } from './bottom-sheet';
|
|
7
23
|
|
|
8
24
|
@Component({
|
|
9
|
-
standalone: true,
|
|
10
25
|
imports: [UiBottomSheet, LYNX_ELEMENTS],
|
|
11
|
-
template:
|
|
12
|
-
|
|
13
|
-
|
|
26
|
+
template: `
|
|
27
|
+
<ui-bottom-sheet [(open)]="open" class="max-h-96" (closed)="closed()">
|
|
28
|
+
<text>Panel</text>
|
|
29
|
+
</ui-bottom-sheet>
|
|
30
|
+
`,
|
|
14
31
|
})
|
|
15
32
|
class BottomSheetHost {
|
|
16
|
-
open =
|
|
33
|
+
readonly open = signal(false);
|
|
34
|
+
readonly closed = vi.fn();
|
|
17
35
|
}
|
|
18
36
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
37
|
+
/**
|
|
38
|
+
* The Lynx function an element's `invoke()` calls to run one of its UI
|
|
39
|
+
* methods, such as moving a screen reader's focus. The testing library
|
|
40
|
+
* defines it on the global object.
|
|
41
|
+
*/
|
|
42
|
+
type InvokeUIMethod = {
|
|
43
|
+
__InvokeUIMethod: (
|
|
44
|
+
element: Element,
|
|
45
|
+
method: string,
|
|
46
|
+
params: Record<string, unknown>,
|
|
47
|
+
callback: (result: { code: number }) => void,
|
|
48
|
+
) => void;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** `__ElementAnimate`'s first argument for starting an animation. */
|
|
52
|
+
const START = 0;
|
|
53
|
+
/** `__ElementAnimate`'s first argument for canceling an animation. */
|
|
54
|
+
const CANCEL = 3;
|
|
55
|
+
|
|
56
|
+
const renderSheet = async () => {
|
|
57
|
+
const result = await render(BottomSheetHost);
|
|
58
|
+
const { container } = result;
|
|
59
|
+
return {
|
|
60
|
+
...result,
|
|
61
|
+
host: result.componentRef.instance as BottomSheetHost,
|
|
62
|
+
overlay: container.querySelector('overlay')!,
|
|
63
|
+
backdrop: container.querySelector('overlay > view')!,
|
|
64
|
+
panel: container.querySelector('.rounded-t-2xl')!,
|
|
65
|
+
// The strip around the grabber pill, which takes the drag.
|
|
66
|
+
handle: container.querySelector('.bg-muted')!.parentElement!,
|
|
27
67
|
};
|
|
68
|
+
};
|
|
28
69
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Opens the sheet and waits out its open sequence: the overlay shows on one
|
|
72
|
+
* tick, and the panel slides in on the next.
|
|
73
|
+
*/
|
|
74
|
+
const openSheet = async (host: BottomSheetHost) => {
|
|
75
|
+
host.open.set(true);
|
|
76
|
+
for (let i = 0; i < 3; i++) await waitForUpdate();
|
|
77
|
+
};
|
|
33
78
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
79
|
+
/**
|
|
80
|
+
* Waits for the close sequence to finish: the panel slides out, then the
|
|
81
|
+
* overlay hides and `closed` fires. Polled rather than timed, since the
|
|
82
|
+
* sequence only starts on the update after `open` changes.
|
|
83
|
+
*/
|
|
84
|
+
const waitForClose = async (host: BottomSheetHost) => {
|
|
85
|
+
await vi.waitFor(() => expect(host.closed).toHaveBeenCalled());
|
|
86
|
+
await waitForUpdate();
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* The panel's live drag offset, from its inline transform.
|
|
91
|
+
*/
|
|
92
|
+
const transformOf = (panel: Element) =>
|
|
93
|
+
(panel as HTMLElement).style.getPropertyValue('transform');
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The touch fields a handle's touch event carries.
|
|
97
|
+
*/
|
|
98
|
+
const touchAt = (clientY: number) => ({
|
|
99
|
+
eventType: 'catchEvent',
|
|
100
|
+
touches: [{ clientY }],
|
|
101
|
+
});
|
|
42
102
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
).not.toThrow();
|
|
103
|
+
describe('UiBottomSheet', () => {
|
|
104
|
+
// Watched per test: the testing library resets the main thread after each.
|
|
105
|
+
let animate: MockInstance<LynxMainThread['__ElementAnimate']>;
|
|
106
|
+
beforeEach(() => {
|
|
107
|
+
animate = vi.spyOn(lynxMainThread(), '__ElementAnimate');
|
|
49
108
|
});
|
|
109
|
+
afterEach(() => animate.mockRestore());
|
|
50
110
|
|
|
51
|
-
it('
|
|
52
|
-
const {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
patchRefs(inst, view);
|
|
111
|
+
it('stays hidden until opened, then shows the panel and its content', async () => {
|
|
112
|
+
const { host, overlay, getByText } = await renderSheet();
|
|
113
|
+
expect(overlay.getAttribute('style')).toContain('display: none');
|
|
114
|
+
expect(overlay.getAttribute('visible')).toBe('false');
|
|
56
115
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
116
|
+
await openSheet(host);
|
|
117
|
+
expect(overlay.getAttribute('style')).not.toContain('display: none');
|
|
118
|
+
expect(overlay.getAttribute('visible')).toBe('true');
|
|
119
|
+
expect(getByText('Panel')).toBeTruthy();
|
|
120
|
+
});
|
|
61
121
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
expect(
|
|
122
|
+
it("adds the class to the panel's own", async () => {
|
|
123
|
+
const { panel } = await renderSheet();
|
|
124
|
+
expect(panel.classList).toContain('max-h-96');
|
|
125
|
+
expect(panel.classList).toContain('bg-background');
|
|
66
126
|
});
|
|
67
127
|
|
|
68
|
-
it('
|
|
69
|
-
const {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
128
|
+
it('fades the backdrop in and slides the panel up when opened', async () => {
|
|
129
|
+
const { host, backdrop, panel } = await renderSheet();
|
|
130
|
+
await openSheet(host);
|
|
131
|
+
expect(animate).toHaveBeenCalledWith(backdrop, [
|
|
132
|
+
START,
|
|
133
|
+
expect.any(String),
|
|
134
|
+
[{ opacity: 0 }, { opacity: 1 }],
|
|
135
|
+
expect.objectContaining({ duration: DURATION.normal }),
|
|
136
|
+
]);
|
|
137
|
+
expect(animate).toHaveBeenCalledWith(panel, [
|
|
138
|
+
START,
|
|
139
|
+
expect.any(String),
|
|
140
|
+
[
|
|
141
|
+
{ transform: 'translateY(100%)', opacity: 0.8 },
|
|
142
|
+
{ transform: 'translateY(0%)', opacity: 1 },
|
|
143
|
+
],
|
|
144
|
+
expect.objectContaining({ duration: DURATION.slow }),
|
|
145
|
+
]);
|
|
77
146
|
});
|
|
78
147
|
|
|
79
|
-
it('
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
148
|
+
it('moves a screen reader into the panel and keeps it there while open', async () => {
|
|
149
|
+
const invoke = vi.spyOn(
|
|
150
|
+
globalThis as unknown as InvokeUIMethod,
|
|
151
|
+
'__InvokeUIMethod',
|
|
152
|
+
);
|
|
153
|
+
const { host, panel } = await renderSheet();
|
|
154
|
+
expect(panel.getAttribute('accessibility-exclusive-focus')).toBe('false');
|
|
86
155
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
expect(inst.open()).toBe(false);
|
|
156
|
+
await openSheet(host);
|
|
157
|
+
expect(invoke).toHaveBeenCalledWith(
|
|
158
|
+
panel,
|
|
159
|
+
'requestAccessibilityFocus',
|
|
160
|
+
expect.anything(),
|
|
161
|
+
expect.any(Function),
|
|
162
|
+
);
|
|
163
|
+
expect(panel.getAttribute('accessibility-exclusive-focus')).toBe('true');
|
|
164
|
+
invoke.mockRestore();
|
|
97
165
|
});
|
|
98
166
|
|
|
99
|
-
it('
|
|
100
|
-
const {
|
|
101
|
-
|
|
102
|
-
const view = container.querySelector('view') as Element;
|
|
103
|
-
patchRefs(inst, view);
|
|
104
|
-
inst.open.set(true);
|
|
105
|
-
await waitForUpdate();
|
|
167
|
+
it('closes when the backdrop is tapped, sliding the panel down', async () => {
|
|
168
|
+
const { host, overlay, backdrop, panel } = await renderSheet();
|
|
169
|
+
await openSheet(host);
|
|
106
170
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
expect(
|
|
171
|
+
fireEvent.tap(backdrop);
|
|
172
|
+
expect(host.open()).toBe(false);
|
|
173
|
+
await waitForClose(host);
|
|
174
|
+
expect(animate).toHaveBeenCalledWith(backdrop, [
|
|
175
|
+
START,
|
|
176
|
+
expect.any(String),
|
|
177
|
+
[{ opacity: 1 }, { opacity: 0 }],
|
|
178
|
+
expect.objectContaining({ duration: DURATION.normal }),
|
|
179
|
+
]);
|
|
180
|
+
expect(animate).toHaveBeenCalledWith(panel, [
|
|
181
|
+
START,
|
|
182
|
+
expect.any(String),
|
|
183
|
+
[
|
|
184
|
+
{ transform: 'translateY(0%)', opacity: 1 },
|
|
185
|
+
{ transform: 'translateY(100%)', opacity: 0.8 },
|
|
186
|
+
],
|
|
187
|
+
expect.objectContaining({ duration: DURATION.normal }),
|
|
188
|
+
]);
|
|
189
|
+
// Once the slide is over, the overlay hides and `closed` fires, only for
|
|
190
|
+
// this close: a sheet that starts closed hasn't closed before.
|
|
191
|
+
expect(overlay.getAttribute('style')).toContain('display: none');
|
|
192
|
+
expect(host.closed).toHaveBeenCalledOnce();
|
|
117
193
|
});
|
|
118
194
|
|
|
119
|
-
it('
|
|
120
|
-
const {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
onHandleTouchEnd: () => void;
|
|
126
|
-
};
|
|
127
|
-
// touchmove without prior touchstart is a no-op (guards `#isDragging`).
|
|
128
|
-
cast.onHandleTouchMove({ touches: [{ clientY: 200 }] });
|
|
129
|
-
// touchstart / touchmove without touches entries is a no-op.
|
|
130
|
-
cast.onHandleTouchStart({ touches: [] });
|
|
131
|
-
cast.onHandleTouchStart({ touches: [{ clientY: 100 }] });
|
|
132
|
-
cast.onHandleTouchMove({ touches: [] });
|
|
133
|
-
// touchend without an active drag is also a no-op.
|
|
134
|
-
cast.onHandleTouchEnd();
|
|
135
|
-
cast.onHandleTouchEnd();
|
|
195
|
+
it('stays open when the panel is tapped', async () => {
|
|
196
|
+
const { host, panel } = await renderSheet();
|
|
197
|
+
await openSheet(host);
|
|
198
|
+
// The panel catches its taps, so they never reach the backdrop.
|
|
199
|
+
fireEvent.tap(panel, { eventType: 'catchEvent' });
|
|
200
|
+
expect(host.open()).toBe(true);
|
|
136
201
|
});
|
|
137
202
|
|
|
138
|
-
it('
|
|
139
|
-
const
|
|
140
|
-
const
|
|
141
|
-
|
|
203
|
+
it('stops its close timers when it is destroyed while closing', async () => {
|
|
204
|
+
const warn = vi.spyOn(console, 'warn');
|
|
205
|
+
const { host, unmount } = await renderSheet();
|
|
206
|
+
await openSheet(host);
|
|
207
|
+
host.open.set(false);
|
|
142
208
|
await waitForUpdate();
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
).
|
|
209
|
+
// Destroyed during the close animation, as an `@if` around the sheet
|
|
210
|
+
// would do. Its close timer (DURATION.normal + 20) used to fire anyway
|
|
211
|
+
// and emit `closed` from the destroyed output.
|
|
212
|
+
unmount();
|
|
213
|
+
await new Promise((resolve) => setTimeout(resolve, DURATION.normal + 50));
|
|
214
|
+
const warnings = warn.mock.calls.map(([message]) => String(message));
|
|
215
|
+
warn.mockRestore();
|
|
216
|
+
expect(warnings.filter((message) => message.includes('NG0953'))).toEqual(
|
|
217
|
+
[],
|
|
218
|
+
);
|
|
219
|
+
expect(host.closed).not.toHaveBeenCalled();
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
describe('dragged by its handle', () => {
|
|
223
|
+
it('follows the finger down, lightening the backdrop as it goes', async () => {
|
|
224
|
+
const { host, backdrop, panel, handle } = await renderSheet();
|
|
225
|
+
await openSheet(host);
|
|
226
|
+
animate.mockClear();
|
|
227
|
+
|
|
228
|
+
fireEvent.touchstart(handle, touchAt(100));
|
|
229
|
+
// The open slide holds the panel in place until it's canceled.
|
|
230
|
+
expect(animate).toHaveBeenCalledWith(panel, [CANCEL, expect.any(String)]);
|
|
231
|
+
fireEvent.touchmove(handle, touchAt(200));
|
|
232
|
+
await waitForUpdate();
|
|
233
|
+
expect(transformOf(panel)).toBe('translateY(100px)');
|
|
234
|
+
// 100px of the 500px over which the backdrop clears: 4/5 of its dim.
|
|
235
|
+
expect(backdrop.getAttribute('style')).toContain('rgba(0, 0, 0, 0.4)');
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('closes when released past the threshold, sliding on from the finger', async () => {
|
|
239
|
+
const { host, panel, handle } = await renderSheet();
|
|
240
|
+
await openSheet(host);
|
|
241
|
+
|
|
242
|
+
fireEvent.touchstart(handle, touchAt(100));
|
|
243
|
+
fireEvent.touchmove(handle, touchAt(300));
|
|
244
|
+
fireEvent.touchend(handle, { eventType: 'catchEvent' });
|
|
245
|
+
expect(host.open()).toBe(false);
|
|
246
|
+
await waitForClose(host);
|
|
247
|
+
expect(animate).toHaveBeenCalledWith(panel, [
|
|
248
|
+
START,
|
|
249
|
+
expect.any(String),
|
|
250
|
+
[
|
|
251
|
+
{ transform: 'translateY(200px)', opacity: 1 },
|
|
252
|
+
{ transform: 'translateY(600px)', opacity: 0.8 },
|
|
253
|
+
],
|
|
254
|
+
expect.objectContaining({ duration: DURATION.normal }),
|
|
255
|
+
]);
|
|
256
|
+
expect(host.closed).toHaveBeenCalledOnce();
|
|
257
|
+
// Hidden, it's back in place for the next open.
|
|
258
|
+
expect(transformOf(panel)).toBe('translateY(0px)');
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it('springs back when released or canceled short of the threshold', async () => {
|
|
262
|
+
const { host, panel, handle } = await renderSheet();
|
|
263
|
+
await openSheet(host);
|
|
264
|
+
|
|
265
|
+
fireEvent.touchstart(handle, touchAt(100));
|
|
266
|
+
fireEvent.touchmove(handle, touchAt(130));
|
|
267
|
+
fireEvent.touchend(handle, { eventType: 'catchEvent' });
|
|
268
|
+
await waitForUpdate();
|
|
269
|
+
expect(host.open()).toBe(true);
|
|
270
|
+
expect(animate).toHaveBeenCalledWith(panel, [
|
|
271
|
+
START,
|
|
272
|
+
expect.any(String),
|
|
273
|
+
[{ transform: 'translateY(30px)' }, { transform: 'translateY(0px)' }],
|
|
274
|
+
expect.objectContaining({ duration: DURATION.fast }),
|
|
275
|
+
]);
|
|
276
|
+
expect(transformOf(panel)).toBe('translateY(0px)');
|
|
277
|
+
|
|
278
|
+
// A scroll that takes the touch over cancels it the same way.
|
|
279
|
+
fireEvent.touchstart(handle, touchAt(100));
|
|
280
|
+
fireEvent.touchmove(handle, touchAt(150));
|
|
281
|
+
fireEvent.touchcancel(handle, { eventType: 'catchEvent' });
|
|
282
|
+
await waitForUpdate();
|
|
283
|
+
expect(host.open()).toBe(true);
|
|
284
|
+
expect(transformOf(panel)).toBe('translateY(0px)');
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it("doesn't move up past where it's docked", async () => {
|
|
288
|
+
const { host, panel, handle } = await renderSheet();
|
|
289
|
+
await openSheet(host);
|
|
290
|
+
fireEvent.touchstart(handle, touchAt(100));
|
|
291
|
+
fireEvent.touchmove(handle, touchAt(40));
|
|
292
|
+
await waitForUpdate();
|
|
293
|
+
expect(transformOf(panel)).toBe('translateY(0px)');
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it('ignores touches without a position, and moves outside a drag', async () => {
|
|
297
|
+
const { host, panel, handle } = await renderSheet();
|
|
298
|
+
await openSheet(host);
|
|
299
|
+
|
|
300
|
+
// A move or release with no drag under way does nothing.
|
|
301
|
+
fireEvent.touchmove(handle, touchAt(300));
|
|
302
|
+
fireEvent.touchend(handle, { eventType: 'catchEvent' });
|
|
303
|
+
// Nor does a touch whose position is missing.
|
|
304
|
+
fireEvent.touchstart(handle, { eventType: 'catchEvent' });
|
|
305
|
+
fireEvent.touchmove(handle, touchAt(300));
|
|
306
|
+
fireEvent.touchstart(handle, { eventType: 'catchEvent', touches: [] });
|
|
307
|
+
fireEvent.touchmove(handle, touchAt(300));
|
|
308
|
+
await waitForUpdate();
|
|
309
|
+
expect(transformOf(panel)).toBe('translateY(0px)');
|
|
310
|
+
|
|
311
|
+
fireEvent.touchstart(handle, touchAt(100));
|
|
312
|
+
fireEvent.touchmove(handle, { eventType: 'catchEvent', touches: [] });
|
|
313
|
+
await waitForUpdate();
|
|
314
|
+
expect(transformOf(panel)).toBe('translateY(0px)');
|
|
315
|
+
expect(host.open()).toBe(true);
|
|
316
|
+
});
|
|
148
317
|
});
|
|
149
318
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
319
|
+
describe('dragged by mouse', () => {
|
|
320
|
+
/**
|
|
321
|
+
* Presses the handle, which catches its own mousedown.
|
|
322
|
+
*/
|
|
323
|
+
const press = (handle: Element, y: number) =>
|
|
324
|
+
fireEvent.mousedown(handle, { eventType: 'catchEvent', y });
|
|
325
|
+
/**
|
|
326
|
+
* Moves the mouse, which the backdrop sees anywhere in the sheet.
|
|
327
|
+
*/
|
|
328
|
+
const move = (backdrop: Element, y: number, buttons = 1) =>
|
|
329
|
+
fireEvent.mousemove(backdrop, { y, buttons });
|
|
330
|
+
|
|
331
|
+
it('closes when released past the threshold', async () => {
|
|
332
|
+
const { host, backdrop, panel, handle } = await renderSheet();
|
|
333
|
+
await openSheet(host);
|
|
334
|
+
|
|
335
|
+
press(handle, 100);
|
|
336
|
+
move(backdrop, 300);
|
|
337
|
+
await waitForUpdate();
|
|
338
|
+
expect(transformOf(panel)).toBe('translateY(200px)');
|
|
339
|
+
fireEvent.mouseup(backdrop);
|
|
340
|
+
expect(host.open()).toBe(false);
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it('springs back when released short of the threshold', async () => {
|
|
344
|
+
const { host, backdrop, panel, handle } = await renderSheet();
|
|
345
|
+
await openSheet(host);
|
|
346
|
+
|
|
347
|
+
press(handle, 100);
|
|
348
|
+
move(backdrop, 130);
|
|
349
|
+
fireEvent.mouseup(backdrop);
|
|
350
|
+
await waitForUpdate();
|
|
351
|
+
expect(host.open()).toBe(true);
|
|
352
|
+
expect(transformOf(panel)).toBe('translateY(0px)');
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it('ignores the backdrop click that follows a moved drag', async () => {
|
|
356
|
+
const { host, backdrop, handle } = await renderSheet();
|
|
357
|
+
await openSheet(host);
|
|
358
|
+
|
|
359
|
+
// A drag released above the panel: the browser's click lands on the
|
|
360
|
+
// backdrop, and must not close the sheet that just snapped back.
|
|
361
|
+
press(handle, 100);
|
|
362
|
+
move(backdrop, 40);
|
|
363
|
+
fireEvent.mouseup(backdrop);
|
|
364
|
+
fireEvent.tap(backdrop);
|
|
365
|
+
expect(host.open()).toBe(true);
|
|
366
|
+
|
|
367
|
+
// Only that one click is ignored: the next backdrop tap closes it.
|
|
368
|
+
fireEvent.tap(backdrop);
|
|
369
|
+
expect(host.open()).toBe(false);
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
it('a new press clears an ignore no click consumed', async () => {
|
|
373
|
+
const { host, backdrop, handle } = await renderSheet();
|
|
374
|
+
await openSheet(host);
|
|
375
|
+
|
|
376
|
+
// Released over the panel, so its catchtap ate the click.
|
|
377
|
+
press(handle, 100);
|
|
378
|
+
move(backdrop, 120);
|
|
379
|
+
fireEvent.mouseup(backdrop);
|
|
380
|
+
// A real backdrop click starts with a mousedown on the backdrop.
|
|
381
|
+
fireEvent.mousedown(backdrop);
|
|
382
|
+
fireEvent.tap(backdrop);
|
|
383
|
+
expect(host.open()).toBe(false);
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
it('a press without a move, or a touch drag, leaves the backdrop tap alone', async () => {
|
|
387
|
+
const { host, backdrop, handle } = await renderSheet();
|
|
388
|
+
await openSheet(host);
|
|
389
|
+
|
|
390
|
+
press(handle, 100);
|
|
391
|
+
fireEvent.mouseup(backdrop);
|
|
392
|
+
// A moved touch is never followed by a tap, so nothing is ignored.
|
|
393
|
+
fireEvent.touchstart(handle, touchAt(100));
|
|
394
|
+
fireEvent.touchmove(handle, touchAt(120));
|
|
395
|
+
fireEvent.touchend(handle, { eventType: 'catchEvent' });
|
|
396
|
+
fireEvent.tap(backdrop);
|
|
397
|
+
expect(host.open()).toBe(false);
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
it('ends a drag whose release it never saw', async () => {
|
|
401
|
+
const { host, backdrop, handle } = await renderSheet();
|
|
402
|
+
await openSheet(host);
|
|
403
|
+
|
|
404
|
+
press(handle, 100);
|
|
405
|
+
move(backdrop, 300);
|
|
406
|
+
// The button came up outside the window; the cursor is back without it.
|
|
407
|
+
move(backdrop, 120, 0);
|
|
408
|
+
// Released 200px down, past the threshold, so it closes.
|
|
409
|
+
expect(host.open()).toBe(false);
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
it('a move outside a drag leaves the sheet in place', async () => {
|
|
413
|
+
const { host, backdrop, panel } = await renderSheet();
|
|
414
|
+
await openSheet(host);
|
|
415
|
+
// The cursor passing over an open sheet with a button held elsewhere.
|
|
416
|
+
move(backdrop, 300);
|
|
417
|
+
await waitForUpdate();
|
|
418
|
+
expect(transformOf(panel)).toBe('translateY(0px)');
|
|
419
|
+
});
|
|
162
420
|
});
|
|
163
421
|
});
|