@ulu/frontend-vue 0.5.10 → 0.5.11
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/components/systems/scroll-anchors/UluScrollAnchors.vue.d.ts +1 -6
- package/dist/components/systems/scroll-anchors/UluScrollAnchors.vue.d.ts.map +1 -1
- package/dist/components/systems/scroll-anchors/UluScrollAnchors.vue.js +25 -15
- package/dist/components/systems/scroll-anchors/useScrollAnchors.d.ts.map +1 -1
- package/dist/components/systems/scroll-anchors/useScrollAnchors.js +48 -33
- package/lib/components/systems/scroll-anchors/UluScrollAnchors.vue +17 -7
- package/lib/components/systems/scroll-anchors/useScrollAnchors.js +24 -3
- package/package.json +1 -1
|
@@ -5,13 +5,8 @@ type __VLS_WithTemplateSlots<T, S> = T & (new () => {
|
|
|
5
5
|
});
|
|
6
6
|
declare const __VLS_component: import('vue').DefineComponent<{}, {
|
|
7
7
|
$emit: (event: "section-change", ...args: any[]) => void;
|
|
8
|
-
observerOptions: Record<string, any>;
|
|
9
|
-
firstItemActive: boolean;
|
|
10
|
-
debug: boolean;
|
|
11
8
|
$props: {
|
|
12
|
-
readonly
|
|
13
|
-
readonly firstItemActive?: boolean | undefined;
|
|
14
|
-
readonly debug?: boolean | undefined;
|
|
9
|
+
readonly [x: string]: any;
|
|
15
10
|
};
|
|
16
11
|
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {
|
|
17
12
|
componentEl: HTMLDivElement;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UluScrollAnchors.vue.d.ts","sourceRoot":"","sources":["../../../../lib/components/systems/scroll-anchors/UluScrollAnchors.vue"],"names":[],"mappings":"AAKA;
|
|
1
|
+
{"version":3,"file":"UluScrollAnchors.vue.d.ts","sourceRoot":"","sources":["../../../../lib/components/systems/scroll-anchors/UluScrollAnchors.vue"],"names":[],"mappings":"AAKA;wBAqLqB,uBAAuB,CAAC,OAAO,eAAe,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;;6BAEtE,CAAC,EAAE,CAAC;;;AAbjC;;;;;;;mBAUG"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ref as
|
|
1
|
+
import { ref as s, provide as n, computed as p, createElementBlock as f, openBlock as m, renderSlot as d } from "vue";
|
|
2
2
|
import { useScrollAnchors as h } from "./useScrollAnchors.js";
|
|
3
3
|
const A = {
|
|
4
4
|
__name: "UluScrollAnchors",
|
|
@@ -8,17 +8,27 @@ const A = {
|
|
|
8
8
|
*/
|
|
9
9
|
firstItemActive: Boolean,
|
|
10
10
|
/**
|
|
11
|
-
* IntersectionObserver options
|
|
12
|
-
*
|
|
11
|
+
* Custom IntersectionObserver options to completely override internal defaults.
|
|
12
|
+
* Defaults: { root: null, threshold: 0, rootMargin: "-25% 0px -55% 0px" }
|
|
13
13
|
* See: https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver
|
|
14
|
+
* @type {Object|null}
|
|
14
15
|
*/
|
|
15
16
|
observerOptions: {
|
|
16
17
|
type: Object,
|
|
17
|
-
default:
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
default: null
|
|
19
|
+
},
|
|
20
|
+
/**
|
|
21
|
+
* Creates a strict 1% horizontal observation line to trigger active states.
|
|
22
|
+
* - Accepts a number representing the percentage down from the top of the screen (e.g., 20 for 20%).
|
|
23
|
+
* - If you pass true it will default to 20%
|
|
24
|
+
* - Optional not enabled by default
|
|
25
|
+
* - You can control this yourself with observerOptions
|
|
26
|
+
* @type {Number|Boolean}
|
|
27
|
+
* @default false
|
|
28
|
+
*/
|
|
29
|
+
snapOffset: {
|
|
30
|
+
type: [Number, Boolean],
|
|
31
|
+
default: !1
|
|
22
32
|
},
|
|
23
33
|
/**
|
|
24
34
|
* Enable debug logging for the IntersectionObserver
|
|
@@ -26,19 +36,19 @@ const A = {
|
|
|
26
36
|
debug: Boolean
|
|
27
37
|
},
|
|
28
38
|
emits: ["section-change"],
|
|
29
|
-
setup(
|
|
30
|
-
const u =
|
|
31
|
-
return h({ sections: e, props: u, emit:
|
|
39
|
+
setup(r, { emit: c }) {
|
|
40
|
+
const u = r, a = c, e = s([]), t = s(null);
|
|
41
|
+
return h({ sections: e, props: u, emit: a, componentElRef: t }), n("uluScrollAnchorsSections", p(() => e.value)), n("uluScrollAnchorsRegister", (o) => {
|
|
32
42
|
e.value.push(o);
|
|
33
|
-
}),
|
|
34
|
-
const l = e.value.findIndex((
|
|
43
|
+
}), n("uluScrollAnchorsUnregister", (o) => {
|
|
44
|
+
const l = e.value.findIndex((i) => i.id === o);
|
|
35
45
|
l > -1 && e.value.splice(l, 1);
|
|
36
|
-
}), (o, l) => (
|
|
46
|
+
}), (o, l) => (m(), f("div", {
|
|
37
47
|
class: "scroll-anchors",
|
|
38
48
|
ref_key: "componentEl",
|
|
39
49
|
ref: t
|
|
40
50
|
}, [
|
|
41
|
-
|
|
51
|
+
d(o.$slots, "default")
|
|
42
52
|
], 512));
|
|
43
53
|
}
|
|
44
54
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useScrollAnchors.d.ts","sourceRoot":"","sources":["../../../../lib/components/systems/scroll-anchors/useScrollAnchors.js"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,4EAFW;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,WAAW;IAAC,cAAc,EAAE,MAAM,CAAA;CAAC,
|
|
1
|
+
{"version":3,"file":"useScrollAnchors.d.ts","sourceRoot":"","sources":["../../../../lib/components/systems/scroll-anchors/useScrollAnchors.js"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,4EAFW;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,WAAW;IAAC,cAAc,EAAE,MAAM,CAAA;CAAC,QA0KnF"}
|
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import { onMounted as
|
|
1
|
+
import { onMounted as T, onUnmounted as Y, watch as F, nextTick as O } from "vue";
|
|
2
2
|
import { getScrollParent as C } from "@ulu/utils/browser/dom.js";
|
|
3
3
|
function D({ sections: i, props: e, emit: h, componentElRef: I }) {
|
|
4
4
|
let r = null;
|
|
5
5
|
function v(t) {
|
|
6
6
|
return i.value.findIndex(({ element: l }) => t === l);
|
|
7
7
|
}
|
|
8
|
-
function
|
|
8
|
+
function w(t = null, l = "down") {
|
|
9
9
|
i.value.forEach((c) => {
|
|
10
10
|
c !== t && (c.active && (c.inactiveFrom = l === "down" ? "forward" : "reverse", c.activeFrom = null), c.active = !1);
|
|
11
11
|
});
|
|
12
12
|
}
|
|
13
|
-
function
|
|
13
|
+
function A() {
|
|
14
14
|
let t = 0, l = !0;
|
|
15
|
-
const c = (
|
|
16
|
-
const { root:
|
|
17
|
-
if (e.debug && (console.group("useScrollAnchors: onObserve"), console.log("Observer:", r), console.log("Last/Current Y:", `${t}/${
|
|
18
|
-
e.debug && console.log("Initial observation, respecting `firstItemActive`."), l = !1, t =
|
|
15
|
+
const c = (a) => {
|
|
16
|
+
const { root: S } = r, d = S ? S.scrollTop : document.documentElement.scrollTop || window.scrollY;
|
|
17
|
+
if (e.debug && (console.group("useScrollAnchors: onObserve"), console.log("Observer:", r), console.log("Last/Current Y:", `${t}/${d}`), console.log("Entries:", a.map((n) => ({ el: n.target, is: n.isIntersecting })))), l && e.firstItemActive) {
|
|
18
|
+
e.debug && console.log("Initial observation, respecting `firstItemActive`."), l = !1, t = d, e.debug && console.groupEnd();
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
21
|
l = !1;
|
|
22
|
-
const s =
|
|
23
|
-
t =
|
|
24
|
-
const
|
|
25
|
-
if (e.debug && console.log("Intersecting entries:",
|
|
26
|
-
|
|
27
|
-
const n = s === "down" ?
|
|
22
|
+
const s = d > t ? "down" : "up";
|
|
23
|
+
t = d, e.debug && console.log(`Scroll direction: ${s}`);
|
|
24
|
+
const f = a.filter((n) => n.isIntersecting);
|
|
25
|
+
if (e.debug && console.log("Intersecting entries:", f.map((n) => n.target)), f.length > 0) {
|
|
26
|
+
f.sort((u, m) => v(u.target) - v(m.target));
|
|
27
|
+
const n = s === "down" ? f[f.length - 1] : f[0];
|
|
28
28
|
e.debug && console.log("Chosen target entry:", n.target);
|
|
29
29
|
const o = i.value[v(n.target)];
|
|
30
|
-
o && !o.active && (e.debug && console.log("Activating section:", o.title),
|
|
31
|
-
|
|
30
|
+
o && !o.active && (e.debug && console.log("Activating section:", o.title), O(() => {
|
|
31
|
+
w(o, s), o.active = !0, o.inactiveFrom = null, o.activeFrom = s === "down" ? "forward" : "reverse", h("section-change", { section: o, sections: i.value, active: !0 });
|
|
32
32
|
}));
|
|
33
33
|
} else {
|
|
34
34
|
e.debug && console.log("No intersecting entries. Checking edge cases.");
|
|
35
35
|
const n = i.value.find((o) => o.active);
|
|
36
36
|
if (n) {
|
|
37
|
-
const o =
|
|
37
|
+
const o = a.find((u) => u.target === n.element);
|
|
38
38
|
if (o && !o.isIntersecting) {
|
|
39
|
-
const u = v(o.target),
|
|
40
|
-
(
|
|
41
|
-
|
|
39
|
+
const u = v(o.target), m = u === 0, y = u === i.value.length - 1;
|
|
40
|
+
(m && s === "up" && !e.firstItemActive || y && s === "down") && (e.debug && console.log("Deactivating section at edge:", n.title), O(() => {
|
|
41
|
+
w(null, s), h("section-change", { section: n, sections: i.value, active: !1 });
|
|
42
42
|
}));
|
|
43
43
|
}
|
|
44
44
|
}
|
|
@@ -46,34 +46,49 @@ function D({ sections: i, props: e, emit: h, componentElRef: I }) {
|
|
|
46
46
|
e.debug && console.groupEnd();
|
|
47
47
|
};
|
|
48
48
|
let g = null;
|
|
49
|
-
e.observerOptions && e.observerOptions.root ? g = e.observerOptions.root : I.value && (g = C(I.value), g === document.scrollingElement && (g = null));
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
e.observerOptions && e.observerOptions.root !== void 0 ? g = e.observerOptions.root : I.value && (g = C(I.value), g === document.scrollingElement && (g = null));
|
|
50
|
+
let E = {
|
|
51
|
+
rootMargin: "-25% 0px -55% 0px",
|
|
52
|
+
threshold: 0
|
|
53
|
+
};
|
|
54
|
+
if (e.snapOffset !== !1 && e.snapOffset !== void 0) {
|
|
55
|
+
const a = e.snapOffset === !0 ? 20 : Number(e.snapOffset);
|
|
56
|
+
E.rootMargin = `-${a}% 0px -${99 - a}% 0px`;
|
|
57
|
+
}
|
|
58
|
+
const $ = {
|
|
59
|
+
...E,
|
|
60
|
+
...e.observerOptions || {},
|
|
52
61
|
root: g
|
|
53
62
|
};
|
|
54
|
-
r = new IntersectionObserver(c,
|
|
63
|
+
r = new IntersectionObserver(c, $);
|
|
55
64
|
}
|
|
56
|
-
function
|
|
65
|
+
function b() {
|
|
57
66
|
r && (r.disconnect(), i.value.forEach(({ element: t }) => {
|
|
58
67
|
t && r.observe(t);
|
|
59
68
|
}));
|
|
60
69
|
}
|
|
61
|
-
function
|
|
70
|
+
function x() {
|
|
62
71
|
r && (r.disconnect(), r = null);
|
|
63
72
|
}
|
|
64
|
-
|
|
73
|
+
T(() => {
|
|
65
74
|
if (e.firstItemActive && i.value.length > 0) {
|
|
66
75
|
const t = i.value[0];
|
|
67
76
|
t && (t.active = !0);
|
|
68
77
|
}
|
|
69
|
-
|
|
70
|
-
}),
|
|
71
|
-
|
|
72
|
-
}),
|
|
73
|
-
|
|
74
|
-
|
|
78
|
+
A(), b();
|
|
79
|
+
}), Y(() => {
|
|
80
|
+
x();
|
|
81
|
+
}), F(() => i.value.length, () => {
|
|
82
|
+
O(() => {
|
|
83
|
+
b();
|
|
75
84
|
});
|
|
76
|
-
})
|
|
85
|
+
}), F(
|
|
86
|
+
() => [e.snapOffset, e.observerOptions],
|
|
87
|
+
() => {
|
|
88
|
+
x(), A(), b();
|
|
89
|
+
},
|
|
90
|
+
{ deep: !0 }
|
|
91
|
+
);
|
|
77
92
|
}
|
|
78
93
|
export {
|
|
79
94
|
D as useScrollAnchors
|
|
@@ -14,17 +14,27 @@
|
|
|
14
14
|
*/
|
|
15
15
|
firstItemActive: Boolean,
|
|
16
16
|
/**
|
|
17
|
-
* IntersectionObserver options
|
|
18
|
-
*
|
|
17
|
+
* Custom IntersectionObserver options to completely override internal defaults.
|
|
18
|
+
* Defaults: { root: null, threshold: 0, rootMargin: "-25% 0px -55% 0px" }
|
|
19
19
|
* See: https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver
|
|
20
|
+
* @type {Object|null}
|
|
20
21
|
*/
|
|
21
22
|
observerOptions: {
|
|
22
23
|
type: Object,
|
|
23
|
-
default:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
default: null
|
|
25
|
+
},
|
|
26
|
+
/**
|
|
27
|
+
* Creates a strict 1% horizontal observation line to trigger active states.
|
|
28
|
+
* - Accepts a number representing the percentage down from the top of the screen (e.g., 20 for 20%).
|
|
29
|
+
* - If you pass true it will default to 20%
|
|
30
|
+
* - Optional not enabled by default
|
|
31
|
+
* - You can control this yourself with observerOptions
|
|
32
|
+
* @type {Number|Boolean}
|
|
33
|
+
* @default false
|
|
34
|
+
*/
|
|
35
|
+
snapOffset: {
|
|
36
|
+
type: [Number, Boolean],
|
|
37
|
+
default: false
|
|
28
38
|
},
|
|
29
39
|
/**
|
|
30
40
|
* Enable debug logging for the IntersectionObserver
|
|
@@ -101,7 +101,7 @@ export function useScrollAnchors({ sections, props, emit, componentElRef }) {
|
|
|
101
101
|
};
|
|
102
102
|
|
|
103
103
|
let root = null;
|
|
104
|
-
if (props.observerOptions && props.observerOptions.root) {
|
|
104
|
+
if (props.observerOptions && props.observerOptions.root !== undefined) {
|
|
105
105
|
root = props.observerOptions.root;
|
|
106
106
|
} else if (componentElRef.value) {
|
|
107
107
|
root = getScrollParent(componentElRef.value);
|
|
@@ -110,11 +110,22 @@ export function useScrollAnchors({ sections, props, emit, componentElRef }) {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
let defaultOptions = {
|
|
114
|
+
rootMargin: "-25% 0px -55% 0px",
|
|
115
|
+
threshold: 0
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
if (props.snapOffset !== false && props.snapOffset !== undefined) {
|
|
119
|
+
const offset = props.snapOffset === true ? 20 : Number(props.snapOffset);
|
|
120
|
+
defaultOptions.rootMargin = `-${offset}% 0px -${99 - offset}% 0px`;
|
|
121
|
+
}
|
|
122
|
+
|
|
113
123
|
const finalObserverOptions = {
|
|
114
|
-
...
|
|
124
|
+
...defaultOptions,
|
|
125
|
+
...(props.observerOptions || {}),
|
|
115
126
|
root
|
|
116
127
|
};
|
|
117
|
-
|
|
128
|
+
|
|
118
129
|
observer = new IntersectionObserver(onObserve, finalObserverOptions);
|
|
119
130
|
}
|
|
120
131
|
|
|
@@ -155,4 +166,14 @@ export function useScrollAnchors({ sections, props, emit, componentElRef }) {
|
|
|
155
166
|
observeItems();
|
|
156
167
|
});
|
|
157
168
|
});
|
|
169
|
+
|
|
170
|
+
watch(
|
|
171
|
+
() => [props.snapOffset, props.observerOptions],
|
|
172
|
+
() => {
|
|
173
|
+
destroyObserver();
|
|
174
|
+
createObserver();
|
|
175
|
+
observeItems();
|
|
176
|
+
},
|
|
177
|
+
{ deep: true }
|
|
178
|
+
);
|
|
158
179
|
}
|
package/package.json
CHANGED