kaioken-gsap
Version:
Tools for using GSAP in Kaioken, like useGSAP() which is a drop-in replacement for useLayoutEffect()/useEffect()
53 lines (52 loc) • 2.27 kB
JavaScript
/**
* @fileoverview Tools for using GSAP in Kaioken, like useGSAP() which is a drop-in replacement for useLayoutEffect()/useEffect()
* @version 1.0.0
* @license ISC
* Based on the work of Jack Doyle, jack@greensock.com - (https://github.com/greensock/react/blob/main/src/index.js)
*/
import { useLayoutEffect, useRef } from "kaioken";
import gsap from "gsap";
const isConfig = (obj) => typeof obj === "object" && !!obj && !Array.isArray(obj);
const defaultConfig = {};
const emptyArray = [];
let _gsap = gsap;
export function useGSAP(callback, dependencies = emptyArray) {
let config = defaultConfig;
if (isConfig(callback)) {
config = callback;
callback = null;
dependencies = "dependencies" in config ? config.dependencies : emptyArray;
}
else if (isConfig(dependencies)) {
config = dependencies;
dependencies = "dependencies" in config ? config.dependencies : emptyArray;
}
if (callback && typeof callback !== "function") {
console.warn("First parameter must be a function or config object");
}
const { scope, revertOnUpdate } = config;
const mounted = useRef(false);
const context = useRef(_gsap.context(() => { }, scope));
const contextSafe = useRef((func) => context.current.add(null, func));
const deferCleanup = dependencies && dependencies.length && !revertOnUpdate;
deferCleanup &&
useLayoutEffect(() => {
mounted.current = true;
return () => context.current.revert();
}, emptyArray);
// @ts-expect-error
useLayoutEffect(() => {
callback && context.current.add(callback, scope);
if (!deferCleanup || !mounted.current) {
// Kaioken renders bottom-up, thus there could be hooks with dependencies that run BEFORE the component mounts, thus cleanup wouldn't occur since a hook with an empty dependency Array would only run once the component mounts.
return () => context.current.revert();
}
}, dependencies);
return {
context: context.current,
contextSafe: contextSafe.current,
};
}
// @ts-expect-error shut up ts
useGSAP.register = (core) => (_gsap = core);
useGSAP.headless = true; // doesn't require the window to be registered.