UNPKG

overlayscrollbars-svelte

Version:
85 lines (84 loc) 2.88 kB
import { untrack } from 'svelte'; import { OverlayScrollbars } from 'overlayscrollbars'; const createDefer = () => { /* c8 ignore start */ if (typeof window === 'undefined') { // mock ssr calls with "noop" const noop = () => { }; return [noop, noop]; } /* c8 ignore end */ let idleId; let rafId; const wnd = window; const idleSupported = typeof wnd.requestIdleCallback === 'function'; const rAF = wnd.requestAnimationFrame; const cAF = wnd.cancelAnimationFrame; const rIdle = idleSupported ? wnd.requestIdleCallback : rAF; const cIdle = idleSupported ? wnd.cancelIdleCallback : cAF; const clear = () => { cIdle(idleId); cAF(rafId); }; return [ (callback, options) => { clear(); idleId = rIdle(idleSupported ? () => { clear(); // inside idle its best practice to use rAF to change DOM for best performance rafId = rAF(callback); } : callback, typeof options === 'object' ? options : { timeout: 2233 }); }, clear, ]; }; // eslint-disable-next-line @typescript-eslint/no-explicit-any const isAccessor = (obj) => typeof obj === 'function'; const unwrapAccessor = (obj) => (isAccessor(obj) ? obj() : obj); export const useOverlayScrollbars = (params) => { let instance = null; const [requestDefer, clearDefer] = createDefer(); const unwrappedParams = unwrapAccessor(params || {}); const options = $derived(unwrapAccessor(unwrappedParams.options)); const events = $derived(unwrapAccessor(unwrappedParams.events)); const defer = $derived(unwrapAccessor(unwrappedParams.defer)); $effect.pre(() => { const currOptions = options; if (OverlayScrollbars.valid(instance)) { instance.options(currOptions || {}, true); } }); $effect.pre(() => { const currEvents = events; if (OverlayScrollbars.valid(instance)) { instance.on(currEvents || {}, true); } }); $effect(() => { return () => { clearDefer(); instance?.destroy(); }; }); return [ (target) => { // if already initialized do nothing if (OverlayScrollbars.valid(instance)) { return instance; } const currOptions = untrack(() => options); const currEvents = untrack(() => events); const currDefer = untrack(() => defer); const init = () => (instance = OverlayScrollbars(target, currOptions || {}, currEvents || {})); if (currDefer) { requestDefer(init, currDefer); } else { init(); } }, () => instance, ]; };