@blotch/dolan 22.2.3 → 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.js +9 -1
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/add.test.js +36 -3
- package/dist/commands/add.test.js.map +1 -1
- package/dist/commands/doctor.js +187 -7
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/doctor.test.js +280 -7
- package/dist/commands/doctor.test.js.map +1 -1
- package/dist/commands/init.d.ts +2 -2
- package/dist/commands/init.js +38 -18
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/init.test.js +107 -1
- package/dist/commands/init.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 +5 -0
- package/dist/commands/update.js +126 -45
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/update.test.js +314 -2
- package/dist/commands/update.test.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 +6 -0
- package/dist/registry.js +48 -2
- package/dist/registry.js.map +1 -1
- package/dist/registry.test.js +45 -3
- 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 +5 -4
- package/dist/testing/set-input-signal.js +5 -4
- package/dist/testing/set-input-signal.js.map +1 -1
- 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 +272 -187
- package/dist/ui/components/action-sheet/action-sheet.ts +40 -34
- 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 +206 -139
- package/dist/ui/components/alert-dialog/alert-dialog.ts +32 -26
- package/dist/ui/components/area-chart/area-chart.test.ts +81 -1
- 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 +82 -1
- package/dist/ui/components/bottom-sheet/bottom-sheet.test.ts +373 -297
- package/dist/ui/components/bottom-sheet/bottom-sheet.ts +34 -33
- package/dist/ui/components/button/button.test.ts +611 -2
- package/dist/ui/components/button/button.ts +431 -62
- 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 +82 -1
- package/dist/ui/components/card/card.test.ts +82 -62
- package/dist/ui/components/chart/chart-presets.test.ts +197 -1
- package/dist/ui/components/chart/chart-presets.ts +8 -1
- package/dist/ui/components/chart/chart-theme.ts +12 -0
- package/dist/ui/components/chart/chart.test.ts +1017 -0
- package/dist/ui/components/chart/chart.ts +56 -43
- 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 +210 -152
- package/dist/ui/components/dialog/dialog.ts +29 -23
- 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 +36 -0
- package/dist/ui/components/icon/icon-theme.ts +36 -13
- package/dist/ui/components/icon/icon.test.ts +52 -41
- 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/line-chart.test.ts +76 -1
- package/dist/ui/components/list/list.test.ts +80 -49
- 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 +425 -260
- package/dist/ui/components/nav-drawer/nav-drawer.ts +72 -56
- package/dist/ui/components/pagination/pagination.test.ts +136 -86
- 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/scatter-chart.test.ts +74 -1
- package/dist/ui/components/scroll-area/scroll-area.test.ts +72 -36
- 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 +64 -46
- package/dist/ui/components/spinner/spinner.ts +16 -19
- 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 +434 -350
- package/dist/ui/components/toast/toast.ts +42 -51
- package/dist/ui/components/toggle/toggle.test.ts +247 -140
- package/dist/ui/theme/chart-colors.test.ts +8 -3
- package/dist/ui/theme/dark.css +38 -2
- package/dist/ui/theme/default.css +55 -7
- package/dist/ui/theme/icon-colors.test.ts +8 -3
- 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 +93 -29
- 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 +12 -0
- package/dist/utils/installed.js +16 -0
- package/dist/utils/installed.js.map +1 -1
- package/dist/utils/installed.test.js +17 -1
- package/dist/utils/installed.test.js.map +1 -1
- package/dist/utils/resolve-paths.d.ts +4 -4
- package/dist/utils/resolve-paths.js +5 -7
- package/dist/utils/resolve-paths.js.map +1 -1
- package/dist/utils/resolve-paths.test.js +9 -5
- 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 +9 -1
- package/dist/ui/components/area-chart/area-chart-render.test.ts +0 -63
- package/dist/ui/components/bar-chart/bar-chart-render.test.ts +0 -58
- package/dist/ui/components/button/button-render.test.ts +0 -132
- 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 -59
- package/dist/ui/components/chart/chart-render.test.ts +0 -730
- package/dist/ui/components/line-chart/line-chart-render.test.ts +0 -83
- package/dist/ui/components/scatter-chart/scatter-chart-render.test.ts +0 -64
|
@@ -1,9 +1,25 @@
|
|
|
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 {
|
|
8
|
+
import {
|
|
9
|
+
type MockInstance,
|
|
10
|
+
afterEach,
|
|
11
|
+
beforeEach,
|
|
12
|
+
describe,
|
|
13
|
+
expect,
|
|
14
|
+
it,
|
|
15
|
+
vi,
|
|
16
|
+
} from 'vitest';
|
|
5
17
|
import { DURATION } from '../../utils/animate';
|
|
6
|
-
import {
|
|
18
|
+
import { fireLynxEvent } from '../../../test-utils/fire-lynx-event';
|
|
19
|
+
import {
|
|
20
|
+
type LynxMainThread,
|
|
21
|
+
lynxMainThread,
|
|
22
|
+
} from '../../../test-utils/lynx-main-thread';
|
|
7
23
|
import {
|
|
8
24
|
UiActionSheet,
|
|
9
25
|
UiActionSheetCancel,
|
|
@@ -20,239 +36,308 @@ import {
|
|
|
20
36
|
LYNX_ELEMENTS,
|
|
21
37
|
],
|
|
22
38
|
template: `
|
|
23
|
-
<ui-action-sheet [(open)]="open">
|
|
24
|
-
<ui-action-sheet-title>Pick</ui-action-sheet-title>
|
|
25
|
-
<ui-action-sheet-item>
|
|
26
|
-
<ui-action-sheet-
|
|
39
|
+
<ui-action-sheet [(open)]="open" class="pb-8" (closed)="closed()">
|
|
40
|
+
<ui-action-sheet-title class="py-4">Pick</ui-action-sheet-title>
|
|
41
|
+
<ui-action-sheet-item (pressed)="shared()">Share</ui-action-sheet-item>
|
|
42
|
+
<ui-action-sheet-item
|
|
43
|
+
variant="destructive"
|
|
44
|
+
class="bg-muted"
|
|
45
|
+
(pressed)="deleted()"
|
|
46
|
+
>
|
|
47
|
+
Delete
|
|
48
|
+
</ui-action-sheet-item>
|
|
49
|
+
<ui-action-sheet-cancel class="mt-2" />
|
|
27
50
|
</ui-action-sheet>
|
|
28
51
|
`,
|
|
29
52
|
})
|
|
30
53
|
class ActionSheetHost {
|
|
31
|
-
open =
|
|
54
|
+
readonly open = signal(false);
|
|
55
|
+
readonly closed = vi.fn();
|
|
56
|
+
readonly shared = vi.fn();
|
|
57
|
+
readonly deleted = vi.fn();
|
|
32
58
|
}
|
|
33
59
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
unmount();
|
|
47
|
-
await new Promise((r) => setTimeout(r, DURATION.normal + 50));
|
|
48
|
-
const warnings = warn.mock.calls.map(([message]) => String(message));
|
|
49
|
-
warn.mockRestore();
|
|
50
|
-
expect(warnings.filter((message) => message.includes('NG0953'))).toEqual(
|
|
51
|
-
[],
|
|
52
|
-
);
|
|
53
|
-
});
|
|
60
|
+
/**
|
|
61
|
+
* A cancel button given its own label.
|
|
62
|
+
*/
|
|
63
|
+
@Component({
|
|
64
|
+
imports: [UiActionSheet, UiActionSheetCancel],
|
|
65
|
+
template: `
|
|
66
|
+
<ui-action-sheet>
|
|
67
|
+
<ui-action-sheet-cancel label="Dismiss" />
|
|
68
|
+
</ui-action-sheet>
|
|
69
|
+
`,
|
|
70
|
+
})
|
|
71
|
+
class CancelLabelHost {}
|
|
54
72
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
nativeElement: panel,
|
|
69
|
-
});
|
|
70
|
-
inst.open.set(true);
|
|
71
|
-
for (let i = 0; i < 5; i++) await waitForUpdate();
|
|
72
|
-
expect(invoke).toHaveBeenCalledWith('requestAccessibilityFocus');
|
|
73
|
-
expect(panel.getAttribute('accessibility-exclusive-focus')).toBe('true');
|
|
74
|
-
});
|
|
73
|
+
/**
|
|
74
|
+
* The Lynx function an element's `invoke()` calls to run one of its UI
|
|
75
|
+
* methods, such as moving a screen reader's focus. The testing library
|
|
76
|
+
* defines it on the global object.
|
|
77
|
+
*/
|
|
78
|
+
type InvokeUIMethod = {
|
|
79
|
+
__InvokeUIMethod: (
|
|
80
|
+
element: Element,
|
|
81
|
+
method: string,
|
|
82
|
+
params: Record<string, unknown>,
|
|
83
|
+
callback: (result: { code: number }) => void,
|
|
84
|
+
) => void;
|
|
85
|
+
};
|
|
75
86
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
87
|
+
/** `__ElementAnimate`'s first argument for starting an animation. */
|
|
88
|
+
const START = 0;
|
|
89
|
+
|
|
90
|
+
const renderSheet = async () => {
|
|
91
|
+
const result = await render(ActionSheetHost);
|
|
92
|
+
const { container } = result;
|
|
93
|
+
return {
|
|
94
|
+
...result,
|
|
95
|
+
host: result.componentRef.instance as ActionSheetHost,
|
|
96
|
+
overlay: container.querySelector('overlay')!,
|
|
97
|
+
backdrop: container.querySelector('overlay > view')!,
|
|
98
|
+
panel: container.querySelector('[accessibility-exclusive-focus]')!,
|
|
99
|
+
// A button's pressable tile: the view around its label.
|
|
100
|
+
button: (label: string) => result.getByText(label).parentElement!,
|
|
83
101
|
};
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Opens the action sheet and waits out its open sequence: the overlay shows
|
|
106
|
+
* on one tick, and the panel slides in on the next.
|
|
107
|
+
*/
|
|
108
|
+
const openSheet = async (host: ActionSheetHost) => {
|
|
109
|
+
host.open.set(true);
|
|
110
|
+
for (let i = 0; i < 3; i++) await waitForUpdate();
|
|
111
|
+
};
|
|
84
112
|
|
|
85
|
-
|
|
86
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Waits for the close sequence to finish: the panel slides out, then the
|
|
115
|
+
* overlay hides and `closed` fires. Polled rather than timed, since the
|
|
116
|
+
* sequence only starts on the update after `open` changes.
|
|
117
|
+
*/
|
|
118
|
+
const waitForClose = async (host: ActionSheetHost) => {
|
|
119
|
+
await vi.waitFor(() => expect(host.closed).toHaveBeenCalled());
|
|
120
|
+
await waitForUpdate();
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The scale a button's inline style holds, if any.
|
|
125
|
+
*/
|
|
126
|
+
const scaleOf = (element: Element) =>
|
|
127
|
+
(element as HTMLElement).style.getPropertyValue('transform');
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Presses a button and lets go every way Lynx reports it, checking that it
|
|
131
|
+
* scales down while pressed and back up once released.
|
|
132
|
+
*/
|
|
133
|
+
const expectPressFeedback = (button: Element) => {
|
|
134
|
+
fireEvent.touchstart(button);
|
|
135
|
+
expect(scaleOf(button)).toBe('scale(0.985)');
|
|
136
|
+
fireEvent.touchend(button);
|
|
137
|
+
expect(scaleOf(button)).toBe('scale(1)');
|
|
138
|
+
|
|
139
|
+
// A scroll that takes the touch over cancels it: the button scales back.
|
|
140
|
+
fireEvent.touchstart(button);
|
|
141
|
+
fireEvent.touchcancel(button);
|
|
142
|
+
expect(scaleOf(button)).toBe('scale(1)');
|
|
143
|
+
|
|
144
|
+
// On web, the mouse drives the same feedback.
|
|
145
|
+
fireEvent.mousedown(button);
|
|
146
|
+
expect(scaleOf(button)).toBe('scale(0.985)');
|
|
147
|
+
fireEvent.mouseup(button);
|
|
148
|
+
expect(scaleOf(button)).toBe('scale(1)');
|
|
149
|
+
|
|
150
|
+
fireEvent.mousedown(button);
|
|
151
|
+
fireLynxEvent(button, 'mouseleave');
|
|
152
|
+
expect(scaleOf(button)).toBe('scale(1)');
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
describe('UiActionSheet', () => {
|
|
156
|
+
// Watched per test: the testing library resets the main thread after each.
|
|
157
|
+
let animate: MockInstance<LynxMainThread['__ElementAnimate']>;
|
|
158
|
+
beforeEach(() => {
|
|
159
|
+
animate = vi.spyOn(lynxMainThread(), '__ElementAnimate');
|
|
160
|
+
});
|
|
161
|
+
afterEach(() => animate.mockRestore());
|
|
162
|
+
|
|
163
|
+
it('stays hidden until opened, then shows its title and buttons', async () => {
|
|
164
|
+
const { host, overlay, getByText } = await renderSheet();
|
|
165
|
+
expect(overlay.getAttribute('style')).toContain('display: none');
|
|
166
|
+
expect(overlay.getAttribute('visible')).toBe('false');
|
|
167
|
+
|
|
168
|
+
await openSheet(host);
|
|
169
|
+
expect(overlay.getAttribute('style')).not.toContain('display: none');
|
|
170
|
+
expect(overlay.getAttribute('visible')).toBe('true');
|
|
87
171
|
expect(getByText('Pick')).toBeTruthy();
|
|
88
|
-
expect(getByText('
|
|
172
|
+
expect(getByText('Share')).toBeTruthy();
|
|
173
|
+
expect(getByText('Delete')).toBeTruthy();
|
|
89
174
|
expect(getByText('Cancel')).toBeTruthy();
|
|
90
175
|
});
|
|
91
176
|
|
|
92
|
-
it(
|
|
93
|
-
const {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
(inst as unknown as { onBackdropTap: () => void }).onBackdropTap();
|
|
98
|
-
expect(inst.open()).toBe(false);
|
|
177
|
+
it("merges the class into the panel's own", async () => {
|
|
178
|
+
const { panel } = await renderSheet();
|
|
179
|
+
expect(panel.classList).toContain('pb-8');
|
|
180
|
+
expect(panel.classList).not.toContain('pb-6');
|
|
181
|
+
expect(panel.classList).toContain('px-4');
|
|
99
182
|
});
|
|
100
183
|
|
|
101
|
-
it('
|
|
102
|
-
const {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
184
|
+
it('fades the backdrop in and slides the panel up when opened', async () => {
|
|
185
|
+
const { host, backdrop, panel } = await renderSheet();
|
|
186
|
+
await openSheet(host);
|
|
187
|
+
expect(animate).toHaveBeenCalledWith(backdrop, [
|
|
188
|
+
START,
|
|
189
|
+
expect.any(String),
|
|
190
|
+
[{ opacity: 0 }, { opacity: 1 }],
|
|
191
|
+
expect.objectContaining({ duration: DURATION.normal }),
|
|
192
|
+
]);
|
|
193
|
+
expect(animate).toHaveBeenCalledWith(panel, [
|
|
194
|
+
START,
|
|
195
|
+
expect.any(String),
|
|
196
|
+
[
|
|
197
|
+
{ transform: 'translateY(100%)', opacity: 0.8 },
|
|
198
|
+
{ transform: 'translateY(0%)', opacity: 1 },
|
|
199
|
+
],
|
|
200
|
+
expect.objectContaining({ duration: DURATION.slow }),
|
|
201
|
+
]);
|
|
107
202
|
});
|
|
108
203
|
|
|
109
|
-
it('panel
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
204
|
+
it('moves a screen reader into the panel and keeps it there while open', async () => {
|
|
205
|
+
const invoke = vi.spyOn(
|
|
206
|
+
globalThis as unknown as InvokeUIMethod,
|
|
207
|
+
'__InvokeUIMethod',
|
|
208
|
+
);
|
|
209
|
+
const { host, panel } = await renderSheet();
|
|
210
|
+
expect(panel.getAttribute('accessibility-exclusive-focus')).toBe('false');
|
|
116
211
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
212
|
+
await openSheet(host);
|
|
213
|
+
expect(invoke).toHaveBeenCalledWith(
|
|
214
|
+
panel,
|
|
215
|
+
'requestAccessibilityFocus',
|
|
216
|
+
expect.anything(),
|
|
217
|
+
expect.any(Function),
|
|
218
|
+
);
|
|
219
|
+
expect(panel.getAttribute('accessibility-exclusive-focus')).toBe('true');
|
|
220
|
+
invoke.mockRestore();
|
|
221
|
+
});
|
|
122
222
|
|
|
123
|
-
|
|
124
|
-
await
|
|
125
|
-
await
|
|
126
|
-
await waitForUpdate();
|
|
223
|
+
it('closes when the backdrop is tapped, sliding the panel down', async () => {
|
|
224
|
+
const { host, overlay, backdrop, panel } = await renderSheet();
|
|
225
|
+
await openSheet(host);
|
|
127
226
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
await
|
|
131
|
-
expect(
|
|
227
|
+
fireEvent.tap(backdrop);
|
|
228
|
+
expect(host.open()).toBe(false);
|
|
229
|
+
await waitForClose(host);
|
|
230
|
+
expect(animate).toHaveBeenCalledWith(backdrop, [
|
|
231
|
+
START,
|
|
232
|
+
expect.any(String),
|
|
233
|
+
[{ opacity: 1 }, { opacity: 0 }],
|
|
234
|
+
expect.objectContaining({ duration: DURATION.normal }),
|
|
235
|
+
]);
|
|
236
|
+
expect(animate).toHaveBeenCalledWith(panel, [
|
|
237
|
+
START,
|
|
238
|
+
expect.any(String),
|
|
239
|
+
[
|
|
240
|
+
{ transform: 'translateY(0%)', opacity: 1 },
|
|
241
|
+
{ transform: 'translateY(100%)', opacity: 0.8 },
|
|
242
|
+
],
|
|
243
|
+
expect.objectContaining({ duration: DURATION.normal }),
|
|
244
|
+
]);
|
|
245
|
+
// Once the slide is over, the overlay hides and `closed` fires, only for
|
|
246
|
+
// this close: an action sheet that starts closed hasn't closed before.
|
|
247
|
+
expect(overlay.getAttribute('style')).toContain('display: none');
|
|
248
|
+
expect(host.closed).toHaveBeenCalledOnce();
|
|
132
249
|
});
|
|
133
250
|
|
|
134
|
-
it('open
|
|
135
|
-
const {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
await waitForUpdate();
|
|
141
|
-
await waitForUpdate();
|
|
142
|
-
inst.open.set(false);
|
|
143
|
-
await waitForUpdate();
|
|
144
|
-
// Wait out the close sequence, so #animateOut runs (and bails) while the
|
|
145
|
-
// component is still alive. Destroying it clears the sequence's timers.
|
|
146
|
-
await new Promise((r) => setTimeout(r, DURATION.normal + 50));
|
|
147
|
-
expect(inst.open()).toBe(false);
|
|
148
|
-
expect(closed).toHaveBeenCalledOnce();
|
|
251
|
+
it('stays open when the panel is tapped', async () => {
|
|
252
|
+
const { host, panel } = await renderSheet();
|
|
253
|
+
await openSheet(host);
|
|
254
|
+
// The panel catches its taps, so they never reach the backdrop.
|
|
255
|
+
fireEvent.tap(panel, { eventType: 'catchEvent' });
|
|
256
|
+
expect(host.open()).toBe(true);
|
|
149
257
|
});
|
|
150
258
|
|
|
151
|
-
it('
|
|
152
|
-
const
|
|
153
|
-
const
|
|
154
|
-
|
|
259
|
+
it('stops its close timers when it is destroyed while closing', async () => {
|
|
260
|
+
const warn = vi.spyOn(console, 'warn');
|
|
261
|
+
const { host, unmount } = await renderSheet();
|
|
262
|
+
await openSheet(host);
|
|
263
|
+
host.open.set(false);
|
|
155
264
|
await waitForUpdate();
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
).
|
|
265
|
+
// Destroyed during the close animation, as an `@if` around the action
|
|
266
|
+
// sheet would do. Its close timer (DURATION.normal + 20) used to fire
|
|
267
|
+
// anyway and emit `closed` from the destroyed output.
|
|
268
|
+
unmount();
|
|
269
|
+
await new Promise((resolve) => setTimeout(resolve, DURATION.normal + 50));
|
|
270
|
+
const warnings = warn.mock.calls.map(([message]) => String(message));
|
|
271
|
+
warn.mockRestore();
|
|
272
|
+
expect(warnings.filter((message) => message.includes('NG0953'))).toEqual(
|
|
273
|
+
[],
|
|
274
|
+
);
|
|
275
|
+
expect(host.closed).not.toHaveBeenCalled();
|
|
161
276
|
});
|
|
162
277
|
});
|
|
163
278
|
|
|
164
279
|
describe('UiActionSheetTitle', () => {
|
|
165
|
-
it('
|
|
166
|
-
const {
|
|
167
|
-
|
|
168
|
-
expect(
|
|
280
|
+
it('shows its text muted, with the class on its container', async () => {
|
|
281
|
+
const { getByText } = await renderSheet();
|
|
282
|
+
const title = getByText('Pick');
|
|
283
|
+
expect(title.classList).toContain('text-muted-foreground');
|
|
284
|
+
expect(title.parentElement?.classList).toContain('py-4');
|
|
285
|
+
expect(title.parentElement?.classList).not.toContain('py-3');
|
|
169
286
|
});
|
|
170
287
|
});
|
|
171
288
|
|
|
172
289
|
describe('UiActionSheetItem', () => {
|
|
173
|
-
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
parent.open.set(true);
|
|
177
|
-
await waitForUpdate();
|
|
290
|
+
it('reports the press and closes the action sheet when tapped', async () => {
|
|
291
|
+
const { host, button } = await renderSheet();
|
|
292
|
+
await openSheet(host);
|
|
178
293
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
};
|
|
294
|
+
fireEvent.tap(button('Share'));
|
|
295
|
+
expect(host.shared).toHaveBeenCalledOnce();
|
|
296
|
+
expect(host.deleted).not.toHaveBeenCalled();
|
|
297
|
+
expect(host.open()).toBe(false);
|
|
298
|
+
});
|
|
184
299
|
|
|
185
|
-
it('
|
|
186
|
-
const {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
onTap: () => void;
|
|
190
|
-
};
|
|
191
|
-
const emitted = vi.fn();
|
|
192
|
-
inst.pressed.subscribe(emitted);
|
|
193
|
-
inst.onTap();
|
|
194
|
-
expect(emitted).toHaveBeenCalledTimes(1);
|
|
195
|
-
expect(parent.open()).toBe(false);
|
|
300
|
+
it('colors its label by variant', async () => {
|
|
301
|
+
const { getByText } = await renderSheet();
|
|
302
|
+
expect(getByText('Share').classList).toContain('text-primary');
|
|
303
|
+
expect(getByText('Delete').classList).toContain('text-destructive');
|
|
196
304
|
});
|
|
197
305
|
|
|
198
|
-
it(
|
|
199
|
-
const {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
onPressEnd: () => void;
|
|
203
|
-
onPressCancel: () => void;
|
|
204
|
-
};
|
|
205
|
-
expect(() => inst.onPressStart()).not.toThrow();
|
|
206
|
-
expect(() => inst.onPressEnd()).not.toThrow();
|
|
207
|
-
expect(() => inst.onPressCancel()).not.toThrow();
|
|
306
|
+
it("merges the class into its tile's own", async () => {
|
|
307
|
+
const { button } = await renderSheet();
|
|
308
|
+
expect(button('Delete').classList).toContain('bg-muted');
|
|
309
|
+
expect(button('Delete').classList).toContain('border-t');
|
|
208
310
|
});
|
|
209
311
|
|
|
210
|
-
it('
|
|
211
|
-
const {
|
|
212
|
-
|
|
213
|
-
setInputSignal(inst.variant, 'destructive');
|
|
214
|
-
await waitForUpdate();
|
|
215
|
-
const text = itemResult.container.querySelector('text');
|
|
216
|
-
expect(text?.getAttribute('class')).toContain('text-destructive');
|
|
312
|
+
it('scales down while pressed, and back on release', async () => {
|
|
313
|
+
const { button } = await renderSheet();
|
|
314
|
+
expectPressFeedback(button('Share'));
|
|
217
315
|
});
|
|
218
316
|
});
|
|
219
317
|
|
|
220
318
|
describe('UiActionSheetCancel', () => {
|
|
221
|
-
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
parent.open.set(true);
|
|
225
|
-
await waitForUpdate();
|
|
319
|
+
it('closes the action sheet when tapped', async () => {
|
|
320
|
+
const { host, button } = await renderSheet();
|
|
321
|
+
await openSheet(host);
|
|
226
322
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
return { parent, cancelResult };
|
|
231
|
-
};
|
|
323
|
+
fireEvent.tap(button('Cancel'));
|
|
324
|
+
expect(host.open()).toBe(false);
|
|
325
|
+
});
|
|
232
326
|
|
|
233
|
-
it('
|
|
234
|
-
|
|
235
|
-
|
|
327
|
+
it('shows Cancel, or the label it is given', async () => {
|
|
328
|
+
expect((await renderSheet()).getByText('Cancel')).toBeTruthy();
|
|
329
|
+
const { getByText } = await render(CancelLabelHost);
|
|
330
|
+
expect(getByText('Dismiss')).toBeTruthy();
|
|
236
331
|
});
|
|
237
332
|
|
|
238
|
-
it(
|
|
239
|
-
const {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
};
|
|
243
|
-
inst.onTap();
|
|
244
|
-
expect(parent.open()).toBe(false);
|
|
333
|
+
it("merges the class into its tile's own", async () => {
|
|
334
|
+
const { button } = await renderSheet();
|
|
335
|
+
expect(button('Cancel').classList).toContain('mt-2');
|
|
336
|
+
expect(button('Cancel').classList).toContain('bg-card');
|
|
245
337
|
});
|
|
246
338
|
|
|
247
|
-
it('
|
|
248
|
-
const {
|
|
249
|
-
|
|
250
|
-
onPressStart: () => void;
|
|
251
|
-
onPressEnd: () => void;
|
|
252
|
-
onPressCancel: () => void;
|
|
253
|
-
};
|
|
254
|
-
expect(() => inst.onPressStart()).not.toThrow();
|
|
255
|
-
expect(() => inst.onPressEnd()).not.toThrow();
|
|
256
|
-
expect(() => inst.onPressCancel()).not.toThrow();
|
|
339
|
+
it('scales down while pressed, and back on release', async () => {
|
|
340
|
+
const { button } = await renderSheet();
|
|
341
|
+
expectPressFeedback(button('Cancel'));
|
|
257
342
|
});
|
|
258
343
|
});
|