srcdev-nuxt-components 6.2.1 → 6.2.3
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.
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="alert-mask-core" :class="[elementClasses]">
|
|
3
|
+
<svg class="alert-mask-decorator" :style="{ '--alertHeight': svgHeight + 'px' }" xmlns="http://www.w3.org/2000/svg">
|
|
4
|
+
<defs>
|
|
5
|
+
<mask id="borderMask" maskUnits="userSpaceOnUse">
|
|
6
|
+
<path :d="outerPath" fill="white" />
|
|
7
|
+
<path :d="innerPath" fill="black" />
|
|
8
|
+
</mask>
|
|
9
|
+
</defs>
|
|
10
|
+
|
|
11
|
+
<path :d="outerPath" :fill="cfg.color" mask="url(#borderMask)" vector-effect="non-scaling-stroke" />
|
|
12
|
+
<path :d="innerPath" fill="rgba(0,0,0,0.5)" />
|
|
13
|
+
</svg>
|
|
14
|
+
|
|
15
|
+
<div
|
|
16
|
+
class="alert-mask-content"
|
|
17
|
+
:style="{
|
|
18
|
+
'--insetInlineStart': (props.config?.borderLeft ?? 0) + 'px',
|
|
19
|
+
'--insetInlineEnd': (props.config?.borderRight ?? 0) + 'px',
|
|
20
|
+
'--insetBlockStart': (props.config?.borderTop ?? 0) + 'px',
|
|
21
|
+
'--insetBlockEnd': (props.config?.borderBottom ?? 0) + 'px',
|
|
22
|
+
}"
|
|
23
|
+
>
|
|
24
|
+
<div class="alert-mask-content-slot" ref="alertContentRef">
|
|
25
|
+
<slot name="default"></slot>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script lang="ts">
|
|
32
|
+
export interface BorderConfig {
|
|
33
|
+
color?: string
|
|
34
|
+
radiusLeft?: number
|
|
35
|
+
radiusRight?: number
|
|
36
|
+
borderLeft?: number
|
|
37
|
+
borderTop?: number
|
|
38
|
+
borderRight?: number
|
|
39
|
+
borderBottom?: number
|
|
40
|
+
}
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<script setup lang="ts">
|
|
44
|
+
const props = defineProps({
|
|
45
|
+
config: Object as PropType<BorderConfig>,
|
|
46
|
+
styleClassPassthrough: {
|
|
47
|
+
type: [String, Array] as PropType<string | string[]>,
|
|
48
|
+
default: () => [],
|
|
49
|
+
},
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
|
|
53
|
+
|
|
54
|
+
const alertContentRef = useTemplateRef<HTMLElement | null>("alertContentRef")
|
|
55
|
+
const svgWidth = ref(0)
|
|
56
|
+
const svgHeight = ref(0)
|
|
57
|
+
|
|
58
|
+
// Update dimensions based on content
|
|
59
|
+
onMounted(() => {
|
|
60
|
+
const updateDimensions = () => {
|
|
61
|
+
const contentEl = alertContentRef.value
|
|
62
|
+
if (!contentEl) return
|
|
63
|
+
|
|
64
|
+
const rect = contentEl.getBoundingClientRect()
|
|
65
|
+
const { borderLeft, borderTop, borderRight, borderBottom } = cfg.value
|
|
66
|
+
|
|
67
|
+
// Calculate total dimensions including borders
|
|
68
|
+
svgWidth.value = rect.width + borderLeft + borderRight
|
|
69
|
+
svgHeight.value = rect.height + borderTop + borderBottom
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Initial measurement
|
|
73
|
+
nextTick(updateDimensions)
|
|
74
|
+
|
|
75
|
+
// Observe content changes
|
|
76
|
+
const contentEl = alertContentRef.value
|
|
77
|
+
if (contentEl) {
|
|
78
|
+
const resizeObserver = new ResizeObserver(updateDimensions)
|
|
79
|
+
resizeObserver.observe(contentEl)
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
const cfg = computed(() => ({
|
|
84
|
+
color: props.config?.color ?? "var(--orange-8)",
|
|
85
|
+
radiusLeft: props.config?.radiusLeft ?? 12,
|
|
86
|
+
radiusRight: props.config?.radiusRight ?? 12,
|
|
87
|
+
borderLeft: props.config?.borderLeft ?? 8,
|
|
88
|
+
borderTop: props.config?.borderTop ?? 8,
|
|
89
|
+
borderRight: props.config?.borderRight ?? 8,
|
|
90
|
+
borderBottom: props.config?.borderBottom ?? 8,
|
|
91
|
+
}))
|
|
92
|
+
|
|
93
|
+
// Outer border path (fixed radii)
|
|
94
|
+
const outerPath = computed(() => {
|
|
95
|
+
const width = svgWidth.value
|
|
96
|
+
const height = svgHeight.value
|
|
97
|
+
const { radiusLeft, radiusRight } = cfg.value
|
|
98
|
+
|
|
99
|
+
if (!width || !height) return ""
|
|
100
|
+
|
|
101
|
+
return `
|
|
102
|
+
M ${radiusLeft} 0
|
|
103
|
+
L ${width - radiusRight} 0
|
|
104
|
+
Q ${width} 0 ${width} ${radiusRight}
|
|
105
|
+
L ${width} ${height - radiusRight}
|
|
106
|
+
Q ${width} ${height} ${width - radiusRight} ${height}
|
|
107
|
+
L ${radiusLeft} ${height}
|
|
108
|
+
Q 0 ${height} 0 ${height - radiusLeft}
|
|
109
|
+
L 0 ${radiusLeft}
|
|
110
|
+
Q 0 0 ${radiusLeft} 0 Z
|
|
111
|
+
`
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
// Inner cutout (based on fixed pixel border thickness)
|
|
115
|
+
const innerPath = computed(() => {
|
|
116
|
+
const width = svgWidth.value
|
|
117
|
+
const height = svgHeight.value
|
|
118
|
+
const { radiusLeft, radiusRight, borderLeft, borderTop, borderRight, borderBottom: borderBottom } = cfg.value
|
|
119
|
+
|
|
120
|
+
if (!width || !height) return ""
|
|
121
|
+
|
|
122
|
+
return `
|
|
123
|
+
M ${radiusLeft + borderLeft} ${borderTop}
|
|
124
|
+
L ${width - radiusRight - borderRight} ${borderTop}
|
|
125
|
+
Q ${width - borderRight} ${borderTop} ${width - borderRight} ${radiusRight + borderTop}
|
|
126
|
+
L ${width - borderRight} ${height - radiusRight - borderBottom}
|
|
127
|
+
Q ${width - borderRight} ${height - borderBottom} ${width - radiusRight - borderRight} ${height - borderBottom}
|
|
128
|
+
L ${radiusLeft + borderLeft} ${height - borderBottom}
|
|
129
|
+
Q ${borderLeft} ${height - borderBottom} ${borderLeft} ${height - radiusLeft - borderBottom}
|
|
130
|
+
L ${borderLeft} ${radiusLeft + borderTop}
|
|
131
|
+
Q ${borderLeft} ${borderTop} ${radiusLeft + borderLeft} ${borderTop} Z
|
|
132
|
+
`
|
|
133
|
+
})
|
|
134
|
+
</script>
|
|
135
|
+
|
|
136
|
+
<style lang="css">
|
|
137
|
+
.alert-mask-core {
|
|
138
|
+
display: grid;
|
|
139
|
+
grid-template-areas: "mask";
|
|
140
|
+
|
|
141
|
+
.alert-mask-decorator {
|
|
142
|
+
grid-area: mask;
|
|
143
|
+
width: 100%;
|
|
144
|
+
height: var(--alertHeight);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.alert-mask-content {
|
|
148
|
+
grid-area: mask;
|
|
149
|
+
margin-block: var(--insetBlockStart) var(--insetBlockEnd);
|
|
150
|
+
margin-inline: var(--insetInlineStart) var(--insetInlineEnd);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
</style>
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
<button
|
|
42
42
|
@click.prevent="jumpToFrame(index - 1)"
|
|
43
43
|
class="btn-marker"
|
|
44
|
-
:class="[{ active:
|
|
44
|
+
:class="[{ active: displayActiveIndex === index - 1 }]"
|
|
45
45
|
:aria-label="`Jump to item ${Math.floor(index + 1)}`"
|
|
46
46
|
></button>
|
|
47
47
|
</li>
|
|
@@ -82,7 +82,11 @@ const props = defineProps({
|
|
|
82
82
|
},
|
|
83
83
|
useFlipAnimation: {
|
|
84
84
|
type: Boolean,
|
|
85
|
-
default:
|
|
85
|
+
default: false,
|
|
86
|
+
},
|
|
87
|
+
useSpringEffect: {
|
|
88
|
+
type: Boolean,
|
|
89
|
+
default: false,
|
|
86
90
|
},
|
|
87
91
|
})
|
|
88
92
|
|
|
@@ -98,13 +102,6 @@ const userHasInteracted = ref(false)
|
|
|
98
102
|
const initialItemOffset = computed(() => {
|
|
99
103
|
return props.useFlipAnimation ? 1 : 2
|
|
100
104
|
})
|
|
101
|
-
const circularOffsetBase = computed(() => {
|
|
102
|
-
return props.useFlipAnimation ? 1 : Math.floor(2 * initialItemOffset.value)
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
function getOffsetIndex(index: number, offset: number, itemCount: number): number {
|
|
106
|
-
return (index + offset) % itemCount
|
|
107
|
-
}
|
|
108
105
|
|
|
109
106
|
const currentIndex = ref(0)
|
|
110
107
|
const itemCount = ref(props.carouselDataIds.length)
|
|
@@ -112,25 +109,32 @@ const transitionSpeedStr = props.transitionSpeed + "ms"
|
|
|
112
109
|
|
|
113
110
|
const itemWidth = ref(0)
|
|
114
111
|
const itemWidthOffsetStr = computed(() => {
|
|
115
|
-
if (props.allowCarouselOverflow) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
} else {
|
|
119
|
-
return `calc(-${initialItemOffset.value} * ${itemWidth.value}px - (2 * var(--_carousel-item-track-gap)))` // Good
|
|
120
|
-
}
|
|
112
|
+
// if (props.allowCarouselOverflow) {
|
|
113
|
+
if (props.useFlipAnimation) {
|
|
114
|
+
return `calc(-${initialItemOffset.value} * ${itemWidth.value}px - var(--_carousel-item-track-gap))` // Good
|
|
121
115
|
} else {
|
|
122
|
-
|
|
123
|
-
return `calc(-${initialItemOffset.value} * ${itemWidth.value}px - var(--_carousel-item-track-gap))` // Goof
|
|
124
|
-
} else {
|
|
125
|
-
return `calc(-${initialItemOffset.value} * ${itemWidth.value}px - (2 * var(--_carousel-item-track-gap)))` // Good
|
|
126
|
-
}
|
|
116
|
+
return `calc(-${initialItemOffset.value} * ${itemWidth.value}px - (2 * var(--_carousel-item-track-gap)))` // Good
|
|
127
117
|
}
|
|
118
|
+
// } else {
|
|
119
|
+
// if (props.useFlipAnimation) {
|
|
120
|
+
// return `calc(-${initialItemOffset.value} * ${itemWidth.value}px - var(--_carousel-item-track-gap))` // Goof
|
|
121
|
+
// } else {
|
|
122
|
+
// return `calc(-${initialItemOffset.value} * ${itemWidth.value}px - (2 * var(--_carousel-item-track-gap)))` // Good
|
|
123
|
+
// }
|
|
124
|
+
// }
|
|
128
125
|
})
|
|
129
126
|
const currentActiveIndex = ref(0)
|
|
130
127
|
|
|
128
|
+
// Computed property to get the display index (what the user sees as active)
|
|
129
|
+
const displayActiveIndex = computed(() => {
|
|
130
|
+
return currentActiveIndex.value
|
|
131
|
+
})
|
|
132
|
+
|
|
131
133
|
const updateItemOrder = (index: number, order: number, zIndex: number = 2) => {
|
|
132
134
|
if (carouselItemsRef?.value && carouselItemsRef.value[index]) {
|
|
133
|
-
|
|
135
|
+
if (order !== -1) {
|
|
136
|
+
carouselItemsRef.value[index].style.order = order.toString()
|
|
137
|
+
}
|
|
134
138
|
carouselItemsRef.value[index].style.zIndex = zIndex.toString()
|
|
135
139
|
}
|
|
136
140
|
}
|
|
@@ -144,8 +148,17 @@ function analyzeOffsets(offsets: number[]) {
|
|
|
144
148
|
|
|
145
149
|
const sorted = [...counts.entries()].sort((a, b) => b[1] - a[1])
|
|
146
150
|
|
|
147
|
-
|
|
148
|
-
|
|
151
|
+
// Handle empty sorted array
|
|
152
|
+
if (sorted.length === 0) {
|
|
153
|
+
return {
|
|
154
|
+
majorityValue: 0,
|
|
155
|
+
minorityValue: 0,
|
|
156
|
+
minorityIndex: -1,
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const majorityValue = sorted[0]![0]
|
|
161
|
+
const minorityValue = sorted[sorted.length - 1]![0]
|
|
149
162
|
const minorityIndex = offsets.findIndex((val) => val === minorityValue)
|
|
150
163
|
|
|
151
164
|
return {
|
|
@@ -161,32 +174,58 @@ const reorderItems = (direction: "next" | "previous" | "jump" = "jump", skipAnim
|
|
|
161
174
|
// Capture positions before reordering (only if we're going to animate)
|
|
162
175
|
const beforeRects = skipAnimation ? [] : carouselItemsRef.value.map((item) => item.getBoundingClientRect())
|
|
163
176
|
|
|
164
|
-
//
|
|
177
|
+
// Store current order positions before reordering
|
|
178
|
+
const currentOrderMap = new Map<number, number>()
|
|
179
|
+
if (!skipAnimation) {
|
|
180
|
+
carouselItemsRef.value.forEach((item, index) => {
|
|
181
|
+
const currentOrder = parseInt(item.style.order || "1")
|
|
182
|
+
currentOrderMap.set(index, currentOrder)
|
|
183
|
+
})
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Apply new order and calculate z-index based on order transition
|
|
165
187
|
let order = 1
|
|
166
188
|
|
|
167
|
-
//
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
if (i === currentActiveIndex.value) {
|
|
172
|
-
// The item becoming visible
|
|
173
|
-
if (direction === "previous") {
|
|
174
|
-
// When going previous, the item moving to first position should go behind
|
|
175
|
-
zIndex = 1
|
|
176
|
-
} else {
|
|
177
|
-
// Normal case - visible item gets highest z-index
|
|
178
|
-
zIndex = 3
|
|
179
|
-
}
|
|
180
|
-
}
|
|
189
|
+
// Helper function to determine if an item should go behind during transition
|
|
190
|
+
const shouldGoBehind = (currentOrder: number, newOrder: number) => {
|
|
191
|
+
// Normal case: moving to higher order (left to right)
|
|
192
|
+
if (currentOrder < newOrder) return true
|
|
181
193
|
|
|
182
|
-
|
|
194
|
+
// Wrap case: moving from end to beginning (high order to low order with big gap)
|
|
195
|
+
// This happens when an item at the end wraps to the beginning
|
|
196
|
+
const orderDifference = Math.abs(currentOrder - newOrder)
|
|
197
|
+
const isWrapping = orderDifference > itemCount.value / 2
|
|
198
|
+
if (isWrapping && currentOrder > newOrder) return true
|
|
199
|
+
|
|
200
|
+
return false
|
|
183
201
|
}
|
|
184
202
|
|
|
185
|
-
//
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
203
|
+
// First, place the previous item (for visual continuity)
|
|
204
|
+
const prevIndex = currentActiveIndex.value === 0 ? itemCount.value - 1 : currentActiveIndex.value - 1
|
|
205
|
+
const prevCurrentOrder = currentOrderMap.get(prevIndex) || 1
|
|
206
|
+
const prevNewOrder = order++
|
|
207
|
+
const prevZIndex = shouldGoBehind(prevCurrentOrder, prevNewOrder) ? 1 : 2
|
|
208
|
+
updateItemOrder(prevIndex, prevNewOrder, prevZIndex)
|
|
209
|
+
|
|
210
|
+
// Then place the current active item
|
|
211
|
+
const currentOrder = currentOrderMap.get(currentActiveIndex.value) || 1
|
|
212
|
+
const newCurrentOrder = order++
|
|
213
|
+
const currentZIndex = shouldGoBehind(currentOrder, newCurrentOrder) ? 1 : 2
|
|
214
|
+
updateItemOrder(currentActiveIndex.value, newCurrentOrder, currentZIndex)
|
|
215
|
+
|
|
216
|
+
// Then place all remaining items in sequence
|
|
217
|
+
let nextIndex = currentActiveIndex.value + 1
|
|
218
|
+
while (nextIndex !== prevIndex) {
|
|
219
|
+
if (nextIndex >= itemCount.value) {
|
|
220
|
+
nextIndex = 0 // Wrap around
|
|
221
|
+
}
|
|
222
|
+
if (nextIndex === prevIndex) break // Don't place the previous item again
|
|
223
|
+
|
|
224
|
+
const itemCurrentOrder = currentOrderMap.get(nextIndex) || 1
|
|
225
|
+
const itemNewOrder = order++
|
|
226
|
+
const itemZIndex = shouldGoBehind(itemCurrentOrder, itemNewOrder) ? 1 : 2
|
|
227
|
+
updateItemOrder(nextIndex, itemNewOrder, itemZIndex)
|
|
228
|
+
nextIndex++
|
|
190
229
|
}
|
|
191
230
|
|
|
192
231
|
// Skip animation if requested (for initial setup)
|
|
@@ -201,15 +240,20 @@ const reorderItems = (direction: "next" | "previous" | "jump" = "jump", skipAnim
|
|
|
201
240
|
// Calculate offset values
|
|
202
241
|
const offsetValues = beforeRects.map((beforeRect, index) => {
|
|
203
242
|
const afterRect = afterRects[index]
|
|
204
|
-
return beforeRect.left - afterRect.left
|
|
243
|
+
return beforeRect.left - (afterRect?.left ?? beforeRect.left)
|
|
205
244
|
})
|
|
206
245
|
|
|
207
246
|
const leftValues = analyzeOffsets(offsetValues)
|
|
208
247
|
|
|
209
248
|
carouselItemsRef.value!.forEach((item, index) => {
|
|
210
|
-
const
|
|
249
|
+
const beforeRect = beforeRects[index]
|
|
250
|
+
const afterRect = afterRects[index]
|
|
251
|
+
const deltaX = (beforeRect?.left ?? 0) - (afterRect?.left ?? 0)
|
|
252
|
+
const timingFunction = props.useSpringEffect ? "var(--spring-easing)" : "ease"
|
|
211
253
|
|
|
212
254
|
if (deltaX !== 0) {
|
|
255
|
+
// Optimize for upcoming transform animation
|
|
256
|
+
item.style.willChange = "transform"
|
|
213
257
|
item.style.transition = "none"
|
|
214
258
|
item.style.transform = `translateX(${deltaX}px)`
|
|
215
259
|
|
|
@@ -220,18 +264,18 @@ const reorderItems = (direction: "next" | "previous" | "jump" = "jump", skipAnim
|
|
|
220
264
|
if (shouldTransition) {
|
|
221
265
|
if (props.allowCarouselOverflow) {
|
|
222
266
|
if (props.useFlipAnimation) {
|
|
223
|
-
transitionProperties = `transform ${transitionSpeedStr}
|
|
267
|
+
transitionProperties = `transform ${transitionSpeedStr} ${timingFunction}`
|
|
224
268
|
} else {
|
|
225
269
|
if (leftValues.minorityIndex !== index) {
|
|
226
|
-
transitionProperties = `transform ${transitionSpeedStr}
|
|
270
|
+
transitionProperties = `transform ${transitionSpeedStr} ${timingFunction}`
|
|
227
271
|
}
|
|
228
272
|
}
|
|
229
273
|
} else {
|
|
230
274
|
if (props.useFlipAnimation) {
|
|
231
|
-
transitionProperties = `transform ${transitionSpeedStr}
|
|
275
|
+
transitionProperties = `transform ${transitionSpeedStr} ${timingFunction}`
|
|
232
276
|
} else {
|
|
233
277
|
if (leftValues.minorityIndex !== index) {
|
|
234
|
-
transitionProperties = `transform ${transitionSpeedStr}
|
|
278
|
+
transitionProperties = `transform ${transitionSpeedStr} ${timingFunction}`
|
|
235
279
|
}
|
|
236
280
|
}
|
|
237
281
|
}
|
|
@@ -240,12 +284,10 @@ const reorderItems = (direction: "next" | "previous" | "jump" = "jump", skipAnim
|
|
|
240
284
|
item.style.transition = transitionProperties
|
|
241
285
|
item.style.transform = "translateX(0)"
|
|
242
286
|
|
|
243
|
-
// After animation completes,
|
|
287
|
+
// After animation completes, clean up will-change (keep z-index as set)
|
|
244
288
|
const handleTransitionEnd = (event: TransitionEvent) => {
|
|
245
289
|
if (event.propertyName === "transform") {
|
|
246
|
-
|
|
247
|
-
const isCurrentlyVisible = index === currentActiveIndex.value
|
|
248
|
-
item.style.zIndex = isCurrentlyVisible ? "3" : "2"
|
|
290
|
+
item.style.willChange = "auto"
|
|
249
291
|
item.removeEventListener("transitionend", handleTransitionEnd)
|
|
250
292
|
}
|
|
251
293
|
}
|
|
@@ -253,9 +295,8 @@ const reorderItems = (direction: "next" | "previous" | "jump" = "jump", skipAnim
|
|
|
253
295
|
if (shouldTransition) {
|
|
254
296
|
item.addEventListener("transitionend", handleTransitionEnd)
|
|
255
297
|
} else {
|
|
256
|
-
// If no transition,
|
|
257
|
-
|
|
258
|
-
item.style.zIndex = isCurrentlyVisible ? "3" : "2"
|
|
298
|
+
// If no transition, just clean up will-change (keep z-index as set)
|
|
299
|
+
item.style.willChange = "auto"
|
|
259
300
|
}
|
|
260
301
|
})
|
|
261
302
|
}
|
|
@@ -300,20 +341,18 @@ const jumpToFrame = (index: number) => {
|
|
|
300
341
|
userHasInteracted.value = true
|
|
301
342
|
}
|
|
302
343
|
|
|
303
|
-
currentActiveIndex.value =
|
|
344
|
+
currentActiveIndex.value = index
|
|
304
345
|
|
|
305
|
-
// currentActiveIndex.value = index;
|
|
306
346
|
reorderItems("jump")
|
|
307
347
|
currentIndex.value = currentActiveIndex.value
|
|
308
348
|
}
|
|
309
349
|
}
|
|
310
350
|
|
|
311
351
|
const checkAndMoveLastItem = () => {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
352
|
+
// We need to reorder items for the initial layout regardless of the settings
|
|
353
|
+
// Keep currentActiveIndex at 0 (first item) but reorder visually
|
|
354
|
+
reorderItems("jump", true) // Skip animation during initial setup
|
|
355
|
+
currentIndex.value = currentActiveIndex.value
|
|
317
356
|
}
|
|
318
357
|
|
|
319
358
|
const initialSetup = () => {
|
|
@@ -331,6 +370,13 @@ const initialSetup = () => {
|
|
|
331
370
|
|
|
332
371
|
carouselInitComplete.value = true
|
|
333
372
|
checkAndMoveLastItem()
|
|
373
|
+
|
|
374
|
+
// Add mounted class to trigger opacity transition after setup is complete
|
|
375
|
+
nextTick(() => {
|
|
376
|
+
if (carouselWrapperRef.value) {
|
|
377
|
+
carouselWrapperRef.value.classList.add("mounted")
|
|
378
|
+
}
|
|
379
|
+
})
|
|
334
380
|
}
|
|
335
381
|
|
|
336
382
|
const { direction } = useSwipe(carouselContainerRef, {
|
|
@@ -376,6 +422,11 @@ onMounted(() => {
|
|
|
376
422
|
display: grid;
|
|
377
423
|
grid-template-columns: 1fr;
|
|
378
424
|
gap: 10px;
|
|
425
|
+
opacity: 0;
|
|
426
|
+
|
|
427
|
+
&.mounted {
|
|
428
|
+
opacity: 1;
|
|
429
|
+
}
|
|
379
430
|
|
|
380
431
|
.sr-only {
|
|
381
432
|
position: absolute;
|
|
@@ -394,6 +445,7 @@ onMounted(() => {
|
|
|
394
445
|
gap: var(--_carousel-item-track-gap);
|
|
395
446
|
overflow-x: hidden;
|
|
396
447
|
position: relative;
|
|
448
|
+
isolation: isolate;
|
|
397
449
|
|
|
398
450
|
max-inline-size: var(--_carousel-display-max-width);
|
|
399
451
|
margin-inline: auto;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div class="expanding-panel" :class="[elementClasses]">
|
|
3
3
|
<details class="expanding-panel-details" :name :open>
|
|
4
4
|
<summary
|
|
5
|
-
@click.prevent="handleToggle"
|
|
5
|
+
@click.prevent.stop="handleToggle"
|
|
6
6
|
@keydown.enter.prevent="handleToggle"
|
|
7
7
|
@keydown.space.prevent="handleToggle"
|
|
8
8
|
class="expanding-panel-summary"
|
|
@@ -56,7 +56,7 @@ const props = defineProps({
|
|
|
56
56
|
},
|
|
57
57
|
})
|
|
58
58
|
|
|
59
|
-
const name =
|
|
59
|
+
const name = shallowRef(props.name || useId())
|
|
60
60
|
const isPanelOpen = defineModel({ default: false }) as Ref<boolean>
|
|
61
61
|
const animationDurationStr = computed(() => `${props.animationDuration}ms`)
|
|
62
62
|
const open = computed(() => {
|
|
@@ -76,6 +76,9 @@ const handleToggle = (event: Event) => {
|
|
|
76
76
|
<style lang="css">
|
|
77
77
|
.expanding-panel {
|
|
78
78
|
.expanding-panel-details {
|
|
79
|
+
&:hover {
|
|
80
|
+
cursor: pointer;
|
|
81
|
+
}
|
|
79
82
|
.expanding-panel-summary {
|
|
80
83
|
display: flex;
|
|
81
84
|
align-items: center;
|
|
@@ -109,6 +112,7 @@ const handleToggle = (event: Event) => {
|
|
|
109
112
|
transform: scaleY(1);
|
|
110
113
|
transition: transform v-bind(animationDurationStr) ease-in-out;
|
|
111
114
|
font-size: 1.2rem;
|
|
115
|
+
will-change: transform;
|
|
112
116
|
}
|
|
113
117
|
}
|
|
114
118
|
}
|
|
@@ -134,6 +138,7 @@ const handleToggle = (event: Event) => {
|
|
|
134
138
|
display: grid;
|
|
135
139
|
grid-template-rows: 0fr;
|
|
136
140
|
transition: all v-bind(animationDurationStr) ease-in-out;
|
|
141
|
+
will-change: grid-template-rows;
|
|
137
142
|
|
|
138
143
|
.inner {
|
|
139
144
|
overflow: hidden;
|
package/app/types/index.ts
CHANGED
|
@@ -3,3 +3,4 @@ export * from "../components/display-chip/DisplayChip.vue"
|
|
|
3
3
|
export * from "../components/carousel-basic/CarouselBasic.vue"
|
|
4
4
|
export * from "../components/image-galleries/SliderGallery.vue"
|
|
5
5
|
export * from "../components/display-toast/DisplayToast.vue"
|
|
6
|
+
export * from "../components/alert-mask/AlertMaskCore.vue"
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "srcdev-nuxt-components",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "6.2.
|
|
4
|
+
"version": "6.2.3",
|
|
5
5
|
"main": "nuxt.config.ts",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"clean": "rm -rf .nuxt && rm -rf .output && rm -rf .playground/.nuxt && rm -rf .playground/.output",
|
|
@@ -23,19 +23,23 @@
|
|
|
23
23
|
],
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@iconify-json/akar-icons": "1.2.7",
|
|
26
|
+
"@iconify-json/bi": "1.2.6",
|
|
26
27
|
"@iconify-json/bitcoin-icons": "1.2.4",
|
|
27
|
-
"@iconify-json/
|
|
28
|
-
"@
|
|
29
|
-
"@
|
|
30
|
-
"@nuxt/
|
|
31
|
-
"@
|
|
32
|
-
"@
|
|
33
|
-
"
|
|
28
|
+
"@iconify-json/gravity-ui": "1.2.10",
|
|
29
|
+
"@iconify-json/material-symbols": "1.2.44",
|
|
30
|
+
"@iconify-json/mdi": "1.2.3",
|
|
31
|
+
"@nuxt/eslint": "1.10.0",
|
|
32
|
+
"@nuxt/icon": "2.1.0",
|
|
33
|
+
"@nuxt/image": "2.0.0",
|
|
34
|
+
"@nuxtjs/i18n": "10.2.0",
|
|
35
|
+
"@vueuse/core": "14.0.0",
|
|
36
|
+
"eslint": "9.39.1",
|
|
34
37
|
"focus-trap-vue": "4.1.0",
|
|
35
|
-
"happy-dom": "
|
|
36
|
-
"nuxt": "4.1
|
|
37
|
-
"
|
|
38
|
-
"
|
|
38
|
+
"happy-dom": "20.0.10",
|
|
39
|
+
"nuxt": "4.2.1",
|
|
40
|
+
"patch-package": "8.0.1",
|
|
41
|
+
"release-it": "19.0.6",
|
|
42
|
+
"typescript": "5.9.3"
|
|
39
43
|
},
|
|
40
44
|
"release-it": {
|
|
41
45
|
"$schema": "https://unpkg.com/release-it/schema/release-it.json",
|