@solid-primitives/scheduled
Advanced tools
Comparing version 1.4.4 to 1.5.0
@@ -1,5 +0,4 @@ | ||
import { Accessor } from 'solid-js'; | ||
type ScheduleCallback = <Args extends unknown[]>(callback: (...args: Args) => void, wait?: number) => Scheduled<Args>; | ||
interface Scheduled<Args extends unknown[]> { | ||
import { Accessor } from "solid-js"; | ||
export type ScheduleCallback = <Args extends unknown[]>(callback: (...args: Args) => void, wait?: number) => Scheduled<Args>; | ||
export interface Scheduled<Args extends unknown[]> { | ||
(...args: Args): void; | ||
@@ -26,3 +25,3 @@ clear: VoidFunction; | ||
*/ | ||
declare const debounce: ScheduleCallback; | ||
export declare const debounce: ScheduleCallback; | ||
/** | ||
@@ -46,3 +45,3 @@ * Creates a callback that is throttled and cancellable. The throttled callback is called on **trailing** edge. | ||
*/ | ||
declare const throttle: ScheduleCallback; | ||
export declare const throttle: ScheduleCallback; | ||
/** | ||
@@ -68,3 +67,3 @@ * Creates a callback throttled using `window.requestIdleCallback()`. ([MDN reference](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback)) | ||
*/ | ||
declare const scheduleIdle: ScheduleCallback; | ||
export declare const scheduleIdle: ScheduleCallback; | ||
/** | ||
@@ -89,3 +88,3 @@ * Creates a scheduled and cancellable callback that will be called on **leading** edge. | ||
*/ | ||
declare function leading<Args extends unknown[]>(schedule: ScheduleCallback, callback: (...args: Args) => void, wait?: number): Scheduled<Args>; | ||
export declare function leading<Args extends unknown[]>(schedule: ScheduleCallback, callback: (...args: Args) => void, wait?: number): Scheduled<Args>; | ||
/** | ||
@@ -110,3 +109,3 @@ * Creates a scheduled and cancellable callback that will be called on the **leading** edge for the first call, and **trailing** edge for other calls. | ||
*/ | ||
declare function leadingAndTrailing<Args extends unknown[]>(schedule: ScheduleCallback, callback: (...args: Args) => void, wait?: number): Scheduled<Args>; | ||
export declare function leadingAndTrailing<Args extends unknown[]>(schedule: ScheduleCallback, callback: (...args: Args) => void, wait?: number): Scheduled<Args>; | ||
/** | ||
@@ -134,4 +133,2 @@ * Creates a signal used for scheduling execution of solid computations by tracking. | ||
*/ | ||
declare function createScheduled(schedule: (callback: VoidFunction) => VoidFunction): Accessor<boolean>; | ||
export { type ScheduleCallback, type Scheduled, createScheduled, debounce, leading, leadingAndTrailing, scheduleIdle, throttle }; | ||
export declare function createScheduled(schedule: (callback: VoidFunction) => VoidFunction): Accessor<boolean>; |
@@ -1,147 +0,271 @@ | ||
import { getOwner, onCleanup, createSignal, getListener } from 'solid-js'; | ||
import { isServer } from 'solid-js/web'; | ||
// src/index.ts | ||
var debounce = (callback, wait) => { | ||
if (isServer) { | ||
return Object.assign(() => void 0, { clear: () => void 0 }); | ||
} | ||
let timeoutId; | ||
const clear = () => clearTimeout(timeoutId); | ||
if (getOwner()) onCleanup(clear); | ||
const debounced = (...args) => { | ||
if (timeoutId !== void 0) clear(); | ||
timeoutId = setTimeout(() => callback(...args), wait); | ||
}; | ||
return Object.assign(debounced, { clear }); | ||
import { createSignal, getListener, getOwner, onCleanup } from "solid-js"; | ||
import { isServer } from "solid-js/web"; | ||
/** | ||
* Creates a callback that is debounced and cancellable. The debounced callback is called on **trailing** edge. | ||
* | ||
* The timeout will be automatically cleared on root dispose. | ||
* | ||
* @param callback The callback to debounce | ||
* @param wait The duration to debounce in milliseconds | ||
* @returns The debounced function | ||
* | ||
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/scheduled#debounce | ||
* | ||
* @example | ||
* ```ts | ||
* const fn = debounce((message: string) => console.log(message), 250); | ||
* fn('Hello!'); | ||
* fn.clear() // clears a timeout in progress | ||
* ``` | ||
*/ | ||
export const debounce = (callback, wait) => { | ||
if (isServer) { | ||
return Object.assign(() => void 0, { clear: () => void 0 }); | ||
} | ||
let timeoutId; | ||
const clear = () => clearTimeout(timeoutId); | ||
if (getOwner()) | ||
onCleanup(clear); | ||
const debounced = (...args) => { | ||
if (timeoutId !== undefined) | ||
clear(); | ||
timeoutId = setTimeout(() => callback(...args), wait); | ||
}; | ||
return Object.assign(debounced, { clear }); | ||
}; | ||
var throttle = (callback, wait) => { | ||
if (isServer) { | ||
return Object.assign(() => void 0, { clear: () => void 0 }); | ||
} | ||
let isThrottled = false, timeoutId, lastArgs; | ||
const throttled = (...args) => { | ||
lastArgs = args; | ||
if (isThrottled) return; | ||
isThrottled = true; | ||
timeoutId = setTimeout(() => { | ||
callback(...lastArgs); | ||
isThrottled = false; | ||
}, wait); | ||
}; | ||
const clear = () => { | ||
clearTimeout(timeoutId); | ||
isThrottled = false; | ||
}; | ||
if (getOwner()) onCleanup(clear); | ||
return Object.assign(throttled, { clear }); | ||
/** | ||
* Creates a callback that is throttled and cancellable. The throttled callback is called on **trailing** edge. | ||
* | ||
* The timeout will be automatically cleared on root dispose. | ||
* | ||
* @param callback The callback to throttle | ||
* @param wait The duration to throttle | ||
* @returns The throttled callback trigger | ||
* | ||
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/scheduled#throttle | ||
* | ||
* @example | ||
* ```ts | ||
* const trigger = throttle((val: string) => console.log(val), 250); | ||
* trigger('my-new-value'); | ||
* trigger.clear() // clears a timeout in progress | ||
* ``` | ||
*/ | ||
export const throttle = (callback, wait) => { | ||
if (isServer) { | ||
return Object.assign(() => void 0, { clear: () => void 0 }); | ||
} | ||
let isThrottled = false, timeoutId, lastArgs; | ||
const throttled = (...args) => { | ||
lastArgs = args; | ||
if (isThrottled) | ||
return; | ||
isThrottled = true; | ||
timeoutId = setTimeout(() => { | ||
callback(...lastArgs); | ||
isThrottled = false; | ||
}, wait); | ||
}; | ||
const clear = () => { | ||
clearTimeout(timeoutId); | ||
isThrottled = false; | ||
}; | ||
if (getOwner()) | ||
onCleanup(clear); | ||
return Object.assign(throttled, { clear }); | ||
}; | ||
var scheduleIdle = isServer ? () => Object.assign(() => void 0, { clear: () => void 0 }) : ( | ||
// requestIdleCallback is not supported in Safari | ||
typeof requestIdleCallback !== "undefined" ? (callback, maxWait) => { | ||
let isDeferred = false, id, lastArgs; | ||
const deferred = (...args) => { | ||
lastArgs = args; | ||
if (isDeferred) return; | ||
isDeferred = true; | ||
id = requestIdleCallback( | ||
() => { | ||
callback(...lastArgs); | ||
isDeferred = false; | ||
}, | ||
{ timeout: maxWait } | ||
); | ||
/** | ||
* Creates a callback throttled using `window.requestIdleCallback()`. ([MDN reference](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback)) | ||
* | ||
* The throttled callback is called on **trailing** edge. | ||
* | ||
* The timeout will be automatically cleared on root dispose. | ||
* | ||
* @param callback The callback to throttle | ||
* @param maxWait maximum wait time in milliseconds until the callback is called | ||
* @returns The throttled callback trigger | ||
* | ||
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/scheduled#scheduleidle | ||
* | ||
* @example | ||
* ```ts | ||
* const trigger = scheduleIdle((val: string) => console.log(val), 250); | ||
* trigger('my-new-value'); | ||
* trigger.clear() // clears a timeout in progress | ||
* ``` | ||
*/ | ||
export const scheduleIdle = isServer | ||
? () => Object.assign(() => void 0, { clear: () => void 0 }) | ||
: // requestIdleCallback is not supported in Safari | ||
typeof requestIdleCallback !== "undefined" | ||
? (callback, maxWait) => { | ||
let isDeferred = false, id, lastArgs; | ||
const deferred = (...args) => { | ||
lastArgs = args; | ||
if (isDeferred) | ||
return; | ||
isDeferred = true; | ||
id = requestIdleCallback(() => { | ||
callback(...lastArgs); | ||
isDeferred = false; | ||
}, { timeout: maxWait }); | ||
}; | ||
const clear = () => { | ||
cancelIdleCallback(id); | ||
isDeferred = false; | ||
}; | ||
if (getOwner()) | ||
onCleanup(clear); | ||
return Object.assign(deferred, { clear }); | ||
} | ||
: // fallback to setTimeout (throttle) | ||
// fallback to setTimeout (throttle) | ||
callback => throttle(callback); | ||
/** | ||
* Creates a scheduled and cancellable callback that will be called on **leading** edge. | ||
* | ||
* The timeout will be automatically cleared on root dispose. | ||
* | ||
* @param schedule {@link debounce} or {@link throttle} | ||
* @param callback The callback to debounce/throttle | ||
* @param wait timeout duration | ||
* @returns The scheduled callback trigger | ||
* | ||
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/scheduled#leading | ||
* | ||
* @example | ||
* ```ts | ||
* const trigger = leading(throttle, (val: string) => console.log(val), 250); | ||
* trigger('my-new-value'); | ||
* trigger.clear() // clears a timeout in progress | ||
* ``` | ||
*/ | ||
export function leading(schedule, callback, wait) { | ||
if (isServer) { | ||
let called = false; | ||
const scheduled = (...args) => { | ||
if (called) | ||
return; | ||
called = true; | ||
callback(...args); | ||
}; | ||
return Object.assign(scheduled, { clear: () => void 0 }); | ||
} | ||
let isScheduled = false; | ||
const scheduled = schedule(() => (isScheduled = false), wait); | ||
const func = (...args) => { | ||
if (!isScheduled) | ||
callback(...args); | ||
isScheduled = true; | ||
scheduled(); | ||
}; | ||
const clear = () => { | ||
cancelIdleCallback(id); | ||
isDeferred = false; | ||
isScheduled = false; | ||
scheduled.clear(); | ||
}; | ||
if (getOwner()) onCleanup(clear); | ||
return Object.assign(deferred, { clear }); | ||
} : ( | ||
// fallback to setTimeout (throttle) | ||
(callback) => throttle(callback) | ||
) | ||
); | ||
function leading(schedule, callback, wait) { | ||
if (isServer) { | ||
let called = false; | ||
const scheduled2 = (...args) => { | ||
if (called) return; | ||
called = true; | ||
callback(...args); | ||
if (getOwner()) | ||
onCleanup(clear); | ||
return Object.assign(func, { clear }); | ||
} | ||
/** | ||
* Creates a scheduled and cancellable callback that will be called on the **leading** edge for the first call, and **trailing** edge for other calls. | ||
* | ||
* The timeout will be automatically cleared on root dispose. | ||
* | ||
* @param schedule {@link debounce} or {@link throttle} | ||
* @param callback The callback to debounce/throttle | ||
* @param wait timeout duration | ||
* @returns The scheduled callback trigger | ||
* | ||
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/scheduled#leadingAndTrailing | ||
* | ||
* @example | ||
* ```ts | ||
* const trigger = leadingAndTrailing(throttle, (val: string) => console.log(val), 250); | ||
* trigger('my-new-value'); | ||
* trigger.clear() // clears a timeout in progress | ||
* ``` | ||
*/ | ||
export function leadingAndTrailing(schedule, callback, wait) { | ||
if (isServer) { | ||
let called = false; | ||
const scheduled = (...args) => { | ||
if (called) | ||
return; | ||
called = true; | ||
callback(...args); | ||
}; | ||
return Object.assign(scheduled, { clear: () => void 0 }); | ||
} | ||
let State; | ||
(function (State) { | ||
State[State["Ready"] = 0] = "Ready"; | ||
State[State["Leading"] = 1] = "Leading"; | ||
State[State["Trailing"] = 2] = "Trailing"; | ||
})(State || (State = {})); | ||
let state = State.Ready; | ||
const scheduled = schedule((args) => { | ||
state === State.Trailing && callback(...args); | ||
state = State.Ready; | ||
}, wait); | ||
const fn = (...args) => { | ||
if (state !== State.Trailing) { | ||
if (state === State.Ready) | ||
callback(...args); | ||
state += 1; | ||
} | ||
scheduled(args); | ||
}; | ||
return Object.assign(scheduled2, { clear: () => void 0 }); | ||
} | ||
let isScheduled = false; | ||
const scheduled = schedule(() => isScheduled = false, wait); | ||
const func = (...args) => { | ||
if (!isScheduled) callback(...args); | ||
isScheduled = true; | ||
scheduled(); | ||
}; | ||
const clear = () => { | ||
isScheduled = false; | ||
scheduled.clear(); | ||
}; | ||
if (getOwner()) onCleanup(clear); | ||
return Object.assign(func, { clear }); | ||
const clear = () => { | ||
state = State.Ready; | ||
scheduled.clear(); | ||
}; | ||
if (getOwner()) | ||
onCleanup(clear); | ||
return Object.assign(fn, { clear }); | ||
} | ||
function leadingAndTrailing(schedule, callback, wait) { | ||
if (isServer) { | ||
let called = false; | ||
const scheduled2 = (...args) => { | ||
if (called) return; | ||
called = true; | ||
callback(...args); | ||
/** | ||
* Creates a signal used for scheduling execution of solid computations by tracking. | ||
* | ||
* @param schedule Schedule the invalidate function (can be {@link debounce} or {@link throttle}) | ||
* @returns A function used to track the signal. It returns `true` if the signal is dirty *(callback should be called)* and `false` otherwise. | ||
* | ||
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/scheduled#createScheduled | ||
* | ||
* @example | ||
* ```ts | ||
* const debounced = createScheduled(fn => debounce(fn, 250)); | ||
* | ||
* createEffect(() => { | ||
* // track source signal | ||
* const value = count(); | ||
* // track the debounced signal and check if it's dirty | ||
* if (debounced()) { | ||
* console.log('count', value); | ||
* } | ||
* }); | ||
* ``` | ||
*/ | ||
// Thanks to Fabio Spampinato (https://github.com/fabiospampinato) for the idea for the primitive | ||
export function createScheduled(schedule) { | ||
let listeners = 0; | ||
let isDirty = false; | ||
const [track, dirty] = createSignal(void 0, { equals: false }); | ||
const call = schedule(() => { | ||
isDirty = true; | ||
dirty(); | ||
}); | ||
return () => { | ||
if (!isDirty) | ||
call(), track(); | ||
if (isDirty) { | ||
isDirty = !!listeners; | ||
return true; | ||
} | ||
if (getListener()) { | ||
listeners++; | ||
onCleanup(() => listeners--); | ||
} | ||
return false; | ||
}; | ||
return Object.assign(scheduled2, { clear: () => void 0 }); | ||
} | ||
let State; | ||
((State2) => { | ||
State2[State2["Ready"] = 0] = "Ready"; | ||
State2[State2["Leading"] = 1] = "Leading"; | ||
State2[State2["Trailing"] = 2] = "Trailing"; | ||
})(State || (State = {})); | ||
let state = 0 /* Ready */; | ||
const scheduled = schedule((args) => { | ||
state === 2 /* Trailing */ && callback(...args); | ||
state = 0 /* Ready */; | ||
}, wait); | ||
const fn = (...args) => { | ||
if (state !== 2 /* Trailing */) { | ||
if (state === 0 /* Ready */) callback(...args); | ||
state += 1; | ||
} | ||
scheduled(args); | ||
}; | ||
const clear = () => { | ||
state = 0 /* Ready */; | ||
scheduled.clear(); | ||
}; | ||
if (getOwner()) onCleanup(clear); | ||
return Object.assign(fn, { clear }); | ||
} | ||
function createScheduled(schedule) { | ||
let listeners = 0; | ||
let isDirty = false; | ||
const [track, dirty] = createSignal(void 0, { equals: false }); | ||
const call = schedule(() => { | ||
isDirty = true; | ||
dirty(); | ||
}); | ||
return () => { | ||
if (!isDirty) call(), track(); | ||
if (isDirty) { | ||
isDirty = !!listeners; | ||
return true; | ||
} | ||
if (getListener()) { | ||
listeners++; | ||
onCleanup(() => listeners--); | ||
} | ||
return false; | ||
}; | ||
} | ||
export { createScheduled, debounce, leading, leadingAndTrailing, scheduleIdle, throttle }; |
{ | ||
"name": "@solid-primitives/scheduled", | ||
"version": "1.4.4", | ||
"version": "1.5.0", | ||
"description": "Primitives for creating scheduled — throttled or debounced — callbacks.", | ||
@@ -38,3 +38,2 @@ "contributors": [ | ||
"type": "module", | ||
"main": "./dist/index.cjs", | ||
"module": "./dist/index.js", | ||
@@ -44,9 +43,6 @@ "types": "./dist/index.d.ts", | ||
"exports": { | ||
"@solid-primitives/source": "./src/index.ts", | ||
"import": { | ||
"types": "./dist/index.d.ts", | ||
"default": "./dist/index.js" | ||
}, | ||
"require": { | ||
"types": "./dist/index.d.cts", | ||
"default": "./dist/index.cjs" | ||
} | ||
@@ -63,4 +59,4 @@ }, | ||
"solid-js": "^1.8.7", | ||
"@solid-primitives/event-listener": "^2.3.3", | ||
"@solid-primitives/timer": "^1.3.10" | ||
"@solid-primitives/event-listener": "^2.4.0", | ||
"@solid-primitives/timer": "^1.4.0" | ||
}, | ||
@@ -67,0 +63,0 @@ "peerDependencies": { |
@@ -7,3 +7,2 @@ <p> | ||
[![turborepo](https://img.shields.io/badge/built%20with-turborepo-cc00ff.svg?style=for-the-badge&logo=turborepo)](https://turborepo.org/) | ||
[![size](https://img.shields.io/bundlephobia/minzip/@solid-primitives/scheduled?style=for-the-badge&label=size)](https://bundlephobia.com/package/@solid-primitives/scheduled) | ||
@@ -10,0 +9,0 @@ [![version](https://img.shields.io/npm/v/@solid-primitives/scheduled?style=for-the-badge)](https://www.npmjs.com/package/@solid-primitives/scheduled) |
23403
5
399
208