@vueuse/shared
Advanced tools
Comparing version 4.0.0-beta.41 to 4.0.0-rc.1
@@ -41,3 +41,154 @@ 'use strict'; | ||
/*! ***************************************************************************** | ||
Copyright (c) Microsoft Corporation. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */ | ||
function __rest(s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { | ||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) | ||
t[p[i]] = s[p[i]]; | ||
} | ||
return t; | ||
} | ||
const isClient = typeof window !== 'undefined'; | ||
const isDef = (val) => typeof val !== 'undefined'; | ||
const assert = (condition, ...infos) => { | ||
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 now = () => Date.now(); | ||
const timestamp = () => +Date.now(); | ||
const clamp = (n, min, max) => Math.min(max, Math.max(min, n)); | ||
const noop = () => { }; | ||
/** | ||
* @internal | ||
*/ | ||
function createFilterWrapper(filter, fn) { | ||
function wrapper(...args) { | ||
filter(() => fn.apply(this, args), { fn, thisArg: this, args }); | ||
} | ||
return wrapper; | ||
} | ||
const bypassFilter = (invoke) => { | ||
return invoke(); | ||
}; | ||
/** | ||
* Create an EventFilter that debounce the events | ||
* | ||
* @param ms | ||
*/ | ||
function debounceFilter(ms) { | ||
if (ms <= 0) | ||
return bypassFilter; | ||
let timer; | ||
const filter = (invoke) => { | ||
if (timer) | ||
clearTimeout(timer); | ||
timer = setTimeout(invoke, ms); | ||
}; | ||
return filter; | ||
} | ||
/** | ||
* Create an EventFilter that throttle the events | ||
* | ||
* @param ms | ||
* @param [trailing=true] | ||
*/ | ||
function throttleFilter(ms, trailing = true) { | ||
if (ms <= 0) | ||
return bypassFilter; | ||
let lastExec = 0; | ||
let timer; | ||
const clear = () => { | ||
if (timer) { | ||
clearTimeout(timer); | ||
timer = undefined; | ||
} | ||
}; | ||
const filter = (invoke) => { | ||
const elapsed = Date.now() - lastExec; | ||
clear(); | ||
if (elapsed > ms) { | ||
lastExec = Date.now(); | ||
invoke(); | ||
} | ||
else if (trailing) { | ||
timer = setTimeout(() => { | ||
clear(); | ||
invoke(); | ||
}, ms); | ||
} | ||
}; | ||
return filter; | ||
} | ||
/** | ||
* EventFilter that gives extra controls to pause and resume the filter | ||
* | ||
* @param extendFilter Extra filter to apply when the PauseableFilter is active, default to none | ||
* | ||
*/ | ||
function pausableFilter(extendFilter = bypassFilter) { | ||
const isActive = vueDemi.ref(true); | ||
function pause() { | ||
isActive.value = false; | ||
} | ||
function resume() { | ||
isActive.value = true; | ||
} | ||
const eventFilter = (...args) => { | ||
if (isActive.value) | ||
extendFilter(...args); | ||
}; | ||
return { isActive, pause, resume, eventFilter }; | ||
} | ||
function promiseTimeout(ms, throwOnTimeout = false, reason = 'Timeout') { | ||
return new Promise((resolve, reject) => { | ||
if (throwOnTimeout) | ||
setTimeout(() => reject(reason), ms); | ||
else | ||
setTimeout(resolve, ms); | ||
}); | ||
} | ||
function invoke(fn) { | ||
return fn(); | ||
} | ||
// implementation | ||
function watchWithFilter(source, cb, options = {}) { | ||
const { eventFilter = bypassFilter } = options, watchOptions = __rest(options, ["eventFilter"]); | ||
return vueDemi.watch(source, createFilterWrapper(eventFilter, cb), watchOptions); | ||
} | ||
// implementation | ||
function debouncedWatch(source, cb, options = {}) { | ||
const { debounce = 0 } = options, watchOptions = __rest(options, ["debounce"]); | ||
return watchWithFilter(source, cb, Object.assign(Object.assign({}, watchOptions), { eventFilter: debounceFilter(debounce) })); | ||
} | ||
// implementation | ||
function extendRef(ref, extend, { enumerable = false, unwrap = true } = {}) { | ||
@@ -65,2 +216,69 @@ for (const [key, value] of Object.entries(extend)) { | ||
function ignorableWatch(source, cb, options = {}) { | ||
const { eventFilter = bypassFilter } = options, watchOptions = __rest(options, ["eventFilter"]); | ||
const filteredCb = createFilterWrapper(eventFilter, cb); | ||
let ignoreUpdates; | ||
let ignorePrevAsyncUpdates; | ||
let stop; | ||
if (watchOptions.flush === 'sync') { | ||
const ignore = vueDemi.ref(false); | ||
// no op for flush: sync | ||
ignorePrevAsyncUpdates = () => { }; | ||
ignoreUpdates = (updater) => { | ||
// Call the updater function and count how many sync updates are performed, | ||
// then add them to the ignore count | ||
ignore.value = true; | ||
updater(); | ||
ignore.value = false; | ||
}; | ||
stop = vueDemi.watch(source, (...args) => { | ||
if (!ignore.value) | ||
filteredCb(...args); | ||
}, watchOptions); | ||
} | ||
else { | ||
// flush 'pre' and 'post' | ||
const disposables = []; | ||
// counters for how many following changes to be ignored | ||
// ignoreCounter is incremented before there is a history operation | ||
// affecting the source ref value (undo, redo, revert). | ||
// syncCounter is incremented in sync with every change to the | ||
// source ref value. This let us know how many times the ref | ||
// was modified and support chained sync operations. If there | ||
// are more sync triggers than the ignore count, the we now | ||
// there are modifications in the source ref value that we | ||
// need to commit | ||
const ignoreCounter = vueDemi.ref(0); | ||
const syncCounter = vueDemi.ref(0); | ||
ignorePrevAsyncUpdates = () => { | ||
ignoreCounter.value = syncCounter.value; | ||
}; | ||
// Sync watch to count modifications to the source | ||
disposables.push(vueDemi.watch(source, () => { | ||
syncCounter.value++; | ||
}, Object.assign(Object.assign({}, watchOptions), { flush: 'sync' }))); | ||
ignoreUpdates = (updater) => { | ||
// Call the updater function and count how many sync updates are performed, | ||
// then add them to the ignore count | ||
const syncCounterPrev = syncCounter.value; | ||
updater(); | ||
ignoreCounter.value += syncCounter.value - syncCounterPrev; | ||
}; | ||
disposables.push(vueDemi.watch(source, (...args) => { | ||
// If a history operation was performed (ignoreCounter > 0) and there are | ||
// no other changes to the source ref value afterwards, then ignore this commit | ||
const ignore = ignoreCounter.value > 0 && ignoreCounter.value === syncCounter.value; | ||
ignoreCounter.value = 0; | ||
syncCounter.value = 0; | ||
if (ignore) | ||
return; | ||
filteredCb(...args); | ||
}, watchOptions)); | ||
stop = () => { | ||
disposables.forEach(fn => fn()); | ||
}; | ||
} | ||
return { stop, ignoreUpdates, ignorePrevAsyncUpdates }; | ||
} | ||
function makeDestructurable(obj, arr) { | ||
@@ -88,2 +306,10 @@ if (typeof Symbol !== 'undefined') { | ||
// implementation | ||
function pausableWatch(source, cb, options = {}) { | ||
const { eventFilter: filter } = options, watchOptions = __rest(options, ["eventFilter"]); | ||
const { eventFilter, pause, resume, isActive } = pausableFilter(filter); | ||
const stop = watchWithFilter(source, cb, Object.assign(Object.assign({}, watchOptions), { eventFilter })); | ||
return { stop, pause, resume, isActive }; | ||
} | ||
/** | ||
@@ -107,2 +333,8 @@ * Keep target ref(s) in sync with the source ref | ||
// implementation | ||
function throttledWatch(source, cb, options = {}) { | ||
const { throttle = 0 } = options, watchOptions = __rest(options, ["throttle"]); | ||
return watchWithFilter(source, cb, Object.assign(Object.assign({}, watchOptions), { eventFilter: throttleFilter(throttle) })); | ||
} | ||
/** | ||
@@ -133,35 +365,170 @@ * Call onMounted() if it's inside a component lifecycle, if not, run just call the function | ||
const isClient = typeof window !== 'undefined'; | ||
const isDef = (val) => typeof val !== 'undefined'; | ||
const assert = (condition, ...infos) => { | ||
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 now = () => Date.now(); | ||
const timestamp = () => +Date.now(); | ||
const clamp = (n, min, max) => Math.min(max, Math.max(min, n)); | ||
const noop = () => { }; | ||
/** | ||
* Debounce execution of a function. | ||
* | ||
* @param fn A function to be executed after delay milliseconds debounced. | ||
* @param ms A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. | ||
* | ||
* @return A new, debounce, function. | ||
*/ | ||
function useDebounceFn(fn, ms = 200) { | ||
return createFilterWrapper(debounceFilter(ms), fn); | ||
} | ||
function promiseTimeout(ms, throwOnTimeout = false, reason = 'Timeout') { | ||
return new Promise((resolve, reject) => { | ||
if (throwOnTimeout) | ||
setTimeout(() => reject(reason), ms); | ||
else | ||
setTimeout(resolve, ms); | ||
}); | ||
function useDebounce(value, ms = 200) { | ||
if (ms <= 0) | ||
return value; | ||
const debounced = vueDemi.ref(value.value); | ||
const updater = useDebounceFn(() => { | ||
debounced.value = value.value; | ||
}, ms); | ||
vueDemi.watch(value, () => updater()); | ||
return debounced; | ||
} | ||
function invoke(fn) { | ||
return fn(); | ||
/** | ||
* Wrapper for `setInterval` with controls | ||
* | ||
* @param cb | ||
* @param interval | ||
* @param immediate | ||
*/ | ||
function useIntervalFn(cb, interval = 1000, immediate = true) { | ||
let timer = null; | ||
const isActive = vueDemi.ref(false); | ||
function clean() { | ||
if (timer) { | ||
clearInterval(timer); | ||
timer = null; | ||
} | ||
} | ||
function pause() { | ||
isActive.value = false; | ||
clean(); | ||
} | ||
function resume() { | ||
isActive.value = true; | ||
clean(); | ||
timer = setInterval(cb, interval); | ||
} | ||
if (immediate) | ||
resume(); | ||
tryOnUnmounted(pause); | ||
return { | ||
isActive, | ||
pause, | ||
resume, | ||
start: resume, | ||
stop: pause, | ||
}; | ||
} | ||
function when(r) { | ||
function useInterval(interval = 1000, immediate = true) { | ||
const counter = vueDemi.ref(0); | ||
return Object.assign({ counter }, useIntervalFn(() => counter.value += 1, interval, immediate)); | ||
} | ||
/** | ||
* Throttle execution of a function. Especially useful for rate limiting | ||
* execution of handlers on events like resize and scroll. | ||
* | ||
* @param fn A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is, | ||
* to `callback` when the throttled-function is executed. | ||
* @param ms A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. | ||
* | ||
* @return A new, throttled, function. | ||
*/ | ||
function useThrottleFn(fn, ms = 200, trailing = true) { | ||
return createFilterWrapper(throttleFilter(ms, trailing), fn); | ||
} | ||
/** | ||
* Throttle execution of a function. Especially useful for rate limiting | ||
* execution of handlers on events like resize and scroll. | ||
* | ||
* @param delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. | ||
*/ | ||
function useThrottle(value, delay = 200) { | ||
if (delay <= 0) | ||
return value; | ||
const throttled = vueDemi.ref(value.value); | ||
const updater = useThrottleFn(() => { | ||
throttled.value = value.value; | ||
}, delay); | ||
vueDemi.watch(value, () => updater()); | ||
return throttled; | ||
} | ||
/** | ||
* Wrapper for `setTimeout` with controls. | ||
* | ||
* @param cb | ||
* @param interval | ||
* @param immediate | ||
*/ | ||
function useTimeoutFn(cb, interval, immediate) { | ||
const isActive = vueDemi.ref(false); | ||
let timer = null; | ||
function clear() { | ||
if (timer) { | ||
clearTimeout(timer); | ||
timer = null; | ||
} | ||
} | ||
function stop() { | ||
isActive.value = false; | ||
stop(); | ||
} | ||
function start() { | ||
clear(); | ||
isActive.value = true; | ||
timer = setTimeout(() => { | ||
timer = null; | ||
cb(); | ||
}, interval); | ||
} | ||
if (immediate) | ||
start(); | ||
tryOnUnmounted(stop); | ||
return { | ||
isActive, | ||
start, | ||
stop, | ||
}; | ||
} | ||
/** | ||
* Update value after a given time with controls. | ||
* | ||
* @param interval | ||
* @param immediate | ||
*/ | ||
function useTimeout(interval = 1000, immediate = true) { | ||
const ready = vueDemi.ref(false); | ||
const controls = useTimeoutFn(() => ready.value = true, interval, immediate); | ||
function stop() { | ||
ready.value = false; | ||
controls.stop(); | ||
} | ||
function start() { | ||
ready.value = false; | ||
controls.start(); | ||
} | ||
return { | ||
ready, | ||
isActive: controls.isActive, | ||
start, | ||
stop, | ||
}; | ||
} | ||
/** | ||
* Promised one-time watch for ref changes | ||
* @param r ref or watch source | ||
* @param options | ||
*/ | ||
function when(r, rootOptions = {}) { | ||
let isNot = false; | ||
function toMatch(condition, { flush = 'sync', timeout, throwOnTimeout } = {}) { | ||
function toMatch(condition, options = {}) { | ||
const { flush = 'pre', timeout = 0, throwOnTimeout = false, } = Object.assign(Object.assign({}, rootOptions), options); | ||
let stop = null; | ||
@@ -236,5 +603,10 @@ const watcher = new Promise((resolve) => { | ||
exports.biSyncRef = biSyncRef; | ||
exports.bypassFilter = bypassFilter; | ||
exports.clamp = clamp; | ||
exports.controlledComputed = controlledComputed; | ||
exports.createFilterWrapper = createFilterWrapper; | ||
exports.debounceFilter = debounceFilter; | ||
exports.debouncedWatch = debouncedWatch; | ||
exports.extendRef = extendRef; | ||
exports.ignorableWatch = ignorableWatch; | ||
exports.invoke = invoke; | ||
@@ -252,7 +624,20 @@ exports.isBoolean = isBoolean; | ||
exports.now = now; | ||
exports.pausableFilter = pausableFilter; | ||
exports.pausableWatch = pausableWatch; | ||
exports.promiseTimeout = promiseTimeout; | ||
exports.syncRef = syncRef; | ||
exports.throttleFilter = throttleFilter; | ||
exports.throttledWatch = throttledWatch; | ||
exports.timestamp = timestamp; | ||
exports.tryOnMounted = tryOnMounted; | ||
exports.tryOnUnmounted = tryOnUnmounted; | ||
exports.useDebounce = useDebounce; | ||
exports.useDebounceFn = useDebounceFn; | ||
exports.useInterval = useInterval; | ||
exports.useIntervalFn = useIntervalFn; | ||
exports.useThrottle = useThrottle; | ||
exports.useThrottleFn = useThrottleFn; | ||
exports.useTimeout = useTimeout; | ||
exports.useTimeoutFn = useTimeoutFn; | ||
exports.watchWithFilter = watchWithFilter; | ||
exports.when = when; |
@@ -1,3 +0,3 @@ | ||
import { Ref, WatchSource, ShallowUnwrapRef, WatchOptions } from 'vue-demi'; | ||
import { ComputedRef, WatchStopHandle } from 'vue-demi'; | ||
import { Ref, WatchSource, ComputedRef as ComputedRef$1, WatchOptions, WatchCallback, WatchStopHandle, ShallowUnwrapRef } from 'vue-demi'; | ||
import { ComputedRef, WatchStopHandle as WatchStopHandle$1, Ref as Ref$1 } from 'vue-demi'; | ||
@@ -14,2 +14,104 @@ declare function biSyncRef<R extends Ref<any>>(a: R, b: R): () => void; | ||
declare const isClient: boolean; | ||
declare const isDef: <T = any>(val?: T | undefined) => val is T; | ||
declare const assert: (condition: boolean, ...infos: any[]) => void; | ||
declare const isBoolean: (val: any) => val is boolean; | ||
declare const isFunction: <T = Function>(val: any) => val is T; | ||
declare const isNumber: (val: any) => val is number; | ||
declare const isString: (val: unknown) => val is string; | ||
declare const isObject: (val: any) => val is object; | ||
declare const isWindow: (val: any) => val is Window; | ||
declare const now: () => number; | ||
declare const timestamp: () => number; | ||
declare const clamp: (n: number, min: number, max: number) => number; | ||
declare const noop: () => void; | ||
declare type Fn = () => void; | ||
declare type MaybeRef<T> = T | Ref<T> | ComputedRef$1<T>; | ||
interface Pausable { | ||
/** | ||
* A ref indicate whether a pusable instance is active | ||
*/ | ||
isActive: Ref<boolean>; | ||
/** | ||
* Temporary pause the effect from executing | ||
*/ | ||
pause: Fn; | ||
/** | ||
* Resume the effects | ||
*/ | ||
resume: Fn; | ||
} | ||
interface ConfigurableFlush { | ||
/** | ||
* Timing for monitoring changes, refer to WatchOptions for more details | ||
* | ||
* @default 'pre' | ||
*/ | ||
flush?: WatchOptions['flush']; | ||
} | ||
interface ConfigurableFlushSync { | ||
/** | ||
* Timing for monitoring changes, refer to WatchOptions for more details. | ||
* Unlike `watch()`, the default is set to `sync` | ||
* | ||
* @default 'sync' | ||
*/ | ||
flush?: WatchOptions['flush']; | ||
} | ||
declare type MapSources<T> = { | ||
[K in keyof T]: T[K] extends WatchSource<infer V> ? V : never; | ||
}; | ||
declare type MapOldSources<T, Immediate> = { | ||
[K in keyof T]: T[K] extends WatchSource<infer V> ? Immediate extends true ? V | undefined : V : never; | ||
}; | ||
declare type FunctionArgs<Args extends any[] = any[], Return = void> = (...args: Args) => Return; | ||
interface FunctionWrapperOptions<Args extends any[] = any[], This = any> { | ||
fn: FunctionArgs<Args, This>; | ||
args: Args; | ||
thisArg: This; | ||
} | ||
declare type EventFilter<Args extends any[] = any[], This = any> = (invoke: Fn, options: FunctionWrapperOptions<Args, This>) => void; | ||
interface ConfigurableEventFilter { | ||
eventFilter?: EventFilter; | ||
} | ||
/** | ||
* @internal | ||
*/ | ||
declare function createFilterWrapper<T extends FunctionArgs>(filter: EventFilter, fn: T): T; | ||
declare const bypassFilter: EventFilter; | ||
/** | ||
* Create an EventFilter that debounce the events | ||
* | ||
* @param ms | ||
*/ | ||
declare function debounceFilter(ms: number): EventFilter<any[], any>; | ||
/** | ||
* Create an EventFilter that throttle the events | ||
* | ||
* @param ms | ||
* @param [trailing=true] | ||
*/ | ||
declare function throttleFilter(ms: number, trailing?: boolean): EventFilter<any[], any>; | ||
/** | ||
* EventFilter that gives extra controls to pause and resume the filter | ||
* | ||
* @param extendFilter Extra filter to apply when the PauseableFilter is active, default to none | ||
* | ||
*/ | ||
declare function pausableFilter(extendFilter?: EventFilter): Pausable & { | ||
eventFilter: EventFilter; | ||
}; | ||
declare function promiseTimeout(ms: number, throwOnTimeout?: boolean, reason?: string): Promise<void>; | ||
declare function invoke<T>(fn: () => T): T; | ||
interface DebouncedWatchOptions<Immediate> extends WatchOptions<Immediate> { | ||
debounce?: number; | ||
} | ||
declare function debouncedWatch<T extends Readonly<WatchSource<unknown>[]>, Immediate extends Readonly<boolean> = false>(sources: T, cb: WatchCallback<MapSources<T>, MapOldSources<T, Immediate>>, options?: DebouncedWatchOptions<Immediate>): WatchStopHandle; | ||
declare function debouncedWatch<T, Immediate extends Readonly<boolean> = false>(source: WatchSource<T>, cb: WatchCallback<T, Immediate extends true ? T | undefined : T>, options?: DebouncedWatchOptions<Immediate>): WatchStopHandle; | ||
declare function debouncedWatch<T extends object, Immediate extends Readonly<boolean> = false>(source: T, cb: WatchCallback<T, Immediate extends true ? T | undefined : T>, options?: DebouncedWatchOptions<Immediate>): WatchStopHandle; | ||
interface ExtendRefOptions<Unwrap extends boolean = boolean> { | ||
@@ -38,12 +140,29 @@ /** | ||
interface WatchWithFilterOptions<Immediate> extends WatchOptions<Immediate>, ConfigurableEventFilter { | ||
} | ||
declare function watchWithFilter<T extends Readonly<WatchSource<unknown>[]>, Immediate extends Readonly<boolean> = false>(sources: T, cb: WatchCallback<MapSources<T>, MapOldSources<T, Immediate>>, options?: WatchWithFilterOptions<Immediate>): WatchStopHandle; | ||
declare function watchWithFilter<T, Immediate extends Readonly<boolean> = false>(source: WatchSource<T>, cb: WatchCallback<T, Immediate extends true ? T | undefined : T>, options?: WatchWithFilterOptions<Immediate>): WatchStopHandle; | ||
declare function watchWithFilter<T extends object, Immediate extends Readonly<boolean> = false>(source: T, cb: WatchCallback<T, Immediate extends true ? T | undefined : T>, options?: WatchWithFilterOptions<Immediate>): WatchStopHandle; | ||
declare type IgnoredUpdater = (updater: () => void) => void; | ||
interface IgnorableWatchReturn { | ||
ignoreUpdates: IgnoredUpdater; | ||
ignorePrevAsyncUpdates: () => void; | ||
stop: WatchStopHandle; | ||
} | ||
declare function ignorableWatch<T extends Readonly<WatchSource<unknown>[]>, Immediate extends Readonly<boolean> = false>(sources: T, cb: WatchCallback<MapSources<T>, MapOldSources<T, Immediate>>, options?: WatchWithFilterOptions<Immediate>): IgnorableWatchReturn; | ||
declare function ignorableWatch<T, Immediate extends Readonly<boolean> = false>(source: WatchSource<T>, cb: WatchCallback<T, Immediate extends true ? T | undefined : T>, options?: WatchWithFilterOptions<Immediate>): IgnorableWatchReturn; | ||
declare function ignorableWatch<T extends object, Immediate extends Readonly<boolean> = false>(source: T, cb: WatchCallback<T, Immediate extends true ? T | undefined : T>, options?: WatchWithFilterOptions<Immediate>): IgnorableWatchReturn; | ||
declare function makeDestructurable<T extends Record<string, unknown>, A extends readonly any[]>(obj: T, arr: A): T & A; | ||
interface SyncRefOptions { | ||
interface PausableWatchReturn extends Pausable { | ||
stop: WatchStopHandle; | ||
} | ||
declare function pausableWatch<T extends Readonly<WatchSource<unknown>[]>, Immediate extends Readonly<boolean> = false>(sources: T, cb: WatchCallback<MapSources<T>, MapOldSources<T, Immediate>>, options?: WatchWithFilterOptions<Immediate>): PausableWatchReturn; | ||
declare function pausableWatch<T, Immediate extends Readonly<boolean> = false>(source: WatchSource<T>, cb: WatchCallback<T, Immediate extends true ? T | undefined : T>, options?: WatchWithFilterOptions<Immediate>): PausableWatchReturn; | ||
declare function pausableWatch<T extends object, Immediate extends Readonly<boolean> = false>(source: T, cb: WatchCallback<T, Immediate extends true ? T | undefined : T>, options?: WatchWithFilterOptions<Immediate>): PausableWatchReturn; | ||
interface SyncRefOptions extends ConfigurableFlushSync { | ||
/** | ||
* Timing for syncing, same as watch's flush option | ||
* | ||
* @default 'sync' | ||
*/ | ||
flush?: WatchOptions['flush']; | ||
/** | ||
* Watch deeply | ||
@@ -67,4 +186,11 @@ * | ||
*/ | ||
declare function syncRef<R extends Ref<any>>(source: R, targets: R | R[], { flush, deep, immediate, }?: SyncRefOptions): WatchStopHandle; | ||
declare function syncRef<R extends Ref<any>>(source: R, targets: R | R[], { flush, deep, immediate, }?: SyncRefOptions): WatchStopHandle$1; | ||
interface ThrottledWatchOptions<Immediate> extends WatchOptions<Immediate> { | ||
throttle?: number; | ||
} | ||
declare function throttledWatch<T extends Readonly<WatchSource<unknown>[]>, Immediate extends Readonly<boolean> = false>(sources: T, cb: WatchCallback<MapSources<T>, MapOldSources<T, Immediate>>, options?: ThrottledWatchOptions<Immediate>): WatchStopHandle; | ||
declare function throttledWatch<T, Immediate extends Readonly<boolean> = false>(source: WatchSource<T>, cb: WatchCallback<T, Immediate extends true ? T | undefined : T>, options?: ThrottledWatchOptions<Immediate>): WatchStopHandle; | ||
declare function throttledWatch<T extends object, Immediate extends Readonly<boolean> = false>(source: T, cb: WatchCallback<T, Immediate extends true ? T | undefined : T>, options?: ThrottledWatchOptions<Immediate>): WatchStopHandle; | ||
/** | ||
@@ -76,3 +202,3 @@ * Call onMounted() if it's inside a component lifecycle, if not, run just call the function | ||
*/ | ||
declare function tryOnMounted(fn: () => void, sync?: boolean): void; | ||
declare function tryOnMounted(fn: Fn, sync?: boolean): void; | ||
@@ -84,25 +210,103 @@ /** | ||
*/ | ||
declare function tryOnUnmounted(fn: () => void): void; | ||
declare function tryOnUnmounted(fn: Fn): void; | ||
declare const isClient: boolean; | ||
declare const isDef: <T = any>(val?: T | undefined) => val is T; | ||
declare const assert: (condition: boolean, ...infos: any[]) => void; | ||
declare const isBoolean: (val: any) => val is boolean; | ||
declare const isFunction: <T = Function>(val: any) => val is T; | ||
declare const isNumber: (val: any) => val is number; | ||
declare const isString: (val: unknown) => val is string; | ||
declare const isObject: (val: any) => val is object; | ||
declare const isWindow: (val: any) => val is Window; | ||
declare const now: () => number; | ||
declare const timestamp: () => number; | ||
declare const clamp: (n: number, min: number, max: number) => number; | ||
declare const noop: () => void; | ||
declare function useDebounce<T>(value: Ref<T>, ms?: number): Ref<T>; | ||
declare type MaybeRef<T> = T | Ref<T>; | ||
declare function promiseTimeout(ms: number, throwOnTimeout?: boolean, reason?: string): Promise<void>; | ||
declare function invoke<T>(fn: () => T): T; | ||
/** | ||
* Debounce execution of a function. | ||
* | ||
* @param fn A function to be executed after delay milliseconds debounced. | ||
* @param ms A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. | ||
* | ||
* @return A new, debounce, function. | ||
*/ | ||
declare function useDebounceFn<T extends FunctionArgs>(fn: T, ms?: number): T; | ||
interface WhenToMatchOptions { | ||
flush?: WatchOptions['flush']; | ||
declare function useInterval(interval?: number, immediate?: boolean): { | ||
stop: Fn; | ||
start: Fn; | ||
isActive: Ref$1<boolean>; | ||
pause: Fn; | ||
resume: Fn; | ||
counter: Ref$1<number>; | ||
}; | ||
interface IntervalFnReturn extends Pausable { | ||
/** | ||
* @deprecated use pause() instead | ||
*/ | ||
stop: Fn; | ||
/** | ||
* @deprecated use resume() instead | ||
*/ | ||
start: Fn; | ||
} | ||
/** | ||
* Wrapper for `setInterval` with controls | ||
* | ||
* @param cb | ||
* @param interval | ||
* @param immediate | ||
*/ | ||
declare function useIntervalFn(cb: Fn, interval?: number, immediate?: boolean): IntervalFnReturn; | ||
/** | ||
* Throttle execution of a function. Especially useful for rate limiting | ||
* execution of handlers on events like resize and scroll. | ||
* | ||
* @param delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. | ||
*/ | ||
declare function useThrottle<T>(value: Ref<T>, delay?: number): Ref<T>; | ||
/** | ||
* Throttle execution of a function. Especially useful for rate limiting | ||
* execution of handlers on events like resize and scroll. | ||
* | ||
* @param fn A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is, | ||
* to `callback` when the throttled-function is executed. | ||
* @param ms A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. | ||
* | ||
* @return A new, throttled, function. | ||
*/ | ||
declare function useThrottleFn<T extends FunctionArgs>(fn: T, ms?: number, trailing?: boolean): T; | ||
/** | ||
* Update value after a given time with controls. | ||
* | ||
* @param interval | ||
* @param immediate | ||
*/ | ||
declare function useTimeout(interval?: number, immediate?: boolean): { | ||
ready: Ref$1<boolean>; | ||
isActive: Ref$1<boolean>; | ||
start: () => void; | ||
stop: () => void; | ||
}; | ||
/** | ||
* Wrapper for `setTimeout` with controls. | ||
* | ||
* @param cb | ||
* @param interval | ||
* @param immediate | ||
*/ | ||
declare function useTimeoutFn(cb: () => any, interval?: number, immediate?: boolean): { | ||
isActive: Ref$1<boolean>; | ||
start: () => void; | ||
stop: () => void; | ||
}; | ||
interface WhenToMatchOptions extends ConfigurableFlush { | ||
/** | ||
* Milseconds timeout for promise to resolve/reject if the when condition does not meet. | ||
* 0 for never timed out | ||
* | ||
* @default 0 | ||
*/ | ||
timeout?: number; | ||
/** | ||
* Reject the promise when timeout | ||
* | ||
* @default false | ||
*/ | ||
throwOnTimeout?: boolean; | ||
@@ -122,4 +326,9 @@ } | ||
} | ||
declare function when<T>(r: WatchSource<T> | object): WhenInstance<T>; | ||
/** | ||
* Promised one-time watch for ref changes | ||
* @param r ref or watch source | ||
* @param options | ||
*/ | ||
declare function when<T>(r: WatchSource<T> | object, rootOptions?: WhenToMatchOptions): WhenInstance<T>; | ||
export { ExtendRefOptions, MaybeRef, SyncRefOptions, WhenInstance, WhenToMatchOptions, assert, biSyncRef, clamp, controlledComputed, extendRef, invoke, isBoolean, isClient, isDef, isFunction, isNumber, isObject, isString, isWindow, makeDestructurable, noop, now, promiseTimeout, syncRef, timestamp, tryOnMounted, tryOnUnmounted, when }; | ||
export { ConfigurableEventFilter, ConfigurableFlush, ConfigurableFlushSync, DebouncedWatchOptions, EventFilter, ExtendRefOptions, Fn, FunctionArgs, FunctionWrapperOptions, IgnorableWatchReturn, IgnoredUpdater, IntervalFnReturn, MapOldSources, MapSources, MaybeRef, Pausable, PausableWatchReturn, SyncRefOptions, ThrottledWatchOptions, WatchWithFilterOptions, WhenInstance, WhenToMatchOptions, assert, biSyncRef, bypassFilter, clamp, controlledComputed, createFilterWrapper, debounceFilter, debouncedWatch, extendRef, ignorableWatch, invoke, isBoolean, isClient, isDef, isFunction, isNumber, isObject, isString, isWindow, makeDestructurable, noop, now, pausableFilter, pausableWatch, promiseTimeout, syncRef, throttleFilter, throttledWatch, timestamp, tryOnMounted, tryOnUnmounted, useDebounce, useDebounceFn, useInterval, useIntervalFn, useThrottle, useThrottleFn, useTimeout, useTimeoutFn, watchWithFilter, when }; |
@@ -37,3 +37,154 @@ import { watch, ref, computed, isRef, getCurrentInstance, onMounted, nextTick, onUnmounted } from 'vue-demi'; | ||
/*! ***************************************************************************** | ||
Copyright (c) Microsoft Corporation. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */ | ||
function __rest(s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { | ||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) | ||
t[p[i]] = s[p[i]]; | ||
} | ||
return t; | ||
} | ||
const isClient = typeof window !== 'undefined'; | ||
const isDef = (val) => typeof val !== 'undefined'; | ||
const assert = (condition, ...infos) => { | ||
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 now = () => Date.now(); | ||
const timestamp = () => +Date.now(); | ||
const clamp = (n, min, max) => Math.min(max, Math.max(min, n)); | ||
const noop = () => { }; | ||
/** | ||
* @internal | ||
*/ | ||
function createFilterWrapper(filter, fn) { | ||
function wrapper(...args) { | ||
filter(() => fn.apply(this, args), { fn, thisArg: this, args }); | ||
} | ||
return wrapper; | ||
} | ||
const bypassFilter = (invoke) => { | ||
return invoke(); | ||
}; | ||
/** | ||
* Create an EventFilter that debounce the events | ||
* | ||
* @param ms | ||
*/ | ||
function debounceFilter(ms) { | ||
if (ms <= 0) | ||
return bypassFilter; | ||
let timer; | ||
const filter = (invoke) => { | ||
if (timer) | ||
clearTimeout(timer); | ||
timer = setTimeout(invoke, ms); | ||
}; | ||
return filter; | ||
} | ||
/** | ||
* Create an EventFilter that throttle the events | ||
* | ||
* @param ms | ||
* @param [trailing=true] | ||
*/ | ||
function throttleFilter(ms, trailing = true) { | ||
if (ms <= 0) | ||
return bypassFilter; | ||
let lastExec = 0; | ||
let timer; | ||
const clear = () => { | ||
if (timer) { | ||
clearTimeout(timer); | ||
timer = undefined; | ||
} | ||
}; | ||
const filter = (invoke) => { | ||
const elapsed = Date.now() - lastExec; | ||
clear(); | ||
if (elapsed > ms) { | ||
lastExec = Date.now(); | ||
invoke(); | ||
} | ||
else if (trailing) { | ||
timer = setTimeout(() => { | ||
clear(); | ||
invoke(); | ||
}, ms); | ||
} | ||
}; | ||
return filter; | ||
} | ||
/** | ||
* EventFilter that gives extra controls to pause and resume the filter | ||
* | ||
* @param extendFilter Extra filter to apply when the PauseableFilter is active, default to none | ||
* | ||
*/ | ||
function pausableFilter(extendFilter = bypassFilter) { | ||
const isActive = ref(true); | ||
function pause() { | ||
isActive.value = false; | ||
} | ||
function resume() { | ||
isActive.value = true; | ||
} | ||
const eventFilter = (...args) => { | ||
if (isActive.value) | ||
extendFilter(...args); | ||
}; | ||
return { isActive, pause, resume, eventFilter }; | ||
} | ||
function promiseTimeout(ms, throwOnTimeout = false, reason = 'Timeout') { | ||
return new Promise((resolve, reject) => { | ||
if (throwOnTimeout) | ||
setTimeout(() => reject(reason), ms); | ||
else | ||
setTimeout(resolve, ms); | ||
}); | ||
} | ||
function invoke(fn) { | ||
return fn(); | ||
} | ||
// implementation | ||
function watchWithFilter(source, cb, options = {}) { | ||
const { eventFilter = bypassFilter } = options, watchOptions = __rest(options, ["eventFilter"]); | ||
return watch(source, createFilterWrapper(eventFilter, cb), watchOptions); | ||
} | ||
// implementation | ||
function debouncedWatch(source, cb, options = {}) { | ||
const { debounce = 0 } = options, watchOptions = __rest(options, ["debounce"]); | ||
return watchWithFilter(source, cb, Object.assign(Object.assign({}, watchOptions), { eventFilter: debounceFilter(debounce) })); | ||
} | ||
// implementation | ||
function extendRef(ref, extend, { enumerable = false, unwrap = true } = {}) { | ||
@@ -61,2 +212,69 @@ for (const [key, value] of Object.entries(extend)) { | ||
function ignorableWatch(source, cb, options = {}) { | ||
const { eventFilter = bypassFilter } = options, watchOptions = __rest(options, ["eventFilter"]); | ||
const filteredCb = createFilterWrapper(eventFilter, cb); | ||
let ignoreUpdates; | ||
let ignorePrevAsyncUpdates; | ||
let stop; | ||
if (watchOptions.flush === 'sync') { | ||
const ignore = ref(false); | ||
// no op for flush: sync | ||
ignorePrevAsyncUpdates = () => { }; | ||
ignoreUpdates = (updater) => { | ||
// Call the updater function and count how many sync updates are performed, | ||
// then add them to the ignore count | ||
ignore.value = true; | ||
updater(); | ||
ignore.value = false; | ||
}; | ||
stop = watch(source, (...args) => { | ||
if (!ignore.value) | ||
filteredCb(...args); | ||
}, watchOptions); | ||
} | ||
else { | ||
// flush 'pre' and 'post' | ||
const disposables = []; | ||
// counters for how many following changes to be ignored | ||
// ignoreCounter is incremented before there is a history operation | ||
// affecting the source ref value (undo, redo, revert). | ||
// syncCounter is incremented in sync with every change to the | ||
// source ref value. This let us know how many times the ref | ||
// was modified and support chained sync operations. If there | ||
// are more sync triggers than the ignore count, the we now | ||
// there are modifications in the source ref value that we | ||
// need to commit | ||
const ignoreCounter = ref(0); | ||
const syncCounter = ref(0); | ||
ignorePrevAsyncUpdates = () => { | ||
ignoreCounter.value = syncCounter.value; | ||
}; | ||
// Sync watch to count modifications to the source | ||
disposables.push(watch(source, () => { | ||
syncCounter.value++; | ||
}, Object.assign(Object.assign({}, watchOptions), { flush: 'sync' }))); | ||
ignoreUpdates = (updater) => { | ||
// Call the updater function and count how many sync updates are performed, | ||
// then add them to the ignore count | ||
const syncCounterPrev = syncCounter.value; | ||
updater(); | ||
ignoreCounter.value += syncCounter.value - syncCounterPrev; | ||
}; | ||
disposables.push(watch(source, (...args) => { | ||
// If a history operation was performed (ignoreCounter > 0) and there are | ||
// no other changes to the source ref value afterwards, then ignore this commit | ||
const ignore = ignoreCounter.value > 0 && ignoreCounter.value === syncCounter.value; | ||
ignoreCounter.value = 0; | ||
syncCounter.value = 0; | ||
if (ignore) | ||
return; | ||
filteredCb(...args); | ||
}, watchOptions)); | ||
stop = () => { | ||
disposables.forEach(fn => fn()); | ||
}; | ||
} | ||
return { stop, ignoreUpdates, ignorePrevAsyncUpdates }; | ||
} | ||
function makeDestructurable(obj, arr) { | ||
@@ -84,2 +302,10 @@ if (typeof Symbol !== 'undefined') { | ||
// implementation | ||
function pausableWatch(source, cb, options = {}) { | ||
const { eventFilter: filter } = options, watchOptions = __rest(options, ["eventFilter"]); | ||
const { eventFilter, pause, resume, isActive } = pausableFilter(filter); | ||
const stop = watchWithFilter(source, cb, Object.assign(Object.assign({}, watchOptions), { eventFilter })); | ||
return { stop, pause, resume, isActive }; | ||
} | ||
/** | ||
@@ -103,2 +329,8 @@ * Keep target ref(s) in sync with the source ref | ||
// implementation | ||
function throttledWatch(source, cb, options = {}) { | ||
const { throttle = 0 } = options, watchOptions = __rest(options, ["throttle"]); | ||
return watchWithFilter(source, cb, Object.assign(Object.assign({}, watchOptions), { eventFilter: throttleFilter(throttle) })); | ||
} | ||
/** | ||
@@ -129,35 +361,170 @@ * Call onMounted() if it's inside a component lifecycle, if not, run just call the function | ||
const isClient = typeof window !== 'undefined'; | ||
const isDef = (val) => typeof val !== 'undefined'; | ||
const assert = (condition, ...infos) => { | ||
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 now = () => Date.now(); | ||
const timestamp = () => +Date.now(); | ||
const clamp = (n, min, max) => Math.min(max, Math.max(min, n)); | ||
const noop = () => { }; | ||
/** | ||
* Debounce execution of a function. | ||
* | ||
* @param fn A function to be executed after delay milliseconds debounced. | ||
* @param ms A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. | ||
* | ||
* @return A new, debounce, function. | ||
*/ | ||
function useDebounceFn(fn, ms = 200) { | ||
return createFilterWrapper(debounceFilter(ms), fn); | ||
} | ||
function promiseTimeout(ms, throwOnTimeout = false, reason = 'Timeout') { | ||
return new Promise((resolve, reject) => { | ||
if (throwOnTimeout) | ||
setTimeout(() => reject(reason), ms); | ||
else | ||
setTimeout(resolve, ms); | ||
}); | ||
function useDebounce(value, ms = 200) { | ||
if (ms <= 0) | ||
return value; | ||
const debounced = ref(value.value); | ||
const updater = useDebounceFn(() => { | ||
debounced.value = value.value; | ||
}, ms); | ||
watch(value, () => updater()); | ||
return debounced; | ||
} | ||
function invoke(fn) { | ||
return fn(); | ||
/** | ||
* Wrapper for `setInterval` with controls | ||
* | ||
* @param cb | ||
* @param interval | ||
* @param immediate | ||
*/ | ||
function useIntervalFn(cb, interval = 1000, immediate = true) { | ||
let timer = null; | ||
const isActive = ref(false); | ||
function clean() { | ||
if (timer) { | ||
clearInterval(timer); | ||
timer = null; | ||
} | ||
} | ||
function pause() { | ||
isActive.value = false; | ||
clean(); | ||
} | ||
function resume() { | ||
isActive.value = true; | ||
clean(); | ||
timer = setInterval(cb, interval); | ||
} | ||
if (immediate) | ||
resume(); | ||
tryOnUnmounted(pause); | ||
return { | ||
isActive, | ||
pause, | ||
resume, | ||
start: resume, | ||
stop: pause, | ||
}; | ||
} | ||
function when(r) { | ||
function useInterval(interval = 1000, immediate = true) { | ||
const counter = ref(0); | ||
return Object.assign({ counter }, useIntervalFn(() => counter.value += 1, interval, immediate)); | ||
} | ||
/** | ||
* Throttle execution of a function. Especially useful for rate limiting | ||
* execution of handlers on events like resize and scroll. | ||
* | ||
* @param fn A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is, | ||
* to `callback` when the throttled-function is executed. | ||
* @param ms A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. | ||
* | ||
* @return A new, throttled, function. | ||
*/ | ||
function useThrottleFn(fn, ms = 200, trailing = true) { | ||
return createFilterWrapper(throttleFilter(ms, trailing), fn); | ||
} | ||
/** | ||
* Throttle execution of a function. Especially useful for rate limiting | ||
* execution of handlers on events like resize and scroll. | ||
* | ||
* @param delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. | ||
*/ | ||
function useThrottle(value, delay = 200) { | ||
if (delay <= 0) | ||
return value; | ||
const throttled = ref(value.value); | ||
const updater = useThrottleFn(() => { | ||
throttled.value = value.value; | ||
}, delay); | ||
watch(value, () => updater()); | ||
return throttled; | ||
} | ||
/** | ||
* Wrapper for `setTimeout` with controls. | ||
* | ||
* @param cb | ||
* @param interval | ||
* @param immediate | ||
*/ | ||
function useTimeoutFn(cb, interval, immediate) { | ||
const isActive = ref(false); | ||
let timer = null; | ||
function clear() { | ||
if (timer) { | ||
clearTimeout(timer); | ||
timer = null; | ||
} | ||
} | ||
function stop() { | ||
isActive.value = false; | ||
stop(); | ||
} | ||
function start() { | ||
clear(); | ||
isActive.value = true; | ||
timer = setTimeout(() => { | ||
timer = null; | ||
cb(); | ||
}, interval); | ||
} | ||
if (immediate) | ||
start(); | ||
tryOnUnmounted(stop); | ||
return { | ||
isActive, | ||
start, | ||
stop, | ||
}; | ||
} | ||
/** | ||
* Update value after a given time with controls. | ||
* | ||
* @param interval | ||
* @param immediate | ||
*/ | ||
function useTimeout(interval = 1000, immediate = true) { | ||
const ready = ref(false); | ||
const controls = useTimeoutFn(() => ready.value = true, interval, immediate); | ||
function stop() { | ||
ready.value = false; | ||
controls.stop(); | ||
} | ||
function start() { | ||
ready.value = false; | ||
controls.start(); | ||
} | ||
return { | ||
ready, | ||
isActive: controls.isActive, | ||
start, | ||
stop, | ||
}; | ||
} | ||
/** | ||
* Promised one-time watch for ref changes | ||
* @param r ref or watch source | ||
* @param options | ||
*/ | ||
function when(r, rootOptions = {}) { | ||
let isNot = false; | ||
function toMatch(condition, { flush = 'sync', timeout, throwOnTimeout } = {}) { | ||
function toMatch(condition, options = {}) { | ||
const { flush = 'pre', timeout = 0, throwOnTimeout = false, } = Object.assign(Object.assign({}, rootOptions), options); | ||
let stop = null; | ||
@@ -230,2 +597,2 @@ const watcher = new Promise((resolve) => { | ||
export { assert, biSyncRef, clamp, controlledComputed, extendRef, invoke, isBoolean, isClient, isDef, isFunction, isNumber, isObject, isString, isWindow, makeDestructurable, noop, now, promiseTimeout, syncRef, timestamp, tryOnMounted, tryOnUnmounted, when }; | ||
export { assert, biSyncRef, bypassFilter, clamp, controlledComputed, createFilterWrapper, debounceFilter, debouncedWatch, extendRef, ignorableWatch, invoke, isBoolean, isClient, isDef, isFunction, isNumber, isObject, isString, isWindow, makeDestructurable, noop, now, pausableFilter, pausableWatch, promiseTimeout, syncRef, throttleFilter, throttledWatch, timestamp, tryOnMounted, tryOnUnmounted, useDebounce, useDebounceFn, useInterval, useIntervalFn, useThrottle, useThrottleFn, useTimeout, useTimeoutFn, watchWithFilter, when }; |
@@ -41,3 +41,154 @@ (function (global, factory) { | ||
/*! ***************************************************************************** | ||
Copyright (c) Microsoft Corporation. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */ | ||
function __rest(s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { | ||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) | ||
t[p[i]] = s[p[i]]; | ||
} | ||
return t; | ||
} | ||
const isClient = typeof window !== 'undefined'; | ||
const isDef = (val) => typeof val !== 'undefined'; | ||
const assert = (condition, ...infos) => { | ||
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 now = () => Date.now(); | ||
const timestamp = () => +Date.now(); | ||
const clamp = (n, min, max) => Math.min(max, Math.max(min, n)); | ||
const noop = () => { }; | ||
/** | ||
* @internal | ||
*/ | ||
function createFilterWrapper(filter, fn) { | ||
function wrapper(...args) { | ||
filter(() => fn.apply(this, args), { fn, thisArg: this, args }); | ||
} | ||
return wrapper; | ||
} | ||
const bypassFilter = (invoke) => { | ||
return invoke(); | ||
}; | ||
/** | ||
* Create an EventFilter that debounce the events | ||
* | ||
* @param ms | ||
*/ | ||
function debounceFilter(ms) { | ||
if (ms <= 0) | ||
return bypassFilter; | ||
let timer; | ||
const filter = (invoke) => { | ||
if (timer) | ||
clearTimeout(timer); | ||
timer = setTimeout(invoke, ms); | ||
}; | ||
return filter; | ||
} | ||
/** | ||
* Create an EventFilter that throttle the events | ||
* | ||
* @param ms | ||
* @param [trailing=true] | ||
*/ | ||
function throttleFilter(ms, trailing = true) { | ||
if (ms <= 0) | ||
return bypassFilter; | ||
let lastExec = 0; | ||
let timer; | ||
const clear = () => { | ||
if (timer) { | ||
clearTimeout(timer); | ||
timer = undefined; | ||
} | ||
}; | ||
const filter = (invoke) => { | ||
const elapsed = Date.now() - lastExec; | ||
clear(); | ||
if (elapsed > ms) { | ||
lastExec = Date.now(); | ||
invoke(); | ||
} | ||
else if (trailing) { | ||
timer = setTimeout(() => { | ||
clear(); | ||
invoke(); | ||
}, ms); | ||
} | ||
}; | ||
return filter; | ||
} | ||
/** | ||
* EventFilter that gives extra controls to pause and resume the filter | ||
* | ||
* @param extendFilter Extra filter to apply when the PauseableFilter is active, default to none | ||
* | ||
*/ | ||
function pausableFilter(extendFilter = bypassFilter) { | ||
const isActive = vueDemi.ref(true); | ||
function pause() { | ||
isActive.value = false; | ||
} | ||
function resume() { | ||
isActive.value = true; | ||
} | ||
const eventFilter = (...args) => { | ||
if (isActive.value) | ||
extendFilter(...args); | ||
}; | ||
return { isActive, pause, resume, eventFilter }; | ||
} | ||
function promiseTimeout(ms, throwOnTimeout = false, reason = 'Timeout') { | ||
return new Promise((resolve, reject) => { | ||
if (throwOnTimeout) | ||
setTimeout(() => reject(reason), ms); | ||
else | ||
setTimeout(resolve, ms); | ||
}); | ||
} | ||
function invoke(fn) { | ||
return fn(); | ||
} | ||
// implementation | ||
function watchWithFilter(source, cb, options = {}) { | ||
const { eventFilter = bypassFilter } = options, watchOptions = __rest(options, ["eventFilter"]); | ||
return vueDemi.watch(source, createFilterWrapper(eventFilter, cb), watchOptions); | ||
} | ||
// implementation | ||
function debouncedWatch(source, cb, options = {}) { | ||
const { debounce = 0 } = options, watchOptions = __rest(options, ["debounce"]); | ||
return watchWithFilter(source, cb, Object.assign(Object.assign({}, watchOptions), { eventFilter: debounceFilter(debounce) })); | ||
} | ||
// implementation | ||
function extendRef(ref, extend, { enumerable = false, unwrap = true } = {}) { | ||
@@ -65,2 +216,69 @@ for (const [key, value] of Object.entries(extend)) { | ||
function ignorableWatch(source, cb, options = {}) { | ||
const { eventFilter = bypassFilter } = options, watchOptions = __rest(options, ["eventFilter"]); | ||
const filteredCb = createFilterWrapper(eventFilter, cb); | ||
let ignoreUpdates; | ||
let ignorePrevAsyncUpdates; | ||
let stop; | ||
if (watchOptions.flush === 'sync') { | ||
const ignore = vueDemi.ref(false); | ||
// no op for flush: sync | ||
ignorePrevAsyncUpdates = () => { }; | ||
ignoreUpdates = (updater) => { | ||
// Call the updater function and count how many sync updates are performed, | ||
// then add them to the ignore count | ||
ignore.value = true; | ||
updater(); | ||
ignore.value = false; | ||
}; | ||
stop = vueDemi.watch(source, (...args) => { | ||
if (!ignore.value) | ||
filteredCb(...args); | ||
}, watchOptions); | ||
} | ||
else { | ||
// flush 'pre' and 'post' | ||
const disposables = []; | ||
// counters for how many following changes to be ignored | ||
// ignoreCounter is incremented before there is a history operation | ||
// affecting the source ref value (undo, redo, revert). | ||
// syncCounter is incremented in sync with every change to the | ||
// source ref value. This let us know how many times the ref | ||
// was modified and support chained sync operations. If there | ||
// are more sync triggers than the ignore count, the we now | ||
// there are modifications in the source ref value that we | ||
// need to commit | ||
const ignoreCounter = vueDemi.ref(0); | ||
const syncCounter = vueDemi.ref(0); | ||
ignorePrevAsyncUpdates = () => { | ||
ignoreCounter.value = syncCounter.value; | ||
}; | ||
// Sync watch to count modifications to the source | ||
disposables.push(vueDemi.watch(source, () => { | ||
syncCounter.value++; | ||
}, Object.assign(Object.assign({}, watchOptions), { flush: 'sync' }))); | ||
ignoreUpdates = (updater) => { | ||
// Call the updater function and count how many sync updates are performed, | ||
// then add them to the ignore count | ||
const syncCounterPrev = syncCounter.value; | ||
updater(); | ||
ignoreCounter.value += syncCounter.value - syncCounterPrev; | ||
}; | ||
disposables.push(vueDemi.watch(source, (...args) => { | ||
// If a history operation was performed (ignoreCounter > 0) and there are | ||
// no other changes to the source ref value afterwards, then ignore this commit | ||
const ignore = ignoreCounter.value > 0 && ignoreCounter.value === syncCounter.value; | ||
ignoreCounter.value = 0; | ||
syncCounter.value = 0; | ||
if (ignore) | ||
return; | ||
filteredCb(...args); | ||
}, watchOptions)); | ||
stop = () => { | ||
disposables.forEach(fn => fn()); | ||
}; | ||
} | ||
return { stop, ignoreUpdates, ignorePrevAsyncUpdates }; | ||
} | ||
function makeDestructurable(obj, arr) { | ||
@@ -88,2 +306,10 @@ if (typeof Symbol !== 'undefined') { | ||
// implementation | ||
function pausableWatch(source, cb, options = {}) { | ||
const { eventFilter: filter } = options, watchOptions = __rest(options, ["eventFilter"]); | ||
const { eventFilter, pause, resume, isActive } = pausableFilter(filter); | ||
const stop = watchWithFilter(source, cb, Object.assign(Object.assign({}, watchOptions), { eventFilter })); | ||
return { stop, pause, resume, isActive }; | ||
} | ||
/** | ||
@@ -107,2 +333,8 @@ * Keep target ref(s) in sync with the source ref | ||
// implementation | ||
function throttledWatch(source, cb, options = {}) { | ||
const { throttle = 0 } = options, watchOptions = __rest(options, ["throttle"]); | ||
return watchWithFilter(source, cb, Object.assign(Object.assign({}, watchOptions), { eventFilter: throttleFilter(throttle) })); | ||
} | ||
/** | ||
@@ -133,35 +365,170 @@ * Call onMounted() if it's inside a component lifecycle, if not, run just call the function | ||
const isClient = typeof window !== 'undefined'; | ||
const isDef = (val) => typeof val !== 'undefined'; | ||
const assert = (condition, ...infos) => { | ||
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 now = () => Date.now(); | ||
const timestamp = () => +Date.now(); | ||
const clamp = (n, min, max) => Math.min(max, Math.max(min, n)); | ||
const noop = () => { }; | ||
/** | ||
* Debounce execution of a function. | ||
* | ||
* @param fn A function to be executed after delay milliseconds debounced. | ||
* @param ms A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. | ||
* | ||
* @return A new, debounce, function. | ||
*/ | ||
function useDebounceFn(fn, ms = 200) { | ||
return createFilterWrapper(debounceFilter(ms), fn); | ||
} | ||
function promiseTimeout(ms, throwOnTimeout = false, reason = 'Timeout') { | ||
return new Promise((resolve, reject) => { | ||
if (throwOnTimeout) | ||
setTimeout(() => reject(reason), ms); | ||
else | ||
setTimeout(resolve, ms); | ||
}); | ||
function useDebounce(value, ms = 200) { | ||
if (ms <= 0) | ||
return value; | ||
const debounced = vueDemi.ref(value.value); | ||
const updater = useDebounceFn(() => { | ||
debounced.value = value.value; | ||
}, ms); | ||
vueDemi.watch(value, () => updater()); | ||
return debounced; | ||
} | ||
function invoke(fn) { | ||
return fn(); | ||
/** | ||
* Wrapper for `setInterval` with controls | ||
* | ||
* @param cb | ||
* @param interval | ||
* @param immediate | ||
*/ | ||
function useIntervalFn(cb, interval = 1000, immediate = true) { | ||
let timer = null; | ||
const isActive = vueDemi.ref(false); | ||
function clean() { | ||
if (timer) { | ||
clearInterval(timer); | ||
timer = null; | ||
} | ||
} | ||
function pause() { | ||
isActive.value = false; | ||
clean(); | ||
} | ||
function resume() { | ||
isActive.value = true; | ||
clean(); | ||
timer = setInterval(cb, interval); | ||
} | ||
if (immediate) | ||
resume(); | ||
tryOnUnmounted(pause); | ||
return { | ||
isActive, | ||
pause, | ||
resume, | ||
start: resume, | ||
stop: pause, | ||
}; | ||
} | ||
function when(r) { | ||
function useInterval(interval = 1000, immediate = true) { | ||
const counter = vueDemi.ref(0); | ||
return Object.assign({ counter }, useIntervalFn(() => counter.value += 1, interval, immediate)); | ||
} | ||
/** | ||
* Throttle execution of a function. Especially useful for rate limiting | ||
* execution of handlers on events like resize and scroll. | ||
* | ||
* @param fn A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is, | ||
* to `callback` when the throttled-function is executed. | ||
* @param ms A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. | ||
* | ||
* @return A new, throttled, function. | ||
*/ | ||
function useThrottleFn(fn, ms = 200, trailing = true) { | ||
return createFilterWrapper(throttleFilter(ms, trailing), fn); | ||
} | ||
/** | ||
* Throttle execution of a function. Especially useful for rate limiting | ||
* execution of handlers on events like resize and scroll. | ||
* | ||
* @param delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. | ||
*/ | ||
function useThrottle(value, delay = 200) { | ||
if (delay <= 0) | ||
return value; | ||
const throttled = vueDemi.ref(value.value); | ||
const updater = useThrottleFn(() => { | ||
throttled.value = value.value; | ||
}, delay); | ||
vueDemi.watch(value, () => updater()); | ||
return throttled; | ||
} | ||
/** | ||
* Wrapper for `setTimeout` with controls. | ||
* | ||
* @param cb | ||
* @param interval | ||
* @param immediate | ||
*/ | ||
function useTimeoutFn(cb, interval, immediate) { | ||
const isActive = vueDemi.ref(false); | ||
let timer = null; | ||
function clear() { | ||
if (timer) { | ||
clearTimeout(timer); | ||
timer = null; | ||
} | ||
} | ||
function stop() { | ||
isActive.value = false; | ||
stop(); | ||
} | ||
function start() { | ||
clear(); | ||
isActive.value = true; | ||
timer = setTimeout(() => { | ||
timer = null; | ||
cb(); | ||
}, interval); | ||
} | ||
if (immediate) | ||
start(); | ||
tryOnUnmounted(stop); | ||
return { | ||
isActive, | ||
start, | ||
stop, | ||
}; | ||
} | ||
/** | ||
* Update value after a given time with controls. | ||
* | ||
* @param interval | ||
* @param immediate | ||
*/ | ||
function useTimeout(interval = 1000, immediate = true) { | ||
const ready = vueDemi.ref(false); | ||
const controls = useTimeoutFn(() => ready.value = true, interval, immediate); | ||
function stop() { | ||
ready.value = false; | ||
controls.stop(); | ||
} | ||
function start() { | ||
ready.value = false; | ||
controls.start(); | ||
} | ||
return { | ||
ready, | ||
isActive: controls.isActive, | ||
start, | ||
stop, | ||
}; | ||
} | ||
/** | ||
* Promised one-time watch for ref changes | ||
* @param r ref or watch source | ||
* @param options | ||
*/ | ||
function when(r, rootOptions = {}) { | ||
let isNot = false; | ||
function toMatch(condition, { flush = 'sync', timeout, throwOnTimeout } = {}) { | ||
function toMatch(condition, options = {}) { | ||
const { flush = 'pre', timeout = 0, throwOnTimeout = false, } = Object.assign(Object.assign({}, rootOptions), options); | ||
let stop = null; | ||
@@ -236,5 +603,10 @@ const watcher = new Promise((resolve) => { | ||
exports.biSyncRef = biSyncRef; | ||
exports.bypassFilter = bypassFilter; | ||
exports.clamp = clamp; | ||
exports.controlledComputed = controlledComputed; | ||
exports.createFilterWrapper = createFilterWrapper; | ||
exports.debounceFilter = debounceFilter; | ||
exports.debouncedWatch = debouncedWatch; | ||
exports.extendRef = extendRef; | ||
exports.ignorableWatch = ignorableWatch; | ||
exports.invoke = invoke; | ||
@@ -252,7 +624,20 @@ exports.isBoolean = isBoolean; | ||
exports.now = now; | ||
exports.pausableFilter = pausableFilter; | ||
exports.pausableWatch = pausableWatch; | ||
exports.promiseTimeout = promiseTimeout; | ||
exports.syncRef = syncRef; | ||
exports.throttleFilter = throttleFilter; | ||
exports.throttledWatch = throttledWatch; | ||
exports.timestamp = timestamp; | ||
exports.tryOnMounted = tryOnMounted; | ||
exports.tryOnUnmounted = tryOnUnmounted; | ||
exports.useDebounce = useDebounce; | ||
exports.useDebounceFn = useDebounceFn; | ||
exports.useInterval = useInterval; | ||
exports.useIntervalFn = useIntervalFn; | ||
exports.useThrottle = useThrottle; | ||
exports.useThrottleFn = useThrottleFn; | ||
exports.useTimeout = useTimeout; | ||
exports.useTimeoutFn = useTimeoutFn; | ||
exports.watchWithFilter = watchWithFilter; | ||
exports.when = when; | ||
@@ -259,0 +644,0 @@ |
@@ -1,1 +0,1 @@ | ||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports,require("vue-demi")):"function"==typeof define&&define.amd?define(["exports","vue-demi"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self)["VueUseShared utilities"]={},e.VueDemi)}(this,(function(e,n){"use strict";const t="undefined"!=typeof window,o=Object.prototype.toString;function u(e,n=!1,t="Timeout"){return new Promise(((o,u)=>{n?setTimeout((()=>u(t)),e):setTimeout(o,e)}))}e.assert=(e,...n)=>{e||console.warn(...n)},e.biSyncRef=function(e,t){const o="sync",u=n.watch(e,(e=>{t.value=e}),{flush:o,immediate:!0}),i=n.watch(t,(n=>{e.value=n}),{flush:o,immediate:!0});return()=>{u(),i()}},e.clamp=(e,n,t)=>Math.min(t,Math.max(n,e)),e.controlledComputed=function(e,t){const o=n.ref(t());return n.watch(e,(()=>o.value=t()),{flush:"sync"}),n.computed((()=>o.value))},e.extendRef=function(e,t,{enumerable:o=!1,unwrap:u=!0}={}){for(const[i,r]of Object.entries(t))"value"!==i&&(n.isRef(r)&&u?Object.defineProperty(e,i,{get:()=>r.value,set(e){r.value=e},enumerable:o}):Object.defineProperty(e,i,{value:r,enumerable:o}));return e},e.invoke=function(e){return e()},e.isBoolean=e=>"boolean"==typeof e,e.isClient=t,e.isDef=e=>void 0!==e,e.isFunction=e=>"function"==typeof e,e.isNumber=e=>"number"==typeof e,e.isObject=e=>"[object Object]"===o.call(e),e.isString=e=>"string"==typeof e,e.isWindow=e=>"undefined"!=typeof window&&"[object Window]"===o.call(e),e.makeDestructurable=function(e,n){if("undefined"!=typeof Symbol){const t=Object.assign({},e);return Object.defineProperty(t,Symbol.iterator,{enumerable:!1,value(){let e=0;return{next:()=>({value:n[e++],done:e>n.length})}}}),t}return Object.assign([...n],e)},e.noop=()=>{},e.now=()=>Date.now(),e.promiseTimeout=u,e.syncRef=function(e,t,{flush:o="sync",deep:u=!1,immediate:i=!0}={}){return Array.isArray(t)||(t=[t]),n.watch(e,(e=>{t.forEach((n=>n.value=e))}),{flush:o,deep:u,immediate:i})},e.timestamp=()=>+Date.now(),e.tryOnMounted=function(e,t=!0){n.getCurrentInstance()?n.onMounted(e):t?e():n.nextTick(e)},e.tryOnUnmounted=function(e){n.getCurrentInstance()&&n.onUnmounted(e)},e.when=function(e){let t=!1;function o(o,{flush:i="sync",timeout:r,throwOnTimeout:c}={}){let f=null;const s=[new Promise((u=>{f=n.watch(e,(e=>{o(e)===!t&&(null==f||f(),u())}),{flush:i,immediate:!0})}))];return r&&s.push(u(r,c).finally((()=>{null==f||f()}))),Promise.race(s)}function i(e,n){return o((n=>n===e),n)}function r(e=1,n){let t=-1;return o((()=>(t+=1,t>=e)),n)}return{toMatch:o,toBe:i,toBeTruthy:function(e){return o((e=>Boolean(e)),e)},toBeNull:function(e){return i(null,e)},toBeNaN:function(e){return o(Number.isNaN,e)},toBeUndefined:function(e){return i(void 0,e)},toContain:function(e,n){return o((n=>Array.from(n).includes(e)),n)},changed:function(e){return r(1,e)},changedTimes:r,get not(){return t=!t,this}}},Object.defineProperty(e,"__esModule",{value:!0})})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vue-demi")):"function"==typeof define&&define.amd?define(["exports","vue-demi"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self)["VueUseShared utilities"]={},e.VueDemi)}(this,(function(e,t){"use strict";function n(e,t){var n={};for(var u in e)Object.prototype.hasOwnProperty.call(e,u)&&t.indexOf(u)<0&&(n[u]=e[u]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var r=0;for(u=Object.getOwnPropertySymbols(e);r<u.length;r++)t.indexOf(u[r])<0&&Object.prototype.propertyIsEnumerable.call(e,u[r])&&(n[u[r]]=e[u[r]])}return n}const u="undefined"!=typeof window,r=Object.prototype.toString;function o(e,t){return function(...n){e((()=>t.apply(this,n)),{fn:t,thisArg:this,args:n})}}const i=e=>e();function c(e){if(e<=0)return i;let t;return n=>{t&&clearTimeout(t),t=setTimeout(n,e)}}function s(e,t=!0){if(e<=0)return i;let n,u=0;const r=()=>{n&&(clearTimeout(n),n=void 0)};return o=>{const i=Date.now()-u;r(),i>e?(u=Date.now(),o()):t&&(n=setTimeout((()=>{r(),o()}),e))}}function l(e=i){const n=t.ref(!0);return{isActive:n,pause:function(){n.value=!1},resume:function(){n.value=!0},eventFilter:(...t)=>{n.value&&e(...t)}}}function a(e,t=!1,n="Timeout"){return new Promise(((u,r)=>{t?setTimeout((()=>r(n)),e):setTimeout(u,e)}))}function f(e,u,r={}){const{eventFilter:c=i}=r,s=n(r,["eventFilter"]);return t.watch(e,o(c,u),s)}function v(e){t.getCurrentInstance()&&t.onUnmounted(e)}function d(e,t=200){return o(c(t),e)}function p(e,n=1e3,u=!0){let r=null;const o=t.ref(!1);function i(){r&&(clearInterval(r),r=null)}function c(){o.value=!1,i()}function s(){o.value=!0,i(),r=setInterval(e,n)}return u&&s(),v(c),{isActive:o,pause:c,resume:s,start:s,stop:c}}function m(e,t=200,n=!0){return o(s(t,n),e)}function h(e,n,u){const r=t.ref(!1);let o=null;function i(){r.value=!1,i()}function c(){o&&(clearTimeout(o),o=null),r.value=!0,o=setTimeout((()=>{o=null,e()}),n)}return u&&c(),v(i),{isActive:r,start:c,stop:i}}e.assert=(e,...t)=>{e||console.warn(...t)},e.biSyncRef=function(e,n){const u="sync",r=t.watch(e,(e=>{n.value=e}),{flush:u,immediate:!0}),o=t.watch(n,(t=>{e.value=t}),{flush:u,immediate:!0});return()=>{r(),o()}},e.bypassFilter=i,e.clamp=(e,t,n)=>Math.min(n,Math.max(t,e)),e.controlledComputed=function(e,n){const u=t.ref(n());return t.watch(e,(()=>u.value=n()),{flush:"sync"}),t.computed((()=>u.value))},e.createFilterWrapper=o,e.debounceFilter=c,e.debouncedWatch=function(e,t,u={}){const{debounce:r=0}=u,o=n(u,["debounce"]);return f(e,t,Object.assign(Object.assign({},o),{eventFilter:c(r)}))},e.extendRef=function(e,n,{enumerable:u=!1,unwrap:r=!0}={}){for(const[o,i]of Object.entries(n))"value"!==o&&(t.isRef(i)&&r?Object.defineProperty(e,o,{get:()=>i.value,set(e){i.value=e},enumerable:u}):Object.defineProperty(e,o,{value:i,enumerable:u}));return e},e.ignorableWatch=function(e,u,r={}){const{eventFilter:c=i}=r,s=n(r,["eventFilter"]),l=o(c,u);let a,f,v;if("sync"===s.flush){const n=t.ref(!1);f=()=>{},a=e=>{n.value=!0,e(),n.value=!1},v=t.watch(e,((...e)=>{n.value||l(...e)}),s)}else{const n=[],u=t.ref(0),r=t.ref(0);f=()=>{u.value=r.value},n.push(t.watch(e,(()=>{r.value++}),Object.assign(Object.assign({},s),{flush:"sync"}))),a=e=>{const t=r.value;e(),u.value+=r.value-t},n.push(t.watch(e,((...e)=>{const t=u.value>0&&u.value===r.value;u.value=0,r.value=0,t||l(...e)}),s)),v=()=>{n.forEach((e=>e()))}}return{stop:v,ignoreUpdates:a,ignorePrevAsyncUpdates:f}},e.invoke=function(e){return e()},e.isBoolean=e=>"boolean"==typeof e,e.isClient=u,e.isDef=e=>void 0!==e,e.isFunction=e=>"function"==typeof e,e.isNumber=e=>"number"==typeof e,e.isObject=e=>"[object Object]"===r.call(e),e.isString=e=>"string"==typeof e,e.isWindow=e=>"undefined"!=typeof window&&"[object Window]"===r.call(e),e.makeDestructurable=function(e,t){if("undefined"!=typeof Symbol){const n=Object.assign({},e);return Object.defineProperty(n,Symbol.iterator,{enumerable:!1,value(){let e=0;return{next:()=>({value:t[e++],done:e>t.length})}}}),n}return Object.assign([...t],e)},e.noop=()=>{},e.now=()=>Date.now(),e.pausableFilter=l,e.pausableWatch=function(e,t,u={}){const{eventFilter:r}=u,o=n(u,["eventFilter"]),{eventFilter:i,pause:c,resume:s,isActive:a}=l(r);return{stop:f(e,t,Object.assign(Object.assign({},o),{eventFilter:i})),pause:c,resume:s,isActive:a}},e.promiseTimeout=a,e.syncRef=function(e,n,{flush:u="sync",deep:r=!1,immediate:o=!0}={}){return Array.isArray(n)||(n=[n]),t.watch(e,(e=>{n.forEach((t=>t.value=e))}),{flush:u,deep:r,immediate:o})},e.throttleFilter=s,e.throttledWatch=function(e,t,u={}){const{throttle:r=0}=u,o=n(u,["throttle"]);return f(e,t,Object.assign(Object.assign({},o),{eventFilter:s(r)}))},e.timestamp=()=>+Date.now(),e.tryOnMounted=function(e,n=!0){t.getCurrentInstance()?t.onMounted(e):n?e():t.nextTick(e)},e.tryOnUnmounted=v,e.useDebounce=function(e,n=200){if(n<=0)return e;const u=t.ref(e.value),r=d((()=>{u.value=e.value}),n);return t.watch(e,(()=>r())),u},e.useDebounceFn=d,e.useInterval=function(e=1e3,n=!0){const u=t.ref(0);return Object.assign({counter:u},p((()=>u.value+=1),e,n))},e.useIntervalFn=p,e.useThrottle=function(e,n=200){if(n<=0)return e;const u=t.ref(e.value),r=m((()=>{u.value=e.value}),n);return t.watch(e,(()=>r())),u},e.useThrottleFn=m,e.useTimeout=function(e=1e3,n=!0){const u=t.ref(!1),r=h((()=>u.value=!0),e,n);return{ready:u,isActive:r.isActive,start:function(){u.value=!1,r.start()},stop:function(){u.value=!1,r.stop()}}},e.useTimeoutFn=h,e.watchWithFilter=f,e.when=function(e,n={}){let u=!1;function r(r,o={}){const{flush:i="pre",timeout:c=0,throwOnTimeout:s=!1}=Object.assign(Object.assign({},n),o);let l=null;const f=[new Promise((n=>{l=t.watch(e,(e=>{r(e)===!u&&(null==l||l(),n())}),{flush:i,immediate:!0})}))];return c&&f.push(a(c,s).finally((()=>{null==l||l()}))),Promise.race(f)}function o(e,t){return r((t=>t===e),t)}function i(e=1,t){let n=-1;return r((()=>(n+=1,n>=e)),t)}return{toMatch:r,toBe:o,toBeTruthy:function(e){return r((e=>Boolean(e)),e)},toBeNull:function(e){return o(null,e)},toBeNaN:function(e){return r(Number.isNaN,e)},toBeUndefined:function(e){return o(void 0,e)},toContain:function(e,t){return r((t=>Array.from(t).includes(e)),t)},changed:function(e){return i(1,e)},changedTimes:i,get not(){return u=!u,this}}},Object.defineProperty(e,"__esModule",{value:!0})})); |
{ | ||
"name": "@vueuse/shared", | ||
"version": "4.0.0-beta.41", | ||
"version": "4.0.0-rc.1", | ||
"main": "dist/index.cjs.js", | ||
@@ -5,0 +5,0 @@ "types": "dist/index.d.ts", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
82145
2108
1