srcdev-nuxt-components 6.1.19 → 6.1.21
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.
|
@@ -5,12 +5,10 @@
|
|
|
5
5
|
class="display-toast"
|
|
6
6
|
:class="[
|
|
7
7
|
elementClasses,
|
|
8
|
+
cssStateClass,
|
|
8
9
|
{
|
|
9
|
-
[theme]: !slots.default,
|
|
10
10
|
'has-theme': !slots.default,
|
|
11
|
-
|
|
12
|
-
'use-timer': displayDurationInt > 0,
|
|
13
|
-
hide: isHiding,
|
|
11
|
+
'auto-dismiss': autoDismiss,
|
|
14
12
|
},
|
|
15
13
|
]"
|
|
16
14
|
:data-theme="theme"
|
|
@@ -25,13 +23,13 @@
|
|
|
25
23
|
</div>
|
|
26
24
|
<div class="toast-message">{{ toastDisplayText }}</div>
|
|
27
25
|
<div class="toast-action">
|
|
28
|
-
<button @click.prevent="
|
|
26
|
+
<button @click.prevent="updateToHiding()">
|
|
29
27
|
<Icon name="material-symbols:close" class="icon" />
|
|
30
28
|
<span class="sr-only">Close</span>
|
|
31
29
|
</button>
|
|
32
30
|
</div>
|
|
33
31
|
</div>
|
|
34
|
-
<div v-if="
|
|
32
|
+
<div v-if="autoDismiss" class="display-toast-progress"></div>
|
|
35
33
|
</div>
|
|
36
34
|
</Teleport>
|
|
37
35
|
</template>
|
|
@@ -46,7 +44,11 @@ const props = defineProps({
|
|
|
46
44
|
},
|
|
47
45
|
revealDuration: {
|
|
48
46
|
type: Number,
|
|
49
|
-
default:
|
|
47
|
+
default: 550,
|
|
48
|
+
},
|
|
49
|
+
autoDismiss: {
|
|
50
|
+
type: Boolean,
|
|
51
|
+
default: true,
|
|
50
52
|
},
|
|
51
53
|
duration: {
|
|
52
54
|
type: Number,
|
|
@@ -76,10 +78,18 @@ const defaultThemeIcons = {
|
|
|
76
78
|
const slots = useSlots()
|
|
77
79
|
const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
|
|
78
80
|
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
+
// single state ref
|
|
82
|
+
const state = ref<"idle" | "entering" | "visible" | "hiding">("idle")
|
|
83
|
+
const cssStateClass = computed(() => {
|
|
84
|
+
return state.value !== "idle" && !props.autoDismiss ? state.value : ""
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
// external toggle
|
|
81
88
|
const publicToastState = defineModel<boolean>({ default: false })
|
|
82
89
|
|
|
90
|
+
// computed helpers
|
|
91
|
+
const privateToastState = ref(false)
|
|
92
|
+
|
|
83
93
|
const revealDurationInt = computed(() => props.revealDuration)
|
|
84
94
|
const revealDuration = computed(() => revealDurationInt.value + "ms")
|
|
85
95
|
const displayDurationInt = computed(() => props.duration)
|
|
@@ -88,16 +98,28 @@ const displayDuration = computed(() => displayDurationInt.value + "ms")
|
|
|
88
98
|
const progressDurationInt = computed(() => Math.floor(displayDurationInt.value - revealDurationInt.value / 2))
|
|
89
99
|
const progressDuration = computed(() => progressDurationInt.value + "ms")
|
|
90
100
|
|
|
91
|
-
const
|
|
101
|
+
const removeToast = () => {
|
|
92
102
|
publicToastState.value = false
|
|
93
103
|
privateToastState.value = false
|
|
94
|
-
isHiding.value = false
|
|
95
104
|
}
|
|
96
105
|
|
|
97
|
-
const
|
|
98
|
-
|
|
106
|
+
const updateToIdle = () => {
|
|
107
|
+
state.value = "idle"
|
|
108
|
+
removeToast()
|
|
109
|
+
}
|
|
110
|
+
const updateToEntering = async () => {
|
|
111
|
+
privateToastState.value = true
|
|
112
|
+
state.value = "entering"
|
|
113
|
+
await useSleep(revealDurationInt.value)
|
|
114
|
+
updateToVisible()
|
|
115
|
+
}
|
|
116
|
+
const updateToVisible = () => {
|
|
117
|
+
state.value = "visible"
|
|
118
|
+
}
|
|
119
|
+
const updateToHiding = async () => {
|
|
120
|
+
state.value = "hiding"
|
|
99
121
|
await useSleep(revealDurationInt.value)
|
|
100
|
-
|
|
122
|
+
updateToIdle()
|
|
101
123
|
}
|
|
102
124
|
|
|
103
125
|
watch(
|
|
@@ -110,22 +132,52 @@ watch(
|
|
|
110
132
|
watch(
|
|
111
133
|
() => publicToastState.value,
|
|
112
134
|
async (newValue, previousValue) => {
|
|
113
|
-
if (
|
|
114
|
-
privateToastState.value =
|
|
135
|
+
if (props.autoDismiss) {
|
|
136
|
+
privateToastState.value = newValue
|
|
137
|
+
await useSleep(displayDurationInt.value)
|
|
138
|
+
updateToIdle()
|
|
139
|
+
return
|
|
140
|
+
}
|
|
115
141
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
142
|
+
if (!previousValue && newValue && state.value === "idle") {
|
|
143
|
+
updateToEntering()
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (previousValue && !newValue && state.value == "visible") {
|
|
147
|
+
updateToHiding()
|
|
122
148
|
}
|
|
123
149
|
}
|
|
124
150
|
)
|
|
125
151
|
</script>
|
|
126
152
|
|
|
127
153
|
<style scoped lang="css">
|
|
128
|
-
@keyframes
|
|
154
|
+
@keyframes slide-in {
|
|
155
|
+
from {
|
|
156
|
+
opacity: 0;
|
|
157
|
+
visibility: hidden;
|
|
158
|
+
transform: translateY(20px);
|
|
159
|
+
}
|
|
160
|
+
to {
|
|
161
|
+
opacity: 1;
|
|
162
|
+
visibility: visible;
|
|
163
|
+
transform: translateY(0);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@keyframes slide-out {
|
|
168
|
+
from {
|
|
169
|
+
opacity: 1;
|
|
170
|
+
visibility: visible;
|
|
171
|
+
transform: translateY(0);
|
|
172
|
+
}
|
|
173
|
+
to {
|
|
174
|
+
opacity: 0;
|
|
175
|
+
visibility: hidden;
|
|
176
|
+
transform: translateY(20px);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
@keyframes slide-in-out {
|
|
129
181
|
5% {
|
|
130
182
|
opacity: 1;
|
|
131
183
|
visibility: visible;
|
|
@@ -174,48 +226,29 @@ watch(
|
|
|
174
226
|
|
|
175
227
|
z-index: 100;
|
|
176
228
|
|
|
177
|
-
&.
|
|
178
|
-
|
|
229
|
+
&.auto-dismiss {
|
|
230
|
+
/* first run slide-in, then slide-out after a delay */
|
|
231
|
+
animation: slide-in 400ms var(--spring-in-easing) forwards,
|
|
232
|
+
slide-out 400ms var(--spring-out-easing) forwards v-bind(displayDuration);
|
|
179
233
|
}
|
|
180
234
|
|
|
181
|
-
&.
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
1.086 26.6%,
|
|
194
|
-
1.014 38.5%,
|
|
195
|
-
0.994 46.3%,
|
|
196
|
-
1
|
|
197
|
-
)
|
|
198
|
-
forwards;
|
|
199
|
-
}
|
|
235
|
+
&:not(&.auto-dismiss) {
|
|
236
|
+
&.show,
|
|
237
|
+
&.entering {
|
|
238
|
+
animation: show v-bind(revealDuration) var(--spring-easing) forwards;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
&.visible {
|
|
242
|
+
/* if you want a steady state style, add here */
|
|
243
|
+
opacity: 1;
|
|
244
|
+
visibility: visible;
|
|
245
|
+
transform: translateY(0);
|
|
246
|
+
}
|
|
200
247
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
0.006 53.7%,
|
|
206
|
-
0.986 61.5%,
|
|
207
|
-
1.014 73.4%,
|
|
208
|
-
1.087 76.1%,
|
|
209
|
-
1.074 78.4%,
|
|
210
|
-
1.046 80.4%,
|
|
211
|
-
1.002 82.3%,
|
|
212
|
-
0.862 85.9%,
|
|
213
|
-
0.651 89.4%,
|
|
214
|
-
0.123 96.5%,
|
|
215
|
-
0.029 98.4%,
|
|
216
|
-
0
|
|
217
|
-
)
|
|
218
|
-
forwards;
|
|
248
|
+
&.hide,
|
|
249
|
+
&.hiding {
|
|
250
|
+
animation: hide v-bind(revealDuration) var(--spring-easing) forwards;
|
|
251
|
+
}
|
|
219
252
|
}
|
|
220
253
|
|
|
221
254
|
&:hover {
|
|
@@ -264,6 +297,9 @@ watch(
|
|
|
264
297
|
border: 0.1rem solid var(--colour-theme-8);
|
|
265
298
|
border-start-start-radius: 8px;
|
|
266
299
|
border-end-start-radius: 8px;
|
|
300
|
+
border-start-end-radius: 4px;
|
|
301
|
+
border-end-end-radius: 4px;
|
|
302
|
+
|
|
267
303
|
overflow: hidden;
|
|
268
304
|
|
|
269
305
|
.display-toast-inner {
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component :is="tag" class="magnetic-navigation" :class="[elementClasses]">
|
|
3
|
+
<nav>
|
|
4
|
+
<ul>
|
|
5
|
+
<li><a href="#">Home</a></li>
|
|
6
|
+
<li><a href="#">About</a></li>
|
|
7
|
+
<li><a href="#">Blog</a></li>
|
|
8
|
+
<li><a href="#">Contact</a></li>
|
|
9
|
+
</ul>
|
|
10
|
+
</nav>
|
|
11
|
+
</component>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
const props = defineProps({
|
|
16
|
+
tag: {
|
|
17
|
+
type: String,
|
|
18
|
+
default: "div",
|
|
19
|
+
validator(value: string) {
|
|
20
|
+
return ["div", "header", "footer", "nav"].includes(value)
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
styleClassPassthrough: {
|
|
24
|
+
type: Array as PropType<string[]>,
|
|
25
|
+
default: () => [],
|
|
26
|
+
},
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
|
|
30
|
+
|
|
31
|
+
watch(
|
|
32
|
+
() => props.styleClassPassthrough,
|
|
33
|
+
() => {
|
|
34
|
+
resetElementClasses(props.styleClassPassthrough)
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<style lang="css">
|
|
40
|
+
.magnetic-navigation {
|
|
41
|
+
/*
|
|
42
|
+
--_background-image: url("/images/rotating-carousel/image-3.webp");
|
|
43
|
+
|
|
44
|
+
background-image: var(--_background-image);
|
|
45
|
+
background-size: cover;
|
|
46
|
+
background-position: 0 -400px;
|
|
47
|
+
background-attachment: fixed;
|
|
48
|
+
*/
|
|
49
|
+
/* padding-block: 200px 2000px; */
|
|
50
|
+
|
|
51
|
+
nav {
|
|
52
|
+
width: fit-content;
|
|
53
|
+
margin: 3rem auto;
|
|
54
|
+
background: hsl(0 0% 0% / 0.8);
|
|
55
|
+
|
|
56
|
+
padding: 8px;
|
|
57
|
+
border-radius: 8px;
|
|
58
|
+
|
|
59
|
+
isolation: isolate;
|
|
60
|
+
|
|
61
|
+
anchor-name: --hovered-link;
|
|
62
|
+
|
|
63
|
+
li:hover {
|
|
64
|
+
anchor-name: --hovered-link;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
&::before,
|
|
68
|
+
&::after {
|
|
69
|
+
content: "";
|
|
70
|
+
position: absolute;
|
|
71
|
+
top: calc(anchor(bottom) - 10px);
|
|
72
|
+
left: calc(anchor(left) + 1rem);
|
|
73
|
+
right: calc(anchor(right) + 1rem);
|
|
74
|
+
bottom: calc(anchor(bottom) + 5px);
|
|
75
|
+
border-radius: 10px;
|
|
76
|
+
|
|
77
|
+
position-anchor: --hovered-link;
|
|
78
|
+
|
|
79
|
+
transition: 500ms
|
|
80
|
+
linear(
|
|
81
|
+
0,
|
|
82
|
+
0.029 1.6%,
|
|
83
|
+
0.123 3.5%,
|
|
84
|
+
0.651 10.6%,
|
|
85
|
+
0.862 14.1%,
|
|
86
|
+
1.002 17.7%,
|
|
87
|
+
1.046 19.6%,
|
|
88
|
+
1.074 21.6%,
|
|
89
|
+
1.087 23.9%,
|
|
90
|
+
1.086 26.6%,
|
|
91
|
+
1.014 38.5%,
|
|
92
|
+
0.994 46.3%,
|
|
93
|
+
1
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
&::before {
|
|
98
|
+
z-index: -1;
|
|
99
|
+
background: rgb(0 0 0 / 0.2);
|
|
100
|
+
backdrop-filter: blur(2px);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
&::after {
|
|
104
|
+
z-index: -2;
|
|
105
|
+
background-image: var(--_background-image);
|
|
106
|
+
background-size: cover;
|
|
107
|
+
background-position: var(--_background-position);
|
|
108
|
+
background-attachment: fixed;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
&:has(a:hover)::before,
|
|
112
|
+
&:has(a:hover)::after {
|
|
113
|
+
top: anchor(top);
|
|
114
|
+
left: anchor(left);
|
|
115
|
+
right: anchor(right);
|
|
116
|
+
bottom: anchor(bottom);
|
|
117
|
+
|
|
118
|
+
@supports (corner-shape: squircle) {
|
|
119
|
+
corner-shape: squircle;
|
|
120
|
+
border-radius: 50%;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
&:has(li:first-of-type a:hover)::before,
|
|
125
|
+
&:has(li:first-of-type a:hover)::after {
|
|
126
|
+
@supports (corner-shape: squircle) {
|
|
127
|
+
border-radius: 32px 50% 50% 32px;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
&:has(li:last-of-type a:hover)::before,
|
|
132
|
+
&:has(li:last-of-type a:hover)::after {
|
|
133
|
+
@supports (corner-shape: squircle) {
|
|
134
|
+
border-radius: 50% 32px 32px 50%;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@supports (corner-shape: squircle) {
|
|
139
|
+
border-radius: 24px;
|
|
140
|
+
corner-shape: squircle;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
> ul {
|
|
144
|
+
padding: 0;
|
|
145
|
+
margin: 0;
|
|
146
|
+
list-style: none;
|
|
147
|
+
display: flex;
|
|
148
|
+
gap: 24px;
|
|
149
|
+
|
|
150
|
+
a {
|
|
151
|
+
display: block;
|
|
152
|
+
padding: 1rem;
|
|
153
|
+
text-decoration: none;
|
|
154
|
+
color: white;
|
|
155
|
+
font-size: var(--step-7);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
</style>
|
package/package.json
CHANGED