@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,199 +1,257 @@
|
|
|
1
|
-
import { Component, signal } from '@angular/core';
|
|
2
|
-
import {
|
|
1
|
+
import { Component, signal, viewChild } from '@angular/core';
|
|
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 {
|
|
18
|
+
type LynxMainThread,
|
|
19
|
+
lynxMainThread,
|
|
20
|
+
} from '../../../test-utils/lynx-main-thread';
|
|
6
21
|
import { UiTabs, UiTabsContent, UiTabsList, UiTabsTrigger } from './tabs';
|
|
7
22
|
|
|
8
23
|
@Component({
|
|
9
|
-
standalone: true,
|
|
10
24
|
imports: [UiTabs, UiTabsList, UiTabsTrigger, UiTabsContent, LYNX_ELEMENTS],
|
|
11
25
|
template: `
|
|
12
|
-
<ui-tabs [(value)]="value">
|
|
13
|
-
<ui-tabs-list>
|
|
14
|
-
<ui-tabs-trigger value="
|
|
15
|
-
<ui-tabs-trigger value="
|
|
26
|
+
<ui-tabs [(value)]="value" (changed)="changes.push($event)" class="w-80">
|
|
27
|
+
<ui-tabs-list class="mb-2">
|
|
28
|
+
<ui-tabs-trigger value="account" class="px-4">Account</ui-tabs-trigger>
|
|
29
|
+
<ui-tabs-trigger value="billing">Billing</ui-tabs-trigger>
|
|
30
|
+
<ui-tabs-trigger value="contact">Contact</ui-tabs-trigger>
|
|
16
31
|
</ui-tabs-list>
|
|
17
|
-
<ui-tabs-content value="
|
|
18
|
-
|
|
32
|
+
<ui-tabs-content value="account" class="gap-2">
|
|
33
|
+
<text>Account panel</text>
|
|
34
|
+
</ui-tabs-content>
|
|
35
|
+
<ui-tabs-content value="billing">
|
|
36
|
+
<text>Billing panel</text>
|
|
37
|
+
</ui-tabs-content>
|
|
38
|
+
<ui-tabs-content value="contact">
|
|
39
|
+
<text>Contact panel</text>
|
|
40
|
+
</ui-tabs-content>
|
|
19
41
|
</ui-tabs>
|
|
20
42
|
`,
|
|
21
43
|
})
|
|
22
44
|
class TabsHost {
|
|
23
|
-
value = '
|
|
45
|
+
readonly value = signal('account');
|
|
46
|
+
readonly changes: string[] = [];
|
|
47
|
+
readonly tabs = viewChild.required(UiTabs);
|
|
24
48
|
}
|
|
25
49
|
|
|
50
|
+
const renderTabs = async () => {
|
|
51
|
+
const result = await render(TabsHost);
|
|
52
|
+
/**
|
|
53
|
+
* A trigger's own view, which holds the tap listener, around its label.
|
|
54
|
+
*/
|
|
55
|
+
const trigger = (label: string) => result.getByText(label).parentElement!;
|
|
56
|
+
/**
|
|
57
|
+
* A panel's own view, which wraps its projected text.
|
|
58
|
+
*/
|
|
59
|
+
const panel = (text: string) => result.getByText(text).parentElement!;
|
|
60
|
+
return {
|
|
61
|
+
...result,
|
|
62
|
+
host: result.componentRef.instance as TabsHost,
|
|
63
|
+
trigger,
|
|
64
|
+
panel,
|
|
65
|
+
/** The display of a panel's host element, which shows or hides it. */
|
|
66
|
+
displayOf: (text: string) =>
|
|
67
|
+
(panel(text).parentElement as HTMLElement).style.display,
|
|
68
|
+
tap: async (label: string) => {
|
|
69
|
+
fireEvent.tap(trigger(label));
|
|
70
|
+
await waitForUpdate();
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/** `__ElementAnimate`'s first argument for starting an animation. */
|
|
76
|
+
const START = 0;
|
|
77
|
+
/** `__ElementAnimate`'s first argument for canceling an animation. */
|
|
78
|
+
const CANCEL = 3;
|
|
79
|
+
|
|
26
80
|
describe('UiTabs', () => {
|
|
27
|
-
it(
|
|
28
|
-
const {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
expect(
|
|
81
|
+
it("merges each part's class with its own", async () => {
|
|
82
|
+
const { container, trigger, panel } = await renderTabs();
|
|
83
|
+
// Each host element carries the given class too, so look for the view
|
|
84
|
+
// that has both its own and the given class.
|
|
85
|
+
expect(container.querySelector('.flex-col.w-80')).not.toBeNull();
|
|
86
|
+
expect(container.querySelector('.rounded-lg.mb-2')).not.toBeNull();
|
|
87
|
+
expect(trigger('Account').classList).toContain('rounded-sm');
|
|
88
|
+
expect(trigger('Account').classList).toContain('px-4');
|
|
89
|
+
expect(panel('Account panel').classList).toContain('mt-2');
|
|
90
|
+
expect(panel('Account panel').classList).toContain('gap-2');
|
|
32
91
|
});
|
|
33
92
|
|
|
34
|
-
it(
|
|
35
|
-
const {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
inst.select('x');
|
|
40
|
-
expect(inst.value()).toBe('x');
|
|
41
|
-
expect(emitted).toEqual(['x']);
|
|
42
|
-
});
|
|
93
|
+
it("shows only the selected tab's panel, and highlights its trigger", async () => {
|
|
94
|
+
const { getByText, trigger, displayOf } = await renderTabs();
|
|
95
|
+
expect(displayOf('Account panel')).toBe('flex');
|
|
96
|
+
expect(displayOf('Billing panel')).toBe('none');
|
|
97
|
+
expect(displayOf('Contact panel')).toBe('none');
|
|
43
98
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
inst.registerTab('b');
|
|
49
|
-
inst.registerTab('a'); // duplicate, should be ignored
|
|
50
|
-
// Seed the effect with a known previousValue so subsequent transitions
|
|
51
|
-
// exercise the direction-set branch (not the initial-run early return).
|
|
52
|
-
inst.value.set('a');
|
|
53
|
-
await waitForUpdate();
|
|
54
|
-
// a=0, b=1 → nextIndex > prevIndex → direction=1 (forward branch)
|
|
55
|
-
inst.value.set('b');
|
|
56
|
-
await waitForUpdate();
|
|
57
|
-
await waitForUpdate();
|
|
58
|
-
expect(inst.direction()).toBe(1);
|
|
59
|
-
// Reverse → direction=-1 (backward branch)
|
|
60
|
-
inst.value.set('a');
|
|
61
|
-
await waitForUpdate();
|
|
62
|
-
await waitForUpdate();
|
|
63
|
-
expect(inst.direction()).toBe(-1);
|
|
99
|
+
expect(trigger('Account').classList).toContain('bg-background');
|
|
100
|
+
expect(getByText('Account').classList).toContain('text-foreground');
|
|
101
|
+
expect(trigger('Billing').classList).toContain('bg-transparent');
|
|
102
|
+
expect(getByText('Billing').classList).toContain('text-muted-foreground');
|
|
64
103
|
});
|
|
65
104
|
|
|
66
|
-
it('
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
expect(
|
|
105
|
+
it('selects a tab when its trigger is tapped', async () => {
|
|
106
|
+
const { host, tap, trigger, displayOf } = await renderTabs();
|
|
107
|
+
await tap('Billing');
|
|
108
|
+
expect(host.value()).toBe('billing');
|
|
109
|
+
expect(host.changes).toEqual(['billing']);
|
|
110
|
+
expect(displayOf('Account panel')).toBe('none');
|
|
111
|
+
expect(displayOf('Billing panel')).toBe('flex');
|
|
112
|
+
expect(trigger('Billing').classList).toContain('bg-background');
|
|
113
|
+
expect(trigger('Account').classList).toContain('bg-transparent');
|
|
75
114
|
});
|
|
76
115
|
|
|
77
|
-
it('
|
|
78
|
-
const {
|
|
79
|
-
|
|
80
|
-
inst.registerTab('a');
|
|
81
|
-
inst.registerTab('b');
|
|
82
|
-
inst.value.set('unknown');
|
|
116
|
+
it('shows the tab its value is set to, without reporting a change', async () => {
|
|
117
|
+
const { host, displayOf } = await renderTabs();
|
|
118
|
+
host.value.set('contact');
|
|
83
119
|
await waitForUpdate();
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
120
|
+
expect(displayOf('Contact panel')).toBe('flex');
|
|
121
|
+
expect(displayOf('Account panel')).toBe('none');
|
|
122
|
+
// `changed` reports what the user selects, not what the app sets.
|
|
123
|
+
expect(host.changes).toEqual([]);
|
|
87
124
|
});
|
|
88
125
|
|
|
89
|
-
it('
|
|
90
|
-
const {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
126
|
+
it('keeps its slide direction for a value with no trigger', async () => {
|
|
127
|
+
const { host, tap } = await renderTabs();
|
|
128
|
+
await tap('Contact');
|
|
129
|
+
await tap('Billing');
|
|
130
|
+
expect(host.tabs().direction()).toBe(-1);
|
|
131
|
+
|
|
132
|
+
// Neither moving to nor moving from a value without a trigger has a
|
|
133
|
+
// place in the tab order to slide from.
|
|
134
|
+
host.value.set('archived');
|
|
95
135
|
await waitForUpdate();
|
|
96
|
-
|
|
136
|
+
expect(host.tabs().direction()).toBe(-1);
|
|
137
|
+
host.value.set('contact');
|
|
97
138
|
await waitForUpdate();
|
|
98
|
-
expect(
|
|
139
|
+
expect(host.tabs().direction()).toBe(-1);
|
|
99
140
|
});
|
|
100
|
-
});
|
|
101
141
|
|
|
102
|
-
describe('
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
142
|
+
describe('animations', () => {
|
|
143
|
+
// Watched per test: the testing library resets the main thread after each.
|
|
144
|
+
let animate: MockInstance<LynxMainThread['__ElementAnimate']>;
|
|
145
|
+
beforeEach(() => {
|
|
146
|
+
animate = vi.spyOn(lynxMainThread(), '__ElementAnimate');
|
|
147
|
+
});
|
|
148
|
+
afterEach(() => animate.mockRestore());
|
|
109
149
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
|
|
150
|
+
/**
|
|
151
|
+
* The keyframes of the animations started on an element.
|
|
152
|
+
*/
|
|
153
|
+
const keyframesOn = (element: Element) =>
|
|
154
|
+
animate.mock.calls
|
|
155
|
+
.filter(
|
|
156
|
+
([target, [operation]]) => target === element && operation === START,
|
|
157
|
+
)
|
|
158
|
+
.map(([, [, , keyframes]]) => keyframes);
|
|
115
159
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
await waitForUpdate();
|
|
126
|
-
await waitForUpdate();
|
|
127
|
-
return { tabs, trigger, triggerResult };
|
|
128
|
-
};
|
|
160
|
+
/**
|
|
161
|
+
* The keys of the animations started on an element.
|
|
162
|
+
*/
|
|
163
|
+
const keysOn = (element: Element) =>
|
|
164
|
+
animate.mock.calls
|
|
165
|
+
.filter(
|
|
166
|
+
([target, [operation]]) => target === element && operation === START,
|
|
167
|
+
)
|
|
168
|
+
.map(([, [, key]]) => key);
|
|
129
169
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
170
|
+
const reveal = [
|
|
171
|
+
{ transform: 'translateY(6px)', opacity: 0 },
|
|
172
|
+
{ transform: 'translateY(0)', opacity: 1 },
|
|
173
|
+
];
|
|
174
|
+
const slideFrom = (x: number) => [
|
|
175
|
+
{ transform: `translateX(${x}px)`, opacity: 0 },
|
|
176
|
+
{ transform: 'translateX(0px)', opacity: 1 },
|
|
177
|
+
];
|
|
178
|
+
const activate = [
|
|
179
|
+
{ transform: 'scaleX(0.95)', opacity: 0.7 },
|
|
180
|
+
{ transform: 'scaleX(1)', opacity: 1 },
|
|
181
|
+
];
|
|
182
|
+
const deactivate = [
|
|
183
|
+
{ transform: 'scaleX(1)', opacity: 1 },
|
|
184
|
+
{ transform: 'scaleX(0.97)', opacity: 0.7 },
|
|
185
|
+
];
|
|
135
186
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
tabs.value.set('a');
|
|
143
|
-
await waitForUpdate();
|
|
144
|
-
await waitForUpdate();
|
|
145
|
-
// Deactivation branch.
|
|
146
|
-
tabs.value.set('b');
|
|
147
|
-
await waitForUpdate();
|
|
148
|
-
await waitForUpdate();
|
|
149
|
-
expect(tabs.value()).toBe('b');
|
|
150
|
-
});
|
|
151
|
-
});
|
|
187
|
+
it('reveals a panel the first time it shows, then slides it in from the side of its tab', async () => {
|
|
188
|
+
const { panel, tap } = await renderTabs();
|
|
189
|
+
// The panel waits a macrotask so its display has applied before it
|
|
190
|
+
// animates; this update lets that run.
|
|
191
|
+
await waitForUpdate();
|
|
192
|
+
expect(keyframesOn(panel('Account panel'))).toEqual([reveal]);
|
|
152
193
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const tabs = tabsResult.componentRef.instance as UiTabs;
|
|
157
|
-
tabs.registerTab('a');
|
|
158
|
-
tabs.registerTab('b');
|
|
194
|
+
await tap('Contact');
|
|
195
|
+
await waitForUpdate();
|
|
196
|
+
expect(keyframesOn(panel('Contact panel'))).toEqual([reveal]);
|
|
159
197
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
198
|
+
// Account is left of Contact, so its panel slides in from the left.
|
|
199
|
+
await tap('Account');
|
|
200
|
+
await waitForUpdate();
|
|
201
|
+
expect(keyframesOn(panel('Account panel'))).toEqual([
|
|
202
|
+
reveal,
|
|
203
|
+
slideFrom(-24),
|
|
204
|
+
]);
|
|
205
|
+
// Showing it again stopped its earlier reveal first.
|
|
206
|
+
const [revealKey] = keysOn(panel('Account panel'));
|
|
207
|
+
expect(animate).toHaveBeenCalledWith(panel('Account panel'), [
|
|
208
|
+
CANCEL,
|
|
209
|
+
revealKey,
|
|
210
|
+
]);
|
|
211
|
+
|
|
212
|
+
// Contact is right of Account, so its panel slides in from the right.
|
|
213
|
+
await tap('Contact');
|
|
214
|
+
await waitForUpdate();
|
|
215
|
+
expect(keyframesOn(panel('Contact panel'))).toEqual([
|
|
216
|
+
reveal,
|
|
217
|
+
slideFrom(24),
|
|
218
|
+
]);
|
|
168
219
|
});
|
|
169
220
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
await waitForUpdate();
|
|
221
|
+
it('scales a trigger up when selected and down when deselected', async () => {
|
|
222
|
+
const { trigger, tap } = await renderTabs();
|
|
223
|
+
// Nothing changed selection yet, so no trigger animates.
|
|
224
|
+
expect(keyframesOn(trigger('Account'))).toEqual([]);
|
|
175
225
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
tabs.value.set('a');
|
|
180
|
-
await waitForUpdate();
|
|
181
|
-
await waitForUpdate();
|
|
226
|
+
await tap('Billing');
|
|
227
|
+
expect(keyframesOn(trigger('Billing'))).toEqual([activate]);
|
|
228
|
+
expect(keyframesOn(trigger('Account'))).toEqual([deactivate]);
|
|
182
229
|
|
|
183
|
-
|
|
184
|
-
|
|
230
|
+
await tap('Account');
|
|
231
|
+
expect(keyframesOn(trigger('Account'))).toEqual([deactivate, activate]);
|
|
232
|
+
// Each animation stops the trigger's previous one.
|
|
233
|
+
const [deactivateKey] = keysOn(trigger('Account'));
|
|
234
|
+
expect(animate).toHaveBeenCalledWith(trigger('Account'), [
|
|
235
|
+
CANCEL,
|
|
236
|
+
deactivateKey,
|
|
237
|
+
]);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it("doesn't animate a selection that changed back within one frame", async () => {
|
|
241
|
+
const { host, trigger, tap } = await renderTabs();
|
|
242
|
+
await tap('Billing');
|
|
243
|
+
await waitForUpdate();
|
|
244
|
+
animate.mockClear();
|
|
185
245
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
246
|
+
// Two taps before the next update: Billing is selected again.
|
|
247
|
+
fireEvent.tap(trigger('Contact'));
|
|
248
|
+
fireEvent.tap(trigger('Billing'));
|
|
249
|
+
await waitForUpdate();
|
|
250
|
+
await waitForUpdate();
|
|
251
|
+
expect(host.changes).toEqual(['billing', 'contact', 'billing']);
|
|
252
|
+
expect(animate).not.toHaveBeenCalled();
|
|
253
|
+
// The direction still points the way Billing was reached, from Account.
|
|
254
|
+
expect(host.tabs().direction()).toBe(1);
|
|
191
255
|
});
|
|
192
|
-
const content = contentResult.componentRef.instance as UiTabsContent;
|
|
193
|
-
setInputSignal(content.contentValue, 'a');
|
|
194
|
-
tabs.value.set('a');
|
|
195
|
-
await waitForUpdate();
|
|
196
|
-
await waitForUpdate();
|
|
197
|
-
expect(tabs.value()).toBe('a');
|
|
198
256
|
});
|
|
199
257
|
});
|