@vikeriait/vue-viewport 1.1.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.
@@ -0,0 +1,330 @@
1
+ import { defineComponent as V, withDirectives as $, createBlock as P, openBlock as I, resolveDynamicComponent as C, withCtx as O, renderSlot as D, unref as T, ref as w, onMounted as _, onUnmounted as A } from "vue";
2
+ const F = [
3
+ "fade",
4
+ "fade-up",
5
+ "fade-down",
6
+ "fade-left",
7
+ "fade-right",
8
+ "slide-up",
9
+ "slide-down",
10
+ "slide-left",
11
+ "slide-right",
12
+ "scale-up",
13
+ "scale-down",
14
+ "blur-in",
15
+ "fade-y",
16
+ "slide-y"
17
+ ], N = F.reduce((e, o) => (e[o] = `animate-${o}`, o.endsWith("-y") || (e[`${o}-up`] = `animate-${o}-up`, e[`${o}-down`] = `animate-${o}-down`), e), {}), x = { ...N };
18
+ function k(e) {
19
+ Object.assign(x, e);
20
+ }
21
+ function W(e) {
22
+ let o = 0, t = 0;
23
+ const n = /(?:(?<prefix>[a-z0-9:-]+):)?(?<neg>-)?translate-y-(?:\[(?<arb>[^\]]+)\]|(?<num>\d+))/gi;
24
+ let s;
25
+ for (; (s = n.exec(e)) !== null; ) {
26
+ const { prefix: r, arb: i, num: u } = s.groups || {};
27
+ let a = 0;
28
+ if (i ? i.endsWith("px") ? a = parseFloat(i) : i.endsWith("rem") && (a = parseFloat(i) * 16) : u && (a = parseInt(u, 10) * 4), a > 0) {
29
+ const l = Math.ceil(a + 10), d = r && r.includes("below"), c = r && r.includes("above");
30
+ d ? t = Math.max(t, l) : c ? o = Math.max(o, l) : (o = Math.max(o, l), t = Math.max(t, l));
31
+ }
32
+ }
33
+ return { top: o, bottom: t };
34
+ }
35
+ function q(e, o) {
36
+ if (o && (o.includes("slide") || o.includes("fade-") && !o.includes("fade-in") || o.includes("scale")))
37
+ try {
38
+ const s = getComputedStyle(e).getPropertyValue("--viewport-distance").trim();
39
+ if (s) {
40
+ let r = 0;
41
+ s.endsWith("px") ? r = parseFloat(s) : s.endsWith("rem") && (r = parseFloat(s) * 16);
42
+ const i = Math.ceil(r);
43
+ return { top: i, bottom: i };
44
+ }
45
+ } catch {
46
+ }
47
+ return { top: 0, bottom: 0 };
48
+ }
49
+ function B(e) {
50
+ try {
51
+ const t = getComputedStyle(e).transform;
52
+ if (t && t !== "none") {
53
+ const n = t.match(/^matrix\((.+)\)$/);
54
+ if (n) {
55
+ const s = n[1].split(",").map(parseFloat);
56
+ if (s.length === 6) {
57
+ const r = Math.abs(s[5]), i = Math.abs(s[4]), u = Math.max(i, r);
58
+ if (u > 0) {
59
+ const a = Math.ceil(u);
60
+ return { top: a, bottom: a };
61
+ }
62
+ }
63
+ }
64
+ }
65
+ } catch {
66
+ }
67
+ return { top: 0, bottom: 0 };
68
+ }
69
+ function L(e, o) {
70
+ const t = W(e.className);
71
+ if (t.top > 0 || t.bottom > 0)
72
+ return `${t.top}px 0px ${t.bottom}px 0px`;
73
+ const n = q(e, o);
74
+ if (n.top > 0 || n.bottom > 0)
75
+ return `${n.top}px 0px ${n.bottom}px 0px`;
76
+ const s = B(e);
77
+ return s.top > 0 || s.bottom > 0 ? `${s.top}px 0px ${s.bottom}px 0px` : "0px";
78
+ }
79
+ class j {
80
+ roots = /* @__PURE__ */ new Map();
81
+ /**
82
+ * Generates a unique key for the observer options.
83
+ */
84
+ getOptionsKey(o, t) {
85
+ const n = Array.isArray(t) ? [...t].sort().join(",") : t;
86
+ return `${o}|${n}`;
87
+ }
88
+ /**
89
+ * Starts observing an element.
90
+ * Reuse an existing observer if one exists with the exact same options.
91
+ */
92
+ observe(o, t, n) {
93
+ const s = t.root || null, r = t.rootMargin || "0px", i = t.threshold ?? 0;
94
+ this.roots.has(s) || this.roots.set(s, /* @__PURE__ */ new Map());
95
+ const u = this.roots.get(s), a = this.getOptionsKey(r, i);
96
+ let l = u.get(a);
97
+ return l || (l = {
98
+ observer: new IntersectionObserver((c) => {
99
+ c.forEach((h) => {
100
+ const E = h.target, b = l?.elements.get(E);
101
+ b && b(h);
102
+ });
103
+ }, {
104
+ root: s,
105
+ rootMargin: r,
106
+ threshold: i
107
+ }),
108
+ elements: /* @__PURE__ */ new Map(),
109
+ root: s,
110
+ key: a
111
+ }, u.set(a, l)), l.observer.observe(o), l.elements.set(o, n), l;
112
+ }
113
+ /**
114
+ * Stops observing an element for a specific observer instance.
115
+ */
116
+ unobserve(o, t) {
117
+ if (o.observer.unobserve(t), o.elements.delete(t), o.elements.size === 0) {
118
+ o.observer.disconnect();
119
+ const n = this.roots.get(o.root);
120
+ n && (n.delete(o.key), n.size === 0 && this.roots.delete(o.root));
121
+ }
122
+ }
123
+ }
124
+ const p = new j();
125
+ function M(e) {
126
+ const { value: o, modifiers: t, arg: n } = e;
127
+ let s = {}, r = n;
128
+ typeof o == "string" ? r = o : typeof o == "object" && o !== null && (s = o, typeof s.animation == "string" && (r = s.animation));
129
+ const i = t.once || s.once || !1;
130
+ return { options: s, animationName: r, once: i };
131
+ }
132
+ function H(e, o) {
133
+ if (typeof e == "number") return e;
134
+ if (typeof e == "string") return g(e);
135
+ if (e === !0) {
136
+ const n = getComputedStyle(o).getPropertyValue("--viewport-stagger").trim();
137
+ return g(n || "100ms");
138
+ }
139
+ return 0;
140
+ }
141
+ function R(e, o, t, n) {
142
+ const s = { el: e, entry: o, direction: t, options: n }, r = H(n.stagger, e);
143
+ r > 0 ? Q(s, r) : y(s, 0);
144
+ }
145
+ function Y(e, o, t, n) {
146
+ n.delay !== void 0 ? e.style.transitionDelay = v(n.delay) : e.style.removeProperty("transition-delay"), delete e.dataset.vpInView, delete e.dataset.vpEntry;
147
+ const s = o.boundingClientRect;
148
+ s.top < 0 ? e.dataset.vpPos = "above" : s.bottom > window.innerHeight && (e.dataset.vpPos = "below"), n.onLeave?.(o, t), e.dispatchEvent(new CustomEvent("view-leave", {
149
+ detail: { entry: o, direction: t }
150
+ }));
151
+ }
152
+ const f = /* @__PURE__ */ new WeakMap(), m = /* @__PURE__ */ new WeakMap();
153
+ function g(e) {
154
+ if (!e) return 0;
155
+ const o = e.split(",").map((t) => {
156
+ const n = /([\d.]+)(m?s)/.exec(t.trim());
157
+ if (!n) return 0;
158
+ const s = parseFloat(n[1]);
159
+ return n[2] === "s" ? s * 1e3 : s;
160
+ });
161
+ return Math.max(...o);
162
+ }
163
+ function y(e, o = 0) {
164
+ const { el: t, entry: n, direction: s, options: r } = e;
165
+ let i = o;
166
+ if (o > 0) {
167
+ const u = getComputedStyle(t), a = g(u.transitionDelay);
168
+ i += a;
169
+ }
170
+ i > 0 && (t.style.transitionDelay = `${i}ms`), t.dataset.vpEntry = s, delete t.dataset.vpPos, r.onEnter?.(n, s), t.dispatchEvent(new CustomEvent("view-enter", {
171
+ detail: { entry: n, direction: s }
172
+ })), requestAnimationFrame(() => {
173
+ t.dataset.vpInView = "";
174
+ });
175
+ }
176
+ function z(e, o) {
177
+ const t = m.get(e);
178
+ if (!t || t.queue.length === 0) return;
179
+ t.queue.sort((s, r) => s.el.compareDocumentPosition(r.el) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1).forEach((s, r) => {
180
+ y(s, r * o);
181
+ }), t.queue = [];
182
+ }
183
+ function Q(e, o) {
184
+ const t = e.el.parentElement;
185
+ if (!t) {
186
+ y(e, 0);
187
+ return;
188
+ }
189
+ let n = m.get(t);
190
+ n || (n = { queue: [], timeout: 0 }, m.set(t, n)), n.queue.push(e), n.timeout && clearTimeout(n.timeout), n.timeout = window.setTimeout(() => {
191
+ z(t, o);
192
+ }, 10);
193
+ }
194
+ function v(e) {
195
+ return typeof e == "number" ? `${e}ms` : e;
196
+ }
197
+ const S = {
198
+ // Apply the preset attribute in beforeMount
199
+ beforeMount(e, o) {
200
+ e.dataset.vpMounted = "";
201
+ const { options: t, animationName: n } = M(o);
202
+ if (t.duration !== void 0 && (e.style.transitionDuration = v(t.duration)), t.delay !== void 0 && (e.style.transitionDelay = v(t.delay)), t.easing !== void 0 && (e.style.transitionTimingFunction = t.easing), n) {
203
+ const r = n.split(/\s+/).map((i) => x[i]).filter((i) => !!i).join(" ");
204
+ r && (e.dataset.vpPreset = r), e.dataset.vpEntry = "down";
205
+ }
206
+ },
207
+ mounted(e, o) {
208
+ const { options: t, animationName: n, once: s } = M(o), r = {
209
+ root: t.root || null,
210
+ rootMargin: t.rootMargin || L(e, n),
211
+ threshold: t.threshold ?? 0.1
212
+ };
213
+ let i = window.scrollY;
214
+ const u = p.observe(e, r, (a) => {
215
+ const l = a.isIntersecting, d = window.scrollY, c = d >= i ? "down" : "up";
216
+ i = d, l ? (R(e, a, c, t), s && p.unobserve(u, e)) : Y(e, a, c, t);
217
+ });
218
+ f.set(e, u);
219
+ },
220
+ unmounted(e) {
221
+ const o = f.get(e);
222
+ o && (p.unobserve(o, e), f.delete(e));
223
+ }
224
+ }, U = /* @__PURE__ */ V({
225
+ name: "Viewport",
226
+ __name: "Viewport",
227
+ props: {
228
+ /** The HTML tag to render. Defaults to 'div'. */
229
+ as: {
230
+ type: String,
231
+ default: "div"
232
+ },
233
+ /** The animation preset name (e.g., 'fade-up'). */
234
+ preset: {
235
+ type: String,
236
+ default: void 0
237
+ },
238
+ /** Delay in ms or CSS string (e.g. '100ms'). Set to true to use global variable. */
239
+ stagger: {
240
+ type: [Number, String, Boolean],
241
+ default: void 0
242
+ },
243
+ /** Intersection threshold (0.0 - 1.0). */
244
+ threshold: {
245
+ type: [Number, Array],
246
+ default: void 0
247
+ },
248
+ /** Custom rootMargin string. */
249
+ rootMargin: {
250
+ type: String,
251
+ default: void 0
252
+ },
253
+ /** If true, disconnects the observer after the first entry. */
254
+ once: {
255
+ type: Boolean,
256
+ default: !1
257
+ },
258
+ /** Custom root element (defaults to viewport). */
259
+ root: {
260
+ type: Object,
261
+ default: void 0
262
+ },
263
+ /** Custom duration for the animation. */
264
+ duration: {
265
+ type: [Number, String],
266
+ default: void 0
267
+ },
268
+ /** Custom delay for the animation. */
269
+ delay: {
270
+ type: [Number, String],
271
+ default: void 0
272
+ },
273
+ /** Custom easing for the animation. */
274
+ easing: {
275
+ type: String,
276
+ default: void 0
277
+ }
278
+ },
279
+ emits: ["enter", "leave"],
280
+ setup(e, { emit: o }) {
281
+ const t = e, n = o, s = {
282
+ animation: t.preset,
283
+ stagger: t.stagger,
284
+ threshold: t.threshold,
285
+ rootMargin: t.rootMargin,
286
+ once: t.once,
287
+ root: t.root,
288
+ duration: t.duration,
289
+ delay: t.delay,
290
+ easing: t.easing,
291
+ onEnter: (r, i) => {
292
+ n("enter", { entry: r, direction: i });
293
+ },
294
+ onLeave: (r, i) => {
295
+ n("leave", { entry: r, direction: i });
296
+ }
297
+ };
298
+ return (r, i) => $((I(), P(C(t.as), null, {
299
+ default: O(() => [
300
+ D(r.$slots, "default")
301
+ ]),
302
+ _: 3
303
+ })), [
304
+ [T(S), s]
305
+ ]);
306
+ }
307
+ });
308
+ function G(e, o = {}) {
309
+ const t = w(!1), n = w(null);
310
+ let s = null, r = null;
311
+ return _(() => {
312
+ e.value && (r = e.value, s = p.observe(r, o, (i) => {
313
+ t.value = i.isIntersecting, n.value = i;
314
+ }));
315
+ }), A(() => {
316
+ s && r && p.unobserve(s, r);
317
+ }), { isInView: t, entry: n };
318
+ }
319
+ const J = {
320
+ install(e, o) {
321
+ o?.presets && k(o.presets), e.directive("viewport", S), e.component("VViewport", U);
322
+ }
323
+ };
324
+ export {
325
+ U as Viewport,
326
+ J as ViewportPlugin,
327
+ J as default,
328
+ G as useInViewport,
329
+ S as vViewport
330
+ };
@@ -0,0 +1 @@
1
+ (function(d,l){typeof exports=="object"&&typeof module<"u"?l(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],l):(d=typeof globalThis<"u"?globalThis:d||self,l(d.VueViewport={},d.Vue))})(this,(function(d,l){"use strict";const M={...["fade","fade-up","fade-down","fade-left","fade-right","slide-up","slide-down","slide-left","slide-right","scale-up","scale-down","blur-in","fade-y","slide-y"].reduce((t,o)=>(t[o]=`animate-${o}`,o.endsWith("-y")||(t[`${o}-up`]=`animate-${o}-up`,t[`${o}-down`]=`animate-${o}-down`),t),{})};function I(t){Object.assign(M,t)}function T(t){let o=0,e=0;const n=/(?:(?<prefix>[a-z0-9:-]+):)?(?<neg>-)?translate-y-(?:\[(?<arb>[^\]]+)\]|(?<num>\d+))/gi;let s;for(;(s=n.exec(t))!==null;){const{prefix:r,arb:i,num:c}=s.groups||{};let a=0;if(i?i.endsWith("px")?a=parseFloat(i):i.endsWith("rem")&&(a=parseFloat(i)*16):c&&(a=parseInt(c,10)*4),a>0){const u=Math.ceil(a+10),m=r&&r.includes("below"),p=r&&r.includes("above");m?e=Math.max(e,u):p?o=Math.max(o,u):(o=Math.max(o,u),e=Math.max(e,u))}}return{top:o,bottom:e}}function $(t,o){if(o&&(o.includes("slide")||o.includes("fade-")&&!o.includes("fade-in")||o.includes("scale")))try{const s=getComputedStyle(t).getPropertyValue("--viewport-distance").trim();if(s){let r=0;s.endsWith("px")?r=parseFloat(s):s.endsWith("rem")&&(r=parseFloat(s)*16);const i=Math.ceil(r);return{top:i,bottom:i}}}catch{}return{top:0,bottom:0}}function O(t){try{const e=getComputedStyle(t).transform;if(e&&e!=="none"){const n=e.match(/^matrix\((.+)\)$/);if(n){const s=n[1].split(",").map(parseFloat);if(s.length===6){const r=Math.abs(s[5]),i=Math.abs(s[4]),c=Math.max(i,r);if(c>0){const a=Math.ceil(c);return{top:a,bottom:a}}}}}}catch{}return{top:0,bottom:0}}function _(t,o){const e=T(t.className);if(e.top>0||e.bottom>0)return`${e.top}px 0px ${e.bottom}px 0px`;const n=$(t,o);if(n.top>0||n.bottom>0)return`${n.top}px 0px ${n.bottom}px 0px`;const s=O(t);return s.top>0||s.bottom>0?`${s.top}px 0px ${s.bottom}px 0px`:"0px"}class A{roots=new Map;getOptionsKey(o,e){const n=Array.isArray(e)?[...e].sort().join(","):e;return`${o}|${n}`}observe(o,e,n){const s=e.root||null,r=e.rootMargin||"0px",i=e.threshold??0;this.roots.has(s)||this.roots.set(s,new Map);const c=this.roots.get(s),a=this.getOptionsKey(r,i);let u=c.get(a);return u||(u={observer:new IntersectionObserver(p=>{p.forEach(V=>{const j=V.target,P=u?.elements.get(j);P&&P(V)})},{root:s,rootMargin:r,threshold:i}),elements:new Map,root:s,key:a},c.set(a,u)),u.observer.observe(o),u.elements.set(o,n),u}unobserve(o,e){if(o.observer.unobserve(e),o.elements.delete(e),o.elements.size===0){o.observer.disconnect();const n=this.roots.get(o.root);n&&(n.delete(o.key),n.size===0&&this.roots.delete(o.root))}}}const f=new A;function x(t){const{value:o,modifiers:e,arg:n}=t;let s={},r=n;typeof o=="string"?r=o:typeof o=="object"&&o!==null&&(s=o,typeof s.animation=="string"&&(r=s.animation));const i=e.once||s.once||!1;return{options:s,animationName:r,once:i}}function C(t,o){if(typeof t=="number")return t;if(typeof t=="string")return v(t);if(t===!0){const n=getComputedStyle(o).getPropertyValue("--viewport-stagger").trim();return v(n||"100ms")}return 0}function D(t,o,e,n){const s={el:t,entry:o,direction:e,options:n},r=C(n.stagger,t);r>0?k(s,r):h(s,0)}function N(t,o,e,n){n.delay!==void 0?t.style.transitionDelay=b(n.delay):t.style.removeProperty("transition-delay"),delete t.dataset.vpInView,delete t.dataset.vpEntry;const s=o.boundingClientRect;s.top<0?t.dataset.vpPos="above":s.bottom>window.innerHeight&&(t.dataset.vpPos="below"),n.onLeave?.(o,e),t.dispatchEvent(new CustomEvent("view-leave",{detail:{entry:o,direction:e}}))}const g=new WeakMap,y=new WeakMap;function v(t){if(!t)return 0;const o=t.split(",").map(e=>{const n=/([\d.]+)(m?s)/.exec(e.trim());if(!n)return 0;const s=parseFloat(n[1]);return n[2]==="s"?s*1e3:s});return Math.max(...o)}function h(t,o=0){const{el:e,entry:n,direction:s,options:r}=t;let i=o;if(o>0){const c=getComputedStyle(e),a=v(c.transitionDelay);i+=a}i>0&&(e.style.transitionDelay=`${i}ms`),e.dataset.vpEntry=s,delete e.dataset.vpPos,r.onEnter?.(n,s),e.dispatchEvent(new CustomEvent("view-enter",{detail:{entry:n,direction:s}})),requestAnimationFrame(()=>{e.dataset.vpInView=""})}function F(t,o){const e=y.get(t);if(!e||e.queue.length===0)return;e.queue.sort((s,r)=>s.el.compareDocumentPosition(r.el)&Node.DOCUMENT_POSITION_FOLLOWING?-1:1).forEach((s,r)=>{h(s,r*o)}),e.queue=[]}function k(t,o){const e=t.el.parentElement;if(!e){h(t,0);return}let n=y.get(e);n||(n={queue:[],timeout:0},y.set(e,n)),n.queue.push(t),n.timeout&&clearTimeout(n.timeout),n.timeout=window.setTimeout(()=>{F(e,o)},10)}function b(t){return typeof t=="number"?`${t}ms`:t}const w={beforeMount(t,o){t.dataset.vpMounted="";const{options:e,animationName:n}=x(o);if(e.duration!==void 0&&(t.style.transitionDuration=b(e.duration)),e.delay!==void 0&&(t.style.transitionDelay=b(e.delay)),e.easing!==void 0&&(t.style.transitionTimingFunction=e.easing),n){const r=n.split(/\s+/).map(i=>M[i]).filter(i=>!!i).join(" ");r&&(t.dataset.vpPreset=r),t.dataset.vpEntry="down"}},mounted(t,o){const{options:e,animationName:n,once:s}=x(o),r={root:e.root||null,rootMargin:e.rootMargin||_(t,n),threshold:e.threshold??.1};let i=window.scrollY;const c=f.observe(t,r,a=>{const u=a.isIntersecting,m=window.scrollY,p=m>=i?"down":"up";i=m,u?(D(t,a,p,e),s&&f.unobserve(c,t)):N(t,a,p,e)});g.set(t,c)},unmounted(t){const o=g.get(t);o&&(f.unobserve(o,t),g.delete(t))}},S=l.defineComponent({name:"Viewport",__name:"Viewport",props:{as:{type:String,default:"div"},preset:{type:String,default:void 0},stagger:{type:[Number,String,Boolean],default:void 0},threshold:{type:[Number,Array],default:void 0},rootMargin:{type:String,default:void 0},once:{type:Boolean,default:!1},root:{type:Object,default:void 0},duration:{type:[Number,String],default:void 0},delay:{type:[Number,String],default:void 0},easing:{type:String,default:void 0}},emits:["enter","leave"],setup(t,{emit:o}){const e=t,n=o,s={animation:e.preset,stagger:e.stagger,threshold:e.threshold,rootMargin:e.rootMargin,once:e.once,root:e.root,duration:e.duration,delay:e.delay,easing:e.easing,onEnter:(r,i)=>{n("enter",{entry:r,direction:i})},onLeave:(r,i)=>{n("leave",{entry:r,direction:i})}};return(r,i)=>l.withDirectives((l.openBlock(),l.createBlock(l.resolveDynamicComponent(e.as),null,{default:l.withCtx(()=>[l.renderSlot(r.$slots,"default")]),_:3})),[[l.unref(w),s]])}});function W(t,o={}){const e=l.ref(!1),n=l.ref(null);let s=null,r=null;return l.onMounted(()=>{t.value&&(r=t.value,s=f.observe(r,o,i=>{e.value=i.isIntersecting,n.value=i}))}),l.onUnmounted(()=>{s&&r&&f.unobserve(s,r)}),{isInView:e,entry:n}}const E={install(t,o){o?.presets&&I(o.presets),t.directive("viewport",w),t.component("VViewport",S)}};d.Viewport=S,d.ViewportPlugin=E,d.default=E,d.useInViewport=W,d.vViewport=w,Object.defineProperties(d,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@vikeriait/vue-viewport",
3
+ "version": "1.1.0",
4
+ "description": "Vue directive & composable: viewport detection + Tailwind scroll animations",
5
+ "keywords": [
6
+ "vue",
7
+ "viewport",
8
+ "intersectionobserver",
9
+ "scroll",
10
+ "tailwind",
11
+ "animate"
12
+ ],
13
+ "author": "Vikeria",
14
+ "license": "MIT",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/vikeriait/vue-viewport.git"
18
+ },
19
+ "type": "module",
20
+ "files": [
21
+ "dist",
22
+ "src/styles/tailwind.css",
23
+ "src/styles/presets.css",
24
+ "types",
25
+ "web-types.json"
26
+ ],
27
+ "main": "./dist/vue-viewport.umd.cjs",
28
+ "module": "./dist/vue-viewport.js",
29
+ "types": "./dist/index.d.ts",
30
+ "web-types": "./web-types.json",
31
+ "style": "./src/styles/tailwind.css",
32
+ "exports": {
33
+ ".": {
34
+ "types": "./dist/index.d.ts",
35
+ "style": "./src/styles/tailwind.css",
36
+ "import": "./dist/vue-viewport.js",
37
+ "require": "./dist/vue-viewport.umd.cjs"
38
+ },
39
+ "./tailwind": "./src/styles/tailwind.css",
40
+ "./css": "./dist/style.css",
41
+ "./style": "./src/styles/tailwind.css"
42
+ },
43
+ "sideEffects": [
44
+ "./src/styles/**/*.css"
45
+ ],
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "peerDependencies": {
50
+ "vue": "^3.4.0"
51
+ },
52
+ "devDependencies": {
53
+ "@types/node": "^25.0.3",
54
+ "@vitejs/plugin-vue": "^6.0.3",
55
+ "@vue/eslint-config-prettier": "^10.2.0",
56
+ "@vue/eslint-config-typescript": "^14.6.0",
57
+ "changelogen": "^0.6.2",
58
+ "esbuild": "^0.27.2",
59
+ "eslint": "^9.39.2",
60
+ "eslint-plugin-vue": "^10.6.2",
61
+ "prettier": "^3.7.4",
62
+ "typescript": "^5.9.3",
63
+ "typescript-eslint": "^8.51.0",
64
+ "vite": "^7.3.0",
65
+ "vite-plugin-dts": "^4.5.4",
66
+ "vue": "^3.4.0"
67
+ },
68
+ "scripts": {
69
+ "dev": "vite build --watch",
70
+ "generate": "node scripts/generate-presets.js",
71
+ "build": "pnpm generate && vite build && pnpm build:css",
72
+ "build:css": "esbuild src/styles/presets.css --minify --outfile=dist/style.css",
73
+ "preview": "vite preview",
74
+ "lint": "eslint .",
75
+ "lint:fix": "eslint . --fix",
76
+ "release": "pnpm changelogen --release --push && pnpm publish"
77
+ }
78
+ }
@@ -0,0 +1,258 @@
1
+ /* AUTO-GENERATED FILE - DO NOT EDIT MANUALLY */
2
+
3
+ :root {
4
+ --viewport-duration: 0.6s;
5
+ --viewport-ease: ease-out;
6
+ --viewport-delay: 0s;
7
+ --viewport-distance: 2rem;
8
+ --viewport-stagger: 100ms;
9
+ --viewport-scale-in: 0.95;
10
+ --viewport-scale-out: 1.05;
11
+ --viewport-blur: 12px;
12
+ }
13
+
14
+ /* Base transition for all animations */
15
+ [data-vp-preset*="animate-"] {
16
+ transition-duration: var(--viewport-duration);
17
+ transition-timing-function: var(--viewport-ease);
18
+ transition-delay: var(--viewport-delay);
19
+ }
20
+
21
+
22
+ /* fade Group */
23
+ [data-vp-preset~="animate-fade"],
24
+ [data-vp-preset~="animate-fade-down"][data-vp-entry="down"],
25
+ [data-vp-preset~="animate-fade-down"][data-vp-pos="below"],
26
+ [data-vp-preset~="animate-fade-up"][data-vp-entry="up"],
27
+ [data-vp-preset~="animate-fade-up"][data-vp-pos="above"] {
28
+ opacity: 0;
29
+ transition-property: opacity;
30
+ }
31
+
32
+ [data-vp-preset~="animate-fade"][data-vp-in-view],
33
+ [data-vp-preset~="animate-fade-down"][data-vp-entry="down"][data-vp-in-view],
34
+ [data-vp-preset~="animate-fade-up"][data-vp-entry="up"][data-vp-in-view] {
35
+ opacity: 1;
36
+ }
37
+
38
+ /* fade-up Group */
39
+ [data-vp-preset~="animate-fade-up"],
40
+ [data-vp-preset~="animate-fade-up-down"][data-vp-entry="down"],
41
+ [data-vp-preset~="animate-fade-up-down"][data-vp-pos="below"],
42
+ [data-vp-preset~="animate-fade-up-up"][data-vp-entry="up"],
43
+ [data-vp-preset~="animate-fade-up-up"][data-vp-pos="above"] {
44
+ opacity: 0; transform: translateY(var(--viewport-distance));
45
+ transition-property: opacity, transform;
46
+ }
47
+
48
+ [data-vp-preset~="animate-fade-up"][data-vp-in-view],
49
+ [data-vp-preset~="animate-fade-up-down"][data-vp-entry="down"][data-vp-in-view],
50
+ [data-vp-preset~="animate-fade-up-up"][data-vp-entry="up"][data-vp-in-view] {
51
+ opacity: 1; transform: translateY(0);
52
+ }
53
+
54
+ /* fade-down Group */
55
+ [data-vp-preset~="animate-fade-down"],
56
+ [data-vp-preset~="animate-fade-down-down"][data-vp-entry="down"],
57
+ [data-vp-preset~="animate-fade-down-down"][data-vp-pos="below"],
58
+ [data-vp-preset~="animate-fade-down-up"][data-vp-entry="up"],
59
+ [data-vp-preset~="animate-fade-down-up"][data-vp-pos="above"] {
60
+ opacity: 0; transform: translateY(calc(var(--viewport-distance) * -1));
61
+ transition-property: opacity, transform;
62
+ }
63
+
64
+ [data-vp-preset~="animate-fade-down"][data-vp-in-view],
65
+ [data-vp-preset~="animate-fade-down-down"][data-vp-entry="down"][data-vp-in-view],
66
+ [data-vp-preset~="animate-fade-down-up"][data-vp-entry="up"][data-vp-in-view] {
67
+ opacity: 1; transform: translateY(0);
68
+ }
69
+
70
+ /* fade-left Group */
71
+ [data-vp-preset~="animate-fade-left"],
72
+ [data-vp-preset~="animate-fade-left-down"][data-vp-entry="down"],
73
+ [data-vp-preset~="animate-fade-left-down"][data-vp-pos="below"],
74
+ [data-vp-preset~="animate-fade-left-up"][data-vp-entry="up"],
75
+ [data-vp-preset~="animate-fade-left-up"][data-vp-pos="above"] {
76
+ opacity: 0; transform: translateX(var(--viewport-distance));
77
+ transition-property: opacity, transform;
78
+ }
79
+
80
+ [data-vp-preset~="animate-fade-left"][data-vp-in-view],
81
+ [data-vp-preset~="animate-fade-left-down"][data-vp-entry="down"][data-vp-in-view],
82
+ [data-vp-preset~="animate-fade-left-up"][data-vp-entry="up"][data-vp-in-view] {
83
+ opacity: 1; transform: translateX(0);
84
+ }
85
+
86
+ /* fade-right Group */
87
+ [data-vp-preset~="animate-fade-right"],
88
+ [data-vp-preset~="animate-fade-right-down"][data-vp-entry="down"],
89
+ [data-vp-preset~="animate-fade-right-down"][data-vp-pos="below"],
90
+ [data-vp-preset~="animate-fade-right-up"][data-vp-entry="up"],
91
+ [data-vp-preset~="animate-fade-right-up"][data-vp-pos="above"] {
92
+ opacity: 0; transform: translateX(calc(var(--viewport-distance) * -1));
93
+ transition-property: opacity, transform;
94
+ }
95
+
96
+ [data-vp-preset~="animate-fade-right"][data-vp-in-view],
97
+ [data-vp-preset~="animate-fade-right-down"][data-vp-entry="down"][data-vp-in-view],
98
+ [data-vp-preset~="animate-fade-right-up"][data-vp-entry="up"][data-vp-in-view] {
99
+ opacity: 1; transform: translateX(0);
100
+ }
101
+
102
+ /* slide-up Group */
103
+ [data-vp-preset~="animate-slide-up"],
104
+ [data-vp-preset~="animate-slide-up-down"][data-vp-entry="down"],
105
+ [data-vp-preset~="animate-slide-up-down"][data-vp-pos="below"],
106
+ [data-vp-preset~="animate-slide-up-up"][data-vp-entry="up"],
107
+ [data-vp-preset~="animate-slide-up-up"][data-vp-pos="above"] {
108
+ transform: translateY(var(--viewport-distance));
109
+ transition-property: transform;
110
+ }
111
+
112
+ [data-vp-preset~="animate-slide-up"][data-vp-in-view],
113
+ [data-vp-preset~="animate-slide-up-down"][data-vp-entry="down"][data-vp-in-view],
114
+ [data-vp-preset~="animate-slide-up-up"][data-vp-entry="up"][data-vp-in-view] {
115
+ transform: translateY(0);
116
+ }
117
+
118
+ /* slide-down Group */
119
+ [data-vp-preset~="animate-slide-down"],
120
+ [data-vp-preset~="animate-slide-down-down"][data-vp-entry="down"],
121
+ [data-vp-preset~="animate-slide-down-down"][data-vp-pos="below"],
122
+ [data-vp-preset~="animate-slide-down-up"][data-vp-entry="up"],
123
+ [data-vp-preset~="animate-slide-down-up"][data-vp-pos="above"] {
124
+ transform: translateY(calc(var(--viewport-distance) * -1));
125
+ transition-property: transform;
126
+ }
127
+
128
+ [data-vp-preset~="animate-slide-down"][data-vp-in-view],
129
+ [data-vp-preset~="animate-slide-down-down"][data-vp-entry="down"][data-vp-in-view],
130
+ [data-vp-preset~="animate-slide-down-up"][data-vp-entry="up"][data-vp-in-view] {
131
+ transform: translateY(0);
132
+ }
133
+
134
+ /* slide-left Group */
135
+ [data-vp-preset~="animate-slide-left"],
136
+ [data-vp-preset~="animate-slide-left-down"][data-vp-entry="down"],
137
+ [data-vp-preset~="animate-slide-left-down"][data-vp-pos="below"],
138
+ [data-vp-preset~="animate-slide-left-up"][data-vp-entry="up"],
139
+ [data-vp-preset~="animate-slide-left-up"][data-vp-pos="above"] {
140
+ transform: translateX(var(--viewport-distance));
141
+ transition-property: transform;
142
+ }
143
+
144
+ [data-vp-preset~="animate-slide-left"][data-vp-in-view],
145
+ [data-vp-preset~="animate-slide-left-down"][data-vp-entry="down"][data-vp-in-view],
146
+ [data-vp-preset~="animate-slide-left-up"][data-vp-entry="up"][data-vp-in-view] {
147
+ transform: translateX(0);
148
+ }
149
+
150
+ /* slide-right Group */
151
+ [data-vp-preset~="animate-slide-right"],
152
+ [data-vp-preset~="animate-slide-right-down"][data-vp-entry="down"],
153
+ [data-vp-preset~="animate-slide-right-down"][data-vp-pos="below"],
154
+ [data-vp-preset~="animate-slide-right-up"][data-vp-entry="up"],
155
+ [data-vp-preset~="animate-slide-right-up"][data-vp-pos="above"] {
156
+ transform: translateX(calc(var(--viewport-distance) * -1));
157
+ transition-property: transform;
158
+ }
159
+
160
+ [data-vp-preset~="animate-slide-right"][data-vp-in-view],
161
+ [data-vp-preset~="animate-slide-right-down"][data-vp-entry="down"][data-vp-in-view],
162
+ [data-vp-preset~="animate-slide-right-up"][data-vp-entry="up"][data-vp-in-view] {
163
+ transform: translateX(0);
164
+ }
165
+
166
+ /* scale-up Group */
167
+ [data-vp-preset~="animate-scale-up"],
168
+ [data-vp-preset~="animate-scale-up-down"][data-vp-entry="down"],
169
+ [data-vp-preset~="animate-scale-up-down"][data-vp-pos="below"],
170
+ [data-vp-preset~="animate-scale-up-up"][data-vp-entry="up"],
171
+ [data-vp-preset~="animate-scale-up-up"][data-vp-pos="above"] {
172
+ opacity: 0; transform: scale(var(--viewport-scale-in));
173
+ transition-property: opacity, transform;
174
+ }
175
+
176
+ [data-vp-preset~="animate-scale-up"][data-vp-in-view],
177
+ [data-vp-preset~="animate-scale-up-down"][data-vp-entry="down"][data-vp-in-view],
178
+ [data-vp-preset~="animate-scale-up-up"][data-vp-entry="up"][data-vp-in-view] {
179
+ opacity: 1; transform: scale(1);
180
+ }
181
+
182
+ /* scale-down Group */
183
+ [data-vp-preset~="animate-scale-down"],
184
+ [data-vp-preset~="animate-scale-down-down"][data-vp-entry="down"],
185
+ [data-vp-preset~="animate-scale-down-down"][data-vp-pos="below"],
186
+ [data-vp-preset~="animate-scale-down-up"][data-vp-entry="up"],
187
+ [data-vp-preset~="animate-scale-down-up"][data-vp-pos="above"] {
188
+ opacity: 0; transform: scale(var(--viewport-scale-out));
189
+ transition-property: opacity, transform;
190
+ }
191
+
192
+ [data-vp-preset~="animate-scale-down"][data-vp-in-view],
193
+ [data-vp-preset~="animate-scale-down-down"][data-vp-entry="down"][data-vp-in-view],
194
+ [data-vp-preset~="animate-scale-down-up"][data-vp-entry="up"][data-vp-in-view] {
195
+ opacity: 1; transform: scale(1);
196
+ }
197
+
198
+ /* blur-in Group */
199
+ [data-vp-preset~="animate-blur-in"],
200
+ [data-vp-preset~="animate-blur-in-down"][data-vp-entry="down"],
201
+ [data-vp-preset~="animate-blur-in-down"][data-vp-pos="below"],
202
+ [data-vp-preset~="animate-blur-in-up"][data-vp-entry="up"],
203
+ [data-vp-preset~="animate-blur-in-up"][data-vp-pos="above"] {
204
+ opacity: 0; filter: blur(var(--viewport-blur));
205
+ transition-property: opacity, filter;
206
+ }
207
+
208
+ [data-vp-preset~="animate-blur-in"][data-vp-in-view],
209
+ [data-vp-preset~="animate-blur-in-down"][data-vp-entry="down"][data-vp-in-view],
210
+ [data-vp-preset~="animate-blur-in-up"][data-vp-entry="up"][data-vp-in-view] {
211
+ opacity: 1; filter: blur(0);
212
+ }
213
+
214
+ /* SMART PRESETS (Composite) */
215
+ /* fade-y */
216
+ [data-vp-preset~="animate-fade-y"][data-vp-entry="down"],
217
+ [data-vp-preset~="animate-fade-y"][data-vp-pos="below"],
218
+ [data-vp-preset~="animate-fade-y"][data-vp-entry="up"],
219
+ [data-vp-preset~="animate-fade-y"][data-vp-pos="above"] {
220
+ opacity: 0;
221
+ transition-property: opacity, transform;
222
+ }
223
+
224
+ [data-vp-preset~="animate-fade-y"][data-vp-entry="down"],
225
+ [data-vp-preset~="animate-fade-y"][data-vp-pos="below"] { transform: translateY(var(--viewport-distance)); }
226
+
227
+ [data-vp-preset~="animate-fade-y"][data-vp-entry="up"],
228
+ [data-vp-preset~="animate-fade-y"][data-vp-pos="above"] { transform: translateY(calc(var(--viewport-distance) * -1)); }
229
+
230
+ [data-vp-preset~="animate-fade-y"][data-vp-in-view] { opacity: 1; transform: translateY(0); }
231
+
232
+ /* slide-y */
233
+ [data-vp-preset~="animate-slide-y"][data-vp-entry="down"],
234
+ [data-vp-preset~="animate-slide-y"][data-vp-pos="below"],
235
+ [data-vp-preset~="animate-slide-y"][data-vp-entry="up"],
236
+ [data-vp-preset~="animate-slide-y"][data-vp-pos="above"] {
237
+ transition-property: transform;
238
+ }
239
+
240
+ [data-vp-preset~="animate-slide-y"][data-vp-entry="down"],
241
+ [data-vp-preset~="animate-slide-y"][data-vp-pos="below"] { transform: translateY(var(--viewport-distance)); }
242
+
243
+ [data-vp-preset~="animate-slide-y"][data-vp-entry="up"],
244
+ [data-vp-preset~="animate-slide-y"][data-vp-pos="above"] { transform: translateY(calc(var(--viewport-distance) * -1)); }
245
+
246
+ [data-vp-preset~="animate-slide-y"][data-vp-in-view] { transform: translateY(0); }
247
+
248
+ /* ACCESSIBILITY & PRINT OVERRIDES */
249
+ @media (prefers-reduced-motion: reduce), print {
250
+ [data-vp-mounted] {
251
+ opacity: 1 !important;
252
+ transform: none !important;
253
+ transition: none !important;
254
+ filter: none !important;
255
+ animation: none !important;
256
+ translate: none !important;
257
+ }
258
+ }
@@ -0,0 +1,8 @@
1
+ @import "./presets.css" layer(utilities);
2
+
3
+ @custom-variant inviewport (&[data-vp-in-view]);
4
+ @custom-variant inviewport-down (&[data-vp-in-view][data-vp-entry="down"]);
5
+ @custom-variant inviewport-up (&[data-vp-in-view][data-vp-entry="up"]);
6
+ @custom-variant aboveviewport (&[data-vp-pos="above"]);
7
+ @custom-variant belowviewport (&[data-vp-pos="below"]);
8
+