@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,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type ElementRef,
|
|
3
|
+
type OnDestroy,
|
|
3
4
|
Component,
|
|
4
5
|
ViewEncapsulation,
|
|
5
6
|
computed,
|
|
@@ -29,7 +30,6 @@ import { cn } from '../../utils/cn';
|
|
|
29
30
|
|
|
30
31
|
@Component({
|
|
31
32
|
selector: 'ui-action-sheet',
|
|
32
|
-
standalone: true,
|
|
33
33
|
imports: [LYNX_ELEMENTS],
|
|
34
34
|
encapsulation: ViewEncapsulation.None,
|
|
35
35
|
template: `
|
|
@@ -37,9 +37,9 @@ import { cn } from '../../utils/cn';
|
|
|
37
37
|
<!-- bg-black/50 dims the content behind the sheet. The fadeIn/fadeOut in
|
|
38
38
|
#animateIn/#animateOut already tween this element's opacity over
|
|
39
39
|
DURATION.normal, so the dim animates in lockstep with the panel slide —
|
|
40
|
-
matching the dialog/bottom-sheet backdrop.
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
matching the dialog/bottom-sheet backdrop. It's a named color, not a
|
|
41
|
+
theme one, because the dim is black in light and dark mode alike;
|
|
42
|
+
bg-black/50 compiles to rgb(0 0 0 / 0.5), which Lynx accepts. -->
|
|
43
43
|
<view
|
|
44
44
|
#backdrop
|
|
45
45
|
class="h-full w-full bg-black/50"
|
|
@@ -49,6 +49,7 @@ import { cn } from '../../utils/cn';
|
|
|
49
49
|
#panel
|
|
50
50
|
[class]="panelClass()"
|
|
51
51
|
[style]="panelPositionStyle()"
|
|
52
|
+
[accessibility-exclusive-focus]="overlayVisible()"
|
|
52
53
|
(catchtap)="onPanelTap()"
|
|
53
54
|
>
|
|
54
55
|
<!-- The elevation shadow is an inline rgba() box-shadow rather than a
|
|
@@ -72,7 +73,7 @@ import { cn } from '../../utils/cn';
|
|
|
72
73
|
</overlay>
|
|
73
74
|
`,
|
|
74
75
|
})
|
|
75
|
-
export class UiActionSheet {
|
|
76
|
+
export class UiActionSheet implements OnDestroy {
|
|
76
77
|
readonly open = model(false);
|
|
77
78
|
readonly userClass = input<string>('', { alias: 'class' });
|
|
78
79
|
|
|
@@ -91,27 +92,36 @@ export class UiActionSheet {
|
|
|
91
92
|
: 'position: fixed; overflow: visible; width: 100vw; height: 100vh; top: 0; left: 0; z-index: 999; display: none;',
|
|
92
93
|
);
|
|
93
94
|
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
// Required: both are always in the template (the overlay is hidden, never
|
|
96
|
+
// removed), and nothing reads them before the first render.
|
|
97
|
+
readonly backdropRef = viewChild.required<ElementRef>('backdrop');
|
|
98
|
+
readonly panelRef = viewChild.required<ElementRef>('panel');
|
|
96
99
|
#backdropAnim?: AnimationHandle;
|
|
97
100
|
#panelAnim?: AnimationHandle;
|
|
98
101
|
#hasBeenOpen = false;
|
|
102
|
+
// The open and close sequences' pending timers, so ngOnDestroy can stop
|
|
103
|
+
// them.
|
|
104
|
+
readonly #timers = new Set<ReturnType<typeof setTimeout>>();
|
|
99
105
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
106
|
+
/**
|
|
107
|
+
* Opens or closes the action sheet as `open` changes. A field rather than a
|
|
108
|
+
* constructor: Angular's test build keeps a function for a constructor that
|
|
109
|
+
* nothing calls, which an app's coverage report would show as uncovered.
|
|
110
|
+
*
|
|
111
|
+
* `#hasBeenOpen` prevents the close animation from running on the initial
|
|
112
|
+
* effect evaluation when `open` starts as false. Without this guard, the
|
|
113
|
+
* first run would call #doClose() and emit `closed` before the action
|
|
114
|
+
* sheet has ever been opened.
|
|
115
|
+
*/
|
|
116
|
+
protected readonly openOrClose = effect(() => {
|
|
117
|
+
const isOpen = this.open();
|
|
118
|
+
if (isOpen) {
|
|
119
|
+
this.#hasBeenOpen = true;
|
|
120
|
+
this.#doOpen();
|
|
121
|
+
} else if (this.#hasBeenOpen) {
|
|
122
|
+
this.#doClose();
|
|
123
|
+
}
|
|
124
|
+
});
|
|
115
125
|
|
|
116
126
|
protected readonly panelClass = computed(() =>
|
|
117
127
|
cn('w-full flex-col gap-2 px-4 pb-6 flex', this.userClass()),
|
|
@@ -137,15 +147,37 @@ export class UiActionSheet {
|
|
|
137
147
|
*/
|
|
138
148
|
protected onPanelTap(): void {}
|
|
139
149
|
|
|
150
|
+
/**
|
|
151
|
+
* The action sheet can be destroyed while its open or close sequence is still
|
|
152
|
+
* running, for example by an `@if` around it or a route change right after
|
|
153
|
+
* closing it. The rest of the sequence then ran on the destroyed component:
|
|
154
|
+
* it animated detached elements and emitted `closed` from a destroyed
|
|
155
|
+
* output, which Angular warns about in dev builds (NG0953).
|
|
156
|
+
*/
|
|
157
|
+
ngOnDestroy(): void {
|
|
158
|
+
for (const timer of this.#timers) clearTimeout(timer);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* `setTimeout`, tracked so that ngOnDestroy can cancel it.
|
|
163
|
+
*/
|
|
164
|
+
#later(callback: () => void, ms: number): void {
|
|
165
|
+
const timer = setTimeout(() => {
|
|
166
|
+
this.#timers.delete(timer);
|
|
167
|
+
callback();
|
|
168
|
+
}, ms);
|
|
169
|
+
this.#timers.add(timer);
|
|
170
|
+
}
|
|
171
|
+
|
|
140
172
|
/**
|
|
141
173
|
* Two-phase open: make overlay visible first (so native elements exist in
|
|
142
174
|
* the tree), then animate on the next frame. See nav-drawer for the same
|
|
143
175
|
* pattern — Lynx animate() requires elements to be mounted before use.
|
|
144
176
|
*/
|
|
145
177
|
#doOpen(): void {
|
|
146
|
-
|
|
178
|
+
this.#later(() => {
|
|
147
179
|
this.overlayVisible.set(true);
|
|
148
|
-
|
|
180
|
+
this.#later(() => this.#animateIn(), 0);
|
|
149
181
|
}, 0);
|
|
150
182
|
}
|
|
151
183
|
|
|
@@ -154,9 +186,9 @@ export class UiActionSheet {
|
|
|
154
186
|
* causing elements to disappear before the animation finishes.
|
|
155
187
|
*/
|
|
156
188
|
#doClose(): void {
|
|
157
|
-
|
|
189
|
+
this.#later(() => {
|
|
158
190
|
this.#animateOut();
|
|
159
|
-
|
|
191
|
+
this.#later(() => {
|
|
160
192
|
this.overlayVisible.set(false);
|
|
161
193
|
this.closed.emit();
|
|
162
194
|
}, DURATION.normal + 20);
|
|
@@ -164,14 +196,18 @@ export class UiActionSheet {
|
|
|
164
196
|
}
|
|
165
197
|
|
|
166
198
|
#animateIn(): void {
|
|
167
|
-
const backdrop = this.backdropRef()
|
|
168
|
-
const panel = this.panelRef()
|
|
169
|
-
if (!backdrop || !panel) return;
|
|
199
|
+
const backdrop = this.backdropRef().nativeElement;
|
|
200
|
+
const panel = this.panelRef().nativeElement;
|
|
170
201
|
|
|
171
202
|
this.#backdropAnim?.cancel();
|
|
172
203
|
this.#panelAnim?.cancel();
|
|
173
204
|
|
|
174
205
|
this.#backdropAnim = fadeIn(backdrop, { duration: DURATION.normal });
|
|
206
|
+
// Move a screen reader into the panel. It would otherwise stay on whatever
|
|
207
|
+
// opened it, which is now behind the overlay. With the panel's
|
|
208
|
+
// accessibility-exclusive-focus (see the template), it then can't leave
|
|
209
|
+
// the panel until it closes.
|
|
210
|
+
panel.invoke?.('requestAccessibilityFocus');
|
|
175
211
|
this.#panelAnim = slideIn(panel, 'up', {
|
|
176
212
|
duration: DURATION.slow,
|
|
177
213
|
easing: EASING.sheet,
|
|
@@ -179,9 +215,8 @@ export class UiActionSheet {
|
|
|
179
215
|
}
|
|
180
216
|
|
|
181
217
|
#animateOut(): void {
|
|
182
|
-
const backdrop = this.backdropRef()
|
|
183
|
-
const panel = this.panelRef()
|
|
184
|
-
if (!backdrop || !panel) return;
|
|
218
|
+
const backdrop = this.backdropRef().nativeElement;
|
|
219
|
+
const panel = this.panelRef().nativeElement;
|
|
185
220
|
|
|
186
221
|
this.#backdropAnim?.cancel();
|
|
187
222
|
this.#panelAnim?.cancel();
|
|
@@ -196,7 +231,6 @@ export class UiActionSheet {
|
|
|
196
231
|
|
|
197
232
|
@Component({
|
|
198
233
|
selector: 'ui-action-sheet-title',
|
|
199
|
-
standalone: true,
|
|
200
234
|
imports: [LYNX_ELEMENTS],
|
|
201
235
|
encapsulation: ViewEncapsulation.None,
|
|
202
236
|
template: `
|
|
@@ -219,7 +253,6 @@ export class UiActionSheetTitle {
|
|
|
219
253
|
|
|
220
254
|
@Component({
|
|
221
255
|
selector: 'ui-action-sheet-item',
|
|
222
|
-
standalone: true,
|
|
223
256
|
imports: [LYNX_ELEMENTS],
|
|
224
257
|
encapsulation: ViewEncapsulation.None,
|
|
225
258
|
template: `
|
|
@@ -246,7 +279,8 @@ export class UiActionSheetItem {
|
|
|
246
279
|
|
|
247
280
|
readonly pressed = output<void>();
|
|
248
281
|
|
|
249
|
-
|
|
282
|
+
// Required: the container is always in the template.
|
|
283
|
+
readonly containerRef = viewChild.required<ElementRef>('container');
|
|
250
284
|
#pressAnim?: AnimationHandle;
|
|
251
285
|
|
|
252
286
|
protected readonly containerClass = computed(() =>
|
|
@@ -266,19 +300,19 @@ export class UiActionSheetItem {
|
|
|
266
300
|
protected onPressStart(): void {
|
|
267
301
|
this.#pressAnim?.cancel();
|
|
268
302
|
this.#pressAnim = pressDown(
|
|
269
|
-
this.containerRef()
|
|
303
|
+
this.containerRef().nativeElement,
|
|
270
304
|
SCALE.pressDownLight,
|
|
271
305
|
);
|
|
272
306
|
}
|
|
273
307
|
|
|
274
308
|
protected onPressEnd(): void {
|
|
275
309
|
this.#pressAnim?.cancel();
|
|
276
|
-
this.#pressAnim = pressRelease(this.containerRef()
|
|
310
|
+
this.#pressAnim = pressRelease(this.containerRef().nativeElement);
|
|
277
311
|
}
|
|
278
312
|
|
|
279
313
|
protected onPressCancel(): void {
|
|
280
314
|
this.#pressAnim?.cancel();
|
|
281
|
-
this.#pressAnim = pressRelease(this.containerRef()
|
|
315
|
+
this.#pressAnim = pressRelease(this.containerRef().nativeElement);
|
|
282
316
|
}
|
|
283
317
|
|
|
284
318
|
protected onTap(): void {
|
|
@@ -289,7 +323,6 @@ export class UiActionSheetItem {
|
|
|
289
323
|
|
|
290
324
|
@Component({
|
|
291
325
|
selector: 'ui-action-sheet-cancel',
|
|
292
|
-
standalone: true,
|
|
293
326
|
imports: [LYNX_ELEMENTS],
|
|
294
327
|
encapsulation: ViewEncapsulation.None,
|
|
295
328
|
template: `
|
|
@@ -315,7 +348,8 @@ export class UiActionSheetCancel {
|
|
|
315
348
|
readonly label = input('Cancel');
|
|
316
349
|
readonly userClass = input<string>('', { alias: 'class' });
|
|
317
350
|
|
|
318
|
-
|
|
351
|
+
// Required: the container is always in the template.
|
|
352
|
+
readonly containerRef = viewChild.required<ElementRef>('container');
|
|
319
353
|
#pressAnim?: AnimationHandle;
|
|
320
354
|
|
|
321
355
|
protected readonly containerClass = computed(() =>
|
|
@@ -332,19 +366,19 @@ export class UiActionSheetCancel {
|
|
|
332
366
|
protected onPressStart(): void {
|
|
333
367
|
this.#pressAnim?.cancel();
|
|
334
368
|
this.#pressAnim = pressDown(
|
|
335
|
-
this.containerRef()
|
|
369
|
+
this.containerRef().nativeElement,
|
|
336
370
|
SCALE.pressDownLight,
|
|
337
371
|
);
|
|
338
372
|
}
|
|
339
373
|
|
|
340
374
|
protected onPressEnd(): void {
|
|
341
375
|
this.#pressAnim?.cancel();
|
|
342
|
-
this.#pressAnim = pressRelease(this.containerRef()
|
|
376
|
+
this.#pressAnim = pressRelease(this.containerRef().nativeElement);
|
|
343
377
|
}
|
|
344
378
|
|
|
345
379
|
protected onPressCancel(): void {
|
|
346
380
|
this.#pressAnim?.cancel();
|
|
347
|
-
this.#pressAnim = pressRelease(this.containerRef()
|
|
381
|
+
this.#pressAnim = pressRelease(this.containerRef().nativeElement);
|
|
348
382
|
}
|
|
349
383
|
|
|
350
384
|
protected onTap(): void {
|
|
@@ -1,19 +1,38 @@
|
|
|
1
|
-
import { Component } from '@angular/core';
|
|
1
|
+
import { Component, signal } from '@angular/core';
|
|
2
2
|
import { render, waitForUpdate } from '@blotch/angular-lynx-testing-library';
|
|
3
3
|
import { LYNX_ELEMENTS } from '@blotch/angular-lynx';
|
|
4
|
-
import { describe, expect, it } from 'vitest';
|
|
5
|
-
import {
|
|
6
|
-
import { UiAlert, alertVariants } from './alert';
|
|
4
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
5
|
+
import { lynxMainThread } from '../../../test-utils/lynx-main-thread';
|
|
6
|
+
import { type AlertVariant, UiAlert, alertVariants } from './alert';
|
|
7
7
|
|
|
8
8
|
@Component({
|
|
9
|
-
standalone: true,
|
|
10
9
|
imports: [UiAlert, LYNX_ELEMENTS],
|
|
11
|
-
template:
|
|
10
|
+
template: `
|
|
11
|
+
<ui-alert
|
|
12
|
+
[variant]="variant()"
|
|
13
|
+
[title]="title()"
|
|
14
|
+
[description]="description()"
|
|
15
|
+
class="mt-2"
|
|
16
|
+
>
|
|
17
|
+
<text>Message</text>
|
|
18
|
+
</ui-alert>
|
|
19
|
+
`,
|
|
12
20
|
})
|
|
13
21
|
class AlertHost {
|
|
14
|
-
variant
|
|
22
|
+
readonly variant = signal<AlertVariant>('default');
|
|
23
|
+
readonly title = signal('');
|
|
24
|
+
readonly description = signal('');
|
|
15
25
|
}
|
|
16
26
|
|
|
27
|
+
const renderAlert = async () => {
|
|
28
|
+
const result = await render(AlertHost);
|
|
29
|
+
return {
|
|
30
|
+
...result,
|
|
31
|
+
host: result.componentRef.instance as AlertHost,
|
|
32
|
+
alert: () => result.container.querySelector('.rounded-lg')!,
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
|
|
17
36
|
describe('alertVariants', () => {
|
|
18
37
|
it('returns default variant classes', () => {
|
|
19
38
|
expect(alertVariants()).toContain('bg-background');
|
|
@@ -27,22 +46,51 @@ describe('alertVariants', () => {
|
|
|
27
46
|
});
|
|
28
47
|
|
|
29
48
|
describe('UiAlert', () => {
|
|
30
|
-
it('renders projected content', async () => {
|
|
31
|
-
const { getByText } = await
|
|
49
|
+
it('renders projected content, without a title or description', async () => {
|
|
50
|
+
const { alert, getByText } = await renderAlert();
|
|
32
51
|
expect(getByText('Message')).toBeTruthy();
|
|
52
|
+
expect(alert().querySelectorAll('text')).toHaveLength(1);
|
|
53
|
+
expect(alert().classList).toContain('mt-2');
|
|
33
54
|
});
|
|
34
55
|
|
|
35
|
-
it('renders title and description
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const { componentRef, container } = await render(UiAlert);
|
|
40
|
-
const inst = componentRef.instance as UiAlert;
|
|
41
|
-
setInputSignal(inst.title, 'Heads up');
|
|
42
|
-
setInputSignal(inst.description, 'Your download is ready.');
|
|
56
|
+
it('renders the title and description when set', async () => {
|
|
57
|
+
const { host, getByText } = await renderAlert();
|
|
58
|
+
host.title.set('Heads up');
|
|
59
|
+
host.description.set('Your download is ready.');
|
|
43
60
|
await waitForUpdate();
|
|
61
|
+
expect(getByText('Heads up').getAttribute('class')).toContain(
|
|
62
|
+
'text-foreground',
|
|
63
|
+
);
|
|
64
|
+
expect(
|
|
65
|
+
getByText('Your download is ready.').getAttribute('class'),
|
|
66
|
+
).toContain('text-muted-foreground');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('colors every part for the destructive variant', async () => {
|
|
70
|
+
const { host, alert, getByText } = await renderAlert();
|
|
71
|
+
host.variant.set('destructive');
|
|
72
|
+
host.title.set('Error');
|
|
73
|
+
host.description.set('Something went wrong.');
|
|
74
|
+
await waitForUpdate();
|
|
75
|
+
expect(alert().classList).toContain('border-destructive');
|
|
76
|
+
expect(getByText('Error').classList).toContain('text-destructive');
|
|
77
|
+
expect(getByText('Something went wrong.').classList).toContain(
|
|
78
|
+
'text-destructive',
|
|
79
|
+
);
|
|
80
|
+
});
|
|
44
81
|
|
|
45
|
-
|
|
46
|
-
|
|
82
|
+
it('reveals itself on first render', async () => {
|
|
83
|
+
const animate = vi.spyOn(lynxMainThread(), '__ElementAnimate');
|
|
84
|
+
const { alert } = await renderAlert();
|
|
85
|
+
expect(animate).toHaveBeenCalledWith(alert(), [
|
|
86
|
+
0, // Starts an animation.
|
|
87
|
+
expect.any(String),
|
|
88
|
+
[
|
|
89
|
+
{ transform: 'translateY(4px)', opacity: 0 },
|
|
90
|
+
{ transform: 'translateY(0)', opacity: 1 },
|
|
91
|
+
],
|
|
92
|
+
expect.any(Object),
|
|
93
|
+
]);
|
|
94
|
+
animate.mockRestore();
|
|
47
95
|
});
|
|
48
96
|
});
|
|
@@ -17,9 +17,10 @@ export const alertVariants = cva('flex-col rounded-lg border p-4 flex', {
|
|
|
17
17
|
variants: {
|
|
18
18
|
variant: {
|
|
19
19
|
default: 'border-border bg-background',
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
// the
|
|
20
|
+
// A solid destructive border over red at 10%. The tint is the
|
|
21
|
+
// pre-composed bg-destructive-subtle, not bg-destructive/10: a modifier
|
|
22
|
+
// needs the theme's --destructive-rgb, which themes copied before it
|
|
23
|
+
// existed don't have.
|
|
23
24
|
destructive: 'border-destructive bg-destructive-subtle',
|
|
24
25
|
},
|
|
25
26
|
},
|
|
@@ -75,20 +76,17 @@ export class UiAlert {
|
|
|
75
76
|
readonly description = input<string>('');
|
|
76
77
|
readonly userClass = input<string>('', { alias: 'class' });
|
|
77
78
|
|
|
78
|
-
readonly containerRef = viewChild<ElementRef>('container');
|
|
79
|
+
readonly containerRef = viewChild.required<ElementRef>('container');
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
}
|
|
81
|
+
/**
|
|
82
|
+
* Reveals the alert with a subtle entrance on first render. A field rather
|
|
83
|
+
* than a constructor: Angular's test build keeps a function for a
|
|
84
|
+
* constructor that nothing calls, which an app's coverage report would show
|
|
85
|
+
* as uncovered.
|
|
86
|
+
*/
|
|
87
|
+
protected readonly entrance = effect(() => {
|
|
88
|
+
revealIn(this.containerRef().nativeElement, { fromY: 4 });
|
|
89
|
+
});
|
|
92
90
|
|
|
93
91
|
protected readonly containerClass = computed(() =>
|
|
94
92
|
cn(alertVariants({ variant: this.variant() }), this.userClass()),
|