kinetic-slider
Version:
A WebGL-powered kinetic slider component using PIXI.js
176 lines (173 loc) • 5.4 kB
JavaScript
import { useRef, useCallback, useEffect } from 'react';
const isDevelopment = false;
const useNavigation = ({
onNext,
onPrev,
enableKeyboardNav = true,
resourceManager
}) => {
const isMountedRef = useRef(true);
const batchOperationsRef = useRef({
pendingListeners: /* @__PURE__ */ new Map(),
processedCount: 0
});
const handlersRef = useRef({
keyDownHandler: (event) => {
try {
if (!isMountedRef.current || !enableKeyboardNav) return;
const keyEvent = event;
const handlers = handlersRef.current;
switch (keyEvent.key) {
case "ArrowLeft":
if (handlers.latestPrevFn) {
handlers.latestPrevFn();
}
break;
case "ArrowRight":
if (handlers.latestNextFn) {
handlers.latestNextFn();
}
break;
}
} catch (error) {
}
},
slideChangeHandler: (event) => {
try {
if (!isMountedRef.current) return;
const customEvent = event;
const handlers = handlersRef.current;
if (customEvent.detail && typeof customEvent.detail.nextIndex === "number") {
if (handlers.latestNextFn) {
handlers.latestNextFn();
}
}
} catch (error) {
}
},
latestNextFn: null,
latestPrevFn: null
});
const processPendingListeners = useCallback(() => {
try {
const { pendingListeners } = batchOperationsRef.current;
if (!resourceManager || pendingListeners.size === 0) return;
let totalProcessed = 0;
pendingListeners.forEach((listenerMap, target) => {
try {
resourceManager.addEventListenerBatch(target, listenerMap);
totalProcessed += Array.from(listenerMap.values()).reduce((sum, callbacks) => sum + callbacks.length, 0);
} catch (error) {
if (isDevelopment) ;
}
});
pendingListeners.clear();
batchOperationsRef.current.processedCount += totalProcessed;
if (isDevelopment) ;
} catch (error) {
batchOperationsRef.current.pendingListeners.clear();
}
}, [resourceManager]);
const addListenerToBatch = useCallback((target, eventType, callback) => {
try {
const { pendingListeners } = batchOperationsRef.current;
if (!pendingListeners.has(target)) {
pendingListeners.set(target, /* @__PURE__ */ new Map());
}
const targetMap = pendingListeners.get(target);
if (!targetMap.has(eventType)) {
targetMap.set(eventType, []);
}
targetMap.get(eventType).push(callback);
return true;
} catch (error) {
return false;
}
}, []);
useEffect(() => {
handlersRef.current.latestNextFn = onNext;
handlersRef.current.latestPrevFn = onPrev;
}, [onNext, onPrev]);
useEffect(() => {
if (typeof window === "undefined") return;
if (!enableKeyboardNav) return;
isMountedRef.current = true;
try {
const { keyDownHandler } = handlersRef.current;
const startTime = isDevelopment ? performance.now() : 0;
if (resourceManager) {
addListenerToBatch(window, "keydown", keyDownHandler);
processPendingListeners();
} else {
window.addEventListener("keydown", keyDownHandler);
}
if (isDevelopment && startTime > 0) ;
return () => {
isMountedRef.current = false;
try {
if (!resourceManager) {
window.removeEventListener("keydown", keyDownHandler);
}
} catch (cleanupError) {
if (isDevelopment) ;
}
};
} catch (error) {
return () => {
};
}
}, [enableKeyboardNav, resourceManager, addListenerToBatch, processPendingListeners]);
useEffect(() => {
if (typeof window === "undefined") return;
try {
const { slideChangeHandler } = handlersRef.current;
const startTime = isDevelopment ? performance.now() : 0;
if (resourceManager) {
addListenerToBatch(window, "slideChange", slideChangeHandler);
processPendingListeners();
} else {
window.addEventListener("slideChange", slideChangeHandler);
}
if (isDevelopment && startTime > 0) ;
return () => {
try {
if (!resourceManager) {
window.removeEventListener("slideChange", slideChangeHandler);
}
} catch (cleanupError) {
if (isDevelopment) ;
}
};
} catch (error) {
return () => {
};
}
}, [resourceManager, addListenerToBatch, processPendingListeners]);
const goNext = useCallback(() => {
try {
if (isMountedRef.current && handlersRef.current.latestNextFn) {
const startTime = isDevelopment ? performance.now() : 0;
handlersRef.current.latestNextFn();
if (isDevelopment && startTime > 0) ;
}
} catch (error) {
}
}, []);
const goPrev = useCallback(() => {
try {
if (isMountedRef.current && handlersRef.current.latestPrevFn) {
const startTime = isDevelopment ? performance.now() : 0;
handlersRef.current.latestPrevFn();
if (isDevelopment && startTime > 0) ;
}
} catch (error) {
}
}, []);
return {
goNext,
goPrev,
isKeyboardEnabled: enableKeyboardNav
};
};
export { useNavigation as default };
//# sourceMappingURL=useNavigation.js.map