UNPKG

kinetic-slider

Version:

A WebGL-powered kinetic slider component using PIXI.js

828 lines (823 loc) 27.6 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var jsxRuntime = require('react/jsx-runtime'); var react = require('react'); var KineticSlider_module = require('./KineticSlider.module.css.cjs'); var pixi_js = require('pixi.js'); var ResourceManager = require('./managers/ResourceManager.cjs'); var AtlasManager = require('./managers/AtlasManager.cjs'); var RenderScheduler = require('./managers/RenderScheduler.cjs'); var UpdateTypes = require('./managers/UpdateTypes.cjs'); var FrameThrottler = require('./managers/FrameThrottler.cjs'); var AnimationCoordinator = require('./managers/AnimationCoordinator.cjs'); var SlidingWindowManager = require('./managers/SlidingWindowManager.cjs'); require('pixi-filters'); require('./managers/ShaderResourceManager.cjs'); require('./filters/advancedBloomFilter.cjs'); require('./filters/blurFilter.cjs'); require('./filters/colorMatrixFilter.cjs'); require('./filters/dropShadowFilter.cjs'); require('gsap'); require('./filters/tiltShiftFilter.cjs'); var FilterFactory = require('./filters/FilterFactory.cjs'); var useDisplacementEffects = require('./hooks/useDisplacementEffects.cjs'); var useFilters = require('./hooks/useFilters.cjs'); var useSlides = require('./hooks/useSlides.cjs'); var useTextContainers = require('./hooks/useTextContainers.cjs'); var useMouseTracking = require('./hooks/useMouseTracking.cjs'); var useIdleTimer = require('./hooks/useIdleTimer.cjs'); var useNavigation = require('./hooks/useNavigation.cjs'); var useExternalNav = require('./hooks/useExternalNav.cjs'); var useTouchSwipe = require('./hooks/useTouchSwipe.cjs'); var useMouseDrag = require('./hooks/useMouseDrag.cjs'); var useTextTilt = require('./hooks/useTextTilt.cjs'); var useResizeHandler = require('./hooks/useResizeHandler.cjs'); var ImportHelpers = require('./ImportHelpers.cjs'); var assetPreload = require('./utils/assetPreload.cjs'); const FILTER_COORDINATION_EVENT = "kinetic-slider:filter-update"; const KineticSlider = ({ // Content sources images = [], texts = [], slidesBasePath = "/images/", // Displacement settings backgroundDisplacementSpriteLocation = "/images/background-displace.jpg", cursorDisplacementSpriteLocation = "/images/cursor-displace.png", cursorImgEffect = true, cursorTextEffect = true, cursorScaleIntensity = 0.65, cursorMomentum = 0.14, // Cursor displacement sizing options cursorDisplacementSizing = "natural", cursorDisplacementWidth, cursorDisplacementHeight, // Text styling textTitleColor = "white", textTitleSize = 64, mobileTextTitleSize = 40, textTitleLetterspacing = 2, textTitleFontFamily, textSubTitleColor = "white", textSubTitleSize = 24, mobileTextSubTitleSize = 18, textSubTitleLetterspacing = 1, textSubTitleOffsetTop = 10, mobileTextSubTitleOffsetTop = 5, textSubTitleFontFamily, // Animation settings maxContainerShiftFraction = 0.05, swipeScaleIntensity = 2, transitionScaleIntensity = 30, // Navigation settings externalNav = false, navElement = { prev: ".main-nav.prev", next: ".main-nav.next" }, buttonMode = false, // Filter configurations imageFilters, textFilters, // Atlas configuration slidesAtlas = "slides-atlas", effectsAtlas = "effects-atlas", useEffectsAtlas = false, useSlidesAtlas = false }) => { console.log("KineticSlider received props:", { useSlidesAtlas, useEffectsAtlas, slidesAtlas, effectsAtlas }); const sliderRef = react.useRef(null); const [isClient, setIsClient] = react.useState(false); const [currentSlideIndex, setCurrentSlideIndex] = react.useState(0); const [isInteracting, setIsInteracting] = react.useState(false); const [isAppReady, setIsAppReady] = react.useState(false); const [assetsLoaded, setAssetsLoaded] = react.useState(false); const cursorActiveRef = react.useRef(false); const scheduler = RenderScheduler.RenderScheduler.getInstance(); const resourceManagerRef = react.useRef(null); const slidingWindowManagerRef = react.useRef(null); const animationCoordinator = AnimationCoordinator.AnimationCoordinator.getInstance(); react.useEffect(() => { if (typeof window === "undefined") return; scheduler.configureThrottling({ targetFps: 60, strategy: FrameThrottler.ThrottleStrategy.PRIORITY }); return () => { scheduler.clearQueue(); }; }, [scheduler]); const atlasManagerRef = react.useRef(null); const appRef = react.useRef(null); const slidesRef = react.useRef([]); const textContainersRef = react.useRef([]); const backgroundDisplacementSpriteRef = react.useRef(null); const cursorDisplacementSpriteRef = react.useRef(null); const bgDispFilterRef = react.useRef(null); const cursorDispFilterRef = react.useRef(null); const currentIndexRef = react.useRef(0); react.useEffect(() => { setIsClient(true); }, []); react.useEffect(() => { const componentId = `kinetic-slider-${Math.random().toString(36).substring(2, 9)}`; resourceManagerRef.current = new ResourceManager.default(componentId, { enableMetrics: true, enableShaderPooling: true, logLevel: "warn" }); FilterFactory.FilterFactory.initialize({ enableShaderPooling: true, enableDebug: false, lazyLoadConfig: { unloadTimeoutMs: 12e4, // 2 minutes maxCachedModules: 20, enablePrefetching: true, retryFailedLoads: true, maxRetries: 3 } }); atlasManagerRef.current = new AtlasManager.AtlasManager({ debug: true, preferAtlas: true, cacheFrameTextures: true, basePath: "/atlas" }, resourceManagerRef.current); if (resourceManagerRef.current) { animationCoordinator.setResourceManager(resourceManagerRef.current); } slidingWindowManagerRef.current = new SlidingWindowManager.default({ totalSlides: images.length, initialIndex: 0, windowSize: 2, // Default: current slide ±2 debug: false }, resourceManagerRef.current); return () => { if (resourceManagerRef.current) { console.log("Component unmounting - disposing all resources"); resourceManagerRef.current.markUnmounting(); resourceManagerRef.current.dispose(); resourceManagerRef.current = null; } if (atlasManagerRef.current) { atlasManagerRef.current.dispose(); atlasManagerRef.current = null; } slidingWindowManagerRef.current = null; }; }, [images.length, animationCoordinator]); const pixiRefs = { app: appRef, slides: slidesRef, textContainers: textContainersRef, backgroundDisplacementSprite: backgroundDisplacementSpriteRef, cursorDisplacementSprite: cursorDisplacementSpriteRef, bgDispFilter: bgDispFilterRef, cursorDispFilter: cursorDispFilterRef, currentIndex: currentIndexRef }; const hookProps = { images, texts, slidesBasePath, backgroundDisplacementSpriteLocation, cursorDisplacementSpriteLocation, cursorImgEffect, cursorTextEffect, cursorScaleIntensity, cursorMomentum, cursorDisplacementSizing, cursorDisplacementWidth, cursorDisplacementHeight, textTitleColor, textTitleSize, mobileTextTitleSize, textTitleLetterspacing, textTitleFontFamily, textSubTitleColor, textSubTitleSize, mobileTextSubTitleSize, textSubTitleLetterspacing, textSubTitleOffsetTop, mobileTextSubTitleOffsetTop, textSubTitleFontFamily, maxContainerShiftFraction, swipeScaleIntensity, transitionScaleIntensity, imageFilters, textFilters, slidesAtlas, effectsAtlas, useSlidesAtlas, useEffectsAtlas }; const hookParams = { sliderRef, pixi: pixiRefs, props: hookProps, resourceManager: resourceManagerRef.current, atlasManager: atlasManagerRef.current, slidingWindowManager: slidingWindowManagerRef.current }; const { showDisplacementEffects, hideDisplacementEffects } = useDisplacementEffects.useDisplacementEffects({ sliderRef, bgDispFilterRef, cursorDispFilterRef, backgroundDisplacementSpriteRef, cursorDisplacementSpriteRef, appRef, backgroundDisplacementSpriteLocation, cursorDisplacementSpriteLocation, cursorImgEffect, cursorScaleIntensity, cursorDisplacementSizing, cursorDisplacementWidth, cursorDisplacementHeight, resourceManager: resourceManagerRef.current, atlasManager: atlasManagerRef.current || void 0, effectsAtlas, useEffectsAtlas }); const { updateFilterIntensities, resetAllFilters, activateFilterEffects, isInitialized: filtersInitialized, isActive: filtersActive, setFiltersActive } = useFilters.useFilters(hookParams); react.useEffect(() => { if (!isAppReady || !assetsLoaded) { console.log("Skipping filter coordination - not ready", { filtersInitialized, isAppReady, assetsLoaded }); return; } if (!filtersInitialized && typeof activateFilterEffects === "function") { console.log("Attempting to initialize filters during coordination"); activateFilterEffects(); } console.log(`Filter coordination - isInteracting: ${isInteracting}, filtersActive: ${filtersActive}`); if (isInteracting) { console.log("Interaction started - activating effects"); showDisplacementEffects(); if (typeof activateFilterEffects === "function") { console.log("Using activateFilterEffects"); activateFilterEffects(); } else { console.log("Using updateFilterIntensities"); updateFilterIntensities(true, true); } } else { console.log("Interaction ended - deactivating effects"); hideDisplacementEffects(); updateFilterIntensities(false); } }, [ isInteracting, isAppReady, assetsLoaded, filtersInitialized, filtersActive, showDisplacementEffects, hideDisplacementEffects, updateFilterIntensities, activateFilterEffects ]); react.useEffect(() => { if (!isAppReady || !assetsLoaded) { resetAllFilters(); } return () => { resetAllFilters(); }; }, [isAppReady, assetsLoaded, resetAllFilters]); react.useEffect(() => { if (typeof window === "undefined" || !isClient) return; const loadAssets = async () => { try { console.log("Preloading assets and fonts..."); if (atlasManagerRef.current) { if (slidesAtlas) { await atlasManagerRef.current.loadAtlas( slidesAtlas, `/atlas/${slidesAtlas}.json`, `/atlas/${slidesAtlas}.png` ); } if (effectsAtlas) { await atlasManagerRef.current.loadAtlas( effectsAtlas, `/atlas/${effectsAtlas}.json`, `/atlas/${effectsAtlas}.png` ); } } await assetPreload.preloadKineticSliderAssets( images, backgroundDisplacementSpriteLocation, cursorDisplacementSpriteLocation, textTitleFontFamily, textSubTitleFontFamily ); setAssetsLoaded(true); console.log("Assets and fonts preloaded successfully"); } catch (error) { console.error("Failed to preload assets:", error); setAssetsLoaded(true); } }; loadAssets(); }, [ isClient, images, backgroundDisplacementSpriteLocation, cursorDisplacementSpriteLocation, textTitleFontFamily, textSubTitleFontFamily, slidesAtlas, effectsAtlas ]); react.useEffect(() => { if (typeof window === "undefined" || !sliderRef.current || appRef.current || !assetsLoaded) return; const initPixi = async () => { try { console.log("Loading PixiJS dependencies..."); const { gsap, pixi, pixiPlugin } = await ImportHelpers.loadKineticSliderDependencies(); if (typeof window !== "undefined" && pixiPlugin) { gsap.registerPlugin(pixiPlugin); if (pixiPlugin.registerPIXI) { pixiPlugin.registerPIXI(pixi); } } console.log("Creating Pixi.js application..."); const app = new pixi_js.Application(); await app.init({ width: sliderRef.current?.clientWidth || 800, height: sliderRef.current?.clientHeight || 600, backgroundAlpha: 0, resizeTo: sliderRef.current || void 0 }); if (resourceManagerRef.current) { resourceManagerRef.current.trackPixiApp(app); } if (sliderRef.current) { sliderRef.current.appendChild(app.canvas); } appRef.current = app; const stage = new pixi_js.Container(); app.stage.addChild(stage); if (resourceManagerRef.current) { resourceManagerRef.current.trackDisplayObject(stage); } setIsAppReady(true); console.log("Pixi.js application initialized"); } catch (error) { console.error("Failed to initialize Pixi.js application:", error); } }; initPixi(); return () => { if (appRef.current) { if (sliderRef.current) { const canvas = sliderRef.current.querySelector("canvas"); if (canvas) { sliderRef.current.removeChild(canvas); } } appRef.current = null; setIsAppReady(false); } }; }, [sliderRef.current, assetsLoaded]); react.useEffect(() => { if (typeof window === "undefined" || !isAppReady) return; if (!hookProps.imageFilters && !hookProps.textFilters) return; const getFilterTypes = (config) => { if (!config) return []; const configs = Array.isArray(config) ? config : [config]; return configs.filter((c) => c && c.type && c.enabled !== false).map((c) => c.type); }; const imageFilterTypes = getFilterTypes(hookProps.imageFilters); const textFilterTypes = getFilterTypes(hookProps.textFilters); const allFilterTypes = [.../* @__PURE__ */ new Set([...imageFilterTypes, ...textFilterTypes])]; if (allFilterTypes.length > 0) { console.log(`Prefetching ${allFilterTypes.length} filter types:`, allFilterTypes); FilterFactory.FilterFactory.prefetchFilterModules(allFilterTypes, "high"); } }, [isAppReady, hookProps.imageFilters, hookProps.textFilters]); const handleSlideChange = react.useCallback((newIndex) => { currentIndexRef.current = newIndex; setCurrentSlideIndex(newIndex); if (filtersInitialized) { if (isInteracting) { console.log("Cursor is within canvas - applying filters immediately with critical priority"); scheduler.scheduleTypedUpdate( "slider", UpdateTypes.UpdateType.DISPLACEMENT_EFFECT, () => { showDisplacementEffects(); }, "critical" ); scheduler.scheduleTypedUpdate( "slider", UpdateTypes.UpdateType.FILTER_UPDATE, () => { currentIndexRef.current = newIndex; if (typeof activateFilterEffects === "function") { activateFilterEffects(); setFiltersActive(true); } }, "critical" ); } else { activateFilterEffects(); const transitionDuration = 1e3; setTimeout(() => { if (!isInteracting) { updateFilterIntensities(false); hideDisplacementEffects(); } }, transitionDuration); } } }, [ filtersInitialized, isInteracting, activateFilterEffects, updateFilterIntensities, hideDisplacementEffects, showDisplacementEffects, scheduler, setFiltersActive ]); const { nextSlide, prevSlide } = useSlides.useSlides({ ...hookParams, onSlideChange: handleSlideChange }); useTextContainers.default({ sliderRef, appRef, slidesRef, textContainersRef, currentIndex: currentIndexRef, buttonMode, texts, textTitleColor, textTitleSize, mobileTextTitleSize, textTitleLetterspacing, textTitleFontFamily, textSubTitleColor, textSubTitleSize, mobileTextSubTitleSize, textSubTitleLetterspacing, textSubTitleOffsetTop, mobileTextSubTitleOffsetTop, textSubTitleFontFamily, resourceManager: resourceManagerRef.current }); useMouseTracking.default({ ...hookParams, backgroundDisplacementSpriteRef, cursorDisplacementSpriteRef, cursorImgEffect, cursorMomentum }); useIdleTimer.default({ sliderRef, cursorActive: cursorActiveRef, bgDispFilterRef, cursorDispFilterRef, cursorImgEffect, defaultBgFilterScale: 20, defaultCursorFilterScale: 10, resourceManager: resourceManagerRef.current }); const handleNext = react.useCallback(() => { if (!appRef.current || !isAppReady || slidesRef.current.length === 0) return; const nextIndex = (currentSlideIndex + 1) % slidesRef.current.length; scheduler.scheduleTypedUpdate( "slider", UpdateTypes.UpdateType.SLIDE_TRANSITION, () => { nextSlide(nextIndex); currentIndexRef.current = nextIndex; setCurrentSlideIndex(nextIndex); setTimeout(() => { console.log("Scheduling effects after slide change (next)"); scheduler.scheduleTypedUpdate( "slider", UpdateTypes.UpdateType.DISPLACEMENT_EFFECT, () => { showDisplacementEffects(); }, // Use critical priority if cursor is within the canvas isInteracting ? "critical" : void 0 ); scheduler.scheduleTypedUpdate( "slider", UpdateTypes.UpdateType.FILTER_UPDATE, () => { currentIndexRef.current = nextIndex; if (typeof activateFilterEffects === "function") { activateFilterEffects(); if (isInteracting) { setFiltersActive(true); } } }, // Use critical priority if cursor is within the canvas isInteracting ? "critical" : void 0 ); }, 100); } ); }, [ appRef, isAppReady, slidesRef, currentSlideIndex, nextSlide, isInteracting, showDisplacementEffects, activateFilterEffects, scheduler, setFiltersActive ]); const handlePrev = react.useCallback(() => { if (!appRef.current || !isAppReady || slidesRef.current.length === 0) return; const prevIndex = (currentSlideIndex - 1 + slidesRef.current.length) % slidesRef.current.length; scheduler.scheduleTypedUpdate( "slider", UpdateTypes.UpdateType.SLIDE_TRANSITION, () => { prevSlide(prevIndex); currentIndexRef.current = prevIndex; setCurrentSlideIndex(prevIndex); setTimeout(() => { console.log("Scheduling effects after slide change (prev)"); scheduler.scheduleTypedUpdate( "slider", UpdateTypes.UpdateType.DISPLACEMENT_EFFECT, () => { showDisplacementEffects(); }, // Use critical priority if cursor is within the canvas isInteracting ? "critical" : void 0 ); scheduler.scheduleTypedUpdate( "slider", UpdateTypes.UpdateType.FILTER_UPDATE, () => { currentIndexRef.current = prevIndex; if (typeof activateFilterEffects === "function") { activateFilterEffects(); if (isInteracting) { setFiltersActive(true); } } }, // Use critical priority if cursor is within the canvas isInteracting ? "critical" : void 0 ); }, 100); } ); }, [ appRef, isAppReady, slidesRef, currentSlideIndex, prevSlide, isInteracting, showDisplacementEffects, activateFilterEffects, scheduler, setFiltersActive ]); react.useEffect(() => { if (!appRef.current || !isAppReady) return; currentIndexRef.current = currentSlideIndex; }, [appRef.current, currentSlideIndex, isAppReady]); useNavigation.default({ onNext: handleNext, onPrev: handlePrev, enableKeyboardNav: true }); useExternalNav.default({ externalNav, navElement, handleNext, handlePrev }); useTouchSwipe.default({ sliderRef, onSwipeLeft: handleNext, onSwipeRight: handlePrev }); useMouseDrag.default({ sliderRef, slidesRef, currentIndex: currentIndexRef, swipeScaleIntensity, swipeDistance: typeof window !== "undefined" ? window.innerWidth * 0.2 : 200, onSwipeLeft: handleNext, onSwipeRight: handlePrev }); useTextTilt.default({ sliderRef, textContainersRef, currentIndex: currentIndexRef, cursorTextEffect, maxContainerShiftFraction, bgDispFilterRef, cursorDispFilterRef, cursorImgEffect }); useResizeHandler.default({ sliderRef, appRef, slidesRef, textContainersRef, backgroundDisplacementSpriteRef, cursorDisplacementSpriteRef }); const handleMouseEnter = react.useCallback(() => { if (!isAppReady) return; console.log("Mouse entered the slider - activating effects immediately", { filtersInitialized, filtersActive, hasActivateFunction: typeof activateFilterEffects === "function", hasUpdateFunction: typeof updateFilterIntensities === "function", currentSlideIndex }); cursorActiveRef.current = true; setIsInteracting(true); scheduler.scheduleTypedUpdate( "slider", UpdateTypes.UpdateType.DISPLACEMENT_EFFECT, () => { showDisplacementEffects(); console.log("Displacement effects activated"); }, "critical" ); scheduler.scheduleTypedUpdate( "slider", UpdateTypes.UpdateType.FILTER_UPDATE, () => { if (!filtersInitialized && typeof activateFilterEffects === "function") { console.log("Filters not initialized, initializing now"); activateFilterEffects(); } else if (typeof activateFilterEffects === "function") { console.log("Using activateFilterEffects function for slide", currentSlideIndex); activateFilterEffects(); } else if (typeof updateFilterIntensities === "function") { console.log("Using updateFilterIntensities function with force=true"); updateFilterIntensities(true, true); } setFiltersActive(true); console.log("Filter activation completed with critical priority"); }, "critical" ); scheduler.scheduleTypedUpdate( "slider", UpdateTypes.UpdateType.FILTER_UPDATE, () => { console.log("Final render update after mouse enter completed"); console.log("Filter state after render:", { filtersActive, bgDispFilterEnabled: bgDispFilterRef.current?.enabled, cursorDispFilterEnabled: cursorDispFilterRef.current?.enabled, currentSlideIndex }); }, "critical" ); }, [ isAppReady, showDisplacementEffects, updateFilterIntensities, activateFilterEffects, filtersInitialized, filtersActive, setFiltersActive, currentSlideIndex, scheduler ]); const handleMouseLeave = react.useCallback(() => { if (!isAppReady) return; setIsInteracting(false); const event1 = new CustomEvent(FILTER_COORDINATION_EVENT, { detail: { type: "background-displacement", intensity: 0, timestamp: Date.now(), source: "slider-component", priority: "critical" } }); window.dispatchEvent(event1); const event2 = new CustomEvent(FILTER_COORDINATION_EVENT, { detail: { type: "cursor-displacement", intensity: 0, timestamp: Date.now(), source: "slider-component", priority: "critical" } }); window.dispatchEvent(event2); updateFilterIntensities(false, true); scheduler.scheduleTypedUpdate( "slider", UpdateTypes.UpdateType.FILTER_UPDATE, () => { }, "critical" ); }, [isAppReady, setIsInteracting, updateFilterIntensities, scheduler]); react.useEffect(() => { return () => { resetAllFilters(); if (resourceManagerRef.current) { resourceManagerRef.current.clearPendingUpdates(); } const transitionTimeouts = Array.from(document.querySelectorAll(`[data-slider-id="${sliderRef.current?.id}"]`)).map((el) => parseInt(el.getAttribute("data-timeout-id") || "0")).filter((id) => id > 0); transitionTimeouts.forEach(clearTimeout); }; }, [resetAllFilters]); react.useEffect(() => { const handleError = (error) => { console.error("Filter system error:", error); resetAllFilters(); hideDisplacementEffects(); }; window.addEventListener("error", (e) => handleError(e.error)); return () => window.removeEventListener("error", (e) => handleError(e.error)); }, [resetAllFilters, hideDisplacementEffects]); react.useEffect(() => { return () => { if (resourceManagerRef.current) { resourceManagerRef.current.clearPendingUpdates(); resourceManagerRef.current.markUnmounting(); } }; }, []); react.useEffect(() => { if (!resourceManagerRef.current) return; let frameCount = 0; let lastTime = performance.now(); let fps = 60; const monitorPerformance = () => { frameCount++; const currentTime = performance.now(); const elapsed = currentTime - lastTime; if (elapsed > 1e3) { fps = frameCount * 1e3 / elapsed; frameCount = 0; lastTime = currentTime; if (resourceManagerRef.current && fps < 55) { resourceManagerRef.current.autoOptimizeFilters(fps, 55); } } performanceMonitorId = requestAnimationFrame(monitorPerformance); }; let performanceMonitorId = requestAnimationFrame(monitorPerformance); return () => { if (performanceMonitorId) { cancelAnimationFrame(performanceMonitorId); } }; }, [resourceManagerRef]); return /* @__PURE__ */ jsxRuntime.jsxs( "div", { className: KineticSlider_module.default.kineticSlider, ref: sliderRef, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [ (!isAppReady || !assetsLoaded) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: KineticSlider_module.default.placeholder, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: KineticSlider_module.default.loadingIndicator, children: [ /* @__PURE__ */ jsxRuntime.jsx("div", { className: KineticSlider_module.default.spinner }), /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Loading slider..." }) ] }) }), !externalNav && isClient && /* @__PURE__ */ jsxRuntime.jsxs("nav", { children: [ /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: handlePrev, className: KineticSlider_module.default.prev, children: "Prev" }), /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: handleNext, className: KineticSlider_module.default.next, children: "Next" }) ] }) ] } ); }; exports.default = KineticSlider; //# sourceMappingURL=KineticSlider.cjs.map