/
index.ts
83 lines (70 loc) · 2.13 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import { Base } from "../base/index.js";
import type { Attributes } from "../types/index.js";
export type IntersectAttributes = Attributes<Intersect> &
Partial<{ threshold: number }>;
type IntersectCallback = () => any;
/**
* Uses the [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) to add a `data-intersect` attribute to `content` when the `trigger` is intersecting.
*
* Use `onIntersect` and `onExit` to customize further with JavaScript.
*
* `threshold`
*
* Specify a `threshold` between `0` and `1` to determine how much of the `trigger` should be visible for the intersection to occur.
*/
export class Intersect extends Base {
/** Functions to run when the `trigger` intersects. */
#intersectCallbacks: Array<IntersectCallback> = [];
/** Functions to run when the `trigger` exits. */
#exitCallbacks: Array<IntersectCallback> = [];
constructor() {
super();
}
/**
* How much of the `trigger` should be visible for the intersection to occur. For example, given a threshold of `.5`, the intersection would occur when the `trigger` is 50% visible.
*
* @default 0
*/
get #threshold() {
return Number(this.getAttribute("threshold") ?? 0);
}
/**
* @param callback Runs when `trigger` intersects.
*/
onIntersect(callback: IntersectCallback) {
this.#intersectCallbacks.push(callback);
}
/**
* @param callback Runs when `trigger` exits.
*/
onExit(callback: IntersectCallback) {
this.#exitCallbacks.push(callback);
}
mount() {
const observer = new IntersectionObserver(
(entries) => {
/** Attribute to add or remove from `content`. */
const attr = "data-intersect";
for (const entry of entries) {
if (entry.isIntersecting) {
this.getContent().setAttribute(attr, "");
for (const callback of this.#intersectCallbacks) {
callback();
}
} else {
this.getContent().removeAttribute(attr);
for (const callback of this.#exitCallbacks) {
callback();
}
}
}
},
{
threshold: this.#threshold,
},
);
for (const trigger of this.getTrigger()) {
observer.observe(trigger);
}
}
}