| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 |
- import { Feature } from '../Feature.mjs';
- import { observeIntersection } from './observers.mjs';
- const thresholdNames = {
- some: 0,
- all: 1,
- };
- class InViewFeature extends Feature {
- constructor() {
- super(...arguments);
- this.hasEnteredView = false;
- this.isInView = false;
- }
- startObserver() {
- this.unmount();
- const { viewport = {} } = this.node.getProps();
- const { root, margin: rootMargin, amount = "some", once } = viewport;
- const options = {
- root: root ? root.current : undefined,
- rootMargin,
- threshold: typeof amount === "number" ? amount : thresholdNames[amount],
- };
- const onIntersectionUpdate = (entry) => {
- const { isIntersecting } = entry;
- /**
- * If there's been no change in the viewport state, early return.
- */
- if (this.isInView === isIntersecting)
- return;
- this.isInView = isIntersecting;
- /**
- * Handle hasEnteredView. If this is only meant to run once, and
- * element isn't visible, early return. Otherwise set hasEnteredView to true.
- */
- if (once && !isIntersecting && this.hasEnteredView) {
- return;
- }
- else if (isIntersecting) {
- this.hasEnteredView = true;
- }
- if (this.node.animationState) {
- this.node.animationState.setActive("whileInView", isIntersecting);
- }
- /**
- * Use the latest committed props rather than the ones in scope
- * when this observer is created
- */
- const { onViewportEnter, onViewportLeave } = this.node.getProps();
- const callback = isIntersecting ? onViewportEnter : onViewportLeave;
- callback && callback(entry);
- };
- return observeIntersection(this.node.current, options, onIntersectionUpdate);
- }
- mount() {
- this.startObserver();
- }
- update() {
- if (typeof IntersectionObserver === "undefined")
- return;
- const { props, prevProps } = this.node;
- const hasOptionsChanged = ["amount", "margin", "root"].some(hasViewportOptionChanged(props, prevProps));
- if (hasOptionsChanged) {
- this.startObserver();
- }
- }
- unmount() { }
- }
- function hasViewportOptionChanged({ viewport = {} }, { viewport: prevViewport = {} } = {}) {
- return (name) => viewport[name] !== prevViewport[name];
- }
- export { InViewFeature };
|