srcdev-nuxt-components 6.1.42 → 6.2.0

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.
@@ -9,7 +9,7 @@
9
9
  </template>
10
10
 
11
11
  <script setup lang="ts">
12
- import { useBreakpoints, useElementSize, useResizeObserver } from "@vueuse/core"
12
+ import { useElementSize, useResizeObserver } from "@vueuse/core"
13
13
 
14
14
  const props = defineProps({
15
15
  gridData: {
@@ -0,0 +1,144 @@
1
+ <template>
2
+ <component
3
+ :is="tag"
4
+ class="wipe-away-vertical"
5
+ :class="[elementClasses]"
6
+ :style="{ 'timeline-scope': timelineScope }"
7
+ ref="scrollContainerRef"
8
+ >
9
+ <div ref="stickyItemsContainerRef" class="sticky-items-container">
10
+ <div
11
+ class="sticky-item"
12
+ v-for="(item, key) in itemCount"
13
+ :key="key"
14
+ :style="{
15
+ 'animation-timeline': key === itemCount - 1 ? 'none' : `--section-${timelineId}-${key}`,
16
+ 'z-index': itemCount - key,
17
+ }"
18
+ >
19
+ <slot :name="`stickyItem-${key}`"></slot>
20
+ </div>
21
+ </div>
22
+
23
+ <section
24
+ v-for="(item, key) in itemCount"
25
+ :key="key"
26
+ class="scrolling-section"
27
+ :style="{
28
+ 'view-timeline-name': `--section-${timelineId}-${key}`,
29
+ }"
30
+ >
31
+ <slot :name="`scrollingItem-${key}`"></slot>
32
+ </section>
33
+ </component>
34
+ </template>
35
+
36
+ <script setup lang="ts">
37
+ const props = defineProps({
38
+ tag: {
39
+ type: String as PropType<"div" | "section" | "main" | "article" | "aside">,
40
+ default: "div",
41
+ validator: (val: string) => ["div", "section", "main", "article", "aside"].includes(val),
42
+ },
43
+ itemCount: {
44
+ type: Number as PropType<number>,
45
+ default: 0,
46
+ },
47
+ styleClassPassthrough: {
48
+ type: [String, Array] as PropType<string | string[]>,
49
+ default: () => [],
50
+ },
51
+ })
52
+
53
+ const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
54
+
55
+ const timelineId = useId()
56
+ const stickyItemsContainerRef = useTemplateRef<HTMLElement | null>("stickyItemsContainerRef")
57
+ const scrollContainerRef = useTemplateRef<HTMLElement | null>("scrollContainerRef")
58
+ const timelineInset = ref("35% 35%")
59
+ const topPercent = ref("0")
60
+ const bottomPercent = ref("0")
61
+
62
+ const timelineScope = computed(() =>
63
+ Array.from({ length: props.itemCount }, (_, i) => `--section-${timelineId}-${i}`).join(", ")
64
+ )
65
+
66
+ const calculateInset = () => {
67
+ if (!stickyItemsContainerRef.value) return
68
+
69
+ const rect = stickyItemsContainerRef.value.getBoundingClientRect()
70
+ const innerHeight = window.innerHeight
71
+
72
+ topPercent.value = ((rect.top / innerHeight) * 100).toFixed(2)
73
+ bottomPercent.value = (((innerHeight - rect.bottom) / innerHeight) * 100).toFixed(2)
74
+
75
+ timelineInset.value = `${topPercent.value}% ${bottomPercent.value}%`
76
+
77
+ if (!scrollContainerRef.value) return
78
+ scrollContainerRef.value.style.setProperty("--calculated-inset", timelineInset.value)
79
+ }
80
+
81
+ let requestAnimationFrameId: number | null = null
82
+ const onScrollDebounce = () => {
83
+ if (requestAnimationFrameId !== null) return
84
+ requestAnimationFrameId = requestAnimationFrame(() => {
85
+ calculateInset()
86
+ requestAnimationFrameId = null
87
+ })
88
+ }
89
+
90
+ watch(
91
+ () => props.styleClassPassthrough,
92
+ () => {
93
+ resetElementClasses(props.styleClassPassthrough)
94
+ }
95
+ )
96
+
97
+ onMounted(() => {
98
+ calculateInset()
99
+ window.addEventListener("scroll", onScrollDebounce)
100
+ })
101
+
102
+ onUnmounted(() => {
103
+ window.removeEventListener("scroll", onScrollDebounce)
104
+ })
105
+ </script>
106
+
107
+ <style lang="css">
108
+ .wipe-away-vertical {
109
+ .sticky-items-container {
110
+ position: sticky;
111
+ top: 50%;
112
+ left: 100%;
113
+ transform: translateY(-50%);
114
+
115
+ .sticky-item {
116
+ position: absolute;
117
+ inset: 0;
118
+ border-radius: 0.5rem;
119
+ width: 100%;
120
+ }
121
+ }
122
+
123
+ .scrolling-section {
124
+ view-timeline-axis: block;
125
+ view-timeline-inset: var(--calculated-inset);
126
+ }
127
+ }
128
+
129
+ @supports (animation-timeline: view()) {
130
+ @keyframes wipe-out {
131
+ 0% {
132
+ clip-path: inset(0 0 0% 0);
133
+ }
134
+ 100% {
135
+ clip-path: inset(0 0 100% 0);
136
+ }
137
+ }
138
+
139
+ .sticky-item {
140
+ animation: wipe-out 1s linear both;
141
+ animation-range: entry 0% entry 100%;
142
+ }
143
+ }
144
+ </style>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "srcdev-nuxt-components",
3
3
  "type": "module",
4
- "version": "6.1.42",
4
+ "version": "6.2.0",
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",