UNPKG

@svelte-use/shared

Version:
327 lines (311 loc) 8.3 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var internal = require('svelte/internal'); var store = require('svelte/store'); var svelte = require('svelte'); /** * Call onDestroy() if it's inside a component lifecycle, if not, do nothing. * * @param fn */ function tryOnDestroy(fn) { if (tryGetCurrentComponent()) { svelte.onDestroy(fn); } } function writable(value, start = noop) { const s = store.writable(value, start); const runs = new Set(); const invalidates = new Set(); let unsubscribe; const prepareUnsubscribe = () => { unsubscribe = s.subscribe((val) => runAll([...runs], val), (val) => runAll([...invalidates], val)); }; if (tryGetCurrentComponent()) { prepareUnsubscribe(); } function set(newValue) { s.set(newValue); } function update(fn) { s.update(fn); } function subscribe(run = noop, invalidate = noop) { if (!unsubscribe) { prepareUnsubscribe(); } runs.add(run); invalidates.add(invalidate); const v = store.get(s); run(v); invalidate(v); return () => { runs.delete(run); invalidates.delete(invalidate); }; } const stop = () => { runs.clear(); invalidates.clear(); if (unsubscribe) { unsubscribe(); } }; tryOnDestroy(stop); return { set, update, subscribe, }; } const isClient = typeof window !== 'undefined'; const isDef = (val) => typeof val !== 'undefined'; const assert = (condition, ...infos) => { // eslint-disable-next-line no-console if (!condition) console.warn(...infos); }; const toString = Object.prototype.toString; const isBoolean = (val) => typeof val === 'boolean'; const isFunction = (val) => typeof val === 'function'; const isNumber = (val) => typeof val === 'number'; const isString = (val) => typeof val === 'string'; const isObject = (val) => toString.call(val) === '[object Object]'; const isWindow = (val) => typeof window !== 'undefined' && toString.call(val) === '[object Window]'; const isReadable = (store) => { return store && isFunction(store.subscribe); }; const isWritable = (store) => { return (store && ['subscribe', 'set', 'update'].every((n) => isFunction(store[n]))); }; const now = () => Date.now(); const timestamp = () => +Date.now(); const clamp = (n, min, max) => Math.min(max, Math.max(min, n)); const noop = () => { }; const rand = (min, max) => { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; }; /** * Run a function */ const run = (fn, ...args) => { fn(...args); }; /** * Run all functions */ const runAll = (fns, ...args) => { fns.forEach((fn) => run(fn, ...args)); }; /** * Silent `get_current_component`. Call `get_current_component()` without throw error. */ function tryGetCurrentComponent() { let currentComponent; try { currentComponent = internal.get_current_component(); } catch (_) { } return currentComponent; } function promiseTimeout(ms, throwOnTimeout = false, reason = 'Timeout') { return new Promise((resolve, reject) => { if (throwOnTimeout) { setTimeout(() => reject(reason), ms); } else { setTimeout(resolve, ms); } }); } function unstore(val) { return isReadable(val) ? store.get(val) : val; } function toReadable(val) { if (isWritable(val)) { return { subscribe: val.subscribe, }; } return isReadable(val) ? val : readable(val); } function toWritable(val) { return isWritable(val) ? val : writable(val); } function readable(value, start = noop) { return { subscribe: writable(value, start).subscribe, }; } /** * Call `onMount()` if it's inside a component lifecycle, if not, run just call the function. * * @param fn */ function tryOnMount(fn) { if (tryGetCurrentComponent()) { svelte.onMount(fn); } else { const cb = fn() || noop; tryOnDestroy(cb); } } /** * Wrapper for `setInterval` with controls * * @param cb * @param interval * @param options */ function useIntervalFn(cb, interval = 1000, options = {}) { const { immediate = true, immediateCallback = false } = options; let timer = null; const isActive = writable(false); function clean() { if (timer) { clearInterval(timer); timer = null; } } function pause() { isActive.set(false); clean(); } function resume() { if (interval <= 0) { return; } isActive.set(true); if (immediateCallback) { cb(); } clean(); timer = setInterval(cb, interval); } if (immediate && isClient) { resume(); } tryOnDestroy(pause); return { isActive, pause, resume, }; } function useInterval(interval = 1000, options = {}) { const { controls: exposeControls = false, immediate = true } = options; const counter = writable(0); const controls = useIntervalFn(() => { counter.update((c) => (c += 1)); }, interval, { immediate }); if (exposeControls) { return Object.assign({ counter }, controls); } return counter; } /** * Wrapper for `setTimeout` with controls. * * @param fn * @param interval * @param options */ function useTimeoutFn(cb, interval, options = {}) { const { immediate = true } = options; const isPending = writable(false); let timer = null; function clear() { if (timer) { clearTimeout(timer); timer = null; } } function stop() { isPending.set(false); clear(); } function start(...args) { clear(); isPending.set(true); timer = setTimeout(() => { isPending.set(false); timer = null; cb(...args); }, interval); } if (immediate) { isPending.set(true); if (isClient) { start(); } } tryOnDestroy(stop); return { isPending, start, stop, }; } function useTimeout(interval = 1000, options = {}) { const { controls: exposeControls = false } = options; const controls = useTimeoutFn(noop, interval, options); const ready = readable(true, (set) => { controls.isPending.subscribe((value) => set(!value)); }); if (exposeControls) { return Object.assign({ ready }, controls); } else { return ready; } } /** * Shorthand for watching value to be truthy * * @see https://svelte-use.vercel.app/shared/whenever */ function whenever(source, cb) { const store = toWritable(source); let ov; return store.subscribe((v) => { if (v) { cb(v, ov); ov = v; } }); } exports.assert = assert; exports.clamp = clamp; exports.isBoolean = isBoolean; exports.isClient = isClient; exports.isDef = isDef; exports.isFunction = isFunction; exports.isNumber = isNumber; exports.isObject = isObject; exports.isReadable = isReadable; exports.isString = isString; exports.isWindow = isWindow; exports.isWritable = isWritable; exports.noop = noop; exports.now = now; exports.promiseTimeout = promiseTimeout; exports.rand = rand; exports.readable = readable; exports.run = run; exports.runAll = runAll; exports.timestamp = timestamp; exports.toReadable = toReadable; exports.toWritable = toWritable; exports.tryGetCurrentComponent = tryGetCurrentComponent; exports.tryOnDestroy = tryOnDestroy; exports.tryOnMount = tryOnMount; exports.unstore = unstore; exports.useInterval = useInterval; exports.useIntervalFn = useIntervalFn; exports.useTimeout = useTimeout; exports.useTimeoutFn = useTimeoutFn; exports.whenever = whenever; exports.writable = writable;