@shwfed/nuxt 0.11.18 → 0.11.20
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/module.json +1 -1
- package/dist/runtime/components/modal.d.vue.ts +10 -8
- package/dist/runtime/components/modal.vue +2 -1
- package/dist/runtime/components/modal.vue.d.ts +10 -8
- package/dist/runtime/components/ui/app/OverlayHost.vue +9 -1
- package/dist/runtime/components/ui/dialog/DialogContent.d.vue.ts +4 -2
- package/dist/runtime/components/ui/dialog/DialogContent.vue +113 -2
- package/dist/runtime/components/ui/dialog/DialogContent.vue.d.ts +4 -2
- package/dist/runtime/components/ui/drawer/DrawerContent.d.vue.ts +7 -3
- package/dist/runtime/components/ui/drawer/DrawerContent.vue +112 -0
- package/dist/runtime/components/ui/drawer/DrawerContent.vue.d.ts +7 -3
- package/dist/runtime/composables/useOverlay.d.ts +2 -0
- package/dist/runtime/composables/useOverlay.js +31 -17
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -9,34 +9,36 @@ declare function close(): void;
|
|
|
9
9
|
declare var __VLS_14: {
|
|
10
10
|
close: typeof close;
|
|
11
11
|
isDesktop: boolean;
|
|
12
|
-
},
|
|
12
|
+
}, __VLS_36: {
|
|
13
13
|
close: typeof close;
|
|
14
14
|
isDesktop: boolean;
|
|
15
|
-
},
|
|
15
|
+
}, __VLS_44: {
|
|
16
16
|
close: typeof close;
|
|
17
17
|
isDesktop: boolean;
|
|
18
|
-
},
|
|
18
|
+
}, __VLS_46: {
|
|
19
19
|
close: typeof close;
|
|
20
20
|
isDesktop: boolean;
|
|
21
|
-
},
|
|
21
|
+
}, __VLS_54: {
|
|
22
22
|
close: typeof close;
|
|
23
23
|
isDesktop: boolean;
|
|
24
24
|
};
|
|
25
25
|
type __VLS_Slots = {} & {
|
|
26
26
|
trigger?: (props: typeof __VLS_14) => any;
|
|
27
27
|
} & {
|
|
28
|
-
title?: (props: typeof
|
|
28
|
+
title?: (props: typeof __VLS_36) => any;
|
|
29
29
|
} & {
|
|
30
|
-
description?: (props: typeof
|
|
30
|
+
description?: (props: typeof __VLS_44) => any;
|
|
31
31
|
} & {
|
|
32
|
-
default?: (props: typeof
|
|
32
|
+
default?: (props: typeof __VLS_46) => any;
|
|
33
33
|
} & {
|
|
34
|
-
footer?: (props: typeof
|
|
34
|
+
footer?: (props: typeof __VLS_54) => any;
|
|
35
35
|
};
|
|
36
36
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
37
37
|
"update:open": (open: boolean) => any;
|
|
38
|
+
"after-close": () => any;
|
|
38
39
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
39
40
|
"onUpdate:open"?: ((open: boolean) => any) | undefined;
|
|
41
|
+
"onAfter-close"?: (() => any) | undefined;
|
|
40
42
|
}>, {
|
|
41
43
|
showCloseButton: boolean;
|
|
42
44
|
breakpoint: string;
|
|
@@ -31,7 +31,7 @@ const props = defineProps({
|
|
|
31
31
|
showCloseButton: { type: Boolean, required: false, default: true },
|
|
32
32
|
dismissible: { type: Boolean, required: false, default: true }
|
|
33
33
|
});
|
|
34
|
-
const emit = defineEmits(["update:open"]);
|
|
34
|
+
const emit = defineEmits(["update:open", "after-close"]);
|
|
35
35
|
const attrs = useAttrs();
|
|
36
36
|
const slots = useSlots();
|
|
37
37
|
const uncontrolledOpen = ref(props.defaultOpen);
|
|
@@ -99,6 +99,7 @@ function close() {
|
|
|
99
99
|
:is="modalComponents.Content"
|
|
100
100
|
v-bind="attrs"
|
|
101
101
|
:show-close-button="props.showCloseButton"
|
|
102
|
+
@after-close="emit('after-close')"
|
|
102
103
|
>
|
|
103
104
|
<component
|
|
104
105
|
:is="modalComponents.Header"
|
|
@@ -9,34 +9,36 @@ declare function close(): void;
|
|
|
9
9
|
declare var __VLS_14: {
|
|
10
10
|
close: typeof close;
|
|
11
11
|
isDesktop: boolean;
|
|
12
|
-
},
|
|
12
|
+
}, __VLS_36: {
|
|
13
13
|
close: typeof close;
|
|
14
14
|
isDesktop: boolean;
|
|
15
|
-
},
|
|
15
|
+
}, __VLS_44: {
|
|
16
16
|
close: typeof close;
|
|
17
17
|
isDesktop: boolean;
|
|
18
|
-
},
|
|
18
|
+
}, __VLS_46: {
|
|
19
19
|
close: typeof close;
|
|
20
20
|
isDesktop: boolean;
|
|
21
|
-
},
|
|
21
|
+
}, __VLS_54: {
|
|
22
22
|
close: typeof close;
|
|
23
23
|
isDesktop: boolean;
|
|
24
24
|
};
|
|
25
25
|
type __VLS_Slots = {} & {
|
|
26
26
|
trigger?: (props: typeof __VLS_14) => any;
|
|
27
27
|
} & {
|
|
28
|
-
title?: (props: typeof
|
|
28
|
+
title?: (props: typeof __VLS_36) => any;
|
|
29
29
|
} & {
|
|
30
|
-
description?: (props: typeof
|
|
30
|
+
description?: (props: typeof __VLS_44) => any;
|
|
31
31
|
} & {
|
|
32
|
-
default?: (props: typeof
|
|
32
|
+
default?: (props: typeof __VLS_46) => any;
|
|
33
33
|
} & {
|
|
34
|
-
footer?: (props: typeof
|
|
34
|
+
footer?: (props: typeof __VLS_54) => any;
|
|
35
35
|
};
|
|
36
36
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
37
37
|
"update:open": (open: boolean) => any;
|
|
38
|
+
"after-close": () => any;
|
|
38
39
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
39
40
|
"onUpdate:open"?: ((open: boolean) => any) | undefined;
|
|
41
|
+
"onAfter-close"?: (() => any) | undefined;
|
|
40
42
|
}>, {
|
|
41
43
|
showCloseButton: boolean;
|
|
42
44
|
breakpoint: string;
|
|
@@ -25,6 +25,12 @@ function handleOpenUpdate(sessionId, open) {
|
|
|
25
25
|
}
|
|
26
26
|
overlay.closeSync(sessionId);
|
|
27
27
|
}
|
|
28
|
+
function handleAfterClose(sessionId) {
|
|
29
|
+
const finalizeCloseSync = Reflect.get(overlay, "finalizeCloseSync");
|
|
30
|
+
if (typeof finalizeCloseSync === "function") {
|
|
31
|
+
finalizeCloseSync(sessionId);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
28
34
|
const renderedSessions = computed(() => {
|
|
29
35
|
const nextSessions = [];
|
|
30
36
|
for (const session of overlay.sessions) {
|
|
@@ -35,6 +41,7 @@ const renderedSessions = computed(() => {
|
|
|
35
41
|
nextSessions.push({
|
|
36
42
|
sessionId: session.sessionId,
|
|
37
43
|
definitionId: session.definitionId,
|
|
44
|
+
open: session.open,
|
|
38
45
|
shell: {
|
|
39
46
|
title: session.shell.title,
|
|
40
47
|
description: session.shell.description,
|
|
@@ -57,11 +64,12 @@ const renderedSessions = computed(() => {
|
|
|
57
64
|
:key="session.sessionId"
|
|
58
65
|
>
|
|
59
66
|
<ShwfedModal
|
|
60
|
-
:open="
|
|
67
|
+
:open="session.open"
|
|
61
68
|
:breakpoint="session.shell.breakpoint"
|
|
62
69
|
:show-close-button="session.shell.showCloseButton"
|
|
63
70
|
:dismissible="session.shell.dismissible"
|
|
64
71
|
@update:open="handleOpenUpdate(session.sessionId, $event)"
|
|
72
|
+
@after-close="handleAfterClose(session.sessionId)"
|
|
65
73
|
>
|
|
66
74
|
<template
|
|
67
75
|
v-if="session.shell.title"
|
|
@@ -4,9 +4,9 @@ type __VLS_Props = DialogContentProps & {
|
|
|
4
4
|
class?: HTMLAttributes['class'];
|
|
5
5
|
showCloseButton?: boolean;
|
|
6
6
|
};
|
|
7
|
-
declare var
|
|
7
|
+
declare var __VLS_22: {};
|
|
8
8
|
type __VLS_Slots = {} & {
|
|
9
|
-
default?: (props: typeof
|
|
9
|
+
default?: (props: typeof __VLS_22) => any;
|
|
10
10
|
};
|
|
11
11
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
12
12
|
escapeKeyDown: (event: KeyboardEvent) => any;
|
|
@@ -15,6 +15,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {},
|
|
|
15
15
|
interactOutside: (event: import("reka-ui").PointerDownOutsideEvent | import("reka-ui").FocusOutsideEvent) => any;
|
|
16
16
|
openAutoFocus: (event: Event) => any;
|
|
17
17
|
closeAutoFocus: (event: Event) => any;
|
|
18
|
+
"after-close": () => any;
|
|
18
19
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
19
20
|
onEscapeKeyDown?: ((event: KeyboardEvent) => any) | undefined;
|
|
20
21
|
onPointerDownOutside?: ((event: import("reka-ui").PointerDownOutsideEvent) => any) | undefined;
|
|
@@ -22,6 +23,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {},
|
|
|
22
23
|
onInteractOutside?: ((event: import("reka-ui").PointerDownOutsideEvent | import("reka-ui").FocusOutsideEvent) => any) | undefined;
|
|
23
24
|
onOpenAutoFocus?: ((event: Event) => any) | undefined;
|
|
24
25
|
onCloseAutoFocus?: ((event: Event) => any) | undefined;
|
|
26
|
+
"onAfter-close"?: (() => any) | undefined;
|
|
25
27
|
}>, {
|
|
26
28
|
showCloseButton: boolean;
|
|
27
29
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import { cn } from "../../../utils/cn";
|
|
10
10
|
import DialogOverlay from "./DialogOverlay.vue";
|
|
11
11
|
import { Icon } from "@iconify/vue";
|
|
12
|
+
import { onBeforeUnmount, shallowRef, watchEffect } from "vue";
|
|
12
13
|
defineOptions({
|
|
13
14
|
inheritAttrs: false
|
|
14
15
|
});
|
|
@@ -20,15 +21,123 @@ const props = defineProps({
|
|
|
20
21
|
class: { type: null, required: false },
|
|
21
22
|
showCloseButton: { type: Boolean, required: false, default: true }
|
|
22
23
|
});
|
|
23
|
-
const
|
|
24
|
+
const emit = defineEmits(["escapeKeyDown", "pointerDownOutside", "focusOutside", "interactOutside", "openAutoFocus", "closeAutoFocus", "after-close"]);
|
|
24
25
|
const delegatedProps = reactiveOmit(props, "class");
|
|
25
|
-
const forwarded = useForwardPropsEmits(delegatedProps,
|
|
26
|
+
const forwarded = useForwardPropsEmits(delegatedProps, emit);
|
|
27
|
+
const contentElement = shallowRef(null);
|
|
28
|
+
let closeFallbackTimer;
|
|
29
|
+
let hasEmittedAfterClose = false;
|
|
30
|
+
function isClosedContentTarget(target) {
|
|
31
|
+
return target instanceof HTMLElement && target.dataset.state === "closed";
|
|
32
|
+
}
|
|
33
|
+
function clearCloseFallbackTimer() {
|
|
34
|
+
if (closeFallbackTimer === void 0) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
window.clearTimeout(closeFallbackTimer);
|
|
38
|
+
closeFallbackTimer = void 0;
|
|
39
|
+
}
|
|
40
|
+
function emitAfterClose() {
|
|
41
|
+
if (hasEmittedAfterClose) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
hasEmittedAfterClose = true;
|
|
45
|
+
clearCloseFallbackTimer();
|
|
46
|
+
emit("after-close");
|
|
47
|
+
}
|
|
48
|
+
function parseDurationMs(value) {
|
|
49
|
+
const normalizedValue = value.trim();
|
|
50
|
+
if (normalizedValue.endsWith("ms")) {
|
|
51
|
+
const duration = Number.parseFloat(normalizedValue.slice(0, -2));
|
|
52
|
+
return Number.isFinite(duration) ? duration : 0;
|
|
53
|
+
}
|
|
54
|
+
if (normalizedValue.endsWith("s")) {
|
|
55
|
+
const duration = Number.parseFloat(normalizedValue.slice(0, -1));
|
|
56
|
+
return Number.isFinite(duration) ? duration * 1e3 : 0;
|
|
57
|
+
}
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
function getLongestMotionMs(element) {
|
|
61
|
+
const style = window.getComputedStyle(element);
|
|
62
|
+
const animationDurations = style.animationDuration.split(",");
|
|
63
|
+
const animationDelays = style.animationDelay.split(",");
|
|
64
|
+
const transitionDurations = style.transitionDuration.split(",");
|
|
65
|
+
const transitionDelays = style.transitionDelay.split(",");
|
|
66
|
+
let longestMotionMs = 0;
|
|
67
|
+
for (const [index, durationValue] of animationDurations.entries()) {
|
|
68
|
+
const durationMs = parseDurationMs(durationValue);
|
|
69
|
+
const delayMs = parseDurationMs(animationDelays[index] ?? animationDelays[0] ?? "0s");
|
|
70
|
+
longestMotionMs = Math.max(longestMotionMs, durationMs + delayMs);
|
|
71
|
+
}
|
|
72
|
+
for (const [index, durationValue] of transitionDurations.entries()) {
|
|
73
|
+
const durationMs = parseDurationMs(durationValue);
|
|
74
|
+
const delayMs = parseDurationMs(transitionDelays[index] ?? transitionDelays[0] ?? "0s");
|
|
75
|
+
longestMotionMs = Math.max(longestMotionMs, durationMs + delayMs);
|
|
76
|
+
}
|
|
77
|
+
return longestMotionMs;
|
|
78
|
+
}
|
|
79
|
+
function syncCloseFallback() {
|
|
80
|
+
const element = contentElement.value;
|
|
81
|
+
clearCloseFallbackTimer();
|
|
82
|
+
if (!element) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (element.dataset.state !== "closed") {
|
|
86
|
+
hasEmittedAfterClose = false;
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const motionMs = getLongestMotionMs(element);
|
|
90
|
+
closeFallbackTimer = window.setTimeout(() => {
|
|
91
|
+
emitAfterClose();
|
|
92
|
+
}, motionMs > 0 ? motionMs : 0);
|
|
93
|
+
}
|
|
94
|
+
function handleCloseMotionEnd(event) {
|
|
95
|
+
if (hasEmittedAfterClose || event.target !== event.currentTarget || !isClosedContentTarget(event.currentTarget)) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
emitAfterClose();
|
|
99
|
+
}
|
|
100
|
+
function setContentElement(target) {
|
|
101
|
+
if (target instanceof HTMLElement) {
|
|
102
|
+
contentElement.value = target;
|
|
103
|
+
syncCloseFallback();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (target && "$el" in target && target.$el instanceof HTMLElement) {
|
|
107
|
+
contentElement.value = target.$el;
|
|
108
|
+
syncCloseFallback();
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
contentElement.value = null;
|
|
112
|
+
clearCloseFallbackTimer();
|
|
113
|
+
}
|
|
114
|
+
watchEffect((onCleanup) => {
|
|
115
|
+
const element = contentElement.value;
|
|
116
|
+
if (!element) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const observer = new MutationObserver(() => {
|
|
120
|
+
syncCloseFallback();
|
|
121
|
+
});
|
|
122
|
+
observer.observe(element, {
|
|
123
|
+
attributes: true,
|
|
124
|
+
attributeFilter: ["data-state"]
|
|
125
|
+
});
|
|
126
|
+
syncCloseFallback();
|
|
127
|
+
onCleanup(() => {
|
|
128
|
+
observer.disconnect();
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
onBeforeUnmount(() => {
|
|
132
|
+
clearCloseFallbackTimer();
|
|
133
|
+
});
|
|
26
134
|
</script>
|
|
27
135
|
|
|
28
136
|
<template>
|
|
29
137
|
<DialogPortal>
|
|
30
138
|
<DialogOverlay />
|
|
31
139
|
<DialogContent
|
|
140
|
+
:ref="setContentElement"
|
|
32
141
|
data-slot="dialog-content"
|
|
33
142
|
v-bind="{ ...$attrs, ...forwarded }"
|
|
34
143
|
:class="
|
|
@@ -37,6 +146,8 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
|
37
146
|
props.class
|
|
38
147
|
)
|
|
39
148
|
"
|
|
149
|
+
@animationend="handleCloseMotionEnd"
|
|
150
|
+
@transitionend="handleCloseMotionEnd"
|
|
40
151
|
>
|
|
41
152
|
<slot />
|
|
42
153
|
|
|
@@ -4,9 +4,9 @@ type __VLS_Props = DialogContentProps & {
|
|
|
4
4
|
class?: HTMLAttributes['class'];
|
|
5
5
|
showCloseButton?: boolean;
|
|
6
6
|
};
|
|
7
|
-
declare var
|
|
7
|
+
declare var __VLS_22: {};
|
|
8
8
|
type __VLS_Slots = {} & {
|
|
9
|
-
default?: (props: typeof
|
|
9
|
+
default?: (props: typeof __VLS_22) => any;
|
|
10
10
|
};
|
|
11
11
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
12
12
|
escapeKeyDown: (event: KeyboardEvent) => any;
|
|
@@ -15,6 +15,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {},
|
|
|
15
15
|
interactOutside: (event: import("reka-ui").PointerDownOutsideEvent | import("reka-ui").FocusOutsideEvent) => any;
|
|
16
16
|
openAutoFocus: (event: Event) => any;
|
|
17
17
|
closeAutoFocus: (event: Event) => any;
|
|
18
|
+
"after-close": () => any;
|
|
18
19
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
19
20
|
onEscapeKeyDown?: ((event: KeyboardEvent) => any) | undefined;
|
|
20
21
|
onPointerDownOutside?: ((event: import("reka-ui").PointerDownOutsideEvent) => any) | undefined;
|
|
@@ -22,6 +23,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {},
|
|
|
22
23
|
onInteractOutside?: ((event: import("reka-ui").PointerDownOutsideEvent | import("reka-ui").FocusOutsideEvent) => any) | undefined;
|
|
23
24
|
onOpenAutoFocus?: ((event: Event) => any) | undefined;
|
|
24
25
|
onCloseAutoFocus?: ((event: Event) => any) | undefined;
|
|
26
|
+
"onAfter-close"?: (() => any) | undefined;
|
|
25
27
|
}>, {
|
|
26
28
|
showCloseButton: boolean;
|
|
27
29
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -3,11 +3,15 @@ type __VLS_Props = {
|
|
|
3
3
|
class?: HTMLAttributes['class'];
|
|
4
4
|
showCloseButton?: boolean;
|
|
5
5
|
};
|
|
6
|
-
declare var
|
|
6
|
+
declare var __VLS_22: {};
|
|
7
7
|
type __VLS_Slots = {} & {
|
|
8
|
-
default?: (props: typeof
|
|
8
|
+
default?: (props: typeof __VLS_22) => any;
|
|
9
9
|
};
|
|
10
|
-
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
10
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
11
|
+
"after-close": () => any;
|
|
12
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
13
|
+
"onAfter-close"?: (() => any) | undefined;
|
|
14
|
+
}>, {
|
|
11
15
|
showCloseButton: boolean;
|
|
12
16
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
13
17
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { reactiveOmit } from "@vueuse/core";
|
|
3
3
|
import { Icon } from "@iconify/vue";
|
|
4
4
|
import { useForwardProps } from "reka-ui";
|
|
5
|
+
import { onBeforeUnmount, shallowRef, watchEffect } from "vue";
|
|
5
6
|
import {
|
|
6
7
|
DrawerClose,
|
|
7
8
|
DrawerContent,
|
|
@@ -16,14 +17,123 @@ const props = defineProps({
|
|
|
16
17
|
class: { type: null, required: false },
|
|
17
18
|
showCloseButton: { type: Boolean, required: false, default: true }
|
|
18
19
|
});
|
|
20
|
+
const emit = defineEmits(["after-close"]);
|
|
19
21
|
const delegatedProps = reactiveOmit(props, "class", "showCloseButton");
|
|
20
22
|
const forwardedProps = useForwardProps(delegatedProps);
|
|
23
|
+
const contentElement = shallowRef(null);
|
|
24
|
+
let closeFallbackTimer;
|
|
25
|
+
let hasEmittedAfterClose = false;
|
|
26
|
+
function isClosedContentTarget(target) {
|
|
27
|
+
return target instanceof HTMLElement && target.dataset.state === "closed";
|
|
28
|
+
}
|
|
29
|
+
function clearCloseFallbackTimer() {
|
|
30
|
+
if (closeFallbackTimer === void 0) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
window.clearTimeout(closeFallbackTimer);
|
|
34
|
+
closeFallbackTimer = void 0;
|
|
35
|
+
}
|
|
36
|
+
function emitAfterClose() {
|
|
37
|
+
if (hasEmittedAfterClose) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
hasEmittedAfterClose = true;
|
|
41
|
+
clearCloseFallbackTimer();
|
|
42
|
+
emit("after-close");
|
|
43
|
+
}
|
|
44
|
+
function parseDurationMs(value) {
|
|
45
|
+
const normalizedValue = value.trim();
|
|
46
|
+
if (normalizedValue.endsWith("ms")) {
|
|
47
|
+
const duration = Number.parseFloat(normalizedValue.slice(0, -2));
|
|
48
|
+
return Number.isFinite(duration) ? duration : 0;
|
|
49
|
+
}
|
|
50
|
+
if (normalizedValue.endsWith("s")) {
|
|
51
|
+
const duration = Number.parseFloat(normalizedValue.slice(0, -1));
|
|
52
|
+
return Number.isFinite(duration) ? duration * 1e3 : 0;
|
|
53
|
+
}
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
function getLongestMotionMs(element) {
|
|
57
|
+
const style = window.getComputedStyle(element);
|
|
58
|
+
const animationDurations = style.animationDuration.split(",");
|
|
59
|
+
const animationDelays = style.animationDelay.split(",");
|
|
60
|
+
const transitionDurations = style.transitionDuration.split(",");
|
|
61
|
+
const transitionDelays = style.transitionDelay.split(",");
|
|
62
|
+
let longestMotionMs = 0;
|
|
63
|
+
for (const [index, durationValue] of animationDurations.entries()) {
|
|
64
|
+
const durationMs = parseDurationMs(durationValue);
|
|
65
|
+
const delayMs = parseDurationMs(animationDelays[index] ?? animationDelays[0] ?? "0s");
|
|
66
|
+
longestMotionMs = Math.max(longestMotionMs, durationMs + delayMs);
|
|
67
|
+
}
|
|
68
|
+
for (const [index, durationValue] of transitionDurations.entries()) {
|
|
69
|
+
const durationMs = parseDurationMs(durationValue);
|
|
70
|
+
const delayMs = parseDurationMs(transitionDelays[index] ?? transitionDelays[0] ?? "0s");
|
|
71
|
+
longestMotionMs = Math.max(longestMotionMs, durationMs + delayMs);
|
|
72
|
+
}
|
|
73
|
+
return longestMotionMs;
|
|
74
|
+
}
|
|
75
|
+
function syncCloseFallback() {
|
|
76
|
+
const element = contentElement.value;
|
|
77
|
+
clearCloseFallbackTimer();
|
|
78
|
+
if (!element) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (element.dataset.state !== "closed") {
|
|
82
|
+
hasEmittedAfterClose = false;
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const motionMs = getLongestMotionMs(element);
|
|
86
|
+
closeFallbackTimer = window.setTimeout(() => {
|
|
87
|
+
emitAfterClose();
|
|
88
|
+
}, motionMs > 0 ? motionMs : 0);
|
|
89
|
+
}
|
|
90
|
+
function handleCloseMotionEnd(event) {
|
|
91
|
+
if (hasEmittedAfterClose || event.target !== event.currentTarget || !isClosedContentTarget(event.currentTarget)) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
emitAfterClose();
|
|
95
|
+
}
|
|
96
|
+
function setContentElement(target) {
|
|
97
|
+
if (target instanceof HTMLElement) {
|
|
98
|
+
contentElement.value = target;
|
|
99
|
+
syncCloseFallback();
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (target && "$el" in target && target.$el instanceof HTMLElement) {
|
|
103
|
+
contentElement.value = target.$el;
|
|
104
|
+
syncCloseFallback();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
contentElement.value = null;
|
|
108
|
+
clearCloseFallbackTimer();
|
|
109
|
+
}
|
|
110
|
+
watchEffect((onCleanup) => {
|
|
111
|
+
const element = contentElement.value;
|
|
112
|
+
if (!element) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const observer = new MutationObserver(() => {
|
|
116
|
+
syncCloseFallback();
|
|
117
|
+
});
|
|
118
|
+
observer.observe(element, {
|
|
119
|
+
attributes: true,
|
|
120
|
+
attributeFilter: ["data-state"]
|
|
121
|
+
});
|
|
122
|
+
syncCloseFallback();
|
|
123
|
+
onCleanup(() => {
|
|
124
|
+
observer.disconnect();
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
onBeforeUnmount(() => {
|
|
128
|
+
clearCloseFallbackTimer();
|
|
129
|
+
});
|
|
21
130
|
</script>
|
|
22
131
|
|
|
23
132
|
<template>
|
|
24
133
|
<DrawerPortal>
|
|
25
134
|
<DrawerOverlay />
|
|
26
135
|
<DrawerContent
|
|
136
|
+
:ref="setContentElement"
|
|
27
137
|
data-slot="drawer-content"
|
|
28
138
|
v-bind="{ ...$attrs, ...forwardedProps }"
|
|
29
139
|
:class="
|
|
@@ -32,6 +142,8 @@ const forwardedProps = useForwardProps(delegatedProps);
|
|
|
32
142
|
props.class
|
|
33
143
|
)
|
|
34
144
|
"
|
|
145
|
+
@animationend="handleCloseMotionEnd"
|
|
146
|
+
@transitionend="handleCloseMotionEnd"
|
|
35
147
|
>
|
|
36
148
|
<div class="mx-auto -mt-2 h-2 w-16 rounded-full bg-zinc-200" />
|
|
37
149
|
|
|
@@ -3,11 +3,15 @@ type __VLS_Props = {
|
|
|
3
3
|
class?: HTMLAttributes['class'];
|
|
4
4
|
showCloseButton?: boolean;
|
|
5
5
|
};
|
|
6
|
-
declare var
|
|
6
|
+
declare var __VLS_22: {};
|
|
7
7
|
type __VLS_Slots = {} & {
|
|
8
|
-
default?: (props: typeof
|
|
8
|
+
default?: (props: typeof __VLS_22) => any;
|
|
9
9
|
};
|
|
10
|
-
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
10
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
11
|
+
"after-close": () => any;
|
|
12
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
13
|
+
"onAfter-close"?: (() => any) | undefined;
|
|
14
|
+
}>, {
|
|
11
15
|
showCloseButton: boolean;
|
|
12
16
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
13
17
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -38,9 +38,11 @@ type OverlayShellState = OverlayShellProps & {
|
|
|
38
38
|
type OverlaySession = {
|
|
39
39
|
sessionId: string;
|
|
40
40
|
definitionId: string;
|
|
41
|
+
open: boolean;
|
|
41
42
|
shell: OverlayShellState;
|
|
42
43
|
props: Record<string, unknown>;
|
|
43
44
|
deferred: Deferred.Deferred<OverlayResult, never>;
|
|
45
|
+
pendingResult?: OverlayResult;
|
|
44
46
|
};
|
|
45
47
|
export type OverlayHandle<T = Record<string, unknown>> = Readonly<{
|
|
46
48
|
sessionId: string;
|
|
@@ -50,19 +50,25 @@ function createOverlayRuntime() {
|
|
|
50
50
|
const [session] = sessions.value.splice(index, 1);
|
|
51
51
|
return session;
|
|
52
52
|
}
|
|
53
|
-
function
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
53
|
+
function finalizeCloseSync(sessionId, result) {
|
|
54
|
+
const session = removeSession(sessionId);
|
|
55
|
+
if (!session) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
Effect.runSync(Deferred.succeed(session.deferred, session.pendingResult ?? result ?? Option.none()));
|
|
59
|
+
}
|
|
60
|
+
function requestCloseSync(sessionId, result) {
|
|
61
|
+
const session = getSession(sessionId);
|
|
62
|
+
if (!session || !session.open) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
session.open = false;
|
|
66
|
+
session.pendingResult = result;
|
|
61
67
|
}
|
|
62
68
|
function closeDefinitionSessions(definitionId) {
|
|
63
69
|
const targetSessions = sessions.value.filter((session) => session.definitionId === definitionId).map((session) => session.sessionId);
|
|
64
70
|
for (const sessionId of targetSessions) {
|
|
65
|
-
|
|
71
|
+
finalizeCloseSync(sessionId, Option.none());
|
|
66
72
|
}
|
|
67
73
|
}
|
|
68
74
|
function registerDefinition(definition) {
|
|
@@ -111,19 +117,19 @@ function createOverlayRuntime() {
|
|
|
111
117
|
}
|
|
112
118
|
}
|
|
113
119
|
function closeSync(sessionId, ...args) {
|
|
114
|
-
|
|
120
|
+
requestCloseSync(sessionId, createResult(...args));
|
|
115
121
|
}
|
|
116
122
|
function closeTopSync() {
|
|
117
123
|
const topSession = sessions.value.at(-1);
|
|
118
124
|
if (!topSession) {
|
|
119
125
|
return;
|
|
120
126
|
}
|
|
121
|
-
|
|
127
|
+
requestCloseSync(topSession.sessionId, Option.none());
|
|
122
128
|
}
|
|
123
129
|
function closeAllSync() {
|
|
124
130
|
const sessionIds = sessions.value.map((session) => session.sessionId);
|
|
125
131
|
for (const sessionId of sessionIds) {
|
|
126
|
-
|
|
132
|
+
requestCloseSync(sessionId, Option.none());
|
|
127
133
|
}
|
|
128
134
|
}
|
|
129
135
|
function createHandle(session) {
|
|
@@ -132,7 +138,9 @@ function createOverlayRuntime() {
|
|
|
132
138
|
patch: (patch) => Effect.sync(() => {
|
|
133
139
|
patchSync(session.sessionId, patch);
|
|
134
140
|
}),
|
|
135
|
-
close: (...args) =>
|
|
141
|
+
close: (...args) => Effect.sync(() => {
|
|
142
|
+
requestCloseSync(session.sessionId, createResult(...args));
|
|
143
|
+
}),
|
|
136
144
|
result: Deferred.await(session.deferred)
|
|
137
145
|
};
|
|
138
146
|
}
|
|
@@ -160,6 +168,7 @@ function createOverlayRuntime() {
|
|
|
160
168
|
const session = {
|
|
161
169
|
sessionId: crypto.randomUUID(),
|
|
162
170
|
definitionId,
|
|
171
|
+
open: true,
|
|
163
172
|
shell: {
|
|
164
173
|
title: explicitTitle ?? buttonTitle ?? definitionTitle,
|
|
165
174
|
description: explicitDescription ?? buttonDescription ?? definitionDescription ?? getDefaultOverlayDescription(buttonAction?.locale ?? "zh"),
|
|
@@ -176,7 +185,9 @@ function createOverlayRuntime() {
|
|
|
176
185
|
sessions.value.push(session);
|
|
177
186
|
return createHandle(session);
|
|
178
187
|
}),
|
|
179
|
-
(handle) =>
|
|
188
|
+
(handle) => Effect.sync(() => {
|
|
189
|
+
finalizeCloseSync(handle.sessionId, Option.none());
|
|
190
|
+
})
|
|
180
191
|
);
|
|
181
192
|
}
|
|
182
193
|
const runtime = {
|
|
@@ -192,7 +203,7 @@ function createOverlayRuntime() {
|
|
|
192
203
|
registerDefinition,
|
|
193
204
|
unregisterDefinition,
|
|
194
205
|
syncDefinitions,
|
|
195
|
-
isOpen: (sessionId) =>
|
|
206
|
+
isOpen: (sessionId) => getSession(sessionId)?.open === true,
|
|
196
207
|
patchSync,
|
|
197
208
|
closeSync,
|
|
198
209
|
closeTopSync,
|
|
@@ -201,13 +212,16 @@ function createOverlayRuntime() {
|
|
|
201
212
|
patch: (sessionId, patch) => Effect.sync(() => {
|
|
202
213
|
patchSync(sessionId, patch);
|
|
203
214
|
}),
|
|
204
|
-
close: (sessionId, ...args) =>
|
|
215
|
+
close: (sessionId, ...args) => Effect.sync(() => {
|
|
216
|
+
requestCloseSync(sessionId, createResult(...args));
|
|
217
|
+
}),
|
|
205
218
|
closeTop: () => Effect.sync(() => {
|
|
206
219
|
closeTopSync();
|
|
207
220
|
}),
|
|
208
221
|
closeAll: () => Effect.sync(() => {
|
|
209
222
|
closeAllSync();
|
|
210
|
-
})
|
|
223
|
+
}),
|
|
224
|
+
finalizeCloseSync
|
|
211
225
|
};
|
|
212
226
|
return runtime;
|
|
213
227
|
}
|