@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,8 +1,23 @@
|
|
|
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 {
|
|
7
22
|
UiAccordion,
|
|
8
23
|
UiAccordionContent,
|
|
@@ -11,7 +26,6 @@ import {
|
|
|
11
26
|
} from './accordion';
|
|
12
27
|
|
|
13
28
|
@Component({
|
|
14
|
-
standalone: true,
|
|
15
29
|
imports: [
|
|
16
30
|
UiAccordion,
|
|
17
31
|
UiAccordionItem,
|
|
@@ -20,175 +34,175 @@ import {
|
|
|
20
34
|
LYNX_ELEMENTS,
|
|
21
35
|
],
|
|
22
36
|
template: `
|
|
23
|
-
<ui-accordion [type]="type">
|
|
24
|
-
<ui-accordion-item value="a">
|
|
25
|
-
<ui-accordion-trigger>
|
|
26
|
-
<ui-accordion-content
|
|
37
|
+
<ui-accordion [type]="type()" class="w-80">
|
|
38
|
+
<ui-accordion-item value="a" class="px-1">
|
|
39
|
+
<ui-accordion-trigger class="gap-2">Alpha</ui-accordion-trigger>
|
|
40
|
+
<ui-accordion-content class="pt-1">
|
|
41
|
+
<text>Alpha body</text>
|
|
42
|
+
</ui-accordion-content>
|
|
27
43
|
</ui-accordion-item>
|
|
28
44
|
<ui-accordion-item value="b">
|
|
29
|
-
<ui-accordion-trigger>
|
|
30
|
-
<ui-accordion-content
|
|
45
|
+
<ui-accordion-trigger>Beta</ui-accordion-trigger>
|
|
46
|
+
<ui-accordion-content>
|
|
47
|
+
<text>Beta body</text>
|
|
48
|
+
</ui-accordion-content>
|
|
31
49
|
</ui-accordion-item>
|
|
32
50
|
</ui-accordion>
|
|
33
51
|
`,
|
|
34
52
|
})
|
|
35
53
|
class AccordionHost {
|
|
36
|
-
type
|
|
54
|
+
readonly type = signal<'single' | 'multiple'>('single');
|
|
55
|
+
readonly accordion = viewChild.required(UiAccordion);
|
|
37
56
|
}
|
|
38
57
|
|
|
58
|
+
const renderAccordion = async () => {
|
|
59
|
+
const result = await render(AccordionHost);
|
|
60
|
+
/**
|
|
61
|
+
* An item's trigger: its own view, which holds the tap listener, around
|
|
62
|
+
* its label.
|
|
63
|
+
*/
|
|
64
|
+
const trigger = (label: string) => result.getByText(label).parentElement!;
|
|
65
|
+
return {
|
|
66
|
+
...result,
|
|
67
|
+
host: result.componentRef.instance as AccordionHost,
|
|
68
|
+
trigger,
|
|
69
|
+
tap: async (label: string) => {
|
|
70
|
+
fireEvent.tap(trigger(label));
|
|
71
|
+
await waitForUpdate();
|
|
72
|
+
},
|
|
73
|
+
/** The chevron beside an item's label. */
|
|
74
|
+
chevron: (label: string) => result.getByText(label).nextElementSibling!,
|
|
75
|
+
/** An item's content view, which is only mounted while it's expanded. */
|
|
76
|
+
content: (text: string) => result.queryByText(text)?.parentElement ?? null,
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/** `__ElementAnimate`'s first argument for starting an animation. */
|
|
81
|
+
const START = 0;
|
|
82
|
+
/** `__ElementAnimate`'s first argument for canceling an animation. */
|
|
83
|
+
const CANCEL = 3;
|
|
84
|
+
|
|
39
85
|
describe('UiAccordion', () => {
|
|
40
|
-
it(
|
|
41
|
-
const {
|
|
42
|
-
|
|
43
|
-
|
|
86
|
+
it("merges each part's class with its own", async () => {
|
|
87
|
+
const { container, trigger, tap, content } = await renderAccordion();
|
|
88
|
+
// Each host element carries the given class too, so look for the view
|
|
89
|
+
// that has both its own and the given class.
|
|
90
|
+
expect(container.querySelector('.flex-col.w-80')).not.toBeNull();
|
|
91
|
+
expect(container.querySelector('.border-b.px-1')).not.toBeNull();
|
|
92
|
+
expect(trigger('Alpha').classList).toContain('justify-between');
|
|
93
|
+
expect(trigger('Alpha').classList).toContain('gap-2');
|
|
94
|
+
|
|
95
|
+
await tap('Alpha');
|
|
96
|
+
expect(content('Alpha body')!.classList).toContain('pb-4');
|
|
97
|
+
expect(content('Alpha body')!.classList).toContain('pt-1');
|
|
44
98
|
});
|
|
45
99
|
|
|
46
|
-
it('
|
|
47
|
-
const {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
expect(
|
|
51
|
-
acc.toggle('b');
|
|
52
|
-
expect(acc.isExpanded('a')).toBe(false);
|
|
53
|
-
expect(acc.isExpanded('b')).toBe(true);
|
|
54
|
-
acc.toggle('b');
|
|
55
|
-
expect(acc.isExpanded('b')).toBe(false);
|
|
56
|
-
});
|
|
100
|
+
it('expands an item when its trigger is tapped, and collapses it on a second tap', async () => {
|
|
101
|
+
const { tap, chevron, content } = await renderAccordion();
|
|
102
|
+
// Collapsed, the content isn't mounted at all.
|
|
103
|
+
expect(content('Alpha body')).toBeNull();
|
|
104
|
+
expect(chevron('Alpha').textContent).toBe('▶');
|
|
57
105
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const { container } = await render(MultiHost);
|
|
66
|
-
expect(container).toBeTruthy();
|
|
106
|
+
await tap('Alpha');
|
|
107
|
+
expect(content('Alpha body')).not.toBeNull();
|
|
108
|
+
expect(chevron('Alpha').textContent).toBe('▼');
|
|
109
|
+
|
|
110
|
+
await tap('Alpha');
|
|
111
|
+
expect(content('Alpha body')).toBeNull();
|
|
112
|
+
expect(chevron('Alpha').textContent).toBe('▶');
|
|
67
113
|
});
|
|
68
114
|
|
|
69
|
-
it('
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
await waitForUpdate();
|
|
76
|
-
acc.toggle('a');
|
|
77
|
-
acc.toggle('b');
|
|
78
|
-
expect(acc.isExpanded('a')).toBe(true);
|
|
79
|
-
expect(acc.isExpanded('b')).toBe(true);
|
|
115
|
+
it('keeps one item expanded at a time by default', async () => {
|
|
116
|
+
const { tap, content } = await renderAccordion();
|
|
117
|
+
await tap('Alpha');
|
|
118
|
+
await tap('Beta');
|
|
119
|
+
expect(content('Alpha body')).toBeNull();
|
|
120
|
+
expect(content('Beta body')).not.toBeNull();
|
|
80
121
|
});
|
|
81
|
-
});
|
|
82
122
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
* DI. Using `render(UiAccordionItem, { providers: [...] })` alone would fail
|
|
87
|
-
* because the required `value` input has no template binding and the
|
|
88
|
-
* component's initial computed reads it — so we set the input before any
|
|
89
|
-
* effect fires. The parent instance comes from rendering UiAccordion (which
|
|
90
|
-
* sets up the internal injection context inputs) and stashing its instance.
|
|
91
|
-
*/
|
|
92
|
-
const renderItemWithParent = async () => {
|
|
93
|
-
// Render the accordion first so we have an instance with initialized signals.
|
|
94
|
-
const parentResult = await render(UiAccordion);
|
|
95
|
-
const parent = parentResult.componentRef.instance as UiAccordion;
|
|
96
|
-
|
|
97
|
-
// Now render the child with the parent as a DI value. This unmounts the
|
|
98
|
-
// previous render but the parent instance object (a plain JS class) still
|
|
99
|
-
// holds its signals.
|
|
100
|
-
const childResult = await render(UiAccordionItem, {
|
|
101
|
-
providers: [{ provide: UiAccordion, useValue: parent }],
|
|
102
|
-
});
|
|
103
|
-
const item = childResult.componentRef.instance as UiAccordionItem;
|
|
104
|
-
setInputSignal(item.itemValue, 'a');
|
|
123
|
+
it('keeps every expanded item open when its type is multiple', async () => {
|
|
124
|
+
const { host, tap, content } = await renderAccordion();
|
|
125
|
+
host.type.set('multiple');
|
|
105
126
|
await waitForUpdate();
|
|
106
|
-
return { parent, item, result: childResult };
|
|
107
|
-
};
|
|
108
127
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
expect(
|
|
128
|
+
await tap('Alpha');
|
|
129
|
+
await tap('Beta');
|
|
130
|
+
expect(content('Alpha body')).not.toBeNull();
|
|
131
|
+
expect(content('Beta body')).not.toBeNull();
|
|
113
132
|
});
|
|
114
133
|
|
|
115
|
-
it('
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const parent = parentResult.componentRef.instance as UiAccordion;
|
|
119
|
-
|
|
120
|
-
const itemResult = await render(UiAccordionItem, {
|
|
121
|
-
providers: [{ provide: UiAccordion, useValue: parent }],
|
|
122
|
-
});
|
|
123
|
-
const item = itemResult.componentRef.instance as UiAccordionItem;
|
|
124
|
-
setInputSignal(item.itemValue, 'a');
|
|
134
|
+
it('expands an item from code, and says which items are expanded', async () => {
|
|
135
|
+
const { host, content } = await renderAccordion();
|
|
136
|
+
host.accordion().toggle('b');
|
|
125
137
|
await waitForUpdate();
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
});
|
|
130
|
-
const trigger = triggerResult.componentRef.instance as UiAccordionTrigger;
|
|
131
|
-
(trigger as unknown as { onTap: () => void }).onTap();
|
|
132
|
-
expect(parent.isExpanded('a')).toBe(true);
|
|
138
|
+
expect(content('Beta body')).not.toBeNull();
|
|
139
|
+
expect(host.accordion().isExpanded('b')).toBe(true);
|
|
140
|
+
expect(host.accordion().isExpanded('a')).toBe(false);
|
|
133
141
|
});
|
|
134
142
|
|
|
135
|
-
describe('
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
parent.toggle('a');
|
|
160
|
-
await waitForUpdate();
|
|
161
|
-
await waitForUpdate(); // wait for the effect's setTimeout(_, 0) to fire
|
|
162
|
-
|
|
163
|
-
// Cancellation path: toggle off then on to re-schedule with `#anim` set.
|
|
164
|
-
parent.toggle('a');
|
|
165
|
-
await waitForUpdate();
|
|
166
|
-
parent.toggle('a');
|
|
143
|
+
describe('reveal animation', () => {
|
|
144
|
+
// Watched per test: the testing library resets the main thread after each.
|
|
145
|
+
let animate: MockInstance<LynxMainThread['__ElementAnimate']>;
|
|
146
|
+
beforeEach(() => {
|
|
147
|
+
animate = vi.spyOn(lynxMainThread(), '__ElementAnimate');
|
|
148
|
+
});
|
|
149
|
+
afterEach(() => animate.mockRestore());
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* The keys of the animations started on an element.
|
|
153
|
+
*/
|
|
154
|
+
const startedOn = (element: Element | null) =>
|
|
155
|
+
animate.mock.calls
|
|
156
|
+
.filter(
|
|
157
|
+
([target, [operation]]) => target === element && operation === START,
|
|
158
|
+
)
|
|
159
|
+
.map(([, [, key]]) => key);
|
|
160
|
+
|
|
161
|
+
it('slides the content down into place each time it expands', async () => {
|
|
162
|
+
const { tap, content } = await renderAccordion();
|
|
163
|
+
|
|
164
|
+
await tap('Alpha');
|
|
165
|
+
// The effect waits a macrotask so the content is committed to Lynx's
|
|
166
|
+
// tree before animating it; this update lets that run.
|
|
167
167
|
await waitForUpdate();
|
|
168
|
+
expect(animate).toHaveBeenCalledWith(content('Alpha body'), [
|
|
169
|
+
START,
|
|
170
|
+
expect.any(String),
|
|
171
|
+
[
|
|
172
|
+
{ transform: 'translateY(-8px)', opacity: 0 },
|
|
173
|
+
{ transform: 'translateY(0)', opacity: 1 },
|
|
174
|
+
],
|
|
175
|
+
// No fill: once it ends, the content's inline resting style applies.
|
|
176
|
+
expect.objectContaining({ fill: 'none' }),
|
|
177
|
+
]);
|
|
178
|
+
const [firstKey] = startedOn(content('Alpha body'));
|
|
179
|
+
|
|
180
|
+
await tap('Alpha');
|
|
181
|
+
await tap('Alpha');
|
|
168
182
|
await waitForUpdate();
|
|
169
|
-
|
|
183
|
+
// Expanding again stops the previous reveal before it plays a new one
|
|
184
|
+
// on the content's new view.
|
|
185
|
+
expect(animate).toHaveBeenCalledWith(expect.anything(), [
|
|
186
|
+
CANCEL,
|
|
187
|
+
firstKey,
|
|
188
|
+
]);
|
|
189
|
+
expect(startedOn(content('Alpha body'))).toHaveLength(1);
|
|
170
190
|
});
|
|
171
191
|
|
|
172
|
-
it('
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const item = itemResult.componentRef.instance as UiAccordionItem;
|
|
182
|
-
setInputSignal(item.itemValue, 'a');
|
|
183
|
-
await waitForUpdate();
|
|
192
|
+
it("doesn't animate content that collapsed before its reveal began", async () => {
|
|
193
|
+
const { componentRef, trigger, tap, content } = await renderAccordion();
|
|
194
|
+
|
|
195
|
+
// The effect has scheduled the reveal for the next macrotask.
|
|
196
|
+
await tap('Alpha');
|
|
197
|
+
// Collapse it before then, and render that straight away.
|
|
198
|
+
fireEvent.tap(trigger('Alpha'));
|
|
199
|
+
componentRef.changeDetectorRef.detectChanges();
|
|
200
|
+
expect(content('Alpha body')).toBeNull();
|
|
184
201
|
|
|
185
|
-
await render(UiAccordionContent, {
|
|
186
|
-
providers: [{ provide: UiAccordionItem, useValue: item }],
|
|
187
|
-
});
|
|
188
|
-
parent.toggle('a');
|
|
189
|
-
await waitForUpdate();
|
|
190
202
|
await waitForUpdate();
|
|
191
|
-
expect(
|
|
203
|
+
expect(
|
|
204
|
+
animate.mock.calls.filter(([, [operation]]) => operation === START),
|
|
205
|
+
).toEqual([]);
|
|
192
206
|
});
|
|
193
207
|
});
|
|
194
208
|
});
|
|
@@ -152,20 +152,25 @@ export class UiAccordionContent {
|
|
|
152
152
|
readonly contentRef = viewChild<ElementRef>('content');
|
|
153
153
|
#anim?: AnimationHandle;
|
|
154
154
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
155
|
+
/**
|
|
156
|
+
* Animates the reveal whenever the panel expands. A field rather than a
|
|
157
|
+
* constructor: Angular's test build keeps a function for a constructor that
|
|
158
|
+
* nothing calls, which an app's coverage report would show as uncovered.
|
|
159
|
+
*
|
|
160
|
+
* contentRef only resolves while the `@if` content is mounted; defer one
|
|
161
|
+
* macrotask so the freshly (re)created element is committed to the native
|
|
162
|
+
* tree before we animate it. By then the panel may have collapsed again,
|
|
163
|
+
* which leaves nothing to animate.
|
|
164
|
+
*/
|
|
165
|
+
protected readonly revealing = effect(() => {
|
|
166
|
+
if (!this.item.isExpanded()) return;
|
|
167
|
+
setTimeout(() => {
|
|
168
|
+
const el = this.contentRef()?.nativeElement;
|
|
169
|
+
if (!el) return;
|
|
170
|
+
this.#anim?.cancel();
|
|
171
|
+
this.#anim = revealIn(el, { fromY: -8, fill: 'none' });
|
|
172
|
+
}, 0);
|
|
173
|
+
});
|
|
169
174
|
|
|
170
175
|
protected readonly contentClass = computed(() =>
|
|
171
176
|
cn('flex-col pb-4 flex', this.userClass()),
|