first commit
This commit is contained in:
72
node_modules/framer-motion/dist/es/motion/features/viewport/index.mjs
generated
vendored
Normal file
72
node_modules/framer-motion/dist/es/motion/features/viewport/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
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 };
|
||||
49
node_modules/framer-motion/dist/es/motion/features/viewport/observers.mjs
generated
vendored
Normal file
49
node_modules/framer-motion/dist/es/motion/features/viewport/observers.mjs
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Map an IntersectionHandler callback to an element. We only ever make one handler for one
|
||||
* element, so even though these handlers might all be triggered by different
|
||||
* observers, we can keep them in the same map.
|
||||
*/
|
||||
const observerCallbacks = new WeakMap();
|
||||
/**
|
||||
* Multiple observers can be created for multiple element/document roots. Each with
|
||||
* different settings. So here we store dictionaries of observers to each root,
|
||||
* using serialised settings (threshold/margin) as lookup keys.
|
||||
*/
|
||||
const observers = new WeakMap();
|
||||
const fireObserverCallback = (entry) => {
|
||||
const callback = observerCallbacks.get(entry.target);
|
||||
callback && callback(entry);
|
||||
};
|
||||
const fireAllObserverCallbacks = (entries) => {
|
||||
entries.forEach(fireObserverCallback);
|
||||
};
|
||||
function initIntersectionObserver({ root, ...options }) {
|
||||
const lookupRoot = root || document;
|
||||
/**
|
||||
* If we don't have an observer lookup map for this root, create one.
|
||||
*/
|
||||
if (!observers.has(lookupRoot)) {
|
||||
observers.set(lookupRoot, {});
|
||||
}
|
||||
const rootObservers = observers.get(lookupRoot);
|
||||
const key = JSON.stringify(options);
|
||||
/**
|
||||
* If we don't have an observer for this combination of root and settings,
|
||||
* create one.
|
||||
*/
|
||||
if (!rootObservers[key]) {
|
||||
rootObservers[key] = new IntersectionObserver(fireAllObserverCallbacks, { root, ...options });
|
||||
}
|
||||
return rootObservers[key];
|
||||
}
|
||||
function observeIntersection(element, options, callback) {
|
||||
const rootInteresectionObserver = initIntersectionObserver(options);
|
||||
observerCallbacks.set(element, callback);
|
||||
rootInteresectionObserver.observe(element);
|
||||
return () => {
|
||||
observerCallbacks.delete(element);
|
||||
rootInteresectionObserver.unobserve(element);
|
||||
};
|
||||
}
|
||||
|
||||
export { observeIntersection };
|
||||
Reference in New Issue
Block a user